Remove current MSSQL implementation from trunk. See wikitech-l for discussion.
authorChad Horohoe <demon@users.mediawiki.org>
Wed, 21 Apr 2010 16:29:29 +0000 (16:29 +0000)
committerChad Horohoe <demon@users.mediawiki.org>
Wed, 21 Apr 2010 16:29:29 +0000 (16:29 +0000)
config/Installer.php
includes/AutoLoader.php
includes/db/DatabaseMssql.php [deleted file]
maintenance/mssql/README [deleted file]
maintenance/mssql/tables.sql [deleted file]

index fb76ef9..45d6d6e 100644 (file)
@@ -83,15 +83,6 @@ $ourdb['sqlite'] = array(
        'serverless' =>  true
 );
 
-$ourdb['mssql'] = array(
-       'fullname'   => 'MSSQL',
-       'havedriver' => 0,
-       'compile'    => 'mssql_not_ready', # Change to 'mssql' after includes/DatabaseMssql.php added;
-       'bgcolor'    => '#ffc0cb',
-       'rootuser'   => 'administrator',
-       'serverless' => false
-);
-
 $ourdb['ibm_db2'] = array(
        'fullname'   => 'DB2',
        'havedriver' => 0,
@@ -639,10 +630,6 @@ print "<li style='font-weight:bold;color:green;font-size:110%'>Environment check
        ## SQLite specific
        $conf->SQLiteDataDir = importPost( "SQLiteDataDir", "$IP/../data" );
 
-       ## MSSQL specific
-       // We need a second field so it doesn't overwrite the MySQL one
-       $conf->DBprefix2 = importPost( "DBprefix2" );
-
        ## DB2 specific:
        // New variable in order to have a different default port number
        $conf->DBport_db2   = importPost( "DBport_db2",      "50000" );
@@ -831,10 +818,7 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
                        $wgDBmwschema = $conf->DBdb2schema;
                }
 
