<?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>Coderholic &#187; mysql</title>
	<atom:link href="http://www.coderholic.com/category/mysql/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.coderholic.com</link>
	<description>Addicted to Development</description>
	<lastBuildDate>Tue, 31 Aug 2010 09:19:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>PostgreSQL for MySQL users</title>
		<link>http://www.coderholic.com/postgresql-for-mysql-users/</link>
		<comments>http://www.coderholic.com/postgresql-for-mysql-users/#comments</comments>
		<pubDate>Sat, 27 Feb 2010 16:54:17 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[mysql]]></category>
		<category><![CDATA[databases]]></category>
		<category><![CDATA[geomium]]></category>
		<category><![CDATA[postgresql]]></category>

		<guid isPermaLink="false">http://www.coderholic.com/?p=567</guid>
		<description><![CDATA[I&#8217;ve been a long time user of MySQL, and despite having had some frustrations I&#8217;ve been pretty happy with MySQL. I&#8217;m comfortable with it, I know where its weaknesses lie and where it&#8217;s strong. I&#8217;ve never really had to look at alternatives. This all changed for a project that has been taking up all of [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been a long time user of MySQL, and despite having had <a href="http://forums.mysql.com/read.php?24,288330,288330#msg-288330">some frustrations</a> I&#8217;ve been pretty happy with MySQL. I&#8217;m comfortable with it, I know where its weaknesses lie and where it&#8217;s strong. I&#8217;ve never really had to look at alternatives.</p>
<p>This all changed for a project that has been taking up all of my spare time lately, <a href="http://www.geomium.com">Geomium</a>, a location-based communication tool. MySQL&#8217;s geospacial support is almost completely non-existant. PostgreSQL, on the other had, when combined with the <a href="http://postgis.refractions.net/">PostGIS</a> extension, has fantastic support. So PostgreSQL was what the project needed. I thought it&#8217;d be fairly easy to transition from MySQL to PostgresSQL but the command line clients of these two RDBMSes are very different. Here are some of the things I&#8217;ve learnt.</p>
<table width=100% border=1>
<tr>
<th>MySQL</th>
<th>PostgreSQL</th>
<th>Description</th>
</tr>
<tr>
<td>mysql -u&lt;user&gt; -p&lt;password &lt;database&gt;</td>
<td>psql -U&lt;user&gt; -P&lt;password&gt; &lt;database&gt;</td>
<td>Start command line client, and connect to &lt;database&gt;</td>
</tr>
<tr>
<td>SHOW DATABASES;</td>
<td>\l</td>
<td>Show available databases</td>
</tr>
<tr>
<td>SHOW TABLES;</td>
<td>\dt</td>
<td>Show available tables</td>
</tr>
<tr>
<td>USE &lt;database&gt;;</td>
<td>\c &lt;database&gt;</td>
<td>Connect to &lt;database&gt;</td>
</tr>
<tr>
<td>DESCRIBE &lt;table&gt;;</td>
<td>\dt &lt;table&gt;</td>
<td>Describe &lt;table&gt; structure</td>
</tr>
<tr>
<td>SHOW FULL PROCESSLIST;</td>
<td>SELECT * FROM pg_stat_activity;</td>
<td>Show all running queries</td>
</tr>
<tr>
<td>exit (or quit or \q)</td>
<td>\q</td>
<td>Quit the client</td>
</tr>
</table>
<p>A few other things to note: PostgreSQL only supports single quotes in queries not double quotes, so
<pre>SELECT * FROM table WHERE column = "value"</pre>
<p> would need to be rewritten as
<pre>SELECT * FROM table WHERE column = 'value'</pre>
<p>PostgreSQL also defaults to being case-sensitive, whereas MySQL defaults to case-insensitive, so you might want to modify your queries to something like
<pre>SELECT * FROM table WHERE lower(column) = 'value'</pre>
<p> although this can prevent an index on &#8220;column&#8221; from being used.</p>
<p>At first I thought PostgreSQL didn&#8217;t support some of the handy MySQL date functions (such as NOW() &#8211; INTERVAL 1 DAYS), but it turns out that it does support them, and more. It&#8217;s just fussier about the format. For details see the <a href="http://developer.postgresql.org/pgdocs/postgres/functions-datetime.html">datetime documentation</a>. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.coderholic.com/postgresql-for-mysql-users/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Server Monitoring with Munin</title>
		<link>http://www.coderholic.com/server-monitoring-with-munin/</link>
		<comments>http://www.coderholic.com/server-monitoring-with-munin/#comments</comments>
		<pubDate>Wed, 21 Oct 2009 21:53:56 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[apache]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[scripts]]></category>
		<category><![CDATA[munin server opensource monitoring sysadmin]]></category>

		<guid isPermaLink="false">http://www.coderholic.com/?p=378</guid>
		<description><![CDATA[Munin is an excellent open source tool for monitoring and graphing server performance metrics. It can be configured to send out alert emails when something goes wrong with your server, and the graphs make it easy to view trends over time: You could see that your site gets much less traffic on a Sunday, for [...]]]></description>
			<content:encoded><![CDATA[<p>Munin is an excellent open source tool for monitoring and graphing server performance metrics. It can be configured to send out alert emails when something goes wrong with your server, and the graphs make it easy to view trends over time: You could see that your site gets much less traffic on a Sunday, for example, or that the number of database queries performed per day has doubled in the last 2 months.</p>
<p><img style="border: 1px solid gray;" src="/wp-content/uploads/munin-graphs1.png" alt="" /></p>
<p>On a Debian-based system installing Munin is as simple as running the following command, and then going to http://your-server/munin/ in your browser:</p>
<pre>sudo aptitude install munin</pre>
<p>Munin comes with lots of monitoring plugins by default, including those for MySQL, PostgresSQL, Apache, Tomcat, Squid, and for things such a CPU and memory usage, load average, network traffic, and many more. You can also find lots of user submitted plugins on sites like <a href="http://muninexchange.projects.linpro.no/">Munin Exchange</a>.</p>
<p>Munin doesn&#8217;t have to be used solely for monitoring server performance though. Being so easy to extend Munin is  also a great tool for tracking non-server performance related trends over time. In just a few lines of code you could write plugins to track the following stats about your website:</p>
<ul>
<li>Number of User signups</li>
<li>Google PageRank</li>
<li>Pages in Google&#8217;s index</li>
<li>Number of backlinks</li>
<li>Number of twitter mentions</li>
<li>Alexa traffic rank</li>
</ul>
<p>The <em>number of pages in Google&#8217;s index</em> is actually a plugin I&#8217;ve written. Simple put the following code in your /etc/munin/plugins directory to see it in action:</p>
<pre name="code" class="python">
#!/bin/sh
# Munin Plugin to display the number of pages in the
# google index for all of the given websites
# Ben Dowling - www.coderholic.com

# Change this to whatever sites you're interested in
websites="www.yahoo.com www.google.com www.twitter.com"

if [ "$1" = "autoconf" ]; then
        echo yes
        exit 0
fi

if [ "$1" = "config" ]; then

        echo 'graph_title Number of Pages in Google Index'
        echo 'graph_args --base 1000 -l 0 '
        echo 'graph_vlabel number of pages'
        echo 'graph_category google'
        echo 'graph_info This graph shows the number of pages in the Google index for a given website.'

        i=0
        for site in $websites
        do
                name="site_${i}"
                echo "${name}.label ${site}"
                echo "${name}.draw LINE2"
                echo "${name}.info The number of pages in the google index."
                i=$((i+1))
        done
        exit 0
fi

i=0
for site in $websites
do
        name="site_${i}"
		value=$(wget -q --user-agent=Firefox -O - "http://www.google.com/search?q=site:${site}" | grep -E "of about <b>[0-9,]+</b>" -o | grep -E "[0-9,]+" -o | sed "s/,//g")
        echo "${name}.value ${value}"

        i=$((i+1))
done
</pre>
<p>For more details about Munin see their <a href="http://munin.projects.linpro.no/">homepage</a>, which also includes detailed documentation on writing your own plugins. </p>
<p>Let me know if you can think of any more Munin plugins that could be interesting, or if you&#8217;ve used any yourself!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coderholic.com/server-monitoring-with-munin/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>MySQL table size reporting script</title>
		<link>http://www.coderholic.com/mysql-table-size-reporting-script/</link>
		<comments>http://www.coderholic.com/mysql-table-size-reporting-script/#comments</comments>
		<pubDate>Tue, 29 Sep 2009 07:40:04 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[mysql]]></category>
		<category><![CDATA[scripts]]></category>

		<guid isPermaLink="false">http://www.coderholic.com/?p=330</guid>
		<description><![CDATA[I&#8217;ve written a small shell script to report how much disk space each table in a given MySQL database is using. For example, below is the output of the script when run against this site&#8217;s database: bmd /~: ./dbSize.sh coderholic root ******** wp_comments Data: 6.60MB Indexes: .15MB Total: 6.75MB wp_links Data: 0MB Indexes: 0MB Total: [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve written a small shell script to report how much disk space each table in a given MySQL database is using. For example, below is the output of the script when run against this site&#8217;s database:</p>
<pre>
bmd /~: ./dbSize.sh coderholic root ********
wp_comments Data: 6.60MB Indexes: .15MB Total: 6.75MB
wp_links Data: 0MB Indexes: 0MB Total: 0MB
wp_options Data: 1.57MB Indexes: .01MB Total: 1.58MB
wp_postmeta Data: .01MB Indexes: .01MB Total: .02MB
wp_posts Data: .57MB Indexes: .02MB Total: .60MB
wp_term_relationships Data: 0MB Indexes: .01MB Total: .02MB
wp_term_taxonomy Data: 0MB Indexes: 0MB Total: 0MB
wp_terms Data: 0MB Indexes: 0MB Total: 0MB
wp_tla_data Data: 0MB Indexes: 0MB Total: 0MB
wp_tla_rss_map Data: 0MB Indexes: 0MB Total: 0MB
wp_usermeta Data: 0MB Indexes: 0MB Total: 0MB
wp_users Data: 0MB Indexes: 0MB Total: 0MB
*** 12 Tables | Data: 8.78MB Indexes: .25MB Total: 9.03MB ***
</pre>
<p>With a few small modifications I&#8217;m sure it&#8217;d be possible to get the script working PostgreSQL or other RDBMSes. The full code is below:</p>
<pre name="code" class="python">
#!/bin/bash
# Calculate the storage space used up by all tables in a given MySQL database
# Ben Dowling - www.coderholic.com
database=$1
username=$2
password=$3

if [ ${#database} -eq 0 ]
then
	echo "Usage: $0 &lt;database&gt; [username [password]]"
	exit
fi

if [ "$password" ]
then
   password="-p$password"
fi

mysql="mysql -u $username $password $database"

$mysql -se "USE $database";

tables=$($mysql -se "SHOW TABLES")

totalData=0
totalIndex=0
totalTables=0

for table in $tables
do
   output=$($mysql -se "SHOW TABLE STATUS LIKE \"$table\"\G")
   data=$(echo "$output" | grep Data_length | awk -F': ' '{print $2}')
   dataMegs=$(echo "scale=2;$data/1048576" | bc)
   index=$(echo "$output" | grep Index_length | awk -F': ' '{print $2}')
   indexMegs=$(echo "scale=2;$index/1048576" | bc)
   total=$(($index+$data))
   totalMegs=$(echo "scale=2;$total/1048576" | bc)

   echo "$table Data: ${dataMegs}MB Indexes: ${indexMegs}MB Total: ${totalMegs}MB"

   totalData=$(($totalData+$data))
   totalIndex=$(($totalIndex+$index))
   totalTables=$(($totalTables+1))
done

dataMegs=$(echo "scale=2;$totalData/1048576" | bc)
indexMegs=$(echo "scale=2;$totalIndex/1048576" | bc)
total=$(($totalIndex+$totalData))
totalMegs=$(echo "scale=2;$total/1048576" | bc)

echo "*** $totalTables Tables | Data: ${dataMegs}MB Indexes: ${indexMegs}MB Total: ${totalMegs}MB ***"
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.coderholic.com/mysql-table-size-reporting-script/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>SQL Antipatterns</title>
		<link>http://www.coderholic.com/sql-antipatterns/</link>
		<comments>http://www.coderholic.com/sql-antipatterns/#comments</comments>
		<pubDate>Sat, 11 Jul 2009 17:43:56 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[mysql]]></category>
		<category><![CDATA[software design]]></category>

		<guid isPermaLink="false">http://www.coderholic.com/?p=283</guid>
		<description><![CDATA[I was really pleased to come across the &#8220;SQL Antipatterns Stirke Back&#8221; presentation recently, which discusses common mistakes with SQL database design. It gives some really good advice on how best to design databases to avoid these issues. I&#8217;ve certainly made some of the mistakes mentioned, and I&#8217;m sure I&#8217;ll be referring back to this [...]]]></description>
			<content:encoded><![CDATA[<p>I was really pleased to come across the &#8220;SQL Antipatterns Stirke Back&#8221; presentation recently, which discusses common mistakes with SQL database design. It gives some really good advice on how best to design databases to avoid these issues. I&#8217;ve certainly made some of the mistakes mentioned, and I&#8217;m sure I&#8217;ll be referring back to this presentation again and again!</p>
<div style="width:425px;text-align:left" id="__ss_1319559"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back" title="Sql Antipatterns Strike Back">Sql Antipatterns Strike Back</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=sqlantipatternsstrikeback-090421005946-phpapp01&#038;stripped_title=sql-antipatterns-strike-back" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=sqlantipatternsstrikeback-090421005946-phpapp01&#038;stripped_title=sql-antipatterns-strike-back" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object>
<div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">documents</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/billkarwin">Bill Karwin</a>.</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.coderholic.com/sql-antipatterns/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Ultimate Scalability Presentation</title>
		<link>http://www.coderholic.com/the-ultimate-scalability-presentation/</link>
		<comments>http://www.coderholic.com/the-ultimate-scalability-presentation/#comments</comments>
		<pubDate>Wed, 29 Apr 2009 19:37:54 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[software design]]></category>
		<category><![CDATA[web dev]]></category>

		<guid isPermaLink="false">http://www.coderholic.com/?p=231</guid>
		<description><![CDATA[At work we&#8217;re experiencing some fairly rapid growth, and our single production server is starting the feel the strain. I&#8217;ve been doing a lot of investigation into how we can scale the site, and thankfully there is lots of information out there. The &#8220;Do you Scale&#8221; presentation I saw at PHP London a couple of [...]]]></description>
			<content:encoded><![CDATA[<p>At <a href="http://www.mendeley.com">work</a> we&#8217;re experiencing some fairly rapid growth, and our single production server is starting the feel the strain. I&#8217;ve been doing a lot of investigation into how we can scale the site, and thankfully there is lots of information out there. </p>
<p>The &#8220;<a href="http://www.coderholic.com/php-london/">Do you  Scale</a>&#8221; presentation I saw at PHP London a couple of months ago gave a good high level overview of scalability issues, and included some useful techniques to help you scale.</p>
<p>I think I&#8217;ve found the ultimate scalability presentation though: &#8220;Real World Web: Performance &#038; Scalability&#8221;. The 189 slides contained within this presentation cover almost everything I&#8217;ve read elsewhere, and it&#8217;s packed full of practice advice!</p>
<p><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=rwwmysql2008-1216304757388368-8&#038;stripped_title=real-world-web-performance-scalability" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=rwwmysql2008-1216304757388368-8&#038;stripped_title=real-world-web-performance-scalability" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://www.coderholic.com/the-ultimate-scalability-presentation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL Connection Killer</title>
		<link>http://www.coderholic.com/mysql-connection-killer/</link>
		<comments>http://www.coderholic.com/mysql-connection-killer/#comments</comments>
		<pubDate>Sun, 26 Apr 2009 14:33:33 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://www.coderholic.com/?p=223</guid>
		<description><![CDATA[MySQL has a kill command which lets you kill a specific query or connection. This is useful it situations where you&#8217;ve accidentally issued a really complex query, or an application created a persistent connection and forgot to close it. Killing lots of connections can be tedious though. Say an application has created lots of persistent [...]]]></description>
			<content:encoded><![CDATA[<p>MySQL has a <a href="http://dev.mysql.com/doc/refman/5.0/en/kill.html">kill</a> command which lets you kill a specific query or connection. This is useful it situations where you&#8217;ve accidentally issued a really complex query, or an application created a persistent connection and forgot to close it. </p>
<p>Killing lots of connections can be tedious though. Say an application has created lots of persistent connections and not closed any of them, you&#8217;d have to go through the following steps:</p>
<p><code><br />
mysql&gt; SHOW FULL PROCESSLIST; /* shows all connections */<br />
mysql&gt; KILL &lt;process_id&gt;; /* for EVERY process you want to kill */<br />
</code></p>
<p>To make this process much simpler I wrote a little bash script that will kill all connections for a given MySQL user.</p>
<pre name="code" class="python">
#!/bin/bash
# Kill all MySQL connections for a given user
# Ben Dowling - Apr 2009
# www.coderholic.com

user="root" # MySQL super user
pass="" # Above user's password
kill_user="myapp" # User who you want to kill all the connections for

# Get the connection IDs for all connections from the user $kill_user
processList=$(mysql -u$user -p$pass -s -e "SHOW FULL PROCESSLIST" | grep $kill_user | awk '{print $1}')
# Loop through all the connection IDs and kill the connection
for id in $processList
do
       result=$(mysql -u$user -p$pass -s -e "KILL $id")
       echo $result
done
</pre>
<p>The MySQL superuser account name and password, along with the user you want to kill all the connection for, are embedded within the script. It would be quite simple to pass these in as command line arguments if you wanted to though.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coderholic.com/mysql-connection-killer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP Database Query Logging with PDO</title>
		<link>http://www.coderholic.com/php-database-query-logging-with-pdo/</link>
		<comments>http://www.coderholic.com/php-database-query-logging-with-pdo/#comments</comments>
		<pubDate>Thu, 26 Feb 2009 22:47:38 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[web dev]]></category>

		<guid isPermaLink="false">http://www.coderholic.com/?p=164</guid>
		<description><![CDATA[One thing I really like about CakePHP is that when it&#8217;s in debug mode it prints out a list of all the database queries used to generate a page, along with the time it took to run each query. This makes it really easy to find problem queries that are slowing down your site. It&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>One thing I really like about <a href="http://cakephp.org/">CakePHP</a> is that when it&#8217;s in debug mode it prints out a list of all the database queries used to generate a page, along with the time it took to run each query. This makes it really easy to find problem queries that are slowing down your site. It&#8217;s such a great feature that I wanted something similar for projects that don&#8217;t use CakePHP. </p>
<p>What I came up with was a LoggedPDO class that extends PHP&#8217;s <a href="http://uk.php.net/pdo">PDO</a> class. If you&#8217;re already using PDO in your project you only need to change a single line of code to enable database query logging:</p>
<pre name="code" class="php">
// Standard PDO...
$db = new PDO($dsn, $username, $password);
// ...should be changed to
$db = new LoggedPDO($dsn, $username, $password);
</pre>
<p>And then all your database queries will be logged, timed and all information printed out at the end of each page. My code also includes a decorator for PDOStatements so any prepared statements that get executed also get logged. Below is a small sample of the code in use:</p>
<pre name="code" class="php">
$db = new LoggedPDO("mysql:dbname=test;host=localhost", "root");
$results = $db-&gt;query("SHOW TABLES");
$tables = $results-&gt;fetchAll(PDO::FETCH_COLUMN);
foreach($tables AS $table) {
	$statement = $db-&gt;prepare("DESCRIBE :table");
	$statement-&gt;bindParam(":table", $table, PDO::PARAM_STR);
	$results = $statement-&gt;execute();
	$columns = $statement-&gt;fetchAll(PDO::FETCH_ASSOC);
}
</pre>
<p>Which would output:</p>
<table border=1>
<tr>
<th>Query</th>
<th>Time (ms)</th>
</tr>
<tr>
<td>SHOW TABLES</td>
<td>0.174</td>
</tr>
<tr>
<td>[PS] DESCRIBE :table</td>
<td>0.06</td>
</tr>
<tr>
<td>[PS] DESCRIBE :table</td>
<td>0.032</td>
</tr>
<tr>
<th>3 queries</th>
<th>0.266</th>
</tr>
</table>
<p>Full code for the both the LoggedPDO and LoggedPDOStatement classes is below:</p>
<pre name="code" class="php">
/**
* Extends PDO and logs all queries that are executed and how long
* they take, including queries issued via prepared statements
*/
class LoggedPDO extends PDO
{
	public static $log = array();

	public function __construct($dsn, $username = null, $password = null) {
		parent::__construct($dsn, $username, $password);
	}

	/**
	 * Print out the log when we're destructed. I'm assuming this will
	 * be at the end of the page. If not you might want to remove this
	 * destructor and manually call LoggedPDO::printLog();
	 */
	public function __destruct() {
		self::printLog();
	}

	public function query($query) {
		$start = microtime(true);
		$result = parent::query($query);
		$time = microtime(true) - $start;
		LoggedPDO::$log[] = array('query' =&gt; $query,
				                  'time' =&gt; round($time * 1000, 3));
		return $result;
	}

	/**
	 * @return LoggedPDOStatement
	 */
	public function prepare($query) {
		return new LoggedPDOStatement(parent::prepare($query));
	}

	public static function printLog() {
		$totalTime = 0;
		echo '&lt;table border=1&gt;&lt;tr&gt;&lt;th&gt;Query&lt;/th&gt;&lt;th&gt;Time (ms)&lt;/th&gt;&lt;/tr&gt;';
		foreach(self::$log as $entry) {
			$totalTime += $entry['time'];
			echo '&lt;tr&gt;&lt;td&gt;' . $entry['query'] . '&lt;/td&gt;&lt;td&gt;' . $entry['time'] . '&lt;/td&gt;&lt;/tr&gt;\n';
		}
		echo '&lt;tr&gt;&lt;th&gt;' . count(self::$log) . ' queries&lt;/th&gt;&lt;th&gt;' . $totalTime . '&lt;/th&gt;&lt;/tr&gt;\n';
		echo '&lt;/table&gt;';
	}
}

/**
* PDOStatement decorator that logs when a PDOStatement is
* executed, and the time it took to run
* @see LoggedPDO
*/
class LoggedPDOStatement {
	/**
	 * The PDOStatement we decorate
	 */
	private $statement;

	public function __construct(PDOStatement $statement) {
		$this-&gt;statement = $statement;
	}

	/**
	* When execute is called record the time it takes and
	* then log the query
	* @return PDO result set
	*/
	public function execute() {
		$start = microtime(true);
		$result = $this-&gt;statement-&gt;execute();
		$time = microtime(true) - $start;
		LoggedPDO::$log[] = array('query' =&gt; '[PS] ' . $this-&gt;statement-&gt;queryString,
				                  'time' =&gt; round($time * 1000, 3));
		return $result;
	}
	/**
	* Other than execute pass all other calls to the PDOStatement object
	* @param string $function_name
	* @param array $parameters arguments
	*/
	public function __call($function_name, $parameters) {
		return call_user_func_array(array($this-&gt;statement, $function_name), $parameters);
	}
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.coderholic.com/php-database-query-logging-with-pdo/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Handling Contact Form Failure</title>
		<link>http://www.coderholic.com/handling-contact-form-failure/</link>
		<comments>http://www.coderholic.com/handling-contact-form-failure/#comments</comments>
		<pubDate>Mon, 17 Nov 2008 15:53:40 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[web dev]]></category>

		<guid isPermaLink="false">http://www.coderholic.com/?p=104</guid>
		<description><![CDATA[There is an article over a DZone today &#8220;What if your contact form fails?&#8221;. The article discusses what to do if the contact form on your website fails to send a message. The approach they suggest is to display a message to the user saying it failed, and presenting them with a mailto link so [...]]]></description>
			<content:encoded><![CDATA[<p>There is an article over a DZone today <a href="http://css.dzone.com/news/what-if-your-contact-form-fail">&#8220;What if your contact form fails?&#8221;</a>. The article discusses what to do if the contact form on your website fails to send a message. The approach they suggest is to display a message to the user saying it failed, and presenting them with a mailto link so they can send you an email themselves.</p>
<p>This is one approach to the failed contact form problem, but it isn&#8217;t going to help much if the problem is actually with your email address. For example, you may have exceeded your disk quota, or you might have a badly configured mail server. </p>
<p>Another problem with the mail solution is that it requires the user to perform another action. They&#8217;ve gone to the trouble of filling out a contact form. If that fails they might not bother to send to send you an email too (although the suggested approach in the article does reduce the effort required).</p>
<p><strong>An Alternative Approach</strong></p>
<p>So what other approaches are there? What I do is store all contact form information in a database. Below is the SQL to create the basic messages table:</p>
<pre name="code" class="sql">
CREATE TABLE messages (
    id int auto_increment NOT NULL,
    sent timestamp NOT NULL,
    sender varchar(255) NOT NULL,
    message text,

    PRIMARY KEY(id)
);
</pre>
<p>Then when a contact form gets submitted you can store the information in the database before sending an email. Below is some sample PHP code, using PDO to access the database:</p>
<pre name="code" class="php">
// Get the form data
$sender = $_POST['sender'];
$message = $_POST['message'];

// Add the message to the database
$query = "INSERT INTO messages(sender, message) VALUES (:sender, :message);
$stmt = $pdo->prepare($query);
$stmt->bindParam(':sender', $sender, PDO::PARAM_STR);
$stmt->bindParam(':message', $message, PDO::PARAM_STR);
$stmt->execute();

// Send the mail
mail("me@my.domain", "Contact Form Message", $message, "From: {$sender}");
</pre>
<p>All that is left to do is create an admin page that lists all messages, and allows us to delete them. We could even include a link to the admin page in the emails we send to ourselves. By using this approach we never lose the message content, even if the mail call fails, because they all get stored in the database. All we need to do is check the admin page every so often and we&#8217;ll soon see if there are any new messages there.</p>
<p>Of course, this approach doesn&#8217;t have to be used in isolation. We can combine it with the approach suggested in the DZone article, and present the user with a mail link if sending the mail does fail. If the user decides not to send a mail though, we haven&#8217;t lost anything.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coderholic.com/handling-contact-form-failure/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automatic SQL generation using Dia</title>
		<link>http://www.coderholic.com/automatic-sql-generation-using-dia/</link>
		<comments>http://www.coderholic.com/automatic-sql-generation-using-dia/#comments</comments>
		<pubDate>Sun, 14 Sep 2008 21:12:03 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://www.coderholic.com/?p=80</guid>
		<description><![CDATA[If you don&#8217;t already know about it, Dia is an open source diagram drawing application, similar to Microsoft&#8217;s Visio. It makes it really simple to create all sorts of diagrams, including UML diagrams, flowcharts, and network diagrams. It also allows diagrams to be exported to a number of formats, including PNG images (which can easily [...]]]></description>
			<content:encoded><![CDATA[<p>If you don&#8217;t already know about it, <a href="http://live.gnome.org/Dia">Dia</a> is an open source diagram drawing application, similar to Microsoft&#8217;s Visio. It makes it really simple to create all sorts of diagrams, including UML diagrams, flowcharts, and network diagrams. It also allows diagrams to be exported to a number of formats, including PNG images (which can easily be converted to GIF images using my handy <a href="http://www.coderholic.com/png2gif/">PNG2GIF utility</a>).</p>
<p>Using a third party tool <a href="http://tedia2sql.tigris.org/">tedia2sql</a>, you can automatically generate SQL schema for a number of databases, including Oracle, MySQL, Postgres, based on your database diagram. In this post I&#8217;ll describe exactly how.</p>
<p><strong>The diagram</strong></p>
<p>To create the database diagram we&#8217;ll be using Dia&#8217;s UML tools. Classes represent database tables, and associations between classes represent foreign key constrains.</p>
<p>In this post I&#8217;ll go over a simple example database with just three tables: Film, Film_Actor and Actor.</p>
<p>To create our database diagram we&#8217;re going to use Dia&#8217;s UML shapes. When you first start Dia it defaults to displaying the &#8220;Assorted&#8221; set of shapes, so you&#8217;ll need to change the drop down to &#8220;UML&#8221;</p>
<p><a href="http://www.coderholic.com/wp-content/uploads/2008/09/dia1.png"><img class="alignnone size-medium wp-image-82" title="Dia user interface" src="http://www.coderholic.com/wp-content/uploads/2008/09/dia1-124x300.png" alt="" width="124" height="300" /></a></p>
<p>Then we can click on the UML class shape, which is at the top left.Once we&#8217;ve done that we should have a diagram that looks like the one below:</p>
<p><a href="http://www.coderholic.com/wp-content/uploads/2008/09/dia2.png"><img class="alignnone size-medium wp-image-83" title="Initial diagram" src="http://www.coderholic.com/wp-content/uploads/2008/09/dia2-300x148.png" alt="" width="300" height="148" /></a></p>
<p>Double clicking on the class will bring up a properties window, which has several tabs. On the first &#8220;Class&#8221; tab we can set the name. For the first table that is &#8220;Film&#8221;. On the &#8220;Attributes&#8221; tab we can enter the rows that this table will have. Setting the attribute visibility to protected signifies that it is a primary key.</p>
<p><a href="http://www.coderholic.com/wp-content/uploads/2008/09/dia3.png"><img class="alignnone size-medium wp-image-85" title="dia3" src="http://www.coderholic.com/wp-content/uploads/2008/09/dia3-242x300.png" alt="" width="242" height="300" /></a></p>
<p>After adding all three tables and attributes we end up with a diagram like the one below:</p>
<p><a href="http://www.coderholic.com/wp-content/uploads/2008/09/dia4.png"><img class="alignnone size-medium wp-image-84" title="dia4" src="http://www.coderholic.com/wp-content/uploads/2008/09/dia4-300x148.png" alt="" width="300" height="148" /></a></p>
<p>At this point we could already generate a database schema, but it wouldn&#8217;t contain any foreign key contraints. If you&#8217;re not interested in adding them then you can skip straight to the generation part.</p>
<p>Foreign key contraints must be modelled using the UML aggregation tool: The line with the white diamond on one end. Select that tool, and then click on one table and drag and drop onto another table. When you let go of the mouse button a link should be drawn between the two. Double clicking on that line brings up a properties dialog.</p>
<p><a href="http://www.coderholic.com/wp-content/uploads/2008/09/dia5.png"><img class="alignnone size-medium wp-image-86" title="dia5" src="http://www.coderholic.com/wp-content/uploads/2008/09/dia5-300x184.png" alt="" width="300" height="184" /></a></p>
<p>Enter the foreign key in one end, and the row to which the foreign key referrs. The link between the Film_Actors table and the Films table is shown above, where the link is from film_id to id.</p>
<p>After adding a similar link between the Film_Actors and Actor table we end up with our complete diagram:</p>
<p><a href="http://www.coderholic.com/wp-content/uploads/2008/09/dia6.png"><img class="alignnone size-medium wp-image-87" title="dia6" src="http://www.coderholic.com/wp-content/uploads/2008/09/dia6-300x142.png" alt="" width="300" height="142" /></a></p>
<p><strong>Generating the SQL</strong></p>
<p>Now that our database diagram is compete we can generate the SQL commands to create the database. The command to generate the code for MySQL InnoDB is:</p>
<blockquote><p>tedia2sql -i diagram.dia -o schema.sql -t innodb -f</p></blockquote>
<p>If we want to generate SQL for a different database (such as Oracle) then we just need to change the -t argument. The generated SQL contains lots of comments, but the main sections are shown below:</p>
<pre class="sql">-- Film
create table Film (
  id                        int not null,
  title                     varchar,
  year                      int,
  constraint pk_Film primary key (id)
) type = InnoDB ;

-- Actor
create table Actor (
  id                        int not null,
  name                      varchar,
  dob                       date,
  constraint pk_Actor primary key (id)
) type = InnoDB ;

-- Film_Actors
create table Film_Actors (
  film_id                   int not null,
  actor_id                  int not null,
  constraint pk_Film_Actors primary key (film_id,actor_id)
) type = InnoDB ;

alter table Film_Actors add constraint film_Actors_fk_Film_id
  foreign key (film_id)
  references Film (id)  ;
alter table Film_Actors add constraint film_Actors_fk_Actor_id
  foreign key (actor_id)
  references Actor (id)  ;</pre>
<p><strong>Other Dia tools<br />
</strong></p>
<p>In this post I described how easy it is to generate SQL from a Dia diagram using tedia2sql. There are lots of other great third party tools to automatically generate output based on your diagram. The <a href="http://www.gnome.org/projects/dia/links.html">official Dia links page</a> lists many of them.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coderholic.com/automatic-sql-generation-using-dia/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Copy MySQL database between servers</title>
		<link>http://www.coderholic.com/copy-mysql-database-between-servers/</link>
		<comments>http://www.coderholic.com/copy-mysql-database-between-servers/#comments</comments>
		<pubDate>Thu, 01 May 2008 16:50:05 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://www.dowling.me.uk/blog/copy-mysql-database-between-servers/</guid>
		<description><![CDATA[I&#8217;ve recently needed to move some databases from one server to another. I found the simplest way to do this was to use mysqldump. The small shell script below copies a given database from a remote host to the local host. Just fill in the variables and run it to copy the whole database: #!/bin/bash [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve recently needed to move some databases from one server to another. I found the simplest way to do this was to use mysqldump. The small shell script below copies a given database from a remote host to the local host. Just fill in the variables and run it to copy the whole database:</p>
<pre>
#!/bin/bash
# Copy a remote database to a local one

REMOTE_HOST=''
REMOTE_USER=''
REMOTE_PWD=''
REMOTE_DB=''

LOCAL_USER=''
LOCAL_PWD=''
LOCAL_DB=''

mysqldump -h$REMOTE_HOST -u$REMOTE_USER -p$REMOTE_PWD --opt --compress $REMOTE_DB | mysql -u$LOCAL_USER -p$LOCAL_PWD $LOCAL_DB
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.coderholic.com/copy-mysql-database-between-servers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
