Binary files boomer-r1117/db/mt.db and boomer/db/mt.db differ
diff -rNu boomer-r1117/lib/MT/App/CMS.pm boomer/lib/MT/App/CMS.pm
--- boomer-r1117/lib/MT/App/CMS.pm	2007-12-13 00:28:56.000000000 +0900
+++ boomer/lib/MT/App/CMS.pm	2007-12-18 15:57:51.000000000 +0900
@@ -13877,7 +13877,7 @@
 
     if ( $app->config->ObjectDriver =~ qr/(db[id]::)?sqlite/i ) {
         $param{hide_build_option} = 1
-          unless $app->config->UseSQLite2;
+          unless $app->config->UseSQLite2 || $app->config->UsePDO;
     }
     my $mtview_path = File::Spec->catfile( $blog->site_path(), "mtview.php" );
 
diff -rNu boomer-r1117/lib/MT/Core.pm boomer/lib/MT/Core.pm
--- boomer-r1117/lib/MT/Core.pm	2007-12-13 00:29:01.000000000 +0900
+++ boomer/lib/MT/Core.pm	2007-12-18 22:29:32.000000000 +0900
@@ -489,6 +489,8 @@
             'UserpicAllowRect' => { default => 0 },
             'UserpicMaxUpload' => { default => 0 },
             'UserpicThumbnailSize' => { default => 100 },