-               if( $conf->DBprefix2 != '' ) {
-                       // For MSSQL
-                       $wgDBprefix = $conf->DBprefix2;
-               } elseif( $conf->DBprefix_ora != '' ) {
+               if( $conf->DBprefix_ora != '' ) {
                        // For Oracle
                        $wgDBprefix = $conf->DBprefix_ora;
                }
@@ -1659,19 +1643,6 @@ if( count( $errs ) ) {
        </div>
        </fieldset>
 
-       <?php database_switcher('mssql'); ?>
-       <div class="config-input"><?php
-               aField( $conf, "DBprefix2", "Database table prefix:" );
-       ?></div>
-       <div class="config-desc">
-               <p>If you need to share one database between multiple wikis, or
-               between MediaWiki and another web application, you may choose to
-               add a prefix to all the table names to avoid conflicts.</p>
-
-               <p>Avoid exotic characters; something like <tt>mw_</tt> is good.</p>
-       </div>
-       </fieldset>
-
        <?php database_switcher('ibm_db2'); ?>
        <div class="config-input"><?php
                aField( $conf, "DBport_db2", "Database port:" );
@@ -1873,10 +1844,6 @@ function writeLocalSettings( $conf ) {
                $dbsettings =
 "# SQLite-specific settings
 \$wgSQLiteDataDir    = \"{$sqliteDataDir}\";";
-       } elseif( $conf->DBtype == 'mssql' ) {
-               $dbsettings =
-"# MSSQL specific settings
-\$wgDBprefix         = \"{$slconf['DBprefix2']}\";";
        } elseif( $conf->DBtype == 'ibm_db2' ) {
                $dbsettings =
 "# DB2 specific settings
index d547e58..a217807 100644 (file)
@@ -353,7 +353,6 @@ $wgAutoloadLocalClasses = array(
        'ChronologyProtector' => 'includes/db/LBFactory.php',
        'Database' => 'includes/db/DatabaseMysql.php',
        'DatabaseBase' => 'includes/db/Database.php',
-       'DatabaseMssql' => 'includes/db/DatabaseMssql.php',
        'DatabaseMysql' => 'includes/db/DatabaseMysql.php',
        'DatabaseOracle' => 'includes/db/DatabaseOracle.php',
        'DatabasePostgres' => 'includes/db/DatabasePostgres.php',
@@ -372,7 +371,6 @@ $wgAutoloadLocalClasses = array(
        'LoadBalancer' => 'includes/db/LoadBalancer.php',
        'LoadMonitor' => 'includes/db/LoadMonitor.php',
        'LoadMonitor_MySQL' => 'includes/db/LoadMonitor.php',
-       'MSSQLField' => 'includes/db/DatabaseMssql.php',
        'MySQLField' => 'includes/db/Database.php',
        'MySQLMasterPos' => 'includes/db/DatabaseMysql.php',
        'ORABlob' => 'includes/db/DatabaseOracle.php',
diff --git a/includes/db/DatabaseMssql.php b/includes/db/DatabaseMssql.php
deleted file mode 100644 (file)
index 73861db..0000000
+++ /dev/null
@@ -1,968 +0,0 @@
-<?php
-/**
- * This script is the MSSQL Server database abstraction layer
- *
- * See maintenance/mssql/README for development notes and other specific information
- * @ingroup Database
- * @file
- */
-
-/**
- * @ingroup Database
- */
-class DatabaseMssql extends DatabaseBase {
-
-       var $mAffectedRows;
-       var $mLastResult;
-       var $mLastError;
-       var $mLastErrorNo;
-       var $mDatabaseFile;
-
-       /**
-        * Constructor
-        */
-       function __construct($server = false, $user = false, $password = false, $dbName = false,
-                       $failFunction = false, $flags = 0, $tablePrefix = 'get from global') {
-
-               global $wgOut, $wgDBprefix, $wgCommandLineMode;
-               if (!isset($wgOut)) $wgOut = null; # Can't get a reference if it hasn't been set yet
-               $this->mOut =& $wgOut;
-               $this->mFailFunction = $failFunction;
-               $this->mFlags = $flags;
-
-               if ( $this->mFlags & DBO_DEFAULT ) {
-                       if ( $wgCommandLineMode ) {
-                               $this->mFlags &= ~DBO_TRX;
-                       } else {
-                               $this->mFlags |= DBO_TRX;
-                       }
-               }
-
-               /** Get the default table prefix*/
-               $this->mTablePrefix = $tablePrefix == 'get from global' ? $wgDBprefix : $tablePrefix;
-
-               if ($server) $this->open($server, $user, $password, $dbName);
-
-       }
-
-       function getType() {
-               return 'mssql';
-       }
-
-       /**
-        * todo: check if these should be true like parent class
-        */
-       function implicitGroupby()   { return false; }
-       function implicitOrderby()   { return false; }
-
-       static function newFromParams($server, $user, $password, $dbName, $failFunction = false, $flags = 0) {
-               return new DatabaseMssql($server, $user, $password, $dbName, $failFunction, $flags);
-       }
-
-       /** Open an MSSQL database and return a resource handle to it
-        *  NOTE: only $dbName is used, the other parameters are irrelevant for MSSQL databases
-        */
-       function open($server,$user,$password,$dbName) {
-               wfProfileIn(__METHOD__);
-
-               # Test for missing mysql.so
-               # First try to load it
-               if (!@extension_loaded('mssql')) {
-                       @dl('mssql.so');
-               }
-
-               # Fail now
-               # Otherwise we get a suppressed fatal error, which is very hard to track down
-               if (!function_exists( 'mssql_connect')) {
-                       throw new DBConnectionError( $this, "MSSQL functions missing, have you compiled PHP with the --with-mssql option?\n" );
-               }
-
-               $this->close();
-               $this->mServer   = $server;
-               $this->mUser     = $user;
-               $this->mPassword = $password;
-               $this->mDBname   = $dbName;
-
-               wfProfileIn("dbconnect-$server");
-
-               # Try to connect up to three times
-               # The kernel's default SYN retransmission period is far too slow for us,
-               # so we use a short timeout plus a manual retry.
-               $this->mConn = false;
-               $max = 3;
-               for ( $i = 0; $i < $max && !$this->mConn; $i++ ) {
-                       if ( $i > 1 ) {
-                               usleep( 1000 );
-                       }
-                       if ($this->mFlags & DBO_PERSISTENT) {
-                               @/**/$this->mConn = mssql_pconnect($server, $user, $password);
-                       } else {
-                               # Create a new connection...
-                               @/**/$this->mConn = mssql_connect($server, $user, $password, true);
-                       }
-               }
-               
-               wfProfileOut("dbconnect-$server");
-
-               if ($dbName != '') {
-                       if ($this->mConn !== false) {
-                               $success = @/**/mssql_select_db($dbName, $this->mConn);
-                               if (!$success) {
-                                       $error = "Error selecting database $dbName on server {$this->mServer} " .
-                                               "from client host " . wfHostname() . "\n";
-                                       wfLogDBError(" Error selecting database $dbName on server {$this->mServer} \n");
-                                       wfDebug( $error );
-                               }
-                       } else {
-                               wfDebug("DB connection error\n");
-                               wfDebug("Server: $server, User: $user, Password: ".substr($password, 0, 3)."...\n");
-                               $success = false;
-                       }
-               } else {
-                       # Delay USE query
-                       $success = (bool)$this->mConn;
-               }
-
-               if (!$success) $this->reportConnectionError();
-               $this->mOpened = $success;
-               wfProfileOut(__METHOD__);
-               return $success;
-       }
-
-       /**
-        * Close an MSSQL database
-        */
-       function close() {
-               $this->mOpened = false;
-               if ($this->mConn) {
-                       if ($this->trxLevel()) $this->commit();
-                       return mssql_close($this->mConn);
-               } else return true;
-       }
-
-       /**
-        * - MSSQL doesn't seem to do buffered results
-        * - the trasnaction syntax is modified here to avoid having to replicate
-        *   Database::query which uses BEGIN, COMMIT, ROLLBACK
-        */
-       function doQuery($sql) {
-               if ($sql == 'BEGIN' || $sql == 'COMMIT' || $sql == 'ROLLBACK') return true; # $sql .= ' TRANSACTION';
-               $sql = preg_replace('|[^\x07-\x7e]|','?',$sql); # TODO: need to fix unicode - just removing it here while testing
-               $ret = mssql_query($sql, $this->mConn);
-               if ($ret === false) {
-                       $err = mssql_get_last_message();
-                       if ($err) $this->mlastError = $err;
-                       $row = mssql_fetch_row(mssql_query('select @@ERROR'));
-                       if ($row[0]) $this->mlastErrorNo = $row[0];
-               } else $this->mlastErrorNo = false;
-               return $ret;
-       }
-
-       /**
-        * Free a result object
-        */
-       function freeResult( $res ) {
-               if ( $res instanceof ResultWrapper ) {
-                       $res = $res->result;
-               }
-               if ( !@/**/mssql_free_result( $res ) ) {
-                       throw new DBUnexpectedError( $this, "Unable to free MSSQL result" );
-               }
-       }
-
-       /**
-        * Fetch the next row from the given result object, in object form.
-        * Fields can be retrieved with $row->fieldname, with fields acting like
-        * member variables.
-        *
-        * @param $res SQL result object as returned from Database::query(), etc.
-        * @return MySQL row object
-        * @throws DBUnexpectedError Thrown if the database returns an error
-        */
-       function fetchObject( $res ) {
-               if ( $res instanceof ResultWrapper ) {
-                       $res = $res->result;
-               }
-               @/**/$row = mssql_fetch_object( $res );
-               if ( $this->lastErrno() ) {
-                       throw new DBUnexpectedError( $this, 'Error in fetchObject(): ' . htmlspecialchars( $this->lastError() ) );
-               }
-               return $row;
-       }
-
-       /**
-        * Fetch the next row from the given result object, in associative array
-        * form.  Fields are retrieved with $row['fieldname'].
-        *
-        * @param $res SQL result object as returned from Database::query(), etc.
-        * @return MySQL row object
-        * @throws DBUnexpectedError Thrown if the database returns an error
-        */
-       function fetchRow( $res ) {
-               if ( $res instanceof ResultWrapper ) {
-                       $res = $res->result;
-               }
-               @/**/$row = mssql_fetch_array( $res );
-               if ( $this->lastErrno() ) {
-                       throw new DBUnexpectedError( $this, 'Error in fetchRow(): ' . htmlspecialchars( $this->lastError() ) );
-               }
-               return $row;
-       }
-
-       /**
-        * Get the number of rows in a result object
-        */
-       function numRows( $res ) {
-               if ( $res instanceof ResultWrapper ) {
-                       $res = $res->result;
-               }
-               @/**/$n = mssql_num_rows( $res );
-               if ( $this->lastErrno() ) {
-                       throw new DBUnexpectedError( $this, 'Error in numRows(): ' . htmlspecialchars( $this->lastError() ) );
-               }
-               return $n;
-       }
-
-       /**
-        * Get the number of fields in a result object
-        * See documentation for mysql_num_fields()
-        * @param $res SQL result object as returned from Database::query(), etc.
-        */
-       function numFields( $res ) {
-               if ( $res instanceof ResultWrapper ) {
-                       $res = $res->result;
-               }
-               return mssql_num_fields( $res );
-       }
-
-       /**
-        * Get a field name in a result object
-        * See documentation for mysql_field_name():
-        * http://www.php.net/mysql_field_name
-        * @param $res SQL result object as returned from Database::query(), etc.
-        * @param $n Int
-        */
-       function fieldName( $res, $n ) {
-               if ( $res instanceof ResultWrapper ) {
-                       $res = $res->result;
-               }
-               return mssql_field_name( $res, $n );
-       }
-
-       /**
-        * Get the inserted value of an auto-increment row
-        *
-        * The value inserted should be fetched from nextSequenceValue()
-        *
-        * Example:
-        * $id = $dbw->nextSequenceValue('page_page_id_seq');
-        * $dbw->insert('page',array('page_id' => $id));
-        * $id = $dbw->insertId();
-        */
-       function insertId() {
-               $row = mssql_fetch_row(mssql_query('select @@IDENTITY'));
-               return $row[0];
-       }
-
-       /**
-        * Change the position of the cursor in a result object
-        * See mysql_data_seek()
-        * @param $res SQL result object as returned from Database::query(), etc.
-        * @param $row Database row
-        */
-       function dataSeek( $res, $row ) {
-               if ( $res instanceof ResultWrapper ) {
-                       $res = $res->result;
-               }
-               return mssql_data_seek( $res, $row );
-       }
-
-       /**
-        * Get the last error number
-        */
-       function lastErrno() {
-               return $this->mlastErrorNo;
-       }
-
-       /**
-        * Get a description of the last error
-        */
-       function lastError() {
-               return $this->mlastError;
-       }
-
-       /**
-        * Get the number of rows affected by the last write query
-        */
-       function affectedRows() {
-               return mssql_rows_affected( $this->mConn );
-       }
-
-       /**
-        * Simple UPDATE wrapper
-        * Usually aborts on failure
-        * If errors are explicitly ignored, returns success
-        *
-        * This function exists for historical reasons, Database::update() has a more standard
-        * calling convention and feature set
-        */
-       function set( $table, $var, $value, $cond, $fname = 'Database::set' )
-       {
-               if ($value == "NULL") $value = "''"; # see comments in makeListWithoutNulls()
-               $table = $this->tableName( $table );
-               $sql = "UPDATE $table SET $var = '" .
-                 $this->strencode( $value ) . "' WHERE ($cond)";
-               return (bool)$this->query( $sql, $fname );
-       }
-
-       /**
-        * 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 selectField( $table, $var, $cond='', $fname = 'Database::selectField', $options = array() ) {
-               if ( !is_array( $options ) ) {
-                       $options = array( $options );
-               }
-               $options['LIMIT'] = 1;
-
-               $res = $this->select( $table, $var, $cond, $fname, $options );
-               if ( $res === false || !$this->numRows( $res ) ) {
-                       return false;
-               }
-               $row = $this->fetchRow( $res );
-               if ( $row !== false ) {
-                       $this->freeResult( $res );
-                       return $row[0];
-               } else {
-                       return false;
-               }
-       }
-
-       /**
-        * Returns an optional USE INDEX clause to go after the table, and a
-        * string to go at the end of the query
-        *
-        * @private
-        *
-        * @param $options Array: an associative array of options to be turned into
-        *              an SQL query, valid keys are listed in the function.
-        * @return array
-        */
-       function makeSelectOptions( $options ) {
-               $preLimitTail = $postLimitTail = '';
-               $startOpts = '';
-
-               $noKeyOptions = array();
-               foreach ( $options as $key => $option ) {
-                       if ( is_numeric( $key ) ) {
-                               $noKeyOptions[$option] = true;
-                       }
-               }
-
-               if ( isset( $options['GROUP BY'] ) ) $preLimitTail .= " GROUP BY {$options['GROUP BY']}";
-               if ( isset( $options['HAVING'] ) ) $preLimitTail .= " HAVING {$options['HAVING']}";
-               if ( isset( $options['ORDER BY'] ) ) $preLimitTail .= " ORDER BY {$options['ORDER BY']}";
-               
-               //if (isset($options['LIMIT'])) {
-               //      $tailOpts .= $this->limitResult('', $options['LIMIT'],
-               //              isset($options['OFFSET']) ? $options['OFFSET'] 
-               //              : false);
-               //}
-
-               if ( isset( $noKeyOptions['FOR UPDATE'] ) ) $postLimitTail .= ' FOR UPDATE';
-               if ( isset( $noKeyOptions['LOCK IN SHARE MODE'] ) ) $postLimitTail .= ' LOCK IN SHARE MODE';
-               if ( isset( $noKeyOptions['DISTINCT'] ) || isset( $noKeyOptions['DISTINCTROW'] ) ) $startOpts .= 'DISTINCT';
-
-               # Various MySQL extensions
-               if ( isset( $noKeyOptions['STRAIGHT_JOIN'] ) ) $startOpts .= ' /*! STRAIGHT_JOIN */';
-               if ( isset( $noKeyOptions['HIGH_PRIORITY'] ) ) $startOpts .= ' HIGH_PRIORITY';
-               if ( isset( $noKeyOptions['SQL_BIG_RESULT'] ) ) $startOpts .= ' SQL_BIG_RESULT';
-               if ( isset( $noKeyOptions['SQL_BUFFER_RESULT'] ) ) $startOpts .= ' SQL_BUFFER_RESULT';
-               if ( isset( $noKeyOptions['SQL_SMALL_RESULT'] ) ) $startOpts .= ' SQL_SMALL_RESULT';
-               if ( isset( $noKeyOptions['SQL_CALC_FOUND_ROWS'] ) ) $startOpts .= ' SQL_CALC_FOUND_ROWS';
-               if ( isset( $noKeyOptions['SQL_CACHE'] ) ) $startOpts .= ' SQL_CACHE';
-               if ( isset( $noKeyOptions['SQL_NO_CACHE'] ) ) $startOpts .= ' SQL_NO_CACHE';
-
-               if ( isset( $options['USE INDEX'] ) && ! is_array( $options['USE INDEX'] ) ) {
-                       $useIndex = $this->useIndexClause( $options['USE INDEX'] );
-               } else {
-                       $useIndex = '';
-               }
-               
-               return array( $startOpts, $useIndex, $preLimitTail, $postLimitTail );
-       }
-
-       /**
-        * SELECT wrapper
-        *
-        * @param $table   Mixed: Array or string, table name(s) (prefix auto-added)
-        * @param $vars    Mixed: Array or string, field name(s) to be retrieved
-        * @param $conds   Mixed: Array or string, condition(s) for WHERE
-        * @param $fname   String: Calling function name (use __METHOD__) for logs/profiling
-        * @param $options Array: Associative array of options (e.g. array('GROUP BY' => 'page_title')),
-        *                        see Database::makeSelectOptions code for list of supported stuff
-        * @return mixed Database result resource (feed to Database::fetchObject or whatever), or false on failure
-        */
-       function select( $table, $vars, $conds='', $fname = 'Database::select', $options = array() )
-       {
-               if( is_array( $vars ) ) {
-                       $vars = implode( ',', $vars );
-               }
-               if( !is_array( $options ) ) {
-                       $options = array( $options );
-               }
-               if( is_array( $table ) ) {
-                       if ( isset( $options['USE INDEX'] ) && is_array( $options['USE INDEX'] ) )
-                               $from = ' FROM ' . $this->tableNamesWithUseIndex( $table, $options['USE INDEX'] );
-                       else
-                               $from = ' FROM ' . implode( ',', array_map( array( &$this, 'tableName' ), $table ) );
-               } elseif ($table!='') {
-                       if ($table{0}==' ') {
-                               $from = ' FROM ' . $table;
-                       } else {
-                               $from = ' FROM ' . $this->tableName( $table );
-                       }
-               } else {
-                       $from = '';
-               }
-
-               list( $startOpts, $useIndex, $preLimitTail, $postLimitTail ) = $this->makeSelectOptions( $options );
-
-               if( !empty( $conds ) ) {
-                       if ( is_array( $conds ) ) {
-                               $conds = $this->makeList( $conds, LIST_AND );
-                       }
-                       $sql = "SELECT $startOpts $vars $from $useIndex WHERE $conds $preLimitTail";
-               } else {
-                       $sql = "SELECT $startOpts $vars $from $useIndex $preLimitTail";
-               }
-
-               if (isset($options['LIMIT']))
-                       $sql = $this->limitResult($sql, $options['LIMIT'],
-                               isset($options['OFFSET']) ? $options['OFFSET'] : false);
-               $sql = "$sql $postLimitTail";
-               
-               if (isset($options['EXPLAIN'])) {
-                       $sql = 'EXPLAIN ' . $sql;
-               }
-               return $this->query( $sql, $fname );
-       }
-
-       /**
-        * Determines whether a field exists in a table
-        * Usually aborts on failure
-        * If errors are explicitly ignored, returns NULL on failure
-        */
-       function fieldExists( $table, $field, $fname = 'Database::fieldExists' ) {
-               $table = $this->tableName( $table );
-               $sql = "SELECT TOP 1 * FROM $table";
-               $res = $this->query( $sql, 'Database::fieldExists' );
-
-               $found = false;
-               while ( $row = $this->fetchArray( $res ) ) {
-                       if ( isset($row[$field]) ) {
-                               $found = true;
-                               break;
-                       }
-               }
-
-               $this->freeResult( $res );
-               return $found;
-       }
-
-       /**
-        * Get information about an index into an object
-        * Returns false if the index does not exist
-        */
-       function indexInfo( $table, $index, $fname = 'Database::indexInfo' ) {
-
-               throw new DBUnexpectedError( $this, 'Database::indexInfo called which is not supported yet' );
-               return null;
-
-               $table = $this->tableName( $table );
-               $sql = 'SHOW INDEX FROM '.$table;
-               $res = $this->query( $sql, $fname );
-               if ( !$res ) {
-                       return null;
-               }
-
-               $result = array();
-               while ( $row = $this->fetchObject( $res ) ) {
-                       if ( $row->Key_name == $index ) {
-                               $result[] = $row;
-                       }
-               }
-               $this->freeResult($res);
-               
-               return empty($result) ? false : $result;
-       }
-
-       /**
-        * Query whether a given table exists
-        */
-       function tableExists( $table ) {
-               $table = $this->tableName( $table );
-               $res = $this->query( "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '$table'" );
-               $exist = ($res->numRows() > 0);
-               $this->freeResult($res);
-               return $exist;
-       }
-
-       /**
-        * mysql_fetch_field() wrapper
-        * Returns false if the field doesn't exist
-        *
-        * @param $table
-        * @param $field
-        */
-       function fieldInfo( $table, $field ) {
-               $table = $this->tableName( $table );
-               $res = $this->query( "SELECT TOP 1 * FROM $table" );
-               $n = mssql_num_fields( $res->result );
-               for( $i = 0; $i < $n; $i++ ) {
-                       $meta = mssql_fetch_field( $res->result, $i );
-                       if( $field == $meta->name ) {
-                               return new MSSQLField($meta);
-                       }
-               }
-               return false;
-       }
-
-       /**
-        * mysql_field_type() wrapper
-        */
-       function fieldType( $res, $index ) {
-               if ( $res instanceof ResultWrapper ) {
-                       $res = $res->result;
-               }
-               return mssql_field_type( $res, $index );
-       }
-
-       /**
-        * INSERT wrapper, inserts an array into a table
-        *
-        * $a may be a single associative array, or an array of these with numeric keys, for
-        * multi-row insert.
-        *
-        * Usually aborts on failure
-        * If errors are explicitly ignored, returns success
-        * 
-        * Same as parent class implementation except that it removes primary key from column lists
-        * because MSSQL doesn't support writing nulls to IDENTITY (AUTO_INCREMENT) columns
-        */
-       function insert( $table, $a, $fname = 'Database::insert', $options = array() ) {
-               # No rows to insert, easy just return now
-               if ( !count( $a ) ) {
-                       return true;
-               }
-               $table = $this->tableName( $table );
-               if ( !is_array( $options ) ) {
-                       $options = array( $options );
-               }
-               
-               # todo: need to record primary keys at table create time, and remove NULL assignments to them
-               if ( isset( $a[0] ) && is_array( $a[0] ) ) {
-                       $multi = true;
-                       $keys = array_keys( $a[0] );
-#                      if (ereg('_id$',$keys[0])) {
-                               foreach ($a as $i) {
-                                       if (is_null($i[$keys[0]])) unset($i[$keys[0]]); # remove primary-key column from multiple insert lists if empty value
-                               }
-#                      }
-                       $keys = array_keys( $a[0] );
-               } else {
-                       $multi = false;
-                       $keys = array_keys( $a );
-#                      if (ereg('_id$',$keys[0]) && empty($a[$keys[0]])) unset($a[$keys[0]]); # remove primary-key column from insert list if empty value
-                       if (is_null($a[$keys[0]])) unset($a[$keys[0]]); # remove primary-key column from insert list if empty value
-                       $keys = array_keys( $a );
-               }
-
-               # handle IGNORE option
-               # example:
-               #   MySQL: INSERT IGNORE INTO user_groups (ug_user,ug_group) VALUES ('1','sysop')
-               #   MSSQL: IF NOT EXISTS (SELECT * FROM user_groups WHERE ug_user = '1') INSERT INTO user_groups (ug_user,ug_group) VALUES ('1','sysop')
-               $ignore = in_array('IGNORE',$options);
-
-               # remove IGNORE from options list
-               if ($ignore) {
-                       $oldoptions = $options;
-                       $options = array();
-                       foreach ($oldoptions as $o) if ($o != 'IGNORE') $options[] = $o;
-               }
-
-               $keylist = implode(',', $keys);
-               $sql = 'INSERT '.implode(' ', $options)." INTO $table (".implode(',', $keys).') VALUES ';
-               if ($multi) {
-                       if ($ignore) {
-                               # If multiple and ignore, then do each row as a separate conditional insert
-                               foreach ($a as $row) {
-                                       $prival = $row[$keys[0]];
-                                       $sql = "IF NOT EXISTS (SELECT * FROM $table WHERE $keys[0] = '$prival') $sql";
-                                       if (!$this->query("$sql (".$this->makeListWithoutNulls($row).')', $fname)) return false;
-                               }
-                               return true;
-                       } else {
-                               $first = true;
-                               foreach ($a as $row) {
-                                       if ($first) $first = false; else $sql .= ',';
-                                       $sql .= '('.$this->makeListWithoutNulls($row).')';
-                               }
-                       }
-               } else {
-                       if ($ignore) {
-                               $prival = $a[$keys[0]];
-                               $sql = "IF NOT EXISTS (SELECT * FROM $table WHERE $keys[0] = '$prival') $sql";
-                       }
-                       $sql .= '('.$this->makeListWithoutNulls($a).')';
-               }
-               return (bool)$this->query( $sql, $fname );
-       }
-
-       /**
-        * MSSQL doesn't allow implicit casting of NULL's into non-null values for NOT NULL columns
-        *   for now I've just converted the NULL's in the lists for updates and inserts into empty strings
-        *   which get implicitly casted to 0 for numeric columns
-        * NOTE: the set() method above converts NULL to empty string as well but not via this method
-        */
-       function makeListWithoutNulls($a, $mode = LIST_COMMA) {
-               return str_replace("NULL","''",$this->makeList($a,$mode));
-       }
-
-       /**
-        * UPDATE wrapper, takes a condition array and a SET array
-        *
-        * @param $table   String: The table to UPDATE
-        * @param $values  Array: An array of values to SET
-        * @param $conds   Array: An array of conditions (WHERE). Use '*' to update all rows.
-        * @param $fname   String: The Class::Function calling this function
-        *                        (for the log)
-        * @param $options Array: An array of UPDATE options, can be one or
-        *                        more of IGNORE, LOW_PRIORITY
-        * @return bool
-        */
-       function update( $table, $values, $conds, $fname = 'Database::update', $options = array() ) {
-               $table = $this->tableName( $table );
-               $opts = $this->makeUpdateOptions( $options );
-               $sql = "UPDATE $opts $table SET " . $this->makeListWithoutNulls( $values, LIST_SET );
-               if ( $conds != '*' ) {
-                       $sql .= " WHERE " . $this->makeList( $conds, LIST_AND );
-               }
-               return $this->query( $sql, $fname );
-       }
-
-       /**
-        * Make UPDATE options for the Database::update function
-        *
-        * @private
-        * @param $options Array: The options passed to Database::update
-        * @return string
-        */
-       function makeUpdateOptions( $options ) {
-               if( !is_array( $options ) ) {
-                       $options = array( $options );
-               }
-               $opts = array();
-               if ( in_array( 'LOW_PRIORITY', $options ) )
-                       $opts[] = $this->lowPriorityOption();
-               if ( in_array( 'IGNORE', $options ) )
-                       $opts[] = 'IGNORE';
-               return implode(' ', $opts);
-       }
-
-       /**
-        * Change the current database
-        */
-       function selectDB( $db ) {
-               $this->mDBname = $db;
-               return mssql_select_db( $db, $this->mConn );
-       }
-
-       /**
-        * MSSQL has a problem with the backtick quoting, so all this does is ensure the prefix is added exactly once
-        */
-       function tableName($name) {
-               return strpos($name, $this->mTablePrefix) === 0 ? $name : "{$this->mTablePrefix}$name";
-       }
-
-       /**
-        * MSSQL doubles quotes instead of escaping them
-        * @param $s String to be slashed.
-        * @return string slashed string.
-        */
-       function strencode($s) {
-               return str_replace("'","''",$s);
-       }
-
-       /**
-        * REPLACE query wrapper
-        * PostgreSQL simulates this with a DELETE followed by INSERT
-        * $row is the row to insert, an associative array
-        * $uniqueIndexes is an array of indexes. Each element may be either a
-        * field name or an array of field names
-        *
-        * It may be more efficient to leave off unique indexes which are unlikely to collide.
-        * However if you do this, you run the risk of encountering errors which wouldn't have
-        * occurred in MySQL
-        *
-        * @todo migrate comment to phodocumentor format
-        */
-       function replace( $table, $uniqueIndexes, $rows, $fname = 'Database::replace' ) {
-               $table = $this->tableName( $table );
-
-               # Single row case
-               if ( !is_array( reset( $rows ) ) ) {
-                       $rows = array( $rows );
-               }
-
-               $sql = "REPLACE INTO $table (" . implode( ',', array_keys( $rows[0] ) ) .') VALUES ';
-               $first = true;
-               foreach ( $rows as $row ) {
-                       if ( $first ) {
-                               $first = false;
-                       } else {
-                               $sql .= ',';
-                       }
-                       $sql .= '(' . $this->makeList( $row ) . ')';
-               }
-               return $this->query( $sql, $fname );
-       }
-
-       /**
-        * DELETE where the condition is a join
-        * MySQL does this with a multi-table DELETE syntax, PostgreSQL does it with sub-selects
-        *
-        * For safety, an empty $conds will not delete everything. If you want to delete all rows where the
-        * join condition matches, set $conds='*'
-        *
-        * DO NOT put the join condition in $conds
-        *
-        * @param $delTable String: The table to delete from.
-        * @param $joinTable String: The other table.
-        * @param $delVar String: The variable to join on, in the first table.
-        * @param $joinVar String: The variable to join on, in the second table.
-        * @param $conds Array: Condition array of field names mapped to variables, ANDed together in the WHERE clause
-        * @param $fname String: Calling function name
-        */
-       function deleteJoin( $delTable, $joinTable, $delVar, $joinVar, $conds, $fname = 'Database::deleteJoin' ) {
-               if ( !$conds ) {
-                       throw new DBUnexpectedError( $this, 'Database::deleteJoin() called with empty $conds' );
-               }
-
-               $delTable = $this->tableName( $delTable );
-               $joinTable = $this->tableName( $joinTable );
-               $sql = "DELETE $delTable FROM $delTable, $joinTable WHERE $delVar=$joinVar ";
-               if ( $conds != '*' ) {
-                       $sql .= ' AND ' . $this->makeList( $conds, LIST_AND );
-               }
-
-               return $this->query( $sql, $fname );
-       }
-
-       /**
-        * Returns the size of a text field, or -1 for "unlimited"
-        */
-       function textFieldSize( $table, $field ) {
-               $table = $this->tableName( $table );
-               $sql = "SELECT TOP 1 * FROM $table;";
-               $res = $this->query( $sql, 'Database::textFieldSize' );
-               $row = $this->fetchObject( $res );
-               $this->freeResult( $res );
-
-               $m = array();
-               if ( preg_match( '/\((.*)\)/', $row->Type, $m ) ) {
-                       $size = $m[1];
-               } else {
-                       $size = -1;
-               }
-               return $size;
-       }
-
-       /**
-        * @return string Returns the text of the low priority option if it is supported, or a blank string otherwise
-        */
-       function lowPriorityOption() {
-               return 'LOW_PRIORITY';
-       }
-
-       /**
-        * INSERT SELECT wrapper
-        * $varMap must be an associative array of the form array( 'dest1' => 'source1', ...)
-        * Source items may be literals rather than field names, but strings should be quoted with Database::addQuotes()
-        * $conds may be "*" to copy the whole table
-        * srcTable may be an array of tables.
-        */
-       function insertSelect( $destTable, $srcTable, $varMap, $conds, $fname = 'Database::insertSelect',
-               $insertOptions = array(), $selectOptions = array() )
-       {
-               $destTable = $this->tableName( $destTable );
-               if ( is_array( $insertOptions ) ) {
-                       $insertOptions = implode( ' ', $insertOptions );
-               }
-               if( !is_array( $selectOptions ) ) {
-                       $selectOptions = array( $selectOptions );
-               }
-               list( $startOpts, $useIndex, $tailOpts ) = $this->makeSelectOptions( $selectOptions );
-               if( is_array( $srcTable ) ) {
-                       $srcTable =  implode( ',', array_map( array( &$this, 'tableName' ), $srcTable ) );
-               } else {
-                       $srcTable = $this->tableName( $srcTable );
-               }
-               $sql = "INSERT $insertOptions INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ')' .
-                       " SELECT $startOpts " . implode( ',', $varMap ) .
-                       " FROM $srcTable $useIndex ";
-               if ( $conds != '*' ) {
-                       $sql .= ' WHERE ' . $this->makeList( $conds, LIST_AND );
-               }
-               $sql .= " $tailOpts";
-               return $this->query( $sql, $fname );
-       }
-
-       /**
-        * Construct a LIMIT query with optional offset
-        * This is used for query pages
-        * $sql string SQL query we will append the limit to
-        * $limit integer the SQL limit
-        * $offset integer the SQL offset (default false)
-        */
-       function limitResult($sql, $limit, $offset=false) {
-               if( !is_numeric($limit) ) {
-                       throw new DBUnexpectedError( $this, "Invalid non-numeric limit passed to limitResult()\n" );
-               }
-               if ($offset) {
-                       throw new DBUnexpectedError( $this, 'Database::limitResult called with non-zero offset which is not supported yet' );
-               } else {
-                       $sql = preg_replace("/^SELECT/i", "SELECT TOP $limit", $sql);
-               }
-               return $sql;
-       }
-
-       /**
-        * Should determine if the last failure was due to a deadlock
-        * @return bool
-        */
-       function wasDeadlock() {
-               return $this->lastErrno() == 1205;
-       }
-
-       /**
-        * Return MW-style timestamp used for MySQL schema
-        */
-       function timestamp( $ts=0 ) {
-               return wfTimestamp(TS_MW,$ts);
-       }
-
-       /**
-        * Local database timestamp format or null
-        */
-       function timestampOrNull( $ts = null ) {
-               if( is_null( $ts ) ) {
-                       return null;
-               } else {
-                       return $this->timestamp( $ts );
-               }
-       }
-
-       /**
-        * @return string wikitext of a link to the server software's web site
-        */
-       function getSoftwareLink() {
-               return "[http://www.microsoft.com/sql/default.mspx Microsoft SQL Server 2005 Home]";
-       }
-
-       /**
-        * @return string Version information from the database
-        */
-       function getServerVersion() {
-               $row = mssql_fetch_row(mssql_query('select @@VERSION'));
-               return preg_match("/^(.+[0-9]+\\.[0-9]+\\.[0-9]+) /",$row[0],$m) ? $m[1] : $row[0];
-       }
-
-       function limitResultForUpdate($sql, $num) {
-               return $sql;
-       }
-
-       /**
-        * How lagged is this slave?
-        */
-       public function getLag() {
-               return 0;
-       }
-
-       /**
-        * Called by the installer script
-        * - this is the same way as DatabasePostgresql.php, MySQL reads in tables.sql and interwiki.sql using dbsource (which calls db->sourceFile)
-        */
-       public function setup_database() {
-               global $IP,$wgDBTableOptions;
-               $wgDBTableOptions = '';
-               $mysql_tmpl = "$IP/maintenance/tables.sql";
-               $mysql_iw   = "$IP/maintenance/interwiki.sql";
-               $mssql_tmpl = "$IP/maintenance/mssql/tables.sql";
-
-               # Make an MSSQL template file if it doesn't exist (based on the same one MySQL uses to create a new wiki db)
-               if (!file_exists($mssql_tmpl)) { # todo: make this conditional again
-                       $sql = file_get_contents($mysql_tmpl);
-                       $sql = preg_replace('/^\s*--.*?$/m','',$sql); # strip comments
-                       $sql = preg_replace('/^\s*(UNIQUE )?(INDEX|KEY|FULLTEXT).+?$/m', '', $sql); # These indexes should be created with a CREATE INDEX query
-                       $sql = preg_replace('/(\sKEY) [^\(]+\(/is', '$1 (', $sql); # "KEY foo (foo)" should just be "KEY (foo)"
-                       $sql = preg_replace('/(varchar\([0-9]+\))\s+binary/i', '$1', $sql); # "varchar(n) binary" cannot be followed by "binary"
-                       $sql = preg_replace('/(var)?binary\(([0-9]+)\)/ie', '"varchar(".strlen(pow(2,$2)).")"', $sql); # use varchar(chars) not binary(bits)
-                       $sql = preg_replace('/ (var)?binary/i', ' varchar', $sql); # use varchar not binary
-                       $sql = preg_replace('/(varchar\([0-9]+\)(?! N))/', '$1 NULL', $sql); # MSSQL complains if NULL is put into a varchar
-                       #$sql = preg_replace('/ binary/i',' varchar',$sql); # MSSQL binary's can't be assigned with strings, so use varchar's instead
-                       #$sql = preg_replace('/(binary\([0-9]+\) (NOT NULL )?default) [\'"].*?[\'"]/i','$1 0',$sql); # binary default cannot be string
-                       $sql = preg_replace('/[a-z]*(blob|text)([ ,])/i', 'text$2', $sql); # no BLOB types in MSSQL
-                       $sql = preg_replace('/\).+?;/',');', $sql); # remove all table options
-                       $sql = preg_replace('/ (un)?signed/i', '', $sql);
-                       $sql = preg_replace('/ENUM\(.+?\)/','TEXT',$sql); # Make ENUM's into TEXT's
-                       $sql = str_replace(' bool ', ' bit ', $sql);
-                       $sql = str_replace('auto_increment', 'IDENTITY(1,1)', $sql);
-                       #$sql = preg_replace('/NOT NULL(?! IDENTITY)/', 'NULL', $sql); # Allow NULL's for non IDENTITY columns
-
-                       # Tidy up and write file
-                       $sql = preg_replace('/,\s*\)/s', "\n)", $sql); # Remove spurious commas left after INDEX removals
-                       $sql = preg_replace('/^\s*^/m', '', $sql); # Remove empty lines
-                       $sql = preg_replace('/;$/m', ";\n", $sql); # Separate each statement with an empty line
-                       file_put_contents($mssql_tmpl, $sql);
-               }
-
-               # Parse the MSSQL template replacing inline variables such as /*$wgDBprefix*/
-               $err = $this->sourceFile($mssql_tmpl);
-               if ($err !== true) $this->reportQueryError($err,0,$sql,__FUNCTION__);
-
-               # Use DatabasePostgres's code to populate interwiki from MySQL template
-               $f = fopen($mysql_iw,'r');
-               if ($f == false) dieout("<li>Could not find the interwiki.sql file");
-               $sql = "INSERT INTO {$this->mTablePrefix}interwiki(iw_prefix,iw_url,iw_local) VALUES ";
-               while (!feof($f)) {
-                       $line = fgets($f,1024);
-                       $matches = array();
-                       if (!preg_match('/^\s*(\(.+?),(\d)\)/', $line, $matches)) continue;
-                       $this->query("$sql $matches[1],$matches[2])");
-               }
-       }
-       
-       public function getSearchEngine() {
-               return "SearchEngineDummy";
-       }
-}
-
-/**
- * @ingroup Database
- */
-class MSSQLField extends MySQLField {
-
-       function __construct() {
-       }
-
-       static function fromText($db, $table, $field) {
-               $n = new MSSQLField;
-               $n->name = $field;
-               $n->tablename = $table;
-               return $n;
-       }
-
-} // end DatabaseMssql class
-
diff --git a/maintenance/mssql/README b/maintenance/mssql/README
deleted file mode 100644 (file)
index bcdeb82..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-== Syntax differences between MySQL and MSSQL ==
-{| border cellspacing=0 cellpadding=4
-!MySQL!!MSSQL
-|-
-
-|AUTO_INCREMENT
-|IDENTITY(1,1)
-|-
-
-|binary
-|varchar NULL ''(MSSQL doesn't allow setting of binary's to string values, and won't implicitly allow NULL's)''
-|-
-
-|bool
-|bit
-|-
-
-|[UN]SIGNED
-|''not valid''
-|-
-
-|SELECT * FROM foo LIMIT x
-|SELECT TOP x * FROM foo
-|-
-
-|SELECT * FROM foo LIMIT x,y|
-''not sure how to implement yet because it must be applied from within '''DatabaseMssql::limitResult'''''
-|-
-
-|INSERT IGNORE INTO foo (foo_id,bar) VALUES ('1','xyz')
-|IF NOT EXISTS (SELECT * FROM foo WHERE foo_id = '1') INSERT INTO foo (foo_id,bar) VALUES ('1','xyz')
-|-
-
-|IF(cond,trueVal,falseVal)
-|CASE WHEN cond THEN trueVal ELSE falseVal END
-|-
-
-|SHOW TABLES
-|SELECT * FROM INFORMATION_SCHEMA.TABLES
-|-
-
-|ENUM
-|''not natively supported, change to text''
-|}
-
-== MSSQL Variables ==
-{| border cellspacing=0 cellpadding=4
-
-|@@VERSION
-|Server version information
-|-
-
-|@@IDENTITY
-|Last inserted row
-|-
-
-|@@ERROR
-|Last error number
-|}
-
-== Changes to INSERT wrapper ==
-=== AUTOINCREMENT vs IDENTITY ===
-MySQL style ''AUTOINCREMENT'' columns are inplemented in MSSQL using ''IDENTITY(x,y)'' where ''x'' is the initial value and ''y'' is the amount to add on each insert. The last value resulting from an insert into an IDENTITY column is stored in the ''@@IDENTITY'' variable. These kinds of columns are usually used as primary keys and are therefore assigned the ''NOT NULL'' property.
-
-In MySQL the standard way of inserting data into rows exhibiting AUTOINCREMENT columns is simply to use a ''NULL'' value which will be ignored. In MSSQL however assigning a ''NULL'' to an ''IDENTITY'' column is not allowed, instead the best way is not to include those items in the list of columns to be updated at all.
-
-To get round this in the MediaWiki MSSQL layer, I've modified the insert wrapper in the ''DatabaseMssql'' class to check if the primary key is used in the insert and remove it if so. It checks this by assuming that the primary key will be of the same name as the table but with ''_id'' on the end, and that it will the first item in the list of columns to update.
-
-=== IGNORE ===
-As you can see from the comparison table above, the MySQL ''INSERT IGNORE'' option takes quite a different form in MSSQL. This is handled in the ''insert'' wrapper method. In the case of multiple row inserts, a separate conditional insert query is performed for each item.
-
-== NULL values and NOT NULL columns ==
-MySQL implicitly casts NULL assignments to NOT NULL columns to an empty string or zero value accordingly, but MSSQL raises an error instead. This is a big problem within the MediaWiki environment because the code relies heavily on this implicit NULL casting. I've tried to get round the problem by replacing NULL's with empty strings from update and insert queries, and MSSQL is happy to cast the empty string to a numeric zero if necessary.
-
-== See also ==
-*[http://msdn.microsoft.com/en-us/library/ms188783.aspx MSSQL reference]
-*[http://doc.ddart.net/mssql/sql70/ca-co_1.htm Type casting]
-*[http://msdn.microsoft.com/en-us/library/ms187752.aspx TransactSQL datatypes]
diff --git a/maintenance/mssql/tables.sql b/maintenance/mssql/tables.sql
deleted file mode 100644 (file)
index 2484733..0000000
+++ /dev/null
@@ -1,395 +0,0 @@
-CREATE TABLE /*$wgDBprefix*/user (
-  user_id int NOT NULL IDENTITY(1,1),
-  user_name varchar(255) NOT NULL default '',
-  user_real_name varchar(255) NOT NULL default '',
-  user_password text NOT NULL,
-  user_newpassword text NOT NULL,
-  user_newpass_time varchar(5) NULL,
-  user_email text NOT NULL,
-  user_options text NOT NULL,
-  user_touched varchar(5) NOT NULL default '',
-  user_token varchar(10) NOT NULL default '',
-  user_email_authenticated varchar(5) NULL,
-  user_email_token varchar(10) NULL,
-  user_email_token_expires varchar(5) NULL,
-  user_registration varchar(5) NULL,
-  user_editcount int,
-  PRIMARY KEY (user_id)
-);
-
-CREATE TABLE /*$wgDBprefix*/user_groups (
-  ug_user int NOT NULL default '0',
-  ug_group varchar(5) NOT NULL default '',
-  PRIMARY KEY (ug_user,ug_group)
-);
-
-CREATE TABLE /*$wgDBprefix*/user_newtalk (
-  user_id int NOT NULL default '0',
-  user_ip varchar(13) NOT NULL default '',
-  user_last_timestamp varchar(5) NOT NULL default ''
-);
-
-CREATE TABLE /*$wgDBprefix*/page (
-  page_id int NOT NULL IDENTITY(1,1),
-  page_namespace int NOT NULL,
-  page_title varchar(255) NOT NULL,
-  page_restrictions text NOT NULL,
-  page_counter bigint NOT NULL default '0',
-  page_is_redirect tinyint NOT NULL default '0',
-  page_is_new tinyint NOT NULL default '0',
-  page_random real NOT NULL,
-  page_touched varchar(5) NOT NULL default '',
-  page_latest int NOT NULL,
-  page_len int NOT NULL,
-  PRIMARY KEY (page_id)
-);
-
-CREATE TABLE /*$wgDBprefix*/revision (
-  rev_id int NOT NULL IDENTITY(1,1),
-  rev_page int NOT NULL,
-  rev_text_id int NOT NULL,
-  rev_comment text NOT NULL,
-  rev_user int NOT NULL default '0',
-  rev_user_text varchar(255) NOT NULL default '',
-  rev_timestamp varchar(5) NOT NULL default '',
-  rev_minor_edit tinyint NOT NULL default '0',
-  rev_deleted tinyint NOT NULL default '0',
-  rev_len int,
-  rev_parent_id int default NULL,
-  PRIMARY KEY (rev_page, rev_id)
-);
-
-CREATE TABLE /*$wgDBprefix*/text (
-  old_id int NOT NULL IDENTITY(1,1),
-  old_text text NOT NULL,
-  old_flags text NOT NULL,
-  PRIMARY KEY (old_id)
-);
-
-CREATE TABLE /*$wgDBprefix*/archive (
-  ar_namespace int NOT NULL default '0',
-  ar_title varchar(255) NOT NULL default '',
-  ar_text text NOT NULL,
-  ar_comment text NOT NULL,
-  ar_user int NOT NULL default '0',
-  ar_user_text varchar(255) NOT NULL,
-  ar_timestamp varchar(5) NOT NULL default '',
-  ar_minor_edit tinyint NOT NULL default '0',
-  ar_flags text NOT NULL,
-  ar_rev_id int,
-  ar_text_id int,
-  ar_deleted tinyint NOT NULL default '0',
-  ar_len int,
-  ar_page_id int,
-  ar_parent_id int default NULL
-);
-
-CREATE TABLE /*$wgDBprefix*/pagelinks (
-  pl_from int NOT NULL default '0',
-  pl_namespace int NOT NULL default '0',
-  pl_title varchar(255) NOT NULL default ''
-);
-
-CREATE TABLE /*$wgDBprefix*/templatelinks (
-  tl_from int NOT NULL default '0',
-  tl_namespace int NOT NULL default '0',
-  tl_title varchar(255) NOT NULL default ''
-);
-
-CREATE TABLE /*$wgDBprefix*/imagelinks (
-  il_from int NOT NULL default '0',
-  il_to varchar(255) NOT NULL default ''
-);
-
-CREATE TABLE /*$wgDBprefix*/categorylinks (
-  cl_from int NOT NULL default '0',
-  cl_to varchar(255) NOT NULL default '',
-  cl_sortkey varchar(70) NOT NULL default '',
-  cl_timestamp timestamp NOT NULL
-);
-
-CREATE TABLE /*$wgDBprefix*/category (
-  cat_id int NOT NULL IDENTITY(1,1),
-  cat_title varchar(255) NOT NULL,
-  cat_pages int NOT NULL default 0,
-  cat_subcats int NOT NULL default 0,
-  cat_files int NOT NULL default 0,
-  cat_hidden tinyint NOT NULL default 0,
-  PRIMARY KEY (cat_id)
-);
-
-CREATE TABLE /*$wgDBprefix*/externallinks (
-  el_from int NOT NULL default '0',
-  el_to text NOT NULL,
-  el_index text NOT NULL
-);
-
-CREATE TABLE /*$wgDBprefix*/langlinks (
-  ll_from int NOT NULL default '0',
-  ll_lang varchar(7) NOT NULL default '',
-  ll_title varchar(255) NOT NULL default ''
-);
-
-CREATE TABLE /*$wgDBprefix*/site_stats (
-  ss_row_id int NOT NULL,
-  ss_total_views bigint default '0',
-  ss_total_edits bigint default '0',
-  ss_good_articles bigint default '0',
-  ss_total_pages bigint default '-1',
-  ss_users bigint default '-1',
-  ss_admins int default '-1',
-  ss_images int default '0'
-);
-
-CREATE TABLE /*$wgDBprefix*/hitcounter (
-  hc_id int NOT NULL
-);
-
-CREATE TABLE /*$wgDBprefix*/ipblocks (
-  ipb_id int NOT NULL IDENTITY(1,1),
-  ipb_address text NOT NULL,
-  ipb_user int NOT NULL default '0',
-  ipb_by int NOT NULL default '0',
-  ipb_by_text varchar(255) NOT NULL default '',
-  ipb_reason text NOT NULL,
-  ipb_timestamp varchar(5) NOT NULL default '',
-  ipb_auto bit NOT NULL default 0,
-  ipb_anon_only bit NOT NULL default 0,
-  ipb_create_account bit NOT NULL default 1,
-  ipb_enable_autoblock bit NOT NULL default '1',
-  ipb_expiry varchar(5) NOT NULL default '',
-  ipb_range_start text NOT NULL,
-  ipb_range_end text NOT NULL,
-  ipb_deleted bit NOT NULL default 0,
-  ipb_block_email bit NOT NULL default 0,
-  PRIMARY KEY (ipb_id)
-);
-
-CREATE TABLE /*$wgDBprefix*/image (
-  img_name varchar(255) NOT NULL default '',
-  img_size int NOT NULL default '0',
-  img_width int NOT NULL default '0',
-  img_height int NOT NULL default '0',
-  img_metadata text NOT NULL,
-  img_bits int NOT NULL default '0',
-  img_media_type TEXT default NULL,
-  img_major_mime TEXT NOT NULL default "unknown",
-  img_minor_mime varchar(10) NOT NULL default "unknown",
-  img_description text NOT NULL,
-  img_user int NOT NULL default '0',
-  img_user_text varchar(255) NOT NULL,
-  img_timestamp varchar(5) NOT NULL default '',
-  img_sha1 varchar(10) NOT NULL default '',
-  PRIMARY KEY (img_name)
-);
-
-CREATE TABLE /*$wgDBprefix*/oldimage (
-  oi_name varchar(255) NOT NULL default '',
-  oi_archive_name varchar(255) NOT NULL default '',
-  oi_size int NOT NULL default 0,
-  oi_width int NOT NULL default 0,
-  oi_height int NOT NULL default 0,
-  oi_bits int NOT NULL default 0,
-  oi_description text NOT NULL,
-  oi_user int NOT NULL default '0',
-  oi_user_text varchar(255) NOT NULL,
-  oi_timestamp varchar(5) NOT NULL default '',
-  oi_metadata text NOT NULL,
-  oi_media_type TEXT default NULL,
-  oi_major_mime TEXT NOT NULL default "unknown",
-  oi_minor_mime varchar(10) NOT NULL default "unknown",
-  oi_deleted tinyint NOT NULL default '0',
-  oi_sha1 varchar(10) NOT NULL default ''
-);
-
-CREATE TABLE /*$wgDBprefix*/filearchive (
-  fa_id int NOT NULL IDENTITY(1,1),
-  fa_name varchar(255) NOT NULL default '',
-  fa_archive_name varchar(255) NULL default '',
-  fa_storage_group varchar(5) NULL,
-  fa_storage_key varchar(17) NULL default '',
-  fa_deleted_user int,
-  fa_deleted_timestamp varchar(5) NULL default '',
-  fa_deleted_reason text,
-  fa_size int default '0',
-  fa_width int default '0',
-  fa_height int default '0',
-  fa_metadata text,
-  fa_bits int default '0',
-  fa_media_type TEXT default NULL,
-  fa_major_mime TEXT default "unknown",
-  fa_minor_mime varchar(10) NULL default "unknown",
-  fa_description text,
-  fa_user int default '0',
-  fa_user_text varchar(255) NULL,
-  fa_timestamp varchar(5) NULL default '',
-  fa_deleted tinyint NOT NULL default '0',
-  PRIMARY KEY (fa_id)
-);
-
-CREATE TABLE /*$wgDBprefix*/recentchanges (
-  rc_id int NOT NULL IDENTITY(1,1),
-  rc_timestamp varchar(5) NOT NULL default '',
-  rc_cur_time varchar(5) NOT NULL default '',
-  rc_user int NOT NULL default '0',
-  rc_user_text varchar(255) NOT NULL,
-  rc_namespace int NOT NULL default '0',
-  rc_title varchar(255) NOT NULL default '',
-  rc_comment varchar(255) NOT NULL default '',
-  rc_minor tinyint NOT NULL default '0',
-  rc_bot tinyint NOT NULL default '0',
-  rc_new tinyint NOT NULL default '0',
-  rc_cur_id int NOT NULL default '0',
-  rc_this_oldid int NOT NULL default '0',
-  rc_last_oldid int NOT NULL default '0',
-  rc_type tinyint NOT NULL default '0',
-  rc_moved_to_ns tinyint NOT NULL default '0',
-  rc_moved_to_title varchar(255) NOT NULL default '',
-  rc_patrolled tinyint NOT NULL default '0',
-  rc_ip varchar(13) NOT NULL default '',
-  rc_old_len int,
-  rc_new_len int,
-  rc_deleted tinyint NOT NULL default '0',
-  rc_logid int NOT NULL default '0',
-  rc_log_type varchar(17) NULL default NULL,
-  rc_log_action varchar(17) NULL default NULL,
-  rc_params text NULL,
-  PRIMARY KEY (rc_id)
-);
-
-CREATE TABLE /*$wgDBprefix*/watchlist (
-  wl_user int NOT NULL,
-  wl_namespace int NOT NULL default '0',
-  wl_title varchar(255) NOT NULL default '',
-  wl_notificationtimestamp varchar(5) NULL
-);
-
-CREATE TABLE /*$wgDBprefix*/math (
-  math_inputhash varchar(5) NOT NULL,
-  math_outputhash varchar(5) NOT NULL,
-  math_html_conservativeness tinyint NOT NULL,
-  math_html text,
-  math_mathml text
-);
-
-CREATE TABLE /*$wgDBprefix*/searchindex (
-  si_page int NOT NULL,
-  si_title varchar(255) NOT NULL default '',
-  si_text text NOT NULL
-);
-
-CREATE TABLE /*$wgDBprefix*/interwiki (
-  iw_prefix varchar(32) NOT NULL,
-  iw_url text NOT NULL,
-  iw_local bit NOT NULL,
-  iw_trans tinyint NOT NULL default 0
-);
-
-CREATE TABLE /*$wgDBprefix*/querycache (
-  qc_type varchar(10) NOT NULL,
-  qc_value int NOT NULL default '0',
-  qc_namespace int NOT NULL default '0',
-  qc_title varchar(255) NOT NULL default ''
-);
-
-CREATE TABLE /*$wgDBprefix*/objectcache (
-  keyname varchar(17) NOT NULL default '',
-  value text,
-  exptime datetime
-);
-
-CREATE TABLE /*$wgDBprefix*/transcache (
-  tc_url varchar(17) NOT NULL,
-  tc_contents text,
-  tc_time int NOT NULL
-);
-
-CREATE TABLE /*$wgDBprefix*/logging (
-  log_id int NOT NULL IDENTITY(1,1),
-  log_type varchar(4) NOT NULL default '',
-  log_action varchar(4) NOT NULL default '',
-  log_timestamp varchar(5) NOT NULL default '19700101000000',
-  log_user int NOT NULL default 0,
-  log_namespace int NOT NULL default 0,
-  log_title varchar(255) NOT NULL default '',
-  log_comment varchar(255) NOT NULL default '',
-  log_params text NOT NULL,
-  log_deleted tinyint NOT NULL default '0',
-  PRIMARY KEY (log_id)
-);
-
-CREATE TABLE /*$wgDBprefix*/trackbacks (
-  tb_id int IDENTITY(1,1),
-  tb_page int REFERENCES /*$wgDBprefix*/page(page_id) ON DELETE CASCADE,
-  tb_title varchar(255) NOT NULL,
-  tb_url text NOT NULL,
-  tb_ex text,
-  tb_name varchar(255) NULL,
-  PRIMARY KEY (tb_id)
-);
-
-CREATE TABLE /*$wgDBprefix*/job (
-  job_id int NOT NULL IDENTITY(1,1),
-  job_cmd varchar(17) NOT NULL default '',
-  job_namespace int NOT NULL,
-  job_title varchar(255) NOT NULL,
-  job_params text NOT NULL,
-  PRIMARY KEY (job_id)
-);
-
-CREATE TABLE /*$wgDBprefix*/querycache_info (
-  qci_type varchar(10) NOT NULL default '',
-  qci_timestamp varchar(5) NOT NULL default '19700101000000'
-);
-
-CREATE TABLE /*$wgDBprefix*/redirect (
-  rd_from int NOT NULL default '0',
-  rd_namespace int NOT NULL default '0',
-  rd_title varchar(255) NOT NULL default '',
-  PRIMARY KEY (rd_from)
-);
-
-CREATE TABLE /*$wgDBprefix*/querycachetwo (
-  qcc_type varchar(10) NOT NULL,
-  qcc_value int NOT NULL default '0',
-  qcc_namespace int NOT NULL default '0',
-  qcc_title varchar(255) NOT NULL default '',
-  qcc_namespacetwo int NOT NULL default '0',
-  qcc_titletwo varchar(255) NOT NULL default ''
-);
-
-CREATE TABLE /*$wgDBprefix*/page_restrictions (
-  pr_page int NOT NULL,
-  pr_type varchar(17) NOT NULL,
-  pr_level varchar(17) NOT NULL,
-  pr_cascade tinyint NOT NULL,
-  pr_user int NULL,
-  pr_expiry varchar(5) NULL,
-  pr_id int NOT NULL IDENTITY(1,1),
-  PRIMARY KEY (pr_page,pr_type)
-);
-
-CREATE TABLE /*$wgDBprefix*/protected_titles (
-  pt_namespace int NOT NULL,
-  pt_title varchar(255) NOT NULL,
-  pt_user int NOT NULL,
-  pt_reason text,
-  pt_timestamp varchar(5) NOT NULL,
-  pt_expiry varchar(5) NOT NULL default '',
-  pt_create_perm varchar(17) NOT NULL,
-  PRIMARY KEY (pt_namespace,pt_title)
-);
-
-CREATE TABLE /*$wgDBprefix*/page_props (
-  pp_page int NOT NULL,
-  pp_propname varchar(17) NOT NULL,
-  pp_value text NOT NULL,
-  PRIMARY KEY (pp_page,pp_propname)
-);
-
-CREATE TABLE /*$wgDBprefix*/updatelog (
-  ul_key varchar(255) NOT NULL,
-  PRIMARY KEY (ul_key)
-);
-
-