Index: trac/db_default.py
===================================================================
--- trac/db_default.py	(revision 2625)
+++ trac/db_default.py	(working copy)
@@ -94,7 +94,7 @@
 
     # Ticket system
     Table('ticket', key='id')[
-        Column('id', auto_increment=True),
+        Column('id', type='int', auto_increment=True),
         Column('type'),
         Column('time', type='int'),
         Column('changetime', type='int'),
@@ -145,7 +145,7 @@
 
     # Report system
     Table('report', key='id')[
-        Column('id', auto_increment=True),
+        Column('id', type='int', auto_increment=True),
         Column('author'),
         Column('title'),
         Column('sql'),
@@ -437,6 +437,7 @@
 )
 
 default_components = ('trac.About', 'trac.attachment',
+                      'trac.db.mysql_backend',
                       'trac.db.postgres_backend', 'trac.db.sqlite_backend',
                       'trac.mimeview.enscript', 'trac.mimeview.patch',
                       'trac.mimeview.php', 'trac.mimeview.rst',
Index: trac/ticket/api.py
===================================================================
--- trac/ticket/api.py	(revision 2625)
+++ trac/ticket/api.py	(working copy)
@@ -167,13 +167,19 @@
             return
         db = self.env.get_db_cnx()
         sql, args = query_to_sql(db, query, 'b.newvalue')
-        sql2, args2 = query_to_sql(db, query, 'summary||keywords||description||reporter||cc')
+        search_fields = ['summary', 'keywords', 'description', 'reporter', 'cc']
+        sql_seq = []
+        for f in search_fields:
+            subsql, subarg = query_to_sql(db, query, f)
+            sql_seq.append(subsql)
+            args += subarg
+        sql2 = ' OR '.join(sql_seq)
         cursor = db.cursor()
-        cursor.execute("SELECT DISTINCT a.summary,a.description,a.reporter, "
-                       "a.keywords,a.id,a.time FROM ticket a "
-                       "LEFT JOIN ticket_change b ON a.id = b.ticket "
-                       "WHERE (b.field='comment' AND %s ) OR %s" % (sql, sql2),
-                       args + args2)
+        sql3 = "SELECT DISTINCT a.summary,a.description,a.reporter, " + \
+                       "a.keywords,a.id,a.time FROM ticket a " +  \
+                       "LEFT JOIN ticket_change b ON a.id = b.ticket " + \
+                       "WHERE (b.field='comment' AND %s ) OR %s" % (sql, sql2)
+        cursor.execute(sql3, args)
         for summary,desc,author,keywords,tid,date in cursor:
             yield (self.env.href.ticket(tid),
                    '#%d: %s' % (tid, util.escape(util.shorten_line(summary))),
Index: trac/db/mysql_backend.py
===================================================================
--- trac/db/mysql_backend.py	(revision 0)
+++ trac/db/mysql_backend.py	(revision 0)
@@ -0,0 +1,127 @@
+# -*- coding: iso8859-1 -*-
+#
+# Copyright (C) 2005 Edgewall Software
+# Copyright (C) 2005 Jeff Weiss <trac@jeffweiss.org>
+# All rights reserved.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at http://trac.edgewall.com/license.html.
+#
+# This software consists of voluntary contributions made by many
+# individuals. For the exact contribution history, see the revision
+# history and logs, available at http://projects.edgewall.com/trac/.
+#
+# Author: Jeff Weiss <trac@jeffweiss.org>
+
+from trac.core import *
+from trac.db.api import IDatabaseConnector
+from trac.db.util import ConnectionWrapper
+
+import MySQLdb
+
+class MySQLConnector(Component):
+    """MySQL database support.  Still extremely experimental!
+Currently only supports database urls of the following formats:
+mysql://user:password@host/database
+mysql://user:password@host:port/database
+"""
+
+    implements(IDatabaseConnector)
+
+    def get_supported_schemes(self):
+        return [('mysql', 1)]
+
+    def get_connection(self, path, user=None, password=None, host=None,
+                       port=None, params={}):
+        return MySQLConnection(path, user, password, host, port, params)
+
+    def init_db(self, path, user=None, password=None, host=None, port=None,
+                params={}):
+        cnx = self.get_connection(path, user, password, host, port, params)
+        cursor = cnx.cursor()
+        from trac.db_default import schema
+        for table in schema:
+            for stmt in self.to_sql(table):
+                cursor.execute(stmt)
+        cnx.commit()
+
+    def to_sql(self, table):
+        sql = ["CREATE TABLE %s (" % table.name]
+        coldefs = []
+        textkeys = []
+        textcols = []
+        mytablekey = []
+        num_key_text = 0
+        for column in table.columns:
+            ctype = column.type
+            if column.auto_increment:
+                ctype += " AUTO_INCREMENT"
+            if column.name in table.key:
+                mytablekey.append(column.name)
+                if column.type == 'text':
+                    num_key_text += 1
+                    textkeys.append(column.name)
+            if column.type == 'text':
+                textcols.append(column.name)
+            coldefs.append("    `%s` %s" % (column.name, ctype))
+        if len(table.key) >= 1:
+            if num_key_text == 0:
+                num_key_text = 1
+            size = 767 / num_key_text
+            keysize = "(%s)" % size
+            for key in textkeys:
+                if key in mytablekey:
+                    mytablekey.remove(key)
+                sizedkey = '`' + key + '`' + keysize
+                mytablekey.append(sizedkey)
+            coldefs.append("    CONSTRAINT %s_pk PRIMARY KEY (%s)"
+                           % (table.name, ','.join(mytablekey)))
+        sql.append(',\n'.join(coldefs) + '\n)')
+        yield '\n'.join(sql)
+# This does not work because what I need to do is not add something about
+# the index size for the text fields because MySQL apparrently can't index
+# on the entire length of the text field
+        for index in table.indices:
+            myidxcols = set([])
+            processedidx = set([])
+            for col in index.columns:
+                if col in textcols:
+                    myidxcols.add(col)
+            myidx = set(index.columns) - myidxcols
+            for col in myidx:
+               escaped_col = '`'+col+'`'
+               processedidx.add(escaped_col) 
+            if len(myidxcols) > 0:
+                size = 767 / len(myidxcols)
+                idxsize  = "(%s)" % size
+                for col in myidxcols:
+                   sizedidx = '`'+col+'`'+idxsize
+                   processedidx.add(sizedidx) 
+            yield "CREATE INDEX %s_%s_idx ON %s (%s)" % (table.name, 
+                   '_'.join(index.columns), table.name, ','.join(processedidx))
+
+
+class MySQLConnection(ConnectionWrapper):
+    """Connection wrapper for MySQL."""
+
+    poolable = True
+
+    def __init__(self, path, usr=None, password=None, hst=None, prt=None,
+                 params={}):
+        cnx = MySQLdb.connect(db=path[1:], user=usr, passwd=password, host=hst, port=prt)
+        ConnectionWrapper.__init__(self, cnx)
+
+    def cast(self, column, type):
+        # Temporary hack needed for the union of selects in the search module
+        return 'CAST(%s AS %s)' % (column, type)
+
+    def like(self):
+        # Temporary hack needed for the case-insensitive string matching in the
+        # search module
+        return 'LIKE'
+
+    def get_last_id(self, cursor, table, column='id'):
+        sql = "SELECT MAX(`%s`) FROM %s" % (column, table)
+        cursor.execute(sql)
+        return cursor.fetchone()[0]
Index: trac/versioncontrol/web_ui/changeset.py
===================================================================
--- trac/versioncontrol/web_ui/changeset.py	(revision 2625)
+++ trac/versioncontrol/web_ui/changeset.py	(working copy)
@@ -384,7 +384,14 @@
             return
         authzperm = SubversionAuthorizer(self.env, req.authname)
         db = self.env.get_db_cnx()
-        sql, args = query_to_sql(db, query, 'message||author')
+        query_fields = ['message', 'author']
+        sql_seq = []
+        args = []
+        for f in query_fields:
+            subsql, subarg = query_to_sql(db, query, f)
+            sql_seq.append(subsql) 
+            args += subarg
+        sql = ' OR '.join(sql_seq)
         cursor = db.cursor()
         cursor.execute("SELECT rev,time,author,message "
                        "FROM revision WHERE " + sql, args)
Index: trac/versioncontrol/cache.py
===================================================================
--- trac/versioncontrol/cache.py	(revision 2625)
+++ trac/versioncontrol/cache.py	(working copy)
@@ -85,7 +85,7 @@
                     kind = kindmap[kind]
                     action = actionmap[action]
                     cursor.execute("INSERT INTO node_change (rev,path,kind,"
-                                   "change,base_path,base_rev) "
+                                   "`change`,base_path,base_rev) "
                                    "VALUES (%s,%s,%s,%s,%s,%s)",
                                    (str(current_rev), path, kind, action,
                                    base_path, base_rev))
Index: trac/web/session.py
===================================================================
--- trac/web/session.py	(revision 2625)
+++ trac/web/session.py	(working copy)
@@ -181,9 +181,19 @@
             # changed as to minimize the purging.
             mintime = now - PURGE_AGE
             self.env.log.debug('Purging old, expired, sessions.')
-            cursor.execute("DELETE FROM session WHERE authenticated=0 AND "
-                           "sid IN (SELECT sid FROM session WHERE "
-                           "var_name='last_visit' AND var_value < %s)",
+            # This is a temporary hack because MySQL doesn't support
+            # a delete statement with the subquery coming from the same
+            # table
+            cursor.execute("SELECT sid from session WHERE "
+                           "var_name='last_visit' AND var_value < %s",
                            (mintime,))
-
+            sids = cursor.fetchall() 
+            if len(sids) >= 1:
+                vals = []
+                sids_args = []
+                for t in sids:
+                    vals.append(t[0])
+                    sids_args.append("sid = %s")
+                sql = "DELETE FROM session WHERE authenticated = 0 AND (%s)" % ' OR '.join(sids_args)
+                cursor.execute(sql, vals)
             db.commit()
