<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>iamtgc &#187; MySQL</title>
	<atom:link href="http://iamtgc.com/category/mysql/feed/" rel="self" type="application/rss+xml" />
	<link>http://iamtgc.com</link>
	<description></description>
	<lastBuildDate>Thu, 01 Mar 2012 19:46:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Exploring Triggers in MySQL and PostgreSQL</title>
		<link>http://iamtgc.com/2011/08/15/exploring-triggers-in-mysql-and-postgresql/</link>
		<comments>http://iamtgc.com/2011/08/15/exploring-triggers-in-mysql-and-postgresql/#comments</comments>
		<pubDate>Mon, 15 Aug 2011 13:25:37 +0000</pubDate>
		<dc:creator>tgc</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Postgres]]></category>

		<guid isPermaLink="false">http://iamtgc.com/?p=533</guid>
		<description><![CDATA[Recently I was working on a car maintenance database. The database stores, among other things, odometer reading, miles per fill up, number of gallons per fill up, and cost per gallon. One of the missing pieces of information I wanted &#8230; <a href="http://iamtgc.com/2011/08/15/exploring-triggers-in-mysql-and-postgresql/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Recently I was working on a car maintenance database.  The database stores, among other things, odometer reading, miles per fill up, number of gallons per fill up, and cost per gallon.  One of the missing pieces of information I wanted to report on is the miles per gallon I was achieving.  While this is trivial to insert, I didn&#8217;t want to modify the client which was already deployed and running.  Since the data to determine this value was already present, I turned to database triggers to help me record this value.</p>
<p>Wikipedia describes <em>&#8220;A <a href="http://en.wikipedia.org/wiki/Database_trigger" title="Database trigger - Wikipedia" target="_blank">database trigger</a> is procedural code that is automatically executed in response to certain events on a particular table or view in a database.&#8221;</em></p>
<p>In our case, the procedural code we want to execute is the computation of our miles per gallon, and the event we are responding to is an insert into our table.  In this article I will outline how to create these triggers in both MySQL and PostgreSQL.<br />
<span id="more-533"></span><br />
Our triggers will be applied to the following table.</p>
<pre class="brush:sql;">
CREATE TABLE mileage (
   miles float,
   gallons float,
   mpg float
);
</pre>
<p>The following was tested in MySQL 5.5.14, but should work on other versions as well.</p>
<p>Let&#8217;s create our trigger.  The key things to note here are <strong>BEFORE INSERT</strong>, since we want to insert the mpg value along with the miles and gallons, and <strong>NEW</strong>, since we are referring to a column of a new row to be inserted.</p>
<pre class="brush:sql;">
-- MySQL
CREATE TRIGGER trig__mileage BEFORE INSERT ON mileage FOR EACH ROW SET NEW.mpg  = NEW.miles / NEW.gallons;
</pre>
<p>Now with our trigger created, we can test to see if it fires correctly.  If it fires correctly, we can expect our mpg column to be populated, otherwise it will be NULL.</p>
<pre class="brush:sql;">
-- MySQL
INSERT INTO mileage (miles, gallons) VALUES ( 250, 10 )

SELECT * FROM mileage;
+-------+---------+------+
| miles | gallons | mpg  |
+-------+---------+------+
|   250 |      10 |   25 |
+-------+---------+------+
</pre>
<p>Success!  It really is that simple.  Additional documentation, including more complex examples, can be found <a href="http://dev.mysql.com/doc/refman/5.5/en/create-trigger.html" title="MySQL ::   MySQL 5.5 Reference Manual :: 12.1.15 CREATE TRIGGER Syntax" target="_blank">here</a>.</p>
<p>Now on to PostgreSQL.  These were tested on PostgreSQL 8.3.15, but should work on other versions as well.</p>
<p>The first thing to note is the <a href="http://www.postgresql.org/docs/8.3/static/sql-createtrigger.html" title="PostgreSQL: Documentation: Manuals: PostgreSQL 8.3: CREATE TRIGGER" target="_blank">CREATE TRIGGER</a> statement in PostgreSQL takes a user supplied function as an argument.  This function must return type TRIGGER, and in our instance will be responsible for calculating our miles per gallon.<br />
In our function we use the <strong>NEW</strong> variable, which holds the new database row for insert.</p>
<pre class="brush:sql;">
-- PostgreSQL
CREATE OR REPLACE FUNCTION trig_proc__calculate_mpg() RETURNS TRIGGER AS $_$
BEGIN
   NEW.mpg := NEW.miles / NEW.gallons;
   RETURN NEW;
END $_$
LANGUAGE plpgsql;
</pre>
<p>With our function created, we now create the trigger.</p>
<pre class="brush:sql;">
-- PostgreSQL
CREATE TRIGGER trig__mileage BEFORE INSERT ON mileage FOR EACH ROW EXECUTE PROCEDURE trig_proc__calculate_mpg();
</pre>
<p>And now to test if our trigger fires correctly.</p>
<pre class="brush:sql;">
-- PostgreSQL
INSERT INTO mileage (miles, gallons) VALUES ( 312.3, 12.1 );

SELECT * FROM mileage;
 miles | gallons |       mpg
-------+---------+------------------
 312.3 |    12.1 | 25.8099173553719
</pre>
<p>As you can see, our trigger has populated the mpg column.  Additional documentation on triggers in Postgres can be found <a href="http://www.postgresql.org/docs/8.3/static/triggers.html" title="PostgreSQL: Documentation: Manuals: PostgreSQL 8.3: Triggers" target="_blank">here</a> and <a href="http://www.postgresql.org/docs/8.3/static/plpgsql-trigger.html" title="PostgreSQL: Documentation: Manuals: PostgreSQL 8.3: Trigger Procedures" target="_blank">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://iamtgc.com/2011/08/15/exploring-triggers-in-mysql-and-postgresql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to change your Amazon Associates ID in WordPress posts</title>
		<link>http://iamtgc.com/2011/07/08/how-to-change-your-amazon-associates-id-in-wordpress-posts/</link>
		<comments>http://iamtgc.com/2011/07/08/how-to-change-your-amazon-associates-id-in-wordpress-posts/#comments</comments>
		<pubDate>Fri, 08 Jul 2011 20:53:44 +0000</pubDate>
		<dc:creator>tgc</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://iamtgc.com/?p=202</guid>
		<description><![CDATA[You may find yourself, for one reason or another, needing to update your amazon affiliate links in your WordPress posts to reflect a new tracking id. Depending on the number of posts your are dealing with, doing this by hand &#8230; <a href="http://iamtgc.com/2011/07/08/how-to-change-your-amazon-associates-id-in-wordpress-posts/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>You may find yourself, for one reason or another, needing to update your amazon affiliate links in your WordPress posts to reflect a new tracking id.</p>
<p>Depending on the number of posts your are dealing with, doing this by hand can be a real pain in the ass, not to mention highly error prone.</p>
<p>The following process was tested in WordPress 3.2, but applies to much older versions of WordPress as well.</p>
<p>You will need access to your WordPress database, either through the command line or an interface like phpMyAdmin.<br />
<span id="more-202"></span><br />
In this example, I will be demonstrating how to makes these changes using the command line.</p>
<p>We begin by connecting to the database, aptly named &#8220;wordpress_database&#8221; for this example. You will need to know your MySQL username and password. Replace <em>mysql_username</em> with your MySQL username on the command line below, your password is prompted for and not passed on the command line.</p>
<pre class="brush:shell">$ mysql -umysql_username -p wordpress_database
Enter password:

mysql&gt;</pre>
<p>Then execute the SQL necessary to update your post content. You will need to know your existing and new Amazon associate ids, referenced as <em>my_old_amazon-id-20</em> and <em>my_new_amazon-id-20</em> respectively below.</p>
<pre class="brush:sql">mysql&gt; update wp_posts set post_content = replace(post_content, 'my_old_amazon-id-20', 'my_new_amazon-id-20');</pre>
<p>If everything went smoothly, you&#8217;ll see something similar the following indicating the number of posts modified output to the screen.</p>
<pre class="brush:shell">Query OK, 3 rows affected (0.00 sec)
Rows matched: 37 Changed: 3 Warnings: 0</pre>
<p>Note the previous SQL statement will change posts, pages, attachments (and any other post types). If for example, you want to change only <em>pages</em>, leaving <em>posts</em> unchanged, you can modify the SQL to.</p>
<pre class="brush:sql">mysql&gt; update wp_posts set post_content = replace(post_content, 'my_old_amazon-id-20', 'my_new_amazon-id-20') where post_type = 'page';</pre>
<p>Now you can revisit your post and verify that the link has been correctly updated with your new associates id.</p>
]]></content:encoded>
			<wfw:commentRss>http://iamtgc.com/2011/07/08/how-to-change-your-amazon-associates-id-in-wordpress-posts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Implementing Zip Code Proximity Functions in MySQL and PostgreSQL</title>
		<link>http://iamtgc.com/2009/01/14/implementing-zip-code-proximity-functions-in-mysql-and-postgresql/</link>
		<comments>http://iamtgc.com/2009/01/14/implementing-zip-code-proximity-functions-in-mysql-and-postgresql/#comments</comments>
		<pubDate>Wed, 14 Jan 2009 17:26:08 +0000</pubDate>
		<dc:creator>tgc</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Postgres]]></category>

		<guid isPermaLink="false">http://iamtgc.com/?p=95</guid>
		<description><![CDATA[On most retail and social networking websites (along with many others), you&#8217;ll have the capability to search for people, businesses, store locations, etc within a given distance of your location. This can be implemented in a number of ways both &#8230; <a href="http://iamtgc.com/2009/01/14/implementing-zip-code-proximity-functions-in-mysql-and-postgresql/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>On most retail and social networking websites (along with many others), you&#8217;ll have the capability to search for people, businesses, store locations, etc within a given distance of your location.  This can be implemented in a number of ways both mathematically and programmatically.  In an attempt to reduce the amount of code I (or others) have to write, be it in PHP, Python, or any number languages that may interface with our database, I have chosen to implement these zip code proximity and distance functions as stored procedures in the database.<br />
<span id="more-95"></span><br />
To start, you may already have your database with Zip Code coordinates, if you are looking for one, Team RedLine offers an excellent <a href="http://teamredline.com/zc">Zip Code Database</a> for $5 US that can be easily imported into the database of your choice.</p>
<p>The table that we will be using was created as follows:</p>
<pre class="brush:sql;">
CREATE TABLE zipcodes (
    zip varchar(5),
    lat double precision,
    lon double precision,
    city varchar(30),
    state varchar(30),
    state_abbrev varchar(2));
</pre>
<p>I use <strong>57.2958</strong> as a constant for <strong>180 / &pi;</strong> to convert between degrees and radians, beyond this I will focus on the implementation and point you to the <a href="http://en.wikipedia.org/wiki/Haversine_formula">Haversine Formula</a> and the <a href="http://en.wikipedia.org/wiki/Law_of_cosines_(spherical)">Law of Consines</a> if you wish to read more on the math.</p>
<p>First we will examine how these functions are written for PostgreSQL.  (MySQL functions are further down)</p>
<p>The first function implements the Law of Consines, and allows the user to specify which measurement (miles or kilometers) to use, to determine the distance between two coordinates.</p>
<pre class="brush:sql;">
CREATE FUNCTION calculate_distance(varchar, double precision, double precision, double precision, double precision) RETURNS double precision
    AS $_$
   DECLARE
      earth_radius double precision;
   BEGIN
      IF $1 = 'mi' THEN
         earth_radius := 3959.0;
      ELSIF $1 = 'km' THEN
         earth_radius := 6371.0;
      END IF;
      RETURN earth_radius * acos(sin($2 / 57.2958) * sin($4 / 57.2958) + cos($2/ 57.2958) * cos($4 / 57.2958) * cos(($5 / 57.2958) - ($3 / 57.2958)));
   END;
   $_$
    LANGUAGE plpgsql;
</pre>
<p>The calculate_distance function can certainly be used stand alone, but in our example it is called exclusively from our zip_proximity function below.</p>
<p>zip_proximity takes a <a href="http://www.postgresql.org/docs/8.1/static/plpgsql-cursors.html">refcursor</a>, a zipcode, a distance, and a distance metric (&#8216;mi&#8217; or &#8216;km&#8217;).<br />
<strong>Update:</strong> Please see <a href="http://iamtgc.com/2009/10/01/returning-composite-types-in-postgres-stored-procedures/" title="Returning Composite Types in Postgres Stored Procedures">this article</a> on implementing this function without using refcursor.</p>
<p>First we retrieve the coordinates for the &#8220;home&#8221; zipcode, and query the databases, performing calculate_distance on each entry in the database, capturing only those that fall withing the given distance.  We add a field to the cursor we return, which is the distance from the home zipcode, to the zipcode which fell within our provided distance.</p>
<pre class="brush:sql;">
CREATE FUNCTION zip_proximity(refcursor, character, double precision, varchar) RETURNS refcursor
    AS $_$
   DECLARE
      home_lat float;
      home_lon float;
   BEGIN
      SELECT lat, lon INTO home_lat, home_lon FROM zipcodes WHERE zip = $2;
      OPEN $1 FOR
         SELECT zip, lat, lon, city, state, state_abbrev, calculate_distance($4, home_lat, home_lon, lat, lon) AS distance FROM zipcodes
             WHERE calculate_distance($4, home_lat, home_lon, lat, lon) < $3 ORDER BY distance;
      RETURN $1;
   END;
   $_$
    LANGUAGE plpgsql;
</pre>
<p>Now we will query all zipcodes within a 3 mile radius of Mountain View, California 94043.<br />
Here is how we call our new function(s).  Since we are using cursors, we need to be in a transaction.</p>
<pre class="brush:plain;">
testdb=# BEGIN;
BEGIN
testdb=# SELECT zip_proximity('zc', '94043', 3, 'mi');
 zip_proximity
---------------
 zc
(1 row)

testdb=# FETCH ALL FROM zc;
  zip  |   lat    |    lon     |     city      |   state    | state_abbrev |     distance
-------+----------+------------+---------------+------------+--------------+-------------------
 94043 | 37.42337 | -122.07981 | MOUNTAIN VIEW | CALIFORNIA | CA           |                 0
 94039 | 37.41884 | -122.09124 | MOUNTAIN VIEW | CALIFORNIA | CA           | 0.701004112864842
 94035 | 37.41753 | -122.05283 | MOUNTAIN VIEW | CALIFORNIA | CA           |  1.53459076775345
 94042 | 37.39314 | -122.07827 | MOUNTAIN VIEW | CALIFORNIA | CA           |  2.09052870375317
 94041 | 37.38961 | -122.07715 | MOUNTAIN VIEW | CALIFORNIA | CA           |  2.33729808540454
 94306 | 37.41478 | -122.12139 | PALO ALTO     | CALIFORNIA | CA           |  2.35776644118448
 94303 | 37.44424 | -122.11736 | PALO ALTO     | CALIFORNIA | CA           |  2.51480871338068
(7 rows)

testdb=# END;
COMMIT
</pre>
<p>Now let's take a look at the MySQL functions.  The calculate_distance function is essentially identical to the PostgreSQL function above.</p>
<pre class="brush:sql;">
DELIMITER //
CREATE FUNCTION calculate_distance(measurement varchar(2), base_lat double precision, base_lon double precision, lat double precision, lon double precision) RETURNS double precision
   BEGIN
      DECLARE earth_radius double precision;
      IF measurement = 'km' THEN
         SET earth_radius = 6371.0;
      ELSEIF measurement = 'mi' THEN
         SET earth_radius = 3959.0;
      END IF;
      RETURN earth_radius * ACOS(SIN(base_lat / 57.2958) * SIN(lat / 57.2958) + COS(base_lat / 57.2958) * COS(lat / 57.2958) * COS((lon / 57.2958) - (base_lon / 57.2958)));
   END //
DELIMITER ;
</pre>
<p>This function differs slightly from it's Postgres counterpart.  Since MySQL does not currently support functions that return a cursor, we will create a procedure which will execute the same query that we would have returned in the cursor.</p>
<pre class="brush:sql;">
DELIMITER //
CREATE PROCEDURE zip_proximity(zipcode varchar(5), radius double precision, measurement varchar(2))
   BEGIN
   DECLARE base_lat double precision;
   DECLARE base_lon double precision;
   SELECT lat, lon INTO base_lat, base_lon FROM zipcodes WHERE zip = zipcode;
   SELECT zip, lat, lon, city, state, state_abbrev, calculate_distance(measurement, base_lat, base_lon, lat, lon) AS distance FROM zipcodes
      WHERE calculate_distance(measurement, base_lat, base_lon, lat, lon) < radius ORDER BY distance;
   END //
DELIMITER ;
</pre>
<p>Now here is how we would call the procedure, again we are querying for all zip codes within a three mile radius of 94043.</p>
<pre class="brush:plain;">
mysql> call zip_proximity('94043', 3, 'mi');
+-------+----------+------------+---------------+------------+--------------+-------------------+
| zip   | lat      | lon        | city          | state      | state_abbrev | distance          |
+-------+----------+------------+---------------+------------+--------------+-------------------+
| 94043 | 37.42337 | -122.07981 | MOUNTAIN VIEW | CALIFORNIA | CA           |                 0 |
| 94039 | 37.41884 | -122.09124 | MOUNTAIN VIEW | CALIFORNIA | CA           | 0.701004115082249 |
| 94035 | 37.41753 | -122.05283 | MOUNTAIN VIEW | CALIFORNIA | CA           |  1.53459076784732 |
| 94042 | 37.39314 | -122.07827 | MOUNTAIN VIEW | CALIFORNIA | CA           |  2.09052870372395 |
| 94041 | 37.38961 | -122.07715 | MOUNTAIN VIEW | CALIFORNIA | CA           |  2.33729808557031 |
| 94306 | 37.41478 | -122.12139 | PALO ALTO     | CALIFORNIA | CA           |  2.35776644108718 |
| 94303 | 37.44424 | -122.11736 | PALO ALTO     | CALIFORNIA | CA           |  2.51480871282271 |
+-------+----------+------------+---------------+------------+--------------+-------------------+
7 rows in set (0.75 sec)

Query OK, 0 rows affected (0.75 sec)
</pre>
<p>Feel free to leave a comment with any questions or suggestions.</p>
]]></content:encoded>
			<wfw:commentRss>http://iamtgc.com/2009/01/14/implementing-zip-code-proximity-functions-in-mysql-and-postgresql/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Exploring Stored Procedures in MySQL and PostgreSQL</title>
		<link>http://iamtgc.com/2008/12/19/exploring-stored-procedures-in-mysql-and-postgresql/</link>
		<comments>http://iamtgc.com/2008/12/19/exploring-stored-procedures-in-mysql-and-postgresql/#comments</comments>
		<pubDate>Fri, 19 Dec 2008 14:38:57 +0000</pubDate>
		<dc:creator>tgc</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Postgres]]></category>

		<guid isPermaLink="false">http://iamtgc.com/?p=69</guid>
		<description><![CDATA[The PostgreSQL PL/pgSQL procedural language is well documented here and the MySQL Reference Manual is available here. The MySQL documentation is, in my opinion, lacking, however the MySQL Stored Procedure Forum helps a great deal in making up for the &#8230; <a href="http://iamtgc.com/2008/12/19/exploring-stored-procedures-in-mysql-and-postgresql/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The PostgreSQL PL/pgSQL procedural language is well documented <a href="http://www.postgresql.org/docs/8.3/static/plpgsql.html">here</a> and the MySQL Reference Manual is available <a href="http://dev.mysql.com/doc/refman/5.1/en/stored-routines.html">here</a>.  The MySQL documentation is, in my opinion, lacking, however the <a href="http://forums.mysql.com/list.php?98">MySQL Stored Procedure Forum</a> helps a great deal in making up for the lack of  documentation.<br />
<span id="more-69"></span><br />
Now, let&#8217;s take for example this simplified user table.  In reality it would contain additional information, a hashed password, real name, who knows, but for the sake of our example, we&#8217;ll keep it minimal.  Once the table is created, we will want to create a stored procedure that automatically expires accounts that have not logged on in more than a month.</p>
<pre class="brush:sql;">
CREATE TABLE users (
   username varchar(12),
   last_login timestamp,
   expired boolean
);
</pre>
<p>Now, we could create a stored procedure that expires all accounts that have not logged on in a month, but to make it more versatile, and to demonstrate more of the capabilities, we will allow the user to define the number of days since last logged on before the account expires.</p>
<p>First, let&#8217;s see how this we could write this for PostgreSQL, we will be using the PL/pgSQL procedural language.</p>
<pre class="brush:sql;">
CREATE OR REPLACE FUNCTION mark_expired(days INT) RETURNS VOID AS
$$
DECLARE
   delta BIGINT;
BEGIN
   delta := $1*86400;
   UPDATE users SET expired=true WHERE EXTRACT(epoch from age(CURRENT_TIMESTAMP, last_login)) > delta;
END;
$$
LANGUAGE plpgsql;
</pre>
<p>Let&#8217;s look at the user table before running the stored procedure</p>
<pre class="brush:plain;">
 username  |     last_login      | expired
----------+---------------------+---------
 homer    | 2008-12-18 00:00:00 | f
 marge    | 2008-11-18 00:00:00 | f
 bart     | 2008-12-14 00:00:00 | f
 lisa     | 2008-12-17 00:00:00 | f
 maggie   | 2008-12-19 00:00:00 | f
</pre>
<p>Here is how you would execute the stored procedure, with our user defined 30 day argument.</p>
<pre class="brush:plain;">
testdb=# select mark_expired(30);
testdb=# select * from users;
 username |     last_login      | expired
----------+---------------------+---------
 homer    | 2008-12-18 00:00:00 | f
 bart     | 2008-12-14 00:00:00 | f
 lisa     | 2008-12-17 00:00:00 | f
 maggie   | 2008-12-19 00:00:00 | f
 marge    | 2008-11-18 00:00:00 | t
</pre>
<p>Success!, Marge&#8217;s account has now been marked expired, since she has not logged on in the last 30 days.</p>
<p>Your first inclination may be to extract the day from age, but this does not work as one may think.  Take for example the following&#8230;</p>
<pre class="brush:plain;">
testdb=# select age(now(), CURRENT_DATE-31);
             age
-----------------------------
 1 mon 1 day 13:02:30.065623
(1 row)
</pre>
<p>Now if we extract day, this is what we get&#8230;</p>
<pre class="brush:plain;">
testdb=# select extract(day from age(now(), CURRENT_DATE-31));
 date_part
-----------
         1
(1 row)
</pre>
<p>This is not in fact what we were looking for, if we were to use this method to expire accounts, this account appears to have been logged in as recently as one day ago, when in fact 31 days have elapsed.  So this is why we chose to use epoch, which in this case will get total elapsed seconds.</p>
<p>Now, let&#8217;s review how you might write this for MySQL.</p>
<pre class="brush:sql;">
DELIMITER //
CREATE PROCEDURE mark_expired (days INT)
BEGIN
   UPDATE users SET expired = true
              WHERE last_login < SUBDATE(CURRENT_TIMESTAMP, INTERVAL days DAY);
END //
DELIMITER ;
</pre>
<p>In this example we take a slightly different approach, we subtract the days argument from the current timestamp, and see if the last login timestamp is older than this.  This leverages MySQL's SUBDATE function and avoids having to convert days into seconds.</p>
<p>Let's take a look at our table again, before calling the procedure</p>
<pre class="brush:plain;">
mysql> select * from users;
+----------+---------------------+---------+
| username | last_login          | expired |
+----------+---------------------+---------+
| homer    | 2008-12-18 00:00:00 |       0 |
| marge    | 2008-11-18 00:00:00 |       0 |
| bart     | 2008-12-14 00:00:00 |       0 |
| lisa     | 2008-12-17 00:00:00 |       0 |
| maggie   | 2008-12-19 00:00:00 |       0 |
+----------+---------------------+---------+
</pre>
<p>And how you would call the procedure in MySQL.</p>
<pre class="brush:plain;">
mysql> CALL mark_expired(30);
mysql> select * from users;
+----------+---------------------+---------+
| username | last_login          | expired |
+----------+---------------------+---------+
| homer    | 2008-12-18 00:00:00 |       0 |
| marge    | 2008-11-18 00:00:00 |       1 |
| bart     | 2008-12-14 00:00:00 |       0 |
| lisa     | 2008-12-17 00:00:00 |       0 |
| maggie   | 2008-12-19 00:00:00 |       0 |
+----------+---------------------+---------+
</pre>
<p>Again, success, Marge's account has been expired.</p>
]]></content:encoded>
			<wfw:commentRss>http://iamtgc.com/2008/12/19/exploring-stored-procedures-in-mysql-and-postgresql/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How to Fix or Remove Uncooperative Widgets in WordPress</title>
		<link>http://iamtgc.com/2008/12/03/how-to-fix-or-remove-uncooperative-widgets-in-wordpress/</link>
		<comments>http://iamtgc.com/2008/12/03/how-to-fix-or-remove-uncooperative-widgets-in-wordpress/#comments</comments>
		<pubDate>Wed, 03 Dec 2008 05:19:41 +0000</pubDate>
		<dc:creator>tgc</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://iamtgc.com/?p=33</guid>
		<description><![CDATA[Recently, I was working with php-code-widget to include some custom PHP code in a WordPress widget. Unfortunately, and much to my surprise, the custom code did not work flawlessly the first time and I was left staring at errors like: &#8230; <a href="http://iamtgc.com/2008/12/03/how-to-fix-or-remove-uncooperative-widgets-in-wordpress/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Recently, I was working with <a href="http://wordpress.org/extend/plugins/php-code-widget/">php-code-widget</a> to include some custom PHP code in a WordPress widget.  </p>
<p>Unfortunately, and much to my surprise, the custom code did not work flawlessly the first time and I was left staring at errors like:</p>
<p><strong>&#8220;Fatal error: Call to undefined function test(); in wp-content/plugins/php-code-widget /execphp.php(37): eval()&#8217;d code on line 1&#8243;.</strong><br />
<span id="more-33"></span><br />
Unfortunately, as this error shows up in the dashboard where I would normally edit the widgets content, this is not as straight forward to fix as one would hope.  So&#8230; after diving into the database and some trial and error I found that the widgets reside in the wp_options table, as this table is quite large, and contains more than just widget information, I had to narrow down what I was looking for.  I ended up with this query:</p>
<pre class="brush:plain;">
mysql> select option_name from wp_options where option_name like 'widget_%';
+------------------------+
| option_name            |
+------------------------+
| widget_akismet         |
| widget_archives        |
| widget_calendar        |
| widget_categories      |
| widget_execphp         |
| widget_meta            |
| widget_pages           |
| widget_recent_comments |
| widget_recent_entries  |
| widget_rss             |
| widget_tag_cloud       |
| widget_text            |
+------------------------+
</pre>
<p>In this case, it is content in the php-code-widget that is causing our errors, as there is no widget_php-code-widget, it seems that the widget_execphp is the next closest thing.  So let&#8217;s inspect the widget_execphp entry.</p>
<pre class="brush:plain;">
mysql> select * from wp_options where option_name='widget_execphp';
+-----------+---------+----------------+-----------------------------------------------------------------------------------+----------+
| option_id | blog_id | option_name    | option_value                                                                      | autoload |
+-----------+---------+----------------+-----------------------------------------------------------------------------------+----------+
|       347 |       0 | widget_execphp | a:1:{i:291302011;a:2:{s:5:"title";s:4:"Test";s:4:"text";s:16:"<?php test();?>";}} | yes      |
+-----------+---------+----------------+-----------------------------------------------------------------------------------+----------+
</pre>
<p>Bingo&#8230; here we can see the code that was entered into the widget.  In this case the test() function does not exist.</p>
<p>The first, and arguably the simplest option is to simply delete the entry,  we delete it using the option_id value we obtained above.  The option_id value is also used later in the article, in the event you chose to update the entry as opposed to removing it.</p>
<pre class="brush:plain;">
mysql> delete from wp_options where option_id=347;
Query OK, 1 row affected (0.29 sec)
</pre>
<p>At this point you can simply go back into the dashboard and recreate your widget, more careful not to include non existent functions this time.  But that would be too easy, a more interesting  alternative is to modify the existing entry.</p>
<pre class="brush:plain;">
mysql> update wp_options set option_value = "a:1:{i:291302011;a:2:{s:5:\"title\";s:4:\"Test\";s:4:\"text\";s:20:\"<?php new_test(); ?>\";}}" where option_id=347;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
</pre>
<p>Let&#8217;s look at this more closely, the above query updates option_value to:<br />
<br />
a:1:{i:291302011;a:2:{s:5:&#8221;title&#8221;;s:4:&#8221;Test&#8221;;s:4:&#8221;text&#8221;;<strong>s:20:&#8221;&lt;?php new_test(); ?&gt;&#8221;</strong>;}}</p>
<p>If you notice, two things have changed from the previous option_value value.  </p>
<p>The first change is to the string length variable, represented by <i>s</i>, which precedes the string.  In our example s:16 becomes s:20.  More simply put <strong>&lt;?php test(); ?&gt;</strong> (16 characters in length) becomes <strong>&lt;?php new_test(); ?&gt;</strong> (20 characters in length).</p>
<p>The necessary changes is to the string itself, and probably the reason you are getting the undesirable behavior in the first place, is left up to the reader.  It is my hope that this sets you in the right direction.</p>
]]></content:encoded>
			<wfw:commentRss>http://iamtgc.com/2008/12/03/how-to-fix-or-remove-uncooperative-widgets-in-wordpress/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

