Fix some issues with Microsoft SQL Server support
[lhc/web/wiklou.git] / includes / db / DatabaseMssql.php
index e304a34..1d05bf6 100644 (file)
@@ -164,8 +164,7 @@ class DatabaseMssql extends DatabaseBase {
         * @throws DBUnexpectedError
         */
        protected function doQuery( $sql ) {
-               global $wgDebugDumpSql;
-               if ( $wgDebugDumpSql ) {
+               if ( $this->debug() ) {
                        wfDebug( "SQL: [$sql]\n" );
                }
                $this->offset = 0;
@@ -216,7 +215,9 @@ class DatabaseMssql extends DatabaseBase {
 
                                foreach ( $errors as $err ) {
                                        if ( $err['SQLSTATE'] == '23000' && $err['code'] == '2601' ) {
-                                               continue; // duplicate key error
+                                               continue; // duplicate key error caused by unique index
+                                       } elseif ( $err['SQLSTATE'] == '23000' && $err['code'] == '2627' ) {
+                                               continue; // duplicate key error caused by primary key
                                        } elseif ( $err['SQLSTATE'] == '01000' && $err['code'] == '3621' ) {
                                                continue; // generic "the statement has been terminated" error
                                        }
@@ -471,7 +472,7 @@ class DatabaseMssql extends DatabaseBase {
                $this->mScrollableCursor = false;
                try {
                        parent::deleteJoin( $delTable, $joinTable, $delVar, $joinVar, $conds, $fname );
-               } catch( Exception $e ) {
+               } catch ( Exception $e ) {
                        $this->mScrollableCursor = true;
                        throw $e;
                }
@@ -482,7 +483,7 @@ class DatabaseMssql extends DatabaseBase {
                $this->mScrollableCursor = false;
                try {
                        parent::delete( $table, $conds, $fname );
-               } catch( Exception $e ) {
+               } catch ( Exception $e ) {
                        $this->mScrollableCursor = true;
                        throw $e;
                }
@@ -730,7 +731,7 @@ class DatabaseMssql extends DatabaseBase {
                                $insertOptions,
                                $selectOptions
                        );
-               } catch( Exception $e ) {
+               } catch ( Exception $e ) {
                        $this->mScrollableCursor = true;
                        throw $e;
                }
@@ -911,7 +912,7 @@ class DatabaseMssql extends DatabaseBase {
                        $first = $offset + 1;
                        $last = $offset + $limit;
                        $sub1 = 'sub_' . $this->mSubqueryId;
-                       $sub2 = 'sub_' . ($this->mSubqueryId + 1);
+                       $sub2 = 'sub_' . ( $this->mSubqueryId + 1 );
                        $this->mSubqueryId += 2;
                        if ( !$s1 ) {
                                // wat
@@ -992,18 +993,22 @@ class DatabaseMssql extends DatabaseBase {
        /**
         * @param string $table
         * @param string $fname
-        * @param bool $schema
         * @return bool
         */
-       public function tableExists( $table, $fname = __METHOD__, $schema = false ) {
-               $res = sqlsrv_query( $this->mConn, "SELECT * FROM information_schema.tables
-                       WHERE table_type='BASE TABLE' AND table_name = '$table'" );
-               if ( $res === false ) {
-                       print "Error in tableExists query: " . $this->lastError();
+       public function tableExists( $table, $fname = __METHOD__ ) {
+               list( $db, $schema, $table ) = $this->tableName( $table, 'split' );
 
+               if ( $db !== false ) {
+                       // remote database
+                       wfDebug( "Attempting to call tableExists on a remote table" );
                        return false;
                }
-               if ( sqlsrv_fetch( $res ) ) {
+
+               $res = $this->query( "SELECT 1 FROM INFORMATION_SCHEMA.TABLES
+                       WHERE TABLE_TYPE = 'BASE TABLE'
+                       AND TABLE_SCHEMA = '$schema' AND TABLE_NAME = '$table'" );
+
+               if ( $res->numRows() ) {
                        return true;
                } else {
                        return false;
@@ -1018,15 +1023,18 @@ class DatabaseMssql extends DatabaseBase {
         * @return bool
         */
        public function fieldExists( $table, $field, $fname = __METHOD__ ) {
-               $table = $this->tableName( $table );
-               $res = sqlsrv_query( $this->mConn, "SELECT DATA_TYPE FROM INFORMATION_SCHEMA.Columns
-                       WHERE TABLE_NAME = '$table' AND COLUMN_NAME = '$field'" );
-               if ( $res === false ) {
-                       print "Error in fieldExists query: " . $this->lastError();
+               list( $db, $schema, $table ) = $this->tableName( $table, 'split' );
 
+               if ( $db !== false ) {
+                       // remote database
+                       wfDebug( "Attempting to call fieldExists on a remote table" );
                        return false;
                }
-               if ( sqlsrv_fetch( $res ) ) {
+
+               $res = $this->query( "SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS
+                       WHERE TABLE_SCHEMA = '$schema' AND TABLE_NAME = '$table' AND COLUMN_NAME = '$field'" );
+
+               if ( $res->numRows() ) {
                        return true;
                } else {
                        return false;
@@ -1034,15 +1042,18 @@ class DatabaseMssql extends DatabaseBase {
        }
 
        public function fieldInfo( $table, $field ) {
-               $table = $this->tableName( $table );
-               $res = sqlsrv_query( $this->mConn, "SELECT * FROM INFORMATION_SCHEMA.Columns
-                       WHERE TABLE_NAME = '$table' AND COLUMN_NAME = '$field'" );
-               if ( $res === false ) {
-                       print "Error in fieldInfo query: " . $this->lastError();
+               list( $db, $schema, $table ) = $this->tableName( $table, 'split' );
 
+               if ( $db !== false ) {
+                       // remote database
+                       wfDebug( "Attempting to call fieldInfo on a remote table" );
                        return false;
                }
-               $meta = $this->fetchRow( $res );
+
+               $res = $this->query( "SELECT * FROM INFORMATION_SCHEMA.COLUMNS
+                       WHERE TABLE_SCHEMA = '$schema' AND TABLE_NAME = '$table' AND COLUMN_NAME = '$field'" );
+
+               $meta = $res->fetchRow();
                if ( $meta ) {
                        return new MssqlField( $meta );
                }
@@ -1223,7 +1234,7 @@ class DatabaseMssql extends DatabaseBase {
         * @param string $field Field name
         * @param string|array $conds Conditions
         * @param string|array $join_conds Join conditions
-        * @return String SQL text
+        * @return string SQL text
         * @since 1.23
         */
        public function buildGroupConcatField( $delim, $table, $field, $conds = '',
@@ -1324,11 +1335,20 @@ class DatabaseMssql extends DatabaseBase {
        /**
         * call this instead of tableName() in the updater when renaming tables
         * @param string $name
-        * @param string $format
+        * @param string $format One of quoted, raw, or split
         * @return string
         */
        function realTableName( $name, $format = 'quoted' ) {
-               return parent::tableName( $name, $format );
+               $table = parent::tableName( $name, $format );
+               if ( $format == 'split' ) {
+                       // Used internally, we want the schema split off from the table name and returned
+                       // as a list with 3 elements (database, schema, table)
+                       $table = explode( '.', $table );
+                       if ( count( $table ) == 2 ) {
+                               array_unshift( $table, false );
+                       }
+               }
+               return $table;
        }
 
        /**