'AllMessagesTablePager' => __DIR__ . '/includes/specials/pagers/AllMessagesTablePager.php',
'AllTrans' => __DIR__ . '/maintenance/language/alltrans.php',
'AlphabeticPager' => __DIR__ . '/includes/pager/AlphabeticPager.php',
- 'AlterSharedConstraints' => __DIR__ . '/maintenance/oracle/alterSharedConstraints.php',
'AncientPagesPage' => __DIR__ . '/includes/specials/SpecialAncientpages.php',
'AnsiTermColorer' => __DIR__ . '/maintenance/term/MWTerm.php',
'ApiAMCreateAccount' => __DIR__ . '/includes/api/ApiAMCreateAccount.php',
'DatabaseInstaller' => __DIR__ . '/includes/installer/DatabaseInstaller.php',
'DatabaseLag' => __DIR__ . '/maintenance/lag.php',
'DatabaseLogEntry' => __DIR__ . '/includes/logging/DatabaseLogEntry.php',
- 'DatabaseMssql' => __DIR__ . '/includes/libs/rdbms/database/DatabaseMssql.php',
'DatabaseMysqlBase' => __DIR__ . '/includes/libs/rdbms/database/DatabaseMysqlBase.php',
'DatabaseMysqli' => __DIR__ . '/includes/libs/rdbms/database/DatabaseMysqli.php',
- 'DatabaseOracle' => __DIR__ . '/includes/db/DatabaseOracle.php',
'DatabasePostgres' => __DIR__ . '/includes/libs/rdbms/database/DatabasePostgres.php',
'DatabaseSqlite' => __DIR__ . '/includes/libs/rdbms/database/DatabaseSqlite.php',
'DatabaseUpdater' => __DIR__ . '/includes/installer/DatabaseUpdater.php',
'MoveLogFormatter' => __DIR__ . '/includes/logging/MoveLogFormatter.php',
'MovePage' => __DIR__ . '/includes/MovePage.php',
'MovePageForm' => __DIR__ . '/includes/specials/SpecialMovepage.php',
- 'MssqlInstaller' => __DIR__ . '/includes/installer/MssqlInstaller.php',
- 'MssqlUpdater' => __DIR__ . '/includes/installer/MssqlUpdater.php',
'MultiConfig' => __DIR__ . '/includes/config/MultiConfig.php',
'MultiHttpClient' => __DIR__ . '/includes/libs/http/MultiHttpClient.php',
'MultiWriteBagOStuff' => __DIR__ . '/includes/libs/objectcache/MultiWriteBagOStuff.php',
'OldChangesList' => __DIR__ . '/includes/changes/OldChangesList.php',
'OldLocalFile' => __DIR__ . '/includes/filerepo/file/OldLocalFile.php',
'OldRevisionImporter' => __DIR__ . '/includes/import/OldRevisionImporter.php',
- 'OracleInstaller' => __DIR__ . '/includes/installer/OracleInstaller.php',
- 'OracleUpdater' => __DIR__ . '/includes/installer/OracleUpdater.php',
'OrderedStreamingForkController' => __DIR__ . '/includes/OrderedStreamingForkController.php',
'OrphanStats' => __DIR__ . '/maintenance/storage/orphanStats.php',
'Orphans' => __DIR__ . '/maintenance/orphans.php',
'Wikimedia\\Rdbms\\DBUnexpectedError' => __DIR__ . '/includes/libs/rdbms/exception/DBUnexpectedError.php',
'Wikimedia\\Rdbms\\Database' => __DIR__ . '/includes/libs/rdbms/database/Database.php',
'Wikimedia\\Rdbms\\DatabaseDomain' => __DIR__ . '/includes/libs/rdbms/database/domain/DatabaseDomain.php',
- 'Wikimedia\\Rdbms\\DatabaseMssql' => __DIR__ . '/includes/libs/rdbms/database/DatabaseMssql.php',
'Wikimedia\\Rdbms\\DatabaseMysqlBase' => __DIR__ . '/includes/libs/rdbms/database/DatabaseMysqlBase.php',
'Wikimedia\\Rdbms\\DatabaseMysqli' => __DIR__ . '/includes/libs/rdbms/database/DatabaseMysqli.php',
'Wikimedia\\Rdbms\\DatabasePostgres' => __DIR__ . '/includes/libs/rdbms/database/DatabasePostgres.php',
+++ /dev/null
-<?php
-/**
- * This is the Oracle database abstraction layer.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Database
- */
-
-use Wikimedia\AtEase\AtEase;
-use Wikimedia\Timestamp\ConvertibleTimestamp;
-use Wikimedia\Rdbms\Database;
-use Wikimedia\Rdbms\DatabaseDomain;
-use Wikimedia\Rdbms\Blob;
-use Wikimedia\Rdbms\ResultWrapper;
-use Wikimedia\Rdbms\IResultWrapper;
-use Wikimedia\Rdbms\DBUnexpectedError;
-use Wikimedia\Rdbms\DBExpectedError;
-
-/**
- * @ingroup Database
- */
-class DatabaseOracle extends Database {
- /** @var resource */
- protected $mLastResult = null;
-
- /** @var int The number of rows affected as an integer */
- protected $mAffectedRows;
-
- /** @var bool */
- private $ignoreDupValOnIndex = false;
-
- /** @var bool|array */
- private $sequenceData = null;
-
- /** @var string Character set for Oracle database */
- private $defaultCharset = 'AL32UTF8';
-
- /** @var array */
- private $mFieldInfoCache = [];
-
- /** @var string[] Map of (reserved table name => alternate table name) */
- private $keywordTableMap = [];
-
- /**
- * @see Database::__construct()
- * @param array $params Additional parameters include:
- * - keywordTableMap : Map of reserved table names to alternative table names to use
- */
- public function __construct( array $params ) {
- $this->keywordTableMap = $params['keywordTableMap'] ?? [];
- $params['tablePrefix'] = strtoupper( $params['tablePrefix'] );
- parent::__construct( $params );
- }
-
- function __destruct() {
- if ( $this->conn ) {
- AtEase::suppressWarnings();
- $this->close();
- AtEase::restoreWarnings();
- }
- }
-
- function getType() {
- return 'oracle';
- }
-
- function implicitOrderby() {
- return false;
- }
-
- protected function open( $server, $user, $password, $dbName, $schema, $tablePrefix ) {
- if ( !function_exists( 'oci_connect' ) ) {
- throw $this->newExceptionAfterConnectError(
- "Oracle functions missing, have you compiled PHP with the --with-oci8 option?\n " .
- "(Note: if you recently installed PHP, you may need to restart your webserver\n " .
- "and database)"
- );
- }
-
- $this->close();
-
- if ( $schema !== null ) {
- // This uses the *database* aspect of $domain for schema, not the domain schema
- throw $this->newExceptionAfterConnectError(
- "Got schema '$schema'; not supported. " .
- "The database component '$dbName' is actually interpreted as the Oracle schema."
- );
- }
-
- $this->user = $user;
- $this->password = $password;
- if ( strlen( $server ) ) {
- // Transparent Network Substrate (TNS) endpoint
- $this->server = $server;
- // Database name, defaulting to the user name
- $realDatabase = strlen( $dbName ) ? $dbName : $user;
- } else {
- // Backward compatibility; $server used to be null and $dbName was the TNS
- $this->server = $dbName;
- $realDatabase = $user;
- }
- $session_mode = ( $this->flags & DBO_SYSDBA ) ? OCI_SYSDBA : OCI_DEFAULT;
-
- $this->installErrorHandler();
- try {
- $this->conn = $this->getFlag( DBO_PERSISTENT )
- ? oci_pconnect(
- $this->user,
- $this->password,
- $this->server,
- $this->defaultCharset,
- $session_mode
- )
- : oci_new_connect(
- $this->user,
- $this->password,
- $this->server,
- $this->defaultCharset,
- $session_mode
- );
- } catch ( Exception $e ) {
- $this->restoreErrorHandler();
- throw $this->newExceptionAfterConnectError( $e->getMessage() );
- }
- $error = $this->restoreErrorHandler();
-
- if ( !$this->conn ) {
- throw $this->newExceptionAfterConnectError( $error ?: $this->lastError() );
- }
-
- try {
- if ( $this->user != $realDatabase ) {
- // Change current schema for the entire session
- $this->selectDomain( new DatabaseDomain(
- $realDatabase,
- $this->currentDomain->getSchema(),
- $this->currentDomain->getTablePrefix()
- ) );
- } else {
- $this->currentDomain = new DatabaseDomain( $realDatabase, null, $tablePrefix );
- }
- $set = [
- 'NLS_TIMESTAMP_FORMAT' => 'DD-MM-YYYY HH24:MI:SS.FF6',
- 'NLS_TIMESTAMP_TZ_FORMAT' => 'DD-MM-YYYY HH24:MI:SS.FF6',
- 'NLS_NUMERIC_CHARACTERS' => '.,'
- ];
- foreach ( $set as $var => $val ) {
- $this->query(
- "ALTER SESSION SET {$var}=" . $this->addQuotes( $val ),
- __METHOD__,
- self::QUERY_IGNORE_DBO_TRX | self::QUERY_NO_RETRY
- );
- }
- } catch ( Exception $e ) {
- throw $this->newExceptionAfterConnectError( $e->getMessage() );
- }
- }
-
- /**
- * Closes a database connection, if it is open
- * Returns success, true if already closed
- * @return bool
- */
- protected function closeConnection() {
- return oci_close( $this->conn );
- }
-
- function execFlags() {
- return $this->trxLevel() ? OCI_NO_AUTO_COMMIT : OCI_COMMIT_ON_SUCCESS;
- }
-
- /**
- * @param string $sql
- * @return bool|mixed|ORAResult
- */
- protected function doQuery( $sql ) {
- if ( !mb_check_encoding( (string)$sql, 'UTF-8' ) ) {
- throw new DBUnexpectedError( $this, "SQL encoding is invalid\n$sql" );
- }
-
- // handle some oracle specifics
- // remove AS column/table/subquery namings
- if ( !$this->getFlag( DBO_DDLMODE ) ) {
- $sql = preg_replace( '/ as /i', ' ', $sql );
- }
-
- // Oracle has issues with UNION clause if the statement includes LOB fields
- // So we do a UNION ALL and then filter the results array with array_unique
- $union_unique = ( preg_match( '/\/\* UNION_UNIQUE \*\/ /', $sql ) != 0 );
- // EXPLAIN syntax in Oracle is EXPLAIN PLAN FOR and it return nothing
- // you have to select data from plan table after explain
- $explain_id = MWTimestamp::getLocalInstance()->format( 'dmYHis' );
-
- $sql = preg_replace(
- '/^EXPLAIN /',
- 'EXPLAIN PLAN SET STATEMENT_ID = \'' . $explain_id . '\' FOR',
- $sql,
- 1,
- $explain_count
- );
-
- Wikimedia\suppressWarnings();
-
- $this->mLastResult = $stmt = oci_parse( $this->conn, $sql );
- if ( $stmt === false ) {
- $e = oci_error( $this->conn );
- $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
-
- return false;
- }
-
- if ( !oci_execute( $stmt, $this->execFlags() ) ) {
- $e = oci_error( $stmt );
- if ( !$this->ignoreDupValOnIndex || $e['code'] != '1' ) {
- $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
-
- return false;
- }
- }
-
- Wikimedia\restoreWarnings();
-
- if ( $explain_count > 0 ) {
- return $this->doQuery( 'SELECT id, cardinality "ROWS" FROM plan_table ' .
- 'WHERE statement_id = \'' . $explain_id . '\'' );
- } elseif ( oci_statement_type( $stmt ) == 'SELECT' ) {
- return new ORAResult( $this, $stmt, $union_unique );
- } else {
- $this->mAffectedRows = oci_num_rows( $stmt );
-
- return true;
- }
- }
-
- function queryIgnore( $sql, $fname = '' ) {
- return $this->query( $sql, $fname, true );
- }
-
- /**
- * Frees resources associated with the LOB descriptor
- * @param IResultWrapper|ORAResult $res
- */
- function freeResult( $res ) {
- ResultWrapper::unwrap( $res )->free();
- }
-
- /**
- * @param IResultWrapper|ORAResult $res
- * @return stdClass|bool
- */
- function fetchObject( $res ) {
- return ResultWrapper::unwrap( $res )->fetchObject();
- }
-
- /**
- * @param IResultWrapper|ORAResult $res
- * @return stdClass|bool
- */
- function fetchRow( $res ) {
- return ResultWrapper::unwrap( $res )->fetchRow();
- }
-
- /**
- * @param IResultWrapper|ORAResult $res
- * @return int
- */
- function numRows( $res ) {
- return ResultWrapper::unwrap( $res )->numRows();
- }
-
- /**
- * @param IResultWrapper|ORAResult $res
- * @return int
- */
- function numFields( $res ) {
- return ResultWrapper::unwrap( $res )->numFields();
- }
-
- function fieldName( $stmt, $n ) {
- return oci_field_name( $stmt, $n );
- }
-
- function insertId() {
- $res = $this->query( "SELECT lastval_pkg.getLastval FROM dual" );
- $row = $this->fetchRow( $res );
- return is_null( $row[0] ) ? null : (int)$row[0];
- }
-
- /**
- * @param mixed $res
- * @param int $row
- */
- function dataSeek( $res, $row ) {
- if ( $res instanceof ORAResult ) {
- $res->seek( $row );
- } else {
- ResultWrapper::unwrap( $res )->seek( $row );
- }
- }
-
- function lastError() {
- if ( $this->conn === false ) {
- $e = oci_error();
- } else {
- $e = oci_error( $this->conn );
- }
-
- return $e['message'];
- }
-
- function lastErrno() {
- if ( $this->conn === false ) {
- $e = oci_error();
- } else {
- $e = oci_error( $this->conn );
- }
-
- return $e['code'];
- }
-
- protected function fetchAffectedRowCount() {
- return $this->mAffectedRows;
- }
-
- /**
- * Returns information about an index
- * If errors are explicitly ignored, returns NULL on failure
- * @param string $table
- * @param string $index
- * @param string $fname
- * @return bool
- */
- function indexInfo( $table, $index, $fname = __METHOD__ ) {
- return false;
- }
-
- function indexUnique( $table, $index, $fname = __METHOD__ ) {
- return false;
- }
-
- function insert( $table, $a, $fname = __METHOD__, $options = [] ) {
- if ( !count( $a ) ) {
- return true;
- }
-
- if ( !is_array( $options ) ) {
- $options = [ $options ];
- }
-
- if ( in_array( 'IGNORE', $options ) ) {
- $this->ignoreDupValOnIndex = true;
- }
-
- if ( !is_array( reset( $a ) ) ) {
- $a = [ $a ];
- }
-
- foreach ( $a as &$row ) {
- $this->insertOneRow( $table, $row, $fname );
- }
-
- if ( in_array( 'IGNORE', $options ) ) {
- $this->ignoreDupValOnIndex = false;
- }
-
- return true;
- }
-
- private function fieldBindStatement( $table, $col, &$val, $includeCol = false ) {
- $col_info = $this->fieldInfoMulti( $table, $col );
- $col_type = $col_info != false ? $col_info->type() : 'CONSTANT';
-
- $bind = '';
- if ( is_numeric( $col ) ) {
- $bind = $val;
- $val = null;
-
- return $bind;
- } elseif ( $includeCol ) {
- $bind = "$col = ";
- }
-
- if ( $val == '' && $val !== 0 && $col_type != 'BLOB' && $col_type != 'CLOB' ) {
- $val = null;
- }
-
- if ( $val === 'NULL' ) {
- $val = null;
- }
-
- if ( $val === null ) {
- if (
- $col_info != false &&
- $col_info->isNullable() == 0 &&
- $col_info->defaultValue() != null
- ) {
- $bind .= 'DEFAULT';
- } else {
- $bind .= 'NULL';
- }
- } else {
- $bind .= ':' . $col;
- }
-
- return $bind;
- }
-
- /**
- * @param string $table
- * @param array $row
- * @param string $fname
- * @return bool
- * @throws DBUnexpectedError
- */
- private function insertOneRow( $table, $row, $fname ) {
- $table = $this->tableName( $table );
- // "INSERT INTO tables (a, b, c)"
- $sql = "INSERT INTO " . $table . " (" . implode( ',', array_keys( $row ) ) . ')';
- $sql .= " VALUES (";
-
- // for each value, append ":key"
- $first = true;
- foreach ( $row as $col => &$val ) {
- if ( !$first ) {
- $sql .= ', ';
- } else {
- $first = false;
- }
- if ( $this->isQuotedIdentifier( $val ) ) {
- $sql .= $this->removeIdentifierQuotes( $val );
- unset( $row[$col] );
- } else {
- $sql .= $this->fieldBindStatement( $table, $col, $val );
- }
- }
- $sql .= ')';
-
- $this->mLastResult = $stmt = oci_parse( $this->conn, $sql );
- if ( $stmt === false ) {
- $e = oci_error( $this->conn );
- $this->reportQueryError( $e['message'], $e['code'], $sql, $fname );
-
- return false;
- }
- foreach ( $row as $col => &$val ) {
- $col_info = $this->fieldInfoMulti( $table, $col );
- $col_type = $col_info != false ? $col_info->type() : 'CONSTANT';
-
- if ( $val === null ) {
- // do nothing ... null was inserted in statement creation
- } elseif ( $col_type != 'BLOB' && $col_type != 'CLOB' ) {
- if ( is_object( $val ) ) {
- $val = $val->fetch();
- }
-
- // backward compatibility
- if (
- preg_match( '/^timestamp.*/i', $col_type ) == 1 &&
- strtolower( $val ) == 'infinity'
- ) {
- $val = $this->getInfinity();
- }
-
- $val = $this->getVerifiedUTF8( $val );
- if ( oci_bind_by_name( $stmt, ":$col", $val, -1, SQLT_CHR ) === false ) {
- $e = oci_error( $stmt );
- $this->reportQueryError( $e['message'], $e['code'], $sql, $fname );
-
- return false;
- }
- } else {
- /** @var OCI_Lob[] $lob */
- $lob[$col] = oci_new_descriptor( $this->conn, OCI_D_LOB );
- if ( $lob[$col] === false ) {
- $e = oci_error( $stmt );
- throw new DBUnexpectedError(
- $this,
- "Cannot create LOB descriptor: " . $e['message']
- );
- }
-
- if ( is_object( $val ) ) {
- $val = $val->fetch();
- }
-
- if ( $col_type == 'BLOB' ) {
- $lob[$col]->writeTemporary( $val, OCI_TEMP_BLOB );
- oci_bind_by_name( $stmt, ":$col", $lob[$col], -1, OCI_B_BLOB );
- } else {
- $lob[$col]->writeTemporary( $val, OCI_TEMP_CLOB );
- oci_bind_by_name( $stmt, ":$col", $lob[$col], -1, OCI_B_CLOB );
- }
- }
- }
-
- Wikimedia\suppressWarnings();
-
- if ( oci_execute( $stmt, $this->execFlags() ) === false ) {
- $e = oci_error( $stmt );
- if ( !$this->ignoreDupValOnIndex || $e['code'] != '1' ) {
- $this->reportQueryError( $e['message'], $e['code'], $sql, $fname );
-
- return false;
- } else {
- $this->mAffectedRows = oci_num_rows( $stmt );
- }
- } else {
- $this->mAffectedRows = oci_num_rows( $stmt );
- }
-
- Wikimedia\restoreWarnings();
-
- if ( isset( $lob ) ) {
- foreach ( $lob as $lob_v ) {
- $lob_v->free();
- }
- }
-
- if ( !$this->trxLevel() ) {
- oci_commit( $this->conn );
- }
-
- return oci_free_statement( $stmt );
- }
-
- function nativeInsertSelect( $destTable, $srcTable, $varMap, $conds, $fname = __METHOD__,
- $insertOptions = [], $selectOptions = [], $selectJoinConds = []
- ) {
- $destTable = $this->tableName( $destTable );
-
- $sequenceData = $this->getSequenceData( $destTable );
- if ( $sequenceData !== false &&
- !isset( $varMap[$sequenceData['column']] )
- ) {
- $varMap[$sequenceData['column']] =
- 'GET_SEQUENCE_VALUE(\'' . $sequenceData['sequence'] . '\')';
- }
-
- // count-alias subselect fields to avoid abigious definition errors
- $i = 0;
- foreach ( $varMap as &$val ) {
- $val .= ' field' . $i;
- $i++;
- }
-
- $selectSql = $this->selectSQLText(
- $srcTable,
- array_values( $varMap ),
- $conds,
- $fname,
- $selectOptions,
- $selectJoinConds
- );
-
- $sql = "INSERT INTO $destTable (" .
- implode( ',', array_keys( $varMap ) ) . ') ' . $selectSql;
-
- if ( in_array( 'IGNORE', $insertOptions ) ) {
- $this->ignoreDupValOnIndex = true;
- }
-
- $this->query( $sql, $fname );
-
- if ( in_array( 'IGNORE', $insertOptions ) ) {
- $this->ignoreDupValOnIndex = false;
- }
- }
-
- public function upsert( $table, array $rows, $uniqueIndexes, array $set,
- $fname = __METHOD__
- ) {
- if ( $rows === [] ) {
- return true; // nothing to do
- }
-
- if ( !is_array( reset( $rows ) ) ) {
- $rows = [ $rows ];
- }
-
- $sequenceData = $this->getSequenceData( $table );
- if ( $sequenceData !== false ) {
- // add sequence column to each list of columns, when not set
- foreach ( $rows as &$row ) {
- if ( !isset( $row[$sequenceData['column']] ) ) {
- $row[$sequenceData['column']] =
- $this->addIdentifierQuotes( 'GET_SEQUENCE_VALUE(\'' .
- $sequenceData['sequence'] . '\')' );
- }
- }
- }
-
- return parent::upsert( $table, $rows, $uniqueIndexes, $set, $fname );
- }
-
- public function tableName( $name, $format = 'quoted' ) {
- // Replace reserved words with better ones
- $name = $this->remappedTableName( $name );
-
- return strtoupper( parent::tableName( $name, $format ) );
- }
-
- /**
- * @param string $name
- * @return string Value of $name or remapped name if $name is a reserved keyword
- */
- public function remappedTableName( $name ) {
- return $this->keywordTableMap[$name] ?? $name;
- }
-
- function tableNameInternal( $name ) {
- $name = $this->tableName( $name );
-
- return preg_replace( '/.*\.(.*)/', '$1', $name );
- }
-
- /**
- * Return sequence_name if table has a sequence
- *
- * @param string $table
- * @return string[]|bool
- */
- private function getSequenceData( $table ) {
- if ( $this->sequenceData == null ) {
- $dbname = $this->currentDomain->getDatabase();
- $prefix = $this->currentDomain->getTablePrefix();
- // See https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions040.htm
- $decodeArgs = [ 'atc.table_name' ]; // the switch
- foreach ( $this->keywordTableMap as $reserved => $alternative ) {
- $search = strtoupper( $prefix . $alternative ); // case
- $replace = strtoupper( $prefix . $reserved ); // result
- $decodeArgs[] = $this->addQuotes( $search );
- $decodeArgs[] = $this->addQuotes( $replace );
- }
- $decodeArgs[] = [ 'atc.table_name' ]; // default
- $decodeArgs = implode( ', ', $decodeArgs );
-
- $result = $this->doQuery(
- "SELECT lower(asq.sequence_name), lower(atc.table_name), lower(atc.column_name)
- FROM all_sequences asq, all_tab_columns atc
- WHERE decode({$decodeArgs}) || '_' ||
- atc.column_name || '_SEQ' = '{$prefix}' || asq.sequence_name
- AND asq.sequence_owner = upper('{$dbname}')
- AND atc.owner = upper('{$dbname}')"
- );
-
- while ( ( $row = $result->fetchRow() ) !== false ) {
- $this->sequenceData[$row[1]] = [
- 'sequence' => $row[0],
- 'column' => $row[2]
- ];
- }
- }
- $table = strtolower( $this->removeIdentifierQuotes( $this->tableName( $table ) ) );
-
- return $this->sequenceData[$table] ?? false;
- }
-
- /**
- * Returns the size of a text field, or -1 for "unlimited"
- *
- * @param string $table
- * @param string $field
- * @return mixed
- */
- function textFieldSize( $table, $field ) {
- $fieldInfoData = $this->fieldInfo( $table, $field );
-
- return $fieldInfoData->maxLength();
- }
-
- function limitResult( $sql, $limit, $offset = false ) {
- if ( $offset === false ) {
- $offset = 0;
- }
-
- return "SELECT * FROM ($sql) WHERE rownum >= (1 + $offset) AND rownum < (1 + $limit + $offset)";
- }
-
- function encodeBlob( $b ) {
- return new Blob( $b );
- }
-
- function unionQueries( $sqls, $all ) {
- $glue = ' UNION ALL ';
-
- return 'SELECT * ' . ( $all ? '' : '/* UNION_UNIQUE */ ' ) .
- 'FROM (' . implode( $glue, $sqls ) . ')';
- }
-
- function wasDeadlock() {
- return $this->lastErrno() == 'OCI-00060';
- }
-
- function duplicateTableStructure( $oldName, $newName, $temporary = false,
- $fname = __METHOD__
- ) {
- $temporary = $temporary ? 'TRUE' : 'FALSE';
- $tablePrefix = $this->currentDomain->getTablePrefix();
-
- $newName = strtoupper( $newName );
- $oldName = strtoupper( $oldName );
-
- $tabName = substr( $newName, strlen( $tablePrefix ) );
- $oldPrefix = substr( $oldName, 0, strlen( $oldName ) - strlen( $tabName ) );
- $newPrefix = strtoupper( $tablePrefix );
-
- return $this->doQuery( "BEGIN DUPLICATE_TABLE( '$tabName', " .
- "'$oldPrefix', '$newPrefix', $temporary ); END;" );
- }
-
- function listTables( $prefix = null, $fname = __METHOD__ ) {
- $listWhere = '';
- if ( !empty( $prefix ) ) {
- $listWhere = ' AND table_name LIKE \'' . strtoupper( $prefix ) . '%\'';
- }
-
- $owner = strtoupper( $this->getDBname() );
- $result = $this->doQuery( "SELECT table_name FROM all_tables " .
- "WHERE owner='$owner' AND table_name NOT LIKE '%!_IDX\$_' ESCAPE '!' $listWhere" );
-
- // dirty code ... i know
- $endArray = [];
- $endArray[] = strtoupper( $prefix . 'MWUSER' );
- $endArray[] = strtoupper( $prefix . 'PAGE' );
- $endArray[] = strtoupper( $prefix . 'IMAGE' );
- $fixedOrderTabs = $endArray;
- while ( ( $row = $result->fetchRow() ) !== false ) {
- if ( !in_array( $row['table_name'], $fixedOrderTabs ) ) {
- $endArray[] = $row['table_name'];
- }
- }
-
- return $endArray;
- }
-
- public function dropTable( $tableName, $fName = __METHOD__ ) {
- $tableName = $this->tableName( $tableName );
- if ( !$this->tableExists( $tableName ) ) {
- return false;
- }
-
- return $this->doQuery( "DROP TABLE $tableName CASCADE CONSTRAINTS PURGE" );
- }
-
- public function timestamp( $ts = 0 ) {
- $t = new ConvertibleTimestamp( $ts );
- // Let errors bubble up to avoid putting garbage in the DB
- return $t->getTimestamp( TS_ORACLE );
- }
-
- /**
- * Return aggregated value function call
- *
- * @param array $valuedata
- * @param string $valuename
- * @return mixed
- */
- public function aggregateValue( $valuedata, $valuename = 'value' ) {
- return $valuedata;
- }
-
- /**
- * @return string Wikitext of a link to the server software's web site
- */
- public function getSoftwareLink() {
- return '[{{int:version-db-oracle-url}} Oracle]';
- }
-
- /**
- * @return string Version information from the database
- */
- function getServerVersion() {
- // better version number, fallback on driver
- $rset = $this->doQuery(
- 'SELECT version FROM product_component_version ' .
- 'WHERE UPPER(product) LIKE \'ORACLE DATABASE%\''
- );
- $row = $rset->fetchRow();
- if ( !$row ) {
- return oci_server_version( $this->conn );
- }
-
- return $row['version'];
- }
-
- /**
- * Query whether a given index exists
- * @param string $table
- * @param string $index
- * @param string $fname
- * @return bool
- */
- function indexExists( $table, $index, $fname = __METHOD__ ) {
- $table = $this->tableName( $table );
- $table = strtoupper( $this->removeIdentifierQuotes( $table ) );
- $index = strtoupper( $index );
- $owner = strtoupper( $this->getDBname() );
- $sql = "SELECT 1 FROM all_indexes WHERE owner='$owner' AND index_name='{$table}_{$index}'";
- $res = $this->doQuery( $sql );
- if ( $res ) {
- $count = $res->numRows();
- $res->free();
- } else {
- $count = 0;
- }
-
- return $count != 0;
- }
-
- /**
- * Query whether a given table exists (in the given schema, or the default mw one if not given)
- * @param string $table
- * @param string $fname
- * @return bool
- */
- function tableExists( $table, $fname = __METHOD__ ) {
- $table = $this->tableName( $table );
- $table = $this->addQuotes( strtoupper( $this->removeIdentifierQuotes( $table ) ) );
- $owner = $this->addQuotes( strtoupper( $this->getDBname() ) );
- $sql = "SELECT 1 FROM all_tables WHERE owner=$owner AND table_name=$table";
- $res = $this->doQuery( $sql );
- if ( $res && $res->numRows() > 0 ) {
- $exists = true;
- } else {
- $exists = false;
- }
-
- $res->free();
-
- return $exists;
- }
-
- /**
- * Function translates mysql_fetch_field() functionality on ORACLE.
- * Caching is present for reducing query time.
- * For internal calls. Use fieldInfo for normal usage.
- * Returns false if the field doesn't exist
- *
- * @param array|string $table
- * @param string $field
- * @return ORAField|ORAResult|false
- */
- private function fieldInfoMulti( $table, $field ) {
- $field = strtoupper( $field );
- if ( is_array( $table ) ) {
- $table = array_map( [ $this, 'tableNameInternal' ], $table );
- $tableWhere = 'IN (';
- foreach ( $table as &$singleTable ) {
- $singleTable = $this->removeIdentifierQuotes( $singleTable );
- if ( isset( $this->mFieldInfoCache["$singleTable.$field"] ) ) {
- return $this->mFieldInfoCache["$singleTable.$field"];
- }
- $tableWhere .= '\'' . $singleTable . '\',';
- }
- $tableWhere = rtrim( $tableWhere, ',' ) . ')';
- } else {
- $table = $this->removeIdentifierQuotes( $this->tableNameInternal( $table ) );
- if ( isset( $this->mFieldInfoCache["$table.$field"] ) ) {
- return $this->mFieldInfoCache["$table.$field"];
- }
- $tableWhere = '= \'' . $table . '\'';
- }
-
- $fieldInfoStmt = oci_parse(
- $this->conn,
- 'SELECT * FROM wiki_field_info_full WHERE table_name ' .
- $tableWhere . ' and column_name = \'' . $field . '\''
- );
- if ( oci_execute( $fieldInfoStmt, $this->execFlags() ) === false ) {
- $e = oci_error( $fieldInfoStmt );
- $this->reportQueryError( $e['message'], $e['code'], 'fieldInfo QUERY', __METHOD__ );
-
- return false;
- }
- $res = new ORAResult( $this, $fieldInfoStmt );
- if ( $res->numRows() == 0 ) {
- if ( is_array( $table ) ) {
- foreach ( $table as &$singleTable ) {
- $this->mFieldInfoCache["$singleTable.$field"] = false;
- }
- } else {
- $this->mFieldInfoCache["$table.$field"] = false;
- }
- $fieldInfoTemp = null;
- } else {
- $fieldInfoTemp = new ORAField( $res->fetchRow() );
- $table = $fieldInfoTemp->tableName();
- $this->mFieldInfoCache["$table.$field"] = $fieldInfoTemp;
- }
- $res->free();
-
- return $fieldInfoTemp;
- }
-
- /**
- * @throws DBUnexpectedError
- * @param string $table
- * @param string $field
- * @return ORAField
- */
- function fieldInfo( $table, $field ) {
- if ( is_array( $table ) ) {
- throw new DBUnexpectedError(
- $this,
- 'DatabaseOracle::fieldInfo called with table array!'
- );
- }
-
- return $this->fieldInfoMulti( $table, $field );
- }
-
- protected function doBegin( $fname = __METHOD__ ) {
- $this->query( 'SET CONSTRAINTS ALL DEFERRED' );
- }
-
- protected function doCommit( $fname = __METHOD__ ) {
- if ( $this->trxLevel() ) {
- $ret = oci_commit( $this->conn );
- if ( !$ret ) {
- throw new DBUnexpectedError( $this, $this->lastError() );
- }
- $this->query( 'SET CONSTRAINTS ALL IMMEDIATE' );
- }
- }
-
- protected function doRollback( $fname = __METHOD__ ) {
- if ( $this->trxLevel() ) {
- oci_rollback( $this->conn );
- $ignoreErrors = true;
- $this->query( 'SET CONSTRAINTS ALL IMMEDIATE', $fname, $ignoreErrors );
- }
- }
-
- function sourceStream(
- $fp,
- callable $lineCallback = null,
- callable $resultCallback = null,
- $fname = __METHOD__, callable $inputCallback = null
- ) {
- $cmd = '';
- $done = false;
- $dollarquote = false;
-
- $replacements = [];
- // Defines must comply with ^define\s*([^\s=]*)\s*=\s?'\{\$([^\}]*)\}';
- while ( !feof( $fp ) ) {
- if ( $lineCallback ) {
- $lineCallback();
- }
- $line = trim( fgets( $fp, 1024 ) );
- $sl = strlen( $line ) - 1;
-
- if ( $sl < 0 ) {
- continue;
- }
- if ( $line[0] == '-' && $line[1] == '-' ) {
- continue;
- }
-
- // Allow dollar quoting for function declarations
- if ( substr( $line, 0, 8 ) == '/*$mw$*/' ) {
- if ( $dollarquote ) {
- $dollarquote = false;
- $line = str_replace( '/*$mw$*/', '', $line ); // remove dollarquotes
- $done = true;
- } else {
- $dollarquote = true;
- }
- } elseif ( !$dollarquote ) {
- if ( $line[$sl] == ';' && ( $sl < 2 || $line[$sl - 1] != ';' ) ) {
- $done = true;
- $line = substr( $line, 0, $sl );
- }
- }
-
- if ( $cmd != '' ) {
- $cmd .= ' ';
- }
- $cmd .= "$line\n";
-
- if ( $done ) {
- $cmd = str_replace( ';;', ";", $cmd );
- if ( strtolower( substr( $cmd, 0, 6 ) ) == 'define' ) {
- if ( preg_match( '/^define\s*([^\s=]*)\s*=\s*\'\{\$([^\}]*)\}\'/', $cmd, $defines ) ) {
- $replacements[$defines[2]] = $defines[1];
- }
- } else {
- foreach ( $replacements as $mwVar => $scVar ) {
- $cmd = str_replace( '&' . $scVar . '.', '`{$' . $mwVar . '}`', $cmd );
- }
-
- $cmd = $this->replaceVars( $cmd );
- if ( $inputCallback ) {
- $inputCallback( $cmd );
- }
- $res = $this->doQuery( $cmd );
- if ( $resultCallback ) {
- call_user_func( $resultCallback, $res, $this );
- }
-
- if ( $res === false ) {
- $err = $this->lastError();
-
- return "Query \"{$cmd}\" failed with error code \"$err\".\n";
- }
- }
-
- $cmd = '';
- $done = false;
- }
- }
-
- return true;
- }
-
- protected function doSelectDomain( DatabaseDomain $domain ) {
- if ( $domain->getSchema() !== null ) {
- // We use the *database* aspect of $domain for schema, not the domain schema
- throw new DBExpectedError(
- $this,
- __CLASS__ . ": domain '{$domain->getId()}' has a schema component; " .
- "the database component is actually interpreted as the Oracle schema."
- );
- }
-
- $database = $domain->getDatabase();
- if ( $database === null || $database === $this->user ) {
- // Backward compatibility
- $this->currentDomain = $domain;
-
- return true;
- }
-
- // https://docs.oracle.com/javadb/10.8.3.0/ref/rrefsqlj32268.html
- $encDatabase = $this->addIdentifierQuotes( strtoupper( $database ) );
- $sql = "ALTER SESSION SET CURRENT_SCHEMA=$encDatabase";
- $stmt = oci_parse( $this->conn, $sql );
- Wikimedia\suppressWarnings();
- $success = oci_execute( $stmt );
- Wikimedia\restoreWarnings();
- if ( $success ) {
- // Update that domain fields on success (no exception thrown)
- $this->currentDomain = $domain;
- } else {
- $e = oci_error( $stmt );
- $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
- }
-
- return true;
- }
-
- function strencode( $s ) {
- return str_replace( "'", "''", $s );
- }
-
- function addQuotes( $s ) {
- return "'" . $this->strencode( $this->getVerifiedUTF8( $s ) ) . "'";
- }
-
- public function addIdentifierQuotes( $s ) {
- if ( !$this->getFlag( DBO_DDLMODE ) ) {
- $s = '/*Q*/' . $s;
- }
-
- return $s;
- }
-
- public function removeIdentifierQuotes( $s ) {
- return strpos( $s, '/*Q*/' ) === false ? $s : substr( $s, 5 );
- }
-
- public function isQuotedIdentifier( $s ) {
- return strpos( $s, '/*Q*/' ) !== false;
- }
-
- private function wrapFieldForWhere( $table, &$col, &$val ) {
- $col_info = $this->fieldInfoMulti( $table, $col );
- $col_type = $col_info != false ? $col_info->type() : 'CONSTANT';
- if ( $col_type == 'CLOB' ) {
- $col = 'TO_CHAR(' . $col . ')';
- $val = $this->getVerifiedUTF8( $val );
- } elseif ( $col_type == 'VARCHAR2' ) {
- $val = $this->getVerifiedUTF8( $val );
- }
- }
-
- private function wrapConditionsForWhere( $table, $conds, $parentCol = null ) {
- $conds2 = [];
- foreach ( $conds as $col => $val ) {
- if ( is_array( $val ) ) {
- $conds2[$col] = $this->wrapConditionsForWhere( $table, $val, $col );
- } else {
- if ( is_numeric( $col ) && $parentCol != null ) {
- $this->wrapFieldForWhere( $table, $parentCol, $val );
- } else {
- $this->wrapFieldForWhere( $table, $col, $val );
- }
- $conds2[$col] = $val;
- }
- }
-
- return $conds2;
- }
-
- function selectRow( $table, $vars, $conds, $fname = __METHOD__,
- $options = [], $join_conds = []
- ) {
- if ( is_array( $conds ) ) {
- $conds = $this->wrapConditionsForWhere( $table, $conds );
- }
-
- return parent::selectRow( $table, $vars, $conds, $fname, $options, $join_conds );
- }
-
- /**
- * Returns an optional USE INDEX clause to go after the table, and a
- * string to go at the end of the query
- *
- * @param array $options 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 = [];
- foreach ( $options as $key => $option ) {
- if ( is_numeric( $key ) ) {
- $noKeyOptions[$option] = true;
- }
- }
-
- $preLimitTail .= $this->makeGroupByWithHaving( $options );
-
- $preLimitTail .= $this->makeOrderBy( $options );
-
- if ( isset( $noKeyOptions['FOR UPDATE'] ) ) {
- $postLimitTail .= ' FOR UPDATE';
- }
-
- if ( isset( $noKeyOptions['DISTINCT'] ) || isset( $noKeyOptions['DISTINCTROW'] ) ) {
- $startOpts .= 'DISTINCT';
- }
-
- if ( isset( $options['USE INDEX'] ) && !is_array( $options['USE INDEX'] ) ) {
- $useIndex = $this->useIndexClause( $options['USE INDEX'] );
- } else {
- $useIndex = '';
- }
-
- if ( isset( $options['IGNORE INDEX'] ) && !is_array( $options['IGNORE INDEX'] ) ) {
- $ignoreIndex = $this->ignoreIndexClause( $options['IGNORE INDEX'] );
- } else {
- $ignoreIndex = '';
- }
-
- return [ $startOpts, $useIndex, $preLimitTail, $postLimitTail, $ignoreIndex ];
- }
-
- public function delete( $table, $conds, $fname = __METHOD__ ) {
- global $wgActorTableSchemaMigrationStage;
-
- if ( is_array( $conds ) ) {
- $conds = $this->wrapConditionsForWhere( $table, $conds );
- }
- // a hack for deleting pages, users and images (which have non-nullable FKs)
- // all deletions on these tables have transactions so final failure rollbacks these updates
- // @todo: Normalize the schema to match MySQL, no special FKs and such
- $table = $this->tableName( $table );
- if ( $table == $this->tableName( 'user' ) &&
- ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_OLD )
- ) {
- $this->update( 'archive', [ 'ar_user' => 0 ],
- [ 'ar_user' => $conds['user_id'] ], $fname );
- $this->update( 'ipblocks', [ 'ipb_user' => 0 ],
- [ 'ipb_user' => $conds['user_id'] ], $fname );
- $this->update( 'image', [ 'img_user' => 0 ],
- [ 'img_user' => $conds['user_id'] ], $fname );
- $this->update( 'oldimage', [ 'oi_user' => 0 ],
- [ 'oi_user' => $conds['user_id'] ], $fname );
- $this->update( 'filearchive', [ 'fa_deleted_user' => 0 ],
- [ 'fa_deleted_user' => $conds['user_id'] ], $fname );
- $this->update( 'filearchive', [ 'fa_user' => 0 ],
- [ 'fa_user' => $conds['user_id'] ], $fname );
- $this->update( 'uploadstash', [ 'us_user' => 0 ],
- [ 'us_user' => $conds['user_id'] ], $fname );
- $this->update( 'recentchanges', [ 'rc_user' => 0 ],
- [ 'rc_user' => $conds['user_id'] ], $fname );
- $this->update( 'logging', [ 'log_user' => 0 ],
- [ 'log_user' => $conds['user_id'] ], $fname );
- } elseif ( $table == $this->tableName( 'image' ) ) {
- $this->update( 'oldimage', [ 'oi_name' => 0 ],
- [ 'oi_name' => $conds['img_name'] ], $fname );
- }
-
- return parent::delete( $table, $conds, $fname );
- }
-
- /**
- * @param string $table
- * @param array $values
- * @param array $conds
- * @param string $fname
- * @param array $options
- * @return bool
- * @throws DBUnexpectedError
- */
- function update( $table, $values, $conds, $fname = __METHOD__, $options = [] ) {
- $table = $this->tableName( $table );
- $opts = $this->makeUpdateOptions( $options );
- $sql = "UPDATE $opts $table SET ";
-
- $first = true;
- foreach ( $values as $col => &$val ) {
- $sqlSet = $this->fieldBindStatement( $table, $col, $val, true );
-
- if ( !$first ) {
- $sqlSet = ', ' . $sqlSet;
- } else {
- $first = false;
- }
- $sql .= $sqlSet;
- }
-
- if ( $conds !== [] && $conds !== '*' ) {
- $conds = $this->wrapConditionsForWhere( $table, $conds );
- $sql .= ' WHERE ' . $this->makeList( $conds, LIST_AND );
- }
-
- $this->mLastResult = $stmt = oci_parse( $this->conn, $sql );
- if ( $stmt === false ) {
- $e = oci_error( $this->conn );
- $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
-
- return false;
- }
- foreach ( $values as $col => &$val ) {
- $col_info = $this->fieldInfoMulti( $table, $col );
- $col_type = $col_info != false ? $col_info->type() : 'CONSTANT';
-
- if ( $val === null ) {
- // do nothing ... null was inserted in statement creation
- } elseif ( $col_type != 'BLOB' && $col_type != 'CLOB' ) {
- if ( is_object( $val ) ) {
- $val = $val->getData();
- }
-
- if (
- preg_match( '/^timestamp.*/i', $col_type ) == 1 &&
- strtolower( $val ) == 'infinity'
- ) {
- $val = '31-12-2030 12:00:00.000000';
- }
-
- $val = $this->getVerifiedUTF8( $val );
- if ( oci_bind_by_name( $stmt, ":$col", $val ) === false ) {
- $e = oci_error( $stmt );
- $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
-
- return false;
- }
- } else {
- /** @var OCI_Lob[] $lob */
- $lob[$col] = oci_new_descriptor( $this->conn, OCI_D_LOB );
- if ( $lob[$col] === false ) {
- $e = oci_error( $stmt );
- throw new DBUnexpectedError(
- $this,
- "Cannot create LOB descriptor: " . $e['message']
- );
- }
-
- if ( is_object( $val ) ) {
- $val = $val->getData();
- }
-
- if ( $col_type == 'BLOB' ) {
- $lob[$col]->writeTemporary( $val );
- oci_bind_by_name( $stmt, ":$col", $lob[$col], -1, SQLT_BLOB );
- } else {
- $lob[$col]->writeTemporary( $val );
- oci_bind_by_name( $stmt, ":$col", $lob[$col], -1, OCI_B_CLOB );
- }
- }
- }
-
- Wikimedia\suppressWarnings();
-
- if ( oci_execute( $stmt, $this->execFlags() ) === false ) {
- $e = oci_error( $stmt );
- if ( !$this->ignoreDupValOnIndex || $e['code'] != '1' ) {
- $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
-
- return false;
- } else {
- $this->mAffectedRows = oci_num_rows( $stmt );
- }
- } else {
- $this->mAffectedRows = oci_num_rows( $stmt );
- }
-
- Wikimedia\restoreWarnings();
-
- if ( isset( $lob ) ) {
- foreach ( $lob as $lob_v ) {
- $lob_v->free();
- }
- }
-
- if ( !$this->trxLevel() ) {
- oci_commit( $this->conn );
- }
-
- return oci_free_statement( $stmt );
- }
-
- function bitNot( $field ) {
- // expecting bit-fields smaller than 4bytes
- return 'BITNOT(' . $field . ')';
- }
-
- function bitAnd( $fieldLeft, $fieldRight ) {
- return 'BITAND(' . $fieldLeft . ', ' . $fieldRight . ')';
- }
-
- function bitOr( $fieldLeft, $fieldRight ) {
- return 'BITOR(' . $fieldLeft . ', ' . $fieldRight . ')';
- }
-
- public function buildGroupConcatField(
- $delim, $table, $field, $conds = '', $join_conds = []
- ) {
- $fld = "LISTAGG($field," . $this->addQuotes( $delim ) . ") WITHIN GROUP (ORDER BY $field)";
-
- return '(' . $this->selectSQLText( $table, $fld, $conds, null, [], $join_conds ) . ')';
- }
-
- public function buildSubstring( $input, $startPosition, $length = null ) {
- $this->assertBuildSubstringParams( $startPosition, $length );
- $params = [ $input, $startPosition ];
- if ( $length !== null ) {
- $params[] = $length;
- }
- return 'SUBSTR(' . implode( ',', $params ) . ')';
- }
-
- /**
- * @param string $field Field or column to cast
- * @return string
- * @since 1.28
- */
- public function buildStringCast( $field ) {
- return 'CAST ( ' . $field . ' AS VARCHAR2 )';
- }
-
- public function getInfinity() {
- return '31-12-2030 12:00:00.000000';
- }
-
- /**
- * @param string $s
- * @return string
- */
- private function getVerifiedUTF8( $s ) {
- if ( mb_check_encoding( (string)$s, 'UTF-8' ) ) {
- return $s; // valid
- }
-
- throw new DBUnexpectedError( $this, "Non BLOB/CLOB field must be UTF-8." );
- }
-}
protected static $dbTypes = [
'mysql',
'postgres',
- 'oracle',
- 'mssql',
'sqlite',
];
+++ /dev/null
-<?php
-/**
- * Microsoft SQL Server-specific installer.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Deployment
- */
-
-use Wikimedia\Rdbms\Database;
-use Wikimedia\Rdbms\DBQueryError;
-use Wikimedia\Rdbms\DBConnectionError;
-
-/**
- * Class for setting up the MediaWiki database using Microsoft SQL Server.
- *
- * @ingroup Deployment
- * @since 1.23
- */
-class MssqlInstaller extends DatabaseInstaller {
-
- protected $globalNames = [
- 'wgDBserver',
- 'wgDBname',
- 'wgDBuser',
- 'wgDBpassword',
- 'wgDBmwschema',
- 'wgDBprefix',
- 'wgDBWindowsAuthentication',
- ];
-
- protected $internalDefaults = [
- '_InstallUser' => 'sa',
- '_InstallWindowsAuthentication' => 'sqlauth',
- '_WebWindowsAuthentication' => 'sqlauth',
- ];
-
- // SQL Server 2005 RTM
- // @todo Are SQL Express version numbers different?)
- public static $minimumVersion = '9.00.1399';
- protected static $notMinimumVersionMessage = 'config-mssql-old';
-
- // These are schema-level privs
- // Note: the web user will be created will full permissions if possible, this permission
- // list is only used if we are unable to grant full permissions.
- public $webUserPrivs = [
- 'DELETE',
- 'INSERT',
- 'SELECT',
- 'UPDATE',
- 'EXECUTE',
- ];
-
- /**
- * @return string
- */
- public function getName() {
- return 'mssql';
- }
-
- /**
- * @return bool
- */
- public function isCompiled() {
- return self::checkExtension( 'sqlsrv' );
- }
-
- /**
- * @return string
- */
- public function getConnectForm() {
- if ( $this->getVar( '_InstallWindowsAuthentication' ) == 'windowsauth' ) {
- $displayStyle = 'display: none;';
- } else {
- $displayStyle = 'display: block;';
- }
-
- return $this->getTextBox(
- 'wgDBserver',
- 'config-db-host',
- [],
- $this->parent->getHelpBox( 'config-db-host-help' )
- ) .
- Html::openElement( 'fieldset' ) .
- Html::element( 'legend', [], wfMessage( 'config-db-wiki-settings' )->text() ) .
- $this->getTextBox( 'wgDBname', 'config-db-name', [ 'dir' => 'ltr' ],
- $this->parent->getHelpBox( 'config-db-name-help' ) ) .
- $this->getTextBox( 'wgDBmwschema', 'config-db-schema', [ 'dir' => 'ltr' ],
- $this->parent->getHelpBox( 'config-db-schema-help' ) ) .
- $this->getTextBox( 'wgDBprefix', 'config-db-prefix', [ 'dir' => 'ltr' ],
- $this->parent->getHelpBox( 'config-db-prefix-help' ) ) .
- Html::closeElement( 'fieldset' ) .
- Html::openElement( 'fieldset' ) .
- Html::element( 'legend', [], wfMessage( 'config-db-install-account' )->text() ) .
- $this->getRadioSet( [
- 'var' => '_InstallWindowsAuthentication',
- 'label' => 'config-mssql-auth',
- 'itemLabelPrefix' => 'config-mssql-',
- 'values' => [ 'sqlauth', 'windowsauth' ],
- 'itemAttribs' => [
- 'sqlauth' => [
- 'class' => 'showHideRadio',
- 'rel' => 'dbCredentialBox',
- ],
- 'windowsauth' => [
- 'class' => 'hideShowRadio',
- 'rel' => 'dbCredentialBox',
- ]
- ],
- 'help' => $this->parent->getHelpBox( 'config-mssql-install-auth' )
- ] ) .
- Html::openElement( 'div', [ 'id' => 'dbCredentialBox', 'style' => $displayStyle ] ) .
- $this->getTextBox(
- '_InstallUser',
- 'config-db-username',
- [ 'dir' => 'ltr' ],
- $this->parent->getHelpBox( 'config-db-install-username' )
- ) .
- $this->getPasswordBox(
- '_InstallPassword',
- 'config-db-password',
- [ 'dir' => 'ltr' ],
- $this->parent->getHelpBox( 'config-db-install-password' )
- ) .
- Html::closeElement( 'div' ) .
- Html::closeElement( 'fieldset' );
- }
-
- public function submitConnectForm() {
- // Get variables from the request.
- $newValues = $this->setVarsFromRequest( [
- 'wgDBserver',
- 'wgDBname',
- 'wgDBmwschema',
- 'wgDBprefix'
- ] );
-
- // Validate them.
- $status = Status::newGood();
- if ( !strlen( $newValues['wgDBserver'] ) ) {
- $status->fatal( 'config-missing-db-host' );
- }
- if ( !strlen( $newValues['wgDBname'] ) ) {
- $status->fatal( 'config-missing-db-name' );
- } elseif ( !preg_match( '/^[a-z0-9_]+$/i', $newValues['wgDBname'] ) ) {
- $status->fatal( 'config-invalid-db-name', $newValues['wgDBname'] );
- }
- if ( !preg_match( '/^[a-z0-9_]*$/i', $newValues['wgDBmwschema'] ) ) {
- $status->fatal( 'config-invalid-schema', $newValues['wgDBmwschema'] );
- }
- if ( !preg_match( '/^[a-z0-9_]*$/i', $newValues['wgDBprefix'] ) ) {
- $status->fatal( 'config-invalid-db-prefix', $newValues['wgDBprefix'] );
- }
- if ( !$status->isOK() ) {
- return $status;
- }
-
- // Check for blank schema and remap to dbo
- if ( $newValues['wgDBmwschema'] === '' ) {
- $this->setVar( 'wgDBmwschema', 'dbo' );
- }
-
- // User box
- $this->setVarsFromRequest( [
- '_InstallUser',
- '_InstallPassword',
- '_InstallWindowsAuthentication'
- ] );
-
- // Try to connect
- $status = $this->getConnection();
- if ( !$status->isOK() ) {
- return $status;
- }
- /**
- * @var Database $conn
- */
- $conn = $status->value;
-
- // Check version
- return static::meetsMinimumRequirement( $conn->getServerVersion() );
- }
-
- /**
- * @return Status
- */
- public function openConnection() {
- global $wgDBWindowsAuthentication;
- $status = Status::newGood();
- $user = $this->getVar( '_InstallUser' );
- $password = $this->getVar( '_InstallPassword' );
-
- if ( $this->getVar( '_InstallWindowsAuthentication' ) == 'windowsauth' ) {
- // Use Windows authentication for this connection
- $wgDBWindowsAuthentication = true;
- } else {
- $wgDBWindowsAuthentication = false;
- }
-
- try {
- /** @var DatabaseMssql $db */
- $db = Database::factory( 'mssql', [
- 'host' => $this->getVar( 'wgDBserver' ),
- 'port' => $this->getVar( 'wgDBport' ),
- 'user' => $user,
- 'password' => $password,
- 'dbname' => false,
- 'flags' => 0,
- 'schema' => $this->getVar( 'wgDBmwschema' ),
- 'tablePrefix' => $this->getVar( 'wgDBprefix' ) ] );
- $db->prepareStatements( false );
- $db->scrollableCursor( false );
- $status->value = $db;
- } catch ( DBConnectionError $e ) {
- $status->fatal( 'config-connection-error', $e->getMessage() );
- }
-
- return $status;
- }
-
- public function preUpgrade() {
- global $wgDBuser, $wgDBpassword;
-
- $status = $this->getConnection();
- if ( !$status->isOK() ) {
- $this->parent->showStatusMessage( $status );
-
- return;
- }
- /**
- * @var Database $conn
- */
- $conn = $status->value;
- $conn->selectDB( $this->getVar( 'wgDBname' ) );
-
- # Normal user and password are selected after this step, so for now
- # just copy these two
- $wgDBuser = $this->getVar( '_InstallUser' );
- $wgDBpassword = $this->getVar( '_InstallPassword' );
- }
-
- /**
- * Return true if the install user can create accounts
- *
- * @return bool
- */
- public function canCreateAccounts() {
- $status = $this->getConnection();
- if ( !$status->isOK() ) {
- return false;
- }
- /** @var Database $conn */
- $conn = $status->value;
-
- // We need the server-level ALTER ANY LOGIN permission to create new accounts
- $res = $conn->query( "SELECT permission_name FROM sys.fn_my_permissions( NULL, 'SERVER' )" );
- $serverPrivs = [
- 'ALTER ANY LOGIN' => false,
- 'CONTROL SERVER' => false,
- ];
-
- foreach ( $res as $row ) {
- $serverPrivs[$row->permission_name] = true;
- }
-
- if ( !$serverPrivs['ALTER ANY LOGIN'] ) {
- return false;
- }
-
- // Check to ensure we can grant everything needed as well
- // We can't actually tell if we have WITH GRANT OPTION for a given permission, so we assume we do
- // and just check for the permission
- // https://technet.microsoft.com/en-us/library/ms178569.aspx
- // The following array sets up which permissions imply whatever permissions we specify
- $implied = [
- // schema database server
- 'DELETE' => [ 'DELETE', 'CONTROL SERVER' ],
- 'EXECUTE' => [ 'EXECUTE', 'CONTROL SERVER' ],
- 'INSERT' => [ 'INSERT', 'CONTROL SERVER' ],
- 'SELECT' => [ 'SELECT', 'CONTROL SERVER' ],
- 'UPDATE' => [ 'UPDATE', 'CONTROL SERVER' ],
- ];
-
- $grantOptions = array_flip( $this->webUserPrivs );
-
- // Check for schema and db-level permissions, but only if the schema/db exists
- $schemaPrivs = $dbPrivs = [
- 'DELETE' => false,
- 'EXECUTE' => false,
- 'INSERT' => false,
- 'SELECT' => false,
- 'UPDATE' => false,
- ];
-
- $dbPrivs['ALTER ANY USER'] = false;
-
- if ( $this->databaseExists( $this->getVar( 'wgDBname' ) ) ) {
- $conn->selectDB( $this->getVar( 'wgDBname' ) );
- $res = $conn->query( "SELECT permission_name FROM sys.fn_my_permissions( NULL, 'DATABASE' )" );
-
- foreach ( $res as $row ) {
- $dbPrivs[$row->permission_name] = true;
- }
-
- // If the db exists, we need ALTER ANY USER privs on it to make a new user
- if ( !$dbPrivs['ALTER ANY USER'] ) {
- return false;
- }
-
- if ( $this->schemaExists( $this->getVar( 'wgDBmwschema' ) ) ) {
- // wgDBmwschema is validated to only contain alphanumeric + underscore, so this is safe
- $res = $conn->query( "SELECT permission_name FROM sys.fn_my_permissions( "
- . "'{$this->getVar( 'wgDBmwschema' )}', 'SCHEMA' )" );
-
- foreach ( $res as $row ) {
- $schemaPrivs[$row->permission_name] = true;
- }
- }
- }
-
- // Now check all the grants we'll need to be doing to see if we can
- foreach ( $this->webUserPrivs as $permission ) {
- if ( ( isset( $schemaPrivs[$permission] ) && $schemaPrivs[$permission] )
- || ( isset( $dbPrivs[$implied[$permission][0]] )
- && $dbPrivs[$implied[$permission][0]] )
- || ( isset( $serverPrivs[$implied[$permission][1]] )
- && $serverPrivs[$implied[$permission][1]] )
- ) {
- unset( $grantOptions[$permission] );
- }
- }
-
- if ( count( $grantOptions ) ) {
- // Can't grant everything
- return false;
- }
-
- return true;
- }
-
- /**
- * @return string
- */
- public function getSettingsForm() {
- if ( $this->canCreateAccounts() ) {
- $noCreateMsg = false;
- } else {
- $noCreateMsg = 'config-db-web-no-create-privs';
- }
-
- $wrapperStyle = $this->getVar( '_SameAccount' ) ? 'display: none' : '';
- $displayStyle = $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth'
- ? 'display: none'
- : '';
- $s = Html::openElement( 'fieldset' ) .
- Html::element( 'legend', [], wfMessage( 'config-db-web-account' )->text() ) .
- $this->getCheckBox(
- '_SameAccount', 'config-db-web-account-same',
- [ 'class' => 'hideShowRadio', 'rel' => 'dbOtherAccount' ]
- ) .
- Html::openElement( 'div', [ 'id' => 'dbOtherAccount', 'style' => $wrapperStyle ] ) .
- $this->getRadioSet( [
- 'var' => '_WebWindowsAuthentication',
- 'label' => 'config-mssql-auth',
- 'itemLabelPrefix' => 'config-mssql-',
- 'values' => [ 'sqlauth', 'windowsauth' ],
- 'itemAttribs' => [
- 'sqlauth' => [
- 'class' => 'showHideRadio',
- 'rel' => 'dbCredentialBox',
- ],
- 'windowsauth' => [
- 'class' => 'hideShowRadio',
- 'rel' => 'dbCredentialBox',
- ]
- ],
- 'help' => $this->parent->getHelpBox( 'config-mssql-web-auth' )
- ] ) .
- Html::openElement( 'div', [ 'id' => 'dbCredentialBox', 'style' => $displayStyle ] ) .
- $this->getTextBox( 'wgDBuser', 'config-db-username' ) .
- $this->getPasswordBox( 'wgDBpassword', 'config-db-password' ) .
- Html::closeElement( 'div' );
-
- if ( $noCreateMsg ) {
- $s .= $this->parent->getWarningBox( wfMessage( $noCreateMsg )->plain() );
- } else {
- $s .= $this->getCheckBox( '_CreateDBAccount', 'config-db-web-create' );
- }
-
- $s .= Html::closeElement( 'div' ) . Html::closeElement( 'fieldset' );
-
- return $s;
- }
-
- /**
- * @return Status
- */
- public function submitSettingsForm() {
- $this->setVarsFromRequest( [
- 'wgDBuser',
- 'wgDBpassword',
- '_SameAccount',
- '_CreateDBAccount',
- '_WebWindowsAuthentication'
- ] );
-
- if ( $this->getVar( '_SameAccount' ) ) {
- $this->setVar( '_WebWindowsAuthentication', $this->getVar( '_InstallWindowsAuthentication' ) );
- $this->setVar( 'wgDBuser', $this->getVar( '_InstallUser' ) );
- $this->setVar( 'wgDBpassword', $this->getVar( '_InstallPassword' ) );
- }
-
- if ( $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth' ) {
- $this->setVar( 'wgDBuser', '' );
- $this->setVar( 'wgDBpassword', '' );
- $this->setVar( 'wgDBWindowsAuthentication', true );
- } else {
- $this->setVar( 'wgDBWindowsAuthentication', false );
- }
-
- if ( $this->getVar( '_CreateDBAccount' )
- && $this->getVar( '_WebWindowsAuthentication' ) == 'sqlauth'
- && strval( $this->getVar( 'wgDBpassword' ) ) == ''
- ) {
- return Status::newFatal( 'config-db-password-empty', $this->getVar( 'wgDBuser' ) );
- }
-
- // Validate the create checkbox
- $canCreate = $this->canCreateAccounts();
- if ( !$canCreate ) {
- $this->setVar( '_CreateDBAccount', false );
- $create = false;
- } else {
- $create = $this->getVar( '_CreateDBAccount' );
- }
-
- if ( !$create ) {
- // Test the web account
- $user = $this->getVar( 'wgDBuser' );
- $password = $this->getVar( 'wgDBpassword' );
-
- if ( $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth' ) {
- $user = 'windowsauth';
- $password = 'windowsauth';
- }
-
- try {
- Database::factory( 'mssql', [
- 'host' => $this->getVar( 'wgDBserver' ),
- 'user' => $user,
- 'password' => $password,
- 'dbname' => false,
- 'flags' => 0,
- 'tablePrefix' => $this->getVar( 'wgDBprefix' ),
- 'schema' => $this->getVar( 'wgDBmwschema' ),
- ] );
- } catch ( DBConnectionError $e ) {
- return Status::newFatal( 'config-connection-error', $e->getMessage() );
- }
- }
-
- return Status::newGood();
- }
-
- public function preInstall() {
- # Add our user callback to installSteps, right before the tables are created.
- $callback = [
- 'name' => 'user',
- 'callback' => [ $this, 'setupUser' ],
- ];
- $this->parent->addInstallStep( $callback, 'tables' );
- }
-
- /**
- * @return Status
- */
- public function setupDatabase() {
- $status = $this->getConnection();
- if ( !$status->isOK() ) {
- return $status;
- }
- /** @var Database $conn */
- $conn = $status->value;
- $dbName = $this->getVar( 'wgDBname' );
- $schemaName = $this->getVar( 'wgDBmwschema' );
- if ( !$this->databaseExists( $dbName ) ) {
- $conn->query(
- "CREATE DATABASE " . $conn->addIdentifierQuotes( $dbName ),
- __METHOD__
- );
- }
- $conn->selectDB( $dbName );
- if ( !$this->schemaExists( $schemaName ) ) {
- $conn->query(
- "CREATE SCHEMA " . $conn->addIdentifierQuotes( $schemaName ),
- __METHOD__
- );
- }
- if ( !$this->catalogExists( $schemaName ) ) {
- $conn->query(
- "CREATE FULLTEXT CATALOG " . $conn->addIdentifierQuotes( $schemaName ),
- __METHOD__
- );
- }
- $this->setupSchemaVars();
-
- return $status;
- }
-
- /**
- * @return Status
- */
- public function setupUser() {
- $dbUser = $this->getVar( 'wgDBuser' );
- if ( $dbUser == $this->getVar( '_InstallUser' )
- || ( $this->getVar( '_InstallWindowsAuthentication' ) == 'windowsauth'
- && $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth' ) ) {
- return Status::newGood();
- }
- $status = $this->getConnection();
- if ( !$status->isOK() ) {
- return $status;
- }
-
- $this->setupSchemaVars();
- $dbName = $this->getVar( 'wgDBname' );
- $this->db->selectDB( $dbName );
- $password = $this->getVar( 'wgDBpassword' );
- $schemaName = $this->getVar( 'wgDBmwschema' );
-
- if ( $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth' ) {
- $dbUser = 'windowsauth';
- $password = 'windowsauth';
- }
-
- if ( $this->getVar( '_CreateDBAccount' ) ) {
- $tryToCreate = true;
- } else {
- $tryToCreate = false;
- }
-
- $escUser = $this->db->addIdentifierQuotes( $dbUser );
- $escDb = $this->db->addIdentifierQuotes( $dbName );
- $escSchema = $this->db->addIdentifierQuotes( $schemaName );
- $grantableNames = [];
- if ( $tryToCreate ) {
- $escPass = $this->db->addQuotes( $password );
-
- if ( !$this->loginExists( $dbUser ) ) {
- try {
- $this->db->begin();
- $this->db->selectDB( 'master' );
- $logintype = $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth'
- ? 'FROM WINDOWS'
- : "WITH PASSWORD = $escPass";
- $this->db->query( "CREATE LOGIN $escUser $logintype" );
- $this->db->selectDB( $dbName );
- $this->db->query( "CREATE USER $escUser FOR LOGIN $escUser WITH DEFAULT_SCHEMA = $escSchema" );
- $this->db->commit();
- $grantableNames[] = $dbUser;
- } catch ( DBQueryError $dqe ) {
- $this->db->rollback();
- $status->warning( 'config-install-user-create-failed', $dbUser, $dqe->getMessage() );
- }
- } elseif ( !$this->userExists( $dbUser ) ) {
- try {
- $this->db->begin();
- $this->db->selectDB( $dbName );
- $this->db->query( "CREATE USER $escUser FOR LOGIN $escUser WITH DEFAULT_SCHEMA = $escSchema" );
- $this->db->commit();
- $grantableNames[] = $dbUser;
- } catch ( DBQueryError $dqe ) {
- $this->db->rollback();
- $status->warning( 'config-install-user-create-failed', $dbUser, $dqe->getMessage() );
- }
- } else {
- $status->warning( 'config-install-user-alreadyexists', $dbUser );
- $grantableNames[] = $dbUser;
- }
- }
-
- // Try to grant to all the users we know exist or we were able to create
- $this->db->selectDB( $dbName );
- if ( $grantableNames ) {
- try {
- // First try to grant full permissions
- $fullPrivArr = [
- 'BACKUP DATABASE', 'BACKUP LOG', 'CREATE FUNCTION', 'CREATE PROCEDURE',
- 'CREATE TABLE', 'CREATE VIEW', 'CREATE FULLTEXT CATALOG', 'SHOWPLAN'
- ];
- $fullPrivList = implode( ', ', $fullPrivArr );
- $this->db->begin();
- $this->db->query( "GRANT $fullPrivList ON DATABASE :: $escDb TO $escUser", __METHOD__ );
- $this->db->query( "GRANT CONTROL ON SCHEMA :: $escSchema TO $escUser", __METHOD__ );
- $this->db->commit();
- } catch ( DBQueryError $dqe ) {
- // If that fails, try to grant the limited subset specified in $this->webUserPrivs
- try {
- $privList = implode( ', ', $this->webUserPrivs );
- $this->db->rollback();
- $this->db->begin();
- $this->db->query( "GRANT $privList ON SCHEMA :: $escSchema TO $escUser", __METHOD__ );
- $this->db->commit();
- } catch ( DBQueryError $dqe ) {
- $this->db->rollback();
- $status->fatal( 'config-install-user-grant-failed', $dbUser, $dqe->getMessage() );
- }
- // Also try to grant SHOWPLAN on the db, but don't fail if we can't
- // (just makes a couple things in mediawiki run slower since
- // we have to run SELECT COUNT(*) instead of getting the query plan)
- try {
- $this->db->query( "GRANT SHOWPLAN ON DATABASE :: $escDb TO $escUser", __METHOD__ );
- } catch ( DBQueryError $dqe ) {
- }
- }
- }
-
- return $status;
- }
-
- public function createTables() {
- $status = parent::createTables();
-
- // Do last-minute stuff like fulltext indexes (since they can't be inside a transaction)
- if ( $status->isOK() ) {
- $searchindex = $this->db->tableName( 'searchindex' );
- $schema = $this->db->addIdentifierQuotes( $this->getVar( 'wgDBmwschema' ) );
- try {
- $this->db->query( "CREATE FULLTEXT INDEX ON $searchindex (si_title, si_text) "
- . "KEY INDEX si_page ON $schema" );
- } catch ( DBQueryError $dqe ) {
- $status->fatal( 'config-install-tables-failed', $dqe->getMessage() );
- }
- }
-
- return $status;
- }
-
- public function getGlobalDefaults() {
- // The default $wgDBmwschema is null, which breaks Postgres and other DBMSes that require
- // the use of a schema, so we need to set it here
- return array_merge( parent::getGlobalDefaults(), [
- 'wgDBmwschema' => 'mediawiki',
- ] );
- }
-
- /**
- * Try to see if the login exists
- * @param string $user Username to check
- * @return bool
- */
- private function loginExists( $user ) {
- $res = $this->db->selectField( 'sys.sql_logins', 1, [ 'name' => $user ] );
- return (bool)$res;
- }
-
- /**
- * Try to see if the user account exists
- * We assume we already have the appropriate database selected
- * @param string $user Username to check
- * @return bool
- */
- private function userExists( $user ) {
- $res = $this->db->selectField( 'sys.sysusers', 1, [ 'name' => $user ] );
- return (bool)$res;
- }
-
- /**
- * Try to see if a given database exists
- * @param string $dbName Database name to check
- * @return bool
- */
- private function databaseExists( $dbName ) {
- $res = $this->db->selectField( 'sys.databases', 1, [ 'name' => $dbName ] );
- return (bool)$res;
- }
-
- /**
- * Try to see if a given schema exists
- * We assume we already have the appropriate database selected
- * @param string $schemaName Schema name to check
- * @return bool
- */
- private function schemaExists( $schemaName ) {
- $res = $this->db->selectField( 'sys.schemas', 1, [ 'name' => $schemaName ] );
- return (bool)$res;
- }
-
- /**
- * Try to see if a given fulltext catalog exists
- * We assume we already have the appropriate database selected
- * @param string $catalogName Catalog name to check
- * @return bool
- */
- private function catalogExists( $catalogName ) {
- $res = $this->db->selectField( 'sys.fulltext_catalogs', 1, [ 'name' => $catalogName ] );
- return (bool)$res;
- }
-
- /**
- * Get variables to substitute into tables.sql and the SQL patch files.
- *
- * @return array
- */
- public function getSchemaVars() {
- return [
- 'wgDBname' => $this->getVar( 'wgDBname' ),
- 'wgDBmwschema' => $this->getVar( 'wgDBmwschema' ),
- 'wgDBuser' => $this->getVar( 'wgDBuser' ),
- 'wgDBpassword' => $this->getVar( 'wgDBpassword' ),
- ];
- }
-
- public function getLocalSettings() {
- $schema = LocalSettingsGenerator::escapePhpString( $this->getVar( 'wgDBmwschema' ) );
- $prefix = LocalSettingsGenerator::escapePhpString( $this->getVar( 'wgDBprefix' ) );
- $windowsauth = $this->getVar( 'wgDBWindowsAuthentication' ) ? 'true' : 'false';
-
- return "# MSSQL specific settings
-\$wgDBWindowsAuthentication = {$windowsauth};
-\$wgDBmwschema = \"{$schema}\";
-\$wgDBprefix = \"{$prefix}\";";
- }
-}
+++ /dev/null
-<?php
-/**
- * Microsoft SQL Server-specific installer.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Deployment
- */
-
-use Wikimedia\Rdbms\DatabaseMssql;
-
-/**
- * Class for setting up the MediaWiki database using Microsoft SQL Server.
- *
- * @ingroup Deployment
- * @since 1.23
- */
-
-class MssqlUpdater extends DatabaseUpdater {
-
- /**
- * @var DatabaseMssql
- */
- protected $db;
-
- protected function getCoreUpdateList() {
- return [
- // 1.23
- [ 'addField', 'mwuser', 'user_password_expires', 'patch-user_password_expires.sql' ],
-
- // 1.24
- [ 'addField', 'page', 'page_lang', 'patch-page_page_lang.sql' ],
-
- // 1.25
- [ 'dropTable', 'hitcounter' ],
- [ 'dropField', 'site_stats', 'ss_total_views', 'patch-drop-ss_total_views.sql' ],
- [ 'dropField', 'page', 'page_counter', 'patch-drop-page_counter.sql' ],
- // scripts were updated in 1.27 due to SQL errors; retaining old updatekeys so that people
- // updating from 1.23->1.25->1.27 do not execute these scripts twice even though the
- // updatekeys no longer make sense as they are.
- [ 'updateSchema', 'categorylinks', 'cl_type-category_types-ck',
- 'patch-categorylinks-constraints.sql' ],
- [ 'updateSchema', 'filearchive', 'fa_major_mime-major_mime-ck',
- 'patch-filearchive-constraints.sql' ],
- [ 'updateSchema', 'oldimage', 'oi_major_mime-major_mime-ck',
- 'patch-oldimage-constraints.sql' ],
- [ 'updateSchema', 'image', 'img_major_mime-major_mime-ck', 'patch-image-constraints.sql' ],
- [ 'updateSchema', 'uploadstash', 'us_media_type-media_type-ck',
- 'patch-uploadstash-constraints.sql' ],
-
- [ 'modifyField', 'image', 'img_major_mime',
- 'patch-img_major_mime-chemical.sql' ],
- [ 'modifyField', 'oldimage', 'oi_major_mime',
- 'patch-oi_major_mime-chemical.sql' ],
- [ 'modifyField', 'filearchive', 'fa_major_mime',
- 'patch-fa_major_mime-chemical.sql' ],
-
- // 1.27
- [ 'dropTable', 'msg_resource_links' ],
- [ 'dropTable', 'msg_resource' ],
- [ 'addField', 'watchlist', 'wl_id', 'patch-watchlist-wl_id.sql' ],
- [ 'dropField', 'mwuser', 'user_options', 'patch-drop-user_options.sql' ],
- [ 'addTable', 'bot_passwords', 'patch-bot_passwords.sql' ],
- [ 'addField', 'pagelinks', 'pl_from_namespace', 'patch-pl_from_namespace.sql' ],
- [ 'addField', 'templatelinks', 'tl_from_namespace', 'patch-tl_from_namespace.sql' ],
- [ 'addField', 'imagelinks', 'il_from_namespace', 'patch-il_from_namespace.sql' ],
- [ 'dropIndex', 'categorylinks', 'cl_collation', 'patch-kill-cl_collation_index.sql' ],
- [ 'addIndex', 'categorylinks', 'cl_collation_ext',
- 'patch-add-cl_collation_ext_index.sql' ],
- [ 'dropField', 'recentchanges', 'rc_cur_time', 'patch-drop-rc_cur_time.sql' ],
- [ 'addField', 'page_props', 'pp_sortkey', 'patch-pp_sortkey.sql' ],
- [ 'updateSchema', 'oldimage', 'oldimage varchar', 'patch-oldimage-schema.sql' ],
- [ 'updateSchema', 'filearchive', 'filearchive varchar', 'patch-filearchive-schema.sql' ],
- [ 'updateSchema', 'image', 'image varchar', 'patch-image-schema.sql' ],
- [ 'updateSchema', 'recentchanges', 'recentchanges-drop-fks',
- 'patch-recentchanges-drop-fks.sql' ],
- [ 'updateSchema', 'logging', 'logging-drop-fks', 'patch-logging-drop-fks.sql' ],
- [ 'updateSchema', 'archive', 'archive-drop-fks', 'patch-archive-drop-fks.sql' ],
-
- // 1.28
- [ 'addIndex', 'recentchanges', 'rc_name_type_patrolled_timestamp',
- 'patch-add-rc_name_type_patrolled_timestamp_index.sql' ],
- [ 'addField', 'change_tag', 'ct_id', 'patch-change_tag-ct_id.sql' ],
-
- // 1.29
- [ 'addField', 'externallinks', 'el_index_60', 'patch-externallinks-el_index_60.sql' ],
- [ 'dropIndex', 'oldimage', 'oi_name_archive_name',
- 'patch-alter-table-oldimage.sql' ],
-
- // 1.30
- [ 'modifyField', 'image', 'img_media_type', 'patch-add-3d.sql' ],
- [ 'addIndex', 'site_stats', 'PRIMARY', 'patch-site_stats-pk.sql' ],
-
- // Should have been in 1.30
- [ 'addTable', 'comment', 'patch-comment-table.sql' ],
- // This field was added in 1.31, but is put here so it can be used by 'migrateComments'
- [ 'addField', 'image', 'img_description_id', 'patch-image-img_description_id.sql' ],
- // Should have been in 1.30
- [ 'migrateComments' ],
-
- // 1.31
- [ 'addTable', 'slot_roles', 'patch-slot_roles.sql' ],
- [ 'addTable', 'content_models', 'patch-content_models.sql' ],
- [ 'addTable', 'content', 'patch-content.sql' ],
- [ 'addTable', 'slots', 'patch-slots.sql' ],
- [ 'addField', 'slots', 'slot_origin', 'patch-slot-origin.sql' ],
- [ 'migrateArchiveText' ],
- [ 'addTable', 'actor', 'patch-actor-table.sql' ],
- [ 'migrateActors' ],
- [ 'modifyField', 'revision', 'rev_text_id', 'patch-rev_text_id-default.sql' ],
- [ 'modifyTable', 'site_stats', 'patch-site_stats-modify.sql' ],
- [ 'populateArchiveRevId' ],
- [ 'modifyField', 'recentchanges', 'rc_patrolled', 'patch-rc_patrolled_type.sql' ],
- [ 'addIndex', 'recentchanges', 'rc_namespace_title_timestamp',
- 'patch-recentchanges-nttindex.sql' ],
-
- // 1.32
- [ 'addTable', 'change_tag_def', 'patch-change_tag_def.sql' ],
- [ 'populateExternallinksIndex60' ],
- [ 'modifyfield', 'externallinks', 'el_index_60',
- 'patch-externallinks-el_index_60-drop-default.sql' ],
- [ 'runMaintenance', DeduplicateArchiveRevId::class, 'maintenance/deduplicateArchiveRevId.php' ],
- [ 'addField', 'change_tag', 'ct_tag_id', 'patch-change_tag-tag_id.sql' ],
- [ 'addIndex', 'archive', 'ar_revid_uniq', 'patch-archive-ar_rev_id-unique.sql' ],
- [ 'populateContentTables' ],
- [ 'addIndex', 'logging', 'log_type_action', 'patch-logging-log-type-action-index.sql' ],
- [ 'dropIndex', 'logging', 'type_action', 'patch-logging-drop-type-action-index.sql' ],
- [ 'addIndex', 'interwiki', 'PRIMARY', 'patch-interwiki-pk.sql' ],
- [ 'addIndex', 'protected_titles', 'PRIMARY', 'patch-protected_titles-pk.sql' ],
- [ 'addIndex', 'page_props', 'PRIMARY', 'patch-page_props-pk.sql' ],
- [ 'addIndex', 'site_identifiers', 'PRIMARY', 'patch-site_identifiers-pk.sql' ],
- [ 'addIndex', 'recentchanges', 'rc_this_oldid', 'patch-recentchanges-rc_this_oldid-index.sql' ],
- [ 'dropTable', 'transcache' ],
- [ 'runMaintenance', PopulateChangeTagDef::class, 'maintenance/populateChangeTagDef.php' ],
- [ 'addIndex', 'change_tag', 'change_tag_rc_tag_id',
- 'patch-change_tag-change_tag_rc_tag_id.sql' ],
- [ 'addField', 'ipblocks', 'ipb_sitewide', 'patch-ipb_sitewide.sql' ],
- [ 'addTable', 'ipblocks_restrictions', 'patch-ipblocks_restrictions-table.sql' ],
- [ 'migrateImageCommentTemp' ],
-
- // 1.33
- [ 'dropField', 'change_tag', 'ct_tag', 'patch-drop-ct_tag.sql' ],
- [ 'dropTable', 'valid_tag' ],
- [ 'dropTable', 'tag_summary' ],
- [ 'dropField', 'protected_titles', 'pt_reason', 'patch-drop-comment-fields.sql' ],
- ];
- }
-
- protected function applyPatch( $path, $isFullPath = false, $msg = null ) {
- $prevScroll = $this->db->scrollableCursor( false );
- $prevPrep = $this->db->prepareStatements( false );
- parent::applyPatch( $path, $isFullPath, $msg );
- $this->db->scrollableCursor( $prevScroll );
- $this->db->prepareStatements( $prevPrep );
- return true;
- }
-
- /**
- * General schema update for a table that touches more than one field or requires
- * destructive actions (such as dropping and recreating the table). NOTE: Usage of
- * this function is highly discouraged, use it's successor DatabaseUpdater::modifyTable
- * instead.
- *
- * @param string $table
- * @param string $updatekey
- * @param string $patch
- * @param bool $fullpath
- * @return bool
- */
- protected function updateSchema( $table, $updatekey, $patch, $fullpath = false ) {
- if ( !$this->db->tableExists( $table, __METHOD__ ) ) {
- $this->output( "...$table table does not exist, skipping schema update patch.\n" );
- } elseif ( $this->updateRowExists( $updatekey ) ) {
- $this->output( "...$table already had schema updated by $patch.\n" );
- } else {
- $apply = $this->applyPatch( $patch, $fullpath, "Updating schema of table $table" );
- if ( $apply ) {
- $this->insertUpdateRow( $updatekey );
- }
- return $apply;
- }
-
- return true;
- }
-}
+++ /dev/null
-<?php
-/**
- * Oracle-specific installer.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Deployment
- */
-
-use Wikimedia\Rdbms\Database;
-use Wikimedia\Rdbms\DBConnectionError;
-
-/**
- * Class for setting up the MediaWiki database using Oracle.
- *
- * @ingroup Deployment
- * @since 1.17
- */
-class OracleInstaller extends DatabaseInstaller {
-
- protected $globalNames = [
- 'wgDBserver',
- 'wgDBname',
- 'wgDBuser',
- 'wgDBpassword',
- 'wgDBprefix',
- ];
-
- protected $internalDefaults = [
- '_OracleDefTS' => 'USERS',
- '_OracleTempTS' => 'TEMP',
- '_InstallUser' => 'SYSTEM',
- ];
-
- public static $minimumVersion = '9.0.1'; // 9iR1
- protected static $notMinimumVersionMessage = 'config-oracle-old';
-
- protected $connError = null;
-
- public function getName() {
- return 'oracle';
- }
-
- public function isCompiled() {
- return self::checkExtension( 'oci8' );
- }
-
- public function getConnectForm() {
- if ( $this->getVar( 'wgDBserver' ) == 'localhost' ) {
- $this->parent->setVar( 'wgDBserver', '' );
- }
-
- return $this->getTextBox(
- 'wgDBserver',
- 'config-db-host-oracle',
- [],
- $this->parent->getHelpBox( 'config-db-host-oracle-help' )
- ) .
- Html::openElement( 'fieldset' ) .
- Html::element( 'legend', [], wfMessage( 'config-db-wiki-settings' )->text() ) .
- $this->getTextBox( 'wgDBprefix', 'config-db-prefix' ) .
- $this->getTextBox( '_OracleDefTS', 'config-oracle-def-ts' ) .
- $this->getTextBox(
- '_OracleTempTS',
- 'config-oracle-temp-ts',
- [],
- $this->parent->getHelpBox( 'config-db-oracle-help' )
- ) .
- Html::closeElement( 'fieldset' ) .
- $this->parent->getWarningBox( wfMessage( 'config-db-account-oracle-warn' )->text() ) .
- $this->getInstallUserBox() .
- $this->getWebUserBox();
- }
-
- public function submitInstallUserBox() {
- parent::submitInstallUserBox();
- $this->parent->setVar( '_InstallDBname', $this->getVar( '_InstallUser' ) );
-
- return Status::newGood();
- }
-
- public function submitConnectForm() {
- // Get variables from the request
- $newValues = $this->setVarsFromRequest( [
- 'wgDBserver',
- 'wgDBprefix',
- 'wgDBuser',
- 'wgDBpassword'
- ] );
- $this->parent->setVar( 'wgDBname', $this->getVar( 'wgDBuser' ) );
-
- // Validate them
- $status = Status::newGood();
- if ( !strlen( $newValues['wgDBserver'] ) ) {
- $status->fatal( 'config-missing-db-server-oracle' );
- } elseif ( !self::checkConnectStringFormat( $newValues['wgDBserver'] ) ) {
- $status->fatal( 'config-invalid-db-server-oracle', $newValues['wgDBserver'] );
- }
- if ( !preg_match( '/^[a-zA-Z0-9_]*$/', $newValues['wgDBprefix'] ) ) {
- $status->fatal( 'config-invalid-schema', $newValues['wgDBprefix'] );
- }
- if ( !$status->isOK() ) {
- return $status;
- }
-
- // Submit user box
- $status = $this->submitInstallUserBox();
- if ( !$status->isOK() ) {
- return $status;
- }
-
- // Try to connect trough multiple scenarios
- // Scenario 1: Install with a manually created account
- $status = $this->getConnection();
- if ( !$status->isOK() ) {
- if ( $this->connError == 28009 ) {
- // _InstallUser seems to be a SYSDBA
- // Scenario 2: Create user with SYSDBA and install with new user
- $status = $this->submitWebUserBox();
- if ( !$status->isOK() ) {
- return $status;
- }
- $status = $this->openSYSDBAConnection();
- if ( !$status->isOK() ) {
- return $status;
- }
- if ( !$this->getVar( '_CreateDBAccount' ) ) {
- $status->fatal( 'config-db-sys-create-oracle' );
- }
- } else {
- return $status;
- }
- } else {
- // check for web user credentials
- // Scenario 3: Install with a priviliged user but use a restricted user
- $statusIS3 = $this->submitWebUserBox();
- if ( !$statusIS3->isOK() ) {
- return $statusIS3;
- }
- }
-
- /**
- * @var Database $conn
- */
- $conn = $status->value;
-
- // Check version
- $status->merge( static::meetsMinimumRequirement( $conn->getServerVersion() ) );
-
- return $status;
- }
-
- public function openConnection() {
- return $this->doOpenConnection();
- }
-
- public function openSYSDBAConnection() {
- return $this->doOpenConnection( DatabaseOracle::DBO_SYSDBA );
- }
-
- /**
- * @param int $flags
- * @return Status Status with DatabaseOracle or null as the value
- */
- private function doOpenConnection( $flags = 0 ) {
- $status = Status::newGood();
- try {
- $db = Database::factory(
- 'oracle',
- [
- 'host' => $this->getVar( 'wgDBserver' ),
- 'user' => $this->getVar( '_InstallUser' ),
- 'password' => $this->getVar( '_InstallPassword' ),
- 'dbname' => $this->getVar( '_InstallDBname' ),
- 'tablePrefix' => $this->getVar( 'wgDBprefix' ),
- 'flags' => $flags
- ]
- );
- $status->value = $db;
- } catch ( DBConnectionError $e ) {
- $this->connError = $e->db->lastErrno();
- $status->fatal( 'config-connection-error', $e->getMessage() );
- }
-
- return $status;
- }
-
- public function needsUpgrade() {
- $tempDBname = $this->getVar( 'wgDBname' );
- $this->parent->setVar( 'wgDBname', $this->getVar( 'wgDBuser' ) );
- $retVal = parent::needsUpgrade();
- $this->parent->setVar( 'wgDBname', $tempDBname );
-
- return $retVal;
- }
-
- public function preInstall() {
- # Add our user callback to installSteps, right before the tables are created.
- $callback = [
- 'name' => 'user',
- 'callback' => [ $this, 'setupUser' ]
- ];
- $this->parent->addInstallStep( $callback, 'database' );
- }
-
- public function setupDatabase() {
- $status = Status::newGood();
-
- return $status;
- }
-
- public function setupUser() {
- global $IP;
-
- if ( !$this->getVar( '_CreateDBAccount' ) ) {
- return Status::newGood();
- }
-
- // normaly only SYSDBA users can create accounts
- $status = $this->openSYSDBAConnection();
- if ( !$status->isOK() ) {
- if ( $this->connError == 1031 ) {
- // insufficient privileges (looks like a normal user)
- $status = $this->openConnection();
- if ( !$status->isOK() ) {
- return $status;
- }
- } else {
- return $status;
- }
- }
-
- $this->db = $status->value;
- $this->setupSchemaVars();
-
- if ( !$this->db->selectDB( $this->getVar( 'wgDBuser' ) ) ) {
- $this->db->setFlag( DBO_DDLMODE );
- $error = $this->db->sourceFile( "$IP/maintenance/oracle/user.sql" );
- if ( $error !== true || !$this->db->selectDB( $this->getVar( 'wgDBuser' ) ) ) {
- $status->fatal( 'config-install-user-failed', $this->getVar( 'wgDBuser' ), $error );
- }
- } elseif ( $this->db->getFlag( DBO_SYSDBA ) ) {
- $status->fatal( 'config-db-sys-user-exists-oracle', $this->getVar( 'wgDBuser' ) );
- }
-
- if ( $status->isOK() ) {
- // user created or already existing, switching back to a normal connection
- // as the new user has all needed privileges to setup the rest of the schema
- // i will be using that user as _InstallUser from this point on
- $this->db->close();
- $this->db = false;
- $this->parent->setVar( '_InstallUser', $this->getVar( 'wgDBuser' ) );
- $this->parent->setVar( '_InstallPassword', $this->getVar( 'wgDBpassword' ) );
- $this->parent->setVar( '_InstallDBname', $this->getVar( 'wgDBuser' ) );
- $status = $this->getConnection();
- }
-
- return $status;
- }
-
- /**
- * Overload: after this action field info table has to be rebuilt
- * @return Status
- */
- public function createTables() {
- $this->setupSchemaVars();
- $this->db->setFlag( DBO_DDLMODE );
- $this->parent->setVar( 'wgDBname', $this->getVar( 'wgDBuser' ) );
- $status = parent::createTables();
- $this->db->clearFlag( DBO_DDLMODE );
-
- $this->db->query( 'BEGIN fill_wiki_info; END;' );
-
- return $status;
- }
-
- public function getSchemaVars() {
- $varNames = [
- # These variables are used by maintenance/oracle/user.sql
- '_OracleDefTS',
- '_OracleTempTS',
- 'wgDBuser',
- 'wgDBpassword',
-
- # These are used by tables.sql
- 'wgDBprefix',
- ];
- $vars = [];
- foreach ( $varNames as $name ) {
- $vars[$name] = $this->getVar( $name );
- }
-
- return $vars;
- }
-
- public function getLocalSettings() {
- $prefix = $this->getVar( 'wgDBprefix' );
-
- return "# Oracle specific settings
-\$wgDBprefix = \"{$prefix}\";
-";
- }
-
- /**
- * Function checks the format of Oracle connect string
- * The actual validity of the string is checked by attempting to connect
- *
- * Regex should be able to validate all connect string formats
- * [//](host|tns_name)[:port][/service_name][:POOLED]
- * http://www.orafaq.com/wiki/EZCONNECT
- *
- * @since 1.22
- *
- * @param string $connect_string
- *
- * @return bool Whether the connection string is valid.
- */
- public static function checkConnectStringFormat( $connect_string ) {
- // phpcs:disable Generic.Files.LineLength
- // @todo Very long regular expression. Make more readable?
- $isValid = preg_match( '/^[[:alpha:]][\w\-]*(?:\.[[:alpha:]][\w\-]*){0,2}$/', $connect_string ); // TNS name
- $isValid |= preg_match( '/^(?:\/\/)?[\w\-\.]+(?::[\d]+)?(?:\/(?:[\w\-\.]+(?::(pooled|dedicated|shared))?)?(?:\/[\w\-\.]+)?)?$/', $connect_string ); // EZConnect
- // phpcs:enable
- return (bool)$isValid;
- }
-}
+++ /dev/null
-<?php
-/**
- * Oracle-specific updater.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Deployment
- */
-
-/**
- * Class for handling updates to Oracle databases.
- *
- * @ingroup Deployment
- * @since 1.17
- */
-class OracleUpdater extends DatabaseUpdater {
-
- /**
- * Handle to the database subclass
- *
- * @var DatabaseOracle
- */
- protected $db;
-
- protected function getCoreUpdateList() {
- return [
- [ 'disableContentHandlerUseDB' ],
-
- // 1.17
- [ 'doNamespaceDefaults' ],
- [ 'doFKRenameDeferr' ],
- [ 'doFunctions17' ],
- [ 'doSchemaUpgrade17' ],
- [ 'doInsertPage0' ],
- [ 'doRemoveNotNullEmptyDefaults' ],
- [ 'addTable', 'user_former_groups', 'patch-user_former_groups.sql' ],
-
- // 1.18
- [ 'addIndex', 'user', 'i02', 'patch-user_email_index.sql' ],
- [ 'modifyField', 'user_properties', 'up_property', 'patch-up_property.sql' ],
- [ 'addTable', 'uploadstash', 'patch-uploadstash.sql' ],
- [ 'doRecentchangesFK2Cascade' ],
-
- // 1.19
- [ 'addIndex', 'logging', 'i05', 'patch-logging_type_action_index.sql' ],
- [ 'addField', 'revision', 'rev_sha1', 'patch-rev_sha1_field.sql' ],
- [ 'addField', 'archive', 'ar_sha1', 'patch-ar_sha1_field.sql' ],
- [ 'doRemoveNotNullEmptyDefaults2' ],
- [ 'addIndex', 'page', 'i03', 'patch-page_redirect_namespace_len.sql' ],
- [ 'addField', 'uploadstash', 'us_chunk_inx', 'patch-us_chunk_inx_field.sql' ],
- [ 'addField', 'job', 'job_timestamp', 'patch-job_timestamp_field.sql' ],
- [ 'addIndex', 'job', 'i02', 'patch-job_timestamp_index.sql' ],
- [ 'doPageRestrictionsPKUKFix' ],
-
- // 1.20
- [ 'addIndex', 'ipblocks', 'i05', 'patch-ipblocks_i05_index.sql' ],
- [ 'addIndex', 'revision', 'i05', 'patch-revision_i05_index.sql' ],
- [ 'dropField', 'category', 'cat_hidden', 'patch-cat_hidden.sql' ],
-
- // 1.21
- [ 'addField', 'revision', 'rev_content_format',
- 'patch-revision-rev_content_format.sql' ],
- [ 'addField', 'revision', 'rev_content_model',
- 'patch-revision-rev_content_model.sql' ],
- [ 'addField', 'archive', 'ar_content_format', 'patch-archive-ar_content_format.sql' ],
- [ 'addField', 'archive', 'ar_content_model', 'patch-archive-ar_content_model.sql' ],
- [ 'addField', 'archive', 'ar_id', 'patch-archive-ar_id.sql' ],
- [ 'addField', 'externallinks', 'el_id', 'patch-externallinks-el_id.sql' ],
- [ 'addField', 'page', 'page_content_model', 'patch-page-page_content_model.sql' ],
- [ 'enableContentHandlerUseDB' ],
- [ 'dropField', 'site_stats', 'ss_admins', 'patch-ss_admins.sql' ],
- [ 'dropField', 'recentchanges', 'rc_moved_to_title', 'patch-rc_moved.sql' ],
- [ 'addTable', 'sites', 'patch-sites.sql' ],
- [ 'addField', 'filearchive', 'fa_sha1', 'patch-fa_sha1.sql' ],
- [ 'addField', 'job', 'job_token', 'patch-job_token.sql' ],
- [ 'addField', 'job', 'job_attempts', 'patch-job_attempts.sql' ],
- [ 'addField', 'uploadstash', 'us_props', 'patch-uploadstash-us_props.sql' ],
- [ 'modifyField', 'user_groups', 'ug_group', 'patch-ug_group-length-increase-255.sql' ],
- [ 'modifyField', 'user_former_groups', 'ufg_group',
- 'patch-ufg_group-length-increase-255.sql' ],
-
- // 1.23
- [ 'addIndex', 'logging', 'i06', 'patch-logging_user_text_type_time_index.sql' ],
- [ 'addIndex', 'logging', 'i07', 'patch-logging_user_text_time_index.sql' ],
- [ 'addField', 'user', 'user_password_expires', 'patch-user_password_expire.sql' ],
- [ 'addField', 'page', 'page_links_updated', 'patch-page_links_updated.sql' ],
- [ 'addField', 'recentchanges', 'rc_source', 'patch-rc_source.sql' ],
-
- // 1.24
- [ 'addField', 'page', 'page_lang', 'patch-page-page_lang.sql' ],
-
- // 1.25
- [ 'dropTable', 'hitcounter' ],
- [ 'dropField', 'site_stats', 'ss_total_views', 'patch-drop-ss_total_views.sql' ],
- [ 'dropField', 'page', 'page_counter', 'patch-drop-page_counter.sql' ],
-
- // 1.27
- [ 'dropTable', 'msg_resource_links' ],
- [ 'dropTable', 'msg_resource' ],
- [ 'addField', 'watchlist', 'wl_id', 'patch-watchlist-wl_id.sql' ],
-
- // 1.28
- [ 'addIndex', 'recentchanges', 'rc_name_type_patrolled_timestamp',
- 'patch-add-rc_name_type_patrolled_timestamp_index.sql' ],
- [ 'addField', 'change_tag', 'ct_id', 'patch-change_tag-ct_id.sql' ],
-
- // 1.29
- [ 'addField', 'externallinks', 'el_index_60', 'patch-externallinks-el_index_60.sql' ],
- [ 'addField', 'user_groups', 'ug_expiry', 'patch-user_groups-ug_expiry.sql' ],
-
- // 1.30
- [ 'doAutoIncrementTriggers' ],
- [ 'addIndex', 'site_stats', 'PRIMARY', 'patch-site_stats-pk.sql' ],
-
- // Should have been in 1.30
- [ 'addTable', 'comment', 'patch-comment-table.sql' ],
- // This field was added in 1.31, but is put here so it can be used by 'migrateComments'
- [ 'addField', 'image', 'img_description_id', 'patch-image-img_description_id.sql' ],
- // Should have been in 1.30
- [ 'migrateComments' ],
-
- // 1.31
- [ 'addTable', 'slots', 'patch-slots.sql' ],
- [ 'addField', 'slots', 'slot_origin', 'patch-slot-origin.sql' ],
- [ 'addTable', 'content', 'patch-content.sql' ],
- [ 'addTable', 'slot_roles', 'patch-slot_roles.sql' ],
- [ 'addTable', 'content_models', 'patch-content_models.sql' ],
- [ 'migrateArchiveText' ],
- [ 'addTable', 'actor', 'patch-actor-table.sql' ],
- [ 'migrateActors' ],
- [ 'modifyTable', 'site_stats', 'patch-site_stats-modify.sql' ],
- [ 'populateArchiveRevId' ],
- [ 'addIndex', 'recentchanges', 'rc_namespace_title_timestamp',
- 'patch-recentchanges-nttindex.sql' ],
-
- // 1.32
- [ 'addTable', 'change_tag_def', 'patch-change_tag_def.sql' ],
- [ 'populateExternallinksIndex60' ],
- [ 'runMaintenance', DeduplicateArchiveRevId::class, 'maintenance/deduplicateArchiveRevId.php' ],
- [ 'addField', 'change_tag', 'ct_tag_id', 'patch-change_tag-tag_id.sql' ],
- [ 'addIndex', 'archive', 'ar_revid_uniq', 'patch-archive-ar_rev_id-unique.sql' ],
- [ 'populateContentTables' ],
- [ 'addIndex', 'recentchanges', 'rc_this_oldid', 'patch-recentchanges-rc_this_oldid-index.sql' ],
- [ 'dropTable', 'transcache' ],
- [ 'runMaintenance', PopulateChangeTagDef::class, 'maintenance/populateChangeTagDef.php' ],
- [ 'addIndex', 'change_tag', 'change_tag_i03',
- 'patch-change_tag-change_tag_rc_tag_id.sql' ],
- [ 'addField', 'ipblocks', 'ipb_sitewide', 'patch-ipb_sitewide.sql' ],
- [ 'addTable', 'ipblocks_restrictions', 'patch-ipblocks_restrictions-table.sql' ],
- [ 'migrateImageCommentTemp' ],
-
- // 1.33
- [ 'dropField', 'change_tag', 'ct_tag', 'patch-drop-ct_tag.sql' ],
- [ 'dropTable', 'valid_tag' ],
- [ 'dropTable', 'tag_summary' ],
- [ 'dropField', 'protected_titles', 'pt_reason', 'patch-drop-comment-fields.sql' ],
-
- // KEEP THIS AT THE BOTTOM!!
- [ 'doRebuildDuplicateFunction' ],
-
- ];
- }
-
- /**
- * MySQL uses datatype defaults for NULL inserted into NOT NULL fields
- * In namespace case that results into insert of 0 which is default namespace
- * Oracle inserts NULL, so namespace fields should have a default value
- */
- protected function doNamespaceDefaults() {
- $meta = $this->db->fieldInfo( 'page', 'page_namespace' );
- if ( $meta->defaultValue() != null ) {
- return;
- }
-
- $this->applyPatch(
- 'patch_namespace_defaults.sql',
- false,
- 'Altering namespace fields with default value'
- );
- }
-
- /**
- * Uniform FK names + deferrable state
- */
- protected function doFKRenameDeferr() {
- $meta = $this->db->query( '
- SELECT COUNT(*) cnt
- FROM user_constraints
- WHERE constraint_type = \'R\' AND deferrable = \'DEFERRABLE\''
- );
- $row = $meta->fetchRow();
- if ( $row && $row['cnt'] > 0 ) {
- return;
- }
-
- $this->applyPatch( 'patch_fk_rename_deferred.sql', false, "Altering foreign keys ... " );
- }
-
- /**
- * Recreate functions to 17 schema layout
- */
- protected function doFunctions17() {
- $this->applyPatch( 'patch_create_17_functions.sql', false, "Recreating functions" );
- }
-
- /**
- * Schema upgrade 16->17
- * there are no incremental patches prior to this
- */
- protected function doSchemaUpgrade17() {
- // check if iwlinks table exists which was added in 1.17
- if ( $this->db->tableExists( 'iwlinks' ) ) {
- return;
- }
- $this->applyPatch( 'patch_16_17_schema_changes.sql', false, "Updating schema to 17" );
- }
-
- /**
- * Insert page (page_id = 0) to prevent FK constraint violation
- */
- protected function doInsertPage0() {
- $this->output( "Inserting page 0 if missing ... " );
- $row = [
- 'page_id' => 0,
- 'page_namespace' => 0,
- 'page_title' => ' ',
- 'page_is_redirect' => 0,
- 'page_is_new' => 0,
- 'page_random' => 0,
- 'page_touched' => $this->db->timestamp(),
- 'page_latest' => 0,
- 'page_len' => 0
- ];
- $this->db->insert( 'page', $row, 'OracleUpdater:doInserPage0', [ 'IGNORE' ] );
- $this->output( "ok\n" );
- }
-
- /**
- * Remove DEFAULT '' NOT NULL constraints from fields as '' is internally
- * converted to NULL in Oracle
- */
- protected function doRemoveNotNullEmptyDefaults() {
- $meta = $this->db->fieldInfo( 'categorylinks', 'cl_sortkey_prefix' );
- if ( $meta->isNullable() ) {
- return;
- }
- $this->applyPatch(
- 'patch_remove_not_null_empty_defs.sql',
- false,
- 'Removing not null empty constraints'
- );
- }
-
- protected function doRemoveNotNullEmptyDefaults2() {
- $meta = $this->db->fieldInfo( 'ipblocks', 'ipb_by_text' );
- if ( $meta->isNullable() ) {
- return;
- }
- $this->applyPatch(
- 'patch_remove_not_null_empty_defs2.sql',
- false,
- 'Removing not null empty constraints'
- );
- }
-
- /**
- * Removed forcing of invalid state on recentchanges_fk2.
- * cascading taken in account in the deleting function
- */
- protected function doRecentchangesFK2Cascade() {
- $meta = $this->db->query( 'SELECT 1 FROM all_constraints WHERE owner = \'' .
- strtoupper( $this->db->getDBname() ) .
- '\' AND constraint_name = \'' .
- $this->db->tablePrefix() .
- 'RECENTCHANGES_FK2\' AND delete_rule = \'CASCADE\''
- );
- $row = $meta->fetchRow();
- if ( $row ) {
- return;
- }
-
- $this->applyPatch( 'patch_recentchanges_fk2_cascade.sql', false, "Altering RECENTCHANGES_FK2" );
- }
-
- /**
- * Fixed wrong PK, UK definition
- */
- protected function doPageRestrictionsPKUKFix() {
- $this->output( "Altering PAGE_RESTRICTIONS keys ... " );
-
- $meta = $this->db->query( 'SELECT column_name FROM all_cons_columns WHERE owner = \'' .
- strtoupper( $this->db->getDBname() ) .
- '\' AND constraint_name = \'' .
- $this->db->tablePrefix() .
- 'PAGE_RESTRICTIONS_PK\' AND rownum = 1'
- );
- $row = $meta->fetchRow();
- if ( $row['column_name'] == 'PR_ID' ) {
- $this->output( "seems to be up to date.\n" );
-
- return;
- }
-
- $this->applyPatch( 'patch-page_restrictions_pkuk_fix.sql', false );
- $this->output( "ok\n" );
- }
-
- /**
- * Add auto-increment triggers
- */
- protected function doAutoIncrementTriggers() {
- $this->output( "Adding auto-increment triggers ... " );
-
- $meta = $this->db->query( 'SELECT trigger_name FROM user_triggers WHERE table_owner = \'' .
- strtoupper( $this->db->getDBname() ) .
- '\' AND trigger_name = \'' .
- $this->db->tablePrefix() .
- 'PAGE_DEFAULT_PAGE_ID\''
- );
- $row = $meta->fetchRow();
- if ( $row['column_name'] ) {
- $this->output( "seems to be up to date.\n" );
-
- return;
- }
-
- $this->applyPatch( 'patch-auto_increment_triggers.sql', false );
-
- $this->output( "ok\n" );
- }
-
- /**
- * rebuilding of the function that duplicates tables for tests
- */
- protected function doRebuildDuplicateFunction() {
- $this->applyPatch( 'patch_rebuild_dupfunc.sql', false, "Rebuilding duplicate function" );
- }
-
- /**
- * Overload: after this action field info table has to be rebuilt
- *
- * @param array $what
- */
- public function doUpdates( array $what = [ 'core', 'extensions', 'purge', 'stats' ] ) {
- parent::doUpdates( $what );
-
- $this->db->query( 'BEGIN fill_wiki_info; END;' );
- }
-
- /**
- * Overload: because of the DDL_MODE tablename escaping is a bit dodgy
- */
- public function purgeCache() {
- # We can't guarantee that the user will be able to use TRUNCATE,
- # but we know that DELETE is available to us
- $this->output( "Purging caches..." );
- $this->db->delete( '/*Q*/' . $this->db->tableName( 'objectcache' ), '*', __METHOD__ );
- $this->output( "done.\n" );
- }
-}
// we auto-detect the first available driver. For types without built-in support,
// an class named "Database<Type>" us used, eg. DatabaseFoo for type 'foo'.
static $builtinTypes = [
- 'mssql' => DatabaseMssql::class,
'mysql' => [ 'mysqli' => DatabaseMysqli::class ],
'sqlite' => DatabaseSqlite::class,
'postgres' => DatabasePostgres::class,
+++ /dev/null
-<?php
-/**
- * This is the MS SQL Server Native database abstraction layer.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Database
- * @author Joel Penner <a-joelpe at microsoft dot com>
- * @author Chris Pucci <a-cpucci at microsoft dot com>
- * @author Ryan Biesemeyer <v-ryanbi at microsoft dot com>
- * @author Ryan Schmidt <skizzerz at gmail dot com>
- */
-
-namespace Wikimedia\Rdbms;
-
-use Exception;
-use RuntimeException;
-use stdClass;
-use Wikimedia\AtEase\AtEase;
-
-/**
- * @ingroup Database
- */
-class DatabaseMssql extends Database {
- /** @var int */
- protected $serverPort;
- /** @var bool */
- protected $useWindowsAuth = false;
- /** @var int|null */
- protected $lastInsertId = null;
- /** @var int|null */
- protected $lastAffectedRowCount = null;
- /** @var int */
- protected $subqueryId = 0;
- /** @var bool */
- protected $scrollableCursor = true;
- /** @var bool */
- protected $prepareStatements = true;
- /** @var stdClass[][]|null */
- protected $binaryColumnCache = null;
- /** @var stdClass[][]|null */
- protected $bitColumnCache = null;
- /** @var bool */
- protected $ignoreDupKeyErrors = false;
- /** @var string[] */
- protected $ignoreErrors = [];
-
- public function implicitOrderby() {
- return false;
- }
-
- public function unionSupportsOrderAndLimit() {
- return false;
- }
-
- public function __construct( array $params ) {
- $this->serverPort = $params['port'];
- $this->useWindowsAuth = $params['UseWindowsAuth'];
-
- parent::__construct( $params );
- }
-
- protected function open( $server, $user, $password, $dbName, $schema, $tablePrefix ) {
- if ( !function_exists( 'sqlsrv_connect' ) ) {
- throw new DBConnectionError(
- $this,
- "Microsoft SQL Server Native (sqlsrv) functions missing.\n
- You can download the driver from: http://go.microsoft.com/fwlink/?LinkId=123470"
- );
- }
-
- $this->close();
-
- if ( $schema !== null ) {
- throw $this->newExceptionAfterConnectError( "Got schema '$schema'; not supported." );
- }
-
- $this->server = $server;
- $this->user = $user;
- $this->password = $password;
-
- $connectionInfo = [];
- if ( strlen( $dbName ) ) {
- $connectionInfo['Database'] = $dbName;
- }
- if ( !$this->useWindowsAuth ) {
- $connectionInfo['UID'] = $user;
- $connectionInfo['PWD'] = $password;
- }
-
- AtEase::suppressWarnings();
- $this->conn = sqlsrv_connect( $server, $connectionInfo ) ?: null;
- AtEase::restoreWarnings();
-
- if ( !$this->conn ) {
- throw $this->newExceptionAfterConnectError( $this->lastError() );
- }
-
- try {
- $this->currentDomain = new DatabaseDomain(
- strlen( $dbName ) ? $dbName : null,
- null,
- $tablePrefix
- );
- } catch ( Exception $e ) {
- throw $this->newExceptionAfterConnectError( $e->getMessage() );
- }
- }
-
- /**
- * Closes a database connection, if it is open
- * Returns success, true if already closed
- * @return bool
- */
- protected function closeConnection() {
- return sqlsrv_close( $this->conn );
- }
-
- /**
- * @param bool|MssqlResultWrapper|resource $result
- * @return bool|MssqlResultWrapper
- */
- protected function resultObject( $result ) {
- if ( !$result ) {
- return false;
- } elseif ( $result instanceof MssqlResultWrapper ) {
- return $result;
- } elseif ( $result === true ) {
- // Successful write query
- return $result;
- } else {
- return new MssqlResultWrapper( $this, $result );
- }
- }
-
- /**
- * @param string $sql
- * @return bool|MssqlResultWrapper|resource
- */
- protected function doQuery( $sql ) {
- // several extensions seem to think that all databases support limits
- // via LIMIT N after the WHERE clause, but MSSQL uses SELECT TOP N,
- // so to catch any of those extensions we'll do a quick check for a
- // LIMIT clause and pass $sql through $this->LimitToTopN() which parses
- // the LIMIT clause and passes the result to $this->limitResult();
- if ( preg_match( '/\bLIMIT\s*/i', $sql ) ) {
- // massage LIMIT -> TopN
- $sql = $this->LimitToTopN( $sql );
- }
-
- // MSSQL doesn't have EXTRACT(epoch FROM XXX)
- if ( preg_match( '#\bEXTRACT\s*?\(\s*?EPOCH\s+FROM\b#i', $sql, $matches ) ) {
- // This is same as UNIX_TIMESTAMP, we need to calc # of seconds from 1970
- $sql = str_replace( $matches[0], "DATEDIFF(s,CONVERT(datetime,'1/1/1970'),", $sql );
- }
-
- // perform query
-
- // SQLSRV_CURSOR_STATIC is slower than SQLSRV_CURSOR_CLIENT_BUFFERED (one of the two is
- // needed if we want to be able to seek around the result set), however CLIENT_BUFFERED
- // has a bug in the sqlsrv driver where wchar_t types (such as nvarchar) that are empty
- // strings make php throw a fatal error "Severe error translating Unicode"
- if ( $this->scrollableCursor ) {
- $scrollArr = [ 'Scrollable' => SQLSRV_CURSOR_STATIC ];
- } else {
- $scrollArr = [];
- }
-
- if ( $this->prepareStatements ) {
- // we do prepare + execute so we can get its field metadata for later usage if desired
- $stmt = sqlsrv_prepare( $this->conn, $sql, [], $scrollArr );
- $success = sqlsrv_execute( $stmt );
- } else {
- $stmt = sqlsrv_query( $this->conn, $sql, [], $scrollArr );
- $success = (bool)$stmt;
- }
-
- // Make a copy to ensure what we add below does not get reflected in future queries
- $ignoreErrors = $this->ignoreErrors;
-
- if ( $this->ignoreDupKeyErrors ) {
- // ignore duplicate key errors
- // this emulates INSERT IGNORE in MySQL
- $ignoreErrors[] = '2601'; // duplicate key error caused by unique index
- $ignoreErrors[] = '2627'; // duplicate key error caused by primary key
- $ignoreErrors[] = '3621'; // generic "the statement has been terminated" error
- }
-
- if ( $success === false ) {
- $errors = sqlsrv_errors();
- $success = true;
-
- foreach ( $errors as $err ) {
- if ( !in_array( $err['code'], $ignoreErrors ) ) {
- $success = false;
- break;
- }
- }
-
- if ( $success === false ) {
- return false;
- }
- }
- // remember number of rows affected
- $this->lastAffectedRowCount = sqlsrv_rows_affected( $stmt );
-
- return $stmt;
- }
-
- public function freeResult( $res ) {
- sqlsrv_free_stmt( ResultWrapper::unwrap( $res ) );
- }
-
- /**
- * @param IResultWrapper $res
- * @return stdClass
- */
- public function fetchObject( $res ) {
- // $res is expected to be an instance of MssqlResultWrapper here
- return $res->fetchObject();
- }
-
- /**
- * @param IResultWrapper $res
- * @return array
- */
- public function fetchRow( $res ) {
- return $res->fetchRow();
- }
-
- /**
- * @param mixed $res
- * @return int
- */
- public function numRows( $res ) {
- $res = ResultWrapper::unwrap( $res );
-
- $ret = sqlsrv_num_rows( $res );
- if ( $ret === false ) {
- // we cannot get an amount of rows from this cursor type
- // has_rows returns bool true/false if the result has rows
- $ret = (int)sqlsrv_has_rows( $res );
- }
-
- return $ret;
- }
-
- /**
- * @param mixed $res
- * @return int
- */
- public function numFields( $res ) {
- return sqlsrv_num_fields( ResultWrapper::unwrap( $res ) );
- }
-
- /**
- * @param mixed $res
- * @param int $n
- * @return int
- */
- public function fieldName( $res, $n ) {
- return sqlsrv_field_metadata( ResultWrapper::unwrap( $res ) )[$n]['Name'];
- }
-
- /**
- * This must be called after nextSequenceVal
- * @return int|null
- */
- public function insertId() {
- return $this->lastInsertId;
- }
-
- /**
- * @param MssqlResultWrapper $res
- * @param int $row
- * @return bool
- */
- public function dataSeek( $res, $row ) {
- return $res->seek( $row );
- }
-
- /**
- * @return string
- */
- public function lastError() {
- $strRet = '';
- $retErrors = sqlsrv_errors( SQLSRV_ERR_ALL );
- if ( $retErrors != null ) {
- foreach ( $retErrors as $arrError ) {
- $strRet .= $this->formatError( $arrError ) . "\n";
- }
- } else {
- $strRet = "No errors found";
- }
-
- return $strRet;
- }
-
- /**
- * @param array $err
- * @return string
- */
- private function formatError( $err ) {
- return '[SQLSTATE ' .
- $err['SQLSTATE'] . '][Error Code ' . $err['code'] . ']' . $err['message'];
- }
-
- /**
- * @return string|int
- */
- public function lastErrno() {
- $err = sqlsrv_errors( SQLSRV_ERR_ALL );
- if ( $err !== null && isset( $err[0] ) ) {
- return $err[0]['code'];
- } else {
- return 0;
- }
- }
-
- protected function wasKnownStatementRollbackError() {
- $errors = sqlsrv_errors( SQLSRV_ERR_ALL );
- if ( !$errors ) {
- return false;
- }
- // The transaction vs statement rollback behavior depends on XACT_ABORT, so make sure
- // that the "statement has been terminated" error (3621) is specifically present.
- // https://docs.microsoft.com/en-us/sql/t-sql/statements/set-xact-abort-transact-sql
- $statementOnly = false;
- $codeWhitelist = [ '2601', '2627', '547' ];
- foreach ( $errors as $error ) {
- if ( $error['code'] == '3621' ) {
- $statementOnly = true;
- } elseif ( !in_array( $error['code'], $codeWhitelist ) ) {
- $statementOnly = false;
- break;
- }
- }
-
- return $statementOnly;
- }
-
- public function serverIsReadOnly() {
- $encDatabase = $this->addQuotes( $this->getDBname() );
- $res = $this->query(
- "SELECT IS_READ_ONLY FROM SYS.DATABASES WHERE NAME = $encDatabase",
- __METHOD__
- );
- $row = $this->fetchObject( $res );
-
- return $row ? (bool)$row->IS_READ_ONLY : false;
- }
-
- /**
- * @return int
- */
- protected function fetchAffectedRowCount() {
- return $this->lastAffectedRowCount;
- }
-
- /**
- * SELECT wrapper
- *
- * @param mixed $table Array or string, table name(s) (prefix auto-added)
- * @param mixed $vars Array or string, field name(s) to be retrieved
- * @param mixed $conds Array or string, condition(s) for WHERE
- * @param string $fname Calling function name (use __METHOD__) for logs/profiling
- * @param array $options Associative array of options (e.g.
- * [ 'GROUP BY' => 'page_title' ]), see Database::makeSelectOptions
- * code for list of supported stuff
- * @param array $join_conds Associative array of table join conditions
- * (optional) (e.g. [ 'page' => [ 'LEFT JOIN','page_latest=rev_id' ] ]
- * @return mixed Database result resource (feed to Database::fetchObject
- * or whatever), or false on failure
- * @throws DBQueryError
- * @throws DBUnexpectedError
- * @throws Exception
- */
- public function select( $table, $vars, $conds = '', $fname = __METHOD__,
- $options = [], $join_conds = []
- ) {
- $sql = $this->selectSQLText( $table, $vars, $conds, $fname, $options, $join_conds );
- if ( isset( $options['EXPLAIN'] ) ) {
- try {
- $this->scrollableCursor = false;
- $this->prepareStatements = false;
- $this->query( "SET SHOWPLAN_ALL ON" );
- $ret = $this->query( $sql, $fname );
- $this->query( "SET SHOWPLAN_ALL OFF" );
- } catch ( DBQueryError $dqe ) {
- if ( isset( $options['FOR COUNT'] ) ) {
- // likely don't have privs for SHOWPLAN, so run a select count instead
- $this->query( "SET SHOWPLAN_ALL OFF" );
- unset( $options['EXPLAIN'] );
- $ret = $this->select(
- $table,
- 'COUNT(*) AS EstimateRows',
- $conds,
- $fname,
- $options,
- $join_conds
- );
- } else {
- // someone actually wanted the query plan instead of an est row count
- // let them know of the error
- $this->scrollableCursor = true;
- $this->prepareStatements = true;
- throw $dqe;
- }
- }
- $this->scrollableCursor = true;
- $this->prepareStatements = true;
- return $ret;
- }
- return $this->query( $sql, $fname );
- }
-
- /**
- * SELECT wrapper
- *
- * @param mixed $table Array or string, table name(s) (prefix auto-added)
- * @param mixed $vars Array or string, field name(s) to be retrieved
- * @param mixed $conds Array or string, condition(s) for WHERE
- * @param string $fname Calling function name (use __METHOD__) for logs/profiling
- * @param array $options Associative array of options (e.g. [ 'GROUP BY' => 'page_title' ]),
- * see Database::makeSelectOptions code for list of supported stuff
- * @param array $join_conds Associative array of table join conditions (optional)
- * (e.g. [ 'page' => [ 'LEFT JOIN','page_latest=rev_id' ] ]
- * @return string The SQL text
- */
- public function selectSQLText( $table, $vars, $conds = '', $fname = __METHOD__,
- $options = [], $join_conds = []
- ) {
- if ( isset( $options['EXPLAIN'] ) ) {
- unset( $options['EXPLAIN'] );
- }
-
- $sql = parent::selectSQLText( $table, $vars, $conds, $fname, $options, $join_conds );
-
- // try to rewrite aggregations of bit columns (currently MAX and MIN)
- if ( strpos( $sql, 'MAX(' ) !== false || strpos( $sql, 'MIN(' ) !== false ) {
- $bitColumns = [];
- if ( is_array( $table ) ) {
- $tables = $table;
- while ( $tables ) {
- $t = array_pop( $tables );
- if ( is_array( $t ) ) {
- $tables = array_merge( $tables, $t );
- } else {
- $bitColumns += $this->getBitColumns( $this->tableName( $t ) );
- }
- }
- } else {
- $bitColumns = $this->getBitColumns( $this->tableName( $table ) );
- }
-
- foreach ( $bitColumns as $col => $info ) {
- $replace = [
- "MAX({$col})" => "MAX(CAST({$col} AS tinyint))",
- "MIN({$col})" => "MIN(CAST({$col} AS tinyint))",
- ];
- $sql = str_replace( array_keys( $replace ), array_values( $replace ), $sql );
- }
- }
-
- return $sql;
- }
-
- public function deleteJoin( $delTable, $joinTable, $delVar, $joinVar, $conds,
- $fname = __METHOD__
- ) {
- $this->scrollableCursor = false;
- try {
- parent::deleteJoin( $delTable, $joinTable, $delVar, $joinVar, $conds, $fname );
- } catch ( Exception $e ) {
- $this->scrollableCursor = true;
- throw $e;
- }
- $this->scrollableCursor = true;
- }
-
- public function delete( $table, $conds, $fname = __METHOD__ ) {
- $this->scrollableCursor = false;
- try {
- parent::delete( $table, $conds, $fname );
- } catch ( Exception $e ) {
- $this->scrollableCursor = true;
- throw $e;
- }
- $this->scrollableCursor = true;
-
- return true;
- }
-
- /**
- * Estimate rows in dataset
- * Returns estimated count, based on SHOWPLAN_ALL output
- * This is not necessarily an accurate estimate, so use sparingly
- * Returns -1 if count cannot be found
- * Takes same arguments as Database::select()
- * @param string $table
- * @param string $var
- * @param string $conds
- * @param string $fname
- * @param array $options
- * @param array $join_conds
- * @return int
- */
- public function estimateRowCount( $table, $var = '*', $conds = '',
- $fname = __METHOD__, $options = [], $join_conds = []
- ) {
- $conds = $this->normalizeConditions( $conds, $fname );
- $column = $this->extractSingleFieldFromList( $var );
- if ( is_string( $column ) && !in_array( $column, [ '*', '1' ] ) ) {
- $conds[] = "$column IS NOT NULL";
- }
-
- // http://msdn2.microsoft.com/en-us/library/aa259203.aspx
- $options['EXPLAIN'] = true;
- $options['FOR COUNT'] = true;
- $res = $this->select( $table, $var, $conds, $fname, $options, $join_conds );
-
- $rows = -1;
- if ( $res ) {
- $row = $this->fetchRow( $res );
-
- if ( isset( $row['EstimateRows'] ) ) {
- $rows = (int)$row['EstimateRows'];
- }
- }
-
- return $rows;
- }
-
- /**
- * Returns information about an index
- * If errors are explicitly ignored, returns NULL on failure
- * @param string $table
- * @param string $index
- * @param string $fname
- * @return array|bool|null
- */
- public function indexInfo( $table, $index, $fname = __METHOD__ ) {
- # This does not return the same info as MYSQL would, but that's OK
- # because MediaWiki never uses the returned value except to check for
- # the existence of indexes.
- $sql = "sp_helpindex '" . $this->tableName( $table ) . "'";
- $res = $this->query( $sql, $fname );
-
- if ( !$res ) {
- return null;
- }
-
- $result = [];
- foreach ( $res as $row ) {
- if ( $row->index_name == $index ) {
- $row->Non_unique = !stristr( $row->index_description, "unique" );
- $cols = explode( ", ", $row->index_keys );
- foreach ( $cols as $col ) {
- $row->Column_name = trim( $col );
- $result[] = clone $row;
- }
- } elseif ( $index == 'PRIMARY' && stristr( $row->index_description, 'PRIMARY' ) ) {
- $row->Non_unique = 0;
- $cols = explode( ", ", $row->index_keys );
- foreach ( $cols as $col ) {
- $row->Column_name = trim( $col );
- $result[] = clone $row;
- }
- }
- }
-
- return $result ?: false;
- }
-
- /**
- * INSERT wrapper, inserts an array into a table
- *
- * $arrToInsert 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
- * @param string $table
- * @param array $arrToInsert
- * @param string $fname
- * @param array $options
- * @return bool
- * @throws Exception
- */
- public function insert( $table, $arrToInsert, $fname = __METHOD__, $options = [] ) {
- # No rows to insert, easy just return now
- if ( !count( $arrToInsert ) ) {
- return true;
- }
-
- if ( !is_array( $options ) ) {
- $options = [ $options ];
- }
-
- $table = $this->tableName( $table );
-
- if ( !( isset( $arrToInsert[0] ) && is_array( $arrToInsert[0] ) ) ) { // Not multi row
- $arrToInsert = [ 0 => $arrToInsert ]; // make everything multi row compatible
- }
-
- // We know the table we're inserting into, get its identity column
- $identity = null;
- // strip matching square brackets and the db/schema from table name
- $tableRawArr = explode( '.', preg_replace( '#\[([^\]]*)\]#', '$1', $table ) );
- $tableRaw = array_pop( $tableRawArr );
- $res = $this->doQuery(
- "SELECT NAME AS idColumn FROM SYS.IDENTITY_COLUMNS " .
- "WHERE OBJECT_NAME(OBJECT_ID)='{$tableRaw}'"
- );
- if ( $res && sqlsrv_has_rows( $res ) ) {
- // There is an identity for this table.
- $identityArr = sqlsrv_fetch_array( $res, SQLSRV_FETCH_ASSOC );
- $identity = array_pop( $identityArr );
- }
- sqlsrv_free_stmt( $res );
-
- // Determine binary/varbinary fields so we can encode data as a hex string like 0xABCDEF
- $binaryColumns = $this->getBinaryColumns( $table );
-
- // INSERT IGNORE is not supported by SQL Server
- // remove IGNORE from options list and set ignore flag to true
- if ( in_array( 'IGNORE', $options ) ) {
- $options = array_diff( $options, [ 'IGNORE' ] );
- $this->ignoreDupKeyErrors = true;
- }
-
- $ret = null;
- foreach ( $arrToInsert as $a ) {
- // start out with empty identity column, this is so we can return
- // it as a result of the INSERT logic
- $sqlPre = '';
- $sqlPost = '';
- $identityClause = '';
-
- // if we have an identity column
- if ( $identity ) {
- // iterate through
- foreach ( $a as $k => $v ) {
- if ( $k == $identity ) {
- if ( !is_null( $v ) ) {
- // there is a value being passed to us,
- // we need to turn on and off inserted identity
- $sqlPre = "SET IDENTITY_INSERT $table ON;";
- $sqlPost = ";SET IDENTITY_INSERT $table OFF;";
- } else {
- // we can't insert NULL into an identity column,
- // so remove the column from the insert.
- unset( $a[$k] );
- }
- }
- }
-
- // we want to output an identity column as result
- $identityClause = "OUTPUT INSERTED.$identity ";
- }
-
- $keys = array_keys( $a );
-
- // Build the actual query
- $sql = $sqlPre . 'INSERT ' . implode( ' ', $options ) .
- " INTO $table (" . implode( ',', $keys ) . ") $identityClause VALUES (";
-
- $first = true;
- foreach ( $a as $key => $value ) {
- if ( isset( $binaryColumns[$key] ) ) {
- $value = new MssqlBlob( $value );
- }
- if ( $first ) {
- $first = false;
- } else {
- $sql .= ',';
- }
- if ( is_null( $value ) ) {
- $sql .= 'null';
- } else {
- $sql .= $this->addQuotes( $value );
- }
- }
- $sql .= ')' . $sqlPost;
-
- // Run the query
- $this->scrollableCursor = false;
- try {
- $ret = $this->query( $sql );
- } catch ( Exception $e ) {
- $this->scrollableCursor = true;
- $this->ignoreDupKeyErrors = false;
- throw $e;
- }
- $this->scrollableCursor = true;
-
- if ( $ret instanceof IResultWrapper && !is_null( $identity ) ) {
- // Then we want to get the identity column value we were assigned and save it off
- $row = $ret->fetchObject();
- if ( is_object( $row ) ) {
- $this->lastInsertId = $row->$identity;
- // It seems that mAffectedRows is -1 sometimes when OUTPUT INSERTED.identity is
- // used if we got an identity back, we know for sure a row was affected, so
- // adjust that here
- if ( $this->lastAffectedRowCount == -1 ) {
- $this->lastAffectedRowCount = 1;
- }
- }
- }
- }
-
- $this->ignoreDupKeyErrors = false;
-
- return true;
- }
-
- /**
- * INSERT SELECT wrapper
- * $varMap must be an associative array of the form [ 'dest1' => 'source1', ... ]
- * Source items may be literals rather than field names, but strings should
- * be quoted with Database::addQuotes().
- * @param string $destTable
- * @param array|string $srcTable May be an array of tables.
- * @param array $varMap
- * @param array $conds May be "*" to copy the whole table.
- * @param string $fname
- * @param array $insertOptions
- * @param array $selectOptions
- * @param array $selectJoinConds
- * @throws Exception
- */
- protected function nativeInsertSelect( $destTable, $srcTable, $varMap, $conds, $fname = __METHOD__,
- $insertOptions = [], $selectOptions = [], $selectJoinConds = []
- ) {
- $this->scrollableCursor = false;
- try {
- parent::nativeInsertSelect(
- $destTable,
- $srcTable,
- $varMap,
- $conds,
- $fname,
- $insertOptions,
- $selectOptions,
- $selectJoinConds
- );
- } catch ( Exception $e ) {
- $this->scrollableCursor = true;
- throw $e;
- }
- $this->scrollableCursor = true;
- }
-
- /**
- * UPDATE wrapper. Takes a condition array and a SET array.
- *
- * @param string $table Name of the table to UPDATE. This will be passed through
- * Database::tableName().
- *
- * @param array $values An array of values to SET. For each array element,
- * the key gives the field name, and the value gives the data
- * to set that field to. The data will be quoted by
- * Database::addQuotes().
- *
- * @param array $conds An array of conditions (WHERE). See
- * Database::select() for the details of the format of
- * condition arrays. Use '*' to update all rows.
- *
- * @param string $fname The function name of the caller (from __METHOD__),
- * for logging and profiling.
- *
- * @param array $options An array of UPDATE options, can be:
- * - IGNORE: Ignore unique key conflicts
- * @return bool
- * @throws DBUnexpectedError
- * @throws Exception
- */
- function update( $table, $values, $conds, $fname = __METHOD__, $options = [] ) {
- $table = $this->tableName( $table );
- $binaryColumns = $this->getBinaryColumns( $table );
-
- $opts = $this->makeUpdateOptions( $options );
- $sql = "UPDATE $opts $table SET " . $this->makeList( $values, LIST_SET, $binaryColumns );
-
- if ( $conds !== [] && $conds !== '*' ) {
- $sql .= " WHERE " . $this->makeList( $conds, LIST_AND, $binaryColumns );
- }
-
- $this->scrollableCursor = false;
- try {
- $this->query( $sql );
- } catch ( Exception $e ) {
- $this->scrollableCursor = true;
- throw $e;
- }
- $this->scrollableCursor = true;
- return true;
- }
-
- /**
- * Makes an encoded list of strings from an array
- * @param array $a Containing the data
- * @param int $mode Constant
- * - LIST_COMMA: comma separated, no field names
- * - LIST_AND: ANDed WHERE clause (without the WHERE). See
- * the documentation for $conds in Database::select().
- * - LIST_OR: ORed WHERE clause (without the WHERE)
- * - LIST_SET: comma separated with field names, like a SET clause
- * - LIST_NAMES: comma separated field names
- * @param array $binaryColumns Contains a list of column names that are binary types
- * This is a custom parameter only present for MS SQL.
- *
- * @throws DBUnexpectedError
- * @return string
- */
- public function makeList( $a, $mode = LIST_COMMA, $binaryColumns = [] ) {
- if ( !is_array( $a ) ) {
- throw new DBUnexpectedError( $this, __METHOD__ . ' called with incorrect parameters' );
- }
-
- if ( $mode != LIST_NAMES ) {
- // In MS SQL, values need to be specially encoded when they are
- // inserted into binary fields. Perform this necessary encoding
- // for the specified set of columns.
- foreach ( array_keys( $a ) as $field ) {
- if ( !isset( $binaryColumns[$field] ) ) {
- continue;
- }
-
- if ( is_array( $a[$field] ) ) {
- foreach ( $a[$field] as &$v ) {
- $v = new MssqlBlob( $v );
- }
- unset( $v );
- } else {
- $a[$field] = new MssqlBlob( $a[$field] );
- }
- }
- }
-
- return parent::makeList( $a, $mode );
- }
-
- /**
- * @param string $table
- * @param string $field
- * @return int Returns the size of a text field, or -1 for "unlimited"
- */
- public function textFieldSize( $table, $field ) {
- $table = $this->tableName( $table );
- $sql = "SELECT CHARACTER_MAXIMUM_LENGTH,DATA_TYPE FROM INFORMATION_SCHEMA.Columns
- WHERE TABLE_NAME = '$table' AND COLUMN_NAME = '$field'";
- $res = $this->query( $sql );
- $row = $this->fetchRow( $res );
- $size = -1;
- if ( strtolower( $row['DATA_TYPE'] ) != 'text' ) {
- $size = $row['CHARACTER_MAXIMUM_LENGTH'];
- }
-
- return $size;
- }
-
- /**
- * Construct a LIMIT query with optional offset
- * This is used for query pages
- *
- * @param string $sql SQL query we will append the limit too
- * @param int $limit The SQL limit
- * @param bool|int $offset The SQL offset (default false)
- * @return array|string
- * @throws DBUnexpectedError
- */
- public function limitResult( $sql, $limit, $offset = false ) {
- if ( $offset === false || $offset == 0 ) {
- if ( strpos( $sql, "SELECT" ) === false ) {
- return "TOP {$limit} " . $sql;
- } else {
- return preg_replace( '/\bSELECT(\s+DISTINCT)?\b/Dsi',
- 'SELECT$1 TOP ' . $limit, $sql, 1 );
- }
- } else {
- // This one is fun, we need to pull out the select list as well as any ORDER BY clause
- $select = $orderby = [];
- $s1 = preg_match( '#SELECT\s+(.+?)\s+FROM#Dis', $sql, $select );
- $s2 = preg_match( '#(ORDER BY\s+.+?)(\s*FOR XML .*)?$#Dis', $sql, $orderby );
- $postOrder = '';
- $first = $offset + 1;
- $last = $offset + $limit;
- $sub1 = 'sub_' . $this->subqueryId;
- $sub2 = 'sub_' . ( $this->subqueryId + 1 );
- $this->subqueryId += 2;
- if ( !$s1 ) {
- // wat
- throw new DBUnexpectedError( $this, "Attempting to LIMIT a non-SELECT query\n" );
- }
- if ( !$s2 ) {
- // no ORDER BY
- $overOrder = 'ORDER BY (SELECT 1)';
- } else {
- if ( !isset( $orderby[2] ) || !$orderby[2] ) {
- // don't need to strip it out if we're using a FOR XML clause
- $sql = str_replace( $orderby[1], '', $sql );
- }
- $overOrder = $orderby[1];
- $postOrder = ' ' . $overOrder;
- }
- $sql = "SELECT {$select[1]}
- FROM (
- SELECT ROW_NUMBER() OVER({$overOrder}) AS rowNumber, *
- FROM ({$sql}) {$sub1}
- ) {$sub2}
- WHERE rowNumber BETWEEN {$first} AND {$last}{$postOrder}";
-
- return $sql;
- }
- }
-
- /**
- * If there is a limit clause, parse it, strip it, and pass the remaining
- * SQL through limitResult() with the appropriate parameters. Not the
- * prettiest solution, but better than building a whole new parser. This
- * exists becase there are still too many extensions that don't use dynamic
- * sql generation.
- *
- * @param string $sql
- * @return array|mixed|string
- */
- public function LimitToTopN( $sql ) {
- // Matches: LIMIT {[offset,] row_count | row_count OFFSET offset}
- $pattern = '/\bLIMIT\s+((([0-9]+)\s*,\s*)?([0-9]+)(\s+OFFSET\s+([0-9]+))?)/i';
- if ( preg_match( $pattern, $sql, $matches ) ) {
- $row_count = $matches[4];
- $offset = $matches[3] ?: $matches[6] ?: false;
-
- // strip the matching LIMIT clause out
- $sql = str_replace( $matches[0], '', $sql );
-
- return $this->limitResult( $sql, $row_count, $offset );
- }
-
- return $sql;
- }
-
- /**
- * @return string Wikitext of a link to the server software's web site
- */
- public function getSoftwareLink() {
- return "[{{int:version-db-mssql-url}} MS SQL Server]";
- }
-
- /**
- * @return string Version information from the database
- */
- public function getServerVersion() {
- $server_info = sqlsrv_server_info( $this->conn );
- $version = $server_info['SQLServerVersion'] ?? 'Error';
-
- return $version;
- }
-
- /**
- * @param string $table
- * @param string $fname
- * @return bool
- */
- public function tableExists( $table, $fname = __METHOD__ ) {
- list( $db, $schema, $table ) = $this->tableName( $table, 'split' );
-
- if ( $db !== false ) {
- // remote database
- $this->queryLogger->error( "Attempting to call tableExists on a remote table" );
- return false;
- }
-
- if ( $schema === false ) {
- $schema = $this->dbSchema();
- }
-
- $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;
- }
- }
-
- /**
- * Query whether a given column exists in the mediawiki schema
- * @param string $table
- * @param string $field
- * @param string $fname
- * @return bool
- */
- public function fieldExists( $table, $field, $fname = __METHOD__ ) {
- list( $db, $schema, $table ) = $this->tableName( $table, 'split' );
-
- if ( $db !== false ) {
- // remote database
- $this->queryLogger->error( "Attempting to call fieldExists on a remote table" );
- return false;
- }
-
- $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;
- }
- }
-
- public function fieldInfo( $table, $field ) {
- list( $db, $schema, $table ) = $this->tableName( $table, 'split' );
-
- if ( $db !== false ) {
- // remote database
- $this->queryLogger->error( "Attempting to call fieldInfo on a remote table" );
- return false;
- }
-
- $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 );
- }
-
- return false;
- }
-
- protected function doSavepoint( $identifier, $fname ) {
- $this->query( 'SAVE TRANSACTION ' . $this->addIdentifierQuotes( $identifier ), $fname );
- }
-
- protected function doReleaseSavepoint( $identifier, $fname ) {
- // Not supported. Also not really needed, a new doSavepoint() for the
- // same identifier will overwrite the old.
- }
-
- protected function doRollbackToSavepoint( $identifier, $fname ) {
- $this->query( 'ROLLBACK TRANSACTION ' . $this->addIdentifierQuotes( $identifier ), $fname );
- }
-
- protected function doBegin( $fname = __METHOD__ ) {
- if ( !sqlsrv_begin_transaction( $this->conn ) ) {
- $this->reportQueryError( $this->lastError(), $this->lastErrno(), 'BEGIN', $fname );
- }
- }
-
- /**
- * End a transaction
- * @param string $fname
- */
- protected function doCommit( $fname = __METHOD__ ) {
- if ( !sqlsrv_commit( $this->conn ) ) {
- $this->reportQueryError( $this->lastError(), $this->lastErrno(), 'COMMIT', $fname );
- }
- }
-
- /**
- * Rollback a transaction.
- * No-op on non-transactional databases.
- * @param string $fname
- */
- protected function doRollback( $fname = __METHOD__ ) {
- if ( !sqlsrv_rollback( $this->conn ) ) {
- $this->queryLogger->error(
- "{fname}\t{db_server}\t{errno}\t{error}\t",
- $this->getLogContext( [
- 'errno' => $this->lastErrno(),
- 'error' => $this->lastError(),
- 'fname' => $fname,
- 'trace' => ( new RuntimeException() )->getTraceAsString()
- ] )
- );
- }
- }
-
- /**
- * @param string $s
- * @return string
- */
- public function strencode( $s ) {
- // Should not be called by us
- return str_replace( "'", "''", $s );
- }
-
- /**
- * @param string|int|null|bool|Blob $s
- * @return string|int
- */
- public function addQuotes( $s ) {
- if ( $s instanceof MssqlBlob ) {
- return $s->fetch();
- } elseif ( $s instanceof Blob ) {
- // this shouldn't really ever be called, but it's here if needed
- // (and will quite possibly make the SQL error out)
- $blob = new MssqlBlob( $s->fetch() );
- return $blob->fetch();
- } else {
- if ( is_bool( $s ) ) {
- $s = $s ? 1 : 0;
- }
- return parent::addQuotes( $s );
- }
- }
-
- /**
- * @param string $s
- * @return string
- */
- public function addIdentifierQuotes( $s ) {
- // http://msdn.microsoft.com/en-us/library/aa223962.aspx
- return '[' . $s . ']';
- }
-
- /**
- * @param string $name
- * @return bool
- */
- public function isQuotedIdentifier( $name ) {
- return strlen( $name ) && $name[0] == '[' && substr( $name, -1, 1 ) == ']';
- }
-
- /**
- * MS SQL supports more pattern operators than other databases (ex: [,],^)
- *
- * @param string $s
- * @param string $escapeChar
- * @return string
- */
- protected function escapeLikeInternal( $s, $escapeChar = '`' ) {
- return str_replace( [ $escapeChar, '%', '_', '[', ']', '^' ],
- [ "{$escapeChar}{$escapeChar}", "{$escapeChar}%", "{$escapeChar}_",
- "{$escapeChar}[", "{$escapeChar}]", "{$escapeChar}^" ],
- $s );
- }
-
- protected function doSelectDomain( DatabaseDomain $domain ) {
- if ( $domain->getSchema() !== null ) {
- throw new DBExpectedError(
- $this,
- __CLASS__ . ": domain '{$domain->getId()}' has a schema component"
- );
- }
-
- $database = $domain->getDatabase();
- if ( $database !== $this->getDBname() ) {
- $sql = 'USE ' . $this->addIdentifierQuotes( $database );
- list( $res, $err, $errno ) =
- $this->executeQuery( $sql, __METHOD__, self::QUERY_IGNORE_DBO_TRX );
-
- if ( $res === false ) {
- $this->reportQueryError( $err, $errno, $sql, __METHOD__ );
- return false; // unreachable
- }
- }
- // Update that domain fields on success (no exception thrown)
- $this->currentDomain = $domain;
-
- return true;
- }
-
- /**
- * @param array $options An associative array of options to be turned into
- * an SQL query, valid keys are listed in the function.
- * @return array
- */
- public function makeSelectOptions( $options ) {
- $tailOpts = '';
- $startOpts = '';
-
- $noKeyOptions = [];
- foreach ( $options as $key => $option ) {
- if ( is_numeric( $key ) ) {
- $noKeyOptions[$option] = true;
- }
- }
-
- $tailOpts .= $this->makeGroupByWithHaving( $options );
-
- $tailOpts .= $this->makeOrderBy( $options );
-
- if ( isset( $noKeyOptions['DISTINCT'] ) || isset( $noKeyOptions['DISTINCTROW'] ) ) {
- $startOpts .= 'DISTINCT';
- }
-
- if ( isset( $noKeyOptions['FOR XML'] ) ) {
- // used in group concat field emulation
- $tailOpts .= " FOR XML PATH('')";
- }
-
- // we want this to be compatible with the output of parent::makeSelectOptions()
- return [ $startOpts, '', $tailOpts, '', '' ];
- }
-
- public function getType() {
- return 'mssql';
- }
-
- /**
- * @param array $stringList
- * @return string
- */
- public function buildConcat( $stringList ) {
- return implode( ' + ', $stringList );
- }
-
- /**
- * Build a GROUP_CONCAT or equivalent statement for a query.
- * MS SQL doesn't have GROUP_CONCAT so we emulate it with other stuff (and boy is it nasty)
- *
- * This is useful for combining a field for several rows into a single string.
- * NULL values will not appear in the output, duplicated values will appear,
- * and the resulting delimiter-separated values have no defined sort order.
- * Code using the results may need to use the PHP unique() or sort() methods.
- *
- * @param string $delim Glue to bind the results together
- * @param string|array $table Table name
- * @param string $field Field name
- * @param string|array $conds Conditions
- * @param string|array $join_conds Join conditions
- * @return string SQL text
- * @since 1.23
- */
- public function buildGroupConcatField( $delim, $table, $field, $conds = '',
- $join_conds = []
- ) {
- $gcsq = 'gcsq_' . $this->subqueryId;
- $this->subqueryId++;
-
- $delimLen = strlen( $delim );
- $fld = "{$field} + {$this->addQuotes( $delim )}";
- $sql = "(SELECT LEFT({$field}, LEN({$field}) - {$delimLen}) FROM ("
- . $this->selectSQLText( $table, $fld, $conds, null, [ 'FOR XML' ], $join_conds )
- . ") {$gcsq} ({$field}))";
-
- return $sql;
- }
-
- public function buildSubstring( $input, $startPosition, $length = null ) {
- $this->assertBuildSubstringParams( $startPosition, $length );
- if ( $length === null ) {
- /**
- * MSSQL doesn't allow an empty length parameter, so when we don't want to limit the
- * length returned use the default maximum size of text.
- * @see https://docs.microsoft.com/en-us/sql/t-sql/statements/set-textsize-transact-sql
- */
- $length = 2147483647;
- }
- return 'SUBSTRING(' . implode( ',', [ $input, $startPosition, $length ] ) . ')';
- }
-
- /**
- * Returns an associative array for fields that are of type varbinary, binary, or image
- * $table can be either a raw table name or passed through tableName() first
- * @param string $table
- * @return array
- */
- private function getBinaryColumns( $table ) {
- $tableRawArr = explode( '.', preg_replace( '#\[([^\]]*)\]#', '$1', $table ) );
- $tableRaw = array_pop( $tableRawArr );
-
- if ( $this->binaryColumnCache === null ) {
- $this->populateColumnCaches();
- }
-
- return $this->binaryColumnCache[$tableRaw] ?? [];
- }
-
- /**
- * @param string $table
- * @return array
- */
- private function getBitColumns( $table ) {
- $tableRawArr = explode( '.', preg_replace( '#\[([^\]]*)\]#', '$1', $table ) );
- $tableRaw = array_pop( $tableRawArr );
-
- if ( $this->bitColumnCache === null ) {
- $this->populateColumnCaches();
- }
-
- return $this->bitColumnCache[$tableRaw] ?? [];
- }
-
- private function populateColumnCaches() {
- $res = $this->select( 'INFORMATION_SCHEMA.COLUMNS', '*',
- [
- 'TABLE_CATALOG' => $this->getDBname(),
- 'TABLE_SCHEMA' => $this->dbSchema(),
- 'DATA_TYPE' => [ 'varbinary', 'binary', 'image', 'bit' ]
- ] );
-
- $this->binaryColumnCache = [];
- $this->bitColumnCache = [];
- foreach ( $res as $row ) {
- if ( $row->DATA_TYPE == 'bit' ) {
- $this->bitColumnCache[$row->TABLE_NAME][$row->COLUMN_NAME] = $row;
- } else {
- $this->binaryColumnCache[$row->TABLE_NAME][$row->COLUMN_NAME] = $row;
- }
- }
- }
-
- /**
- * @param string $name
- * @param string $format One of "quoted" (default), "raw", or "split".
- * @return string|array When the requested $format is "split", a list of database, schema, and
- * table name is returned. Database and schema can be `false`.
- */
- function tableName( $name, $format = 'quoted' ) {
- # Replace reserved words with better ones
- switch ( $name ) {
- case 'user':
- return $this->realTableName( 'mwuser', $format );
- default:
- return $this->realTableName( $name, $format );
- }
- }
-
- /**
- * call this instead of tableName() in the updater when renaming tables
- * @param string $name
- * @param string $format One of "quoted" (default), "raw", or "split".
- * @return string|array When the requested $format is "split", a list of database, schema, and
- * table name is returned. Database and schema can be `false`.
- * @private
- */
- function realTableName( $name, $format = 'quoted' ) {
- $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)
- return array_pad( explode( '.', $table, 3 ), -3, false );
- }
- return $table;
- }
-
- /**
- * Delete a table
- * @param string $tableName
- * @param string $fName
- * @return bool|IResultWrapper
- * @since 1.18
- */
- public function dropTable( $tableName, $fName = __METHOD__ ) {
- if ( !$this->tableExists( $tableName, $fName ) ) {
- return false;
- }
-
- // parent function incorrectly appends CASCADE, which we don't want
- $sql = "DROP TABLE " . $this->tableName( $tableName );
-
- return $this->query( $sql, $fName );
- }
-
- /**
- * Called in the installer and updater.
- * Probably doesn't need to be called anywhere else in the codebase.
- * @param bool|null $value
- * @return bool|null
- */
- public function prepareStatements( $value = null ) {
- $old = $this->prepareStatements;
- if ( $value !== null ) {
- $this->prepareStatements = $value;
- }
-
- return $old;
- }
-
- /**
- * Called in the installer and updater.
- * Probably doesn't need to be called anywhere else in the codebase.
- * @param bool|null $value
- * @return bool|null
- */
- public function scrollableCursor( $value = null ) {
- $old = $this->scrollableCursor;
- if ( $value !== null ) {
- $this->scrollableCursor = $value;
- }
-
- return $old;
- }
-
- public function buildStringCast( $field ) {
- return "CAST( $field AS NVARCHAR )";
- }
-
- public static function getAttributes() {
- return [ self::ATTR_SCHEMAS_AS_TABLE_GROUPS => true ];
- }
-}
-
-/**
- * @deprecated since 1.29
- */
-class_alias( DatabaseMssql::class, 'DatabaseMssql' );
+++ /dev/null
---
--- patch-actor-table.sql
---
--- T167246. Add an `actor` table and various columns (and temporary tables) to reference it.
-
-CREATE TABLE /*_*/actor (
- actor_id bigint NOT NULL CONSTRAINT PK_actor PRIMARY KEY IDENTITY(0,1),
- actor_user int,
- actor_name nvarchar(255) NOT NULL
-);
-CREATE UNIQUE INDEX /*i*/actor_user ON /*_*/actor (actor_user);
-CREATE UNIQUE INDEX /*i*/actor_name ON /*_*/actor (actor_name);
-
--- Dummy
-INSERT INTO /*_*/actor (actor_name) VALUES ('##Anonymous##');
-
-CREATE TABLE /*_*/revision_actor_temp (
- revactor_rev int NOT NULL CONSTRAINT FK_revactor_rev FOREIGN KEY REFERENCES /*_*/revision(rev_id) ON DELETE CASCADE,
- revactor_actor bigint NOT NULL,
- revactor_timestamp varchar(14) NOT NULL CONSTRAINT DF_revactor_timestamp DEFAULT '',
- revactor_page int NOT NULL,
- CONSTRAINT PK_revision_actor_temp PRIMARY KEY (revactor_rev, revactor_actor)
-);
-CREATE UNIQUE INDEX /*i*/revactor_rev ON /*_*/revision_actor_temp (revactor_rev);
-CREATE INDEX /*i*/actor_timestamp ON /*_*/revision_actor_temp (revactor_actor,revactor_timestamp);
-CREATE INDEX /*i*/page_actor_timestamp ON /*_*/revision_actor_temp (revactor_page,revactor_actor,revactor_timestamp);
-
-ALTER TABLE /*_*/archive ADD CONSTRAINT DF_ar_user_text DEFAULT '' FOR ar_user_text;
-ALTER TABLE /*_*/archive ADD ar_actor bigint NOT NULL CONSTRAINT DF_ar_actor DEFAULT 0;
-CREATE INDEX /*i*/ar_actor_timestamp ON /*_*/archive (ar_actor,ar_timestamp);
-
-ALTER TABLE /*_*/ipblocks ADD ipb_by_actor bigint NOT NULL CONSTRAINT DF_ipb_by_actor DEFAULT 0;
-
-ALTER TABLE /*_*/image ADD CONSTRAINT DF_img_user_text DEFAULT '' FOR img_user_text;
-ALTER TABLE /*_*/image ADD img_actor bigint NOT NULL CONSTRAINT DF_img_actor DEFAULT 0;
-CREATE INDEX /*i*/img_actor_timestamp ON /*_*/image (img_actor, img_timestamp);
-
-ALTER TABLE /*_*/oldimage ADD CONSTRAINT DF_oi_user_text DEFAULT '' FOR oi_user_text;
-ALTER TABLE /*_*/oldimage ADD oi_actor bigint NOT NULL CONSTRAINT DF_oi_actor DEFAULT 0;
-CREATE INDEX /*i*/oi_actor_timestamp ON /*_*/oldimage (oi_actor,oi_timestamp);
-
-ALTER TABLE /*_*/filearchive ADD CONSTRAINT DF_fa_user_text DEFAULT '' FOR fa_user_text;
-ALTER TABLE /*_*/filearchive ADD fa_actor bigint NOT NULL CONSTRAINT DF_fa_actor DEFAULT 0;
-CREATE INDEX /*i*/fa_actor_timestamp ON /*_*/filearchive (fa_actor,fa_timestamp);
-
-ALTER TABLE /*_*/recentchanges ADD CONSTRAINT DF_rc_user_text DEFAULT '' FOR rc_user_text;
-ALTER TABLE /*_*/recentchanges ADD rc_actor bigint NOT NULL CONSTRAINT DF_rc_actor DEFAULT 0;
-CREATE INDEX /*i*/rc_ns_actor ON /*_*/recentchanges (rc_namespace, rc_actor);
-CREATE INDEX /*i*/rc_actor ON /*_*/recentchanges (rc_actor, rc_timestamp);
-
-ALTER TABLE /*_*/logging ADD log_actor bigint NOT NULL CONSTRAINT DF_log_actor DEFAULT 0;
-CREATE INDEX /*i*/actor_time ON /*_*/logging (log_actor, log_timestamp);
-CREATE INDEX /*i*/log_actor_type_time ON /*_*/logging (log_actor, log_type, log_timestamp);
+++ /dev/null
-ALTER TABLE /*$wgDBprefix*/image
- DROP CONSTRAINT img_media_type_ckc;
-
-ALTER TABLE /*$wgDBprefix*/image
- ADD CONSTRAINT img_media_type_ckc
- CHECK (img_media_type IN("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE", "3D"));
-
-ALTER TABLE /*$wgDBprefix*/oldimage
- DROP CONSTRAINT oi_media_type_ckc;
-
-ALTER TABLE /*$wgDBprefix*/oldimage
- ADD CONSTRAINT oi_media_type_ckc
- CHECK (oi_media_type IN("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE", "3D"));
-
-ALTER TABLE /*$wgDBprefix*/filearchive
- DROP CONSTRAINT fa_media_type_ckc;
-
-ALTER TABLE /*$wgDBprefix*/filearchive
- ADD CONSTRAINT fa_media_type_ckc
- CHECK (fa_media_type IN("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE", "3D"));
-
-ALTER TABLE /*$wgDBprefix*/uploadstash
- DROP CONSTRAINT us_media_type_ckc;
-
-ALTER TABLE /*$wgDBprefix*/uploadstash
- ADD CONSTRAINT us_media_type_ckc
- CHECK (us_media_type IN("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE", "3D"));
+++ /dev/null
--- @since 1.27
-CREATE INDEX /*i*/cl_collation_ext ON /*_*/categorylinks (cl_collation, cl_to, cl_type, cl_from);
+++ /dev/null
-DROP INDEX /*i*/oi_name_archive_name ON /*_*/oldimage;
+++ /dev/null
-ALTER TABLE /*_*/archive ALTER COLUMN ar_rev_id INT NOT NULL;
+++ /dev/null
-DECLARE @base nvarchar(max),
- @SQL nvarchar(max),
- @id sysname;--
-
-SET @base = 'ALTER TABLE /*_*/archive DROP CONSTRAINT ';--
-
-SELECT @id = fk.name
-FROM sys.foreign_keys fk
-JOIN sys.foreign_key_columns fkc
- ON fkc.constraint_object_id = fk.object_id
-JOIN sys.columns c
- ON c.column_id = fkc.parent_column_id
- AND c.object_id = fkc.parent_object_id
-WHERE
- fk.parent_object_id = OBJECT_ID('/*_*/archive')
- AND fk.referenced_object_id = OBJECT_ID('/*_*/revision')
- AND c.name = 'ar_parent_id';--
-
-SET @SQL = @base + @id;--
-
-EXEC sp_executesql @SQL;--
-
--- while we're at it, let's fix up the other foreign key constraints on archive
--- as future patches touch constraints on other tables, they'll take the time to update constraint names there as well
-SELECT @id = fk.name
-FROM sys.foreign_keys fk
-JOIN sys.foreign_key_columns fkc
- ON fkc.constraint_object_id = fk.object_id
-JOIN sys.columns c
- ON c.column_id = fkc.parent_column_id
- AND c.object_id = fkc.parent_object_id
-WHERE
- fk.parent_object_id = OBJECT_ID('/*_*/archive')
- AND fk.referenced_object_id = OBJECT_ID('/*_*/mwuser')
- AND c.name = 'ar_user';--
-
-SET @SQL = @base + @id;--
-
-EXEC sp_executesql @SQL;--
-
-ALTER TABLE /*_*/archive ADD CONSTRAINT ar_user__user_id__fk FOREIGN KEY (ar_user) REFERENCES /*_*/mwuser(user_id);--
-
-SELECT @id = fk.name
-FROM sys.foreign_keys fk
-JOIN sys.foreign_key_columns fkc
- ON fkc.constraint_object_id = fk.object_id
-JOIN sys.columns c
- ON c.column_id = fkc.parent_column_id
- AND c.object_id = fkc.parent_object_id
-WHERE
- fk.parent_object_id = OBJECT_ID('/*_*/archive')
- AND fk.referenced_object_id = OBJECT_ID('/*_*/text')
- AND c.name = 'ar_text_id';--
-
-SET @SQL = @base + @id;--
-
-EXEC sp_executesql @SQL;--
-
-ALTER TABLE /*_*/archive ADD CONSTRAINT ar_text_id__old_id__fk FOREIGN KEY (ar_text_id) REFERENCES /*_*/text(old_id) ON DELETE CASCADE;
+++ /dev/null
---
--- This table contains a user's bot passwords: passwords that allow access to
--- the account via the API with limited rights.
---
-CREATE TABLE /*_*/bot_passwords (
- bp_user int NOT NULL REFERENCES /*_*/mwuser(user_id) ON DELETE CASCADE,
- bp_app_id nvarchar(32) NOT NULL,
- bp_password nvarchar(255) NOT NULL,
- bp_token nvarchar(255) NOT NULL,
- bp_restrictions nvarchar(max) NOT NULL,
- bp_grants nvarchar(max) NOT NULL,
- PRIMARY KEY (bp_user, bp_app_id)
-);
+++ /dev/null
-DECLARE @baseSQL nvarchar(max),
- @SQL nvarchar(max),
- @id sysname;--
-
-SET @baseSQL = 'ALTER TABLE /*_*/categorylinks DROP CONSTRAINT ';--
-
-SELECT @id = cc.name
-FROM sys.check_constraints cc
-JOIN sys.columns c
- ON c.object_id = cc.parent_object_id
- AND c.column_id = cc.parent_column_id
-WHERE
- cc.parent_object_id = OBJECT_ID('/*_*/categorylinks')
- AND c.name = 'cl_type';--
-
-SET @SQL = @baseSQL + @id;--
-
-EXEC sp_executesql @SQL;--
-
-ALTER TABLE /*_*/categorylinks ADD CONSTRAINT cl_type_ckc CHECK (cl_type IN('page', 'subcat', 'file'));
+++ /dev/null
--- Primary key in change_tag table
-
-ALTER TABLE /*_*/change_tag ADD ct_id INT IDENTITY;
-ALTER TABLE /*_*/change_tag ADD CONSTRAINT pk_change_tag PRIMARY KEY(ct_id)
+++ /dev/null
---
--- Add ctd_tag_id to change_tag table to normalize it
---
-ALTER TABLE /*_*/change_tag
- ADD COLUMN ct_tag_id int NULL CONSTRAINT ctd_tag_id__fk FOREIGN KEY REFERENCES /*_*/change_tag_def(ctd_id);
-
-CREATE INDEX /*i*/change_tag_tag_id_id ON /*_*/change_tag (ct_tag_id,ct_rc_id,ct_rev_id,ct_log_id);
+++ /dev/null
--- Table defining tag names for IDs. Also stores hit counts to avoid expensive queries on change_tag
-
-CREATE TABLE /*_*/change_tag_def (
- -- Numerical ID of the tag (ct_tag_id refers to this)
- ctd_id int NOT NULL CONSTRAINT PK_change_tag_def PRIMARY KEY IDENTITY,
- -- Symbolic name of the tag (what would previously be put in ct_tag)
- ctd_name nvarchar(255) NOT NULL,
- -- Whether this tag was defined manually by a privileged user using Special:Tags
- ctd_user_defined tinyint NOT NULL CONSTRAINT DF_ctd_user_defined DEFAULT 0,
- -- Number of times this tag was used
- ctd_count int NOT NULL CONSTRAINT DF_ctd_count DEFAULT 0
-) /*$wgDBTableOptions*/;
-
-CREATE UNIQUE INDEX /*i*/ctd_name ON /*_*/change_tag_def (ctd_name);
-CREATE INDEX /*i*/ctd_count ON /*_*/change_tag_def (ctd_count);
-CREATE INDEX /*i*/ctd_user_defined ON /*_*/change_tag_def (ctd_user_defined);
+++ /dev/null
---
--- patch-comment-table.sql
---
--- T166732. Add a `comment` table and various columns (and temporary tables) to reference it.
-
-CREATE TABLE /*_*/comment (
- comment_id bigint NOT NULL PRIMARY KEY IDENTITY(0,1),
- comment_hash INT NOT NULL,
- comment_text nvarchar(max) NOT NULL,
- comment_data nvarchar(max)
-);
-CREATE INDEX /*i*/comment_hash ON /*_*/comment (comment_hash);
-
--- dummy row for FKs. Hash is intentionally wrong so CommentStore won't match it.
-INSERT INTO /*_*/comment (comment_hash, comment_text) VALUES (-1, '** dummy **');
-
-
-CREATE TABLE /*_*/revision_comment_temp (
- revcomment_rev INT NOT NULL CONSTRAINT FK_revcomment_rev FOREIGN KEY REFERENCES /*_*/revision(rev_id) ON DELETE CASCADE,
- revcomment_comment_id bigint NOT NULL CONSTRAINT FK_revcomment_comment_id FOREIGN KEY REFERENCES /*_*/comment(comment_id),
- CONSTRAINT PK_revision_comment_temp PRIMARY KEY (revcomment_rev, revcomment_comment_id)
-);
-CREATE UNIQUE INDEX /*i*/revcomment_rev ON /*_*/revision_comment_temp (revcomment_rev);
-
-
-CREATE TABLE /*_*/image_comment_temp (
- imgcomment_name nvarchar(255) NOT NULL CONSTRAINT FK_imgcomment_name FOREIGN KEY REFERENCES /*_*/image(img_name) ON DELETE CASCADE,
- imgcomment_description_id bigint NOT NULL CONSTRAINT FK_imgcomment_description_id FOREIGN KEY REFERENCES /*_*/comment(comment_id),
- CONSTRAINT PK_image_comment_temp PRIMARY KEY (imgcomment_name, imgcomment_description_id)
-);
-CREATE UNIQUE INDEX /*i*/imgcomment_name ON /*_*/image_comment_temp (imgcomment_name);
-
-
-ALTER TABLE /*_*/revision ADD CONSTRAINT DF_rev_comment DEFAULT '' FOR rev_comment;
-
-ALTER TABLE /*_*/archive ADD CONSTRAINT DF_ar_comment DEFAULT '' FOR ar_comment;
-ALTER TABLE /*_*/archive ADD ar_comment_id bigint NOT NULL CONSTRAINT DF_ar_comment_id DEFAULT 0 CONSTRAINT FK_ar_comment_id FOREIGN KEY REFERENCES /*_*/comment(comment_id);
-
-ALTER TABLE /*_*/ipblocks ADD CONSTRAINT DF_ipb_reason DEFAULT '' FOR ipb_reason;
-ALTER TABLE /*_*/ipblocks ADD ipb_reason_id bigint NOT NULL CONSTRAINT DF_ipb_reason_id DEFAULT 0 CONSTRAINT FK_ipb_reason_id FOREIGN KEY REFERENCES /*_*/comment(comment_id);
-
-ALTER TABLE /*_*/image ADD CONSTRAINT DF_img_description DEFAULT '' FOR img_description;
-
-ALTER TABLE /*_*/oldimage ADD CONSTRAINT DF_oi_description DEFAULT '' FOR oi_description;
-ALTER TABLE /*_*/oldimage ADD oi_description_id bigint NOT NULL CONSTRAINT DF_oi_description_id DEFAULT 0 CONSTRAINT FK_oi_description_id FOREIGN KEY REFERENCES /*_*/comment(comment_id);
-
-ALTER TABLE /*_*/filearchive ADD CONSTRAINT DF_fa_deleted_reason DEFAULT '' FOR fa_deleted_reason;
-ALTER TABLE /*_*/filearchive ADD fa_deleted_reason_id bigint NOT NULL CONSTRAINT DF_fa_deleted_reason_id DEFAULT 0 CONSTRAINT FK_fa_deleted_reason_id FOREIGN KEY REFERENCES /*_*/comment(comment_id);
-ALTER TABLE /*_*/filearchive ADD CONSTRAINT DF_fa_description DEFAULT '' FOR fa_description;
-ALTER TABLE /*_*/filearchive ADD fa_description_id bigint NOT NULL CONSTRAINT DF_fa_description_id DEFAULT 0 CONSTRAINT FK_fa_description_id FOREIGN KEY REFERENCES /*_*/comment(comment_id);
-
-ALTER TABLE /*_*/recentchanges ADD rc_comment_id bigint NOT NULL CONSTRAINT DF_rc_comment_id DEFAULT 0 CONSTRAINT FK_rc_comment_id FOREIGN KEY REFERENCES /*_*/comment(comment_id);
-
-ALTER TABLE /*_*/logging ADD log_comment_id bigint NOT NULL CONSTRAINT DF_log_comment_id DEFAULT 0 CONSTRAINT FK_log_comment_id FOREIGN KEY REFERENCES /*_*/comment(comment_id);
-
-ALTER TABLE /*_*/protected_titles ADD CONSTRAINT DF_pt_reason DEFAULT '' FOR pt_reason;
-ALTER TABLE /*_*/protected_titles ADD pt_reason_id bigint NOT NULL CONSTRAINT DF_pt_reason_id DEFAULT 0 CONSTRAINT FK_pt_reason_id FOREIGN KEY REFERENCES /*_*/comment(comment_id);
+++ /dev/null
---
--- The content table represents content objects. It's primary purpose is to provide the necessary
--- meta-data for loading and interpreting a serialized data blob to create a content object.
---
-CREATE TABLE /*_*/content (
-
- -- ID of the content object
- content_id bigint NOT NULL CONSTRAINT PK_content PRIMARY KEY IDENTITY,
-
- -- Nominal size of the content object (not necessarily of the serialized blob)
- content_size int NOT NULL,
-
- -- Nominal hash of the content object (not necessarily of the serialized blob)
- content_sha1 varchar(32) NOT NULL,
-
- -- reference to model_id
- content_model smallint NOT NULL CONSTRAINT FK_content_content_models FOREIGN KEY REFERENCES /*_*/content_models(model_id),
-
- -- URL-like address of the content blob
- content_address nvarchar(255) NOT NULL
-);
+++ /dev/null
-
---
--- Normalization table for content model names
---
-CREATE TABLE /*_*/content_models (
- model_id smallint NOT NULL CONSTRAINT PK_content_models PRIMARY KEY IDENTITY,
- model_name nvarchar(64) NOT NULL
-);
-
--- Index for looking of the internal ID of for a name
-CREATE UNIQUE INDEX /*i*/model_name ON /*_*/content_models (model_name);
\ No newline at end of file
+++ /dev/null
-DECLARE @sql nvarchar(max),
- @id sysname;--
-
-SET @sql = 'ALTER TABLE /*_*/archive DROP CONSTRAINT ';--
-
-SELECT @id = df.name
-FROM sys.default_constraints df
-JOIN sys.columns c
- ON c.object_id = df.parent_object_id
- AND c.column_id = df.parent_column_id
-WHERE
- df.parent_object_id = OBJECT_ID('/*_*/archive')
- AND ( c.name = 'ar_text' OR c.name = 'ar_flags' );--
-
-SET @sql = @sql + @id;--
-
-EXEC sp_executesql @sql;--
-
-ALTER TABLE /*_*/archive DROP COLUMN ar_text;
-ALTER TABLE /*_*/archive DROP COLUMN ar_flags;
-ALTER TABLE /*_*/archive ALTER COLUMN ar_text_id INT NOT NULL CONSTRAINT DF_ar_text_id DEFAULT 0;
+++ /dev/null
---
--- patch-drop-comment-fields.sql
---
--- T166732. Drop old xx_comment fields, and defaults from xx_comment_id fields.
-
-DECLARE @sql nvarchar(max),
- @id sysname;
-
-ALTER TABLE /*_*/archive DROP CONSTRAINT DF_ar_comment, COLUMN ar_comment;
-ALTER TABLE /*_*/archive DROP CONSTRAINT DF_ar_comment_id;
-
-ALTER TABLE /*_*/ipblocks DROP CONSTRAINT DF_ipb_reason, COLUMN ipb_reason;
-ALTER TABLE /*_*/ipblocks DROP CONSTRAINT DF_ipb_reason_id;
-
-ALTER TABLE /*_*/image DROP CONSTRAINT DF_img_description, COLUMN img_description;
-ALTER TABLE /*_*/image DROP CONSTRAINT DF_img_description_id;
-
-ALTER TABLE /*_*/oldimage DROP CONSTRAINT DF_oi_description, COLUMN oi_description;
-ALTER TABLE /*_*/oldimage DROP CONSTRAINT DF_oi_description_id;
-
-ALTER TABLE /*_*/filearchive DROP CONSTRAINT DF_fa_deleted_reason, COLUMN fa_deleted_reason;
-ALTER TABLE /*_*/filearchive DROP CONSTRAINT DF_fa_deleted_reason_id;
-ALTER TABLE /*_*/filearchive DROP CONSTRAINT DF_fa_description, COLUMN fa_description;
-ALTER TABLE /*_*/filearchive DROP CONSTRAINT DF_fa_description_id;
-
-SET @sql = 'ALTER TABLE /*_*/recentchanges DROP CONSTRAINT ';
-SELECT @id = df.name
-FROM sys.default_constraints df
-JOIN sys.columns c
- ON c.object_id = df.parent_object_id
- AND c.column_id = df.parent_column_id
-WHERE
- df.parent_object_id = OBJECT_ID('/*_*/recentchanges')
- AND c.name = 'rc_comment';
-SET @sql = @sql + @id;
-EXEC sp_executesql @sql;
-ALTER TABLE /*_*/recentchanges DROP COLUMN rc_comment;
-ALTER TABLE /*_*/recentchanges DROP CONSTRAINT DF_rc_comment_id;
-
-SET @sql = 'ALTER TABLE /*_*/logging DROP CONSTRAINT ';
-SELECT @id = df.name
-FROM sys.default_constraints df
-JOIN sys.columns c
- ON c.object_id = df.parent_object_id
- AND c.column_id = df.parent_column_id
-WHERE
- df.parent_object_id = OBJECT_ID('/*_*/logging')
- AND c.name = 'log_comment';
-SET @sql = @sql + @id;
-EXEC sp_executesql @sql;
-ALTER TABLE /*_*/logging DROP COLUMN log_comment;
-ALTER TABLE /*_*/logging DROP CONSTRAINT DF_log_comment_id;
-
-ALTER TABLE /*_*/protected_titles DROP CONSTRAINT DF_pt_reason, COLUMN pt_reason;
-ALTER TABLE /*_*/protected_titles DROP CONSTRAINT DF_pt_reason_id;
+++ /dev/null
--- T185355
-ALTER TABLE /*_*/change_tag ALTER COLUMN ct_tag INTEGER NOT NULL
-
-DECLARE @sql nvarchar(max),
- @id sysname;--
-
-SET @sql = 'ALTER TABLE /*_*/change_tag DROP CONSTRAINT ';--
-
-SELECT @id = df.name
-FROM sys.default_constraints df
-JOIN sys.columns c
- ON c.object_id = df.parent_object_id
- AND c.column_id = df.parent_column_id
-WHERE
- df.parent_object_id = OBJECT_ID('/*_*/change_tag')
- AND c.name = 'ct_tag';--
-
-SET @sql = @sql + @id;--
-
-EXEC sp_executesql @sql;--
-
-ALTER TABLE /*_*/change_tag DROP COLUMN ct_tag;
+++ /dev/null
-DECLARE @sql nvarchar(max),
- @id sysname;--
-
-SET @sql = 'ALTER TABLE /*_*/page DROP CONSTRAINT ';--
-
-SELECT @id = df.name
-FROM sys.default_constraints df
-JOIN sys.columns c
- ON c.object_id = df.parent_object_id
- AND c.column_id = df.parent_column_id
-WHERE
- df.parent_object_id = OBJECT_ID('/*_*/page')
- AND c.name = 'page_counter';--
-
-SET @sql = @sql + @id;--
-
-EXEC sp_executesql @sql;--
-
-ALTER TABLE /*_*/page DROP COLUMN page_counter;
+++ /dev/null
-DECLARE @sql nvarchar(max),
- @id sysname;--
-
-SET @sql = 'ALTER TABLE /*_*/recentchanges DROP CONSTRAINT ';--
-
-SELECT @id = df.name
-FROM sys.default_constraints df
-JOIN sys.columns c
- ON c.object_id = df.parent_object_id
- AND c.column_id = df.parent_column_id
-WHERE
- df.parent_object_id = OBJECT_ID('/*_*/recentchanges')
- AND c.name = 'rc_cur_time';--
-
-SET @sql = @sql + @id;--
-
-EXEC sp_executesql @sql;--
-
-ALTER TABLE /*_*/recentchanges DROP COLUMN rc_cur_time;
+++ /dev/null
-DECLARE @sql nvarchar(max),
- @id sysname;--
-
-SET @sql = 'ALTER TABLE /*_*/site_stats DROP CONSTRAINT ';--
-
-SELECT @id = df.name
-FROM sys.default_constraints df
-JOIN sys.columns c
- ON c.object_id = df.parent_object_id
- AND c.column_id = df.parent_column_id
-WHERE
- df.parent_object_id = OBJECT_ID('/*_*/site_stats')
- AND c.name = 'ss_total_views';--
-
-SET @sql = @sql + @id;--
-
-EXEC sp_executesql @sql;--
-
-ALTER TABLE /*_*/site_stats DROP COLUMN ss_total_views;
+++ /dev/null
-DECLARE @sql nvarchar(max),
- @id sysname;--
-
-SET @sql = 'ALTER TABLE /*_*/mwuser DROP CONSTRAINT ';--
-
-SELECT @id = df.name
-FROM sys.default_constraints df
-JOIN sys.columns c
- ON c.object_id = df.parent_object_id
- AND c.column_id = df.parent_column_id
-WHERE
- df.parent_object_id = OBJECT_ID('/*_*/mwuser')
- AND c.name = 'user_options';--
-
-SET @sql = @sql + @id;--
-
-EXEC sp_executesql @sql;--
-
-ALTER TABLE /*_*/mwuser DROP COLUMN user_options;
+++ /dev/null
-DECLARE @sql nvarchar(max)
-SET @sql=''
-
-SELECT @sql= @sql + 'ALTER TABLE /*_*/externallinks DROP CONSTRAINT ' + df.name + '; '
-FROM sys.default_constraints df
-JOIN sys.columns c
- ON c.object_id = df.parent_object_id
- AND c.column_id = df.parent_column_id
-WHERE
- df.parent_object_id = OBJECT_ID('/*_*/externallinks')
- AND c.name = 'el_index_60';--
-
-EXEC sp_executesql @sql;
+++ /dev/null
-ALTER TABLE /*_*/filearchive
-DROP CONSTRAINT fa_major_mime_ckc;
-ALTER TABLE /*_*/filearchive
-WITH NOCHECK ADD CONSTRAINT fa_major_mime_ckc CHECK (fa_major_mime IN('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart', 'chemical'));
\ No newline at end of file
+++ /dev/null
-DECLARE @baseSQL nvarchar(max),
- @SQL nvarchar(max),
- @id sysname;--
-
-SET @baseSQL = 'ALTER TABLE /*_*/filearchive DROP CONSTRAINT ';--
-
-SELECT @id = cc.name
-FROM sys.check_constraints cc
-JOIN sys.columns c
- ON c.object_id = cc.parent_object_id
- AND c.column_id = cc.parent_column_id
-WHERE
- cc.parent_object_id = OBJECT_ID('/*_*/filearchive')
- AND c.name = 'fa_major_mime';--
-
-SET @SQL = @baseSQL + @id;--
-
-EXEC sp_executesql @SQL;--
-
-SELECT @id = cc.name
-FROM sys.check_constraints cc
-JOIN sys.columns c
- ON c.object_id = cc.parent_object_id
- AND c.column_id = cc.parent_column_id
-WHERE
- cc.parent_object_id = OBJECT_ID('/*_*/filearchive')
- AND c.name = 'fa_media_type';--
-
-SET @SQL = @baseSQL + @id;--
-
-EXEC sp_executesql @SQL;--
-
-ALTER TABLE /*_*/filearchive ADD CONSTRAINT fa_major_mime_ckc check (fa_major_mime IN('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart'));--
-ALTER TABLE /*_*/filearchive ADD CONSTRAINT fa_media_type_ckc check (fa_media_type in('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA', 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE'));
+++ /dev/null
--- MediaWiki looks for lines ending with semicolons and sends them as separate queries
--- However here we *really* need this all to be sent as a single batch. As such, DO NOT
--- remove the -- from the end of each statement.
-
-DECLARE @temp table (
- fa_id int,
- fa_name nvarchar(255),
- fa_archive_name nvarchar(255),
- fa_storage_group nvarchar(16),
- fa_storage_key nvarchar(64),
- fa_deleted_user int,
- fa_deleted_timestamp varchar(14),
- fa_deleted_reason nvarchar(max),
- fa_size int,
- fa_width int,
- fa_height int,
- fa_metadata nvarchar(max),
- fa_bits int,
- fa_media_type varchar(16),
- fa_major_mime varchar(16),
- fa_minor_mime nvarchar(100),
- fa_description nvarchar(255),
- fa_user int,
- fa_user_text nvarchar(255),
- fa_timestamp varchar(14),
- fa_deleted tinyint,
- fa_sha1 nvarchar(32)
-);--
-
-INSERT INTO @temp
-SELECT * FROM /*_*/filearchive;--
-
-DROP TABLE /*_*/filearchive;--
-
-CREATE TABLE /*_*/filearchive (
- fa_id int NOT NULL PRIMARY KEY IDENTITY,
- fa_name nvarchar(255) NOT NULL default '',
- fa_archive_name nvarchar(255) default '',
- fa_storage_group nvarchar(16),
- fa_storage_key nvarchar(64) default '',
- fa_deleted_user int,
- fa_deleted_timestamp varchar(14) default '',
- fa_deleted_reason nvarchar(max),
- fa_size int default 0,
- fa_width int default 0,
- fa_height int default 0,
- fa_metadata varbinary(max),
- fa_bits int default 0,
- fa_media_type varchar(16) default null,
- fa_major_mime varchar(16) not null default 'unknown',
- fa_minor_mime nvarchar(100) default 'unknown',
- fa_description nvarchar(255),
- fa_user int default 0 REFERENCES /*_*/mwuser(user_id) ON DELETE SET NULL,
- fa_user_text nvarchar(255),
- fa_timestamp varchar(14) default '',
- fa_deleted tinyint NOT NULL default 0,
- fa_sha1 nvarchar(32) NOT NULL default '',
- CONSTRAINT fa_major_mime_ckc check (fa_major_mime in('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart', 'chemical')),
- CONSTRAINT fa_media_type_ckc check (fa_media_type in('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA', 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE'))
-);--
-
-CREATE INDEX /*i*/fa_name ON /*_*/filearchive (fa_name, fa_timestamp);--
-CREATE INDEX /*i*/fa_storage_group ON /*_*/filearchive (fa_storage_group, fa_storage_key);--
-CREATE INDEX /*i*/fa_deleted_timestamp ON /*_*/filearchive (fa_deleted_timestamp);--
-CREATE INDEX /*i*/fa_user_timestamp ON /*_*/filearchive (fa_user_text,fa_timestamp);--
-CREATE INDEX /*i*/fa_sha1 ON /*_*/filearchive (fa_sha1);--
-
-SET IDENTITY_INSERT /*_*/filearchive ON;--
-
-INSERT INTO /*_*/filearchive
-(
- fa_id,
- fa_name,
- fa_archive_name,
- fa_storage_group,
- fa_storage_key,
- fa_deleted_user,
- fa_deleted_timestamp,
- fa_deleted_reason,
- fa_size,
- fa_width,
- fa_height,
- fa_metadata,
- fa_bits,
- fa_media_type,
- fa_major_mime,
- fa_minor_mime,
- fa_description,
- fa_user,
- fa_user_text,
- fa_timestamp,
- fa_deleted,
- fa_sha1
-)
-SELECT
- fa_id,
- fa_name,
- fa_archive_name,
- fa_storage_group,
- fa_storage_key,
- fa_deleted_user,
- fa_deleted_timestamp,
- fa_deleted_reason,
- fa_size,
- fa_width,
- fa_height,
- CONVERT(varbinary(max), fa_metadata, 0),
- fa_bits,
- fa_media_type,
- fa_major_mime,
- fa_minor_mime,
- fa_description,
- fa_user,
- fa_user_text,
- fa_timestamp,
- fa_deleted,
- fa_sha1
-FROM @temp t;--
-
-SET IDENTITY_INSERT /*_*/filearchive OFF;
+++ /dev/null
-ALTER TABLE /*_*/imagelinks
- ADD il_from_namespace int NOT NULL default 0;
-
-CREATE INDEX /*i*/il_backlinks_namespace ON /*_*/imagelinks (il_from_namespace,il_to,il_from);
\ No newline at end of file
+++ /dev/null
-DECLARE @baseSQL nvarchar(max),
- @SQL nvarchar(max),
- @id sysname;--
-
-SET @baseSQL = 'ALTER TABLE /*_*/image DROP CONSTRAINT ';--
-
-SELECT @id = cc.name
-FROM sys.check_constraints cc
-JOIN sys.columns c
- ON c.object_id = cc.parent_object_id
- AND c.column_id = cc.parent_column_id
-WHERE
- cc.parent_object_id = OBJECT_ID('/*_*/image')
- AND c.name = 'img_major_mime';--
-
-SET @SQL = @baseSQL + @id;--
-
-EXEC sp_executesql @SQL;--
-
-SELECT @id = cc.name
-FROM sys.check_constraints cc
-JOIN sys.columns c
- ON c.object_id = cc.parent_object_id
- AND c.column_id = cc.parent_column_id
-WHERE
- cc.parent_object_id = OBJECT_ID('/*_*/image')
- AND c.name = 'img_media_type';--
-
-SET @SQL = @baseSQL + @id;--
-
-EXEC sp_executesql @SQL;--
-
-ALTER TABLE /*_*/image ADD CONSTRAINT img_major_mime_ckc check (img_major_mime IN('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart'));--
-ALTER TABLE /*_*/image ADD CONSTRAINT img_media_type_ckc check (img_media_type in('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA', 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE'));
+++ /dev/null
---
--- patch-image-img_description_id.sql
---
--- T188132. Add `img_description_id` to the `image` table.
-
-ALTER TABLE /*_*/image ADD img_description_id bigint NOT NULL CONSTRAINT DF_img_description_id DEFAULT 0 CONSTRAINT FK_img_description_id FOREIGN KEY REFERENCES /*_*/comment(comment_id);
+++ /dev/null
--- MediaWiki looks for lines ending with semicolons and sends them as separate queries
--- However here we *really* need this all to be sent as a single batch. As such, DO NOT
--- remove the -- from the end of each statement.
-
-DECLARE @temp table (
- img_name varbinary(255),
- img_size int,
- img_width int,
- img_height int,
- img_metadata varbinary(max),
- img_bits int,
- img_media_type varchar(16),
- img_major_mime varchar(16),
- img_minor_mime nvarchar(100),
- img_description nvarchar(255),
- img_user int,
- img_user_text nvarchar(255),
- img_timestamp nvarchar(14),
- img_sha1 nvarchar(32)
-);--
-
-INSERT INTO @temp
-SELECT * FROM /*_*/image;--
-
-DROP TABLE /*_*/image;--
-
-CREATE TABLE /*_*/image (
- img_name nvarchar(255) NOT NULL default '' PRIMARY KEY,
- img_size int NOT NULL default 0,
- img_width int NOT NULL default 0,
- img_height int NOT NULL default 0,
- img_metadata varbinary(max) NOT NULL,
- img_bits int NOT NULL default 0,
- img_media_type varchar(16) default null,
- img_major_mime varchar(16) not null default 'unknown',
- img_minor_mime nvarchar(100) NOT NULL default 'unknown',
- img_description nvarchar(255) NOT NULL,
- img_user int REFERENCES /*_*/mwuser(user_id) ON DELETE SET NULL,
- img_user_text nvarchar(255) NOT NULL,
- img_timestamp nvarchar(14) NOT NULL default '',
- img_sha1 nvarchar(32) NOT NULL default '',
- CONSTRAINT img_major_mime_ckc check (img_major_mime IN('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart', 'chemical')),
- CONSTRAINT img_media_type_ckc check (img_media_type in('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA', 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE'))
-);--
-
-CREATE INDEX /*i*/img_usertext_timestamp ON /*_*/image (img_user_text,img_timestamp);--
-CREATE INDEX /*i*/img_size ON /*_*/image (img_size);--
-CREATE INDEX /*i*/img_timestamp ON /*_*/image (img_timestamp);--
-CREATE INDEX /*i*/img_sha1 ON /*_*/image (img_sha1);--
-CREATE INDEX /*i*/img_media_mime ON /*_*/image (img_media_type,img_major_mime,img_minor_mime);--
-
-INSERT INTO /*_*/image
-(
- img_name,
- img_size,
- img_width,
- img_height,
- img_metadata,
- img_bits,
- img_media_type,
- img_major_mime,
- img_minor_mime,
- img_description,
- img_user,
- img_user_text,
- img_timestamp,
- img_sha1
-)
-SELECT
- img_name,
- img_size,
- img_width,
- img_height,
- img_metadata,
- img_bits,
- img_media_type,
- img_major_mime,
- img_minor_mime,
- img_description,
- img_user,
- img_user_text,
- img_timestamp,
- img_sha1
-FROM @temp t;
+++ /dev/null
-ALTER TABLE /*_*/image
-DROP CONSTRAINT img_major_mime_ckc;
-ALTER TABLE /*_*/image
-WITH NOCHECK ADD CONSTRAINT img_major_mime_ckc CHECK (img_major_mime IN('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart', 'chemical'));
\ No newline at end of file
+++ /dev/null
-DROP INDEX IF EXISTS /*i*/iw_prefix ON /*_*/interwiki;
-ALTER TABLE /*_*/interwiki ADD CONSTRAINT PK_interwiki PRIMARY KEY(iw_prefix);
\ No newline at end of file
+++ /dev/null
--- Adding ipb_sitewide for blocks
-ALTER TABLE /*$wgDBprefix*/ipblocks
- ADD ipb_sitewide bit NOT NULL CONSTRAINT DF_ipb_sitewide DEFAULT 1;
+++ /dev/null
--- For partial block restrictions --
-
-CREATE TABLE /*_*/ipblocks_restrictions (
- ir_ipb_id int NOT NULL CONSTRAINT FK_ir_ipb_id FOREIGN KEY REFERENCES /*_*/ipblocks(ipb_id) ON DELETE CASCADE,
- ir_type tinyint NOT NULL,
- ir_value int NOT NULL,
- CONSTRAINT PK_ipblocks_restrictions PRIMARY KEY (ir_ipb_id, ir_type, ir_value)
-) /*$wgDBTableOptions*/;
-
--- Index to query restrictions by the page or namespace.
-CREATE INDEX /*i*/ir_type_value ON /*_*/ipblocks_restrictions (ir_type, ir_value);
+++ /dev/null
---
--- Kill cl_collation index.
--- @since 1.27
---
-
-DROP INDEX /*i*/cl_collation ON /*_*/categorylinks;
-
+++ /dev/null
-DECLARE @base nvarchar(max),
- @SQL nvarchar(max),
- @id sysname;--
-
-SET @base = 'ALTER TABLE /*_*/logging DROP CONSTRAINT ';--
-
-SELECT @id = fk.name
-FROM sys.foreign_keys fk
-JOIN sys.foreign_key_columns fkc
- ON fkc.constraint_object_id = fk.object_id
-JOIN sys.columns c
- ON c.column_id = fkc.parent_column_id
- AND c.object_id = fkc.parent_object_id
-WHERE
- fk.parent_object_id = OBJECT_ID('/*_*/logging')
- AND fk.referenced_object_id = OBJECT_ID('/*_*/mwuser')
- AND c.name = 'log_user';--
-
-SET @SQL = @base + @id;--
-
-EXEC sp_executesql @SQL;--
-
-SELECT @id = fk.name
-FROM sys.foreign_keys fk
-JOIN sys.foreign_key_columns fkc
- ON fkc.constraint_object_id = fk.object_id
-JOIN sys.columns c
- ON c.column_id = fkc.parent_column_id
- AND c.object_id = fkc.parent_object_id
-WHERE
- fk.parent_object_id = OBJECT_ID('/*_*/logging')
- AND fk.referenced_object_id = OBJECT_ID('/*_*/page')
- AND c.name = 'log_page';--
-
-SET @SQL = @base + @id;--
-
-EXEC sp_executesql @SQL;
+++ /dev/null
-ALTER TABLE /*_*/oldimage
-DROP CONSTRAINT oi_major_mime_ckc;
-ALTER TABLE /*_*/oldimage
-WITH NOCHECK ADD CONSTRAINT oi_major_mime_ckc CHECK (oi_major_mime IN('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart', 'chemical'));
\ No newline at end of file
+++ /dev/null
-DECLARE @baseSQL nvarchar(max),
- @SQL nvarchar(max),
- @id sysname;--
-
-SET @baseSQL = 'ALTER TABLE /*_*/oldimage DROP CONSTRAINT ';--
-
-SELECT @id = cc.name
-FROM sys.check_constraints cc
-JOIN sys.columns c
- ON c.object_id = cc.parent_object_id
- AND c.column_id = cc.parent_column_id
-WHERE
- cc.parent_object_id = OBJECT_ID('/*_*/oldimage')
- AND c.name = 'oi_major_mime';--
-
-SET @SQL = @baseSQL + @id;--
-
-EXEC sp_executesql @SQL;--
-
-SELECT @id = cc.name
-FROM sys.check_constraints cc
-JOIN sys.columns c
- ON c.object_id = cc.parent_object_id
- AND c.column_id = cc.parent_column_id
-WHERE
- cc.parent_object_id = OBJECT_ID('/*_*/oldimage')
- AND c.name = 'oi_media_type';--
-
-SET @SQL = @baseSQL + @id;--
-
-EXEC sp_executesql @SQL;--
-
-ALTER TABLE /*_*/oldimage ADD CONSTRAINT oi_major_mime_ckc check (oi_major_mime IN('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart'));--
-ALTER TABLE /*_*/oldimage ADD CONSTRAINT oi_media_type_ckc check (oi_media_type in('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA', 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE'));
+++ /dev/null
--- MediaWiki looks for lines ending with semicolons and sends them as separate queries
--- However here we *really* need this all to be sent as a single batch. As such, DO NOT
--- remove the -- from the end of each statement.
-
-DECLARE @temp table (
- oi_name varbinary(255),
- oi_archive_name varbinary(255),
- oi_size int,
- oi_width int,
- oi_height int,
- oi_bits int,
- oi_description nvarchar(255),
- oi_user int,
- oi_user_text nvarchar(255),
- oi_timestamp varchar(14),
- oi_metadata nvarchar(max),
- oi_media_type varchar(16),
- oi_major_mime varchar(16),
- oi_minor_mime nvarchar(100),
- oi_deleted tinyint,
- oi_sha1 nvarchar(32)
-);--
-
-INSERT INTO @temp
-SELECT * FROM /*_*/oldimage;--
-
-DROP TABLE /*_*/oldimage;--
-
-CREATE TABLE /*_*/oldimage (
- oi_name nvarchar(255) NOT NULL default '',
- oi_archive_name nvarchar(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 nvarchar(255) NOT NULL,
- oi_user int REFERENCES /*_*/mwuser(user_id),
- oi_user_text nvarchar(255) NOT NULL,
- oi_timestamp varchar(14) NOT NULL default '',
- oi_metadata varbinary(max) NOT NULL,
- oi_media_type varchar(16) default null,
- oi_major_mime varchar(16) not null default 'unknown',
- oi_minor_mime nvarchar(100) NOT NULL default 'unknown',
- oi_deleted tinyint NOT NULL default 0,
- oi_sha1 nvarchar(32) NOT NULL default '',
- CONSTRAINT oi_major_mime_ckc check (oi_major_mime IN('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart', 'chemical')),
- CONSTRAINT oi_media_type_ckc check (oi_media_type IN('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA', 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE'))
-);--
-
-CREATE INDEX /*i*/oi_usertext_timestamp ON /*_*/oldimage (oi_user_text, oi_timestamp);--
-CREATE INDEX /*i*/oi_name_timestamp ON /*_*/oldimage (oi_name, oi_timestamp);--
-CREATE INDEX /*i*/oi_name_archive_name ON /*_*/oldimage (oi_name, oi_archive_name);--
-CREATE INDEX /*i*/oi_sha1 ON /*_*/oldimage (oi_sha1);--
-
-INSERT INTO /*_*/oldimage
-(
- oi_name,
- oi_archive_name,
- oi_size,
- oi_width,
- oi_height,
- oi_bits,
- oi_description,
- oi_user,
- oi_user_text,
- oi_timestamp,
- oi_metadata,
- oi_media_type,
- oi_major_mime,
- oi_minor_mime,
- oi_deleted,
- oi_sha1
-)
-SELECT
- oi_name,
- oi_archive_name,
- oi_size,
- oi_width,
- oi_height,
- oi_bits,
- oi_description,
- oi_user,
- oi_user_text,
- oi_timestamp,
- CONVERT(varbinary(max), oi_metadata, 0),
- oi_media_type,
- oi_major_mime,
- oi_minor_mime,
- oi_deleted,
- oi_sha1
-FROM @temp t;
+++ /dev/null
-ALTER TABLE /*_*/page ADD page_lang VARBINARY(35) DEFAULT NULL
+++ /dev/null
-DROP INDEX IF EXISTS /*i*/pp_page_propname ON /*_*/page_props;
-ALTER TABLE /*_*/page_props ADD CONSTRAINT PK_page_props PRIMARY KEY(pp_page,pp_propname);
\ No newline at end of file
+++ /dev/null
-ALTER TABLE /*_*/pagelinks
- ADD pl_from_namespace int NOT NULL default 0;
-
-CREATE INDEX /*i*/pl_backlinks_namespace ON /*_*/pagelinks (pl_from_namespace,pl_namespace,pl_title,pl_from);
+++ /dev/null
--- Add a 'sortkey' field to page_props so pages can be efficiently
--- queried by the numeric value of a property.
-
-ALTER TABLE /*_*/page_props
- ADD pp_sortkey float DEFAULT NULL;
-
-CREATE UNIQUE INDEX /*i*/pp_propname_sortkey_page
- ON /*_*/page_props ( pp_propname, pp_sortkey, pp_page );
+++ /dev/null
-DROP INDEX IF EXISTS /*i*/pt_namespace_title ON /*_*/protected_titles;
-ALTER TABLE /*_*/protected_titles ADD CONSTRAINT PK_protected_titles PRIMARY KEY(pt_namespace,pt_title);
\ No newline at end of file
+++ /dev/null
-DECLARE @cname sysname;--
-
-SELECT @cname = dc.name
-FROM sys.default_constraints dc
-JOIN sys.columns c
- ON c.object_id = dc.parent_object_id
- AND c.column_id = dc.parent_column_id
-WHERE
- c.name = 'rc_patrolled'
- AND c.object_id = OBJECT_ID('/*_*/recentchanges', 'U');--
-
-IF @cname IS NOT NULL
-BEGIN;--
- DECLARE @sql nvarchar(max);--
- SET @sql = N'ALTER TABLE /*_*/recentchanges DROP CONSTRAINT ' + @cname;--
- EXEC sp_executesql @sql;--
-END;--
-
-DROP INDEX /*i*/rc_name_type_patrolled_timestamp ON /*_*/recentchanges;--
-ALTER TABLE /*_*/recentchanges ALTER COLUMN rc_patrolled tinyint NOT NULL;--
-ALTER TABLE /*_*/recentchanges ADD CONSTRAINT DF_rc_patrolled DEFAULT 0 FOR rc_patrolled;--
-CREATE INDEX /*i*/rc_name_type_patrolled_timestamp ON /*_*/recentchanges (rc_namespace, rc_type, rc_patrolled, rc_timestamp);
\ No newline at end of file
+++ /dev/null
-DECLARE @base nvarchar(max),
- @SQL nvarchar(max),
- @id sysname;--
-
-SET @base = 'ALTER TABLE /*_*/recentchanges DROP CONSTRAINT ';--
-
-SELECT @id = fk.name
-FROM sys.foreign_keys fk
-JOIN sys.foreign_key_columns fkc
- ON fkc.constraint_object_id = fk.object_id
-JOIN sys.columns c
- ON c.column_id = fkc.parent_column_id
- AND c.object_id = fkc.parent_object_id
-WHERE
- fk.parent_object_id = OBJECT_ID('/*_*/recentchanges')
- AND fk.referenced_object_id = OBJECT_ID('/*_*/page')
- AND c.name = 'rc_cur_id';--
-
-SET @SQL = @base + @id;--
-
-EXEC sp_executesql @SQL;--
-
-SELECT @id = fk.name
-FROM sys.foreign_keys fk
-JOIN sys.foreign_key_columns fkc
- ON fkc.constraint_object_id = fk.object_id
-JOIN sys.columns c
- ON c.column_id = fkc.parent_column_id
- AND c.object_id = fkc.parent_object_id
-WHERE
- fk.parent_object_id = OBJECT_ID('/*_*/recentchanges')
- AND fk.referenced_object_id = OBJECT_ID('/*_*/revision')
- AND c.name = 'rc_this_oldid';--
-
-SET @SQL = @base + @id;--
-
-EXEC sp_executesql @SQL;--
-
-SELECT @id = fk.name
-FROM sys.foreign_keys fk
-JOIN sys.foreign_key_columns fkc
- ON fkc.constraint_object_id = fk.object_id
-JOIN sys.columns c
- ON c.column_id = fkc.parent_column_id
- AND c.object_id = fkc.parent_object_id
-WHERE
- fk.parent_object_id = OBJECT_ID('/*_*/recentchanges')
- AND fk.referenced_object_id = OBJECT_ID('/*_*/revision')
- AND c.name = 'rc_last_oldid';--
-
-SET @SQL = @base + @id;--
-
-EXEC sp_executesql @SQL;--
-
--- while we're at it, let's fix up the other foreign key constraints on recentchanges
--- as future patches touch constraints on other tables, they'll take the time to update constraint names there as well
-ALTER TABLE /*_*/recentchanges DROP CONSTRAINT FK_rc_logid_log_id;--
-ALTER TABLE /*_*/recentchanges ADD CONSTRAINT rc_logid__log_id__fk FOREIGN KEY (rc_logid) REFERENCES /*_*/logging(log_id) ON DELETE CASCADE;--
-
-SELECT @id = fk.name
-FROM sys.foreign_keys fk
-JOIN sys.foreign_key_columns fkc
- ON fkc.constraint_object_id = fk.object_id
-JOIN sys.columns c
- ON c.column_id = fkc.parent_column_id
- AND c.object_id = fkc.parent_object_id
-WHERE
- fk.parent_object_id = OBJECT_ID('/*_*/recentchanges')
- AND fk.referenced_object_id = OBJECT_ID('/*_*/mwuser')
- AND c.name = 'rc_user';--
-
-SET @SQL = @base + @id;--
-
-EXEC sp_executesql @SQL;--
-
-ALTER TABLE /*_*/recentchanges ADD CONSTRAINT rc_user__user_id__fk FOREIGN KEY (rc_user) REFERENCES /*_*/mwuser(user_id);
+++ /dev/null
---
--- Adds a default value to the rev_text_id field in the revision table.
--- This is to allow the Multi Content Revisions migration to happen where
--- rows will have to be added to the revision table with no rev_text_id.
---
--- 2018-03-12
---
-
-ALTER TABLE /*_*/revision
- ADD CONSTRAINT DF_rev_text_id DEFAULT 0 FOR rev_text_id;
\ No newline at end of file
+++ /dev/null
-DROP INDEX IF EXISTS /*i*/site_ids_type ON /*_*/site_identifiers;
-ALTER TABLE /*_*/site_identifiers ADD CONSTRAINT PK_site_identifiers PRIMARY KEY(si_type, si_key);
\ No newline at end of file
+++ /dev/null
-/* Delete old default constraints */
-DECLARE @sql nvarchar(max)
-SET @sql=''
-
-/* IMHO: A DBMS where you have to do THIS to change a default value sucks. */
-SELECT @sql= @sql + 'ALTER TABLE site_stats DROP CONSTRAINT ' + df.name + '; '
-FROM sys.default_constraints df
-JOIN sys.columns c
- ON c.object_id = df.parent_object_id
- AND c.column_id = df.parent_column_id
-WHERE
- df.parent_object_id = OBJECT_ID('site_stats');--
-
-EXEC sp_executesql @sql;
-
-/* Change data type of ss_images from int to bigint.
- * All other fields (except ss_row_id) already are bigint.
- * This MUST happen before adding new constraints. */
-ALTER TABLE site_stats ALTER COLUMN ss_images bigint;
-
-/* Add new default constraints.
- * Don't ask me why I have to repeat ALTER TABLE site_stats
- * instead of using commas, for some reason SQL Server 2016
- * didn't accept it in any other way. Maybe I just don't know
- * enough about mssql, but this works.
- */
-ALTER TABLE site_stats ADD CONSTRAINT col_ss_total_edits DEFAULT NULL FOR ss_total_edits;
-ALTER TABLE site_stats ADD CONSTRAINT col_ss_good_article DEFAULT NULL FOR ss_good_articles;
-ALTER TABLE site_stats ADD CONSTRAINT col_ss_total_pages DEFAULT NULL FOR ss_total_pages;
-ALTER TABLE site_stats ADD CONSTRAINT col_ss_users DEFAULT NULL FOR ss_users;
-ALTER TABLE site_stats ADD CONSTRAINT col_ss_active_users DEFAULT NULL FOR ss_active_users;
-ALTER TABLE site_stats ADD CONSTRAINT col_ss_images DEFAULT NULL FOR ss_images;
+++ /dev/null
-DROP INDEX ss_row_id ON site_stats;
-ALTER TABLE /*_*/site_stats ADD CONSTRAINT /*i*/ss_row_id PRIMARY KEY (ss_row_id);
+++ /dev/null
---
--- Replace slot_inherited with slot_origin.
---
--- NOTE: There is no release that has slot_inherited. This is only needed to transition between
--- snapshot versions of 1.30.
---
--- NOTE: No code that writes to the slots table was merge yet, the table is assumed to be empty.
---
-DROP INDEX /*i*/slot_role_inherited ON /*_*/slots;
-
-ALTER TABLE /*_*/slots DROP CONSTRAINT DF_slot_inherited, COLUMN slot_inherited;
-ALTER TABLE /*_*/slots ADD COLUMN slot_origin bigint NOT NULL;
-
-CREATE INDEX /*i*/slot_revision_origin_role ON /*_*/slots (slot_revision_id, slot_origin, slot_role_id);
+++ /dev/null
---
--- Normalization table for role names
---
-CREATE TABLE /*_*/slot_roles (
- role_id smallint NOT NULL CONSTRAINT PK_slot_roles PRIMARY KEY IDENTITY,
- role_name nvarchar(64) NOT NULL
-);
-
--- Index for looking of the internal ID of for a name
-CREATE UNIQUE INDEX /*i*/role_name ON /*_*/slot_roles (role_name);
\ No newline at end of file
+++ /dev/null
---
--- Slots represent an n:m relation between revisions and content objects.
--- A content object can have a specific "role" in one or more revisions.
--- Each revision can have multiple content objects, each having a different role.
---
-CREATE TABLE /*_*/slots (
-
- -- reference to rev_id
- slot_revision_id bigint NOT NULL,
-
- -- reference to role_id
- slot_role_id smallint NOT NULL CONSTRAINT FK_slots_slot_role FOREIGN KEY REFERENCES slot_roles(role_id),
-
- -- reference to content_id
- slot_content_id bigint NOT NULL CONSTRAINT FK_slots_content_id FOREIGN KEY REFERENCES content(content_id),
-
- -- The revision ID of the revision that originated the slot's content.
- -- To find revisions that changed slots, look for slot_origin = slot_revision_id.
- slot_origin bigint NOT NULL,
-
- CONSTRAINT PK_slots PRIMARY KEY (slot_revision_id, slot_role_id)
-);
-
--- Index for finding revisions that modified a specific slot
-CREATE INDEX /*i*/slot_revision_origin_role ON /*_*/slots (slot_revision_id, slot_origin, slot_role_id);
+++ /dev/null
-ALTER TABLE /*_*/templatelinks
- ADD tl_from_namespace int NOT NULL default 0;
-
-CREATE INDEX /*i*/tl_backlinks_namespace ON /*_*/templatelinks (tl_from_namespace,tl_namespace,tl_title,tl_from);
+++ /dev/null
-DECLARE @baseSQL nvarchar(max),
- @SQL nvarchar(max),
- @id sysname;--
-
-SET @baseSQL = 'ALTER TABLE /*_*/uploadstash DROP CONSTRAINT ';--
-
-SELECT @id = cc.name
-FROM sys.check_constraints cc
-JOIN sys.columns c
- ON c.object_id = cc.parent_object_id
- AND c.column_id = cc.parent_column_id
-WHERE
- cc.parent_object_id = OBJECT_ID('/*_*/uploadstash')
- AND c.name = 'us_media_type';--
-
-SET @SQL = @baseSQL + @id;--
-
-EXEC sp_executesql @SQL;--
-
-ALTER TABLE /*_*/uploadstash ADD CONSTRAINT us_media_type_ckc check (us_media_type in('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA', 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE'));
+++ /dev/null
--- Primary key and expiry column in user_groups table
-
-DROP INDEX IF EXISTS /*i*/ug_user_group ON /*_*/user_groups;
-ALTER TABLE /*_*/user_groups ADD CONSTRAINT pk_user_groups PRIMARY KEY(ug_user, ug_group);
-ALTER TABLE /*_*/user_groups ADD ug_expiry varchar(14) DEFAULT NULL;
-CREATE INDEX /*i*/ug_expiry ON /*_*/user_groups(ug_expiry);
+++ /dev/null
-ALTER TABLE /*_*/mwuser ADD user_password_expires VARCHAR(14) DEFAULT NULL
\ No newline at end of file
+++ /dev/null
-ALTER TABLE /*_*/watchlist ADD wl_id INT IDENTITY;
-ALTER TABLE /*_*/watchlist ADD CONSTRAINT pk_watchlist PRIMARY KEY(wl_id)
+++ /dev/null
--- T193874: Add new indexes to change_tag table using ct_tag_id instead of ct_tag
-
-CREATE UNIQUE INDEX /*i*/change_tag_rc_tag_id ON /*_*/change_tag (ct_rc_id,ct_tag_id);
-CREATE UNIQUE INDEX /*i*/change_tag_log_tag_id ON /*_*/change_tag (ct_log_id,ct_tag_id);
-CREATE UNIQUE INDEX /*i*/change_tag_rev_tag_id ON /*_*/change_tag (ct_rev_id,ct_tag_id);
-
-CREATE INDEX /*i*/change_tag_rc_tag_nonuniq ON /*_*/change_tag (ct_rc_id,ct_tag);
-CREATE INDEX /*i*/change_tag_log_tag_nonuniq ON /*_*/change_tag (ct_log_id,ct_tag);
-CREATE INDEX /*i*/change_tag_rev_tag_nonuniq ON /*_*/change_tag (ct_rev_id,ct_tag);
-
-DROP INDEX /*i*/change_tag_rc_tag ON /*_*/change_tag;
-DROP INDEX /*i*/change_tag_log_tag ON /*_*/change_tag;
-DROP INDEX /*i*/change_tag_rev_tag ON /*_*/change_tag;
-
-ALTER TABLE /*i*/change_tag
- ADD CONSTRAINT DF_ct_tag DEFAULT '' FOR ct_tag;
\ No newline at end of file
+++ /dev/null
--- Experimental table definitions for Microsoft SQL Server with
--- content-holding fields switched to explicit BINARY charset.
--- ------------------------------------------------------------
-
--- SQL to create the initial tables for the MediaWiki database.
--- This is read and executed by the install script; you should
--- not have to run it by itself unless doing a manual install.
-
---
--- General notes:
---
--- The comments in this and other files are
--- replaced with the defined table prefix by the installer
--- and updater scripts. If you are installing or running
--- updates manually, you will need to manually insert the
--- table prefix if any when running these scripts.
---
-
-
---
--- The user table contains basic account information,
--- authentication keys, etc.
---
--- Some multi-wiki sites may share a single central user table
--- between separate wikis using the $wgSharedDB setting.
---
--- Note that when a external authentication plugin is used,
--- user table entries still need to be created to store
--- preferences and to key tracking information in the other
--- tables.
-
--- LINE:53
-CREATE TABLE /*_*/mwuser (
- user_id INT NOT NULL PRIMARY KEY IDENTITY(0,1),
- user_name NVARCHAR(255) NOT NULL UNIQUE DEFAULT '',
- user_real_name NVARCHAR(255) NOT NULL DEFAULT '',
- user_password NVARCHAR(255) NOT NULL DEFAULT '',
- user_newpassword NVARCHAR(255) NOT NULL DEFAULT '',
- user_newpass_time varchar(14) NULL DEFAULT NULL,
- user_email NVARCHAR(255) NOT NULL DEFAULT '',
- user_touched varchar(14) NOT NULL DEFAULT '',
- user_token NCHAR(32) NOT NULL DEFAULT '',
- user_email_authenticated varchar(14) DEFAULT NULL,
- 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 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);
-CREATE INDEX /*i*/user_email ON /*_*/mwuser (user_email);
-
--- Insert a dummy user to represent anons
-INSERT INTO /*_*/mwuser (user_name) VALUES ('##Anonymous##');
-
---
--- The "actor" table associates user names or IP addresses with integers for
--- the benefit of other tables that need to refer to either logged-in or
--- logged-out users. If something can only ever be done by logged-in users, it
--- can refer to the user table directly.
---
-CREATE TABLE /*_*/actor (
- actor_id bigint NOT NULL CONSTRAINT PK_actor PRIMARY KEY IDENTITY(0,1),
- actor_user int,
- actor_name nvarchar(255) NOT NULL
-);
-CREATE UNIQUE INDEX /*i*/actor_user ON /*_*/actor (actor_user);
-CREATE UNIQUE INDEX /*i*/actor_name ON /*_*/actor (actor_name);
-
--- Insert a dummy actor to represent no actor
-INSERT INTO /*_*/actor (actor_name) VALUES ('##Anonymous##');
-
---
--- User permissions have been broken out to a separate table;
--- this allows sites with a shared user table to have different
--- permissions assigned to a user in each project.
---
--- This table replaces the old user_rights field which used a
--- comma-separated nvarchar(max).
-CREATE TABLE /*_*/user_groups (
- ug_user INT NOT NULL REFERENCES /*_*/mwuser(user_id) ON DELETE CASCADE,
- ug_group NVARCHAR(255) NOT NULL DEFAULT '',
- ug_expiry varchar(14) DEFAULT NULL,
- PRIMARY KEY(ug_user, ug_group)
-);
-CREATE INDEX /*i*/ug_group ON /*_*/user_groups(ug_group);
-CREATE INDEX /*i*/ug_expiry ON /*_*/user_groups(ug_expiry);
-
--- Stores the groups the user has once belonged to.
--- The user may still belong to these groups (check user_groups).
--- Users are not autopromoted to groups from which they were removed.
-CREATE TABLE /*_*/user_former_groups (
- ufg_user INT NOT NULL REFERENCES /*_*/mwuser(user_id) ON DELETE CASCADE,
- ufg_group nvarchar(255) NOT NULL default ''
-);
-CREATE UNIQUE INDEX /*i*/ufg_user_group ON /*_*/user_former_groups (ufg_user,ufg_group);
-
--- Stores notifications of user talk page changes, for the display
--- of the "you have new messages" box
--- Changed user_id column to user_id to avoid clashing with user_id function
-CREATE TABLE /*_*/user_newtalk (
- user_id INT NOT NULL REFERENCES /*_*/mwuser(user_id) ON DELETE CASCADE,
- user_ip NVARCHAR(40) NOT NULL DEFAULT '',
- user_last_timestamp varchar(14) DEFAULT NULL,
-);
-CREATE INDEX /*i*/un_user_id ON /*_*/user_newtalk (user_id);
-CREATE INDEX /*i*/un_user_ip ON /*_*/user_newtalk (user_ip);
-
---
--- User preferences and other fun stuff
--- replaces old user.user_options nvarchar(max)
---
-CREATE TABLE /*_*/user_properties (
- up_user INT NOT NULL REFERENCES /*_*/mwuser(user_id) ON DELETE CASCADE,
- up_property NVARCHAR(255) NOT NULL,
- up_value NVARCHAR(MAX),
-);
-CREATE UNIQUE CLUSTERED INDEX /*i*/user_properties_user_property ON /*_*/user_properties (up_user,up_property);
-CREATE INDEX /*i*/user_properties_property ON /*_*/user_properties (up_property);
-
---
--- This table contains a user's bot passwords: passwords that allow access to
--- the account via the API with limited rights.
---
-CREATE TABLE /*_*/bot_passwords (
- bp_user int NOT NULL REFERENCES /*_*/mwuser(user_id) ON DELETE CASCADE,
- bp_app_id nvarchar(32) NOT NULL,
- bp_password nvarchar(255) NOT NULL,
- bp_token nvarchar(255) NOT NULL,
- bp_restrictions nvarchar(max) NOT NULL,
- bp_grants nvarchar(max) NOT NULL,
- PRIMARY KEY (bp_user, bp_app_id)
-);
-
-
---
--- Edits, blocks, and other actions typically have a textual comment describing
--- the action. They are stored here to reduce the size of the main tables, and
--- to allow for deduplication.
---
--- Deduplication is currently best-effort to avoid locking on inserts that
--- would be required for strict deduplication. There MAY be multiple rows with
--- the same comment_text and comment_data.
---
-CREATE TABLE /*_*/comment (
- comment_id bigint NOT NULL PRIMARY KEY IDENTITY(0,1),
- comment_hash INT NOT NULL,
- comment_text nvarchar(max) NOT NULL,
- comment_data nvarchar(max)
-);
--- Index used for deduplication.
-CREATE INDEX /*i*/comment_hash ON /*_*/comment (comment_hash);
-
--- dummy row for FKs. Hash is intentionally wrong so CommentStore won't match it.
-INSERT INTO /*_*/comment (comment_hash, comment_text) VALUES (-1, '** dummy **');
-
-
---
--- Core of the wiki: each page has an entry here which identifies
--- it by title and contains some essential metadata.
---
-CREATE TABLE /*_*/page (
- page_id INT NOT NULL PRIMARY KEY IDENTITY(0,1),
- page_namespace INT NOT NULL,
- page_title NVARCHAR(255) NOT NULL,
- page_restrictions NVARCHAR(255) NOT NULL,
- page_is_redirect BIT NOT NULL DEFAULT 0,
- page_is_new BIT NOT NULL DEFAULT 0,
- page_random real NOT NULL DEFAULT RAND(),
- page_touched varchar(14) NOT NULL default '',
- page_links_updated varchar(14) DEFAULT NULL,
- page_latest INT, -- FK inserted later
- page_len INT NOT NULL,
- page_content_model nvarchar(32) default null,
- page_lang VARBINARY(35) DEFAULT NULL
-);
-CREATE UNIQUE INDEX /*i*/name_title ON /*_*/page (page_namespace,page_title);
-CREATE INDEX /*i*/page_random ON /*_*/page (page_random);
-CREATE INDEX /*i*/page_len ON /*_*/page (page_len);
-CREATE INDEX /*i*/page_redirect_namespace_len ON /*_*/page (page_is_redirect, page_namespace, page_len);
-
--- insert a dummy page
-INSERT INTO /*_*/page (page_namespace, page_title, page_restrictions, page_latest, page_len) VALUES (-1,'','',0,0);
-
---
--- Every edit of a page creates also a revision row.
--- This stores metadata about the revision, and a reference
--- to the TEXT storage backend.
---
-CREATE TABLE /*_*/revision (
- rev_id INT NOT NULL UNIQUE IDENTITY(0,1),
- rev_page INT NOT NULL REFERENCES /*_*/page(page_id) ON DELETE CASCADE,
- rev_text_id INT NOT NULL CONSTRAINT DF_rev_text_id DEFAULT 0, -- FK added later
- rev_comment NVARCHAR(255) NOT NULL CONSTRAINT DF_rev_comment DEFAULT '',
- rev_user INT REFERENCES /*_*/mwuser(user_id) ON DELETE SET NULL,
- rev_user_text NVARCHAR(255) NOT NULL DEFAULT '',
- rev_timestamp varchar(14) NOT NULL default '',
- rev_minor_edit BIT NOT NULL DEFAULT 0,
- rev_deleted TINYINT NOT NULL DEFAULT 0,
- rev_len INT,
- rev_parent_id INT DEFAULT NULL REFERENCES /*_*/revision(rev_id),
- rev_sha1 nvarchar(32) not null default '',
- rev_content_model nvarchar(32) default null,
- rev_content_format nvarchar(64) default null
-);
-CREATE UNIQUE CLUSTERED INDEX /*i*/rev_page_id ON /*_*/revision (rev_page, rev_id);
-CREATE INDEX /*i*/rev_timestamp ON /*_*/revision (rev_timestamp);
-CREATE INDEX /*i*/page_timestamp ON /*_*/revision (rev_page,rev_timestamp);
-CREATE INDEX /*i*/user_timestamp ON /*_*/revision (rev_user,rev_timestamp);
-CREATE INDEX /*i*/usertext_timestamp ON /*_*/revision (rev_user_text,rev_timestamp);
-CREATE INDEX /*i*/page_user_timestamp ON /*_*/revision (rev_page,rev_user,rev_timestamp);
-
--- insert a dummy revision
-INSERT INTO /*_*/revision (rev_page,rev_text_id,rev_comment,rev_user,rev_len) VALUES (0,0,'',0,0);
-
-ALTER TABLE /*_*/page ADD CONSTRAINT FK_page_latest_page_id FOREIGN KEY (page_latest) REFERENCES /*_*/revision(rev_id);
-
---
--- Temporary tables to avoid blocking on an alter of revision.
---
--- On large wikis like the English Wikipedia, altering the revision table is a
--- months-long process. This table is being created to avoid such an alter, and
--- will be merged back into revision in the future.
---
-CREATE TABLE /*_*/revision_comment_temp (
- revcomment_rev INT NOT NULL CONSTRAINT FK_revcomment_rev FOREIGN KEY REFERENCES /*_*/revision(rev_id) ON DELETE CASCADE,
- revcomment_comment_id bigint NOT NULL CONSTRAINT FK_revcomment_comment_id FOREIGN KEY REFERENCES /*_*/comment(comment_id),
- CONSTRAINT PK_revision_comment_temp PRIMARY KEY (revcomment_rev, revcomment_comment_id)
-);
-CREATE UNIQUE INDEX /*i*/revcomment_rev ON /*_*/revision_comment_temp (revcomment_rev);
-
-CREATE TABLE /*_*/revision_actor_temp (
- revactor_rev int NOT NULL CONSTRAINT FK_revactor_rev FOREIGN KEY REFERENCES /*_*/revision(rev_id) ON DELETE CASCADE,
- revactor_actor bigint NOT NULL,
- revactor_timestamp varchar(14) NOT NULL CONSTRAINT DF_revactor_timestamp DEFAULT '',
- revactor_page int NOT NULL,
- CONSTRAINT PK_revision_actor_temp PRIMARY KEY (revactor_rev, revactor_actor)
-);
-CREATE UNIQUE INDEX /*i*/revactor_rev ON /*_*/revision_actor_temp (revactor_rev);
-CREATE INDEX /*i*/actor_timestamp ON /*_*/revision_actor_temp (revactor_actor,revactor_timestamp);
-CREATE INDEX /*i*/page_actor_timestamp ON /*_*/revision_actor_temp (revactor_page,revactor_actor,revactor_timestamp);
-
---
--- Holds TEXT of individual page revisions.
---
--- Field names are a holdover from the 'old' revisions table in
--- MediaWiki 1.4 and earlier: an upgrade will transform that
--- table INTo the 'text' table to minimize unnecessary churning
--- and downtime. If upgrading, the other fields will be left unused.
-CREATE TABLE /*_*/text (
- old_id INT NOT NULL PRIMARY KEY IDENTITY(0,1),
- old_text nvarchar(max) NOT NULL,
- old_flags NVARCHAR(255) NOT NULL,
-);
-
--- insert a dummy text
-INSERT INTO /*_*/text (old_text,old_flags) VALUES ('','');
-
-ALTER TABLE /*_*/revision ADD CONSTRAINT FK_rev_text_id_old_id FOREIGN KEY (rev_text_id) REFERENCES /*_*/text(old_id) ON DELETE CASCADE;
-
---
--- Holding area for deleted articles, which may be viewed
--- or restored by admins through the Special:Undelete interface.
--- The fields generally correspond to the page, revision, and text
--- fields, with several caveats.
--- Cannot reasonably create views on this table, due to the presence of TEXT
--- columns.
-CREATE TABLE /*_*/archive (
- ar_id int NOT NULL PRIMARY KEY IDENTITY,
- ar_namespace SMALLINT NOT NULL DEFAULT 0,
- ar_title NVARCHAR(255) NOT NULL DEFAULT '',
- ar_comment_id bigint NOT NULL CONSTRAINT FK_ar_comment_id FOREIGN KEY REFERENCES /*_*/comment(comment_id),
- ar_user INT CONSTRAINT ar_user__user_id__fk FOREIGN KEY REFERENCES /*_*/mwuser(user_id),
- ar_user_text NVARCHAR(255) NOT NULL CONSTRAINT DF_ar_user_text DEFAULT '',
- ar_actor bigint NOT NULL CONSTRAINT DF_ar_actor DEFAULT 0,
- ar_timestamp varchar(14) NOT NULL default '',
- ar_minor_edit BIT NOT NULL DEFAULT 0,
- ar_rev_id INT NOT NULL, -- NOT a FK, the row gets deleted from revision and moved here
- ar_text_id INT NOT NULL CONSTRAINT DF_ar_text_id DEFAULT 0 CONSTRAINT ar_text_id__old_id__fk FOREIGN KEY REFERENCES /*_*/text(old_id) ON DELETE CASCADE,
- ar_deleted TINYINT NOT NULL DEFAULT 0,
- ar_len INT,
- ar_page_id INT NULL, -- NOT a FK, the row gets deleted from page and moved here
- ar_parent_id INT NULL, -- NOT FK
- ar_sha1 nvarchar(32) default null,
- ar_content_model nvarchar(32) DEFAULT NULL,
- ar_content_format nvarchar(64) DEFAULT NULL
-);
-CREATE INDEX /*i*/name_title_timestamp ON /*_*/archive (ar_namespace,ar_title,ar_timestamp);
-CREATE INDEX /*i*/ar_usertext_timestamp ON /*_*/archive (ar_user_text,ar_timestamp);
-CREATE INDEX /*i*/ar_actor_timestamp ON /*_*/archive (ar_actor,ar_timestamp);
-CREATE UNIQUE INDEX /*i*/ar_revid_uniq ON /*_*/archive (ar_rev_id);
-
-
---
--- Normalization table for role names
---
-CREATE TABLE /*_*/slot_roles (
- role_id smallint NOT NULL CONSTRAINT PK_slot_roles PRIMARY KEY IDENTITY,
- role_name nvarchar(64) NOT NULL
-);
-
--- Index for looking of the internal ID of for a name
-CREATE UNIQUE INDEX /*i*/role_name ON /*_*/slot_roles (role_name);
-
---
--- Normalization table for content model names
---
-CREATE TABLE /*_*/content_models (
- model_id smallint NOT NULL CONSTRAINT PK_content_models PRIMARY KEY IDENTITY,
- model_name nvarchar(64) NOT NULL
-);
-
--- Index for looking of the internal ID of for a name
-CREATE UNIQUE INDEX /*i*/model_name ON /*_*/content_models (model_name);
-
---
--- The content table represents content objects. It's primary purpose is to provide the necessary
--- meta-data for loading and interpreting a serialized data blob to create a content object.
---
-CREATE TABLE /*_*/content (
-
- -- ID of the content object
- content_id bigint NOT NULL CONSTRAINT PK_content PRIMARY KEY IDENTITY,
-
- -- Nominal size of the content object (not necessarily of the serialized blob)
- content_size int NOT NULL,
-
- -- Nominal hash of the content object (not necessarily of the serialized blob)
- content_sha1 varchar(32) NOT NULL,
-
- -- reference to model_id
- content_model smallint NOT NULL CONSTRAINT FK_content_content_models FOREIGN KEY REFERENCES /*_*/content_models(model_id),
-
- -- URL-like address of the content blob
- content_address nvarchar(255) NOT NULL
-);
-
---
--- Slots represent an n:m relation between revisions and content objects.
--- A content object can have a specific "role" in one or more revisions.
--- Each revision can have multiple content objects, each having a different role.
---
-CREATE TABLE /*_*/slots (
-
- -- reference to rev_id
- slot_revision_id bigint NOT NULL,
-
- -- reference to role_id
- slot_role_id smallint NOT NULL CONSTRAINT FK_slots_slot_role FOREIGN KEY REFERENCES slot_roles(role_id),
-
- -- reference to content_id
- slot_content_id bigint NOT NULL CONSTRAINT FK_slots_content_id FOREIGN KEY REFERENCES content(content_id),
-
- -- The revision ID of the revision that originated the slot's content.
- -- To find revisions that changed slots, look for slot_origin = slot_revision_id.
- slot_origin bigint NOT NULL,
-
- CONSTRAINT PK_slots PRIMARY KEY (slot_revision_id, slot_role_id)
-);
-
--- Index for finding revisions that modified a specific slot
-CREATE INDEX /*i*/slot_revision_origin_role ON /*_*/slots (slot_revision_id, slot_origin, slot_role_id);
-
-
---
--- Track page-to-page hyperlinks within the wiki.
---
-CREATE TABLE /*_*/pagelinks (
- pl_from INT NOT NULL REFERENCES /*_*/page(page_id) ON DELETE CASCADE,
- pl_from_namespace int NOT NULL DEFAULT 0,
- pl_namespace INT NOT NULL DEFAULT 0,
- pl_title NVARCHAR(255) NOT NULL DEFAULT '',
-);
-CREATE UNIQUE INDEX /*i*/pl_from ON /*_*/pagelinks (pl_from,pl_namespace,pl_title);
-CREATE UNIQUE INDEX /*i*/pl_namespace ON /*_*/pagelinks (pl_namespace,pl_title,pl_from);
-CREATE INDEX /*i*/pl_backlinks_namespace ON /*_*/pagelinks (pl_from_namespace,pl_namespace,pl_title,pl_from);
-
-
---
--- Track template inclusions.
---
-CREATE TABLE /*_*/templatelinks (
- tl_from int NOT NULL REFERENCES /*_*/page(page_id) ON DELETE CASCADE,
- tl_from_namespace int NOT NULL default 0,
- tl_namespace int NOT NULL default 0,
- tl_title nvarchar(255) NOT NULL default ''
-);
-
-CREATE UNIQUE INDEX /*i*/tl_from ON /*_*/templatelinks (tl_from,tl_namespace,tl_title);
-CREATE UNIQUE INDEX /*i*/tl_namespace ON /*_*/templatelinks (tl_namespace,tl_title,tl_from);
-CREATE INDEX /*i*/tl_backlinks_namespace ON /*_*/templatelinks (tl_from_namespace,tl_namespace,tl_title,tl_from);
-
-
---
--- Track links to images *used inline*
--- We don't distinguish live from broken links here, so
--- they do not need to be changed on upload/removal.
---
-CREATE TABLE /*_*/imagelinks (
- -- Key to page_id of the page containing the image / media link.
- il_from int NOT NULL REFERENCES /*_*/page(page_id) ON DELETE CASCADE,
- il_from_namespace int NOT NULL default 0,
-
- -- Filename of target image.
- -- This is also the page_title of the file's description page;
- -- all such pages are in namespace 6 (NS_FILE).
- il_to nvarchar(255) NOT NULL default ''
-);
-
-CREATE UNIQUE INDEX /*i*/il_from ON /*_*/imagelinks (il_from,il_to);
-CREATE UNIQUE INDEX /*i*/il_to ON /*_*/imagelinks (il_to,il_from);
-CREATE INDEX /*i*/il_backlinks_namespace ON /*_*/imagelinks (il_from_namespace,il_to,il_from);
-
---
--- Track category inclusions *used inline*
--- This tracks a single level of category membership
---
-CREATE TABLE /*_*/categorylinks (
- -- Key to page_id of the page defined as a category member.
- cl_from int NOT NULL REFERENCES /*_*/page(page_id) ON DELETE CASCADE,
-
- -- Name of the category.
- -- This is also the page_title of the category's description page;
- -- all such pages are in namespace 14 (NS_CATEGORY).
- cl_to nvarchar(255) NOT NULL default '',
-
- -- A binary string obtained by applying a sortkey generation algorithm
- -- (Collation::getSortKey()) to page_title, or cl_sortkey_prefix . "\n"
- -- . page_title if cl_sortkey_prefix is nonempty.
- cl_sortkey varbinary(230) NOT NULL default 0x,
-
- -- A prefix for the raw sortkey manually specified by the user, either via
- -- [[Category:Foo|prefix]] or {{defaultsort:prefix}}. If nonempty, it's
- -- concatenated with a line break followed by the page title before the sortkey
- -- conversion algorithm is run. We store this so that we can update
- -- collations without reparsing all pages.
- -- Note: If you change the length of this field, you also need to change
- -- code in LinksUpdate.php. See T27254.
- cl_sortkey_prefix varbinary(255) NOT NULL default 0x,
-
- -- This isn't really used at present. Provided for an optional
- -- sorting method by approximate addition time.
- cl_timestamp varchar(14) NOT NULL,
-
- -- Stores $wgCategoryCollation at the time cl_sortkey was generated. This
- -- can be used to install new collation versions, tracking which rows are not
- -- yet updated. '' means no collation, this is a legacy row that needs to be
- -- updated by updateCollation.php. In the future, it might be possible to
- -- specify different collations per category.
- cl_collation nvarchar(32) NOT NULL default '',
-
- -- Stores whether cl_from is a category, file, or other page, so we can
- -- paginate the three categories separately. This never has to be updated
- -- after the page is created, since none of these page types can be moved to
- -- any other.
- cl_type varchar(10) NOT NULL default 'page',
- -- SQL server doesn't have enums, so we approximate with this
- CONSTRAINT cl_type_ckc CHECK (cl_type IN('page', 'subcat', 'file'))
-);
-
-CREATE UNIQUE INDEX /*i*/cl_from ON /*_*/categorylinks (cl_from,cl_to);
-
--- We always sort within a given category, and within a given type. FIXME:
--- Formerly this index didn't cover cl_type (since that didn't exist), so old
--- callers won't be using an index: fix this?
-CREATE INDEX /*i*/cl_sortkey ON /*_*/categorylinks (cl_to,cl_type,cl_sortkey,cl_from);
-
--- Used by the API (and some extensions)
-CREATE INDEX /*i*/cl_timestamp ON /*_*/categorylinks (cl_to,cl_timestamp);
-
--- Used when updating collation (e.g. updateCollation.php)
-CREATE INDEX /*i*/cl_collation_ext ON /*_*/categorylinks (cl_collation, cl_to, cl_type, cl_from);
-
---
--- Track all existing categories. Something is a category if 1) it has an entry
--- somewhere in categorylinks, or 2) it has a description page. Categories
--- might not have corresponding pages, so they need to be tracked separately.
---
-CREATE TABLE /*_*/category (
- -- Primary key
- cat_id int NOT NULL PRIMARY KEY IDENTITY,
-
- -- Name of the category, in the same form as page_title (with underscores).
- -- If there is a category page corresponding to this category, by definition,
- -- it has this name (in the Category namespace).
- cat_title nvarchar(255) NOT NULL,
-
- -- The numbers of member pages (including categories and media), subcatego-
- -- ries, and Image: namespace members, respectively. These are signed to
- -- make underflow more obvious. We make the first number include the second
- -- two for better sorting: subtracting for display is easy, adding for order-
- -- ing is not.
- cat_pages int NOT NULL default 0,
- cat_subcats int NOT NULL default 0,
- cat_files int NOT NULL default 0
-);
-
-CREATE UNIQUE INDEX /*i*/cat_title ON /*_*/category (cat_title);
-
--- For Special:Mostlinkedcategories
-CREATE INDEX /*i*/cat_pages ON /*_*/category (cat_pages);
-
-
---
--- Table defining tag names for IDs. Also stores hit counts to avoid expensive queries on change_tag
---
-CREATE TABLE /*_*/change_tag_def (
- -- Numerical ID of the tag (ct_tag_id refers to this)
- ctd_id int NOT NULL CONSTRAINT PK_change_tag_def PRIMARY KEY IDENTITY,
- -- Symbolic name of the tag (what would previously be put in ct_tag)
- ctd_name nvarchar(255) NOT NULL,
- -- Whether this tag was defined manually by a privileged user using Special:Tags
- ctd_user_defined tinyint NOT NULL CONSTRAINT DF_ctd_user_defined DEFAULT 0,
- -- Number of times this tag was used
- ctd_count int NOT NULL CONSTRAINT DF_ctd_count DEFAULT 0
-) /*$wgDBTableOptions*/;
-
-CREATE UNIQUE INDEX /*i*/ctd_name ON /*_*/change_tag_def (ctd_name);
-CREATE INDEX /*i*/ctd_count ON /*_*/change_tag_def (ctd_count);
-CREATE INDEX /*i*/ctd_user_defined ON /*_*/change_tag_def (ctd_user_defined);
-
---
--- Track links to external URLs
---
-CREATE TABLE /*_*/externallinks (
- -- Primary key
- el_id int NOT NULL PRIMARY KEY IDENTITY,
-
- -- page_id of the referring page
- el_from int NOT NULL REFERENCES /*_*/page(page_id) ON DELETE CASCADE,
-
- -- The URL
- el_to nvarchar(max) NOT NULL,
-
- -- In the case of HTTP URLs, this is the URL with any username or password
- -- removed, and with the labels in the hostname reversed and converted to
- -- lower case. An extra dot is added to allow for matching of either
- -- example.com or *.example.com in a single scan.
- -- Example:
- -- http://user:password@sub.example.com/page.html
- -- becomes
- -- http://com.example.sub./page.html
- -- which allows for fast searching for all pages under example.com with the
- -- clause:
- -- WHERE el_index LIKE 'http://com.example.%'
- --
- -- Note if you enable or disable PHP's intl extension, you'll need to run
- -- maintenance/refreshExternallinksIndex.php to refresh this field.
- el_index nvarchar(450) NOT NULL,
-
- -- This is el_index truncated to 60 bytes to allow for sortable queries that
- -- aren't supported by a partial index.
- el_index_60 varbinary(60) NOT NULL
-);
-
-CREATE INDEX /*i*/el_from ON /*_*/externallinks (el_from);
-CREATE INDEX /*i*/el_index ON /*_*/externallinks (el_index);
-CREATE INDEX /*i*/el_index_60 ON /*_*/externallinks (el_index_60, el_id);
-CREATE INDEX /*i*/el_from_index_60 ON /*_*/externallinks (el_from, el_index_60, el_id);
--- el_to index intentionally not added; we cannot index nvarchar(max) columns,
--- but we also cannot restrict el_to to a smaller column size as the external
--- link may be larger.
-
---
--- Track interlanguage links
---
-CREATE TABLE /*_*/langlinks (
- -- page_id of the referring page
- ll_from int NOT NULL REFERENCES /*_*/page(page_id) ON DELETE CASCADE,
-
- -- Language code of the target
- ll_lang nvarchar(20) NOT NULL default '',
-
- -- Title of the target, including namespace
- ll_title nvarchar(255) NOT NULL default ''
-);
-
-CREATE UNIQUE INDEX /*i*/ll_from ON /*_*/langlinks (ll_from, ll_lang);
-CREATE INDEX /*i*/ll_lang ON /*_*/langlinks (ll_lang, ll_title);
-
-
---
--- Track inline interwiki links
---
-CREATE TABLE /*_*/iwlinks (
- -- page_id of the referring page
- iwl_from int NOT NULL REFERENCES /*_*/page(page_id) ON DELETE CASCADE,
-
- -- Interwiki prefix code of the target
- iwl_prefix nvarchar(20) NOT NULL default '',
-
- -- Title of the target, including namespace
- iwl_title nvarchar(255) NOT NULL default ''
-);
-
-CREATE UNIQUE INDEX /*i*/iwl_from ON /*_*/iwlinks (iwl_from, iwl_prefix, iwl_title);
-CREATE INDEX /*i*/iwl_prefix_title_from ON /*_*/iwlinks (iwl_prefix, iwl_title, iwl_from);
-CREATE INDEX /*i*/iwl_prefix_from_title ON /*_*/iwlinks (iwl_prefix, iwl_from, iwl_title);
-
-
---
--- Contains a single row with some aggregate info
--- on the state of the site.
---
-CREATE TABLE /*_*/site_stats (
- -- The single row should contain 1 here.
- ss_row_id int NOT NULL CONSTRAINT /*i*/ss_row_id PRIMARY KEY,
-
- -- Total number of edits performed.
- ss_total_edits bigint default NULL,
-
- -- See SiteStatsInit::articles().
- ss_good_articles bigint default NULL,
-
- -- Total pages, theoretically equal to SELECT COUNT(*) FROM page.
- ss_total_pages bigint default NULL,
-
- -- Number of users, theoretically equal to SELECT COUNT(*) FROM user.
- ss_users bigint default NULL,
-
- -- Number of users that still edit.
- ss_active_users bigint default NULL,
-
- -- Number of images, equivalent to SELECT COUNT(*) FROM image.
- ss_images bigint default NULL
-);
-
-
---
--- The internet is full of jerks, alas. Sometimes it's handy
--- to block a vandal or troll account.
---
-CREATE TABLE /*_*/ipblocks (
- -- Primary key, introduced for privacy.
- ipb_id int NOT NULL PRIMARY KEY IDENTITY,
-
- -- Blocked IP address in dotted-quad form or user name.
- ipb_address nvarchar(255) NOT NULL,
-
- -- Blocked user ID or 0 for IP blocks.
- ipb_user int REFERENCES /*_*/mwuser(user_id),
-
- -- User ID who made the block.
- ipb_by int REFERENCES /*_*/mwuser(user_id) ON DELETE CASCADE,
-
- -- Actor ID who made the block.
- ipb_by_actor bigint NOT NULL CONSTRAINT DF_ipb_by_actor DEFAULT 0,
-
- -- User name of blocker
- ipb_by_text nvarchar(255) NOT NULL default '',
-
- -- Key to comment_id. Text comment made by blocker.
- ipb_reason_id bigint NOT NULL CONSTRAINT FK_ipb_reason_id FOREIGN KEY REFERENCES /*_*/comment(comment_id),
-
- -- Creation (or refresh) date in standard YMDHMS form.
- -- IP blocks expire automatically.
- ipb_timestamp varchar(14) NOT NULL default '',
-
- -- Indicates that the IP address was banned because a banned
- -- user accessed a page through it. If this is 1, ipb_address
- -- will be hidden, and the block identified by block ID number.
- ipb_auto bit NOT NULL default 0,
-
- -- If set to 1, block applies only to logged-out users
- ipb_anon_only bit NOT NULL default 0,
-
- -- Block prevents account creation from matching IP addresses
- ipb_create_account bit NOT NULL default 1,
-
- -- Block triggers autoblocks
- ipb_enable_autoblock bit NOT NULL default 1,
-
- -- Time at which the block will expire.
- -- May be "infinity"
- ipb_expiry varchar(14) NOT NULL,
-
- -- Start and end of an address range, in hexadecimal
- -- Size chosen to allow IPv6
- -- FIXME: these fields were originally blank for single-IP blocks,
- -- but now they are populated. No migration was ever done. They
- -- should be fixed to be blank again for such blocks (T51504).
- ipb_range_start varchar(255) NOT NULL,
- ipb_range_end varchar(255) NOT NULL,
-
- -- Flag for entries hidden from users and Sysops
- ipb_deleted bit NOT NULL default 0,
-
- -- Block prevents user from accessing Special:Emailuser
- ipb_block_email bit NOT NULL default 0,
-
- -- Block allows user to edit their own talk page
- ipb_allow_usertalk bit NOT NULL default 0,
-
- -- ID of the block that caused this block to exist
- -- Autoblocks set this to the original block
- -- so that the original block being deleted also
- -- deletes the autoblocks
- ipb_parent_block_id int default NULL REFERENCES /*_*/ipblocks(ipb_id),
-
- -- Block user from editing any page on the site (other than their own user
- -- talk page).
- ipb_sitewide bit NOT NULL CONSTRAINT DF_ipb_sitewide DEFAULT 1
-);
-
--- Unique index to support "user already blocked" messages
--- Any new options which prevent collisions should be included
-CREATE UNIQUE INDEX /*i*/ipb_address ON /*_*/ipblocks (ipb_address, ipb_user, ipb_auto, ipb_anon_only);
-
-CREATE INDEX /*i*/ipb_user ON /*_*/ipblocks (ipb_user);
-CREATE INDEX /*i*/ipb_range ON /*_*/ipblocks (ipb_range_start, ipb_range_end);
-CREATE INDEX /*i*/ipb_timestamp ON /*_*/ipblocks (ipb_timestamp);
-CREATE INDEX /*i*/ipb_expiry ON /*_*/ipblocks (ipb_expiry);
-CREATE INDEX /*i*/ipb_parent_block_id ON /*_*/ipblocks (ipb_parent_block_id);
-
---
--- Partial Block Restrictions
---
-CREATE TABLE /*_*/ipblocks_restrictions (
-
- -- The ipb_id from ipblocks
- ir_ipb_id int NOT NULL CONSTRAINT FK_ir_ipb_id FOREIGN KEY REFERENCES /*_*/ipblocks(ipb_id) ON DELETE CASCADE,
-
- -- The restriction type id.
- ir_type tinyint NOT NULL,
-
- -- The restriction id that corrposponds to the type. Typically a Page ID or a
- -- Namespace ID.
- ir_value int NOT NULL,
-
- CONSTRAINT PK_ipblocks_restrictions PRIMARY KEY (ir_ipb_id, ir_type, ir_value)
-) /*$wgDBTableOptions*/;
-
--- Index to query restrictions by the page or namespace.
-CREATE INDEX /*i*/ir_type_value ON /*_*/ipblocks_restrictions (ir_type, ir_value);
-
---
--- Uploaded images and other files.
---
-CREATE TABLE /*_*/image (
- -- Filename.
- -- This is also the title of the associated description page,
- -- which will be in namespace 6 (NS_FILE).
- img_name nvarchar(255) NOT NULL default '' PRIMARY KEY,
-
- -- File size in bytes.
- img_size int NOT NULL default 0,
-
- -- For images, size in pixels.
- img_width int NOT NULL default 0,
- img_height int NOT NULL default 0,
-
- -- Extracted Exif metadata stored as a serialized PHP array.
- img_metadata varbinary(max) NOT NULL,
-
- -- For images, bits per pixel if known.
- img_bits int NOT NULL default 0,
-
- -- Media type as defined by the MEDIATYPE_xxx constants
- img_media_type varchar(16) default null,
-
- -- major part of a MIME media type as defined by IANA
- -- see https://www.iana.org/assignments/media-types/
- img_major_mime varchar(16) not null default 'unknown',
-
- -- minor part of a MIME media type as defined by IANA
- -- the minor parts are not required to adher to any standard
- -- but should be consistent throughout the database
- -- see https://www.iana.org/assignments/media-types/
- img_minor_mime nvarchar(100) NOT NULL default 'unknown',
-
- -- Description field as entered by the uploader.
- -- This is displayed in image upload history and logs.
- img_description_id bigint NOT NULL CONSTRAINT FK_img_description_id FOREIGN KEY REFERENCES /*_*/comment(comment_id),
-
- -- user_id and user_name of uploader.
- img_user int REFERENCES /*_*/mwuser(user_id) ON DELETE SET NULL,
- img_user_text nvarchar(255) NOT NULL CONSTRAINT DF_img_user_text DEFAULT '',
- img_actor bigint NOT NULL CONSTRAINT DF_img_actor DEFAULT 0,
-
- -- Time of the upload.
- img_timestamp nvarchar(14) NOT NULL default '',
-
- -- SHA-1 content hash in base-36
- img_sha1 nvarchar(32) NOT NULL default '',
-
- CONSTRAINT img_major_mime_ckc check (img_major_mime IN('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart', 'chemical')),
- CONSTRAINT img_media_type_ckc check (img_media_type in('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA', 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE','3D'))
-);
-
-CREATE INDEX /*i*/img_usertext_timestamp ON /*_*/image (img_user_text,img_timestamp);
-CREATE INDEX /*i*/img_actor_timestamp ON /*_*/image (img_actor, img_timestamp);
--- Used by Special:ListFiles for sort-by-size
-CREATE INDEX /*i*/img_size ON /*_*/image (img_size);
--- Used by Special:Newimages and Special:ListFiles
-CREATE INDEX /*i*/img_timestamp ON /*_*/image (img_timestamp);
--- Used in API and duplicate search
-CREATE INDEX /*i*/img_sha1 ON /*_*/image (img_sha1);
--- Used to get media of one type
-CREATE INDEX /*i*/img_media_mime ON /*_*/image (img_media_type,img_major_mime,img_minor_mime);
-
-
---
--- Previous revisions of uploaded files.
--- Awkwardly, image rows have to be moved into
--- this table at re-upload time.
---
-CREATE TABLE /*_*/oldimage (
- -- Base filename: key to image.img_name
- -- Not a FK because deleting images removes them from image
- oi_name nvarchar(255) NOT NULL default '',
-
- -- Filename of the archived file.
- -- This is generally a timestamp and '!' prepended to the base name.
- oi_archive_name nvarchar(255) NOT NULL default '',
-
- -- Other fields as in image...
- 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_id bigint NOT NULL CONSTRAINT FK_oi_description_id FOREIGN KEY REFERENCES /*_*/comment(comment_id),
- oi_user int REFERENCES /*_*/mwuser(user_id),
- oi_user_text nvarchar(255) NOT NULL CONSTRAINT DF_oi_user_text DEFAULT '',
- oi_actor bigint NOT NULL CONSTRAINT DF_oi_actor DEFAULT 0,
- oi_timestamp varchar(14) NOT NULL default '',
-
- oi_metadata varbinary(max) NOT NULL,
- oi_media_type varchar(16) default null,
- oi_major_mime varchar(16) not null default 'unknown',
- oi_minor_mime nvarchar(100) NOT NULL default 'unknown',
- oi_deleted tinyint NOT NULL default 0,
- oi_sha1 nvarchar(32) NOT NULL default '',
-
- CONSTRAINT oi_major_mime_ckc check (oi_major_mime IN('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart', 'chemical')),
- CONSTRAINT oi_media_type_ckc check (oi_media_type IN('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA', 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE','3D'))
-);
-
-CREATE INDEX /*i*/oi_usertext_timestamp ON /*_*/oldimage (oi_user_text,oi_timestamp);
-CREATE INDEX /*i*/oi_actor_timestamp ON /*_*/oldimage (oi_actor,oi_timestamp);
-CREATE INDEX /*i*/oi_name_timestamp ON /*_*/oldimage (oi_name,oi_timestamp);
-CREATE INDEX /*i*/oi_sha1 ON /*_*/oldimage (oi_sha1);
-
-
---
--- Record of deleted file data
---
-CREATE TABLE /*_*/filearchive (
- -- Unique row id
- fa_id int NOT NULL PRIMARY KEY IDENTITY,
-
- -- Original base filename; key to image.img_name, page.page_title, etc
- fa_name nvarchar(255) NOT NULL default '',
-
- -- Filename of archived file, if an old revision
- fa_archive_name nvarchar(255) default '',
-
- -- Which storage bin (directory tree or object store) the file data
- -- is stored in. Should be 'deleted' for files that have been deleted;
- -- any other bin is not yet in use.
- fa_storage_group nvarchar(16),
-
- -- SHA-1 of the file contents plus extension, used as a key for storage.
- -- eg 8f8a562add37052a1848ff7771a2c515db94baa9.jpg
- --
- -- If NULL, the file was missing at deletion time or has been purged
- -- from the archival storage.
- fa_storage_key nvarchar(64) default '',
-
- -- Deletion information, if this file is deleted.
- fa_deleted_user int,
- fa_deleted_timestamp varchar(14) default '',
- fa_deleted_reason_id bigint NOT NULL CONSTRAINT FK_fa_deleted_reason_id FOREIGN KEY REFERENCES /*_*/comment(comment_id),
-
- -- Duped fields from image
- fa_size int default 0,
- fa_width int default 0,
- fa_height int default 0,
- fa_metadata varbinary(max),
- fa_bits int default 0,
- fa_media_type varchar(16) default null,
- fa_major_mime varchar(16) not null default 'unknown',
- fa_minor_mime nvarchar(100) default 'unknown',
- fa_description_id bigint NOT NULL CONSTRAINT FK_fa_description_id FOREIGN KEY REFERENCES /*_*/comment(comment_id),
- fa_user int default 0 REFERENCES /*_*/mwuser(user_id) ON DELETE SET NULL,
- fa_user_text nvarchar(255) CONSTRAINT DF_fa_user_text DEFAULT '',
- fa_actor bigint NOT NULL CONSTRAINT DF_fa_actor DEFAULT 0,
- fa_timestamp varchar(14) default '',
-
- -- Visibility of deleted revisions, bitfield
- fa_deleted tinyint NOT NULL default 0,
-
- -- sha1 hash of file content
- fa_sha1 nvarchar(32) NOT NULL default '',
-
- CONSTRAINT fa_major_mime_ckc check (fa_major_mime in('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart', 'chemical')),
- CONSTRAINT fa_media_type_ckc check (fa_media_type in('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA', 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE','3D'))
-);
-
--- pick out by image name
-CREATE INDEX /*i*/fa_name ON /*_*/filearchive (fa_name, fa_timestamp);
--- pick out dupe files
-CREATE INDEX /*i*/fa_storage_group ON /*_*/filearchive (fa_storage_group, fa_storage_key);
--- sort by deletion time
-CREATE INDEX /*i*/fa_deleted_timestamp ON /*_*/filearchive (fa_deleted_timestamp);
--- sort by uploader
-CREATE INDEX /*i*/fa_user_timestamp ON /*_*/filearchive (fa_user_text,fa_timestamp);
-CREATE INDEX /*i*/fa_actor_timestamp ON /*_*/filearchive (fa_actor,fa_timestamp);
--- find file by sha1, 10 bytes will be enough for hashes to be indexed
-CREATE INDEX /*i*/fa_sha1 ON /*_*/filearchive (fa_sha1);
-
-
---
--- Store information about newly uploaded files before they're
--- moved into the actual filestore
---
-CREATE TABLE /*_*/uploadstash (
- us_id int NOT NULL PRIMARY KEY IDENTITY,
-
- -- the user who uploaded the file.
- us_user int REFERENCES /*_*/mwuser(user_id) ON DELETE SET NULL,
-
- -- file key. this is how applications actually search for the file.
- -- this might go away, or become the primary key.
- us_key nvarchar(255) NOT NULL,
-
- -- the original path
- us_orig_path nvarchar(255) NOT NULL,
-
- -- the temporary path at which the file is actually stored
- us_path nvarchar(255) NOT NULL,
-
- -- which type of upload the file came from (sometimes)
- us_source_type nvarchar(50),
-
- -- the date/time on which the file was added
- us_timestamp varchar(14) NOT NULL,
-
- us_status nvarchar(50) NOT NULL,
-
- -- chunk counter starts at 0, current offset is stored in us_size
- us_chunk_inx int NULL,
-
- -- Serialized file properties from FSFile::getProps()
- us_props nvarchar(max),
-
- -- file size in bytes
- us_size int NOT NULL,
- -- this hash comes from FSFile::getSha1Base36(), and is 31 characters
- us_sha1 nvarchar(31) NOT NULL,
- us_mime nvarchar(255),
- -- Media type as defined by the MEDIATYPE_xxx constants, should duplicate definition in the image table
- us_media_type varchar(16) default null,
- -- image-specific properties
- us_image_width int,
- us_image_height int,
- us_image_bits smallint,
-
- CONSTRAINT us_media_type_ckc check (us_media_type in('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA', 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE', '3D'))
-);
-
--- sometimes there's a delete for all of a user's stuff.
-CREATE INDEX /*i*/us_user ON /*_*/uploadstash (us_user);
--- pick out files by key, enforce key uniqueness
-CREATE UNIQUE INDEX /*i*/us_key ON /*_*/uploadstash (us_key);
--- the abandoned upload cleanup script needs this
-CREATE INDEX /*i*/us_timestamp ON /*_*/uploadstash (us_timestamp);
-
-
---
--- Primarily a summary table for Special:Recentchanges,
--- this table contains some additional info on edits from
--- the last few days, see Article::editUpdates()
---
-CREATE TABLE /*_*/recentchanges (
- rc_id int NOT NULL CONSTRAINT recentchanges__pk PRIMARY KEY IDENTITY,
- rc_timestamp varchar(14) not null default '',
-
- -- As in revision
- rc_user int NOT NULL default 0 CONSTRAINT rc_user__user_id__fk FOREIGN KEY REFERENCES /*_*/mwuser(user_id),
- rc_user_text nvarchar(255) NOT NULL CONSTRAINT DF_rc_user_text DEFAULT '',
- rc_actor bigint NOT NULL CONSTRAINT DF_rc_actor DEFAULT 0,
-
- -- When pages are renamed, their RC entries do _not_ change.
- rc_namespace int NOT NULL default 0,
- rc_title nvarchar(255) NOT NULL default '',
-
- -- as in revision...
- rc_comment_id bigint NOT NULL CONSTRAINT FK_rc_comment_id FOREIGN KEY REFERENCES /*_*/comment(comment_id),
- rc_minor bit NOT NULL default 0,
-
- -- Edits by user accounts with the 'bot' rights key are
- -- marked with a 1 here, and will be hidden from the
- -- default view.
- rc_bot bit NOT NULL default 0,
-
- -- Set if this change corresponds to a page creation
- rc_new bit NOT NULL default 0,
-
- -- Key to page_id (was cur_id prior to 1.5).
- -- This will keep links working after moves while
- -- retaining the at-the-time name in the changes list.
- rc_cur_id int, -- NOT FK
-
- -- rev_id of the given revision
- rc_this_oldid int, -- NOT FK
-
- -- rev_id of the prior revision, for generating diff links.
- rc_last_oldid int, -- NOT FK
-
- -- The type of change entry (RC_EDIT,RC_NEW,RC_LOG,RC_EXTERNAL)
- rc_type tinyint NOT NULL default 0,
-
- -- The source of the change entry (replaces rc_type)
- -- default of '' is temporary, needed for initial migration
- rc_source nvarchar(16) not null default '',
-
- -- If the Recent Changes Patrol option is enabled,
- -- users may mark edits as having been reviewed to
- -- remove a warning flag on the RC list.
- -- A value of 1 indicates the page has been reviewed manually.
- -- A value of 2 indicates the page has been automatically reviewed.
- rc_patrolled tinyint NOT NULL CONSTRAINT DF_rc_patrolled DEFAULT 0,
-
- -- Recorded IP address the edit was made from, if the
- -- $wgPutIPinRC option is enabled.
- rc_ip nvarchar(40) NOT NULL default '',
-
- -- Text length in characters before
- -- and after the edit
- rc_old_len int,
- rc_new_len int,
-
- -- Visibility of recent changes items, bitfield
- rc_deleted tinyint NOT NULL default 0,
-
- -- Value corresponding to log_id, specific log entries
- rc_logid int, -- FK added later
- -- Store log type info here, or null
- rc_log_type nvarchar(255) NULL default NULL,
- -- Store log action or null
- rc_log_action nvarchar(255) NULL default NULL,
- -- Log params
- rc_params nvarchar(max) NULL
-);
-
-CREATE INDEX /*i*/rc_timestamp ON /*_*/recentchanges (rc_timestamp);
-CREATE INDEX /*i*/rc_namespace_title_timestamp ON /*_*/recentchanges (rc_namespace, rc_title, rc_timestamp);
-CREATE INDEX /*i*/rc_cur_id ON /*_*/recentchanges (rc_cur_id);
-CREATE INDEX /*i*/new_name_timestamp ON /*_*/recentchanges (rc_new,rc_namespace,rc_timestamp);
-CREATE INDEX /*i*/rc_ip ON /*_*/recentchanges (rc_ip);
-CREATE INDEX /*i*/rc_ns_usertext ON /*_*/recentchanges (rc_namespace, rc_user_text);
-CREATE INDEX /*i*/rc_user_text ON /*_*/recentchanges (rc_user_text, rc_timestamp);
-CREATE INDEX /*i*/rc_ns_actor ON /*_*/recentchanges (rc_namespace, rc_actor);
-CREATE INDEX /*i*/rc_actor ON /*_*/recentchanges (rc_actor, rc_timestamp);
-CREATE INDEX /*i*/rc_name_type_patrolled_timestamp ON /*_*/recentchanges (rc_namespace, rc_type, rc_patrolled, rc_timestamp);
-CREATE INDEX /*i*/rc_this_oldid ON /*_*/recentchanges (rc_this_oldid);
-
-
-CREATE TABLE /*_*/watchlist (
- wl_id int NOT NULL PRIMARY KEY IDENTITY,
- -- Key to user.user_id
- wl_user int NOT NULL REFERENCES /*_*/mwuser(user_id) ON DELETE CASCADE,
-
- -- Key to page_namespace/page_title
- -- Note that users may watch pages which do not exist yet,
- -- or existed in the past but have been deleted.
- wl_namespace int NOT NULL default 0,
- wl_title nvarchar(255) NOT NULL default '',
-
- -- Timestamp used to send notification e-mails and show "updated since last visit" markers on
- -- history and recent changes / watchlist. Set to NULL when the user visits the latest revision
- -- of the page, which means that they should be sent an e-mail on the next change.
- wl_notificationtimestamp varchar(14)
-
-);
-
-CREATE UNIQUE INDEX /*i*/wl_user ON /*_*/watchlist (wl_user, wl_namespace, wl_title);
-CREATE INDEX /*i*/namespace_title ON /*_*/watchlist (wl_namespace, wl_title);
-
-
---
--- Our search index for the builtin MediaWiki search
---
-CREATE TABLE /*_*/searchindex (
- -- Key to page_id
- si_page int NOT NULL REFERENCES /*_*/page(page_id) ON DELETE CASCADE,
-
- -- Munged version of title
- si_title nvarchar(255) NOT NULL default '',
-
- -- Munged version of body text
- si_text nvarchar(max) NOT NULL
-);
-
-CREATE UNIQUE INDEX /*i*/si_page ON /*_*/searchindex (si_page);
--- Fulltext index is defined in MssqlInstaller.php
-
---
--- Recognized interwiki link prefixes
---
-CREATE TABLE /*_*/interwiki (
- -- The interwiki prefix, (e.g. "Meatball", or the language prefix "de")
- iw_prefix nvarchar(32) NOT NULL CONSTRAINT PK_interwiki PRIMARY KEY,
-
- -- The URL of the wiki, with "$1" as a placeholder for an article name.
- -- Any spaces in the name will be transformed to underscores before
- -- insertion.
- iw_url nvarchar(max) NOT NULL,
-
- -- The URL of the file api.php
- iw_api nvarchar(max) NOT NULL,
-
- -- The name of the database (for a connection to be established with LBFactory::getMainLB( 'wikiid' ))
- iw_wikiid nvarchar(64) NOT NULL,
-
- -- A boolean value indicating whether the wiki is in this project
- -- (used, for example, to detect redirect loops)
- iw_local bit NOT NULL,
-
- -- Boolean value indicating whether interwiki transclusions are allowed.
- iw_trans bit NOT NULL default 0
-);
-
---
--- Used for caching expensive grouped queries
---
-CREATE TABLE /*_*/querycache (
- -- A key name, generally the base name of of the special page.
- qc_type nvarchar(32) NOT NULL,
-
- -- Some sort of stored value. Sizes, counts...
- qc_value int NOT NULL default 0,
-
- -- Target namespace+title
- qc_namespace int NOT NULL default 0,
- qc_title nvarchar(255) NOT NULL default ''
-);
-
-CREATE INDEX /*i*/qc_type ON /*_*/querycache (qc_type,qc_value);
-
-
---
--- For a few generic cache operations if not using Memcached
---
-CREATE TABLE /*_*/objectcache (
- keyname nvarchar(255) NOT NULL default '' PRIMARY KEY,
- value varbinary(max),
- exptime varchar(14)
-);
-CREATE INDEX /*i*/exptime ON /*_*/objectcache (exptime);
-
-
-CREATE TABLE /*_*/logging (
- -- Log ID, for referring to this specific log entry, probably for deletion and such.
- log_id int NOT NULL PRIMARY KEY IDENTITY(0,1),
-
- -- Symbolic keys for the general log type and the action type
- -- within the log. The output format will be controlled by the
- -- action field, but only the type controls categorization.
- log_type nvarchar(32) NOT NULL default '',
- log_action nvarchar(32) NOT NULL default '',
-
- -- Timestamp. Duh.
- log_timestamp varchar(14) NOT NULL default '',
-
- -- The user who performed this action; key to user_id
- log_user int, -- NOT an FK, if a user is deleted we still want to maintain a record of who did a thing
-
- -- Name of the user who performed this action
- log_user_text nvarchar(255) NOT NULL default '',
-
- -- The actor who performed this action
- log_actor bigint NOT NULL CONSTRAINT DF_log_actor DEFAULT 0,
-
- -- Key to the page affected. Where a user is the target,
- -- this will point to the user page.
- log_namespace int NOT NULL default 0,
- log_title nvarchar(255) NOT NULL default '',
- log_page int NULL, -- NOT an FK, logging entries are inserted for deleted pages which still reference the deleted page ids
-
- -- Key to comment_id. Comment summarizing the change.
- log_comment_id bigint NOT NULL CONSTRAINT FK_log_comment_id FOREIGN KEY REFERENCES /*_*/comment(comment_id),
-
- -- miscellaneous parameters:
- -- LF separated list (old system) or serialized PHP array (new system)
- log_params nvarchar(max) NOT NULL,
-
- -- rev_deleted for logs
- log_deleted tinyint NOT NULL default 0
-);
-
-CREATE INDEX /*i*/type_time ON /*_*/logging (log_type, log_timestamp);
-CREATE INDEX /*i*/user_time ON /*_*/logging (log_user, log_timestamp);
-CREATE INDEX /*i*/page_time ON /*_*/logging (log_namespace, log_title, log_timestamp);
-CREATE INDEX /*i*/times ON /*_*/logging (log_timestamp);
-CREATE INDEX /*i*/log_user_type_time ON /*_*/logging (log_user, log_type, log_timestamp);
-CREATE INDEX /*i*/log_page_id_time ON /*_*/logging (log_page,log_timestamp);
-CREATE INDEX /*i*/log_type_action ON /*_*/logging (log_type, log_action, log_timestamp);
-CREATE INDEX /*i*/log_user_text_type_time ON /*_*/logging (log_user_text, log_type, log_timestamp);
-CREATE INDEX /*i*/log_user_text_time ON /*_*/logging (log_user_text, log_timestamp);
-CREATE INDEX /*i*/actor_time ON /*_*/logging (log_actor, log_timestamp);
-CREATE INDEX /*i*/log_actor_type_time ON /*_*/logging (log_actor, log_type, log_timestamp);
-
-INSERT INTO /*_*/logging (log_user,log_page,log_params) VALUES(0,0,'');
-
-ALTER TABLE /*_*/recentchanges ADD CONSTRAINT rc_logid__log_id__fk FOREIGN KEY (rc_logid) REFERENCES /*_*/logging(log_id) ON DELETE CASCADE;
-
-CREATE TABLE /*_*/log_search (
- -- The type of ID (rev ID, log ID, rev timestamp, username)
- ls_field nvarchar(32) NOT NULL,
- -- The value of the ID
- ls_value nvarchar(255) NOT NULL,
- -- Key to log_id
- ls_log_id int REFERENCES /*_*/logging(log_id) ON DELETE CASCADE
-);
-CREATE UNIQUE INDEX /*i*/ls_field_val ON /*_*/log_search (ls_field,ls_value,ls_log_id);
-CREATE INDEX /*i*/ls_log_id ON /*_*/log_search (ls_log_id);
-
-
--- Jobs performed by parallel apache threads or a command-line daemon
-CREATE TABLE /*_*/job (
- job_id int NOT NULL PRIMARY KEY IDENTITY,
-
- -- Command name
- -- Limited to 60 to prevent key length overflow
- job_cmd nvarchar(60) NOT NULL default '',
-
- -- Namespace and title to act on
- -- Should be 0 and '' if the command does not operate on a title
- job_namespace int NOT NULL,
- job_title nvarchar(255) NOT NULL,
-
- -- Timestamp of when the job was inserted
- -- NULL for jobs added before addition of the timestamp
- job_timestamp nvarchar(14) NULL default NULL,
-
- -- Any other parameters to the command
- -- Stored as a PHP serialized array, or an empty string if there are no parameters
- job_params nvarchar(max) NOT NULL,
-
- -- Random, non-unique, number used for job acquisition (for lock concurrency)
- job_random int NOT NULL default 0,
-
- -- The number of times this job has been locked
- job_attempts int NOT NULL default 0,
-
- -- Field that conveys process locks on rows via process UUIDs
- job_token nvarchar(32) NOT NULL default '',
-
- -- Timestamp when the job was locked
- job_token_timestamp varchar(14) NULL default NULL,
-
- -- Base 36 SHA1 of the job parameters relevant to detecting duplicates
- job_sha1 nvarchar(32) NOT NULL default ''
-);
-
-CREATE INDEX /*i*/job_sha1 ON /*_*/job (job_sha1);
-CREATE INDEX /*i*/job_cmd_token ON /*_*/job (job_cmd,job_token,job_random);
-CREATE INDEX /*i*/job_cmd_token_id ON /*_*/job (job_cmd,job_token,job_id);
-CREATE INDEX /*i*/job_cmd ON /*_*/job (job_cmd, job_namespace, job_title);
-CREATE INDEX /*i*/job_timestamp ON /*_*/job (job_timestamp);
-
-
--- Details of updates to cached special pages
-CREATE TABLE /*_*/querycache_info (
- -- Special page name
- -- Corresponds to a qc_type value
- qci_type nvarchar(32) NOT NULL default '',
-
- -- Timestamp of last update
- qci_timestamp varchar(14) NOT NULL default ''
-);
-
-CREATE UNIQUE INDEX /*i*/qci_type ON /*_*/querycache_info (qci_type);
-
-
--- For each redirect, this table contains exactly one row defining its target
-CREATE TABLE /*_*/redirect (
- -- Key to the page_id of the redirect page
- rd_from int NOT NULL REFERENCES /*_*/page(page_id) ON DELETE CASCADE,
-
- -- Key to page_namespace/page_title of the target page.
- -- The target page may or may not exist, and due to renames
- -- and deletions may refer to different page records as time
- -- goes by.
- rd_namespace int NOT NULL default 0,
- rd_title nvarchar(255) NOT NULL default '',
- rd_interwiki nvarchar(32) default NULL,
- rd_fragment nvarchar(255) default NULL
-);
-
-CREATE INDEX /*i*/rd_ns_title ON /*_*/redirect (rd_namespace,rd_title,rd_from);
-
-
--- Used for caching expensive grouped queries that need two links (for example double-redirects)
-CREATE TABLE /*_*/querycachetwo (
- -- A key name, generally the base name of of the special page.
- qcc_type nvarchar(32) NOT NULL,
-
- -- Some sort of stored value. Sizes, counts...
- qcc_value int NOT NULL default 0,
-
- -- Target namespace+title
- qcc_namespace int NOT NULL default 0,
- qcc_title nvarchar(255) NOT NULL default '',
-
- -- Target namespace+title2
- qcc_namespacetwo int NOT NULL default 0,
- qcc_titletwo nvarchar(255) NOT NULL default ''
-);
-
-CREATE INDEX /*i*/qcc_type ON /*_*/querycachetwo (qcc_type,qcc_value);
-CREATE INDEX /*i*/qcc_title ON /*_*/querycachetwo (qcc_type,qcc_namespace,qcc_title);
-CREATE INDEX /*i*/qcc_titletwo ON /*_*/querycachetwo (qcc_type,qcc_namespacetwo,qcc_titletwo);
-
-
--- Used for storing page restrictions (i.e. protection levels)
-CREATE TABLE /*_*/page_restrictions (
- -- Field for an ID for this restrictions row (sort-key for Special:ProtectedPages)
- pr_id int NOT NULL PRIMARY KEY IDENTITY,
- -- Page to apply restrictions to (Foreign Key to page).
- pr_page int NOT NULL REFERENCES /*_*/page(page_id) ON DELETE CASCADE,
- -- The protection type (edit, move, etc)
- pr_type nvarchar(60) NOT NULL,
- -- The protection level (Sysop, autoconfirmed, etc)
- pr_level nvarchar(60) NOT NULL,
- -- Whether or not to cascade the protection down to pages transcluded.
- pr_cascade bit NOT NULL,
- -- Field for future support of per-user restriction.
- pr_user int NULL,
- -- Field for time-limited protection.
- pr_expiry varchar(14) NULL
-);
-
-CREATE UNIQUE INDEX /*i*/pr_pagetype ON /*_*/page_restrictions (pr_page,pr_type);
-CREATE INDEX /*i*/pr_typelevel ON /*_*/page_restrictions (pr_type,pr_level);
-CREATE INDEX /*i*/pr_level ON /*_*/page_restrictions (pr_level);
-CREATE INDEX /*i*/pr_cascade ON /*_*/page_restrictions (pr_cascade);
-
-
--- Protected titles - nonexistent pages that have been protected
-CREATE TABLE /*_*/protected_titles (
- pt_namespace int NOT NULL,
- pt_title nvarchar(255) NOT NULL,
- pt_user int REFERENCES /*_*/mwuser(user_id) ON DELETE SET NULL,
- pt_reason_id bigint NOT NULL CONSTRAINT FK_pt_reason_id FOREIGN KEY REFERENCES /*_*/comment(comment_id),
- pt_timestamp varchar(14) NOT NULL,
- pt_expiry varchar(14) NOT NULL,
- pt_create_perm nvarchar(60) NOT NULL,
- CONSTRAINT PK_protected_titles PRIMARY KEY(pt_namespace,pt_title)
-);
-
-CREATE INDEX /*i*/pt_timestamp ON /*_*/protected_titles (pt_timestamp);
-
-
--- Name/value pairs indexed by page_id
-CREATE TABLE /*_*/page_props (
- pp_page int NOT NULL REFERENCES /*_*/page(page_id) ON DELETE CASCADE,
- pp_propname nvarchar(60) NOT NULL,
- pp_value nvarchar(max) NOT NULL,
- pp_sortkey float DEFAULT NULL,
- CONSTRAINT PK_page_props PRIMARY KEY(pp_page,pp_propname)
-);
-
-CREATE UNIQUE INDEX /*i*/pp_propname_page ON /*_*/page_props (pp_propname,pp_page);
-CREATE UNIQUE INDEX /*i*/pp_propname_sortkey_page ON /*_*/page_props (pp_propname,pp_sortkey,pp_page);
-
-
--- A table to log updates, one text key row per update.
-CREATE TABLE /*_*/updatelog (
- ul_key nvarchar(255) NOT NULL PRIMARY KEY,
- ul_value nvarchar(max)
-);
-
-
--- A table to track tags for revisions, logs and recent changes.
-CREATE TABLE /*_*/change_tag (
- ct_id int NOT NULL PRIMARY KEY IDENTITY,
- -- RCID for the change
- ct_rc_id int NULL REFERENCES /*_*/recentchanges(rc_id),
- -- LOGID for the change
- ct_log_id int NULL REFERENCES /*_*/logging(log_id),
- -- REVID for the change
- ct_rev_id int NULL REFERENCES /*_*/revision(rev_id),
- -- Parameters for the tag, presently unused
- ct_params nvarchar(max) NULL,
- -- Foreign key to change_tag_def row
- ct_tag_id int NOT NULL CONSTRAINT ctd_tag_id__fk FOREIGN KEY REFERENCES /*_*/change_tag_def(ctd_id)
-);
-
-CREATE UNIQUE INDEX /*i*/change_tag_rc_tag_id ON /*_*/change_tag (ct_rc_id,ct_tag_id);
-CREATE UNIQUE INDEX /*i*/change_tag_log_tag_id ON /*_*/change_tag (ct_log_id,ct_tag_id);
-CREATE UNIQUE INDEX /*i*/change_tag_rev_tag_id ON /*_*/change_tag (ct_rev_id,ct_tag_id);
-
--- Covering index, so we can pull all the info only out of the index.
-CREATE INDEX /*i*/change_tag_tag_id_id ON /*_*/change_tag (ct_tag_id,ct_rc_id,ct_rev_id,ct_log_id);
-
--- Table for storing localisation data
-CREATE TABLE /*_*/l10n_cache (
- -- Language code
- lc_lang nvarchar(32) NOT NULL,
- -- Cache key
- lc_key nvarchar(255) NOT NULL,
- -- Value
- lc_value varbinary(max) NOT NULL
-);
-CREATE INDEX /*i*/lc_lang_key ON /*_*/l10n_cache (lc_lang, lc_key);
-
--- Table caching which local files a module depends on that aren't
--- registered directly, used for fast retrieval of file dependency.
--- Currently only used for tracking images that CSS depends on
-CREATE TABLE /*_*/module_deps (
- -- Module name
- md_module nvarchar(255) NOT NULL,
- -- Skin name
- md_skin nvarchar(32) NOT NULL,
- -- JSON nvarchar(max) with file dependencies
- md_deps nvarchar(max) NOT NULL
-);
-CREATE UNIQUE INDEX /*i*/md_module_skin ON /*_*/module_deps (md_module, md_skin);
-
--- Holds all the sites known to the wiki.
-CREATE TABLE /*_*/sites (
- -- Numeric id of the site
- site_id int NOT NULL PRIMARY KEY IDENTITY,
-
- -- Global identifier for the site, ie 'enwiktionary'
- site_global_key nvarchar(32) NOT NULL,
-
- -- Type of the site, ie 'mediawiki'
- site_type nvarchar(32) NOT NULL,
-
- -- Group of the site, ie 'wikipedia'
- site_group nvarchar(32) NOT NULL,
-
- -- Source of the site data, ie 'local', 'wikidata', 'my-magical-repo'
- site_source nvarchar(32) NOT NULL,
-
- -- Language code of the sites primary language.
- site_language nvarchar(32) NOT NULL,
-
- -- Protocol of the site, ie 'http://', 'irc://', '//'
- -- This field is an index for lookups and is build from type specific data in site_data.
- site_protocol nvarchar(32) NOT NULL,
-
- -- Domain of the site in reverse order, ie 'org.mediawiki.www.'
- -- This field is an index for lookups and is build from type specific data in site_data.
- site_domain NVARCHAR(255) NOT NULL,
-
- -- Type dependent site data.
- site_data nvarchar(max) NOT NULL,
-
- -- If site.tld/path/key:pageTitle should forward users to the page on
- -- the actual site, where "key" is the local identifier.
- site_forward bit NOT NULL,
-
- -- Type dependent site config.
- -- For instance if template transclusion should be allowed if it's a MediaWiki.
- site_config nvarchar(max) NOT NULL
-);
-
-CREATE UNIQUE INDEX /*i*/sites_global_key ON /*_*/sites (site_global_key);
-CREATE INDEX /*i*/sites_type ON /*_*/sites (site_type);
-CREATE INDEX /*i*/sites_group ON /*_*/sites (site_group);
-CREATE INDEX /*i*/sites_source ON /*_*/sites (site_source);
-CREATE INDEX /*i*/sites_language ON /*_*/sites (site_language);
-CREATE INDEX /*i*/sites_protocol ON /*_*/sites (site_protocol);
-CREATE INDEX /*i*/sites_domain ON /*_*/sites (site_domain);
-CREATE INDEX /*i*/sites_forward ON /*_*/sites (site_forward);
-
--- Links local site identifiers to their corresponding site.
-CREATE TABLE /*_*/site_identifiers (
- -- Key on site.site_id
- si_site int NOT NULL REFERENCES /*_*/sites(site_id) ON DELETE CASCADE,
-
- -- local key type, ie 'interwiki' or 'langlink'
- si_type nvarchar(32) NOT NULL,
-
- -- local key value, ie 'en' or 'wiktionary'
- si_key nvarchar(32) NOT NULL,
-
- CONSTRAINT PK_site_identifiers PRIMARY KEY(si_type, si_key)
-);
-
-CREATE INDEX /*i*/site_ids_site ON /*_*/site_identifiers (si_site);
-CREATE INDEX /*i*/site_ids_key ON /*_*/site_identifiers (si_key);
+++ /dev/null
--- Update keys for Microsoft SQL Server
--- SQL to insert update keys into the initial tables after a
--- fresh installation of MediaWiki's database.
--- This is read and executed by the install script; you should
--- not have to run it by itself unless doing a manual install.
--- Insert keys here if either the unnecessary would cause heavy
--- processing or could potentially cause trouble by lowering field
--- sizes, adding constraints, etc.
--- When adjusting field sizes, it is recommended removing old
--- patches but to play safe, update keys should also inserted here.
-
---
--- The /*_*/ comments in this and other files are
--- replaced with the defined table prefix by the installer
--- and updater scripts. If you are installing or running
--- updates manually, you will need to manually insert the
--- table prefix if any when running these scripts.
---
-
-INSERT INTO /*_*/updatelog
- SELECT 'filearchive-fa_major_mime-patch-fa_major_mime-chemical.sql' AS ul_key, null as ul_value
- UNION SELECT 'image-img_major_mime-patch-img_major_mime-chemical.sql', null
- UNION SELECT 'oldimage-oi_major_mime-patch-oi_major_mime-chemical.sql', null
- UNION SELECT 'cl_type-category_types-ck', null
- UNION SELECT 'fa_major_mime-major_mime-ck', null
- UNION SELECT 'fa_media_type-media_type-ck', null
- UNION SELECT 'img_major_mime-major_mime-ck', null
- UNION SELECT 'img_media_type-media_type-ck', null
- UNION SELECT 'oi_major_mime-major_mime-ck', null
- UNION SELECT 'oi_media_type-media_type-ck', null
- UNION SELECT 'us_media_type-media_type-ck', null;
\ No newline at end of file
+++ /dev/null
-<?php
-/**
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Maintenance
- */
-
-use Wikimedia\Rdbms\DBQueryError;
-
-/**
- * When using shared tables that are referenced by foreign keys on local
- * tables you have to change the constraints on local tables.
- *
- * The shared tables have to have GRANT REFERENCE on shared tables to local schema
- * i.e.: GRANT REFERENCES (user_id) ON mwuser TO hubclient;
- */
-
-require_once __DIR__ . '/../Maintenance.php';
-
-class AlterSharedConstraints extends Maintenance {
- public function __construct() {
- parent::__construct();
- $this->addDescription( 'Alter foreign key to reference master tables in shared database setup.' );
- }
-
- public function getDbType() {
- return Maintenance::DB_ADMIN;
- }
-
- public function execute() {
- global $wgSharedDB, $wgSharedTables, $wgSharedPrefix, $wgDBprefix;
-
- if ( $wgSharedDB == null ) {
- $this->output( "Database sharing is not enabled\n" );
-
- return;
- }
-
- $dbw = $this->getDB( DB_MASTER );
- foreach ( $wgSharedTables as $table ) {
- $stable = $dbw->tableNameInternal( $table );
- if ( $wgSharedPrefix != null ) {
- $ltable = preg_replace( "/^$wgSharedPrefix(.*)/i", "$wgDBprefix\\1", $stable );
- } else {
- $ltable = "{$wgDBprefix}{$stable}";
- }
-
- $result = $dbw->query( "SELECT uc.constraint_name, uc.table_name, ucc.column_name,
- uccpk.table_name pk_table_name, uccpk.column_name pk_column_name,
- uc.delete_rule, uc.deferrable, uc.deferred
- FROM user_constraints uc, user_cons_columns ucc, user_cons_columns uccpk
- WHERE uc.constraint_type = 'R'
- AND ucc.constraint_name = uc.constraint_name
- AND uccpk.constraint_name = uc.r_constraint_name
- AND uccpk.table_name = '$ltable'" );
-
- while ( ( $row = $result->fetchRow() ) !== false ) {
- $this->output( "Altering {$row['constraint_name']} ..." );
-
- try {
- $dbw->query( "ALTER TABLE {$row['table_name']}
- DROP CONSTRAINT {$wgDBprefix}{$row['constraint_name']}" );
- } catch ( DBQueryError $exdb ) {
- if ( $exdb->errno != 2443 ) {
- throw $exdb;
- }
- }
-
- $deleteRule = $row['delete_rule'] == 'NO ACTION' ? '' : "ON DELETE {$row['delete_rule']}";
- $dbw->query( "ALTER TABLE {$row['table_name']}
- ADD CONSTRAINT {$wgDBprefix}{$row['constraint_name']}
- FOREIGN KEY ({$row['column_name']})
- REFERENCES {$wgSharedDB}.$stable({$row['pk_column_name']})
- {$deleteRule} {$row['deferrable']} INITIALLY {$row['deferred']}" );
-
- $this->output( "DONE\n" );
- }
- }
- }
-}
-
-$maintClass = AlterSharedConstraints::class;
-require_once RUN_MAINTENANCE_IF_MAIN;
+++ /dev/null
---
--- patch-actor-table.sql
---
--- T167246. Add an `actor` table and various columns (and temporary tables) to reference it.
-
-define mw_prefix='{$wgDBprefix}';
-
-CREATE SEQUENCE actor_actor_id_seq;
-CREATE TABLE &mw_prefix.actor (
- actor_id NUMBER NOT NULL,
- actor_user NUMBER,
- actor_name VARCHAR2(255) NOT NULL
-);
-
-ALTER TABLE &mw_prefix.actor ADD CONSTRAINT &mw_prefix.actor_pk PRIMARY KEY (actor_id);
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.actor_seq_trg BEFORE INSERT ON &mw_prefix.actor
- FOR EACH ROW WHEN (new.actor_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(actor_actor_id_seq.nextval, :new.actor_id);
-END;
-/*$mw$*/
-
--- Create a dummy actor to satisfy fk contraints
-INSERT INTO &mw_prefix.actor (actor_id, actor_name) VALUES (0,'##Anonymous##');
-
-CREATE TABLE &mw_prefix.revision_actor_temp (
- revactor_rev NUMBER NOT NULL,
- revactor_actor NUMBER NOT NULL,
- revactor_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL,
- revactor_page NUMBER NOT NULL
-);
-ALTER TABLE &mw_prefix.revision_actor_temp ADD CONSTRAINT &mw_prefix.revision_actor_temp_pk PRIMARY KEY (revactor_rev, revactor_actor);
-CREATE UNIQUE INDEX &mw_prefix.revactor_rev ON &mw_prefix.revision_actor_temp (revactor_rev);
-CREATE INDEX &mw_prefix.actor_timestamp ON &mw_prefix.revision_actor_temp (revactor_actor,revactor_timestamp);
-CREATE INDEX &mw_prefix.page_actor_timestamp ON &mw_prefix.revision_actor_temp (revactor_page,revactor_actor,revactor_timestamp);
-
-ALTER TABLE &mw_prefix.archive MODIFY ( ar_user_text NULL );
-ALTER TABLE &mw_prefix.archive ADD ( ar_actor NUMBER DEFAULT 0 NOT NULL );
-CREATE INDEX &mw_prefix.ar_actor_timestamp ON &mw_prefix.archive (ar_actor,ar_timestamp);
-
-ALTER TABLE &mw_prefix.ipblocks ADD ( ipb_by_actor NUMBER DEFAULT 0 NOT NULL );
-
-ALTER TABLE &mw_prefix.image MODIFY ( img_user_text NULL );
-ALTER TABLE &mw_prefix.image ADD ( img_actor NUMBER DEFAULT 0 NOT NULL );
-CREATE INDEX &mw_prefix.img_actor_timestamp ON &mw_prefix.image (img_actor, img_timestamp);
-
-ALTER TABLE &mw_prefix.oldimage MODIFY ( oi_user_text NULL );
-ALTER TABLE &mw_prefix.oldimage ADD ( oi_actor NUMBER DEFAULT 0 NOT NULL );
-CREATE INDEX &mw_prefix.oi_actor_timestamp ON &mw_prefix.oldimage (oi_actor,oi_timestamp);
-
-ALTER TABLE &mw_prefix.filearchive MODIFY ( fa_user_text NULL );
-ALTER TABLE &mw_prefix.filearchive ADD ( fa_actor NUMBER DEFAULT 0 NOT NULL );
-CREATE INDEX &mw_prefix.fa_actor_timestamp ON &mw_prefix.filearchive (fa_actor,fa_timestamp);
-
-ALTER TABLE &mw_prefix.recentchanges MODIFY ( rc_user_text NULL );
-ALTER TABLE &mw_prefix.recentchanges ADD ( rc_actor NUMBER DEFAULT 0 NOT NULL );
-CREATE INDEX &mw_prefix.rc_ns_actor ON &mw_prefix.recentchanges (rc_namespace, rc_actor);
-CREATE INDEX &mw_prefix.rc_actor ON &mw_prefix.recentchanges (rc_actor, rc_timestamp);
-
-ALTER TABLE &mw_prefix.logging ADD ( log_actor NUMBER DEFAULT 0 NOT NULL );
-CREATE INDEX &mw_prefix.actor_time ON &mw_prefix.logging (log_actor, log_timestamp);
-CREATE INDEX &mw_prefix.log_actor_type_time ON &mw_prefix.logging (log_actor, log_type, log_timestamp);
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-CREATE INDEX &mw_prefix.recentchanges_i08 ON &mw_prefix.recentchanges (rc_namespace, rc_type, rc_patrolled, rc_timestamp);
-
+++ /dev/null
--- T182678: Make ar_rev_id not nullable
-
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.archive MODIFY ar_rev_id NUMBER NOT NULL;
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.archive ADD ar_sha1 VARCHAR2(32);
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.archive ADD ar_content_format VARCHAR2(64);
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.archive ADD ar_content_model VARCHAR2(32);
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.archive ADD (
-ar_id NUMBER NOT NULL,
-);
-ALTER TABLE &mw_prefix.archive ADD CONSTRAINT &mw_prefix.archive_pk PRIMARY KEY (ar_id);
+++ /dev/null
--- T193180: ar_rev_id should be unique
-
-define mw_prefix='{$wgDBprefix}';
-
-CREATE UNIQUE INDEX &mw_prefix.archive_i04 ON &mw_prefix.archive (ar_rev_id);
-DROP INDEX &mw_prefix.archive_i03;
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
--- Package to help with making Oracle more like other DBs with respect to
--- auto-incrementing columns.
-/*$mw$*/
-CREATE PACKAGE &mw_prefix.lastval_pkg IS
- lastval NUMBER;
- PROCEDURE setLastval(val IN NUMBER, field OUT NUMBER);
- FUNCTION getLastval RETURN NUMBER;
-END;
-/*$mw$*/
-
-/*$mw$*/
-CREATE PACKAGE BODY &mw_prefix.lastval_pkg IS
- PROCEDURE setLastval(val IN NUMBER, field OUT NUMBER) IS BEGIN
- lastval := val;
- field := val;
- END;
-
- FUNCTION getLastval RETURN NUMBER IS BEGIN
- RETURN lastval;
- END;
-END;
-/*$mw$*/
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.mwuser_seq_trg BEFORE INSERT ON &mw_prefix.mwuser
- FOR EACH ROW WHEN (new.user_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(user_user_id_seq.nextval, :new.user_id);
-END;
-/*$mw$*/
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.page_seq_trg BEFORE INSERT ON &mw_prefix.page
- FOR EACH ROW WHEN (new.page_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(page_page_id_seq.nextval, :new.page_id);
-END;
-/*$mw$*/
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.revision_seq_trg BEFORE INSERT ON &mw_prefix.revision
- FOR EACH ROW WHEN (new.rev_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(revision_rev_id_seq.nextval, :new.rev_id);
-END;
-/*$mw$*/
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.pagecontent_seq_trg BEFORE INSERT ON &mw_prefix.pagecontent
- FOR EACH ROW WHEN (new.old_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(text_old_id_seq.nextval, :new.old_id);
-END;
-/*$mw$*/
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.archive_seq_trg BEFORE INSERT ON &mw_prefix.archive
- FOR EACH ROW WHEN (new.ar_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(archive_ar_id_seq.nextval, :new.ar_id);
-END;
-/*$mw$*/
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.category_seq_trg BEFORE INSERT ON &mw_prefix.category
- FOR EACH ROW WHEN (new.cat_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(category_cat_id_seq.nextval, :new.cat_id);
-END;
-/*$mw$*/
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.externallinks_seq_trg BEFORE INSERT ON &mw_prefix.externallinks
- FOR EACH ROW WHEN (new.el_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(externallinks_el_id_seq.nextval, :new.el_id);
-END;
-/*$mw$*/
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.ipblocks_seq_trg BEFORE INSERT ON &mw_prefix.ipblocks
- FOR EACH ROW WHEN (new.ipb_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(ipblocks_ipb_id_seq.nextval, :new.ipb_id);
-END;
-/*$mw$*/
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.filearchive_seq_trg BEFORE INSERT ON &mw_prefix.filearchive
- FOR EACH ROW WHEN (new.fa_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(filearchive_fa_id_seq.nextval, :new.fa_id);
-END;
-/*$mw$*/
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.uploadstash_seq_trg BEFORE INSERT ON &mw_prefix.uploadstash
- FOR EACH ROW WHEN (new.us_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(uploadstash_us_id_seq.nextval, :new.us_id);
-END;
-/*$mw$*/
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.recentchanges_seq_trg BEFORE INSERT ON &mw_prefix.recentchanges
- FOR EACH ROW WHEN (new.rc_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(recentchanges_rc_id_seq.nextval, :new.rc_id);
-END;
-/*$mw$*/
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.logging_seq_trg BEFORE INSERT ON &mw_prefix.logging
- FOR EACH ROW WHEN (new.log_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(logging_log_id_seq.nextval, :new.log_id);
-END;
-/*$mw$*/
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.job_seq_trg BEFORE INSERT ON &mw_prefix.job
- FOR EACH ROW WHEN (new.job_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(job_job_id_seq.nextval, :new.job_id);
-END;
-/*$mw$*/
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.page_restrictions_seq_trg BEFORE INSERT ON &mw_prefix.page_restrictions
- FOR EACH ROW WHEN (new.pr_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(page_restrictions_pr_id_seq.nextval, :new.pr_id);
-END;
-/*$mw$*/
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.sites_seq_trg BEFORE INSERT ON &mw_prefix.sites
- FOR EACH ROW WHEN (new.site_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(sites_site_id_seq.nextval, :new.site_id);
-END;
-/*$mw$*/
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.category DROP COLUMN cat_hidden;
-
+++ /dev/null
--- T193874: Add new indexes to change_tag table using ct_tag_id instead of ct_tag
-
-define mw_prefix='{$wgDBprefix}';
-
-CREATE UNIQUE INDEX &mw_prefix.change_tag_u04 ON &mw_prefix.change_tag (ct_rc_id,ct_tag_id);
-CREATE UNIQUE INDEX &mw_prefix.change_tag_u05 ON &mw_prefix.change_tag (ct_log_id,ct_tag_id);
-CREATE UNIQUE INDEX &mw_prefix.change_tag_u06 ON &mw_prefix.change_tag (ct_rev_id,ct_tag_id);
-
-CREATE INDEX &mw_prefix.change_tag_i03 ON &mw_prefix.change_tag (ct_rc_id,ct_tag);
-CREATE INDEX &mw_prefix.change_tag_i04 ON &mw_prefix.change_tag (ct_log_id,ct_tag);
-CREATE INDEX &mw_prefix.change_tag_i05 ON &mw_prefix.change_tag (ct_rev_id,ct_tag);
-
-DROP INDEX &mw_prefix.change_tag_u01;
-DROP INDEX &mw_prefix.change_tag_u02;
-DROP INDEX &mw_prefix.change_tag_u03;
-
-ALTER TABLE &mw_prefix.change_tag
- MODIFY ct_tag DEFAULT '///invalid///';
\ No newline at end of file
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.change_tag ADD (
-ct_id NUMBER NOT NULL,
-);
-ALTER TABLE &mw_prefix.change_tag ADD CONSTRAINT &mw_prefix.change_tag_pk PRIMARY KEY (ct_id);
+++ /dev/null
---
--- Add ctd_tag_id to change_tag table to normalize it
---
-ALTER TABLE &mw_prefix.change_tag ADD ( ct_tag_id NUMBER DEFAULT NULL );
-
-CREATE INDEX &mw_prefix.change_tag_i02 ON &mw_prefix.change_tag (ct_tag_id,ct_rc_id,ct_rev_id,ct_log_id);
+++ /dev/null
--- Table defining tag names for IDs. Also stores hit counts to avoid expensive queries on change_tag
-CREATE SEQUENCE change_tag_def_ctd_id_seq;
-CREATE TABLE &mw_prefix.change_tag_def (
- -- Numerical ID of the tag (ct_tag_id refers to this)
- ctd_id NUMBER NOT NULL,
- -- Symbolic name of the tag (what would previously be put in ct_tag)
- ctd_name VARCHAR2(255) NOT NULL,
- -- Whether this tag was defined manually by a privileged user using Special:Tags
- ctd_user_defined CHAR(1) DEFAULT '0' NOT NULL,
- -- Number of times this tag was used
- ctd_count NUMBER NOT NULL DEFAULT 0
-);
-
-ALTER TABLE &mw_prefix.change_tag_def ADD CONSTRAINT &mw_prefix.change_tag_def_pk PRIMARY KEY (ctd_id);
-CREATE UNIQUE INDEX &mw_prefix.ctd_name ON &mw_prefix.change_tag_def (ctd_name);
-CREATE INDEX &mw_prefix.ctd_count ON &mw_prefix.change_tag_def (ctd_count);
-CREATE INDEX &mw_prefix.ctd_user_defined ON &mw_prefix.change_tag_def (ctd_user_defined);
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.change_tag_def_seq_trg BEFORE INSERT ON &mw_prefix.change_tag_def
- FOR EACH ROW WHEN (new.ctd_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(change_tag_def_ctd_id_seq.nextval, :new.ctd_id);
-END;
-/*$mw$*/
\ No newline at end of file
+++ /dev/null
---
--- patch-comment-table.sql
---
--- T166732. Add a `comment` table and various columns (and temporary tables) to reference it.
-
-CREATE SEQUENCE comment_comment_id_seq;
-CREATE TABLE &mw_prefix."COMMENT" (
- comment_id NUMBER NOT NULL,
- comment_hash NUMBER NOT NULL,
- comment_text CLOB,
- comment_data CLOB
-);
-CREATE INDEX &mw_prefix.comment_hash ON &mw_prefix."COMMENT" (comment_hash);
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.comment_seq_trg BEFORE INSERT ON &mw_prefix."COMMENT"
- FOR EACH ROW WHEN (new.comment_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(comment_comment_id_seq.nextval, :new.comment_id);
-END;
-/*$mw$*/
-
--- dummy row for FKs. Hash is intentionally wrong so CommentStore won't match it.
-INSERT INTO &mw_prefix."COMMENT" (comment_hash, comment_text) VALUES (-1, '** dummy **');
-
-
-CREATE TABLE &mw_prefix.revision_comment_temp (
- revcomment_rev NUMBER NOT NULL,
- revcomment_comment_id NUMBER NOT NULL
-);
-ALTER TABLE &mw_prefix.revision_comment_temp ADD CONSTRAINT &mw_prefix.revision_comment_temp_pk PRIMARY KEY (revcomment_rev, revcomment_comment_id);
-ALTER TABLE &mw_prefix.revision_comment_temp ADD CONSTRAINT &mw_prefix.revision_comment_temp_fk1 FOREIGN KEY (revcomment_rev) REFERENCES &mw_prefix.revision(rev_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.revision_comment_temp ADD CONSTRAINT &mw_prefix.revision_comment_temp_fk2 FOREIGN KEY (revcomment_comment_id) REFERENCES &mw_prefix."COMMENT"(comment_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE UNIQUE INDEX &mw_prefix.revcomment_rev ON &mw_prefix.revision_comment_temp (revcomment_rev);
-
-
-CREATE TABLE &mw_prefix.image_comment_temp (
- imgcomment_name VARCHAR2(255) NOT NULL,
- imgcomment_description_id NUMBER NOT NULL
-);
-ALTER TABLE &mw_prefix.image_comment_temp ADD CONSTRAINT &mw_prefix.image_comment_temp_pk PRIMARY KEY (imgcomment_name, imgcomment_description_id);
-ALTER TABLE &mw_prefix.image_comment_temp ADD CONSTRAINT &mw_prefix.image_comment_temp_fk1 FOREIGN KEY (imgcomment_name) REFERENCES &mw_prefix.image(img_name) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.image_comment_temp ADD CONSTRAINT &mw_prefix.image_comment_temp_fk2 FOREIGN KEY (imgcomment_description_id) REFERENCES &mw_prefix."COMMENT"(comment_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE UNIQUE INDEX &mw_prefix.imgcomment_name ON &mw_prefix.image_comment_temp (imgcomment_name);
-
-
-ALTER TABLE &mw_prefix.archive ADD ( ar_comment_id NUMBER DEFAULT 0 NOT NULL );
-ALTER TABLE &mw_prefix.archive ADD CONSTRAINT &mw_prefix.archive_fk2 FOREIGN KEY (ar_comment_id) REFERENCES &mw_prefix."COMMENT"(comment_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-
-ALTER TABLE &mw_prefix.ipblocks MODIFY ( ipb_reason NULL );
-ALTER TABLE &mw_prefix.ipblocks ADD ( ipb_reason_id NUMBER DEFAULT 0 NOT NULL );
-ALTER TABLE &mw_prefix.ipblocks ADD CONSTRAINT &mw_prefix.ipblocks_fk3 FOREIGN KEY (ipb_reason_id) REFERENCES &mw_prefix."COMMENT"(comment_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-
-ALTER TABLE &mw_prefix.oldimage ADD ( oi_description_id NUMBER DEFAULT 0 NOT NULL );
-ALTER TABLE &mw_prefix.oldimage ADD CONSTRAINT &mw_prefix.oldimage_fk3 FOREIGN KEY (oi_description_id) REFERENCES &mw_prefix."COMMENT"(comment_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-
-ALTER TABLE &mw_prefix.filearchive ADD ( fa_deleted_reason_id NUMBER DEFAULT 0 NOT NULL );
-ALTER TABLE &mw_prefix.filearchive ADD ( fa_description_id NUMBER DEFAULT 0 NOT NULL );
-ALTER TABLE &mw_prefix.filearchive ADD CONSTRAINT &mw_prefix.filearchive_fk3 FOREIGN KEY (fa_deleted_reason_id) REFERENCES &mw_prefix."COMMENT"(comment_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.filearchive ADD CONSTRAINT &mw_prefix.filearchive_fk4 FOREIGN KEY (fa_description_id) REFERENCES &mw_prefix."COMMENT"(comment_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-
-ALTER TABLE &mw_prefix.recentchanges ADD ( rc_comment_id NUMBER DEFAULT 0 NOT NULL );
-ALTER TABLE &mw_prefix.recentchanges ADD CONSTRAINT &mw_prefix.recentchanges_fk3 FOREIGN KEY (rc_comment_id) REFERENCES &mw_prefix."COMMENT"(comment_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-
-ALTER TABLE &mw_prefix.logging ADD ( log_comment_id NUMBER DEFAULT 0 NOT NULL );
-ALTER TABLE &mw_prefix.logging ADD CONSTRAINT &mw_prefix.logging_fk2 FOREIGN KEY (log_comment_id) REFERENCES &mw_prefix."COMMENT"(comment_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-
-ALTER TABLE &mw_prefix.protected_titles ADD ( pt_reason_id NUMBER DEFAULT 0 NOT NULL );
-ALTER TABLE &mw_prefix.protected_titles ADD CONSTRAINT &mw_prefix.protected_titles_fk1 FOREIGN KEY (pt_reason_id) REFERENCES &mw_prefix."COMMENT"(comment_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
+++ /dev/null
-CREATE SEQUENCE content_content_id_seq;
-CREATE TABLE &mw_prefix.content (
- content_id NUMBER NOT NULL,
- content_size NUMBER NOT NULL,
- content_sha1 VARCHAR2(32) NOT NULL,
- content_model NUMBER NOT NULL,
- content_address VARCHAR2(255) NOT NULL
-);
-
-ALTER TABLE &mw_prefix.content ADD CONSTRAINT &mw_prefix.content_pk PRIMARY KEY (content_id);
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.content_seq_trg BEFORE INSERT ON &mw_prefix.content
- FOR EACH ROW WHEN (new.content_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(content_content_id_seq.nextval, :new.content_id);
-END;
-/*$mw$*/
\ No newline at end of file
+++ /dev/null
-CREATE SEQUENCE content_models_model_id_seq;
-CREATE TABLE &mw_prefix.content_models (
- model_id NUMBER NOT NULL,
- model_name VARCHAR2(64) NOT NULL
-);
-
-
-ALTER TABLE &mw_prefix.content_models ADD CONSTRAINT &mw_prefix.content_models_pk PRIMARY KEY (model_id);
-
-CREATE UNIQUE INDEX &mw_prefix.model_name_u01 ON &mw_prefix.content_models (model_name);
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.content_models_seq_trg BEFORE INSERT ON &mw_prefix.content_models
- FOR EACH ROW WHEN (new.model_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(content_models_model_id_seq.nextval, :new.model_id);
-END;
-/*$mw$*/
\ No newline at end of file
+++ /dev/null
--- T33223: Remove obsolete ar_text and ar_flags columns
--- (and make ar_text_id not nullable and default 0)
-
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.archive DROP (ar_text, ar_flags);
-ALTER TABLE &mw_prefix.archive MODIFY ar_text_id NUMBER DEFAULT 0 NOT NULL;
+++ /dev/null
---
--- patch-drop-comment-fields.sql
---
--- T166732. Drop old xx_comment fields, and defaults from xx_comment_id fields.
-
-ALTER TABLE &mw_prefix.archive DROP COLUMN ar_comment;
-ALTER TABLE &mw_prefix.archive MODIFY ar_comment_id DEFAULT NULL;
-
-ALTER TABLE &mw_prefix.ipblocks DROP COLUMN ipb_reason;
-ALTER TABLE &mw_prefix.ipblocks MODIFY ipb_reason_id DEFAULT NULL;
-
-ALTER TABLE &mw_prefix.image DROP COLUMN img_description;
-ALTER TABLE &mw_prefix.image MODIFY img_description_id DEFAULT NULL;
-
-ALTER TABLE &mw_prefix.oldimage DROP COLUMN oi_description;
-ALTER TABLE &mw_prefix.oldimage MODIFY oi_description_id DEFAULT NULL;
-
-ALTER TABLE &mw_prefix.filearchive DROP COLUMN fa_deleted_reason;
-ALTER TABLE &mw_prefix.filearchive MODIFY fa_deleted_reason_id DEFAULT NULL,
-ALTER TABLE &mw_prefix.filearchive DROP COLUMN fa_description;
-ALTER TABLE &mw_prefix.filearchive MODIFY fa_description_id DEFAULT NULL;
-
-ALTER TABLE &mw_prefix.recentchanges DROP COLUMN rc_comment;
-ALTER TABLE &mw_prefix.recentchanges MODIFY rc_comment_id DEFAULT NULL;
-
-ALTER TABLE &mw_prefix.logging DROP COLUMN log_comment;
-ALTER TABLE &mw_prefix.logging MODIFY log_comment_id DEFAULT NULL;
-
-ALTER TABLE &mw_prefix.protected_titles DROP COLUMN pt_reason;
-ALTER TABLE &mw_prefix.protected_titles MODIFY pt_reason_id DEFAULT NULL;
+++ /dev/null
--- T185355
-ALTER TABLE &mw_prefix.change_tag MODIFY &mw_prefix.ct_tag_id NUMBER NOT NULL;
-
-DROP INDEX &mw_prefix.change_tag_i03;
-DROP INDEX &mw_prefix.change_tag_i04;
-DROP INDEX &mw_prefix.change_tag_i05;
-DROP INDEX &mw_prefix.change_tag_i01;
-
-ALTER TABLE &mw_prefix.change_tag DROP COLUMN &mw_prefix.ct_tag;
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.externallinks ADD el_id NUMBER NOT NULL;
-ALTER TABLE &mw_prefix.externallinks ADD CONSTRAINT &mw_prefix.externallinks_pk PRIMARY KEY (el_id);
\ No newline at end of file
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.externallinks ADD el_index_60 VARCHAR2(60);
-CREATE INDEX &mw_prefix.externallinks_i04 ON &mw_prefix.externallinks (el_index_60, el_id);
-CREATE INDEX &mw_prefix.externallinks_i05 ON &mw_prefix.externallinks (el_from, el_index_60, el_id);
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.filearchive ADD fa_sha1 VARCHAR2(32);
-CREATE INDEX &mw_prefix.filearchive_i05 ON &mw_prefix.filearchive (fa_sha1);
-
+++ /dev/null
---
--- patch-image-img_description_id.sql
---
--- T188132. Add `img_description_id` to the `image` table.
-
-ALTER TABLE &mw_prefix.image ADD ( img_description_id NUMBER DEFAULT 0 NOT NULL );
-ALTER TABLE &mw_prefix.image ADD CONSTRAINT &mw_prefix.oldimage_fk2 FOREIGN KEY (img_description_id) REFERENCES &mw_prefix."COMMENT"(comment_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
+++ /dev/null
--- Adding ipb_sitewide for blocks
-ALTER TABLE &mw_prefix.ipblocks
- ADD ipb_sitewide CHAR(1) DEFAULT '1' NOT NULL;
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-CREATE INDEX &mw_prefix.ipblocks_i05 ON &mw_prefix.ipblocks (ipb_parent_block_id);
-
+++ /dev/null
--- For partial block restrictions --
-
-CREATE TABLE &mw_prefix.ipblocks_restrictions (
- ir_ipb_id NUMBER NOT NULL,
- ir_type NUMBER NOT NULL,
- ir_value NUMBER NOT NULL
-);
-
-ALTER TABLE &mw_prefix.ipblocks_restrictions ADD CONSTRAINT ipblocks_restrictions_pk PRIMARY KEY (ir_ipb_id, ir_type, ir_value);
-
--- Index to query restrictions by the page or namespace.
-CREATE INDEX &mw_prefix.ir_type_value ON &mw_prefix.ipblocks_restrictions (ir_type, ir_value);
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.job ADD job_attempts NUMBER DEFAULT 0 NOT NULL;
-CREATE INDEX &mw_prefix.job_i05 ON &mw_prefix.job (job_attempts);
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.job ADD job_timestamp TIMESTAMP(6) WITH TIME ZONE NULL;
-
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-CREATE INDEX &mw_prefix.job_i02 ON &mw_prefix.job (job_timestamp);
-
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.job ADD (
- job_random NUMBER DEFAULT 0 NOT NULL,
- job_token VARCHAR2(32),
- job_token_timestamp TIMESTAMP(6) WITH TIME ZONE,
- job_sha1 VARCHAR2(32)
-);
-
-CREATE INDEX &mw_prefix.job_i03 ON &mw_prefix.job (job_sha1);
-CREATE INDEX &mw_prefix.job_i04 ON &mw_prefix.job (job_cmd,job_token,job_random);
-
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-CREATE INDEX &mw_prefix.logging_i05 ON &mw_prefix.logging (log_type, log_action, log_timestamp);
-
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-CREATE INDEX &mw_prefix.logging_i07 ON &mw_prefix.logging (log_user_text, log_timestamp);
-
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-CREATE INDEX &mw_prefix.logging_i06 ON &mw_prefix.logging (log_user_text, log_type, log_timestamp);
-
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.page ADD page_content_model VARCHAR2(32);
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.page ADD page_lang VARCHAR2(35);
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.page ADD page_links_updated TIMESTAMP(6) WITH TIME ZONE;
-
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-CREATE INDEX &mw_prefix.page_i03 ON &mw_prefix.page (page_is_redirect, page_namespace, page_len);
-
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.page_restrictions DROP CONSTRAINT &mw_prefix.page_restrictions_pk;
-
-ALTER TABLE &mw_prefix.page_restrictions ADD CONSTRAINT &mw_prefix.page_restrictions_pk PRIMARY KEY (pr_id);
-
-CREATE UNIQUE INDEX &mw_prefix.page_restrictions_u01 ON &mw_prefix.page_restrictions (pr_page,pr_type);
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.recentchanges DROP ( rc_moved_to_ns, rc_moved_to_title );
-
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.recentchanges ADD rc_source VARCHAR2(16);
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-DROP INDEX IF EXISTS &mw_prefix.recentchanges_i02;
-CREATE INDEX &mw_prefix.recentchanges_i09 ON &mw_prefix.recentchanges (rc_namespace, rc_title, rc_timestamp);
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.revision ADD rev_sha1 VARCHAR2(32);
-
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.revision ADD rev_content_format VARCHAR2(64);
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.revision ADD rev_content_model VARCHAR2(32);
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-CREATE INDEX &mw_prefix.revision_i05 ON &mw_prefix.revision (rev_page,rev_user,rev_timestamp);
-
+++ /dev/null
-ALTER TABLE /*_*/site_stats
- ALTER ss_total_edits SET DEFAULT NULL,
- ALTER ss_good_articles SET DEFAULT NULL,
- ALTER ss_total_pages SET DEFAULT NULL,
- ALTER ss_users SET DEFAULT NULL,
- ALTER ss_active_users SET DEFAULT NULL,
- ALTER ss_images SET DEFAULT NULL;
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.site_stats DROP CONSTRAINT &mw_prefix.site_stats_u01;
-ALTER TABLE &mw_prefix.site_stats ADD CONSTRAINT &mw_prefix.site_stats_pk PRIMARY KEY(ss_row_id);
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-CREATE SEQUENCE sites_site_id_seq MINVALUE 0 START WITH 0;
-CREATE TABLE &mw_prefix.sites (
- site_id NUMBER NOT NULL,
- site_global_key VARCHAR2(32) NOT NULL,
- site_type VARCHAR2(32) NOT NULL,
- site_group VARCHAR2(32) NOT NULL,
- site_source VARCHAR2(32) NOT NULL,
- site_language VARCHAR2(32) NOT NULL,
- site_protocol VARCHAR2(32) NOT NULL,
- site_domain VARCHAR2(255) NOT NULL,
- site_data BLOB NOT NULL,
- site_forward NUMBER(1) NOT NULL,
- site_config BLOB NOT NULL
-);
-ALTER TABLE &mw_prefix.sites ADD CONSTRAINT &mw_prefix.sites_pk PRIMARY KEY (site_id);
-CREATE UNIQUE INDEX &mw_prefix.sites_u01 ON &mw_prefix.sites (site_global_key);
-CREATE INDEX &mw_prefix.sites_i01 ON &mw_prefix.sites (site_type);
-CREATE INDEX &mw_prefix.sites_i02 ON &mw_prefix.sites (site_group);
-CREATE INDEX &mw_prefix.sites_i03 ON &mw_prefix.sites (site_source);
-CREATE INDEX &mw_prefix.sites_i04 ON &mw_prefix.sites (site_language);
-CREATE INDEX &mw_prefix.sites_i05 ON &mw_prefix.sites (site_protocol);
-CREATE INDEX &mw_prefix.sites_i06 ON &mw_prefix.sites (site_domain);
-CREATE INDEX &mw_prefix.sites_i07 ON &mw_prefix.sites (site_forward);
-
-CREATE TABLE &mw_prefix.site_identifiers (
- si_site NUMBER NOT NULL,
- si_type VARCHAR2(32) NOT NULL,
- si_key VARCHAR2(32) NOT NULL
-);
-CREATE UNIQUE INDEX &mw_prefix.site_identifiers_u01 ON &mw_prefix.site_identifiers (si_type, si_key);
-CREATE INDEX &mw_prefix.site_identifiers_i01 ON &mw_prefix.site_identifiers (si_site);
-CREATE INDEX &mw_prefix.site_identifiers_i02 ON &mw_prefix.site_identifiers (si_key);
+++ /dev/null
---
--- Replace slot_inherited with slot_origin.
---
--- NOTE: There is no release that has slot_inherited. This is only needed to transition between
--- snapshot versions of 1.30.
---
--- NOTE: No code that writes to the slots table was merge yet, the table is assumed to be empty.
---
-DROP INDEX &mw_prefix.slot_role_inherited;
-
-ALTER TABLE &mw_prefix.slots DROP COLUMN slot_inherited;
-ALTER TABLE &mw_prefix.slots ADD ( slot_origin NUMBER NOT NULL );
-
-CREATE INDEX &mw_prefix.slot_revision_origin_role ON &mw_prefix.slots (slot_revision_id, slot_origin, slot_role_id);
+++ /dev/null
-CREATE SEQUENCE slot_roles_role_id_seq;
-CREATE TABLE &mw_prefix.slot_roles (
- role_id NUMBER NOT NULL,
- role_name VARCHAR2(64) NOT NULL
-);
-
-ALTER TABLE &mw_prefix.slot_roles ADD CONSTRAINT &mw_prefix.slot_roles_pk PRIMARY KEY (role_id);
-
-CREATE UNIQUE INDEX &mw_prefix.role_name_u01 ON &mw_prefix.slot_roles (role_name);
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.slot_roles_seq_trg BEFORE INSERT ON &mw_prefix.slot_roles
- FOR EACH ROW WHEN (new.role_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(slot_roles_role_id_seq.nextval, :new.role_id);
-END;
-/*$mw$*/
\ No newline at end of file
+++ /dev/null
-CREATE TABLE &mw_prefix.slots (
- slot_revision_id NUMBER NOT NULL,
- slot_role_id NUMBER NOT NULL,
- slot_content_id NUMBER NOT NULL,
- slot_origin NUMBER NOT NULL
-);
-
-ALTER TABLE &mw_prefix.slots ADD CONSTRAINT &mw_prefix.slots_pk PRIMARY KEY (slot_revision_id, slot_role_id);
-
-CREATE INDEX &mw_prefix.slot_revision_origin_role ON &mw_prefix.slots (slot_revision_id, slot_origin, slot_role_id);
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.site_stats DROP COLUMN ss_admins;
-
+++ /dev/null
---
--- Optional tables for parserTests recording mode
--- With --record option, success data will be saved to these tables,
--- and comparisons of what's changed from the previous run will be
--- displayed at the end of each run.
---
--- defines must comply with ^define\s*([^\s=]*)\s*=\s?'\{\$([^\}]*)\}';
-define mw_prefix='{$wgDBprefix}';
-
-DROP TABLE &mw_prefix.testitem CASCADE CONSTRAINTS;
-DROP TABLE &mw_prefix.testrun CASCADE CONSTRAINTS;
-
-CREATE SEQUENCE testrun_tr_id_seq;
-CREATE TABLE &mw_prefix.testrun (
- tr_id NUMBER NOT NULL,
- tr_date DATE,
- tr_mw_version BLOB,
- tr_php_version BLOB,
- tr_db_version BLOB,
- tr_uname BLOB,
-);
-ALTER TABLE &mw_prefix.testrun ADD CONSTRAINT &mw_prefix.testrun_pk PRIMARY KEY (tr_id);
-CREATE OR REPLACE TRIGGER &mw_prefix.testrun_bir
-BEFORE UPDATE FOR EACH ROW
-ON &mw_prefix.testrun
-BEGIN
- SELECT testrun_tr_id_seq.NEXTVAL into :NEW.tr_id FROM dual;
-END;
-
-CREATE TABLE /*$wgDBprefix*/testitem (
- ti_run NUMBER NOT NULL REFERENCES &mw_prefix.testrun (tr_id) ON DELETE CASCADE,
- ti_name VARCHAR22(255),
- ti_success NUMBER(1)
-);
-CREATE UNIQUE INDEX &mw_prefix.testitem_u01 ON &mw_prefix.testitem (ti_run, ti_name);
-CREATE UNIQUE INDEX &mw_prefix.testitem_u01 ON &mw_prefix.testitem (ti_run, ti_success);
-
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-/*$mw$*/
-BEGIN
- EXECUTE IMMEDIATE 'ALTER TABLE &mw_prefix.user_former_groups MODIFY ufg_group VARCHAR2(255) NOT NULL';
-EXCEPTION WHEN OTHERS THEN
- IF (SQLCODE = -01442) THEN NULL; ELSE RAISE; END IF;
-END;
-/*$mw$*/
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-/*$mw$*/
-BEGIN
- EXECUTE IMMEDIATE 'ALTER TABLE &mw_prefix.user_groups MODIFY ug_group VARCHAR2(255) NOT NULL';
-EXCEPTION WHEN OTHERS THEN
- IF (SQLCODE = -01442) THEN NULL; ELSE RAISE; END IF;
-END;
-/*$mw$*/
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.user_properties MODIFY up_property varchar2(255);
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.uploadstash ADD us_props BLOB;
-
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-CREATE SEQUENCE uploadstash_us_id_seq;
-CREATE TABLE &mw_prefix.uploadstash (
- us_id NUMBER NOT NULL,
- us_user NUMBER DEFAULT 0 NOT NULL,
- us_key VARCHAR2(255) NOT NULL,
- us_orig_path VARCHAR2(255) NOT NULL,
- us_path VARCHAR2(255) NOT NULL,
- us_source_type VARCHAR2(50),
- us_timestamp TIMESTAMP(6) WITH TIME ZONE,
- us_status VARCHAR2(50) NOT NULL,
- us_size NUMBER NOT NULL,
- us_sha1 VARCHAR2(32) NOT NULL,
- us_mime VARCHAR2(255),
- us_media_type VARCHAR2(32) DEFAULT NULL,
- us_image_width NUMBER,
- us_image_height NUMBER,
- us_image_bits NUMBER
-);
-ALTER TABLE &mw_prefix.uploadstash ADD CONSTRAINT &mw_prefix.uploadstash_pk PRIMARY KEY (us_id);
-ALTER TABLE &mw_prefix.uploadstash ADD CONSTRAINT &mw_prefix.uploadstash_fk1 FOREIGN KEY (us_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-CREATE INDEX &mw_prefix.uploadstash_i01 ON &mw_prefix.uploadstash (us_user);
-CREATE INDEX &mw_prefix.uploadstash_i02 ON &mw_prefix.uploadstash (us_timestamp);
-CREATE UNIQUE INDEX &mw_prefix.uploadstash_u01 ON &mw_prefix.uploadstash (us_key);
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.uploadstash ADD us_chunk_inx NUMBER;
-
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-CREATE INDEX &mw_prefix.mwuser_i02 ON &mw_prefix.mwuser (user_email);
-
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-CREATE TABLE &mw_prefix.user_former_groups (
- ufg_user NUMBER DEFAULT 0 NOT NULL,
- ufg_group VARCHAR2(255) NOT NULL
-);
-ALTER TABLE &mw_prefix.user_former_groups ADD CONSTRAINT &mw_prefix.user_former_groups_fk1 FOREIGN KEY (ufg_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE UNIQUE INDEX &mw_prefix.user_former_groups_u01 ON &mw_prefix.user_former_groups (ufg_user,ufg_group);
-
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.user_groups ADD (
-ug_expiry TIMESTAMP(6) WITH TIME ZONE NULL
-);
-DROP INDEX IF EXISTS &mw_prefix.user_groups_u01;
-ALTER TABLE &mw_prefix.user_groups ADD CONSTRAINT &mw_prefix.user_groups_pk PRIMARY KEY (ug_user,ug_group);
-CREATE INDEX &mw_prefix.user_groups_i02 ON &mw_prefix.user_groups (ug_expiry);
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.mwuser ADD user_password_expires TIMESTAMP(6) WITH TIME ZONE;
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.watchlist ADD (
-wl_id NUMBER NOT NULL,
-);
-ALTER TABLE &mw_prefix.watchlist ADD CONSTRAINT &mw_prefix.watchlist_pk PRIMARY KEY (wl_id);
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.archive MODIFY ar_user DEFAULT 0 NOT NULL;
-ALTER TABLE &mw_prefix.archive MODIFY ar_deleted CHAR(1);
-CREATE INDEX &mw_prefix.archive_i03 ON &mw_prefix.archive (ar_rev_id);
-
-ALTER TABLE &mw_prefix.page MODIFY page_is_redirect default '0';
-ALTER TABLE &mw_prefix.page MODIFY page_is_new default '0';
-ALTER TABLE &mw_prefix.page MODIFY page_latest default 0;
-ALTER TABLE &mw_prefix.page MODIFY page_len default 0;
-
-ALTER TABLE &mw_prefix.categorylinks MODIFY cl_sortkey VARCHAR2(230);
-ALTER TABLE &mw_prefix.categorylinks ADD cl_sortkey_prefix VARCHAR2(255) DEFAULT '' NOT NULL;
-ALTER TABLE &mw_prefix.categorylinks ADD cl_collation VARCHAR2(32) DEFAULT '' NOT NULL;
-ALTER TABLE &mw_prefix.categorylinks ADD cl_type VARCHAR2(6) DEFAULT 'page' NOT NULL;
-DROP INDEX &mw_prefix.categorylinks_i01;
-CREATE INDEX &mw_prefix.categorylinks_i01 ON &mw_prefix.categorylinks (cl_to,cl_type,cl_sortkey,cl_from);
-CREATE INDEX &mw_prefix.categorylinks_i03 ON &mw_prefix.categorylinks (cl_collation);
-
-ALTER TABLE &mw_prefix.filearchive MODIFY fa_deleted_user DEFAULT 0 NOT NULL;
-ALTER TABLE &mw_prefix.filearchive MODIFY fa_size DEFAULT 0;
-ALTER TABLE &mw_prefix.filearchive MODIFY fa_width DEFAULT 0;
-ALTER TABLE &mw_prefix.filearchive MODIFY fa_height DEFAULT 0;
-ALTER TABLE &mw_prefix.filearchive MODIFY fa_bits DEFAULT 0 NOT NULL;
-ALTER TABLE &mw_prefix.filearchive MODIFY fa_user DEFAULT 0 NOT NULL;
-ALTER TABLE &mw_prefix.filearchive MODIFY fa_deleted DEFAULT 0;
-
-ALTER TABLE &mw_prefix.image MODIFY img_size DEFAULT 0;
-ALTER TABLE &mw_prefix.image MODIFY img_width DEFAULT 0;
-ALTER TABLE &mw_prefix.image MODIFY img_height DEFAULT 0;
-ALTER TABLE &mw_prefix.image MODIFY img_bits DEFAULT 0 NOT NULL;
-ALTER TABLE &mw_prefix.image MODIFY img_user DEFAULT 0 NOT NULL;
-
-ALTER TABLE &mw_prefix.interwiki ADD iw_api BLOB DEFAULT EMPTY_BLOB();
-ALTER TABLE &mw_prefix.interwiki MODIFY iw_api DEFAULT NULL NOT NULL;
-ALTER TABLE &mw_prefix.interwiki ADD iw_wikiid VARCHAR2(64);
-
-ALTER TABLE &mw_prefix.ipblocks MODIFY ipb_user DEFAULT 0 NOT NULL;
-ALTER TABLE &mw_prefix.ipblocks MODIFY ipb_by DEFAULT 0;
-
-CREATE TABLE &mw_prefix.iwlinks (
- iwl_from NUMBER DEFAULT 0 NOT NULL,
- iwl_prefix VARCHAR2(20) DEFAULT '' NOT NULL,
- iwl_title VARCHAR2(255) DEFAULT '' NOT NULL
-);
-CREATE UNIQUE INDEX &mw_prefix.iwlinks_ui01 ON &mw_prefix.iwlinks (iwl_from, iwl_prefix, iwl_title);
-CREATE UNIQUE INDEX &mw_prefix.iwlinks_ui02 ON &mw_prefix.iwlinks (iwl_prefix, iwl_title, iwl_from);
-
-ALTER TABLE &mw_prefix.logging MODIFY log_user DEFAULT 0 NOT NULL;
-ALTER TABLE &mw_prefix.logging MODIFY log_deleted CHAR(1);
-
-CREATE TABLE &mw_prefix.module_deps (
- md_module VARCHAR2(255) NOT NULL,
- md_skin VARCHAR2(32) NOT NULL,
- md_deps BLOB NOT NULL
-);
-CREATE UNIQUE INDEX &mw_prefix.module_deps_u01 ON &mw_prefix.module_deps (md_module, md_skin);
-
-ALTER TABLE &mw_prefix.oldimage MODIFY oi_name DEFAULT 0;
-ALTER TABLE &mw_prefix.oldimage MODIFY oi_size DEFAULT 0;
-ALTER TABLE &mw_prefix.oldimage MODIFY oi_width DEFAULT 0;
-ALTER TABLE &mw_prefix.oldimage MODIFY oi_height DEFAULT 0;
-ALTER TABLE &mw_prefix.oldimage MODIFY oi_bits DEFAULT 0;
-ALTER TABLE &mw_prefix.oldimage MODIFY oi_user DEFAULT 0 NOT NULL;
-
-ALTER TABLE &mw_prefix.querycache MODIFY qc_value DEFAULT 0;
-
-ALTER TABLE &mw_prefix.recentchanges MODIFY rc_user DEFAULT 0 NOT NULL;
-ALTER TABLE &mw_prefix.recentchanges MODIFY rc_cur_id DEFAULT 0 NOT NULL;
-ALTER TABLE &mw_prefix.recentchanges MODIFY rc_this_oldid DEFAULT 0;
-ALTER TABLE &mw_prefix.recentchanges MODIFY rc_last_oldid DEFAULT 0;
-ALTER TABLE &mw_prefix.recentchanges MODIFY rc_moved_to_ns DEFAULT 0 NOT NULL;
-ALTER TABLE &mw_prefix.recentchanges MODIFY rc_deleted CHAR(1);
-ALTER TABLE &mw_prefix.recentchanges MODIFY rc_logid DEFAULT 0;
-
-ALTER TABLE &mw_prefix.revision MODIFY rev_page NOT NULL;
-ALTER TABLE &mw_prefix.revision MODIFY rev_user DEFAULT 0;
-
-ALTER TABLE &mw_prefix.updatelog ADD ul_value BLOB;
-
-ALTER TABLE &mw_prefix.user_groups MODIFY ug_user DEFAULT 0 NOT NULL;
-
-ALTER TABLE &mw_prefix.user_newtalk MODIFY user_id DEFAULT 0;
-
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-/*$mw$*/
-CREATE OR REPLACE PROCEDURE duplicate_table(p_tabname IN VARCHAR2,
- p_oldprefix IN VARCHAR2,
- p_newprefix IN VARCHAR2,
- p_temporary IN BOOLEAN) IS
- e_table_not_exist EXCEPTION;
- PRAGMA EXCEPTION_INIT(e_table_not_exist, -00942);
- l_temp_ei_sql VARCHAR2(2000);
-BEGIN
- BEGIN
- EXECUTE IMMEDIATE 'DROP TABLE ' || p_newprefix || p_tabname ||
- ' CASCADE CONSTRAINTS';
- EXCEPTION
- WHEN e_table_not_exist THEN
- NULL;
- END;
- IF (p_temporary) THEN
- EXECUTE IMMEDIATE 'CREATE GLOBAL TEMPORARY TABLE ' || p_newprefix ||
- p_tabname || ' AS SELECT * FROM ' || p_oldprefix ||
- p_tabname || ' WHERE ROWNUM = 0';
- ELSE
- EXECUTE IMMEDIATE 'CREATE TABLE ' || p_newprefix || p_tabname ||
- ' AS SELECT * FROM ' || p_oldprefix || p_tabname ||
- ' WHERE ROWNUM = 0';
- END IF;
- FOR rc IN (SELECT column_name, data_default
- FROM user_tab_columns
- WHERE table_name = p_oldprefix || p_tabname
- AND data_default IS NOT NULL) LOOP
- EXECUTE IMMEDIATE 'ALTER TABLE ' || p_newprefix || p_tabname ||
- ' MODIFY ' || rc.column_name || ' DEFAULT ' ||
- SUBSTR(rc.data_default, 1, 2000);
- END LOOP;
- FOR rc IN (SELECT REPLACE(REPLACE(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl('CONSTRAINT',
- constraint_name),
- 32767,
- 1),
- USER || '"."' || p_oldprefix,
- USER || '"."' || p_newprefix),
- '"' || constraint_name || '"',
- '"' || p_newprefix || constraint_name || '"') DDLVC2,
- constraint_name
- FROM user_constraints uc
- WHERE table_name = p_oldprefix || p_tabname
- AND constraint_type = 'P') LOOP
- l_temp_ei_sql := SUBSTR(rc.ddlvc2, 1, INSTR(rc.ddlvc2, 'PCTFREE') - 1);
- l_temp_ei_sql := SUBSTR(l_temp_ei_sql, 1, INSTR(l_temp_ei_sql, ')', INSTR(l_temp_ei_sql, 'PRIMARY KEY')+1)+1);
- EXECUTE IMMEDIATE l_temp_ei_sql;
- END LOOP;
- IF (NOT p_temporary) THEN
- FOR rc IN (SELECT REPLACE(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl('REF_CONSTRAINT',
- constraint_name),
- 32767,
- 1),
- USER || '"."' || p_oldprefix,
- USER || '"."' || p_newprefix) DDLVC2,
- constraint_name
- FROM user_constraints uc
- WHERE table_name = p_oldprefix || p_tabname
- AND constraint_type = 'R') LOOP
- EXECUTE IMMEDIATE rc.ddlvc2;
- END LOOP;
- END IF;
- FOR rc IN (SELECT REPLACE(REPLACE(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl('INDEX',
- index_name),
- 32767,
- 1),
- USER || '"."' || p_oldprefix,
- USER || '"."' || p_newprefix),
- '"' || index_name || '"',
- '"' || p_newprefix || index_name || '"') DDLVC2,
- index_name,
- index_type
- FROM user_indexes ui
- WHERE table_name = p_oldprefix || p_tabname
- AND index_type NOT IN ('LOB', 'DOMAIN')
- AND NOT EXISTS
- (SELECT NULL
- FROM user_constraints
- WHERE table_name = ui.table_name
- AND constraint_name = ui.index_name)) LOOP
- l_temp_ei_sql := SUBSTR(rc.ddlvc2, 1, INSTR(rc.ddlvc2, 'PCTFREE') - 1);
- l_temp_ei_sql := SUBSTR(l_temp_ei_sql, 1, INSTR(l_temp_ei_sql, ')', INSTR(l_temp_ei_sql, '"' || USER || '"."' || p_newprefix || '"')+1)+1);
- EXECUTE IMMEDIATE l_temp_ei_sql;
- END LOOP;
- FOR rc IN (SELECT REPLACE(REPLACE(UPPER(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl('TRIGGER',
- trigger_name),
- 32767,
- 1)),
- USER || '"."' || p_oldprefix,
- USER || '"."' || p_newprefix),
- ' ON ' || p_oldprefix || p_tabname,
- ' ON ' || p_newprefix || p_tabname) DDLVC2,
- trigger_name
- FROM user_triggers
- WHERE table_name = p_oldprefix || p_tabname) LOOP
- l_temp_ei_sql := SUBSTR(rc.ddlvc2, 1, INSTR(rc.ddlvc2, 'ALTER ') - 1);
- dbms_output.put_line(l_temp_ei_sql);
- EXECUTE IMMEDIATE l_temp_ei_sql;
- END LOOP;
-END;
-/*$mw$*/
-
-CREATE OR REPLACE TYPE GET_OUTPUT_TYPE IS TABLE OF VARCHAR2(255);
-
-/*$mw$*/
-CREATE OR REPLACE FUNCTION GET_OUTPUT_LINES RETURN GET_OUTPUT_TYPE PIPELINED AS
- v_line VARCHAR2(255);
- v_status INTEGER := 0;
-BEGIN
-
- LOOP
- DBMS_OUTPUT.GET_LINE(v_line, v_status);
- IF (v_status = 0) THEN RETURN; END IF;
- PIPE ROW (v_line);
- END LOOP;
- RETURN;
-EXCEPTION
- WHEN OTHERS THEN
- RETURN;
-END;
-/*$mw$*/
-
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-/*$mw$*/
-BEGIN
--- drop all, recreate manual in case anyone was missing
- FOR cc1 IN (SELECT uc.table_name,
- uc.constraint_name
- FROM user_constraints uc
- WHERE uc.constraint_type = 'R') LOOP
- EXECUTE IMMEDIATE 'ALTER TABLE &mw_prefix.' || cc1.table_name ||
- ' DROP CONSTRAINT ' || cc1.constraint_name;
- END LOOP;
-END;
-/*$mw$*/
-
-ALTER TABLE &mw_prefix.user_groups ADD CONSTRAINT &mw_prefix.user_groups_fk1 FOREIGN KEY (ug_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.user_newtalk ADD CONSTRAINT &mw_prefix.user_newtalk_fk1 FOREIGN KEY (user_id) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.revision ADD CONSTRAINT &mw_prefix.revision_fk1 FOREIGN KEY (rev_page) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.revision ADD CONSTRAINT &mw_prefix.revision_fk2 FOREIGN KEY (rev_user) REFERENCES &mw_prefix.mwuser(user_id) DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.archive ADD CONSTRAINT &mw_prefix.archive_fk1 FOREIGN KEY (ar_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.pagelinks ADD CONSTRAINT &mw_prefix.pagelinks_fk1 FOREIGN KEY (pl_from) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.templatelinks ADD CONSTRAINT &mw_prefix.templatelinks_fk1 FOREIGN KEY (tl_from) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.imagelinks ADD CONSTRAINT &mw_prefix.imagelinks_fk1 FOREIGN KEY (il_from) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.categorylinks ADD CONSTRAINT &mw_prefix.categorylinks_fk1 FOREIGN KEY (cl_from) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.externallinks ADD CONSTRAINT &mw_prefix.externallinks_fk1 FOREIGN KEY (el_from) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.langlinks ADD CONSTRAINT &mw_prefix.langlinks_fk1 FOREIGN KEY (ll_from) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.ipblocks ADD CONSTRAINT &mw_prefix.ipblocks_fk1 FOREIGN KEY (ipb_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.ipblocks ADD CONSTRAINT &mw_prefix.ipblocks_fk2 FOREIGN KEY (ipb_by) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.image ADD CONSTRAINT &mw_prefix.image_fk1 FOREIGN KEY (img_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.oldimage ADD CONSTRAINT &mw_prefix.oldimage_fk1 FOREIGN KEY (oi_name) REFERENCES &mw_prefix.image(img_name) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.oldimage ADD CONSTRAINT &mw_prefix.oldimage_fk2 FOREIGN KEY (oi_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.filearchive ADD CONSTRAINT &mw_prefix.filearchive_fk1 FOREIGN KEY (fa_deleted_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.filearchive ADD CONSTRAINT &mw_prefix.filearchive_fk2 FOREIGN KEY (fa_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.recentchanges ADD CONSTRAINT &mw_prefix.recentchanges_fk1 FOREIGN KEY (rc_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.recentchanges ADD CONSTRAINT &mw_prefix.recentchanges_fk2 FOREIGN KEY (rc_cur_id) REFERENCES &mw_prefix.page(page_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.watchlist ADD CONSTRAINT &mw_prefix.watchlist_fk1 FOREIGN KEY (wl_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.logging ADD CONSTRAINT &mw_prefix.logging_fk1 FOREIGN KEY (log_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.redirect ADD CONSTRAINT &mw_prefix.redirect_fk1 FOREIGN KEY (rd_from) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.page_restrictions ADD CONSTRAINT &mw_prefix.page_restrictions_fk1 FOREIGN KEY (pr_page) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.page MODIFY page_namespace DEFAULT 0;
-ALTER TABLE &mw_prefix.archive MODIFY ar_namespace DEFAULT 0;
-ALTER TABLE &mw_prefix.pagelinks MODIFY pl_namespace DEFAULT 0;
-ALTER TABLE &mw_prefix.templatelinks MODIFY tl_namespace DEFAULT 0;
-ALTER TABLE &mw_prefix.recentchanges MODIFY rc_namespace DEFAULT 0;
-ALTER TABLE &mw_prefix.querycache MODIFY qc_namespace DEFAULT 0;
-ALTER TABLE &mw_prefix.logging MODIFY log_namespace DEFAULT 0;
-ALTER TABLE &mw_prefix.job MODIFY job_namespace DEFAULT 0;
-ALTER TABLE &mw_prefix.redirect MODIFY rd_namespace DEFAULT 0;
-ALTER TABLE &mw_prefix.protected_titles MODIFY pt_namespace DEFAULT 0;
-ALTER TABLE &mw_prefix.archive MODIFY ar_namespace DEFAULT 0;
-ALTER TABLE &mw_prefix.archive MODIFY ar_namespace DEFAULT 0;
-ALTER TABLE &mw_prefix.archive MODIFY ar_namespace DEFAULT 0;
-ALTER TABLE &mw_prefix.archive MODIFY ar_namespace DEFAULT 0;
-
+++ /dev/null
-/*$mw$*/
-CREATE OR REPLACE PROCEDURE duplicate_table(p_tabname IN VARCHAR2,
- p_oldprefix IN VARCHAR2,
- p_newprefix IN VARCHAR2,
- p_temporary IN BOOLEAN) IS
- e_table_not_exist EXCEPTION;
- PRAGMA EXCEPTION_INIT(e_table_not_exist, -00942);
- l_temp_ei_sql VARCHAR2(2000);
- l_temporary BOOLEAN := p_temporary;
-BEGIN
- BEGIN
- EXECUTE IMMEDIATE 'DROP TABLE ' || p_newprefix || p_tabname ||
- ' CASCADE CONSTRAINTS PURGE';
- EXCEPTION
- WHEN e_table_not_exist THEN
- NULL;
- END;
- IF (p_tabname = 'SEARCHINDEX') THEN
- l_temporary := FALSE;
- END IF;
- IF (l_temporary) THEN
- EXECUTE IMMEDIATE 'CREATE GLOBAL TEMPORARY TABLE ' || p_newprefix ||
- p_tabname ||
- ' ON COMMIT PRESERVE ROWS AS SELECT * FROM ' ||
- p_oldprefix || p_tabname || ' WHERE ROWNUM = 0';
- ELSE
- EXECUTE IMMEDIATE 'CREATE TABLE ' || p_newprefix || p_tabname ||
- ' AS SELECT * FROM ' || p_oldprefix || p_tabname ||
- ' WHERE ROWNUM = 0';
- END IF;
- FOR rc IN (SELECT column_name, data_default
- FROM user_tab_columns
- WHERE table_name = p_oldprefix || p_tabname
- AND data_default IS NOT NULL) LOOP
- EXECUTE IMMEDIATE 'ALTER TABLE ' || p_newprefix || p_tabname ||
- ' MODIFY ' || rc.column_name || ' DEFAULT ' ||
- SUBSTR(rc.data_default, 1, 2000);
- END LOOP;
- FOR rc IN (SELECT REPLACE(REPLACE(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl('CONSTRAINT',
- constraint_name),
- 32767,
- 1),
- USER || '"."' || p_oldprefix,
- USER || '"."' || p_newprefix),
- '"' || constraint_name || '"',
- '"' || p_newprefix || constraint_name || '"') DDLVC2,
- constraint_name
- FROM user_constraints uc
- WHERE table_name = p_oldprefix || p_tabname
- AND constraint_type = 'P') LOOP
- l_temp_ei_sql := SUBSTR(rc.ddlvc2, 1, INSTR(rc.ddlvc2, 'PCTFREE') - 1);
- l_temp_ei_sql := SUBSTR(l_temp_ei_sql,
- 1,
- INSTR(l_temp_ei_sql,
- ')',
- INSTR(l_temp_ei_sql, 'PRIMARY KEY') + 1) + 1);
- IF nvl(length(l_temp_ei_sql), 0) > 0 THEN
- EXECUTE IMMEDIATE l_temp_ei_sql;
- END IF;
- END LOOP;
- IF (NOT l_temporary) THEN
- FOR rc IN (SELECT REPLACE(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl('REF_CONSTRAINT',
- constraint_name),
- 32767,
- 1),
- USER || '"."' || p_oldprefix,
- USER || '"."' || p_newprefix) DDLVC2,
- constraint_name
- FROM user_constraints uc
- WHERE table_name = p_oldprefix || p_tabname
- AND constraint_type = 'R') LOOP
- IF nvl(length(l_temp_ei_sql), 0) > 0 AND
- INSTR(l_temp_ei_sql, 'PRIMARY KEY') = 0 THEN
- EXECUTE IMMEDIATE l_temp_ei_sql;
- END IF;
- END LOOP;
- END IF;
- FOR rc IN (SELECT REPLACE(REPLACE(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl('INDEX',
- index_name),
- 32767,
- 1),
- USER || '"."' || p_oldprefix,
- USER || '"."' || p_newprefix),
- '"' || index_name || '"',
- '"' || p_newprefix || index_name || '"') DDLVC2,
- index_name,
- index_type
- FROM user_indexes ui
- WHERE table_name = p_oldprefix || p_tabname
- AND index_type NOT IN ('LOB', 'DOMAIN')
- AND NOT EXISTS
- (SELECT NULL
- FROM user_constraints
- WHERE table_name = ui.table_name
- AND constraint_name = ui.index_name)) LOOP
- l_temp_ei_sql := SUBSTR(rc.ddlvc2, 1, INSTR(rc.ddlvc2, 'PCTFREE') - 1);
- l_temp_ei_sql := SUBSTR(l_temp_ei_sql,
- 1,
- INSTR(l_temp_ei_sql,
- ')',
- INSTR(l_temp_ei_sql,
- '"' || USER || '"."' || p_newprefix || '"') + 1) + 1);
- IF nvl(length(l_temp_ei_sql), 0) > 0 THEN
- EXECUTE IMMEDIATE l_temp_ei_sql;
- END IF;
- END LOOP;
- FOR rc IN (SELECT REPLACE(REPLACE(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl('INDEX',
- index_name),
- 32767,
- 1),
- USER || '"."' || p_oldprefix,
- USER || '"."' || p_newprefix),
- '"' || index_name || '"',
- '"' || p_newprefix || index_name || '"') DDLVC2,
- index_name,
- index_type
- FROM user_indexes ui
- WHERE table_name = p_oldprefix || p_tabname
- AND index_type = 'DOMAIN'
- AND NOT EXISTS
- (SELECT NULL
- FROM user_constraints
- WHERE table_name = ui.table_name
- AND constraint_name = ui.index_name)) LOOP
- l_temp_ei_sql := rc.ddlvc2;
- IF nvl(length(l_temp_ei_sql), 0) > 0 THEN
- EXECUTE IMMEDIATE l_temp_ei_sql;
- END IF;
- END LOOP;
- FOR rc IN (SELECT REPLACE(REPLACE(UPPER(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl('TRIGGER',
- trigger_name),
- 32767,
- 1)),
- USER || '"."' || p_oldprefix,
- USER || '"."' || p_newprefix),
- ' ON ' || p_oldprefix || p_tabname,
- ' ON ' || p_newprefix || p_tabname) DDLVC2,
- trigger_name
- FROM user_triggers
- WHERE table_name = p_oldprefix || p_tabname) LOOP
- l_temp_ei_sql := SUBSTR(rc.ddlvc2, 1, INSTR(rc.ddlvc2, 'ALTER ') - 1);
- IF nvl(length(l_temp_ei_sql), 0) > 0 THEN
- EXECUTE IMMEDIATE l_temp_ei_sql;
- END IF;
- END LOOP;
-END;
-
-/*$mw$*/
-
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.recentchanges DROP CONSTRAINT &mw_prefix.recentchanges_fk2;
-ALTER TABLE &mw_prefix.recentchanges ADD CONSTRAINT &mw_prefix.recentchanges_fk2 FOREIGN KEY (rc_cur_id) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.categorylinks MODIFY cl_sortkey_prefix DEFAULT NULL NULL;
-ALTER TABLE &mw_prefix.categorylinks MODIFY cl_collation DEFAULT NULL NULL;
-ALTER TABLE &mw_prefix.iwlinks MODIFY iwl_prefix DEFAULT NULL NULL;
-ALTER TABLE &mw_prefix.iwlinks MODIFY iwl_title DEFAULT NULL NULL;
-ALTER TABLE &mw_prefix.searchindex MODIFY si_title DEFAULT NULL NULL;
-ALTER TABLE &mw_prefix.querycachetwo MODIFY qcc_title DEFAULT NULL NULL;
-ALTER TABLE &mw_prefix.querycachetwo MODIFY qcc_titletwo DEFAULT NULL NULL;
+++ /dev/null
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.ipblocks MODIFY ipb_by_text DEFAULT NULL NULL;
+++ /dev/null
--- script for renameing sequence names to conform with <table>_<field>_seq format
-RENAME rev_rev_id_val TO revision_rev_id_seq;
-RENAME text_old_id_val TO text_old_id_seq;
-RENAME category_id_seq TO category_cat_id_seq;
-RENAME ipblocks_ipb_id_val TO ipblocks_ipb_id_seq;
-RENAME rc_rc_id_seq TO recentchanges_rc_id_seq;
-RENAME log_log_id_seq TO logging_log_id_seq;
-RENAME pr_id_val TO page_restrictions_pr_id_seq;
\ No newline at end of file
+++ /dev/null
--- defines must comply with ^define\s*([^\s=]*)\s*=\s?'\{\$([^\}]*)\}';
-define mw_prefix='{$wgDBprefix}';
-
--- Package to help with making Oracle more like other DBs with respect to
--- auto-incrementing columns.
-/*$mw$*/
-CREATE PACKAGE &mw_prefix.lastval_pkg IS
- lastval NUMBER;
- PROCEDURE setLastval(val IN NUMBER, field OUT NUMBER);
- FUNCTION getLastval RETURN NUMBER;
-END;
-/*$mw$*/
-
-/*$mw$*/
-CREATE PACKAGE BODY &mw_prefix.lastval_pkg IS
- PROCEDURE setLastval(val IN NUMBER, field OUT NUMBER) IS BEGIN
- lastval := val;
- field := val;
- END;
-
- FUNCTION getLastval RETURN NUMBER IS BEGIN
- RETURN lastval;
- END;
-END;
-/*$mw$*/
-
-CREATE SEQUENCE user_user_id_seq;
-CREATE TABLE &mw_prefix.mwuser ( -- replace reserved word 'user'
- user_id NUMBER NOT NULL,
- user_name VARCHAR2(255) NOT NULL,
- user_real_name VARCHAR2(512),
- user_password VARCHAR2(255),
- user_newpassword VARCHAR2(255),
- user_newpass_time TIMESTAMP(6) WITH TIME ZONE,
- user_token VARCHAR2(32),
- user_email VARCHAR2(255),
- user_email_token VARCHAR2(32),
- user_email_token_expires TIMESTAMP(6) WITH TIME ZONE,
- user_email_authenticated TIMESTAMP(6) WITH TIME ZONE,
- user_options CLOB,
- user_touched TIMESTAMP(6) WITH TIME ZONE,
- user_registration TIMESTAMP(6) WITH TIME ZONE,
- user_editcount NUMBER,
- user_password_expires TIMESTAMP(6) WITH TIME ZONE
-);
-ALTER TABLE &mw_prefix.mwuser ADD CONSTRAINT &mw_prefix.mwuser_pk PRIMARY KEY (user_id);
-CREATE UNIQUE INDEX &mw_prefix.mwuser_u01 ON &mw_prefix.mwuser (user_name);
-CREATE INDEX &mw_prefix.mwuser_i01 ON &mw_prefix.mwuser (user_email_token);
-CREATE INDEX &mw_prefix.mwuser_i02 ON &mw_prefix.mwuser (user_email, user_name);
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.mwuser_seq_trg BEFORE INSERT ON &mw_prefix.mwuser
- FOR EACH ROW WHEN (new.user_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(user_user_id_seq.nextval, :new.user_id);
-END;
-/*$mw$*/
-
--- Create a dummy user to satisfy fk contraints especially with revisions
-INSERT INTO &mw_prefix.mwuser
- (user_id, user_name, user_options, user_touched, user_registration, user_editcount)
- VALUES (0,'Anonymous','', current_timestamp, current_timestamp,0);
-
-CREATE SEQUENCE actor_actor_id_seq;
-CREATE TABLE &mw_prefix.actor (
- actor_id NUMBER NOT NULL,
- actor_user NUMBER,
- actor_name VARCHAR2(255) NOT NULL
-);
-
-ALTER TABLE &mw_prefix.actor ADD CONSTRAINT &mw_prefix.actor_pk PRIMARY KEY (actor_id);
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.actor_seq_trg BEFORE INSERT ON &mw_prefix.actor
- FOR EACH ROW WHEN (new.actor_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(actor_actor_id_seq.nextval, :new.actor_id);
-END;
-/*$mw$*/
-
--- Create a dummy actor to satisfy fk contraints
-INSERT INTO &mw_prefix.actor (actor_id, actor_name) VALUES (0,'##Anonymous##');
-
-CREATE TABLE &mw_prefix.user_groups (
- ug_user NUMBER DEFAULT 0 NOT NULL,
- ug_group VARCHAR2(255) NOT NULL,
- ug_expiry TIMESTAMP(6) WITH TIME ZONE NULL
-);
-ALTER TABLE &mw_prefix.user_groups ADD CONSTRAINT &mw_prefix.user_groups_pk PRIMARY KEY (ug_user,ug_group);
-ALTER TABLE &mw_prefix.user_groups ADD CONSTRAINT &mw_prefix.user_groups_fk1 FOREIGN KEY (ug_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE INDEX &mw_prefix.user_groups_i01 ON &mw_prefix.user_groups (ug_group);
-CREATE INDEX &mw_prefix.user_groups_i02 ON &mw_prefix.user_groups (ug_expiry);
-
-CREATE TABLE &mw_prefix.user_former_groups (
- ufg_user NUMBER DEFAULT 0 NOT NULL,
- ufg_group VARCHAR2(255) NOT NULL
-);
-ALTER TABLE &mw_prefix.user_former_groups ADD CONSTRAINT &mw_prefix.user_former_groups_fk1 FOREIGN KEY (ufg_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE UNIQUE INDEX &mw_prefix.user_former_groups_u01 ON &mw_prefix.user_former_groups (ufg_user,ufg_group);
-
-CREATE TABLE &mw_prefix.user_newtalk (
- user_id NUMBER DEFAULT 0 NOT NULL,
- user_ip VARCHAR2(40) NULL,
- user_last_timestamp TIMESTAMP(6) WITH TIME ZONE
-);
-ALTER TABLE &mw_prefix.user_newtalk ADD CONSTRAINT &mw_prefix.user_newtalk_fk1 FOREIGN KEY (user_id) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE INDEX &mw_prefix.user_newtalk_i01 ON &mw_prefix.user_newtalk (user_id);
-CREATE INDEX &mw_prefix.user_newtalk_i02 ON &mw_prefix.user_newtalk (user_ip);
-
-CREATE TABLE &mw_prefix.user_properties (
- up_user NUMBER NOT NULL,
- up_property VARCHAR2(255) NOT NULL,
- up_value CLOB
-);
-CREATE UNIQUE INDEX &mw_prefix.user_properties_u01 on &mw_prefix.user_properties (up_user,up_property);
-CREATE INDEX &mw_prefix.user_properties_i01 on &mw_prefix.user_properties (up_property);
-
-CREATE SEQUENCE page_page_id_seq;
-CREATE TABLE &mw_prefix.page (
- page_id NUMBER NOT NULL,
- page_namespace NUMBER DEFAULT 0 NOT NULL,
- page_title VARCHAR2(255) NOT NULL,
- page_restrictions VARCHAR2(255),
- page_is_redirect CHAR(1) DEFAULT '0' NOT NULL,
- page_is_new CHAR(1) DEFAULT '0' NOT NULL,
- page_random NUMBER(15,14) NOT NULL,
- page_touched TIMESTAMP(6) WITH TIME ZONE,
- page_links_updated TIMESTAMP(6) WITH TIME ZONE,
- page_latest NUMBER DEFAULT 0 NOT NULL, -- FK?
- page_len NUMBER DEFAULT 0 NOT NULL,
- page_content_model VARCHAR2(32),
- page_lang VARCHAR2(35) DEFAULT NULL
-);
-ALTER TABLE &mw_prefix.page ADD CONSTRAINT &mw_prefix.page_pk PRIMARY KEY (page_id);
-CREATE UNIQUE INDEX &mw_prefix.page_u01 ON &mw_prefix.page (page_namespace,page_title);
-CREATE INDEX &mw_prefix.page_i01 ON &mw_prefix.page (page_random);
-CREATE INDEX &mw_prefix.page_i02 ON &mw_prefix.page (page_len);
-CREATE INDEX &mw_prefix.page_i03 ON &mw_prefix.page (page_is_redirect, page_namespace, page_len);
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.page_seq_trg BEFORE INSERT ON &mw_prefix.page
- FOR EACH ROW WHEN (new.page_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(page_page_id_seq.nextval, :new.page_id);
-END;
-/*$mw$*/
-
--- Create a dummy page to satisfy fk contraints especially with revisions
-INSERT INTO &mw_prefix.page
- VALUES (0, 0, ' ', NULL, 0, 0, 0, current_timestamp, NULL, 0, 0, NULL, NULL);
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.page_set_random BEFORE INSERT ON &mw_prefix.page
- FOR EACH ROW WHEN (new.page_random IS NULL)
-BEGIN
- SELECT dbms_random.value INTO :NEW.page_random FROM dual;
-END;
-/*$mw$*/
-
-CREATE SEQUENCE comment_comment_id_seq;
-CREATE TABLE &mw_prefix."COMMENT" (
- comment_id NUMBER NOT NULL,
- comment_hash NUMBER NOT NULL,
- comment_text CLOB,
- comment_data CLOB
-);
-CREATE INDEX &mw_prefix.comment_hash ON &mw_prefix."COMMENT" (comment_hash);
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.comment_seq_trg BEFORE INSERT ON &mw_prefix."COMMENT"
- FOR EACH ROW WHEN (new.comment_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(comment_comment_id_seq.nextval, :new.comment_id);
-END;
-/*$mw$*/
-
--- dummy row for FKs. Hash is intentionally wrong so CommentStore won't match it.
-INSERT INTO &mw_prefix."COMMENT" (comment_hash, comment_text) VALUES (-1, '** dummy **');
-
-CREATE SEQUENCE revision_rev_id_seq;
-CREATE TABLE &mw_prefix.revision (
- rev_id NUMBER NOT NULL,
- rev_page NUMBER NOT NULL,
- rev_text_id NUMBER NULL,
- rev_comment VARCHAR2(255),
- rev_user NUMBER DEFAULT 0 NOT NULL,
- rev_user_text VARCHAR2(255) NOT NULL,
- rev_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL,
- rev_minor_edit CHAR(1) DEFAULT '0' NOT NULL,
- rev_deleted CHAR(1) DEFAULT '0' NOT NULL,
- rev_len NUMBER NULL,
- rev_parent_id NUMBER DEFAULT NULL,
- rev_sha1 VARCHAR2(32) NULL,
- rev_content_model VARCHAR2(32),
- rev_content_format VARCHAR2(64)
-);
-ALTER TABLE &mw_prefix.revision ADD CONSTRAINT &mw_prefix.revision_pk PRIMARY KEY (rev_id);
-ALTER TABLE &mw_prefix.revision ADD CONSTRAINT &mw_prefix.revision_fk1 FOREIGN KEY (rev_page) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.revision ADD CONSTRAINT &mw_prefix.revision_fk2 FOREIGN KEY (rev_user) REFERENCES &mw_prefix.mwuser(user_id) DEFERRABLE INITIALLY DEFERRED;
-CREATE UNIQUE INDEX &mw_prefix.revision_u01 ON &mw_prefix.revision (rev_page, rev_id);
-CREATE INDEX &mw_prefix.revision_i01 ON &mw_prefix.revision (rev_timestamp);
-CREATE INDEX &mw_prefix.revision_i02 ON &mw_prefix.revision (rev_page,rev_timestamp);
-CREATE INDEX &mw_prefix.revision_i03 ON &mw_prefix.revision (rev_user,rev_timestamp);
-CREATE INDEX &mw_prefix.revision_i04 ON &mw_prefix.revision (rev_user_text,rev_timestamp);
-CREATE INDEX &mw_prefix.revision_i05 ON &mw_prefix.revision (rev_page,rev_user,rev_timestamp);
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.revision_seq_trg BEFORE INSERT ON &mw_prefix.revision
- FOR EACH ROW WHEN (new.rev_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(revision_rev_id_seq.nextval, :new.rev_id);
-END;
-/*$mw$*/
-
-CREATE TABLE &mw_prefix.revision_comment_temp (
- revcomment_rev NUMBER NOT NULL,
- revcomment_comment_id NUMBER NOT NULL
-);
-ALTER TABLE &mw_prefix.revision_comment_temp ADD CONSTRAINT &mw_prefix.revision_comment_temp_pk PRIMARY KEY (revcomment_rev, revcomment_comment_id);
-ALTER TABLE &mw_prefix.revision_comment_temp ADD CONSTRAINT &mw_prefix.revision_comment_temp_fk1 FOREIGN KEY (revcomment_rev) REFERENCES &mw_prefix.revision(rev_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.revision_comment_temp ADD CONSTRAINT &mw_prefix.revision_comment_temp_fk2 FOREIGN KEY (revcomment_comment_id) REFERENCES &mw_prefix."COMMENT"(comment_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE UNIQUE INDEX &mw_prefix.revcomment_rev ON &mw_prefix.revision_comment_temp (revcomment_rev);
-
-CREATE TABLE &mw_prefix.revision_actor_temp (
- revactor_rev NUMBER NOT NULL,
- revactor_actor NUMBER NOT NULL,
- revactor_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL,
- revactor_page NUMBER NOT NULL
-);
-ALTER TABLE &mw_prefix.revision_actor_temp ADD CONSTRAINT &mw_prefix.revision_actor_temp_pk PRIMARY KEY (revactor_rev, revactor_actor);
-CREATE UNIQUE INDEX &mw_prefix.revactor_rev ON &mw_prefix.revision_actor_temp (revactor_rev);
-CREATE INDEX &mw_prefix.actor_timestamp ON &mw_prefix.revision_actor_temp (revactor_actor,revactor_timestamp);
-CREATE INDEX &mw_prefix.page_actor_timestamp ON &mw_prefix.revision_actor_temp (revactor_page,revactor_actor,revactor_timestamp);
-
-CREATE SEQUENCE text_old_id_seq;
-CREATE TABLE &mw_prefix.pagecontent ( -- replaces reserved word 'text'
- old_id NUMBER NOT NULL,
- old_text CLOB,
- old_flags VARCHAR2(255)
-);
-ALTER TABLE &mw_prefix.pagecontent ADD CONSTRAINT &mw_prefix.pagecontent_pk PRIMARY KEY (old_id);
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.pagecontent_seq_trg BEFORE INSERT ON &mw_prefix.pagecontent
- FOR EACH ROW WHEN (new.old_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(text_old_id_seq.nextval, :new.old_id);
-END;
-/*$mw$*/
-
-CREATE SEQUENCE archive_ar_id_seq;
-CREATE TABLE &mw_prefix.archive (
- ar_id NUMBER NOT NULL,
- ar_namespace NUMBER DEFAULT 0 NOT NULL,
- ar_title VARCHAR2(255) NOT NULL,
- ar_comment_id NUMBER NOT NULL,
- ar_user NUMBER DEFAULT 0 NOT NULL,
- ar_user_text VARCHAR2(255) NULL,
- ar_actor NUMBER DEFAULT 0 NOT NULL,
- ar_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL,
- ar_minor_edit CHAR(1) DEFAULT '0' NOT NULL,
- ar_rev_id NUMBER NOT NULL,
- ar_text_id NUMBER DEFAULT 0 NOT NULL,
- ar_deleted CHAR(1) DEFAULT '0' NOT NULL,
- ar_len NUMBER,
- ar_page_id NUMBER,
- ar_parent_id NUMBER,
- ar_sha1 VARCHAR2(32),
- ar_content_model VARCHAR2(32),
- ar_content_format VARCHAR2(64)
-);
-ALTER TABLE &mw_prefix.archive ADD CONSTRAINT &mw_prefix.archive_pk PRIMARY KEY (ar_id);
-ALTER TABLE &mw_prefix.archive ADD CONSTRAINT &mw_prefix.archive_fk1 FOREIGN KEY (ar_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.archive ADD CONSTRAINT &mw_prefix.archive_fk2 FOREIGN KEY (ar_comment_id) REFERENCES &mw_prefix."COMMENT"(comment_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE INDEX &mw_prefix.archive_i01 ON &mw_prefix.archive (ar_namespace,ar_title,ar_timestamp);
-CREATE INDEX &mw_prefix.archive_i02 ON &mw_prefix.archive (ar_user_text,ar_timestamp);
-CREATE INDEX &mw_prefix.ar_actor_timestamp ON &mw_prefix.archive (ar_actor,ar_timestamp);
-CREATE UNIQUE INDEX &mw_prefix.archive_i04 ON &mw_prefix.archive (ar_rev_id);
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.archive_seq_trg BEFORE INSERT ON &mw_prefix.archive
- FOR EACH ROW WHEN (new.ar_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(archive_ar_id_seq.nextval, :new.ar_id);
-END;
-/*$mw$*/
-
-
-CREATE TABLE &mw_prefix.slots (
- slot_revision_id NUMBER NOT NULL,
- slot_role_id NUMBER NOT NULL,
- slot_content_id NUMBER NOT NULL,
- slot_origin NUMBER NOT NULL
-);
-
-ALTER TABLE &mw_prefix.slots ADD CONSTRAINT &mw_prefix.slots_pk PRIMARY KEY (slot_revision_id, slot_role_id);
-
-CREATE INDEX &mw_prefix.slot_revision_origin_role ON &mw_prefix.slots (slot_revision_id, slot_origin, slot_role_id);
-
-
-CREATE SEQUENCE content_content_id_seq;
-CREATE TABLE &mw_prefix.content (
- content_id NUMBER NOT NULL,
- content_size NUMBER NOT NULL,
- content_sha1 VARCHAR2(32) NOT NULL,
- content_model NUMBER NOT NULL,
- content_address VARCHAR2(255) NOT NULL
-);
-
-ALTER TABLE &mw_prefix.content ADD CONSTRAINT &mw_prefix.content_pk PRIMARY KEY (content_id);
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.content_seq_trg BEFORE INSERT ON &mw_prefix.content
- FOR EACH ROW WHEN (new.content_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(content_content_id_seq.nextval, :new.content_id);
-END;
-/*$mw$*/
-
-
-CREATE SEQUENCE slot_roles_role_id_seq;
-CREATE TABLE &mw_prefix.slot_roles (
- role_id NUMBER NOT NULL,
- role_name VARCHAR2(64) NOT NULL
-);
-
-ALTER TABLE &mw_prefix.slot_roles ADD CONSTRAINT &mw_prefix.slot_roles_pk PRIMARY KEY (role_id);
-
-CREATE UNIQUE INDEX &mw_prefix.role_name_u01 ON &mw_prefix.slot_roles (role_name);
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.slot_roles_seq_trg BEFORE INSERT ON &mw_prefix.slot_roles
- FOR EACH ROW WHEN (new.role_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(slot_roles_role_id_seq.nextval, :new.role_id);
-END;
-/*$mw$*/
-
-
-CREATE SEQUENCE content_models_model_id_seq;
-CREATE TABLE &mw_prefix.content_models (
- model_id NUMBER NOT NULL,
- model_name VARCHAR2(64) NOT NULL
-);
-
-
-ALTER TABLE &mw_prefix.content_models ADD CONSTRAINT &mw_prefix.content_models_pk PRIMARY KEY (model_id);
-
-CREATE UNIQUE INDEX &mw_prefix.model_name_u01 ON &mw_prefix.content_models (model_name);
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.content_models_seq_trg BEFORE INSERT ON &mw_prefix.content_models
- FOR EACH ROW WHEN (new.model_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(content_models_model_id_seq.nextval, :new.model_id);
-END;
-/*$mw$*/
-
-
-CREATE TABLE &mw_prefix.pagelinks (
- pl_from NUMBER NOT NULL,
- pl_namespace NUMBER DEFAULT 0 NOT NULL,
- pl_title VARCHAR2(255) NOT NULL
-);
-ALTER TABLE &mw_prefix.pagelinks ADD CONSTRAINT &mw_prefix.pagelinks_fk1 FOREIGN KEY (pl_from) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE UNIQUE INDEX &mw_prefix.pagelinks_u01 ON &mw_prefix.pagelinks (pl_from,pl_namespace,pl_title);
-CREATE UNIQUE INDEX &mw_prefix.pagelinks_u02 ON &mw_prefix.pagelinks (pl_namespace,pl_title,pl_from);
-
-CREATE TABLE &mw_prefix.templatelinks (
- tl_from NUMBER NOT NULL,
- tl_namespace NUMBER DEFAULT 0 NOT NULL,
- tl_title VARCHAR2(255) NOT NULL
-);
-ALTER TABLE &mw_prefix.templatelinks ADD CONSTRAINT &mw_prefix.templatelinks_fk1 FOREIGN KEY (tl_from) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE UNIQUE INDEX &mw_prefix.templatelinks_u01 ON &mw_prefix.templatelinks (tl_from,tl_namespace,tl_title);
-CREATE UNIQUE INDEX &mw_prefix.templatelinks_u02 ON &mw_prefix.templatelinks (tl_namespace,tl_title,tl_from);
-
-CREATE TABLE &mw_prefix.imagelinks (
- il_from NUMBER NOT NULL,
- il_to VARCHAR2(255) NOT NULL
-);
-ALTER TABLE &mw_prefix.imagelinks ADD CONSTRAINT &mw_prefix.imagelinks_fk1 FOREIGN KEY (il_from) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE UNIQUE INDEX &mw_prefix.imagelinks_u01 ON &mw_prefix.imagelinks (il_from,il_to);
-CREATE UNIQUE INDEX &mw_prefix.imagelinks_u02 ON &mw_prefix.imagelinks (il_to,il_from);
-
-
-CREATE TABLE &mw_prefix.categorylinks (
- cl_from NUMBER NOT NULL,
- cl_to VARCHAR2(255) NOT NULL,
- cl_sortkey VARCHAR2(230),
- cl_sortkey_prefix VARCHAR2(255),
- cl_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL,
- cl_collation VARCHAR2(32),
- cl_type VARCHAR2(6) DEFAULT 'page' NOT NULL
-);
-ALTER TABLE &mw_prefix.categorylinks ADD CONSTRAINT &mw_prefix.categorylinks_fk1 FOREIGN KEY (cl_from) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE UNIQUE INDEX &mw_prefix.categorylinks_u01 ON &mw_prefix.categorylinks (cl_from,cl_to);
-CREATE INDEX &mw_prefix.categorylinks_i01 ON &mw_prefix.categorylinks (cl_to,cl_type,cl_sortkey,cl_from);
-CREATE INDEX &mw_prefix.categorylinks_i02 ON &mw_prefix.categorylinks (cl_to,cl_timestamp);
-CREATE INDEX &mw_prefix.categorylinks_i03 ON &mw_prefix.categorylinks (cl_collation);
-
-CREATE SEQUENCE category_cat_id_seq;
-CREATE TABLE &mw_prefix.category (
- cat_id NUMBER NOT NULL,
- cat_title VARCHAR2(255) NOT NULL,
- cat_pages NUMBER DEFAULT 0 NOT NULL,
- cat_subcats NUMBER DEFAULT 0 NOT NULL,
- cat_files NUMBER DEFAULT 0 NOT NULL
-);
-ALTER TABLE &mw_prefix.category ADD CONSTRAINT &mw_prefix.category_pk PRIMARY KEY (cat_id);
-CREATE UNIQUE INDEX &mw_prefix.category_u01 ON &mw_prefix.category (cat_title);
-CREATE INDEX &mw_prefix.category_i01 ON &mw_prefix.category (cat_pages);
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.category_seq_trg BEFORE INSERT ON &mw_prefix.category
- FOR EACH ROW WHEN (new.cat_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(category_cat_id_seq.nextval, :new.cat_id);
-END;
-/*$mw$*/
-
-CREATE SEQUENCE externallinks_el_id_seq;
-CREATE TABLE &mw_prefix.externallinks (
- el_id NUMBER NOT NULL,
- el_from NUMBER NOT NULL,
- el_to VARCHAR2(2048) NOT NULL,
- el_index VARCHAR2(2048) NOT NULL,
- el_index_60 VARCHAR2(60)
-);
-ALTER TABLE &mw_prefix.externallinks ADD CONSTRAINT &mw_prefix.externallinks_pk PRIMARY KEY (el_id);
-ALTER TABLE &mw_prefix.externallinks ADD CONSTRAINT &mw_prefix.externallinks_fk1 FOREIGN KEY (el_from) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE INDEX &mw_prefix.externallinks_i01 ON &mw_prefix.externallinks (el_from, el_to);
-CREATE INDEX &mw_prefix.externallinks_i02 ON &mw_prefix.externallinks (el_to, el_from);
-CREATE INDEX &mw_prefix.externallinks_i03 ON &mw_prefix.externallinks (el_index);
-CREATE INDEX &mw_prefix.externallinks_i04 ON &mw_prefix.externallinks (el_index_60, el_id);
-CREATE INDEX &mw_prefix.externallinks_i05 ON &mw_prefix.externallinks (el_from, el_index_60, el_id);
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.externallinks_seq_trg BEFORE INSERT ON &mw_prefix.externallinks
- FOR EACH ROW WHEN (new.el_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(externallinks_el_id_seq.nextval, :new.el_id);
-END;
-/*$mw$*/
-
--- Table defining tag names for IDs. Also stores hit counts to avoid expensive queries on change_tag
-CREATE SEQUENCE change_tag_def_ctd_id_seq;
-CREATE TABLE &mw_prefix.change_tag_def (
- -- Numerical ID of the tag (ct_tag_id refers to this)
- ctd_id NUMBER NOT NULL,
- -- Symbolic name of the tag (what would previously be put in ct_tag)
- ctd_name VARCHAR2(255) NOT NULL,
- -- Whether this tag was defined manually by a privileged user using Special:Tags
- ctd_user_defined CHAR(1) DEFAULT '0' NOT NULL,
- -- Number of times this tag was used
- ctd_count NUMBER NOT NULL DEFAULT 0
-);
-
-ALTER TABLE &mw_prefix.change_tag_def ADD CONSTRAINT &mw_prefix.change_tag_def_pk PRIMARY KEY (ctd_id);
-CREATE UNIQUE INDEX &mw_prefix.ctd_name ON &mw_prefix.change_tag_def (ctd_name);
-CREATE INDEX &mw_prefix.ctd_count ON &mw_prefix.change_tag_def (ctd_count);
-CREATE INDEX &mw_prefix.ctd_user_defined ON &mw_prefix.change_tag_def (ctd_user_defined);
-
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.change_tag_def_seq_trg BEFORE INSERT ON &mw_prefix.change_tag_def
- FOR EACH ROW WHEN (new.ctd_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(change_tag_def_ctd_id_seq.nextval, :new.ctd_id);
-END;
-/*$mw$*/
-
-CREATE TABLE &mw_prefix.langlinks (
- ll_from NUMBER NOT NULL,
- ll_lang VARCHAR2(20),
- ll_title VARCHAR2(255)
-);
-ALTER TABLE &mw_prefix.langlinks ADD CONSTRAINT &mw_prefix.langlinks_fk1 FOREIGN KEY (ll_from) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE UNIQUE INDEX &mw_prefix.langlinks_u01 ON &mw_prefix.langlinks (ll_from, ll_lang);
-CREATE INDEX &mw_prefix.langlinks_i01 ON &mw_prefix.langlinks (ll_lang, ll_title);
-
-CREATE TABLE &mw_prefix.iwlinks (
- iwl_from NUMBER DEFAULT 0 NOT NULL,
- iwl_prefix VARCHAR2(20),
- iwl_title VARCHAR2(255)
-);
-CREATE UNIQUE INDEX &mw_prefix.iwlinks_ui01 ON &mw_prefix.iwlinks (iwl_from, iwl_prefix, iwl_title);
-CREATE UNIQUE INDEX &mw_prefix.iwlinks_ui02 ON &mw_prefix.iwlinks (iwl_prefix, iwl_title, iwl_from);
-
-CREATE TABLE &mw_prefix.site_stats (
- ss_row_id NUMBER NOT NULL PRIMARY KEY,
- ss_total_edits NUMBER DEFAULT NULL,
- ss_good_articles NUMBER DEFAULT NULL,
- ss_total_pages NUMBER DEFAULT NULL,
- ss_users NUMBER DEFAULT NULL,
- ss_active_users NUMBER DEFAULT NULL,
- ss_images NUMBER DEFAULT NULL
-);
-
-CREATE SEQUENCE ipblocks_ipb_id_seq;
-CREATE TABLE &mw_prefix.ipblocks (
- ipb_id NUMBER NOT NULL,
- ipb_address VARCHAR2(255) NULL,
- ipb_user NUMBER DEFAULT 0 NOT NULL,
- ipb_by NUMBER DEFAULT 0 NOT NULL,
- ipb_by_text VARCHAR2(255) NULL,
- ipb_by_actor NUMBER DEFAULT 0 NOT NULL,
- ipb_reason_id NUMBER NOT NULL,
- ipb_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL,
- ipb_auto CHAR(1) DEFAULT '0' NOT NULL,
- ipb_anon_only CHAR(1) DEFAULT '0' NOT NULL,
- ipb_create_account CHAR(1) DEFAULT '1' NOT NULL,
- ipb_enable_autoblock CHAR(1) DEFAULT '1' NOT NULL,
- ipb_expiry TIMESTAMP(6) WITH TIME ZONE NOT NULL,
- ipb_range_start VARCHAR2(255),
- ipb_range_end VARCHAR2(255),
- ipb_deleted CHAR(1) DEFAULT '0' NOT NULL,
- ipb_block_email CHAR(1) DEFAULT '0' NOT NULL,
- ipb_allow_usertalk CHAR(1) DEFAULT '0' NOT NULL,
- ipb_parent_block_id NUMBER DEFAULT NULL,
- ipb_sitewide CHAR(1) DEFAULT '1' NOT NULL
-);
-ALTER TABLE &mw_prefix.ipblocks ADD CONSTRAINT &mw_prefix.ipblocks_pk PRIMARY KEY (ipb_id);
-ALTER TABLE &mw_prefix.ipblocks ADD CONSTRAINT &mw_prefix.ipblocks_fk1 FOREIGN KEY (ipb_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.ipblocks ADD CONSTRAINT &mw_prefix.ipblocks_fk2 FOREIGN KEY (ipb_by) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.ipblocks ADD CONSTRAINT &mw_prefix.ipblocks_fk3 FOREIGN KEY (ipb_reason_id) REFERENCES &mw_prefix."COMMENT"(comment_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE UNIQUE INDEX &mw_prefix.ipblocks_u01 ON &mw_prefix.ipblocks (ipb_address, ipb_user, ipb_auto, ipb_anon_only);
-CREATE INDEX &mw_prefix.ipblocks_i01 ON &mw_prefix.ipblocks (ipb_user);
-CREATE INDEX &mw_prefix.ipblocks_i02 ON &mw_prefix.ipblocks (ipb_range_start, ipb_range_end);
-CREATE INDEX &mw_prefix.ipblocks_i03 ON &mw_prefix.ipblocks (ipb_timestamp);
-CREATE INDEX &mw_prefix.ipblocks_i04 ON &mw_prefix.ipblocks (ipb_expiry);
-CREATE INDEX &mw_prefix.ipblocks_i05 ON &mw_prefix.ipblocks (ipb_parent_block_id);
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.ipblocks_seq_trg BEFORE INSERT ON &mw_prefix.ipblocks
- FOR EACH ROW WHEN (new.ipb_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(ipblocks_ipb_id_seq.nextval, :new.ipb_id);
-END;
-/*$mw$*/
-
-CREATE TABLE &mw_prefix.ipblocks_restrictions (
- ir_ipb_id NUMBER NOT NULL,
- ir_type NUMBER NOT NULL,
- ir_value NUMBER NOT NULL
-);
-ALTER TABLE &mw_prefix.ipblocks_restrictions ADD CONSTRAINT ipblocks_restrictions_pk PRIMARY KEY (ir_ipb_id, ir_type, ir_value);
-CREATE INDEX &mw_prefix.ir_type_value ON &mw_prefix.ipblocks_restrictions (ir_type, ir_value);
-
-CREATE TABLE &mw_prefix.image (
- img_name VARCHAR2(255) NOT NULL,
- img_size NUMBER DEFAULT 0 NOT NULL,
- img_width NUMBER DEFAULT 0 NOT NULL,
- img_height NUMBER DEFAULT 0 NOT NULL,
- img_metadata CLOB,
- img_bits NUMBER DEFAULT 0 NOT NULL,
- img_media_type VARCHAR2(32),
- img_major_mime VARCHAR2(32) DEFAULT 'unknown',
- img_minor_mime VARCHAR2(100) DEFAULT 'unknown',
- img_description_id NUMBER NOT NULL,
- img_user NUMBER DEFAULT 0 NOT NULL,
- img_user_text VARCHAR2(255) NULL,
- img_actor NUMBER DEFAULT 0 NOT NULL,
- img_timestamp TIMESTAMP(6) WITH TIME ZONE,
- img_sha1 VARCHAR2(32)
-);
-ALTER TABLE &mw_prefix.image ADD CONSTRAINT &mw_prefix.image_pk PRIMARY KEY (img_name);
-ALTER TABLE &mw_prefix.image ADD CONSTRAINT &mw_prefix.image_fk1 FOREIGN KEY (img_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.image ADD CONSTRAINT &mw_prefix.image_fk2 FOREIGN KEY (img_description_id) REFERENCES &mw_prefix."COMMENT"(comment_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE INDEX &mw_prefix.image_i01 ON &mw_prefix.image (img_user_text,img_timestamp);
-CREATE INDEX &mw_prefix.image_i02 ON &mw_prefix.image (img_size);
-CREATE INDEX &mw_prefix.image_i03 ON &mw_prefix.image (img_timestamp);
-CREATE INDEX &mw_prefix.image_i04 ON &mw_prefix.image (img_sha1);
-CREATE INDEX &mw_prefix.img_actor_timestamp ON &mw_prefix.image (img_actor, img_timestamp);
-
-
-CREATE TABLE &mw_prefix.oldimage (
- oi_name VARCHAR2(255) DEFAULT 0 NOT NULL,
- oi_archive_name VARCHAR2(255),
- oi_size NUMBER DEFAULT 0 NOT NULL,
- oi_width NUMBER DEFAULT 0 NOT NULL,
- oi_height NUMBER DEFAULT 0 NOT NULL,
- oi_bits NUMBER DEFAULT 0 NOT NULL,
- oi_description_id NUMBER NOT NULL,
- oi_user NUMBER DEFAULT 0 NOT NULL,
- oi_user_text VARCHAR2(255) NULL,
- oi_actor NUMBER DEFAULT 0 NOT NULL,
- oi_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL,
- oi_metadata CLOB,
- oi_media_type VARCHAR2(32) DEFAULT NULL,
- oi_major_mime VARCHAR2(32) DEFAULT 'unknown',
- oi_minor_mime VARCHAR2(100) DEFAULT 'unknown',
- oi_deleted NUMBER DEFAULT 0 NOT NULL,
- oi_sha1 VARCHAR2(32)
-);
-ALTER TABLE &mw_prefix.oldimage ADD CONSTRAINT &mw_prefix.oldimage_fk1 FOREIGN KEY (oi_name) REFERENCES &mw_prefix.image(img_name) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.oldimage ADD CONSTRAINT &mw_prefix.oldimage_fk2 FOREIGN KEY (oi_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.oldimage ADD CONSTRAINT &mw_prefix.oldimage_fk3 FOREIGN KEY (oi_description_id) REFERENCES &mw_prefix."COMMENT"(comment_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE INDEX &mw_prefix.oldimage_i01 ON &mw_prefix.oldimage (oi_user_text,oi_timestamp);
-CREATE INDEX &mw_prefix.oi_actor_timestamp ON &mw_prefix.oldimage (oi_actor,oi_timestamp);
-CREATE INDEX &mw_prefix.oldimage_i02 ON &mw_prefix.oldimage (oi_name,oi_timestamp);
-CREATE INDEX &mw_prefix.oldimage_i03 ON &mw_prefix.oldimage (oi_name,oi_archive_name);
-CREATE INDEX &mw_prefix.oldimage_i04 ON &mw_prefix.oldimage (oi_sha1);
-
-
-CREATE SEQUENCE filearchive_fa_id_seq;
-CREATE TABLE &mw_prefix.filearchive (
- fa_id NUMBER NOT NULL,
- fa_name VARCHAR2(255) NOT NULL,
- fa_archive_name VARCHAR2(255),
- fa_storage_group VARCHAR2(16),
- fa_storage_key VARCHAR2(64),
- fa_deleted_user NUMBER DEFAULT 0 NOT NULL,
- fa_deleted_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL,
- fa_deleted_reason_id NUMBER NOT NULL,
- fa_size NUMBER DEFAULT 0 NOT NULL,
- fa_width NUMBER DEFAULT 0 NOT NULL,
- fa_height NUMBER DEFAULT 0 NOT NULL,
- fa_metadata CLOB,
- fa_bits NUMBER DEFAULT 0 NOT NULL,
- fa_media_type VARCHAR2(32) DEFAULT NULL,
- fa_major_mime VARCHAR2(32) DEFAULT 'unknown',
- fa_minor_mime VARCHAR2(100) DEFAULT 'unknown',
- fa_description_id NUMBER NOT NULL,
- fa_user NUMBER DEFAULT 0 NOT NULL,
- fa_user_text VARCHAR2(255) NULL,
- fa_actor NUMBER DEFAULT 0 NOT NULL,
- fa_timestamp TIMESTAMP(6) WITH TIME ZONE,
- fa_deleted NUMBER DEFAULT 0 NOT NULL,
- fa_sha1 VARCHAR2(32)
-);
-ALTER TABLE &mw_prefix.filearchive ADD CONSTRAINT &mw_prefix.filearchive_pk PRIMARY KEY (fa_id);
-ALTER TABLE &mw_prefix.filearchive ADD CONSTRAINT &mw_prefix.filearchive_fk1 FOREIGN KEY (fa_deleted_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.filearchive ADD CONSTRAINT &mw_prefix.filearchive_fk2 FOREIGN KEY (fa_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.filearchive ADD CONSTRAINT &mw_prefix.filearchive_fk3 FOREIGN KEY (fa_deleted_reason_id) REFERENCES &mw_prefix."COMMENT"(comment_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.filearchive ADD CONSTRAINT &mw_prefix.filearchive_fk4 FOREIGN KEY (fa_description_id) REFERENCES &mw_prefix."COMMENT"(comment_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE INDEX &mw_prefix.filearchive_i01 ON &mw_prefix.filearchive (fa_name, fa_timestamp);
-CREATE INDEX &mw_prefix.filearchive_i02 ON &mw_prefix.filearchive (fa_storage_group, fa_storage_key);
-CREATE INDEX &mw_prefix.filearchive_i03 ON &mw_prefix.filearchive (fa_deleted_timestamp);
-CREATE INDEX &mw_prefix.filearchive_i04 ON &mw_prefix.filearchive (fa_user_text,fa_timestamp);
-CREATE INDEX &mw_prefix.fa_actor_timestamp ON &mw_prefix.filearchive (fa_actor,fa_timestamp);
-CREATE INDEX &mw_prefix.filearchive_i05 ON &mw_prefix.filearchive (fa_sha1);
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.filearchive_seq_trg BEFORE INSERT ON &mw_prefix.filearchive
- FOR EACH ROW WHEN (new.fa_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(filearchive_fa_id_seq.nextval, :new.fa_id);
-END;
-/*$mw$*/
-
-CREATE SEQUENCE uploadstash_us_id_seq;
-CREATE TABLE &mw_prefix.uploadstash (
- us_id NUMBER NOT NULL,
- us_user NUMBER DEFAULT 0 NOT NULL,
- us_key VARCHAR2(255) NOT NULL,
- us_orig_path VARCHAR2(255) NOT NULL,
- us_path VARCHAR2(255) NOT NULL,
- us_source_type VARCHAR2(50),
- us_timestamp TIMESTAMP(6) WITH TIME ZONE,
- us_status VARCHAR2(50) NOT NULL,
- us_chunk_inx NUMBER,
- us_size NUMBER NOT NULL,
- us_sha1 VARCHAR2(32) NOT NULL,
- us_mime VARCHAR2(255),
- us_media_type VARCHAR2(32) DEFAULT NULL,
- us_image_width NUMBER,
- us_image_height NUMBER,
- us_image_bits NUMBER,
- us_props BLOB
-);
-ALTER TABLE &mw_prefix.uploadstash ADD CONSTRAINT &mw_prefix.uploadstash_pk PRIMARY KEY (us_id);
-ALTER TABLE &mw_prefix.uploadstash ADD CONSTRAINT &mw_prefix.uploadstash_fk1 FOREIGN KEY (us_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-CREATE INDEX &mw_prefix.uploadstash_i01 ON &mw_prefix.uploadstash (us_user);
-CREATE INDEX &mw_prefix.uploadstash_i02 ON &mw_prefix.uploadstash (us_timestamp);
-CREATE UNIQUE INDEX &mw_prefix.uploadstash_u01 ON &mw_prefix.uploadstash (us_key);
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.uploadstash_seq_trg BEFORE INSERT ON &mw_prefix.uploadstash
- FOR EACH ROW WHEN (new.us_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(uploadstash_us_id_seq.nextval, :new.us_id);
-END;
-/*$mw$*/
-
-CREATE SEQUENCE recentchanges_rc_id_seq;
-CREATE TABLE &mw_prefix.recentchanges (
- rc_id NUMBER NOT NULL,
- rc_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL,
- rc_cur_time TIMESTAMP(6) WITH TIME ZONE,
- rc_user NUMBER DEFAULT 0 NOT NULL,
- rc_user_text VARCHAR2(255) NULL,
- rc_actor NUMBER DEFAULT 0 NOT NULL,
- rc_namespace NUMBER DEFAULT 0 NOT NULL,
- rc_title VARCHAR2(255) NOT NULL,
- rc_comment_id NUMBER NOT NULL,
- rc_minor CHAR(1) DEFAULT '0' NOT NULL,
- rc_bot CHAR(1) DEFAULT '0' NOT NULL,
- rc_new CHAR(1) DEFAULT '0' NOT NULL,
- rc_cur_id NUMBER DEFAULT 0 NOT NULL,
- rc_this_oldid NUMBER DEFAULT 0 NOT NULL,
- rc_last_oldid NUMBER DEFAULT 0 NOT NULL,
- rc_type CHAR(1) DEFAULT '0' NOT NULL,
- rc_source VARCHAR2(16),
- rc_patrolled CHAR(1) DEFAULT '0' NOT NULL,
- rc_ip VARCHAR2(15),
- rc_old_len NUMBER,
- rc_new_len NUMBER,
- rc_deleted CHAR(1) DEFAULT '0' NOT NULL,
- rc_logid NUMBER DEFAULT 0 NOT NULL,
- rc_log_type VARCHAR2(255),
- rc_log_action VARCHAR2(255),
- rc_params CLOB
-);
-ALTER TABLE &mw_prefix.recentchanges ADD CONSTRAINT &mw_prefix.recentchanges_pk PRIMARY KEY (rc_id);
-ALTER TABLE &mw_prefix.recentchanges ADD CONSTRAINT &mw_prefix.recentchanges_fk1 FOREIGN KEY (rc_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.recentchanges ADD CONSTRAINT &mw_prefix.recentchanges_fk2 FOREIGN KEY (rc_cur_id) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.recentchanges ADD CONSTRAINT &mw_prefix.recentchanges_fk3 FOREIGN KEY (rc_comment_id) REFERENCES &mw_prefix."COMMENT"(comment_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE INDEX &mw_prefix.recentchanges_i01 ON &mw_prefix.recentchanges (rc_timestamp);
-CREATE INDEX &mw_prefix.recentchanges_i09 ON &mw_prefix.recentchanges (rc_namespace, rc_title, rc_timestamp);
-CREATE INDEX &mw_prefix.recentchanges_i03 ON &mw_prefix.recentchanges (rc_cur_id);
-CREATE INDEX &mw_prefix.recentchanges_i04 ON &mw_prefix.recentchanges (rc_new,rc_namespace,rc_timestamp);
-CREATE INDEX &mw_prefix.recentchanges_i05 ON &mw_prefix.recentchanges (rc_ip);
-CREATE INDEX &mw_prefix.recentchanges_i06 ON &mw_prefix.recentchanges (rc_namespace, rc_user_text);
-CREATE INDEX &mw_prefix.recentchanges_i07 ON &mw_prefix.recentchanges (rc_user_text, rc_timestamp);
-CREATE INDEX &mw_prefix.rc_ns_actor ON &mw_prefix.recentchanges (rc_namespace, rc_actor);
-CREATE INDEX &mw_prefix.rc_actor ON &mw_prefix.recentchanges (rc_actor, rc_timestamp);
-CREATE INDEX &mw_prefix.recentchanges_i08 ON &mw_prefix.recentchanges (rc_namespace, rc_type, rc_patrolled, rc_timestamp);
-CREATE INDEX &mw_prefix.recentchanges_i10 ON &mw_prefix.recentchanges (rc_this_oldid);
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.recentchanges_seq_trg BEFORE INSERT ON &mw_prefix.recentchanges
- FOR EACH ROW WHEN (new.rc_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(recentchanges_rc_id_seq.nextval, :new.rc_id);
-END;
-/*$mw$*/
-
-CREATE TABLE &mw_prefix.watchlist (
- wl_id NUMBER NOT NULL,
- wl_user NUMBER NOT NULL,
- wl_namespace NUMBER DEFAULT 0 NOT NULL,
- wl_title VARCHAR2(255) NOT NULL,
- wl_notificationtimestamp TIMESTAMP(6) WITH TIME ZONE
-);
-ALTER TABLE &mw_prefix.watchlist ADD CONSTRAINT &mw_prefix.watchlist_pk PRIMARY KEY (wl_id);
-ALTER TABLE &mw_prefix.watchlist ADD CONSTRAINT &mw_prefix.watchlist_fk1 FOREIGN KEY (wl_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE UNIQUE INDEX &mw_prefix.watchlist_u01 ON &mw_prefix.watchlist (wl_user, wl_namespace, wl_title);
-CREATE INDEX &mw_prefix.watchlist_i01 ON &mw_prefix.watchlist (wl_namespace, wl_title);
-
-
-CREATE TABLE &mw_prefix.searchindex (
- si_page NUMBER NOT NULL,
- si_title VARCHAR2(255),
- si_text CLOB NOT NULL
-);
-CREATE UNIQUE INDEX &mw_prefix.searchindex_u01 ON &mw_prefix.searchindex (si_page);
-
-CREATE TABLE &mw_prefix.interwiki (
- iw_prefix VARCHAR2(32) NOT NULL,
- iw_url VARCHAR2(127) NOT NULL,
- iw_api BLOB NOT NULL,
- iw_wikiid VARCHAR2(64),
- iw_local CHAR(1) NOT NULL,
- iw_trans CHAR(1) DEFAULT '0' NOT NULL
-);
-CREATE UNIQUE INDEX &mw_prefix.interwiki_u01 ON &mw_prefix.interwiki (iw_prefix);
-
-CREATE TABLE &mw_prefix.querycache (
- qc_type VARCHAR2(32) NOT NULL,
- qc_value NUMBER DEFAULT 0 NOT NULL,
- qc_namespace NUMBER DEFAULT 0 NOT NULL,
- qc_title VARCHAR2(255) NOT NULL
-);
-CREATE INDEX &mw_prefix.querycache_u01 ON &mw_prefix.querycache (qc_type,qc_value);
-
-CREATE TABLE &mw_prefix.objectcache (
- keyname VARCHAR2(255) ,
- value BLOB,
- exptime TIMESTAMP(6) WITH TIME ZONE NOT NULL
-);
-CREATE INDEX &mw_prefix.objectcache_i01 ON &mw_prefix.objectcache (exptime);
-
-
-CREATE SEQUENCE logging_log_id_seq;
-CREATE TABLE &mw_prefix.logging (
- log_id NUMBER NOT NULL,
- log_type VARCHAR2(10) NOT NULL,
- log_action VARCHAR2(10) NOT NULL,
- log_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL,
- log_user NUMBER DEFAULT 0 NOT NULL,
- log_user_text VARCHAR2(255),
- log_actor NUMBER DEFAULT 0 NOT NULL,
- log_namespace NUMBER DEFAULT 0 NOT NULL,
- log_title VARCHAR2(255) NOT NULL,
- log_page NUMBER,
- log_comment_id NUMBER NOT NULL,
- log_params CLOB,
- log_deleted CHAR(1) DEFAULT '0' NOT NULL
-);
-ALTER TABLE &mw_prefix.logging ADD CONSTRAINT &mw_prefix.logging_pk PRIMARY KEY (log_id);
-ALTER TABLE &mw_prefix.logging ADD CONSTRAINT &mw_prefix.logging_fk1 FOREIGN KEY (log_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.logging ADD CONSTRAINT &mw_prefix.logging_fk2 FOREIGN KEY (log_comment_id) REFERENCES &mw_prefix."COMMENT"(comment_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE INDEX &mw_prefix.logging_i01 ON &mw_prefix.logging (log_type, log_timestamp);
-CREATE INDEX &mw_prefix.logging_i02 ON &mw_prefix.logging (log_user, log_timestamp);
-CREATE INDEX &mw_prefix.logging_i03 ON &mw_prefix.logging (log_namespace, log_title, log_timestamp);
-CREATE INDEX &mw_prefix.logging_i04 ON &mw_prefix.logging (log_timestamp);
-CREATE INDEX &mw_prefix.logging_i05 ON &mw_prefix.logging (log_type, log_action, log_timestamp);
-CREATE INDEX &mw_prefix.logging_i06 ON &mw_prefix.logging (log_user_text, log_type, log_timestamp);
-CREATE INDEX &mw_prefix.logging_i07 ON &mw_prefix.logging (log_user_text, log_timestamp);
-CREATE INDEX &mw_prefix.actor_time ON &mw_prefix.logging (log_actor, log_timestamp);
-CREATE INDEX &mw_prefix.log_actor_type_time ON &mw_prefix.logging (log_actor, log_type, log_timestamp);
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.logging_seq_trg BEFORE INSERT ON &mw_prefix.logging
- FOR EACH ROW WHEN (new.log_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(logging_log_id_seq.nextval, :new.log_id);
-END;
-/*$mw$*/
-
-CREATE TABLE &mw_prefix.log_search (
- ls_field VARCHAR2(32) NOT NULL,
- ls_value VARCHAR2(255) NOT NULL,
- ls_log_id NuMBER DEFAULT 0 NOT NULL
-);
-ALTER TABLE &mw_prefix.log_search ADD CONSTRAINT log_search_pk PRIMARY KEY (ls_field,ls_value,ls_log_id);
-CREATE INDEX &mw_prefix.log_search_i01 ON &mw_prefix.log_search (ls_log_id);
-
-
-CREATE SEQUENCE job_job_id_seq;
-CREATE TABLE &mw_prefix.job (
- job_id NUMBER NOT NULL,
- job_cmd VARCHAR2(60) NOT NULL,
- job_namespace NUMBER DEFAULT 0 NOT NULL,
- job_title VARCHAR2(255) NOT NULL,
- job_timestamp TIMESTAMP(6) WITH TIME ZONE NULL,
- job_params CLOB NOT NULL,
- job_random NUMBER DEFAULT 0 NOT NULL,
- job_token VARCHAR2(32),
- job_token_timestamp TIMESTAMP(6) WITH TIME ZONE,
- job_sha1 VARCHAR2(32),
- job_attempts NUMBER DEFAULT 0 NOT NULL
-);
-ALTER TABLE &mw_prefix.job ADD CONSTRAINT &mw_prefix.job_pk PRIMARY KEY (job_id);
-CREATE INDEX &mw_prefix.job_i01 ON &mw_prefix.job (job_cmd, job_namespace, job_title);
-CREATE INDEX &mw_prefix.job_i02 ON &mw_prefix.job (job_timestamp);
-CREATE INDEX &mw_prefix.job_i03 ON &mw_prefix.job (job_sha1);
-CREATE INDEX &mw_prefix.job_i04 ON &mw_prefix.job (job_cmd,job_token,job_random);
-CREATE INDEX &mw_prefix.job_i05 ON &mw_prefix.job (job_attempts);
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.job_seq_trg BEFORE INSERT ON &mw_prefix.job
- FOR EACH ROW WHEN (new.job_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(job_job_id_seq.nextval, :new.job_id);
-END;
-/*$mw$*/
-
-CREATE TABLE &mw_prefix.querycache_info (
- qci_type VARCHAR2(32) NOT NULL,
- qci_timestamp TIMESTAMP(6) WITH TIME ZONE NULL
-);
-CREATE UNIQUE INDEX &mw_prefix.querycache_info_u01 ON &mw_prefix.querycache_info (qci_type);
-
-CREATE TABLE &mw_prefix.redirect (
- rd_from NUMBER NOT NULL,
- rd_namespace NUMBER DEFAULT 0 NOT NULL,
- rd_title VARCHAR2(255) NOT NULL,
- rd_interwiki VARCHAR2(32),
- rd_fragment VARCHAR2(255)
-);
-ALTER TABLE &mw_prefix.redirect ADD CONSTRAINT &mw_prefix.redirect_fk1 FOREIGN KEY (rd_from) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE INDEX &mw_prefix.redirect_i01 ON &mw_prefix.redirect (rd_namespace,rd_title,rd_from);
-
-CREATE TABLE &mw_prefix.querycachetwo (
- qcc_type VARCHAR2(32) NOT NULL,
- qcc_value NUMBER DEFAULT 0 NOT NULL,
- qcc_namespace NUMBER DEFAULT 0 NOT NULL,
- qcc_title VARCHAR2(255),
- qcc_namespacetwo NUMBER DEFAULT 0 NOT NULL,
- qcc_titletwo VARCHAR2(255)
-);
-CREATE INDEX &mw_prefix.querycachetwo_i01 ON &mw_prefix.querycachetwo (qcc_type,qcc_value);
-CREATE INDEX &mw_prefix.querycachetwo_i02 ON &mw_prefix.querycachetwo (qcc_type,qcc_namespace,qcc_title);
-CREATE INDEX &mw_prefix.querycachetwo_i03 ON &mw_prefix.querycachetwo (qcc_type,qcc_namespacetwo,qcc_titletwo);
-
-CREATE SEQUENCE page_restrictions_pr_id_seq;
-CREATE TABLE &mw_prefix.page_restrictions (
- pr_id NUMBER NOT NULL,
- pr_page NUMBER NOT NULL,
- pr_type VARCHAR2(255) NOT NULL,
- pr_level VARCHAR2(255) NOT NULL,
- pr_cascade NUMBER NOT NULL,
- pr_user NUMBER NULL,
- pr_expiry TIMESTAMP(6) WITH TIME ZONE NULL
-);
-ALTER TABLE &mw_prefix.page_restrictions ADD CONSTRAINT &mw_prefix.page_restrictions_pk PRIMARY KEY (pr_id);
-ALTER TABLE &mw_prefix.page_restrictions ADD CONSTRAINT &mw_prefix.page_restrictions_fk1 FOREIGN KEY (pr_page) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE UNIQUE INDEX &mw_prefix.page_restrictions_u01 ON &mw_prefix.page_restrictions (pr_page,pr_type);
-CREATE INDEX &mw_prefix.page_restrictions_i01 ON &mw_prefix.page_restrictions (pr_type,pr_level);
-CREATE INDEX &mw_prefix.page_restrictions_i02 ON &mw_prefix.page_restrictions (pr_level);
-CREATE INDEX &mw_prefix.page_restrictions_i03 ON &mw_prefix.page_restrictions (pr_cascade);
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.page_restrictions_seq_trg BEFORE INSERT ON &mw_prefix.page_restrictions
- FOR EACH ROW WHEN (new.pr_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(page_restrictions_pr_id_seq.nextval, :new.pr_id);
-END;
-/*$mw$*/
-
-CREATE TABLE &mw_prefix.protected_titles (
- pt_namespace NUMBER DEFAULT 0 NOT NULL,
- pt_title VARCHAR2(255) NOT NULL,
- pt_user NUMBER NOT NULL,
- pt_reason_id NUMBER NOT NULL,
- pt_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL,
- pt_expiry VARCHAR2(14) NOT NULL,
- pt_create_perm VARCHAR2(60) NOT NULL
-);
-ALTER TABLE &mw_prefix.protected_titles ADD CONSTRAINT &mw_prefix.protected_titles_fk1 FOREIGN KEY (pt_reason_id) REFERENCES &mw_prefix."COMMENT"(comment_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE UNIQUE INDEX &mw_prefix.protected_titles_u01 ON &mw_prefix.protected_titles (pt_namespace,pt_title);
-CREATE INDEX &mw_prefix.protected_titles_i01 ON &mw_prefix.protected_titles (pt_timestamp);
-
-CREATE TABLE &mw_prefix.page_props (
- pp_page NUMBER NOT NULL,
- pp_propname VARCHAR2(60) NOT NULL,
- pp_value BLOB NOT NULL
-);
-CREATE UNIQUE INDEX &mw_prefix.page_props_u01 ON &mw_prefix.page_props (pp_page,pp_propname);
-
-
-CREATE TABLE &mw_prefix.updatelog (
- ul_key VARCHAR2(255) NOT NULL,
- ul_value BLOB
-);
-ALTER TABLE &mw_prefix.updatelog ADD CONSTRAINT &mw_prefix.updatelog_pk PRIMARY KEY (ul_key);
-
-CREATE TABLE &mw_prefix.change_tag (
- ct_id NUMBER NOT NULL,
- ct_rc_id NUMBER NULL,
- ct_log_id NUMBER NULL,
- ct_rev_id NUMBER NULL,
- ct_params BLOB NULL,
- ct_tag_id NUMBER NOT NULL
-);
-ALTER TABLE &mw_prefix.change_tag ADD CONSTRAINT &mw_prefix.change_tag_pk PRIMARY KEY (ct_id);
-
-CREATE UNIQUE INDEX &mw_prefix.change_tag_u04 ON &mw_prefix.change_tag (ct_rc_id,ct_tag_id);
-CREATE UNIQUE INDEX &mw_prefix.change_tag_u05 ON &mw_prefix.change_tag (ct_log_id,ct_tag_id);
-CREATE UNIQUE INDEX &mw_prefix.change_tag_u06 ON &mw_prefix.change_tag (ct_rev_id,ct_tag_id);
-
-CREATE INDEX &mw_prefix.change_tag_i02 ON &mw_prefix.change_tag (ct_tag_id,ct_rc_id,ct_rev_id,ct_log_id);
-
--- This table is not used unless profiling is turned on
---CREATE TABLE &mw_prefix.profiling (
--- pf_count NUMBER DEFAULT 0 NOT NULL,
--- pf_time NUMBER(18,10) DEFAULT 0 NOT NULL,
--- pf_memory NUMBER(18,10) DEFAULT 0 NOT NULL,
--- pf_name VARCHAR2(255),
--- pf_server VARCHAR2(30)
---);
---CREATE UNIQUE INDEX &mw_prefix.profiling_u01 ON &mw_prefix.profiling (pf_name, pf_server);
-
-CREATE INDEX &mw_prefix.si_title_idx ON &mw_prefix.searchindex(si_title) INDEXTYPE IS ctxsys.context;
-CREATE INDEX &mw_prefix.si_text_idx ON &mw_prefix.searchindex(si_text) INDEXTYPE IS ctxsys.context;
-
-CREATE TABLE &mw_prefix.l10n_cache (
- lc_lang varchar2(32) NOT NULL,
- lc_key varchar2(255) NOT NULL,
- lc_value clob NOT NULL
-);
-CREATE INDEX &mw_prefix.l10n_cache_u01 ON &mw_prefix.l10n_cache (lc_lang, lc_key);
-
-CREATE TABLE &mw_prefix.module_deps (
- md_module VARCHAR2(255) NOT NULL,
- md_skin VARCHAR2(32) NOT NULL,
- md_deps BLOB NOT NULL
-);
-CREATE UNIQUE INDEX &mw_prefix.module_deps_u01 ON &mw_prefix.module_deps (md_module, md_skin);
-
-CREATE SEQUENCE sites_site_id_seq MINVALUE 0 START WITH 0;
-CREATE TABLE &mw_prefix.sites (
- site_id NUMBER NOT NULL,
- site_global_key VARCHAR2(32) NOT NULL,
- site_type VARCHAR2(32) NOT NULL,
- site_group VARCHAR2(32) NOT NULL,
- site_source VARCHAR2(32) NOT NULL,
- site_language VARCHAR2(32) NOT NULL,
- site_protocol VARCHAR2(32) NOT NULL,
- site_domain VARCHAR2(255) NOT NULL,
- site_data BLOB NOT NULL,
- site_forward NUMBER(1) NOT NULL,
- site_config BLOB NOT NULL
-);
-ALTER TABLE &mw_prefix.sites ADD CONSTRAINT &mw_prefix.sites_pk PRIMARY KEY (site_id);
-CREATE UNIQUE INDEX &mw_prefix.sites_u01 ON &mw_prefix.sites (site_global_key);
-CREATE INDEX &mw_prefix.sites_i01 ON &mw_prefix.sites (site_type);
-CREATE INDEX &mw_prefix.sites_i02 ON &mw_prefix.sites (site_group);
-CREATE INDEX &mw_prefix.sites_i03 ON &mw_prefix.sites (site_source);
-CREATE INDEX &mw_prefix.sites_i04 ON &mw_prefix.sites (site_language);
-CREATE INDEX &mw_prefix.sites_i05 ON &mw_prefix.sites (site_protocol);
-CREATE INDEX &mw_prefix.sites_i06 ON &mw_prefix.sites (site_domain);
-CREATE INDEX &mw_prefix.sites_i07 ON &mw_prefix.sites (site_forward);
-/*$mw$*/
-CREATE TRIGGER &mw_prefix.sites_seq_trg BEFORE INSERT ON &mw_prefix.sites
- FOR EACH ROW WHEN (new.site_id IS NULL)
-BEGIN
- &mw_prefix.lastval_pkg.setLastval(sites_site_id_seq.nextval, :new.site_id);
-END;
-/*$mw$*/
-
-CREATE TABLE &mw_prefix.site_identifiers (
- si_site NUMBER NOT NULL,
- si_type VARCHAR2(32) NOT NULL,
- si_key VARCHAR2(32) NOT NULL
-);
-CREATE UNIQUE INDEX &mw_prefix.site_identifiers_u01 ON &mw_prefix.site_identifiers (si_type, si_key);
-CREATE INDEX &mw_prefix.site_identifiers_i01 ON &mw_prefix.site_identifiers (si_site);
-CREATE INDEX &mw_prefix.site_identifiers_i02 ON &mw_prefix.site_identifiers (si_key);
-
--- do not prefix this table as it breaks parserTests
-CREATE TABLE wiki_field_info_full (
-table_name VARCHAR2(35) NOT NULL,
-column_name VARCHAR2(35) NOT NULL,
-data_default VARCHAR2(4000),
-data_length NUMBER NOT NULL,
-data_type VARCHAR2(106),
-not_null CHAR(1) NOT NULL,
-prim NUMBER(1),
-uniq NUMBER(1),
-nonuniq NUMBER(1)
-);
-ALTER TABLE wiki_field_info_full ADD CONSTRAINT wiki_field_info_full_pk PRIMARY KEY (table_name, column_name);
-
-/*$mw$*/
-CREATE PROCEDURE fill_wiki_info IS
- BEGIN
- DELETE wiki_field_info_full;
-
- FOR x_rec IN (SELECT t.table_name table_name, t.column_name,
- t.data_default, t.data_length, t.data_type,
- DECODE (t.nullable, 'Y', '1', 'N', '0') not_null,
- (SELECT 1
- FROM user_cons_columns ucc,
- user_constraints uc
- WHERE ucc.table_name = t.table_name
- AND ucc.column_name = t.column_name
- AND uc.constraint_name = ucc.constraint_name
- AND uc.constraint_type = 'P'
- AND ROWNUM < 2) prim,
- (SELECT 1
- FROM user_ind_columns uic,
- user_indexes ui
- WHERE uic.table_name = t.table_name
- AND uic.column_name = t.column_name
- AND ui.index_name = uic.index_name
- AND ui.uniqueness = 'UNIQUE'
- AND ROWNUM < 2) uniq,
- (SELECT 1
- FROM user_ind_columns uic,
- user_indexes ui
- WHERE uic.table_name = t.table_name
- AND uic.column_name = t.column_name
- AND ui.index_name = uic.index_name
- AND ui.uniqueness = 'NONUNIQUE'
- AND ROWNUM < 2) nonuniq
- FROM user_tab_columns t, user_tables ut
- WHERE ut.table_name = t.table_name)
- LOOP
- INSERT INTO wiki_field_info_full
- (table_name, column_name,
- data_default, data_length,
- data_type, not_null, prim,
- uniq, nonuniq
- )
- VALUES (x_rec.table_name, x_rec.column_name,
- x_rec.data_default, x_rec.data_length,
- x_rec.data_type, x_rec.not_null, x_rec.prim,
- x_rec.uniq, x_rec.nonuniq
- );
- END LOOP;
- COMMIT;
-END;
-/*$mw$*/
-
-/*$mw$*/
-CREATE OR REPLACE PROCEDURE duplicate_table(p_tabname IN VARCHAR2,
- p_oldprefix IN VARCHAR2,
- p_newprefix IN VARCHAR2,
- p_temporary IN BOOLEAN) IS
- e_table_not_exist EXCEPTION;
- PRAGMA EXCEPTION_INIT(e_table_not_exist, -00942);
- l_temp_ei_sql VARCHAR2(2000);
- l_temporary BOOLEAN := p_temporary;
-BEGIN
- BEGIN
- EXECUTE IMMEDIATE 'DROP TABLE ' || p_newprefix || p_tabname ||
- ' CASCADE CONSTRAINTS PURGE';
- EXCEPTION
- WHEN e_table_not_exist THEN
- NULL;
- END;
- IF (p_tabname = 'SEARCHINDEX') THEN
- l_temporary := FALSE;
- END IF;
- IF (l_temporary) THEN
- EXECUTE IMMEDIATE 'CREATE GLOBAL TEMPORARY TABLE ' || p_newprefix ||
- p_tabname ||
- ' ON COMMIT PRESERVE ROWS AS SELECT * FROM ' ||
- p_oldprefix || p_tabname || ' WHERE ROWNUM = 0';
- ELSE
- EXECUTE IMMEDIATE 'CREATE TABLE ' || p_newprefix || p_tabname ||
- ' AS SELECT * FROM ' || p_oldprefix || p_tabname ||
- ' WHERE ROWNUM = 0';
- END IF;
- FOR rc IN (SELECT column_name, data_default
- FROM user_tab_columns
- WHERE table_name = p_oldprefix || p_tabname
- AND data_default IS NOT NULL) LOOP
- EXECUTE IMMEDIATE 'ALTER TABLE ' || p_newprefix || p_tabname ||
- ' MODIFY ' || rc.column_name || ' DEFAULT ' ||
- SUBSTR(rc.data_default, 1, 2000);
- END LOOP;
- FOR rc IN (SELECT REPLACE(REPLACE(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl('CONSTRAINT',
- constraint_name),
- 32767,
- 1),
- USER || '"."' || p_oldprefix,
- USER || '"."' || p_newprefix),
- '"' || constraint_name || '"',
- '"' || p_newprefix || constraint_name || '"') DDLVC2,
- constraint_name
- FROM user_constraints uc
- WHERE table_name = p_oldprefix || p_tabname
- AND constraint_type = 'P') LOOP
- l_temp_ei_sql := SUBSTR(rc.ddlvc2, 1, INSTR(rc.ddlvc2, 'PCTFREE') - 1);
- l_temp_ei_sql := SUBSTR(l_temp_ei_sql,
- 1,
- INSTR(l_temp_ei_sql,
- ')',
- INSTR(l_temp_ei_sql, 'PRIMARY KEY') + 1) + 1);
- IF nvl(length(l_temp_ei_sql), 0) > 0 THEN
- EXECUTE IMMEDIATE l_temp_ei_sql;
- END IF;
- END LOOP;
- IF (NOT l_temporary) THEN
- FOR rc IN (SELECT REPLACE(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl('REF_CONSTRAINT',
- constraint_name),
- 32767,
- 1),
- USER || '"."' || p_oldprefix,
- USER || '"."' || p_newprefix) DDLVC2,
- constraint_name
- FROM user_constraints uc
- WHERE table_name = p_oldprefix || p_tabname
- AND constraint_type = 'R') LOOP
- IF nvl(length(l_temp_ei_sql), 0) > 0 AND
- INSTR(l_temp_ei_sql, 'PRIMARY KEY') = 0 THEN
- EXECUTE IMMEDIATE l_temp_ei_sql;
- END IF;
- END LOOP;
- END IF;
- FOR rc IN (SELECT REPLACE(REPLACE(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl('INDEX',
- index_name),
- 32767,
- 1),
- USER || '"."' || p_oldprefix,
- USER || '"."' || p_newprefix),
- '"' || index_name || '"',
- '"' || p_newprefix || index_name || '"') DDLVC2,
- index_name,
- index_type
- FROM user_indexes ui
- WHERE table_name = p_oldprefix || p_tabname
- AND index_type NOT IN ('LOB', 'DOMAIN')
- AND NOT EXISTS
- (SELECT NULL
- FROM user_constraints
- WHERE table_name = ui.table_name
- AND constraint_name = ui.index_name)) LOOP
- l_temp_ei_sql := SUBSTR(rc.ddlvc2, 1, INSTR(rc.ddlvc2, 'PCTFREE') - 1);
- l_temp_ei_sql := SUBSTR(l_temp_ei_sql,
- 1,
- INSTR(l_temp_ei_sql,
- ')',
- INSTR(l_temp_ei_sql,
- '"' || USER || '"."' || p_newprefix || '"') + 1) + 1);
- IF nvl(length(l_temp_ei_sql), 0) > 0 THEN
- EXECUTE IMMEDIATE l_temp_ei_sql;
- END IF;
- END LOOP;
- FOR rc IN (SELECT REPLACE(REPLACE(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl('INDEX',
- index_name),
- 32767,
- 1),
- USER || '"."' || p_oldprefix,
- USER || '"."' || p_newprefix),
- '"' || index_name || '"',
- '"' || p_newprefix || index_name || '"') DDLVC2,
- index_name,
- index_type
- FROM user_indexes ui
- WHERE table_name = p_oldprefix || p_tabname
- AND index_type = 'DOMAIN'
- AND NOT EXISTS
- (SELECT NULL
- FROM user_constraints
- WHERE table_name = ui.table_name
- AND constraint_name = ui.index_name)) LOOP
- l_temp_ei_sql := rc.ddlvc2;
- IF nvl(length(l_temp_ei_sql), 0) > 0 THEN
- EXECUTE IMMEDIATE l_temp_ei_sql;
- END IF;
- END LOOP;
- FOR rc IN (SELECT REPLACE(REPLACE(UPPER(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl('TRIGGER',
- trigger_name),
- 32767,
- 1)),
- USER || '"."' || p_oldprefix,
- USER || '"."' || p_newprefix),
- ' ON ' || p_oldprefix || p_tabname,
- ' ON ' || p_newprefix || p_tabname) DDLVC2,
- trigger_name
- FROM user_triggers
- WHERE table_name = p_oldprefix || p_tabname) LOOP
- l_temp_ei_sql := SUBSTR(rc.ddlvc2, 1, INSTR(rc.ddlvc2, 'ALTER ') - 1);
- IF nvl(length(l_temp_ei_sql), 0) > 0 THEN
- EXECUTE IMMEDIATE l_temp_ei_sql;
- END IF;
- END LOOP;
-END;
-
-/*$mw$*/
-
-/*$mw$*/
-CREATE OR REPLACE FUNCTION BITOR (x IN NUMBER, y IN NUMBER) RETURN NUMBER AS
-BEGIN
- RETURN (x + y - BITAND(x, y));
-END;
-/*$mw$*/
-
-/*$mw$*/
-CREATE OR REPLACE FUNCTION BITNOT (x IN NUMBER) RETURN NUMBER AS
-BEGIN
- RETURN (4294967295 - x);
-END;
-/*$mw$*/
-
-CREATE OR REPLACE TYPE GET_OUTPUT_TYPE IS TABLE OF VARCHAR2(255);
-
-/*$mw$*/
-CREATE OR REPLACE FUNCTION GET_OUTPUT_LINES RETURN GET_OUTPUT_TYPE PIPELINED AS
- v_line VARCHAR2(255);
- v_status INTEGER := 0;
-BEGIN
-
- LOOP
- DBMS_OUTPUT.GET_LINE(v_line, v_status);
- IF (v_status = 0) THEN RETURN; END IF;
- PIPE ROW (v_line);
- END LOOP;
- RETURN;
-EXCEPTION
- WHEN OTHERS THEN
- RETURN;
-END;
-/*$mw$*/
-
-/*$mw$*/
-CREATE OR REPLACE FUNCTION GET_SEQUENCE_VALUE(seq IN VARCHAR2) RETURN NUMBER AS
- v_value NUMBER;
-BEGIN
- EXECUTE IMMEDIATE 'SELECT '||seq||'.NEXTVAL INTO :outVar FROM DUAL' INTO v_value;
- RETURN v_value;
-END;
-/*$mw$*/
+++ /dev/null
--- SQL to insert update keys into the initial tables after a
--- fresh installation of MediaWiki's database.
--- This is read and executed by the install script; you should
--- not have to run it by itself unless doing a manual install.
--- Insert keys here if either the unnecessary would cause heavy
--- processing or could potentially cause trouble by lowering field
--- sizes, adding constraints, etc.
--- When adjusting field sizes, it is recommended removing old
--- patches but to play safe, update keys should also inserted here.
-
--- The /*_*/ comments in this and other files are
--- replaced with the defined table prefix by the installer
--- and updater scripts. If you are installing or running
--- updates manually, you will need to manually insert the
--- table prefix if any when running these scripts.
---
-
-INSERT INTO /*_*/updatelog (ul_key, ul_value)
- VALUES( 'filearchive-fa_major_mime-patch-fa_major_mime-chemical.sql', null );
-INSERT INTO /*_*/updatelog (ul_key, ul_value)
- VALUES( 'image-img_major_mime-patch-img_major_mime-chemical.sql', null );
-INSERT INTO /*_*/updatelog (ul_key, ul_value)
- VALUES( 'oldimage-oi_major_mime-patch-oi_major_mime-chemical.sql', null );
-INSERT INTO /*_*/updatelog (ul_key, ul_value)
- VALUES( 'user_groups-ug_group-patch-ug_group-length-increase-255.sql', null );
-INSERT INTO /*_*/updatelog (ul_key, ul_value)
- VALUES( 'user_former_groups-ufg_group-patch-ufg_group-length-increase-255.sql', null );
-INSERT INTO /*_*/updatelog (ul_key, ul_value)
- VALUES( 'user_properties-up_property-patch-up_property.sql', null );
+++ /dev/null
--- defines must comply with ^define\s*([^\s=]*)\s*=\s?'\{\$([^\}]*)\}';
-define wiki_user='{$wgDBuser}';
-define wiki_pass='{$wgDBpassword}';
-define def_ts='{$_OracleDefTS}';
-define temp_ts='{$_OracleTempTS}';
-
-create user &wiki_user. identified by &wiki_pass. default tablespace &def_ts. temporary tablespace &temp_ts. quota unlimited on &def_ts.;
-grant connect, resource to &wiki_user.;
-grant alter session to &wiki_user.;
-grant ctxapp to &wiki_user.;
-grant execute on ctx_ddl to &wiki_user.;
-grant create view to &wiki_user.;
-grant create synonym to &wiki_user.;
-grant create table to &wiki_user.;
-grant create sequence to &wiki_user.;
-grant create trigger to &wiki_user.;
-grant create type to &wiki_user.;
-grant create procedure to &wiki_user.;
* @covers \Wikimedia\Rdbms\LoadBalancer::getConnection
* @covers \Wikimedia\Rdbms\DatabaseMysqlBase::doSelectDomain
* @covers \Wikimedia\Rdbms\DatabaseMysqlBase::selectDB
- * @covers \Wikimedia\Rdbms\DatabaseMssql::selectDB
- * @covers DatabaseOracle::selectDB
*/
public function testNiceDomains() {
global $wgDBname;
* @covers \Wikimedia\Rdbms\LoadBalancer::getConnection
* @covers \Wikimedia\Rdbms\DatabaseMysqlBase::doSelectDomain
* @covers \Wikimedia\Rdbms\DatabaseMysqlBase::selectDB
- * @covers \Wikimedia\Rdbms\DatabaseMssql::selectDB
- * @covers DatabaseOracle::selectDB
*/
public function testTrickyDomain() {
global $wgDBname;
* @covers \Wikimedia\Rdbms\LoadBalancer::getConnection
* @covers \Wikimedia\Rdbms\DatabaseMysqlBase::doSelectDomain
* @covers \Wikimedia\Rdbms\DatabaseMysqlBase::selectDB
- * @covers \Wikimedia\Rdbms\DatabaseMssql::selectDB
- * @covers DatabaseOracle::selectDB
*/
public function testInvalidSelectDB() {
if ( wfGetDB( DB_MASTER )->databasesAreIndependent() ) {
* @covers \Wikimedia\Rdbms\LoadBalancer::getConnection
* @covers \Wikimedia\Rdbms\LoadBalancer::redefineLocalDomain
* @covers \Wikimedia\Rdbms\DatabaseMysqlBase::selectDB
- * @covers \Wikimedia\Rdbms\DatabaseMssql::selectDB
- * @covers DatabaseOracle::selectDB
*/
public function testRedefineLocalDomain() {
global $wgDBname;
+++ /dev/null
-<?php
-
-use Wikimedia\Rdbms\Database;
-use Wikimedia\Rdbms\DatabaseMssql;
-
-class DatabaseMssqlTest extends PHPUnit\Framework\TestCase {
-
- use MediaWikiCoversValidator;
- use PHPUnit4And6Compat;
-
- /**
- * @return PHPUnit_Framework_MockObject_MockObject|DatabaseMssql
- */
- private function getMockDb() {
- return $this->getMockBuilder( DatabaseMssql::class )
- ->disableOriginalConstructor()
- ->setMethods( null )
- ->getMock();
- }
-
- public function provideBuildSubstring() {
- yield [ 'someField', 1, 2, 'SUBSTRING(someField,1,2)' ];
- yield [ 'someField', 1, null, 'SUBSTRING(someField,1,2147483647)' ];
- yield [ 'someField', 1, 3333333333, 'SUBSTRING(someField,1,3333333333)' ];
- }
-
- /**
- * @covers Wikimedia\Rdbms\DatabaseMssql::buildSubstring
- * @dataProvider provideBuildSubstring
- */
- public function testBuildSubstring( $input, $start, $length, $expected ) {
- $mockDb = $this->getMockDb();
- $output = $mockDb->buildSubstring( $input, $start, $length );
- $this->assertSame( $expected, $output );
- }
-
- public function provideBuildSubstring_invalidParams() {
- yield [ -1, 1 ];
- yield [ 1, -1 ];
- yield [ 1, 'foo' ];
- yield [ 'foo', 1 ];
- yield [ null, 1 ];
- yield [ 0, 1 ];
- }
-
- /**
- * @covers Wikimedia\Rdbms\DatabaseMssql::buildSubstring
- * @dataProvider provideBuildSubstring_invalidParams
- */
- public function testBuildSubstring_invalidParams( $start, $length ) {
- $mockDb = $this->getMockDb();
- $this->setExpectedException( InvalidArgumentException::class );
- $mockDb->buildSubstring( 'foo', $start, $length );
- }
-
- /**
- * @covers \Wikimedia\Rdbms\DatabaseMssql::getAttributes
- */
- public function testAttributes() {
- $this->assertTrue( DatabaseMssql::getAttributes()[Database::ATTR_SCHEMAS_AS_TABLE_GROUPS] );
- }
-}
use Wikimedia\TestingAccessWrapper;
use Wikimedia\Rdbms\DatabaseSqlite;
use Wikimedia\Rdbms\DatabasePostgres;
-use Wikimedia\Rdbms\DatabaseMssql;
use Wikimedia\Rdbms\DBUnexpectedError;
class DatabaseTest extends PHPUnit\Framework\TestCase {
$this->assertInstanceOf( DatabasePostgres::class, Database::factory( 'Postgres', $p, $m ) );
$x = $p + [ 'port' => 10000, 'UseWindowsAuth' => false ];
- $this->assertInstanceOf( DatabaseMssql::class, Database::factory( 'mssql', $x, $m ) );
$x = $p + [ 'dbFilePath' => 'some/file.sqlite' ];
$this->assertInstanceOf( DatabaseSqlite::class, Database::factory( 'sqlite', $x, $m ) );
+++ /dev/null
-<?php
-
-class DatabaseOracleTest extends MediaWikiUnitTestCase {
-
- /**
- * @return PHPUnit_Framework_MockObject_MockObject|DatabaseOracle
- */
- private function getMockDb() {
- return $this->getMockBuilder( DatabaseOracle::class )
- ->disableOriginalConstructor()
- ->setMethods( null )
- ->getMock();
- }
-
- public function provideBuildSubstring() {
- yield [ 'someField', 1, 2, 'SUBSTR(someField,1,2)' ];
- yield [ 'someField', 1, null, 'SUBSTR(someField,1)' ];
- }
-
- /**
- * @covers DatabaseOracle::buildSubstring
- * @dataProvider provideBuildSubstring
- */
- public function testBuildSubstring( $input, $start, $length, $expected ) {
- $mockDb = $this->getMockDb();
- $output = $mockDb->buildSubstring( $input, $start, $length );
- $this->assertSame( $expected, $output );
- }
-
- public function provideBuildSubstring_invalidParams() {
- yield [ -1, 1 ];
- yield [ 1, -1 ];
- yield [ 1, 'foo' ];
- yield [ 'foo', 1 ];
- yield [ null, 1 ];
- yield [ 0, 1 ];
- }
-
- /**
- * @covers DatabaseOracle::buildSubstring
- * @dataProvider provideBuildSubstring_invalidParams
- */
- public function testBuildSubstring_invalidParams( $start, $length ) {
- $mockDb = $this->getMockDb();
- $this->setExpectedException( InvalidArgumentException::class );
- $mockDb->buildSubstring( 'foo', $start, $length );
- }
-
-}
+++ /dev/null
-<?php
-
-/**
- * @group Installer
- */
-class OracleInstallerTest extends \MediaWikiUnitTestCase {
-
- /**
- * @dataProvider provideOracleConnectStrings
- * @covers OracleInstaller::checkConnectStringFormat
- */
- public function testCheckConnectStringFormat( $expected, $connectString, $msg = '' ) {
- $validity = $expected ? 'should be valid' : 'should NOT be valid';
- $msg = "'$connectString' ($msg) $validity.";
- $this->assertEquals( $expected,
- OracleInstaller::checkConnectStringFormat( $connectString ),
- $msg
- );
- }
-
- /**
- * Provider to test OracleInstaller::checkConnectStringFormat()
- */
- function provideOracleConnectStrings() {
- // expected result, connectString[, message]
- return [
- [ true, 'simple_01', 'Simple TNS name' ],
- [ true, 'simple_01.world', 'TNS name with domain' ],
- [ true, 'simple_01.domain.net', 'TNS name with domain' ],
- [ true, 'host123', 'Host only' ],
- [ true, 'host123.domain.net', 'FQDN only' ],
- [ true, '//host123.domain.net', 'FQDN URL only' ],
- [ true, '123.223.213.132', 'Host IP only' ],
- [ true, 'host:1521', 'Host and port' ],
- [ true, 'host:1521/service', 'Host, port and service' ],
- [ true, 'host:1521/service:shared', 'Host, port, service and shared server type' ],
- [ true, 'host:1521/service:dedicated', 'Host, port, service and dedicated server type' ],
- [ true, 'host:1521/service:pooled', 'Host, port, service and pooled server type' ],
- [
- true,
- 'host:1521/service:shared/instance1',
- 'Host, port, service, server type and instance'
- ],
- [ true, 'host:1521//instance1', 'Host, port and instance' ],
- ];
- }
-
-}