more cssification of diff rendering, some " -> ' in diff engine
[lhc/web/wiklou.git] / includes / Database.php
index 84f2c46..60647d5 100644 (file)
@@ -1,6 +1,9 @@
 <?php
-include_once( "FulltextStoplist.php" );
-include_once( "CacheManager.php" );
+# $Id$
+# This file deals with MySQL interface functions 
+# and query specifics/optimisations
+#
+require_once( "CacheManager.php" );
 
 define( "DB_READ", -1 );
 define( "DB_WRITE", -2 );
@@ -8,6 +11,7 @@ define( "DB_LAST", -3 );
 
 define( "LIST_COMMA", 0 );
 define( "LIST_AND", 1 );
+define( "LIST_SET", 2 );
 
 class Database {
 
@@ -63,7 +67,11 @@ class Database {
        function Database()
        {
                global $wgOut;
-               $this->mOut = $wgOut;
+               # Can't get a reference if it hasn't been set yet
+               if ( !isset( $wgOut ) ) {
+                       $wgOut = NULL;
+               }
+               $this->mOut =& $wgOut;
        
        }
        
@@ -74,6 +82,7 @@ class Database {
                $db->mFailFunction = $failFunction;
                $db->mIgnoreErrors = $ignoreErrors;
                $db->mDebug = $debug;
+               $db->mBufferResults = $bufferResults;
                $db->open( $server, $user, $password, $dbName );
                return $db;
        }
@@ -100,14 +109,14 @@ class Database {
                                        wfDebug( "Error selecting database \"$dbName\": " . $this->lastError() . "\n" );
                                }
                        } else {
-                               wfDebug( "DB connect error: " . $this->lastError() . "\n" );
+                               wfDebug( "DB connection error\n" );
                                wfDebug( "Server: $server, User: $user, Password: " . 
                                        substr( $password, 0, 3 ) . "...\n" );
                                $success = false;
                        }
                } else {
-                       # Delay USE
-                       $success = true;
+                       # Delay USE query
+                       $success = !!$this->mConn;
                }
                
                if ( !$success ) {
@@ -168,13 +177,15 @@ class Database {
                }
        
                if ( false === $ret ) {
+                       $error = mysql_error( $this->mConn );
+                       $errno = mysql_errno( $this->mConn );
                        if( $this->mIgnoreErrors ) {
-                               wfDebug("SQL ERROR (ignored): " . mysql_error( $this->mConn ) . "\n");
+                               wfDebug("SQL ERROR (ignored): " . $error . "\n");
                        } else {
-                               wfDebug("SQL ERROR: " . mysql_error( $this->mConn ) . "\n");
+                               wfDebug("SQL ERROR: " . $error . "\n");
                                if ( $this->mOut ) {
                                        // this calls wfAbruptExit()
-                                       $this->mOut->databaseError( $fname, $this );                            
+                                       $this->mOut->databaseError( $fname, $sql, $error, $errno );                             
                                }
                        }
                }
@@ -185,15 +196,41 @@ class Database {
                return $ret;
        }
        
-       function freeResult( $res ) { mysql_free_result( $res ); }
-       function fetchObject( $res ) { return mysql_fetch_object( $res ); }
-       function numRows( $res ) { return mysql_num_rows( $res ); }
+       function freeResult( $res ) {
+               if ( !@mysql_free_result( $res ) ) {
+                       wfDebugDieBacktrace( "Unable to free MySQL result\n" );
+               }
+       }
+       function fetchObject( $res ) {
+               @$row = mysql_fetch_object( $res );
+               # FIXME: HACK HACK HACK HACK debug
+               if( mysql_errno() ) {
+                       wfDebugDieBacktrace( "SQL error: " . htmlspecialchars( mysql_error() ) );
+               }
+               return $row;
+       }
+       
+       function fetchRow( $res ) {
+               @$row = mysql_fetch_array( $res );
+               if (mysql_errno() ) {
+                       wfDebugDieBacktrace( "SQL error: " . htmlspecialchars( mysql_error() ) );
+               }
+               return $row;
+       }       
+
+       function numRows( $res ) {
+               @$n = mysql_num_rows( $res ); 
+               if( mysql_errno() ) {
+                       wfDebugDieBacktrace( "SQL error: " . htmlspecialchars( mysql_error() ) );
+               }
+               return $n;
+       }
        function numFields( $res ) { return mysql_num_fields( $res ); }
        function fieldName( $res, $n ) { return mysql_field_name( $res, $n ); }
        function insertId() { return mysql_insert_id( $this->mConn ); }
        function dataSeek( $res, $row ) { return mysql_data_seek( $res, $row ); }
-       function lastErrno() { return mysql_errno( $this->mConn ); }
-       function lastError() { return mysql_error(  $this->mConn ); }
+       function lastErrno() { return mysql_errno(); }
+       function lastError() { return mysql_error(); }
        function affectedRows() { return mysql_affected_rows( $this->mConn ); }
        
        # Simple UPDATE wrapper
@@ -206,7 +243,7 @@ class Database {
                return !!$this->query( $sql, DB_WRITE, $fname );
        }
        
-       # Simple SELECT wrapper
+       # Simple SELECT wrapper, returns a single field, input must be encoded
        # Usually aborts on failure
        # If errors are explicitly ignored, returns FALSE on failure
        function get( $table, $var, $cond, $fname = "Database::get" )
@@ -232,12 +269,14 @@ class Database {
        {
                $vars = implode( ",", $vars );
                $where = Database::makeList( $conds, LIST_AND );
-               $sql = "SELECT $vars FROM $table WHERE $where";
+               $sql = "SELECT $vars FROM $table WHERE $where LIMIT 1";
                $res = $this->query( $sql, $fname );
                if ( $res === false || !$this->numRows( $res ) ) {
                        return false;
                }
-               return $this->fetchObject( $res );
+               $obj = $this->fetchObject( $res );
+               $this->freeResult( $res );
+               return $obj;
        }
        
        # Removes most variables from an SQL query and replaces them with X or N for numbers.
@@ -289,7 +328,10 @@ class Database {
        # If errors are explicitly ignored, returns NULL on failure
        function indexExists( $table, $index, $fname = "Database::indexExists" ) 
        {
-               $sql = "SHOW INDEXES FROM $table";
+               # SHOW INDEX works in MySQL 3.23.58, but SHOW INDEXES does not.
+               # SHOW INDEX should work for 3.x and up:
+               # http://dev.mysql.com/doc/mysql/en/SHOW_INDEX.html
+               $sql = "SHOW INDEX FROM $table";
                $res = $this->query( $sql, DB_READ, $fname );
                if ( !$res ) {
                        return NULL;
@@ -308,15 +350,16 @@ class Database {
        
        function tableExists( $table )
        {
-               $res = mysql_list_tables( $this->mDBname );
-               if( !$res ) {
-                       echo "** " . $this->lastError() . "\n";
+               $old = $this->mIgnoreErrors;
+               $this->mIgnoreErrors = true;
+               $res = $this->query( "SELECT 1 FROM $table LIMIT 1" );
+               $this->mIgnoreErrors = $old;
+               if( $res ) {
+                       $this->freeResult( $res );
+                       return true;
+               } else {
                        return false;
                }
-               for( $i = $this->numRows( $res ) - 1; $i--; $i > 0 ) {
-                       if( mysql_tablename( $res, $i ) == $table ) return true;
-               }
-               return false;
        }
 
        function fieldInfo( $table, $field )
@@ -352,10 +395,19 @@ class Database {
                return !!$this->query( $sql, $fname );
        }
        
+       # A cross between insertArray and getArray, takes a condition array and a SET array
+       function updateArray( $table, $values, $conds, $fname = "Database::updateArray" )
+       {
+               $sql = "UPDATE $table SET " . $this->makeList( $values, LIST_SET );
+               $sql .= " WHERE " . $this->makeList( $conds, LIST_AND );
+               $this->query( $sql, $fname );
+       }
+       
        # Makes a wfStrencoded list from an array
-       # $mode: LIST_COMMA - comma separated
+       # $mode: LIST_COMMA - comma separated, no field names
        #        LIST_AND   - ANDed WHERE clause (without the WHERE)
-       /* static */ function makeList( $a, $mode = LIST_COMMA)
+       #        LIST_SET   - comma separated with field names, like a SET clause
+       /* static */ function makeList( $a, $mode = LIST_COMMA )
        {
                $first = true;
                $list = "";
@@ -369,10 +421,10 @@ class Database {
                        } else {
                                $first = false;
                        }
-                       if ( $mode == LIST_AND ) {
+                       if ( $mode == LIST_AND || $mode == LIST_SET ) {
                                $list .= "$field=";
                        }
-                       if ( is_string( $value ) ) {
+                       if ( !is_numeric( $value ) ) {
                                $list .= "'" . wfStrencode( $value ) . "'";
                        } else {
                                $list .= $value;
@@ -383,7 +435,7 @@ class Database {
        
        function selectDB( $db ) 
        {
-               $this->mDatabase = $db;
+               $this->mDBname = $db;
                mysql_select_db( $db, $this->mConn );
        }
 
@@ -421,7 +473,7 @@ function wfEmergencyAbort( &$conn ) {
                } else {
                        if($title) {
                                $t = Title::newFromURL( $title );
-                       } elseif ($_REQUEST['search']) {
+                       } elseif (@$_REQUEST['search']) {
                                $search = $_REQUEST['search'];
                                echo wfMsgNoDB( "searchdisabled" );
                                echo wfMsgNoDB( "googlesearch", htmlspecialchars( $search ), $wgInputEncoding );
@@ -433,7 +485,7 @@ function wfEmergencyAbort( &$conn ) {
 
                $cache = new CacheManager( $t );
                if( $cache->isFileCached() ) {
-                       $msg = "<p style='color: red'><b>$msg<br>\n" .
+                       $msg = "<p style='color: red'><b>$msg<br />\n" .
                                wfMsgNoDB( "cachederror" ) . "</b></p>\n";
                        
                        $tag = "<div id='article'>";
@@ -481,4 +533,9 @@ function wfInvertTimestamp( $ts ) {
                "9876543210"
        );
 }
+
+function wfLimitResult( $limit, $offset ) {
+       return " LIMIT ".(is_numeric($offset)?"{$offset},":"")."{$limit} ";
+}
+
 ?>