+            ## Experimental
+            'UsePDO' => { default => 0, },
         },
         upgrade_functions => \&load_upgrade_fns,
         applications      => {
diff -rNu boomer-r1117/php/extlib/ezsql/ezsql_pdo.php boomer/php/extlib/ezsql/ezsql_pdo.php
--- boomer-r1117/php/extlib/ezsql/ezsql_pdo.php	1970-01-01 09:00:00.000000000 +0900
+++ boomer/php/extlib/ezsql/ezsql_pdo.php	2007-12-19 20:10:40.000000000 +0900
@@ -0,0 +1,566 @@
+<?php
+	// This is a derived work of:
+	// ==================================================================
+	//  Author: Justin Vincent (justin@visunet.ie)
+	//	Web: 	http://php.justinvincent.com
+	//	Name: 	ezSQL
+	// 	Desc: 	Class to make it very easy to deal with mySQL database connections.
+	//
+	// !! IMPORTANT !!
+	//
+	//  Please send me a mail telling me what you think of ezSQL
+	//  and what your using it for!! Cheers. [ justin@visunet.ie ]
+	//
+	// ==================================================================
+	// User Settings -- CHANGE HERE
+
+	if (!class_exists('PDO')) die('PDO class not found.');
+
+	// ==================================================================
+	//	ezSQL Constants
+	define("EZSQL_VERSION","1.26");
+	define("OBJECT", PDO::FETCH_OBJ, true);
+	define("ARRAY_A", PDO::FETCH_ASSOC, true);
+	define("ARRAY_N", PDO::FETCH_NUM, true);
+
+	// ==================================================================
+	//	The Main Class
+
+	class ezsql {
+
+		var $trace = false;      // same as $debug_all
+		var $debug_all = false;  // same as $trace
+		var $show_errors = true;
+		var $num_queries = 0;	
+		var $last_query;
+		var $col_info;
+		var $debug_called;
+		var $vardump_called;
+
+		// ==================================================================
+		//	DB Constructor - connects to the server and selects a database
+
+		function db($dsn='', $user='', $password='')
+		{
+			try
+			{
+				$this->dbh = new PDO($dsn, $user, $password);
+			}
+			catch (PDOException $e) 
+			{
+				$this->print_error("<ol><b>Error establishing a database connection!</b><li>Are you sure you have the correct user/password?<li>Are you sure that you have typed the correct hostname?<li>Are you sure that the database server is running?</ol>");
+
+			}
+
+		}
+
+		// ==================================================================
+		//	Select a DB (if another one needs to be selected)
+
+		function select($dsn='', $user='', $password='')
+		{
+			$this->db($dsn, $user, $password);
+		}
+
+		// ====================================================================
+		//	Format a string correctly for safe insert under all PHP conditions
+		
+		function escape($str)
+		{
+			return substr($this->dbh->quote($str), 1, -1);
+		}
+
+		// ==================================================================
+		//	Print SQL/DB error.
+
+		function print_error($str = "")
+		{
+			
+			// All erros go to the global error array $EZSQL_ERROR..
+			global $EZSQL_ERROR;
+
+			// If no special error string then use PDO->errorInfo() ..
+			if ( !$str )
+			{
+				$err_info = $this->dbh->errorInfo();
+				$str = $err_info[2];
+				$error_no = $err_info[1];
+			}
+			
+			// Log this error to the global array..
+			$EZSQL_ERROR[] = array 
+							(
+								"query"      => $this->last_query,
+								"error_str"  => $str,
+								"error_no"   => $error_no
+							);
+
+			// Is error output turned on or not..
+			if ( $this->show_errors )
+			{
+				// If there is an error then take note of it
+				print "<blockquote><font face=arial size=2 color=ff0000>";
+				print "<b>SQL/DB Error --</b> ";
+				print "[<font color=000077>$str</font>]";
+				print "</font></blockquote>";
+			}
+			else
+			{
+				return false;	
+			}
+		}
+
+		// ==================================================================
+		//	Turn error handling on or off..
+
+		function show_errors()
+		{
+			$this->show_errors = true;
+		}
+		
+		function hide_errors()
+		{
+			$this->show_errors = false;
+		}
+
+		// ==================================================================
+		//	Kill cached query results
+
+		function flush()
+		{
+
+			// Get rid of these
+			$this->last_result = null;
+			$this->col_info = null;
+			$this->last_query = null;
+
+		}
+
+		// ==================================================================
+		//	Basic Query	- see docs for more detail
+
+		function query($query)
+		{
+			
+			// For reg expressions
+			$query = trim($query); 
+			
+			// initialise return
+			$return_val = 0;
+
+			// Flush cached values..
+			$this->flush();
+
+			// Log how the function was called
+			$this->func_call = "\$db->query(\"$query\")";
+
+			// Keep track of the last query for debug..
+			$this->last_query = $query;
+
+			$this->num_queries++;
+			
+			// Query was an insert, delete, update, replace
+			if ( preg_match("/^(insert|delete|update|replace|drop|create)\s+/i",$query) )
+			{		
+
+				// Perform the query and log number of affected rows
+				$this->rows_affected = $this->dbh->exec($query);
+
+				// Take note of the insert_id
+				if ( preg_match("/^(insert|replace)\s+/i",$query) )
+				{
+					$this->insert_id = $this->dbh->lastInsertId();
+				}
+				
+				// Return number fo rows affected
+				$return_val = $this->rows_affected;
+			}
+			// Query was an select
+			else
+			{
+
+				// Perform the query and log number of affected rows
+				$sth = $this->dbh->query($query);
+
+				if (!$sth)
+				{
+					$this->print_error();
+					return false;
+				}
+
+				$col_count = $sth->columnCount();
+				
+				for ( $i=0 ; $i < $col_count ; $i++ )
+				{
+					if ( $meta = $sth->getColumnMeta($i) )
+					{					
+						$this->col_info[$i]->name =  $meta['name'];
+						$this->col_info[$i]->type =  $meta['native_type'];
+						$this->col_info[$i]->max_length =  '';
+					}
+					else
+					{
+						$this->col_info[$i]->name =  'undefined';
+						$this->col_info[$i]->type =  'undefined';
+						$this->col_info[$i]->max_length = '';
+					}
+				}
+				
+				// Store Query Results	
+				$this->last_result = $sth->fetchAll(PDO::FETCH_OBJ);
+
+				// Log number of rows the query returned
+				$this->num_rows = count($this->last_result);
+				
+				// Return number of rows selected
+				$return_val = $this->num_rows;
+			}
+
+			// If debug ALL queries
+			$this->trace || $this->debug_all ? $this->debug() : null ;
+
+			return $return_val;
+
+		}
+
+		// ==================================================================
+		//	Get one variable from the DB - see docs for more detail
+
+		function get_var($query=null,$x=0,$y=0)
+		{
+
+			// Log how the function was called
+			$this->func_call = "\$db->get_var(\"$query\",$x,$y)";
+
+			// If there is a query then perform it if not then use cached results..
+			if ( $query )
+			{
+				$this->query($query);
+			}
+
+			// Extract var out of cached results based x,y vals
+			if ( $this->last_result[$y] )
+			{
+				$values = array_values(get_object_vars($this->last_result[$y]));
+			}
+
+			// If there is a value return it else return null
+			return (isset($values[$x]) && $values[$x]!=='')?$values[$x]:null;
+		}
+
+		// ==================================================================
+		//	Get one row from the DB - see docs for more detail
+
+		function get_row($query=null,$output=OBJECT,$y=0)
+		{
+
+			// Log how the function was called
+			$this->func_call = "\$db->get_row(\"$query\",$output,$y)";
+
+			// If there is a query then perform it if not then use cached results..
+			if ( $query )
+			{
+				$this->query($query);
+			}
+
+			// If the output is an object then return object using the row offset..
+			if ( $output == OBJECT )
+			{
+				return $this->last_result[$y]?$this->last_result[$y]:null;
+			}
+			// If the output is an associative array then return row as such..
+			elseif ( $output == ARRAY_A )
+			{
+				return $this->last_result[$y]?get_object_vars($this->last_result[$y]):null;
+			}
+			// If the output is an numerical array then return row as such..
+			elseif ( $output == ARRAY_N )
+			{
+				return $this->last_result[$y]?array_values(get_object_vars($this->last_result[$y])):null;
+			}
+			// If invalid output type was specified..
+			else
+			{
+				$this->print_error(" \$db->get_row(string query, output type, int offset) -- Output type must be one of: OBJECT, ARRAY_A, ARRAY_N");
+			}
+
+		}
+
+		// ==================================================================
+		//	Function to get 1 column from the cached result set based in X index
+		// se docs for usage and info
+
+		function get_col($query=null,$x=0)
+		{
+
+			// If there is a query then perform it if not then use cached results..
+			if ( $query )
+			{
+				$this->query($query);
+			}
+
+			// Extract the column values
+			for ( $i=0; $i < count($this->last_result); $i++ )
+			{
+				$new_array[$i] = $this->get_var(null,$x,$i);
+			}
+
+			return $new_array;
+		}
+
+		// ==================================================================
+		// Return the the query as a result set - see docs for more details
+
+		function get_results($query=null, $output = OBJECT)
+		{
+
+			// Log how the function was called
+			$this->func_call = "\$db->get_results(\"$query\", $output)";
+
+			// If there is a query then perform it if not then use cached results..
+			if ( $query )
+			{
+				$result = $this->query_start($query);
+				if ($result) {
+				    return $this->query_fetch_all($output);
+				}
+			}
+			return null;
+		}
+
+
+		// ==================================================================
+		// Function to get column meta data info pertaining to the last query
+		// see docs for more info and usage
+
+		function get_col_info($info_type="name",$col_offset=-1)
+		{
+
+			if ( $this->col_info )
+			{
+				if ( $col_offset == -1 )
+				{
+					$i=0;
+					foreach($this->col_info as $col )
+					{
+						$new_array[$i] = $col->{$info_type};
+						$i++;
+					}
+					return $new_array;
+				}
+				else
+				{
+					return $this->col_info[$col_offset]->{$info_type};
+				}
+
+			}
+
+		}
+
+    function query_start($query)
+    {
+        // For reg expressions
+        $query = trim($query); 
+
+        // Query was an insert, delete, update, replace
+        if ( preg_match("/^(insert|delete|update|replace)\s+/i",$query) )
+        {
+            return false;
+        }
+
+        $this->savedqueries[] = $query;
+
+        // Flush cached values..
+        $this->flush();
+
+        // Log how the function was called
+        $this->func_call = "\$db->query_start(\"$query\")";
+
+        // Keep track of the last query for debug..
+        $this->last_query = $query;
+
+        // Perform the query via std mysql_query function..
+        $this->result = $this->dbh->query($query);
+        $this->num_queries++;
+
+        // If there is an error then take note of it..
+        if ( !$this->result )
+        {
+            $this->print_error();
+            return false;
+        }
+        
+        // Take note of column info
+        $col_count = $this->result->columnCount();
+
+        for ( $i=0 ; $i < $col_count ; $i++ )
+        {
+            if ( $meta = $this->result->getColumnMeta($i) )
+            {                                        
+                $this->col_info[$i]->name =  $meta['name'];
+                $this->col_info[$i]->type =  $meta['native_type'];
+                $this->col_info[$i]->max_length =  '';
+            }
+            else
+            {
+                $this->col_info[$i]->name =  'undefined';
+                $this->col_info[$i]->type =  'undefined';
+                $this->col_info[$i]->max_length = '';
+            }
+        }
+
+        $this->last_result = array();
+        $this->num_rows = 0;
+     
+        // If debug ALL queries
+        $this->trace || $this->debug_all ? $this->debug() : null ;
+
+        return true;
+    }
+
+    function query_fetch($output=OBJECT) {
+        $row = $this->result->fetch($output);
+        if ($row) {
+            $this->num_rows++;
+            return $row;
+        }
+        return null;
+    }
+
+    function query_fetch_all($output=OBJECT) {
+        $row = $this->result->fetchAll($output);
+        if ($row) {
+            return $row;
+        }
+        return null;
+    }
+
+    function query_finish() {
+        if (isset($this->result)) {
+            unset($this->result);
+        }
+    }
+
+		// ==================================================================
+		// Dumps the contents of any input variable to screen in a nicely
+		// formatted and easy to understand way - any type: Object, Var or Array
+
+		function vardump($mixed='')
+		{
+
+			echo "<p><table><tr><td bgcolor=ffffff><blockquote><font color=000090>";
+			echo "<pre><font face=arial>";
+
+			if ( ! $this->vardump_called )
+			{
+				echo "<font color=800080><b>ezSQL</b> (v".EZSQL_VERSION.") <b>Variable Dump..</b></font>\n\n";
+			}
+
+			$var_type = gettype ($mixed);
+			print_r(($mixed?$mixed:"<font color=red>No Value / False</font>"));
+			echo "\n\n<b>Type:</b> " . ucfirst($var_type) . "\n";
+			echo "<b>Last Query</b> [$this->num_queries]<b>:</b> ".($this->last_query?$this->last_query:"NULL")."\n";
+			echo "<b>Last Function Call:</b> " . ($this->func_call?$this->func_call:"None")."\n";
+			echo "<b>Last Rows Returned:</b> ".count($this->last_result)."\n";
+			echo "</font></pre></font></blockquote></td></tr></table>".$this->donation();
+			echo "\n<hr size=1 noshade color=dddddd>";
+
+			$this->vardump_called = true;
+
+		}
+
+		// Alias for the above function
+		function dumpvar($mixed)
+		{
+			$this->vardump($mixed);
+		}
+
+		// ==================================================================
+		// Displays the last query string that was sent to the database & a
+		// table listing results (if there were any).
+		// (abstracted into a seperate file to save server overhead).
+
+		function debug()
+		{
+
+			echo "<blockquote>";
+
+			// Only show ezSQL credits once..
+			if ( ! $this->debug_called )
+			{
+				echo "<font color=800080 face=arial size=2><b>ezSQL</b> (v".EZSQL_VERSION.") <b>Debug..</b></font><p>\n";
+			}
+			echo "<font face=arial size=2 color=000099><b>Query</b> [$this->num_queries] <b>--</b> ";
+			echo "[<font color=000000><b>$this->last_query</b></font>]</font><p>";
+
+				echo "<font face=arial size=2 color=000099><b>Query Result..</b></font>";
+				echo "<blockquote>";
+
+			if ( $this->col_info )
+			{
+
+				// =====================================================
+				// Results top rows
+
+				echo "<table cellpadding=5 cellspacing=1 bgcolor=555555>";
+				echo "<tr bgcolor=eeeeee><td nowrap valign=bottom><font color=555599 face=arial size=2><b>(row)</b></font></td>";
+
+
+				for ( $i=0; $i < count($this->col_info); $i++ )
+				{
+					echo "<td nowrap align=left valign=top><font size=1 color=555599 face=arial>{$this->col_info[$i]->type} {$this->col_info[$i]->max_length}</font><br><span style='font-family: arial; font-size: 10pt; font-weight: bold;'>{$this->col_info[$i]->name}</span></td>";
+				}
+
+				echo "</tr>";
+
+				// ======================================================
+				// print main results
+
+			if ( $this->last_result )
+			{
+
+				$i=0;
+				foreach ( $this->get_results(null,ARRAY_N) as $one_row )
+				{
+					$i++;
+					echo "<tr bgcolor=ffffff><td bgcolor=eeeeee nowrap align=middle><font size=2 color=555599 face=arial>$i</font></td>";
+
+					foreach ( $one_row as $item )
+					{
+						echo "<td nowrap><font face=arial size=2>$item</font></td>";
+					}
+
+					echo "</tr>";
+				}
+
+			} // if last result
+			else
+			{
+				echo "<tr bgcolor=ffffff><td colspan=".(count($this->col_info)+1)."><font face=arial size=2>No Results</font></td></tr>";
+			}
+
+			echo "</table>";
+
+			} // if col_info
+			else
+			{
+				echo "<font face=arial size=2>No Results</font>";
+			}
+
+			echo "</blockquote></blockquote>".$this->donation()."<hr noshade color=dddddd size=1>";
+
+
+			$this->debug_called = true;
+		}
+
+		// =======================================================
+		// Naughty little function to ask for some remuniration!
+
+		function donation()
+		{
+			return "<font size=1 face=arial color=000000>If ezSQL has helped <a href=\"https://www.paypal.com/xclick/business=justin%40justinvincent.com&item_name=ezSQL&no_note=1&tax=0\" style=\"color: 0000CC;\">make a donation!?</a> &nbsp;&nbsp;[ go on! you know you want to! ]</font>";	
+		}
+
+	}
+
+?>
diff -rNu boomer-r1117/php/lib/mtdb_pdo_mysql.php boomer/php/lib/mtdb_pdo_mysql.php
--- boomer-r1117/php/lib/mtdb_pdo_mysql.php	1970-01-01 09:00:00.000000000 +0900
+++ boomer/php/lib/mtdb_pdo_mysql.php	2007-12-19 19:08:09.000000000 +0900
@@ -0,0 +1,203 @@
+<?php
+# Movable Type (r) Open Source (C) 2001-2007 Six Apart, Ltd.
+# This program is distributed under the terms of the
+# GNU General Public License, version 2.
+#
+# $Id: mtdb_mysql.php 1104 2007-12-12 01:49:35Z hachi $
+
+require_once("ezsql".DIRECTORY_SEPARATOR."ezsql_pdo.php");
+require_once("mtdb_base.php");
+
+class MTDatabase_pdo_mysql extends MTDatabaseBase {
+    var $vendor = 'pdo_mysql';
+    function MTDatabase_pdo_mysql($dbuser, $dbpassword, $dbname, $dbhost, $dbport) {
+        $dsn = 'mysql:'
+            . ($dbhost ? "host=$dbhost;" : "")
+            . ($dbport ? "port=$dbport;" : "")
+            . ($dbname ? "dbname=$dbname" : "");
+        parent::MTDatabaseBase($dsn, $dbuser, $dbpassword);
+    }
+
+    function apply_limit_sql($sql, $limit, $offset = 0) {
+        $limit = intval($limit);
+        $offset = intval($offset);
+        $limitStr = '';
+        if ($limit == -1) $limit = 0;
+        if ($limit || $offset) {
+            if (!$limit) $limit = 2147483647;
+            $limitStr = 'limit ' . ($offset ? $offset . ',' : '')
+                . $limit;
+        }
+        $sql = preg_replace('/<LIMIT>/', $limitStr, $sql);
+        return $sql;
+    }
+    function limit_by_day_sql($column, $days) {
+        return 'date_add(' . $column .', interval ' . 
+            $days . ' day) >= current_date()';
+    }
+
+    function &fetch_entry_tags($args) {
+        $class = 'entry';
+        if (isset($args['class'])) {
+            $class = $args['class'];
+        } else {
+          $args['class'] = $class;
+        }
+        
+        # load tags
+        if (isset($args['entry_id'])) {
+            if (!isset($args['tags'])) {
+              if (isset($this->_entry_tag_cache[$args['entry_id']]))
+                    return $this->_entry_tag_cache[$args['entry_id']];
+            }
+            $tags =& $this->fetch_tags_by_entry($args);
+            if (!isset($args['tags']))
+                $this->_entry_tag_cache[$args['entry_id']] = $tags;
+            return $tags;
+        }
+        $blog_filter = $this->include_exclude_blogs($args);
+        if ($blog_filter == '' and isset($args['blog_id'])) {
+            if (!isset($args['tags'])) {
+                if (!isset($args['entry_id'])) {
+                    if (isset($this->_blog_tag_cache[$args['blog_id']]))
+                        return $this->_blog_tag_cache[$args['blog_id']];
+                }
+            }
+            $blog_filter = ' = '. intval($args['blog_id']);
+        }
+        if ($blog_filter != '') 
+            $blog_filter = 'and objecttag_blog_id ' . $blog_filter;
+        if (!isset($args['include_private'])) {
+            $private_filter = 'and (tag_is_private = 0 or tag_is_private is null)';
+        }
+        if (isset($args['tags']) && ($args['tags'] != '')) {
+            $tag_list = '';
+            require_once("MTUtil.php");
+            $tag_array = tag_split($args['tags']);
+            foreach ($tag_array as $tag) {
+                if ($tag_list != '') $tag_list .= ',';
+                $tag_list .= "'" . $this->escape($tag) . "'";
+            }
+            if ($tag_list != '') {
+                $tag_filter = 'and (tag_name in (' . $tag_list . '))';
+                $private_filter = '';
+            }
+        }
+        $sort_col = isset($args['sort_by']) ? $args['sort_by'] : 'name';
+        $sort_col = "tag_$sort_col";
+        if (isset($args['sort_order']) and $args['sort_order'] == 'descend') {
+            $order = 'desc';
+        } else {
+            $order = 'asc';
+        }
+        $id_order = '';
+        if ($sort_col == 'tag_name') {
+            $sort_col = 'lower(tag_name)';
+        } else {
+            $id_order = ', lower(tag_name)';
+        }
+
+
+        $sql = "
+            select tag_id, tag_name, count(distinct entry_id) as tag_count
+              from mt_tag left join mt_objecttag on objecttag_tag_id = tag_id
+                          left join mt_entry on entry_id = objecttag_object_id
+             where objecttag_object_datasource='entry'
+               and entry_status = 2
+                   and entry_class='$class'
+                   $blog_filter
+                   $tag_filter
+                   $entry_filter
+                   $private_filter
+          group by tag_id, tag_name
+          order by $sort_col $order $id_order";
+        $tags = $this->get_results($sql, ARRAY_A);
+        return $tags;
+    }
+
+    function &fetch_tags_by_entry($args) {
+        $class = 'entry';
+        if (isset($args['class'])) {
+            $class = $args['class'];
+        }
+
+        # load tags by entry_id
+        if (isset($args['entry_id'])) {
+            $entry_filter = 'and B.objecttag_object_id = '.intval($args['entry_id']);
+        }
+        if (isset($args['blog_id'])) {
+            $blog_filter = 'and A.objecttag_blog_id = '.intval($args['blog_id']);
+        }
+
+        if (!isset($args['include_private'])) {
+            $private_filter = 'and (tag_is_private = 0 or tag_is_private is null)';
+        }
+
+        if (isset($args['tags']) && ($args['tags'] != '')) {
+            $tag_list = '';
+            require_once("MTUtil.php");
+            $tag_array = tag_split($args['tags']);
+            foreach ($tag_array as $tag) {
+                if ($tag_list != '') $tag_list .= ',';
+                $tag_list .= "'" . $this->escape($tag) . "'";
+            }
+            if ($tag_list != '') {
+                $tag_filter = 'and (tag_name in (' . $tag_list . '))';
+                $private_filter = '';
+            }
+        }
+
+        $sql = "
+            select
+                A.objecttag_tag_id tag_id
+                , C.tag_name
+                , count(A.objecttag_tag_id) as tag_count
+                , B.objecttag_object_id
+                , A.objecttag_blog_id
+            from
+                mt_objecttag A
+                left join mt_objecttag B on A.objecttag_tag_id = B.objecttag_tag_id $entry_filter $blog_filter
+                left join mt_entry D on B.objecttag_object_id = D.entry_id
+                ,mt_tag C
+            where
+                D.entry_class='$class'
+                and A.objecttag_object_datasource='entry'
+                and C.tag_id=A.objecttag_tag_id
+                and entry_status = 2
+                $tag_filter
+                $private_filter
+            group by
+                A.objecttag_blog_id
+                , A.objecttag_tag_id
+                , B.objecttag_object_id
+          order by
+                C.tag_name";
+        $tags = $this->get_results($sql, ARRAY_A);
+        return $tags;
+    }
+
+    function &fetch_tag_by_name($tag_name) {
+        $tag_name = $this->escape($tag_name);
+        $tag = $this->get_row("
+            select *
+              from mt_tag
+             where tag_name = binary '$tag_name'
+        ", ARRAY_A);
+        $this->_tag_id_cache[$tag['tag_id']] = $tag;
+        return $tag;
+    }
+
+    function entries_recently_commented_on_sql($subsql) {
+      $sql = $subsql;
+        $sql = preg_replace("/from mt_entry\s+left/i",
+                    ",MAX(comment_created_on) as cco from mt_entry\ninner join mt_comment on comment_entry_id = entry_id and comment_visible = 1\nleft",
+                    $sql);
+        $sql = preg_replace("/order by(.+)/i",
+                    "group by entry_id order by cco desc, \$1 <LIMIT>",
+                   $sql);
+      return $sql;
+    }
+
+
+}
+?>
diff -rNu boomer-r1117/php/lib/mtdb_pdo_sqlite.php boomer/php/lib/mtdb_pdo_sqlite.php
--- boomer-r1117/php/lib/mtdb_pdo_sqlite.php	1970-01-01 09:00:00.000000000 +0900
+++ boomer/php/lib/mtdb_pdo_sqlite.php	2007-12-19 19:05:17.000000000 +0900
@@ -0,0 +1,71 @@
+<?php
+# Movable Type (r) Open Source (C) 2001-2007 Six Apart, Ltd.
+# This program is distributed under the terms of the
+# GNU General Public License, version 2.
+#
+# $Id$
+
+require_once("ezsql".DIRECTORY_SEPARATOR."ezsql_pdo.php");
+require_once("mtdb_base.php");
+
+class MTDatabase_pdo_sqlite extends MTDatabaseBase {
+    var $vendor = 'pdo_sqlite';
+    function MTDatabase_pdo_sqlite($dbuser, $dbpassword, $dbname, $dbhost, $dbport) {
+        $dsn = 'sqlite:' . $dbname;
+        parent::MTDatabaseBase($dsn);
+    }
+
+    // required?
+    function unserialize($data) {
+        $data = stripslashes($data);  #SQLite uses addslashes for binary data
+        return parent::unserialize($data);
+    }
+
+    // required?
+    function &convert_fieldname($array) {
+        $converted = array();
+        foreach ($array as $key => $value) {
+            list ($t,$c) = explode('.', $key);
+            $converted[$c?$c:$t] = $value;
+        }
+        return $converted;
+    }
+
+    function apply_limit_sql($sql, $limit, $offset = 0) {
+        $limit = intval($limit);
+        $offset = intval($offset);
+        $limitStr = '';
+        if ($limit == -1) $limit = 0;
+        if ($limit)
+            $limitStr = 'limit ' . $limit;
+        if ($offset) {
+            $limitStr .= ' offset ' . $offset;
+            if (!$limit)
+                $limitStr = 'limit 2147483647' . $limitStr;
+        }
+        $sql = preg_replace('/<LIMIT>/', $limitStr, $sql);
+        return $sql;
+    }
+
+    function limit_by_day_sql($column, $days) {
+        return 'datetime(' . $column . ', \'+' .
+            $days . ' days\') >= date(\'now\', \'localtime\')';
+    }
+
+    function apply_extract_date($part, $column) {
+        $lowPart = strtolower($part);
+        if ($lowPart == 'year') {
+            $part = "'%Y'";
+        } elseif ($lowPart == 'month') {
+            $part = "'%m'";
+        } elseif ($lowPart == 'day') {
+            $part = "'%d'";
+        } else {
+            return null;
+        }
+
+        return "strftime($part, $column)";
+    }
+
+}
+?>
diff -rNu boomer-r1117/php/mt.php.pre boomer/php/mt.php.pre
--- boomer-r1117/php/mt.php.pre	2007-12-13 00:28:13.000000000 +0900
+++ boomer/php/mt.php.pre	2007-12-19 16:12:43.000000000 +0900
@@ -214,6 +214,10 @@
             }
         }
 
+        if ($cfg['usepdo']) {
+            $cfg['dbdriver'] = 'pdo_' . $cfg['dbdriver'];
+        }
+
         $this->config =& $cfg;
         $this->config_defaults();
 
