Merge "Fix some issues with Microsoft SQL Server support"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 29 Apr 2014 20:15:31 +0000 (20:15 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 29 Apr 2014 20:15:31 +0000 (20:15 +0000)
includes/db/DatabaseMssql.php
includes/installer/MssqlUpdater.php
maintenance/mssql/archives/patch-user_password_expires.sql [new file with mode: 0644]
maintenance/mssql/tables.sql

index 0da47d3..1d05bf6 100644 (file)
@@ -215,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
                                        }
@@ -991,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;
@@ -1017,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;
@@ -1033,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 );
                }
@@ -1323,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;
        }
 
        /**
index 7d3833b..49e7b40 100644 (file)
@@ -37,10 +37,8 @@ class MssqlUpdater extends DatabaseUpdater {
 
        protected function getCoreUpdateList() {
                return array(
-                       array( 'disableContentHandlerUseDB' ),
-
                        // 1.23
-
+                       array( 'addField', 'mwuser', 'user_password_expires', 'patch-user_password_expires.sql' ),
                );
        }
 }
diff --git a/maintenance/mssql/archives/patch-user_password_expires.sql b/maintenance/mssql/archives/patch-user_password_expires.sql
new file mode 100644 (file)
index 0000000..c22b10c
--- /dev/null
@@ -0,0 +1 @@
+ALTER TABLE /*_*/mwuser ADD user_password_expires VARCHAR(14) DEFAULT NULL
\ No newline at end of file
index 4a3cdea..fb8db08 100644 (file)
@@ -45,8 +45,8 @@ CREATE TABLE /*_*/mwuser (
    user_email_token  NCHAR(32) DEFAULT '',
    user_email_token_expires varchar(14) DEFAULT NULL,
    user_registration varchar(14) DEFAULT NULL,
-   user_editcount    INT NULL DEFAULT NULL
-   user_password_expires DATETIME DEFAULT NULL
+   user_editcount    INT NULL DEFAULT NULL,
+   user_password_expires varchar(14) DEFAULT NULL
 );
 CREATE UNIQUE INDEX /*i*/user_name ON /*_*/mwuser (user_name);
 CREATE INDEX /*i*/user_email_token ON /*_*/mwuser (user_email_token);