summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--INSTALL2
-rw-r--r--docs/database.txt2
-rw-r--r--includes/db/DatabaseMssql.php1490
-rw-r--r--includes/db/DatabaseOracle.php1546
-rw-r--r--includes/installer/MssqlInstaller.php736
-rw-r--r--includes/installer/MssqlUpdater.php143
-rw-r--r--includes/installer/OracleInstaller.php344
-rw-r--r--includes/installer/OracleUpdater.php289
-rw-r--r--includes/libs/IEContentAnalyzer.php851
-rw-r--r--includes/libs/IEUrlExtension.php271
-rw-r--r--includes/search/SearchMssql.php210
-rw-r--r--includes/search/SearchOracle.php273
-rw-r--r--maintenance/dictionary/mediawiki.dic2
-rw-r--r--maintenance/mssql/archives/named_constraints.sql38
-rw-r--r--maintenance/mssql/archives/patch-fa_major_mime-chemical.sql4
-rw-r--r--maintenance/mssql/archives/patch-img_major_mime-chemical.sql4
-rw-r--r--maintenance/mssql/archives/patch-oi_major_mime-chemical.sql4
-rw-r--r--maintenance/mssql/archives/patch-page_page_lang.sql1
-rw-r--r--maintenance/mssql/archives/patch-user_password_expires.sql1
-rw-r--r--maintenance/mssql/tables.sql1324
-rw-r--r--maintenance/mssql/update-keys.sql31
-rw-r--r--maintenance/oracle/alterSharedConstraints.php95
-rw-r--r--maintenance/oracle/archives/patch-ar_sha1_field.sql3
-rw-r--r--maintenance/oracle/archives/patch-archive-ar_content_format.sql3
-rw-r--r--maintenance/oracle/archives/patch-archive-ar_content_model.sql3
-rw-r--r--maintenance/oracle/archives/patch-archive-ar_id.sql6
-rw-r--r--maintenance/oracle/archives/patch-cat_hidden.sql4
-rw-r--r--maintenance/oracle/archives/patch-externallinks-el_id.sql4
-rw-r--r--maintenance/oracle/archives/patch-fa_sha1.sql5
-rw-r--r--maintenance/oracle/archives/patch-ipblocks_i05_index.sql4
-rw-r--r--maintenance/oracle/archives/patch-job_attempts.sql4
-rw-r--r--maintenance/oracle/archives/patch-job_timestamp_field.sql4
-rw-r--r--maintenance/oracle/archives/patch-job_timestamp_index.sql4
-rw-r--r--maintenance/oracle/archives/patch-job_token.sql12
-rw-r--r--maintenance/oracle/archives/patch-logging_type_action_index.sql4
-rw-r--r--maintenance/oracle/archives/patch-logging_user_text_time_index.sql4
-rw-r--r--maintenance/oracle/archives/patch-logging_user_text_type_time_index.sql4
-rw-r--r--maintenance/oracle/archives/patch-page-page_content_model.sql3
-rw-r--r--maintenance/oracle/archives/patch-page-page_lang.sql3
-rw-r--r--maintenance/oracle/archives/patch-page_links_updated.sql4
-rw-r--r--maintenance/oracle/archives/patch-page_redirect_namespace_len.sql4
-rw-r--r--maintenance/oracle/archives/patch-page_restrictions_pkuk_fix.sql7
-rw-r--r--maintenance/oracle/archives/patch-rc_moved.sql4
-rw-r--r--maintenance/oracle/archives/patch-rc_source.sql3
-rw-r--r--maintenance/oracle/archives/patch-rev_sha1_field.sql4
-rw-r--r--maintenance/oracle/archives/patch-revision-rev_content_format.sql3
-rw-r--r--maintenance/oracle/archives/patch-revision-rev_content_model.sql3
-rw-r--r--maintenance/oracle/archives/patch-revision_i05_index.sql4
-rw-r--r--maintenance/oracle/archives/patch-sites.sql34
-rw-r--r--maintenance/oracle/archives/patch-ss_admins.sql4
-rw-r--r--maintenance/oracle/archives/patch-testrun.sql37
-rw-r--r--maintenance/oracle/archives/patch-ufg_group-length-increase-255.sql9
-rw-r--r--maintenance/oracle/archives/patch-ug_group-length-increase-255.sql9
-rw-r--r--maintenance/oracle/archives/patch-up_property.sql3
-rw-r--r--maintenance/oracle/archives/patch-uploadstash-us_props.sql4
-rw-r--r--maintenance/oracle/archives/patch-uploadstash.sql25
-rw-r--r--maintenance/oracle/archives/patch-us_chunk_inx_field.sql4
-rw-r--r--maintenance/oracle/archives/patch-user_email_index.sql4
-rw-r--r--maintenance/oracle/archives/patch-user_former_groups.sql9
-rw-r--r--maintenance/oracle/archives/patch-user_password_expire.sql3
-rw-r--r--maintenance/oracle/archives/patch_16_17_schema_changes.sql98
-rw-r--r--maintenance/oracle/archives/patch_create_17_functions.sql125
-rw-r--r--maintenance/oracle/archives/patch_fk_rename_deferred.sql40
-rw-r--r--maintenance/oracle/archives/patch_namespace_defaults.sql17
-rw-r--r--maintenance/oracle/archives/patch_rebuild_dupfunc.sql149
-rw-r--r--maintenance/oracle/archives/patch_recentchanges_fk2_cascade.sql5
-rw-r--r--maintenance/oracle/archives/patch_remove_not_null_empty_defs.sql9
-rw-r--r--maintenance/oracle/archives/patch_remove_not_null_empty_defs2.sql3
-rw-r--r--maintenance/oracle/patch_seq_names_pre1.16.sql8
-rw-r--r--maintenance/oracle/tables.sql971
-rw-r--r--maintenance/oracle/update-keys.sql29
-rw-r--r--maintenance/oracle/user.sql16
-rw-r--r--tests/phpunit/includes/installer/OracleInstallerTest.php52
73 files changed, 0 insertions, 9438 deletions
diff --git a/INSTALL b/INSTALL
index 2054a57e..7889f9b3 100644
--- a/INSTALL
+++ b/INSTALL
@@ -11,8 +11,6 @@ Required software:
** MySQL 5.0.3 or higher
** PostgreSQL 8.3 or higher
** SQLite 3.3.7 or higher
-** Oracle 9.0.1 or higher
-** Microsoft SQL Server 2005 (9.00.1399)
MediaWiki is developed and tested mainly on Unix/Linux platforms, but should
work on Windows as well.
diff --git a/docs/database.txt b/docs/database.txt
index ba3045ed..fe287c59 100644
--- a/docs/database.txt
+++ b/docs/database.txt
@@ -176,8 +176,6 @@ MediaWiki does support the following other DBMSs to varying degrees.
* PostgreSQL
* SQLite
-* Oracle
-* MSSQL
More information can be found about each of these databases (known issues,
level of support, extra configuration) in the "databases" subdirectory in
diff --git a/includes/db/DatabaseMssql.php b/includes/db/DatabaseMssql.php
deleted file mode 100644
index 85f1b96d..00000000
--- a/includes/db/DatabaseMssql.php
+++ /dev/null
@@ -1,1490 +0,0 @@
-<?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>
- */
-
-/**
- * @ingroup Database
- */
-class DatabaseMssql extends DatabaseBase {
- protected $mInsertId = null;
- protected $mLastResult = null;
- protected $mAffectedRows = null;
- protected $mSubqueryId = 0;
- protected $mScrollableCursor = true;
- protected $mPrepareStatements = true;
- protected $mBinaryColumnCache = null;
- protected $mBitColumnCache = null;
- protected $mIgnoreDupKeyErrors = false;
-
- protected $mPort;
-
- public function cascadingDeletes() {
- return true;
- }
-
- public function cleanupTriggers() {
- return false;
- }
-
- public function strictIPs() {
- return false;
- }
-
- public function realTimestamps() {
- return false;
- }
-
- public function implicitGroupby() {
- return false;
- }
-
- public function implicitOrderby() {
- return false;
- }
-
- public function functionalIndexes() {
- return true;
- }
-
- public function unionSupportsOrderAndLimit() {
- return false;
- }
-
- /**
- * Usually aborts on failure
- * @param string $server
- * @param string $user
- * @param string $password
- * @param string $dbName
- * @throws DBConnectionError
- * @return bool|DatabaseBase|null
- */
- public function open( $server, $user, $password, $dbName ) {
- # Test for driver support, to avoid suppressed fatal error
- if ( !function_exists( 'sqlsrv_connect' ) ) {
- throw new DBConnectionError(
- $this,
- "Microsoft SQL Server Native (sqlsrv) functions missing.
- You can download the driver from: http://go.microsoft.com/fwlink/?LinkId=123470\n"
- );
- }
-
- global $wgDBport, $wgDBWindowsAuthentication;
-
- # e.g. the class is being loaded
- if ( !strlen( $user ) ) {
- return null;
- }
-
- $this->close();
- $this->mServer = $server;
- $this->mPort = $wgDBport;
- $this->mUser = $user;
- $this->mPassword = $password;
- $this->mDBname = $dbName;
-
- $connectionInfo = array();
-
- if ( $dbName ) {
- $connectionInfo['Database'] = $dbName;
- }
-
- // Decide which auth scenerio to use
- // if we are using Windows auth, don't add credentials to $connectionInfo
- if ( !$wgDBWindowsAuthentication ) {
- $connectionInfo['UID'] = $user;
- $connectionInfo['PWD'] = $password;
- }
-
- MediaWiki\suppressWarnings();
- $this->mConn = sqlsrv_connect( $server, $connectionInfo );
- MediaWiki\restoreWarnings();
-
- if ( $this->mConn === false ) {
- throw new DBConnectionError( $this, $this->lastError() );
- }
-
- $this->mOpened = true;
-
- return $this->mConn;
- }
-
- /**
- * Closes a database connection, if it is open
- * Returns success, true if already closed
- * @return bool
- */
- protected function closeConnection() {
- return sqlsrv_close( $this->mConn );
- }
-
- /**
- * @param bool|MssqlResultWrapper|resource $result
- * @return bool|MssqlResultWrapper
- */
- public function resultObject( $result ) {
- if ( empty( $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|MssqlResult
- * @throws DBUnexpectedError
- */
- protected function doQuery( $sql ) {
- if ( $this->debug() ) {
- wfDebug( "SQL: [$sql]\n" );
- }
- $this->offset = 0;
-
- // several extensions seem to think that all databases support limits
- // via LIMIT N after the WHERE clause well, 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->mScrollableCursor ) {
- $scrollArr = array( 'Scrollable' => SQLSRV_CURSOR_STATIC );
- } else {
- $scrollArr = array();
- }
-
- if ( $this->mPrepareStatements ) {
- // we do prepare + execute so we can get its field metadata for later usage if desired
- $stmt = sqlsrv_prepare( $this->mConn, $sql, array(), $scrollArr );
- $success = sqlsrv_execute( $stmt );
- } else {
- $stmt = sqlsrv_query( $this->mConn, $sql, array(), $scrollArr );
- $success = (bool)$stmt;
- }
-
- if ( $this->mIgnoreDupKeyErrors ) {
- // ignore duplicate key errors, but nothing else
- // this emulates INSERT IGNORE in MySQL
- if ( $success === false ) {
- $errors = sqlsrv_errors( SQLSRV_ERR_ERRORS );
- $success = true;
-
- foreach ( $errors as $err ) {
- if ( $err['SQLSTATE'] == '23000' && $err['code'] == '2601' ) {
- continue; // duplicate key error caused by unique index
- } elseif ( $err['SQLSTATE'] == '23000' && $err['code'] == '2627' ) {
- continue; // duplicate key error caused by primary key
- } elseif ( $err['SQLSTATE'] == '01000' && $err['code'] == '3621' ) {
- continue; // generic "the statement has been terminated" error
- }
-
- $success = false; // getting here means we got an error we weren't expecting
- break;
- }
-
- if ( $success ) {
- $this->mAffectedRows = 0;
- return $stmt;
- }
- }
- }
-
- if ( $success === false ) {
- return false;
- }
- // remember number of rows affected
- $this->mAffectedRows = sqlsrv_rows_affected( $stmt );
-
- return $stmt;
- }
-
- public function freeResult( $res ) {
- if ( $res instanceof ResultWrapper ) {
- $res = $res->result;
- }
-
- sqlsrv_free_stmt( $res );
- }
-
- /**
- * @param MssqlResultWrapper $res
- * @return stdClass
- */
- public function fetchObject( $res ) {
- // $res is expected to be an instance of MssqlResultWrapper here
- return $res->fetchObject();
- }
-
- /**
- * @param MssqlResultWrapper $res
- * @return array
- */
- public function fetchRow( $res ) {
- return $res->fetchRow();
- }
-
- /**
- * @param mixed $res
- * @return int
- */
- public function numRows( $res ) {
- if ( $res instanceof ResultWrapper ) {
- $res = $res->result;
- }
-
- return sqlsrv_num_rows( $res );
- }
-
- /**
- * @param mixed $res
- * @return int
- */
- public function numFields( $res ) {
- if ( $res instanceof ResultWrapper ) {
- $res = $res->result;
- }
-
- return sqlsrv_num_fields( $res );
- }
-
- /**
- * @param mixed $res
- * @param int $n
- * @return int
- */
- public function fieldName( $res, $n ) {
- if ( $res instanceof ResultWrapper ) {
- $res = $res->result;
- }
-
- $metadata = sqlsrv_field_metadata( $res );
- return $metadata[$n]['Name'];
- }
-
- /**
- * This must be called after nextSequenceVal
- * @return int|null
- */
- public function insertId() {
- return $this->mInsertId;
- }
-
- /**
- * @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
- */
- public function lastErrno() {
- $err = sqlsrv_errors( SQLSRV_ERR_ALL );
- if ( $err !== null && isset( $err[0] ) ) {
- return $err[0]['code'];
- } else {
- return 0;
- }
- }
-
- /**
- * @return int
- */
- public function affectedRows() {
- return $this->mAffectedRows;
- }
-
- /**
- * 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.
- * array('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. array( 'page' => array('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 = array(), $join_conds = array()
- ) {
- $sql = $this->selectSQLText( $table, $vars, $conds, $fname, $options, $join_conds );
- if ( isset( $options['EXPLAIN'] ) ) {
- try {
- $this->mScrollableCursor = false;
- $this->mPrepareStatements = 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->mScrollableCursor = true;
- $this->mPrepareStatements = true;
- throw $dqe;
- }
- }
- $this->mScrollableCursor = true;
- $this->mPrepareStatements = 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. array('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. array( 'page' => array('LEFT JOIN','page_latest=rev_id') )
- * @return string The SQL text
- */
- public function selectSQLText( $table, $vars, $conds = '', $fname = __METHOD__,
- $options = array(), $join_conds = array()
- ) {
- 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 = array();
- if ( is_array( $table ) ) {
- foreach ( $table as $t ) {
- $bitColumns += $this->getBitColumns( $this->tableName( $t ) );
- }
- } else {
- $bitColumns = $this->getBitColumns( $this->tableName( $table ) );
- }
-
- foreach ( $bitColumns as $col => $info ) {
- $replace = array(
- "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->mScrollableCursor = false;
- try {
- parent::deleteJoin( $delTable, $joinTable, $delVar, $joinVar, $conds, $fname );
- } catch ( Exception $e ) {
- $this->mScrollableCursor = true;
- throw $e;
- }
- $this->mScrollableCursor = true;
- }
-
- public function delete( $table, $conds, $fname = __METHOD__ ) {
- $this->mScrollableCursor = false;
- try {
- parent::delete( $table, $conds, $fname );
- } catch ( Exception $e ) {
- $this->mScrollableCursor = true;
- throw $e;
- }
- $this->mScrollableCursor = 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 $vars
- * @param string $conds
- * @param string $fname
- * @param array $options
- * @return int
- */
- public function estimateRowCount( $table, $vars = '*', $conds = '',
- $fname = __METHOD__, $options = array()
- ) {
- // http://msdn2.microsoft.com/en-us/library/aa259203.aspx
- $options['EXPLAIN'] = true;
- $options['FOR COUNT'] = true;
- $res = $this->select( $table, $vars, $conds, $fname, $options );
-
- $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 existance of indexes.
- $sql = "sp_helpindex '" . $table . "'";
- $res = $this->query( $sql, $fname );
- if ( !$res ) {
- return null;
- }
-
- $result = array();
- 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 empty( $result ) ? false : $result;
- }
-
- /**
- * 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 = array() ) {
- # No rows to insert, easy just return now
- if ( !count( $arrToInsert ) ) {
- return true;
- }
-
- if ( !is_array( $options ) ) {
- $options = array( $options );
- }
-
- $table = $this->tableName( $table );
-
- if ( !( isset( $arrToInsert[0] ) && is_array( $arrToInsert[0] ) ) ) { // Not multi row
- $arrToInsert = array( 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, array( 'IGNORE' ) );
- $this->mIgnoreDupKeyErrors = true;
- }
-
- 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';
- } elseif ( is_array( $value ) || is_object( $value ) ) {
- if ( is_object( $value ) && $value instanceof Blob ) {
- $sql .= $this->addQuotes( $value );
- } else {
- $sql .= $this->addQuotes( serialize( $value ) );
- }
- } else {
- $sql .= $this->addQuotes( $value );
- }
- }
- $sql .= ')' . $sqlPost;
-
- // Run the query
- $this->mScrollableCursor = false;
- try {
- $ret = $this->query( $sql );
- } catch ( Exception $e ) {
- $this->mScrollableCursor = true;
- $this->mIgnoreDupKeyErrors = false;
- throw $e;
- }
- $this->mScrollableCursor = true;
-
- if ( !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->mInsertId = $row->$identity;
- }
- }
- }
- $this->mIgnoreDupKeyErrors = false;
- return $ret;
- }
-
- /**
- * INSERT SELECT wrapper
- * $varMap must be an associative array of the form array( 'dest1' => 'source1', ...)
- * Source items may be literals rather than field names, but strings should
- * be quoted with Database::addQuotes().
- * @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
- * @return null|ResultWrapper
- * @throws Exception
- */
- public function insertSelect( $destTable, $srcTable, $varMap, $conds, $fname = __METHOD__,
- $insertOptions = array(), $selectOptions = array()
- ) {
- $this->mScrollableCursor = false;
- try {
- $ret = parent::insertSelect(
- $destTable,
- $srcTable,
- $varMap,
- $conds,
- $fname,
- $insertOptions,
- $selectOptions
- );
- } catch ( Exception $e ) {
- $this->mScrollableCursor = true;
- throw $e;
- }
- $this->mScrollableCursor = true;
-
- return $ret;
- }
-
- /**
- * UPDATE wrapper. Takes a condition array and a SET array.
- *
- * @param string $table Name of the table to UPDATE. This will be passed through
- * DatabaseBase::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
- * DatabaseBase::addQuotes().
- *
- * @param array $conds An array of conditions (WHERE). See
- * DatabaseBase::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
- * - LOW_PRIORITY: MySQL-specific, see MySQL manual.
- * @return bool
- * @throws DBUnexpectedError
- * @throws Exception
- * @throws MWException
- */
- function update( $table, $values, $conds, $fname = __METHOD__, $options = array() ) {
- $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 !== array() && $conds !== '*' ) {
- $sql .= " WHERE " . $this->makeList( $conds, LIST_AND, $binaryColumns );
- }
-
- $this->mScrollableCursor = false;
- try {
- $ret = $this->query( $sql );
- } catch ( Exception $e ) {
- $this->mScrollableCursor = true;
- throw $e;
- }
- $this->mScrollableCursor = 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 DatabaseBase::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 MWException|DBUnexpectedError
- * @return string
- */
- public function makeList( $a, $mode = LIST_COMMA, $binaryColumns = array() ) {
- if ( !is_array( $a ) ) {
- throw new DBUnexpectedError( $this,
- 'DatabaseBase::makeList 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 = array();
- $s1 = preg_match( '#SELECT\s+(.+?)\s+FROM#Dis', $sql, $select );
- $s2 = preg_match( '#(ORDER BY\s+.+?)(\s*FOR XML .*)?$#Dis', $sql, $orderby );
- $overOrder = $postOrder = '';
- $first = $offset + 1;
- $last = $offset + $limit;
- $sub1 = 'sub_' . $this->mSubqueryId;
- $sub2 = 'sub_' . ( $this->mSubqueryId + 1 );
- $this->mSubqueryId += 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->mConn );
- $version = 'Error';
- if ( isset( $server_info['SQLServerVersion'] ) ) {
- $version = $server_info['SQLServerVersion'];
- }
-
- 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
- wfDebug( "Attempting to call tableExists on a remote table" );
- return false;
- }
-
- if ( $schema === false ) {
- global $wgDBmwschema;
- $schema = $wgDBmwschema;
- }
-
- $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
- wfDebug( "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
- wfDebug( "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;
- }
-
- /**
- * Begin a transaction, committing any previously open transaction
- * @param string $fname
- */
- protected function doBegin( $fname = __METHOD__ ) {
- sqlsrv_begin_transaction( $this->mConn );
- $this->mTrxLevel = 1;
- }
-
- /**
- * End a transaction
- * @param string $fname
- */
- protected function doCommit( $fname = __METHOD__ ) {
- sqlsrv_commit( $this->mConn );
- $this->mTrxLevel = 0;
- }
-
- /**
- * Rollback a transaction.
- * No-op on non-transactional databases.
- * @param string $fname
- */
- protected function doRollback( $fname = __METHOD__ ) {
- sqlsrv_rollback( $this->mConn );
- $this->mTrxLevel = 0;
- }
-
- /**
- * Escapes a identifier for use inm SQL.
- * Throws an exception if it is invalid.
- * Reference: http://msdn.microsoft.com/en-us/library/aa224033%28v=SQL.80%29.aspx
- * @param string $identifier
- * @throws MWException
- * @return string
- */
- private function escapeIdentifier( $identifier ) {
- if ( strlen( $identifier ) == 0 ) {
- throw new MWException( "An identifier must not be empty" );
- }
- if ( strlen( $identifier ) > 128 ) {
- throw new MWException( "The identifier '$identifier' is too long (max. 128)" );
- }
- if ( ( strpos( $identifier, '[' ) !== false )
- || ( strpos( $identifier, ']' ) !== false )
- ) {
- // It may be allowed if you quoted with double quotation marks, but
- // that would break if QUOTED_IDENTIFIER is OFF
- throw new MWException( "Square brackets are not allowed in '$identifier'" );
- }
-
- return "[$identifier]";
- }
-
- /**
- * @param string $s
- * @return string
- */
- public function strencode( $s ) {
- // Should not be called by us
-
- return str_replace( "'", "''", $s );
- }
-
- /**
- * @param string|Blob $s
- * @return string
- */
- 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 ) == ']';
- }
-
- /**
- * @param string $db
- * @return bool
- */
- public function selectDB( $db ) {
- try {
- $this->mDBname = $db;
- $this->query( "USE $db" );
- return true;
- } catch ( Exception $e ) {
- return false;
- }
- }
-
- /**
- * @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 = array();
- 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 array( $startOpts, '', $tailOpts, '' );
- }
-
- /**
- * Get the type of the DBMS, as it appears in $wgDBtype.
- * @return string
- */
- 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 = array()
- ) {
- $gcsq = 'gcsq_' . $this->mSubqueryId;
- $this->mSubqueryId++;
-
- $delimLen = strlen( $delim );
- $fld = "{$field} + {$this->addQuotes( $delim )}";
- $sql = "(SELECT LEFT({$field}, LEN({$field}) - {$delimLen}) FROM ("
- . $this->selectSQLText( $table, $fld, $conds, null, array( 'FOR XML' ), $join_conds )
- . ") {$gcsq} ({$field}))";
-
- return $sql;
- }
-
- /**
- * @return string
- */
- public function getSearchEngine() {
- return "SearchMssql";
- }
-
- /**
- * 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->mBinaryColumnCache === null ) {
- $this->populateColumnCaches();
- }
-
- return isset( $this->mBinaryColumnCache[$tableRaw] )
- ? $this->mBinaryColumnCache[$tableRaw]
- : array();
- }
-
- /**
- * @param string $table
- * @return array
- */
- private function getBitColumns( $table ) {
- $tableRawArr = explode( '.', preg_replace( '#\[([^\]]*)\]#', '$1', $table ) );
- $tableRaw = array_pop( $tableRawArr );
-
- if ( $this->mBitColumnCache === null ) {
- $this->populateColumnCaches();
- }
-
- return isset( $this->mBitColumnCache[$tableRaw] )
- ? $this->mBitColumnCache[$tableRaw]
- : array();
- }
-
- private function populateColumnCaches() {
- $res = $this->select( 'INFORMATION_SCHEMA.COLUMNS', '*',
- array(
- 'TABLE_CATALOG' => $this->mDBname,
- 'TABLE_SCHEMA' => $this->mSchema,
- 'DATA_TYPE' => array( 'varbinary', 'binary', 'image', 'bit' )
- ) );
-
- $this->mBinaryColumnCache = array();
- $this->mBitColumnCache = array();
- foreach ( $res as $row ) {
- if ( $row->DATA_TYPE == 'bit' ) {
- $this->mBitColumnCache[$row->TABLE_NAME][$row->COLUMN_NAME] = $row;
- } else {
- $this->mBinaryColumnCache[$row->TABLE_NAME][$row->COLUMN_NAME] = $row;
- }
- }
- }
-
- /**
- * @param string $name
- * @param string $format
- * @return string
- */
- 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, raw, or split
- * @return string
- */
- 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)
- $table = explode( '.', $table );
- while ( count( $table ) < 3 ) {
- array_unshift( $table, false );
- }
- }
- return $table;
- }
-
- /**
- * 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 ) {
- return wfSetVar( $this->mPrepareStatements, $value );
- }
-
- /**
- * 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 ) {
- return wfSetVar( $this->mScrollableCursor, $value );
- }
-} // end DatabaseMssql class
-
-/**
- * Utility class.
- *
- * @ingroup Database
- */
-class MssqlField implements Field {
- private $name, $tableName, $default, $max_length, $nullable, $type;
-
- function __construct( $info ) {
- $this->name = $info['COLUMN_NAME'];
- $this->tableName = $info['TABLE_NAME'];
- $this->default = $info['COLUMN_DEFAULT'];
- $this->max_length = $info['CHARACTER_MAXIMUM_LENGTH'];
- $this->nullable = !( strtolower( $info['IS_NULLABLE'] ) == 'no' );
- $this->type = $info['DATA_TYPE'];
- }
-
- function name() {
- return $this->name;
- }
-
- function tableName() {
- return $this->tableName;
- }
-
- function defaultValue() {
- return $this->default;
- }
-
- function maxLength() {
- return $this->max_length;
- }
-
- function isNullable() {
- return $this->nullable;
- }
-
- function type() {
- return $this->type;
- }
-}
-
-class MssqlBlob extends Blob {
- public function __construct( $data ) {
- if ( $data instanceof MssqlBlob ) {
- return $data;
- } elseif ( $data instanceof Blob ) {
- $this->mData = $data->fetch();
- } elseif ( is_array( $data ) && is_object( $data ) ) {
- $this->mData = serialize( $data );
- } else {
- $this->mData = $data;
- }
- }
-
- /**
- * Returns an unquoted hex representation of a binary string
- * for insertion into varbinary-type fields
- * @return string
- */
- public function fetch() {
- if ( $this->mData === null ) {
- return 'null';
- }
-
- $ret = '0x';
- $dataLength = strlen( $this->mData );
- for ( $i = 0; $i < $dataLength; $i++ ) {
- $ret .= bin2hex( pack( 'C', ord( $this->mData[$i] ) ) );
- }
-
- return $ret;
- }
-}
-
-class MssqlResultWrapper extends ResultWrapper {
- private $mSeekTo = null;
-
- /**
- * @return stdClass|bool
- */
- public function fetchObject() {
- $res = $this->result;
-
- if ( $this->mSeekTo !== null ) {
- $result = sqlsrv_fetch_object( $res, 'stdClass', array(),
- SQLSRV_SCROLL_ABSOLUTE, $this->mSeekTo );
- $this->mSeekTo = null;
- } else {
- $result = sqlsrv_fetch_object( $res );
- }
-
- // MediaWiki expects us to return boolean false when there are no more rows instead of null
- if ( $result === null ) {
- return false;
- }
-
- return $result;
- }
-
- /**
- * @return array|bool
- */
- public function fetchRow() {
- $res = $this->result;
-
- if ( $this->mSeekTo !== null ) {
- $result = sqlsrv_fetch_array( $res, SQLSRV_FETCH_BOTH,
- SQLSRV_SCROLL_ABSOLUTE, $this->mSeekTo );
- $this->mSeekTo = null;
- } else {
- $result = sqlsrv_fetch_array( $res );
- }
-
- // MediaWiki expects us to return boolean false when there are no more rows instead of null
- if ( $result === null ) {
- return false;
- }
-
- return $result;
- }
-
- /**
- * @param int $row
- * @return bool
- */
- public function seek( $row ) {
- $res = $this->result;
-
- // check bounds
- $numRows = $this->db->numRows( $res );
- $row = intval( $row );
-
- if ( $numRows === 0 ) {
- return false;
- } elseif ( $row < 0 || $row > $numRows - 1 ) {
- return false;
- }
-
- // Unlike MySQL, the seek actually happens on the next access
- $this->mSeekTo = $row;
- return true;
- }
-}
diff --git a/includes/db/DatabaseOracle.php b/includes/db/DatabaseOracle.php
deleted file mode 100644
index 87c31646..00000000
--- a/includes/db/DatabaseOracle.php
+++ /dev/null
@@ -1,1546 +0,0 @@
-<?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
- */
-
-/**
- * The oci8 extension is fairly weak and doesn't support oci_num_rows, among
- * other things. We use a wrapper class to handle that and other
- * Oracle-specific bits, like converting column names back to lowercase.
- * @ingroup Database
- */
-class ORAResult {
- private $rows;
- private $cursor;
- private $nrows;
-
- private $columns = array();
-
- private function array_unique_md( $array_in ) {
- $array_out = array();
- $array_hashes = array();
-
- foreach ( $array_in as $item ) {
- $hash = md5( serialize( $item ) );
- if ( !isset( $array_hashes[$hash] ) ) {
- $array_hashes[$hash] = $hash;
- $array_out[] = $item;
- }
- }
-
- return $array_out;
- }
-
- /**
- * @param DatabaseBase $db
- * @param resource $stmt A valid OCI statement identifier
- * @param bool $unique
- */
- function __construct( &$db, $stmt, $unique = false ) {
- $this->db =& $db;
-
- $this->nrows = oci_fetch_all( $stmt, $this->rows, 0, -1, OCI_FETCHSTATEMENT_BY_ROW | OCI_NUM );
- if ( $this->nrows === false ) {
- $e = oci_error( $stmt );
- $db->reportQueryError( $e['message'], $e['code'], '', __METHOD__ );
- $this->free();
-
- return;
- }
-
- if ( $unique ) {
- $this->rows = $this->array_unique_md( $this->rows );
- $this->nrows = count( $this->rows );
- }
-
- if ( $this->nrows > 0 ) {
- foreach ( $this->rows[0] as $k => $v ) {
- $this->columns[$k] = strtolower( oci_field_name( $stmt, $k + 1 ) );
- }
- }
-
- $this->cursor = 0;
- oci_free_statement( $stmt );
- }
-
- public function free() {
- unset( $this->db );
- }
-
- public function seek( $row ) {
- $this->cursor = min( $row, $this->nrows );
- }
-
- public function numRows() {
- return $this->nrows;
- }
-
- public function numFields() {
- return count( $this->columns );
- }
-
- public function fetchObject() {
- if ( $this->cursor >= $this->nrows ) {
- return false;
- }
- $row = $this->rows[$this->cursor++];
- $ret = new stdClass();
- foreach ( $row as $k => $v ) {
- $lc = $this->columns[$k];
- $ret->$lc = $v;
- }
-
- return $ret;
- }
-
- public function fetchRow() {
- if ( $this->cursor >= $this->nrows ) {
- return false;
- }
-
- $row = $this->rows[$this->cursor++];
- $ret = array();
- foreach ( $row as $k => $v ) {
- $lc = $this->columns[$k];
- $ret[$lc] = $v;
- $ret[$k] = $v;
- }
-
- return $ret;
- }
-}
-
-/**
- * Utility class.
- * @ingroup Database
- */
-class ORAField implements Field {
- private $name, $tablename, $default, $max_length, $nullable,
- $is_pk, $is_unique, $is_multiple, $is_key, $type;
-
- function __construct( $info ) {
- $this->name = $info['column_name'];
- $this->tablename = $info['table_name'];
- $this->default = $info['data_default'];
- $this->max_length = $info['data_length'];
- $this->nullable = $info['not_null'];
- $this->is_pk = isset( $info['prim'] ) && $info['prim'] == 1 ? 1 : 0;
- $this->is_unique = isset( $info['uniq'] ) && $info['uniq'] == 1 ? 1 : 0;
- $this->is_multiple = isset( $info['nonuniq'] ) && $info['nonuniq'] == 1 ? 1 : 0;
- $this->is_key = ( $this->is_pk || $this->is_unique || $this->is_multiple );
- $this->type = $info['data_type'];
- }
-
- function name() {
- return $this->name;
- }
-
- function tableName() {
- return $this->tablename;
- }
-
- function defaultValue() {
- return $this->default;
- }
-
- function maxLength() {
- return $this->max_length;
- }
-
- function isNullable() {
- return $this->nullable;
- }
-
- function isKey() {
- return $this->is_key;
- }
-
- function isMultipleKey() {
- return $this->is_multiple;
- }
-
- function type() {
- return $this->type;
- }
-}
-
-/**
- * @ingroup Database
- */
-class DatabaseOracle extends DatabaseBase {
- /** @var resource */
- protected $mLastResult = null;
-
- /** @var int The number of rows affected as an integer */
- protected $mAffectedRows;
-
- /** @var int */
- private $mInsertId = null;
-
- /** @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 = array();
-
- function __construct( array $p ) {
- global $wgDBprefix;
-
- if ( $p['tablePrefix'] == 'get from global' ) {
- $p['tablePrefix'] = $wgDBprefix;
- }
- $p['tablePrefix'] = strtoupper( $p['tablePrefix'] );
- parent::__construct( $p );
- Hooks::run( 'DatabaseOraclePostInit', array( $this ) );
- }
-
- function __destruct() {
- if ( $this->mOpened ) {
- MediaWiki\suppressWarnings();
- $this->close();
- MediaWiki\restoreWarnings();
- }
- }
-
- function getType() {
- return 'oracle';
- }
-
- function cascadingDeletes() {
- return true;
- }
-
- function cleanupTriggers() {
- return true;
- }
-
- function strictIPs() {
- return true;
- }
-
- function realTimestamps() {
- return true;
- }
-
- function implicitGroupby() {
- return false;
- }
-
- function implicitOrderby() {
- return false;
- }
-
- function searchableIPs() {
- return true;
- }
-
- /**
- * Usually aborts on failure
- * @param string $server
- * @param string $user
- * @param string $password
- * @param string $dbName
- * @throws DBConnectionError
- * @return DatabaseBase|null
- */
- function open( $server, $user, $password, $dbName ) {
- global $wgDBOracleDRCP;
- if ( !function_exists( 'oci_connect' ) ) {
- throw new DBConnectionError(
- $this,
- "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)\n" );
- }
-
- $this->close();
- $this->mUser = $user;
- $this->mPassword = $password;
- // changed internal variables functions
- // mServer now holds the TNS endpoint
- // mDBname is schema name if different from username
- if ( !$server ) {
- // backward compatibillity (server used to be null and TNS was supplied in dbname)
- $this->mServer = $dbName;
- $this->mDBname = $user;
- } else {
- $this->mServer = $server;
- if ( !$dbName ) {
- $this->mDBname = $user;
- } else {
- $this->mDBname = $dbName;
- }
- }
-
- if ( !strlen( $user ) ) { # e.g. the class is being loaded
- return null;
- }
-
- if ( $wgDBOracleDRCP ) {
- $this->setFlag( DBO_PERSISTENT );
- }
-
- $session_mode = $this->mFlags & DBO_SYSDBA ? OCI_SYSDBA : OCI_DEFAULT;
-
- MediaWiki\suppressWarnings();
- if ( $this->mFlags & DBO_PERSISTENT ) {
- $this->mConn = oci_pconnect(
- $this->mUser,
- $this->mPassword,
- $this->mServer,
- $this->defaultCharset,
- $session_mode
- );
- } elseif ( $this->mFlags & DBO_DEFAULT ) {
- $this->mConn = oci_new_connect(
- $this->mUser,
- $this->mPassword,
- $this->mServer,
- $this->defaultCharset,
- $session_mode
- );
- } else {
- $this->mConn = oci_connect(
- $this->mUser,
- $this->mPassword,
- $this->mServer,
- $this->defaultCharset,
- $session_mode
- );
- }
- MediaWiki\restoreWarnings();
-
- if ( $this->mUser != $this->mDBname ) {
- //change current schema in session
- $this->selectDB( $this->mDBname );
- }
-
- if ( !$this->mConn ) {
- throw new DBConnectionError( $this, $this->lastError() );
- }
-
- $this->mOpened = true;
-
- # removed putenv calls because they interfere with the system globaly
- $this->doQuery( 'ALTER SESSION SET NLS_TIMESTAMP_FORMAT=\'DD-MM-YYYY HH24:MI:SS.FF6\'' );
- $this->doQuery( 'ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT=\'DD-MM-YYYY HH24:MI:SS.FF6\'' );
- $this->doQuery( 'ALTER SESSION SET NLS_NUMERIC_CHARACTERS=\'.,\'' );
-
- return $this->mConn;
- }
-
- /**
- * Closes a database connection, if it is open
- * Returns success, true if already closed
- * @return bool
- */
- protected function closeConnection() {
- return oci_close( $this->mConn );
- }
-
- function execFlags() {
- return $this->mTrxLevel ? OCI_NO_AUTO_COMMIT : OCI_COMMIT_ON_SUCCESS;
- }
-
- protected function doQuery( $sql ) {
- wfDebug( "SQL: [$sql]\n" );
- if ( !StringUtils::isUtf8( $sql ) ) {
- throw new MWException( "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
- );
-
- MediaWiki\suppressWarnings();
-
- if ( ( $this->mLastResult = $stmt = oci_parse( $this->mConn, $sql ) ) === false ) {
- $e = oci_error( $this->mConn );
- $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;
- }
- }
-
- MediaWiki\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 ResultWrapper|resource $res
- */
- function freeResult( $res ) {
- if ( $res instanceof ResultWrapper ) {
- $res = $res->result;
- }
-
- $res->free();
- }
-
- /**
- * @param ResultWrapper|stdClass $res
- * @return mixed
- */
- function fetchObject( $res ) {
- if ( $res instanceof ResultWrapper ) {
- $res = $res->result;
- }
-
- return $res->fetchObject();
- }
-
- function fetchRow( $res ) {
- if ( $res instanceof ResultWrapper ) {
- $res = $res->result;
- }
-
- return $res->fetchRow();
- }
-
- function numRows( $res ) {
- if ( $res instanceof ResultWrapper ) {
- $res = $res->result;
- }
-
- return $res->numRows();
- }
-
- function numFields( $res ) {
- if ( $res instanceof ResultWrapper ) {
- $res = $res->result;
- }
-
- return $res->numFields();
- }
-
- function fieldName( $stmt, $n ) {
- return oci_field_name( $stmt, $n );
- }
-
- /**
- * This must be called after nextSequenceVal
- * @return null|int
- */
- function insertId() {
- return $this->mInsertId;
- }
-
- /**
- * @param mixed $res
- * @param int $row
- */
- function dataSeek( $res, $row ) {
- if ( $res instanceof ORAResult ) {
- $res->seek( $row );
- } else {
- $res->result->seek( $row );
- }
- }
-
- function lastError() {
- if ( $this->mConn === false ) {
- $e = oci_error();
- } else {
- $e = oci_error( $this->mConn );
- }
-
- return $e['message'];
- }
-
- function lastErrno() {
- if ( $this->mConn === false ) {
- $e = oci_error();
- } else {
- $e = oci_error( $this->mConn );
- }
-
- return $e['code'];
- }
-
- function affectedRows() {
- 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 = array() ) {
- if ( !count( $a ) ) {
- return true;
- }
-
- if ( !is_array( $options ) ) {
- $options = array( $options );
- }
-
- if ( in_array( 'IGNORE', $options ) ) {
- $this->ignoreDupValOnIndex = true;
- }
-
- if ( !is_array( reset( $a ) ) ) {
- $a = array( $a );
- }
-
- foreach ( $a as &$row ) {
- $this->insertOneRow( $table, $row, $fname );
- }
- $retVal = true;
-
- if ( in_array( 'IGNORE', $options ) ) {
- $this->ignoreDupValOnIndex = false;
- }
-
- return $retVal;
- }
-
- 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 ) {
- global $wgContLang;
-
- $table = $this->tableName( $table );
- // "INSERT INTO tables (a, b, c)"
- $sql = "INSERT INTO " . $table . " (" . join( ',', 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 .= ')';
-
- if ( ( $this->mLastResult = $stmt = oci_parse( $this->mConn, $sql ) ) === false ) {
- $e = oci_error( $this->mConn );
- $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
-
- 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 = ( $wgContLang != null ) ? $wgContLang->checkTitleEncoding( $val ) : $val;
- if ( oci_bind_by_name( $stmt, ":$col", $val, -1, SQLT_CHR ) === false ) {
- $e = oci_error( $stmt );
- $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
-
- return false;
- }
- } else {
- /** @var OCI_Lob[] $lob */
- if ( ( $lob[$col] = oci_new_descriptor( $this->mConn, OCI_D_LOB ) ) === 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 );
- }
- }
- }
-
- MediaWiki\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 );
- }
-
- MediaWiki\restoreWarnings();
-
- if ( isset( $lob ) ) {
- foreach ( $lob as $lob_v ) {
- $lob_v->free();
- }
- }
-
- if ( !$this->mTrxLevel ) {
- oci_commit( $this->mConn );
- }
-
- return oci_free_statement( $stmt );
- }
-
- function insertSelect( $destTable, $srcTable, $varMap, $conds, $fname = __METHOD__,
- $insertOptions = array(), $selectOptions = array()
- ) {
- $destTable = $this->tableName( $destTable );
- if ( !is_array( $selectOptions ) ) {
- $selectOptions = array( $selectOptions );
- }
- list( $startOpts, $useIndex, $tailOpts ) = $this->makeSelectOptions( $selectOptions );
- if ( is_array( $srcTable ) ) {
- $srcTable = implode( ',', array_map( array( &$this, 'tableName' ), $srcTable ) );
- } else {
- $srcTable = $this->tableName( $srcTable );
- }
-
- if ( ( $sequenceData = $this->getSequenceData( $destTable ) ) !== 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 = $val . ' field' . ( $i++ );
- }
-
- $sql = "INSERT INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ')' .
- " SELECT $startOpts " . implode( ',', $varMap ) .
- " FROM $srcTable $useIndex ";
- if ( $conds != '*' ) {
- $sql .= ' WHERE ' . $this->makeList( $conds, LIST_AND );
- }
- $sql .= " $tailOpts";
-
- if ( in_array( 'IGNORE', $insertOptions ) ) {
- $this->ignoreDupValOnIndex = true;
- }
-
- $retval = $this->query( $sql, $fname );
-
- if ( in_array( 'IGNORE', $insertOptions ) ) {
- $this->ignoreDupValOnIndex = false;
- }
-
- return $retval;
- }
-
- public function upsert( $table, array $rows, array $uniqueIndexes, array $set,
- $fname = __METHOD__
- ) {
- if ( !count( $rows ) ) {
- return true; // nothing to do
- }
-
- if ( !is_array( reset( $rows ) ) ) {
- $rows = array( $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 );
- }
-
- function tableName( $name, $format = 'quoted' ) {
- /*
- Replace reserved words with better ones
- Using uppercase because that's the only way Oracle can handle
- quoted tablenames
- */
- switch ( $name ) {
- case 'user':
- $name = 'MWUSER';
- break;
- case 'text':
- $name = 'PAGECONTENT';
- break;
- }
-
- return strtoupper( parent::tableName( $name, $format ) );
- }
-
- function tableNameInternal( $name ) {
- $name = $this->tableName( $name );
-
- return preg_replace( '/.*\.(.*)/', '$1', $name );
- }
-
- /**
- * Return the next in a sequence, save the value for retrieval via insertId()
- *
- * @param string $seqName
- * @return null|int
- */
- function nextSequenceValue( $seqName ) {
- $res = $this->query( "SELECT $seqName.nextval FROM dual" );
- $row = $this->fetchRow( $res );
- $this->mInsertId = $row[0];
-
- return $this->mInsertId;
- }
-
- /**
- * Return sequence_name if table has a sequence
- *
- * @param string $table
- * @return bool
- */
- private function getSequenceData( $table ) {
- if ( $this->sequenceData == null ) {
- $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(
- atc.table_name,
- '{$this->mTablePrefix}MWUSER',
- '{$this->mTablePrefix}USER',
- atc.table_name
- ) || '_' ||
- atc.column_name || '_SEQ' = '{$this->mTablePrefix}' || asq.sequence_name
- AND asq.sequence_owner = upper('{$this->mDBname}')
- AND atc.owner = upper('{$this->mDBname}')" );
-
- while ( ( $row = $result->fetchRow() ) !== false ) {
- $this->sequenceData[$row[1]] = array(
- 'sequence' => $row[0],
- 'column' => $row[2]
- );
- }
- }
- $table = strtolower( $this->removeIdentifierQuotes( $this->tableName( $table ) ) );
-
- return ( isset( $this->sequenceData[$table] ) ) ? $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 decodeBlob( $b ) {
- if ( $b instanceof Blob ) {
- $b = $b->fetch();
- }
-
- return $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';
-
- $newName = strtoupper( $newName );
- $oldName = strtoupper( $oldName );
-
- $tabName = substr( $newName, strlen( $this->mTablePrefix ) );
- $oldPrefix = substr( $oldName, 0, strlen( $oldName ) - strlen( $tabName ) );
- $newPrefix = strtoupper( $this->mTablePrefix );
-
- 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->mDBname );
- $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 = array();
- $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" );
- }
-
- function timestamp( $ts = 0 ) {
- return wfTimestamp( TS_ORACLE, $ts );
- }
-
- /**
- * 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%\''
- );
- if ( !( $row = $rset->fetchRow() ) ) {
- return oci_server_version( $this->mConn );
- }
-
- 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->mDBname );
- $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->mDBname ) );
- $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
- */
- private function fieldInfoMulti( $table, $field ) {
- $field = strtoupper( $field );
- if ( is_array( $table ) ) {
- $table = array_map( array( &$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->mConn,
- '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->mTrxLevel = 1;
- $this->doQuery( 'SET CONSTRAINTS ALL DEFERRED' );
- }
-
- protected function doCommit( $fname = __METHOD__ ) {
- if ( $this->mTrxLevel ) {
- $ret = oci_commit( $this->mConn );
- if ( !$ret ) {
- throw new DBUnexpectedError( $this, $this->lastError() );
- }
- $this->mTrxLevel = 0;
- $this->doQuery( 'SET CONSTRAINTS ALL IMMEDIATE' );
- }
- }
-
- protected function doRollback( $fname = __METHOD__ ) {
- if ( $this->mTrxLevel ) {
- oci_rollback( $this->mConn );
- $this->mTrxLevel = 0;
- $this->doQuery( 'SET CONSTRAINTS ALL IMMEDIATE' );
- }
- }
-
- /**
- * defines must comply with ^define\s*([^\s=]*)\s*=\s?'\{\$([^\}]*)\}';
- *
- * @param resource $fp
- * @param bool|string $lineCallback
- * @param bool|callable $resultCallback
- * @param string $fname
- * @param bool|callable $inputCallback
- * @return bool|string
- */
- function sourceStream( $fp, $lineCallback = false, $resultCallback = false,
- $fname = __METHOD__, $inputCallback = false ) {
- $cmd = '';
- $done = false;
- $dollarquote = false;
-
- $replacements = array();
-
- while ( !feof( $fp ) ) {
- if ( $lineCallback ) {
- call_user_func( $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 ) {
- call_user_func( $inputCallback, $cmd );
- }
- $res = $this->doQuery( $cmd );
- if ( $resultCallback ) {
- call_user_func( $resultCallback, $res, $this );
- }
-
- if ( false === $res ) {
- $err = $this->lastError();
-
- return "Query \"{$cmd}\" failed with error code \"$err\".\n";
- }
- }
-
- $cmd = '';
- $done = false;
- }
- }
-
- return true;
- }
-
- function selectDB( $db ) {
- $this->mDBname = $db;
- if ( $db == null || $db == $this->mUser ) {
- return true;
- }
- $sql = 'ALTER SESSION SET CURRENT_SCHEMA=' . strtoupper( $db );
- $stmt = oci_parse( $this->mConn, $sql );
- MediaWiki\suppressWarnings();
- $success = oci_execute( $stmt );
- MediaWiki\restoreWarnings();
- if ( !$success ) {
- $e = oci_error( $stmt );
- if ( $e['code'] != '1435' ) {
- $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
- }
-
- return false;
- }
-
- return true;
- }
-
- function strencode( $s ) {
- return str_replace( "'", "''", $s );
- }
-
- function addQuotes( $s ) {
- global $wgContLang;
- if ( isset( $wgContLang->mLoaded ) && $wgContLang->mLoaded ) {
- $s = $wgContLang->checkTitleEncoding( $s );
- }
-
- return "'" . $this->strencode( $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 ) {
- global $wgContLang;
-
- $col_info = $this->fieldInfoMulti( $table, $col );
- $col_type = $col_info != false ? $col_info->type() : 'CONSTANT';
- if ( $col_type == 'CLOB' ) {
- $col = 'TO_CHAR(' . $col . ')';
- $val = $wgContLang->checkTitleEncoding( $val );
- } elseif ( $col_type == 'VARCHAR2' ) {
- $val = $wgContLang->checkTitleEncoding( $val );
- }
- }
-
- private function wrapConditionsForWhere( $table, $conds, $parentCol = null ) {
- $conds2 = array();
- 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 = array(), $join_conds = array()
- ) {
- 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 = array();
- 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 = '';
- }
-
- return array( $startOpts, $useIndex, $preLimitTail, $postLimitTail );
- }
-
- public function delete( $table, $conds, $fname = __METHOD__ ) {
- 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
- $table = $this->tableName( $table );
- if ( $table == $this->tableName( 'user' ) ) {
- $this->update( 'archive', array( 'ar_user' => 0 ),
- array( 'ar_user' => $conds['user_id'] ), $fname );
- $this->update( 'ipblocks', array( 'ipb_user' => 0 ),
- array( 'ipb_user' => $conds['user_id'] ), $fname );
- $this->update( 'image', array( 'img_user' => 0 ),
- array( 'img_user' => $conds['user_id'] ), $fname );
- $this->update( 'oldimage', array( 'oi_user' => 0 ),
- array( 'oi_user' => $conds['user_id'] ), $fname );
- $this->update( 'filearchive', array( 'fa_deleted_user' => 0 ),
- array( 'fa_deleted_user' => $conds['user_id'] ), $fname );
- $this->update( 'filearchive', array( 'fa_user' => 0 ),
- array( 'fa_user' => $conds['user_id'] ), $fname );
- $this->update( 'uploadstash', array( 'us_user' => 0 ),
- array( 'us_user' => $conds['user_id'] ), $fname );
- $this->update( 'recentchanges', array( 'rc_user' => 0 ),
- array( 'rc_user' => $conds['user_id'] ), $fname );
- $this->update( 'logging', array( 'log_user' => 0 ),
- array( 'log_user' => $conds['user_id'] ), $fname );
- } elseif ( $table == $this->tableName( 'image' ) ) {
- $this->update( 'oldimage', array( 'oi_name' => 0 ),
- array( '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 = array() ) {
- global $wgContLang;
-
- $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 !== array() && $conds !== '*' ) {
- $conds = $this->wrapConditionsForWhere( $table, $conds );
- $sql .= ' WHERE ' . $this->makeList( $conds, LIST_AND );
- }
-
- if ( ( $this->mLastResult = $stmt = oci_parse( $this->mConn, $sql ) ) === false ) {
- $e = oci_error( $this->mConn );
- $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 = ( $wgContLang != null ) ? $wgContLang->checkTitleEncoding( $val ) : $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 */
- if ( ( $lob[$col] = oci_new_descriptor( $this->mConn, OCI_D_LOB ) ) === 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 );
- }
- }
- }
-
- MediaWiki\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 );
- }
-
- MediaWiki\restoreWarnings();
-
- if ( isset( $lob ) ) {
- foreach ( $lob as $lob_v ) {
- $lob_v->free();
- }
- }
-
- if ( !$this->mTrxLevel ) {
- oci_commit( $this->mConn );
- }
-
- 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 . ')';
- }
-
- function getDBname() {
- return $this->mDBname;
- }
-
- function getServer() {
- return $this->mServer;
- }
-
- public function buildGroupConcatField(
- $delim, $table, $field, $conds = '', $join_conds = array()
- ) {
- $fld = "LISTAGG($field," . $this->addQuotes( $delim ) . ") WITHIN GROUP (ORDER BY $field)";
-
- return '(' . $this->selectSQLText( $table, $fld, $conds, null, array(), $join_conds ) . ')';
- }
-
- public function getSearchEngine() {
- return 'SearchOracle';
- }
-
- public function getInfinity() {
- return '31-12-2030 12:00:00.000000';
- }
-}
diff --git a/includes/installer/MssqlInstaller.php b/includes/installer/MssqlInstaller.php
deleted file mode 100644
index 4d79d966..00000000
--- a/includes/installer/MssqlInstaller.php
+++ /dev/null
@@ -1,736 +0,0 @@
-<?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
- */
-
-/**
- * Class for setting up the MediaWiki database using Microsoft SQL Server.
- *
- * @ingroup Deployment
- * @since 1.23
- */
-class MssqlInstaller extends DatabaseInstaller {
-
- protected $globalNames = array(
- 'wgDBserver',
- 'wgDBname',
- 'wgDBuser',
- 'wgDBpassword',
- 'wgDBmwschema',
- 'wgDBprefix',
- 'wgDBWindowsAuthentication',
- );
-
- protected $internalDefaults = array(
- '_InstallUser' => 'sa',
- '_InstallWindowsAuthentication' => 'sqlauth',
- '_WebWindowsAuthentication' => 'sqlauth',
- );
-
- // SQL Server 2005 RTM
- // @todo Are SQL Express version numbers different?)
- public $minimumVersion = '9.00.1399';
-
- // 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 = array(
- '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',
- array(),
- $this->parent->getHelpBox( 'config-db-host-help' )
- ) .
- Html::openElement( 'fieldset' ) .
- Html::element( 'legend', array(), wfMessage( 'config-db-wiki-settings' )->text() ) .
- $this->getTextBox( 'wgDBname', 'config-db-name', array( 'dir' => 'ltr' ),
- $this->parent->getHelpBox( 'config-db-name-help' ) ) .
- $this->getTextBox( 'wgDBmwschema', 'config-db-schema', array( 'dir' => 'ltr' ),
- $this->parent->getHelpBox( 'config-db-schema-help' ) ) .
- $this->getTextBox( 'wgDBprefix', 'config-db-prefix', array( 'dir' => 'ltr' ),
- $this->parent->getHelpBox( 'config-db-prefix-help' ) ) .
- Html::closeElement( 'fieldset' ) .
- Html::openElement( 'fieldset' ) .
- Html::element( 'legend', array(), wfMessage( 'config-db-install-account' )->text() ) .
- $this->getRadioSet( array(
- 'var' => '_InstallWindowsAuthentication',
- 'label' => 'config-mssql-auth',
- 'itemLabelPrefix' => 'config-mssql-',
- 'values' => array( 'sqlauth', 'windowsauth' ),
- 'itemAttribs' => array(
- 'sqlauth' => array(
- 'class' => 'showHideRadio',
- 'rel' => 'dbCredentialBox',
- ),
- 'windowsauth' => array(
- 'class' => 'hideShowRadio',
- 'rel' => 'dbCredentialBox',
- )
- ),
- 'help' => $this->parent->getHelpBox( 'config-mssql-install-auth' )
- ) ) .
- Html::openElement( 'div', array( 'id' => 'dbCredentialBox', 'style' => $displayStyle ) ) .
- $this->getTextBox(
- '_InstallUser',
- 'config-db-username',
- array( 'dir' => 'ltr' ),
- $this->parent->getHelpBox( 'config-db-install-username' )
- ) .
- $this->getPasswordBox(
- '_InstallPassword',
- 'config-db-password',
- array( '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( array(
- '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( array(
- '_InstallUser',
- '_InstallPassword',
- '_InstallWindowsAuthentication'
- ) );
-
- // Try to connect
- $status = $this->getConnection();
- if ( !$status->isOK() ) {
- return $status;
- }
- /**
- * @var $conn DatabaseBase
- */
- $conn = $status->value;
-
- // Check version
- $version = $conn->getServerVersion();
- if ( version_compare( $version, $this->minimumVersion ) < 0 ) {
- return Status::newFatal( 'config-mssql-old', $this->minimumVersion, $version );
- }
-
- return $status;
- }
-
- /**
- * @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 {
- $db = DatabaseBase::factory( 'mssql', array(
- 'host' => $this->getVar( 'wgDBserver' ),
- '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->showStatusError( $status );
-
- return;
- }
- /**
- * @var $conn DatabaseBase
- */
- $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 $conn DatabaseBase */
- $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 = array(
- '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
- // http://technet.microsoft.com/en-us/library/ms178569.aspx
- // The following array sets up which permissions imply whatever permissions we specify
- $implied = array(
- // schema database server
- 'DELETE' => array( 'DELETE', 'CONTROL SERVER' ),
- 'EXECUTE' => array( 'EXECUTE', 'CONTROL SERVER' ),
- 'INSERT' => array( 'INSERT', 'CONTROL SERVER' ),
- 'SELECT' => array( 'SELECT', 'CONTROL SERVER' ),
- 'UPDATE' => array( 'UPDATE', 'CONTROL SERVER' ),
- );
-
- $grantOptions = array_flip( $this->webUserPrivs );
-
- // Check for schema and db-level permissions, but only if the schema/db exists
- $schemaPrivs = $dbPrivs = array(
- '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', array(), wfMessage( 'config-db-web-account' )->text() ) .
- $this->getCheckBox(
- '_SameAccount', 'config-db-web-account-same',
- array( 'class' => 'hideShowRadio', 'rel' => 'dbOtherAccount' )
- ) .
- Html::openElement( 'div', array( 'id' => 'dbOtherAccount', 'style' => $wrapperStyle ) ) .
- $this->getRadioSet( array(
- 'var' => '_WebWindowsAuthentication',
- 'label' => 'config-mssql-auth',
- 'itemLabelPrefix' => 'config-mssql-',
- 'values' => array( 'sqlauth', 'windowsauth' ),
- 'itemAttribs' => array(
- 'sqlauth' => array(
- 'class' => 'showHideRadio',
- 'rel' => 'dbCredentialBox',
- ),
- 'windowsauth' => array(
- 'class' => 'hideShowRadio',
- 'rel' => 'dbCredentialBox',
- )
- ),
- 'help' => $this->parent->getHelpBox( 'config-mssql-web-auth' )
- ) ) .
- Html::openElement( 'div', array( '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( array(
- '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 {
- DatabaseBase::factory( 'mssql', array(
- '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 = array(
- 'name' => 'user',
- 'callback' => array( $this, 'setupUser' ),
- );
- $this->parent->addInstallStep( $callback, 'tables' );
- }
-
- /**
- * @return Status
- */
- public function setupDatabase() {
- $status = $this->getConnection();
- if ( !$status->isOK() ) {
- return $status;
- }
- /** @var DatabaseBase $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 = array();
- 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->getText() );
- }
- } 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->getText() );
- }
- } 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 );
- foreach ( $grantableNames as $name ) {
- try {
- // First try to grant full permissions
- $fullPrivArr = array(
- '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->getText() );
- }
- // 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->getText() );
- }
- }
-
- 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(), array(
- '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, array( '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, array( '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, array( '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, array( '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, array( 'name' => $catalogName ) );
- return (bool)$res;
- }
-
- /**
- * Get variables to substitute into tables.sql and the SQL patch files.
- *
- * @return array
- */
- public function getSchemaVars() {
- return array(
- '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}\";";
- }
-}
diff --git a/includes/installer/MssqlUpdater.php b/includes/installer/MssqlUpdater.php
deleted file mode 100644
index 164cfab4..00000000
--- a/includes/installer/MssqlUpdater.php
+++ /dev/null
@@ -1,143 +0,0 @@
-<?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
- */
-
-/**
- * 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 array(
- // 1.23
- array( 'addField', 'mwuser', 'user_password_expires', 'patch-user_password_expires.sql' ),
-
- // 1.24
- array( 'addField', 'page', 'page_lang', 'patch-page-page_lang.sql' ),
-
- // 1.25
- array( 'dropTable', 'hitcounter' ),
- array( 'dropField', 'site_stats', 'ss_total_views', 'patch-drop-ss_total_views.sql' ),
- array( 'dropField', 'page', 'page_counter', 'patch-drop-page_counter.sql' ),
- // Constraint updates
- array( 'updateConstraints', 'category_types', 'categorylinks', 'cl_type' ),
- array( 'updateConstraints', 'major_mime', 'filearchive', 'fa_major_mime' ),
- array( 'updateConstraints', 'media_type', 'filearchive', 'fa_media_type' ),
- array( 'updateConstraints', 'major_mime', 'oldimage', 'oi_major_mime' ),
- array( 'updateConstraints', 'media_type', 'oldimage', 'oi_media_type' ),
- array( 'updateConstraints', 'major_mime', 'image', 'img_major_mime' ),
- array( 'updateConstraints', 'media_type', 'image', 'img_media_type' ),
- array( 'updateConstraints', 'media_type', 'uploadstash', 'us_media_type' ),
- // END: Constraint updates
-
- array( 'modifyField', 'image', 'img_major_mime',
- 'patch-img_major_mime-chemical.sql' ),
- array( 'modifyField', 'oldimage', 'oi_major_mime',
- 'patch-oi_major_mime-chemical.sql' ),
- array( 'modifyField', 'filearchive', 'fa_major_mime',
- 'patch-fa_major_mime-chemical.sql' ),
- );
- }
-
- /**
- * Drops unnamed and creates named constraints following the pattern
- * <column>_ckc
- *
- * @param string $constraintType
- * @param string $table Name of the table to which the field belongs
- * @param string $field Name of the field to modify
- * @return bool False if patch is skipped.
- */
- protected function updateConstraints( $constraintType, $table, $field ) {
- global $wgDBname, $wgDBmwschema;
-
- if ( !$this->doTable( $table ) ) {
- return true;
- }
-
- $this->output( "...updating constraints on [$table].[$field] ..." );
- $updateKey = "$field-$constraintType-ck";
- if ( !$this->db->tableExists( $table, __METHOD__ ) ) {
- $this->output( "...$table table does not exist, skipping modify field patch.\n" );
- return true;
- } elseif ( !$this->db->fieldExists( $table, $field, __METHOD__ ) ) {
- $this->output( "...$field field does not exist in $table table, " .
- "skipping modify field patch.\n" );
- return true;
- } elseif ( $this->updateRowExists( $updateKey ) ) {
- $this->output( "...$field in table $table already patched.\n" );
- return true;
- }
-
- # After all checks passed, start the update
- $this->insertUpdateRow( $updateKey );
- $path = 'named_constraints.sql';
- $constraintMap = array(
- 'category_types' =>
- "($field in('page', 'subcat', 'file'))",
- 'major_mime' =>
- "($field in('unknown', 'application', 'audio', 'image', 'text', 'video'," .
- " 'message', 'model', 'multipart'))",
- 'media_type' =>
- "($field in('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA'," .
- "'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE'))"
- );
- $constraint = $constraintMap[$constraintType];
-
- # and hack-in those variables that should be replaced
- # in our template file right now
- $this->db->setSchemaVars( array(
- 'tableName' => $table,
- 'fieldName' => $field,
- 'checkConstraint' => $constraint,
- 'wgDBname' => $wgDBname,
- 'wgDBmwschema' => $wgDBmwschema,
- ) );
-
- # Full path from file name
- $path = $this->db->patchPath( $path );
-
- # No need for a cursor allowing result-iteration; just apply a patch
- # store old value for re-setting later
- $wasScrollable = $this->db->scrollableCursor( false );
-
- # Apply patch
- $this->db->sourceFile( $path );
-
- # Reset DB instance to have original state
- $this->db->setSchemaVars( false );
- $this->db->scrollableCursor( $wasScrollable );
-
- $this->output( "done.\n" );
-
- return true;
- }
-}
diff --git a/includes/installer/OracleInstaller.php b/includes/installer/OracleInstaller.php
deleted file mode 100644
index 9e692ea4..00000000
--- a/includes/installer/OracleInstaller.php
+++ /dev/null
@@ -1,344 +0,0 @@
-<?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
- */
-
-/**
- * Class for setting up the MediaWiki database using Oracle.
- *
- * @ingroup Deployment
- * @since 1.17
- */
-class OracleInstaller extends DatabaseInstaller {
-
- protected $globalNames = array(
- 'wgDBserver',
- 'wgDBname',
- 'wgDBuser',
- 'wgDBpassword',
- 'wgDBprefix',
- );
-
- protected $internalDefaults = array(
- '_OracleDefTS' => 'USERS',
- '_OracleTempTS' => 'TEMP',
- '_InstallUser' => 'SYSTEM',
- );
-
- public $minimumVersion = '9.0.1'; // 9iR1
-
- 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',
- array(),
- $this->parent->getHelpBox( 'config-db-host-oracle-help' )
- ) .
- Html::openElement( 'fieldset' ) .
- Html::element( 'legend', array(), 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',
- array(),
- $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( array(
- '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 $conn DatabaseBase
- */
- $conn = $status->value;
-
- // Check version
- $version = $conn->getServerVersion();
- if ( version_compare( $version, $this->minimumVersion ) < 0 ) {
- return Status::newFatal( 'config-oracle-old', $this->minimumVersion, $version );
- }
-
- return $status;
- }
-
- public function openConnection() {
- $status = Status::newGood();
- try {
- $db = new DatabaseOracle(
- $this->getVar( 'wgDBserver' ),
- $this->getVar( '_InstallUser' ),
- $this->getVar( '_InstallPassword' ),
- $this->getVar( '_InstallDBname' ),
- 0,
- $this->getVar( 'wgDBprefix' )
- );
- $status->value = $db;
- } catch ( DBConnectionError $e ) {
- $this->connError = $e->db->lastErrno();
- $status->fatal( 'config-connection-error', $e->getMessage() );
- }
-
- return $status;
- }
-
- public function openSYSDBAConnection() {
- $status = Status::newGood();
- try {
- $db = new DatabaseOracle(
- $this->getVar( 'wgDBserver' ),
- $this->getVar( '_InstallUser' ),
- $this->getVar( '_InstallPassword' ),
- $this->getVar( '_InstallDBname' ),
- DBO_SYSDBA,
- $this->getVar( 'wgDBprefix' )
- );
- $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 = array(
- 'name' => 'user',
- 'callback' => array( $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 = array(
- # These variables are used by maintenance/oracle/user.sql
- '_OracleDefTS',
- '_OracleTempTS',
- 'wgDBuser',
- 'wgDBpassword',
-
- # These are used by tables.sql
- 'wgDBprefix',
- );
- $vars = array();
- 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 ) {
- // @@codingStandardsIgnoreStart Long lines with regular expressions.
- // @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
- // @@codingStandardsIgnoreEnd
- return (bool)$isValid;
- }
-}
diff --git a/includes/installer/OracleUpdater.php b/includes/installer/OracleUpdater.php
deleted file mode 100644
index 03dbd1ce..00000000
--- a/includes/installer/OracleUpdater.php
+++ /dev/null
@@ -1,289 +0,0 @@
-<?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 array(
- array( 'disableContentHandlerUseDB' ),
-
- // 1.17
- array( 'doNamespaceDefaults' ),
- array( 'doFKRenameDeferr' ),
- array( 'doFunctions17' ),
- array( 'doSchemaUpgrade17' ),
- array( 'doInsertPage0' ),
- array( 'doRemoveNotNullEmptyDefaults' ),
- array( 'addTable', 'user_former_groups', 'patch-user_former_groups.sql' ),
-
- // 1.18
- array( 'addIndex', 'user', 'i02', 'patch-user_email_index.sql' ),
- array( 'modifyField', 'user_properties', 'up_property', 'patch-up_property.sql' ),
- array( 'addTable', 'uploadstash', 'patch-uploadstash.sql' ),
- array( 'doRecentchangesFK2Cascade' ),
-
- // 1.19
- array( 'addIndex', 'logging', 'i05', 'patch-logging_type_action_index.sql' ),
- array( 'addField', 'revision', 'rev_sha1', 'patch-rev_sha1_field.sql' ),
- array( 'addField', 'archive', 'ar_sha1', 'patch-ar_sha1_field.sql' ),
- array( 'doRemoveNotNullEmptyDefaults2' ),
- array( 'addIndex', 'page', 'i03', 'patch-page_redirect_namespace_len.sql' ),
- array( 'addField', 'uploadstash', 'us_chunk_inx', 'patch-us_chunk_inx_field.sql' ),
- array( 'addField', 'job', 'job_timestamp', 'patch-job_timestamp_field.sql' ),
- array( 'addIndex', 'job', 'i02', 'patch-job_timestamp_index.sql' ),
- array( 'doPageRestrictionsPKUKFix' ),
-
- // 1.20
- array( 'addIndex', 'ipblocks', 'i05', 'patch-ipblocks_i05_index.sql' ),
- array( 'addIndex', 'revision', 'i05', 'patch-revision_i05_index.sql' ),
- array( 'dropField', 'category', 'cat_hidden', 'patch-cat_hidden.sql' ),
-
- // 1.21
- array( 'addField', 'revision', 'rev_content_format',
- 'patch-revision-rev_content_format.sql' ),
- array( 'addField', 'revision', 'rev_content_model',
- 'patch-revision-rev_content_model.sql' ),
- array( 'addField', 'archive', 'ar_content_format', 'patch-archive-ar_content_format.sql' ),
- array( 'addField', 'archive', 'ar_content_model', 'patch-archive-ar_content_model.sql' ),
- array( 'addField', 'archive', 'ar_id', 'patch-archive-ar_id.sql' ),
- array( 'addField', 'externallinks', 'el_id', 'patch-externallinks-el_id.sql' ),
- array( 'addField', 'page', 'page_content_model', 'patch-page-page_content_model.sql' ),
- array( 'enableContentHandlerUseDB' ),
- array( 'dropField', 'site_stats', 'ss_admins', 'patch-ss_admins.sql' ),
- array( 'dropField', 'recentchanges', 'rc_moved_to_title', 'patch-rc_moved.sql' ),
- array( 'addTable', 'sites', 'patch-sites.sql' ),
- array( 'addField', 'filearchive', 'fa_sha1', 'patch-fa_sha1.sql' ),
- array( 'addField', 'job', 'job_token', 'patch-job_token.sql' ),
- array( 'addField', 'job', 'job_attempts', 'patch-job_attempts.sql' ),
- array( 'addField', 'uploadstash', 'us_props', 'patch-uploadstash-us_props.sql' ),
- array( 'modifyField', 'user_groups', 'ug_group', 'patch-ug_group-length-increase-255.sql' ),
- array( 'modifyField', 'user_former_groups', 'ufg_group',
- 'patch-ufg_group-length-increase-255.sql' ),
-
- // 1.23
- array( 'addIndex', 'logging', 'i06', 'patch-logging_user_text_type_time_index.sql' ),
- array( 'addIndex', 'logging', 'i07', 'patch-logging_user_text_time_index.sql' ),
- array( 'addField', 'user', 'user_password_expires', 'patch-user_password_expire.sql' ),
- array( 'addField', 'page', 'page_links_updated', 'patch-page_links_updated.sql' ),
- array( 'addField', 'recentchanges', 'rc_source', 'patch-rc_source.sql' ),
-
- // 1.24
- array( 'addField', 'page', 'page_lang', 'patch-page-page_lang.sql' ),
-
- // 1.25
- array( 'dropTable', 'hitcounter' ),
- array( 'dropField', 'site_stats', 'ss_total_views', 'patch-drop-ss_total_views.sql' ),
- array( 'dropField', 'page', 'page_counter', 'patch-drop-page_counter.sql' ),
-
- // KEEP THIS AT THE BOTTOM!!
- array( '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 = array(
- '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', array( '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" );
- }
-
- /**
- * 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( $what = array( '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" );
- }
-}
diff --git a/includes/libs/IEContentAnalyzer.php b/includes/libs/IEContentAnalyzer.php
deleted file mode 100644
index c31a3527..00000000
--- a/includes/libs/IEContentAnalyzer.php
+++ /dev/null
@@ -1,851 +0,0 @@
-<?php
-/**
- * Simulation of Microsoft Internet Explorer's MIME type detection algorithm.
- *
- * @file
- * @todo Define the exact license of this file.
- */
-
-/**
- * This class simulates Microsoft Internet Explorer's terribly broken and
- * insecure MIME type detection algorithm. It can be used to check web uploads
- * with an apparently safe type, to see if IE will reinterpret them to produce
- * something dangerous.
- *
- * It is full of bugs and strange design choices should not under any
- * circumstances be used to determine a MIME type to present to a user or
- * client. (Apple Safari developers, this means you too.)
- *
- * This class is based on a disassembly of IE 5.0, 6.0 and 7.0. Although I have
- * attempted to ensure that this code works in exactly the same way as Internet
- * Explorer, it does not share any source code, or creative choices such as
- * variable names, thus I (Tim Starling) claim copyright on it.
- *
- * It may be redistributed without restriction. To aid reuse, this class does
- * not depend on any MediaWiki module.
- */
-class IEContentAnalyzer {
- /**
- * Relevant data taken from the type table in IE 5
- */
- protected $baseTypeTable = array(
- 'ambiguous' /*1*/ => array(
- 'text/plain',
- 'application/octet-stream',
- 'application/x-netcdf', // [sic]
- ),
- 'text' /*3*/ => array(
- 'text/richtext', 'image/x-bitmap', 'application/postscript', 'application/base64',
- 'application/macbinhex40', 'application/x-cdf', 'text/scriptlet'
- ),
- 'binary' /*4*/ => array(
- 'application/pdf', 'audio/x-aiff', 'audio/basic', 'audio/wav', 'image/gif',
- 'image/pjpeg', 'image/jpeg', 'image/tiff', 'image/x-png', 'image/png', 'image/bmp',
- 'image/x-jg', 'image/x-art', 'image/x-emf', 'image/x-wmf', 'video/avi',
- 'video/x-msvideo', 'video/mpeg', 'application/x-compressed',
- 'application/x-zip-compressed', 'application/x-gzip-compressed', 'application/java',
- 'application/x-msdownload'
- ),
- 'html' /*5*/ => array( 'text/html' ),
- );
-
- /**
- * Changes to the type table in later versions of IE
- */
- protected $addedTypes = array(
- 'ie07' => array(
- 'text' => array( 'text/xml', 'application/xml' )
- ),
- );
-
- /**
- * An approximation of the "Content Type" values in HKEY_CLASSES_ROOT in a
- * typical Windows installation.
- *
- * Used for extension to MIME type mapping if detection fails.
- */
- protected $registry = array(
- '.323' => 'text/h323',
- '.3g2' => 'video/3gpp2',
- '.3gp' => 'video/3gpp',
- '.3gp2' => 'video/3gpp2',
- '.3gpp' => 'video/3gpp',
- '.aac' => 'audio/aac',
- '.ac3' => 'audio/ac3',
- '.accda' => 'application/msaccess',
- '.accdb' => 'application/msaccess',
- '.accdc' => 'application/msaccess',
- '.accde' => 'application/msaccess',
- '.accdr' => 'application/msaccess',
- '.accdt' => 'application/msaccess',
- '.ade' => 'application/msaccess',
- '.adp' => 'application/msaccess',
- '.adts' => 'audio/aac',
- '.ai' => 'application/postscript',
- '.aif' => 'audio/aiff',
- '.aifc' => 'audio/aiff',
- '.aiff' => 'audio/aiff',
- '.amc' => 'application/x-mpeg',
- '.application' => 'application/x-ms-application',
- '.asf' => 'video/x-ms-asf',
- '.asx' => 'video/x-ms-asf',
- '.au' => 'audio/basic',
- '.avi' => 'video/avi',
- '.bmp' => 'image/bmp',
- '.caf' => 'audio/x-caf',
- '.cat' => 'application/vnd.ms-pki.seccat',
- '.cbo' => 'application/sha',
- '.cdda' => 'audio/aiff',
- '.cer' => 'application/x-x509-ca-cert',
- '.conf' => 'text/plain',
- '.crl' => 'application/pkix-crl',
- '.crt' => 'application/x-x509-ca-cert',
- '.css' => 'text/css',
- '.csv' => 'application/vnd.ms-excel',
- '.der' => 'application/x-x509-ca-cert',
- '.dib' => 'image/bmp',
- '.dif' => 'video/x-dv',
- '.dll' => 'application/x-msdownload',
- '.doc' => 'application/msword',
- '.docm' => 'application/vnd.ms-word.document.macroEnabled.12',
- '.docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
- '.dot' => 'application/msword',
- '.dotm' => 'application/vnd.ms-word.template.macroEnabled.12',
- '.dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
- '.dv' => 'video/x-dv',
- '.dwfx' => 'model/vnd.dwfx+xps',
- '.edn' => 'application/vnd.adobe.edn',
- '.eml' => 'message/rfc822',
- '.eps' => 'application/postscript',
- '.etd' => 'application/x-ebx',
- '.exe' => 'application/x-msdownload',
- '.fdf' => 'application/vnd.fdf',
- '.fif' => 'application/fractals',
- '.gif' => 'image/gif',
- '.gsm' => 'audio/x-gsm',
- '.hqx' => 'application/mac-binhex40',
- '.hta' => 'application/hta',
- '.htc' => 'text/x-component',
- '.htm' => 'text/html',
- '.html' => 'text/html',
- '.htt' => 'text/webviewhtml',
- '.hxa' => 'application/xml',
- '.hxc' => 'application/xml',
- '.hxd' => 'application/octet-stream',
- '.hxe' => 'application/xml',
- '.hxf' => 'application/xml',
- '.hxh' => 'application/octet-stream',
- '.hxi' => 'application/octet-stream',
- '.hxk' => 'application/xml',
- '.hxq' => 'application/octet-stream',
- '.hxr' => 'application/octet-stream',
- '.hxs' => 'application/octet-stream',
- '.hxt' => 'application/xml',
- '.hxv' => 'application/xml',
- '.hxw' => 'application/octet-stream',
- '.ico' => 'image/x-icon',
- '.iii' => 'application/x-iphone',
- '.ins' => 'application/x-internet-signup',
- '.iqy' => 'text/x-ms-iqy',
- '.isp' => 'application/x-internet-signup',
- '.jfif' => 'image/jpeg',
- '.jnlp' => 'application/x-java-jnlp-file',
- '.jpe' => 'image/jpeg',
- '.jpeg' => 'image/jpeg',
- '.jpg' => 'image/jpeg',
- '.jtx' => 'application/x-jtx+xps',
- '.latex' => 'application/x-latex',
- '.log' => 'text/plain',
- '.m1v' => 'video/mpeg',
- '.m2v' => 'video/mpeg',
- '.m3u' => 'audio/x-mpegurl',
- '.mac' => 'image/x-macpaint',
- '.man' => 'application/x-troff-man',
- '.mda' => 'application/msaccess',
- '.mdb' => 'application/msaccess',
- '.mde' => 'application/msaccess',
- '.mfp' => 'application/x-shockwave-flash',
- '.mht' => 'message/rfc822',
- '.mhtml' => 'message/rfc822',
- '.mid' => 'audio/mid',
- '.midi' => 'audio/mid',
- '.mod' => 'video/mpeg',
- '.mov' => 'video/quicktime',
- '.mp2' => 'video/mpeg',
- '.mp2v' => 'video/mpeg',
- '.mp3' => 'audio/mpeg',
- '.mp4' => 'video/mp4',
- '.mpa' => 'video/mpeg',
- '.mpe' => 'video/mpeg',
- '.mpeg' => 'video/mpeg',
- '.mpf' => 'application/vnd.ms-mediapackage',
- '.mpg' => 'video/mpeg',
- '.mpv2' => 'video/mpeg',
- '.mqv' => 'video/quicktime',
- '.NMW' => 'application/nmwb',
- '.nws' => 'message/rfc822',
- '.odc' => 'text/x-ms-odc',
- '.ols' => 'application/vnd.ms-publisher',
- '.p10' => 'application/pkcs10',
- '.p12' => 'application/x-pkcs12',
- '.p7b' => 'application/x-pkcs7-certificates',
- '.p7c' => 'application/pkcs7-mime',
- '.p7m' => 'application/pkcs7-mime',
- '.p7r' => 'application/x-pkcs7-certreqresp',
- '.p7s' => 'application/pkcs7-signature',
- '.pct' => 'image/pict',
- '.pdf' => 'application/pdf',
- '.pdx' => 'application/vnd.adobe.pdx',
- '.pfx' => 'application/x-pkcs12',
- '.pic' => 'image/pict',
- '.pict' => 'image/pict',
- '.pinstall' => 'application/x-picasa-detect',
- '.pko' => 'application/vnd.ms-pki.pko',
- '.png' => 'image/png',
- '.pnt' => 'image/x-macpaint',
- '.pntg' => 'image/x-macpaint',
- '.pot' => 'application/vnd.ms-powerpoint',
- '.potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12',
- '.potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
- '.ppa' => 'application/vnd.ms-powerpoint',
- '.ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
- '.pps' => 'application/vnd.ms-powerpoint',
- '.ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
- '.ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
- '.ppt' => 'application/vnd.ms-powerpoint',
- '.pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
- '.pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
- '.prf' => 'application/pics-rules',
- '.ps' => 'application/postscript',
- '.pub' => 'application/vnd.ms-publisher',
- '.pwz' => 'application/vnd.ms-powerpoint',
- '.py' => 'text/plain',
- '.pyw' => 'text/plain',
- '.qht' => 'text/x-html-insertion',
- '.qhtm' => 'text/x-html-insertion',
- '.qt' => 'video/quicktime',
- '.qti' => 'image/x-quicktime',
- '.qtif' => 'image/x-quicktime',
- '.qtl' => 'application/x-quicktimeplayer',
- '.rat' => 'application/rat-file',
- '.rmf' => 'application/vnd.adobe.rmf',
- '.rmi' => 'audio/mid',
- '.rqy' => 'text/x-ms-rqy',
- '.rtf' => 'application/msword',
- '.sct' => 'text/scriptlet',
- '.sd2' => 'audio/x-sd2',
- '.sdp' => 'application/sdp',
- '.shtml' => 'text/html',
- '.sit' => 'application/x-stuffit',
- '.sldm' => 'application/vnd.ms-powerpoint.slide.macroEnabled.12',
- '.sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
- '.slk' => 'application/vnd.ms-excel',
- '.snd' => 'audio/basic',
- '.so' => 'application/x-apachemodule',
- '.sol' => 'text/plain',
- '.sor' => 'text/plain',
- '.spc' => 'application/x-pkcs7-certificates',
- '.spl' => 'application/futuresplash',
- '.sst' => 'application/vnd.ms-pki.certstore',
- '.stl' => 'application/vnd.ms-pki.stl',
- '.swf' => 'application/x-shockwave-flash',
- '.thmx' => 'application/vnd.ms-officetheme',
- '.tif' => 'image/tiff',
- '.tiff' => 'image/tiff',
- '.txt' => 'text/plain',
- '.uls' => 'text/iuls',
- '.vcf' => 'text/x-vcard',
- '.vdx' => 'application/vnd.ms-visio.viewer',
- '.vsd' => 'application/vnd.ms-visio.viewer',
- '.vss' => 'application/vnd.ms-visio.viewer',
- '.vst' => 'application/vnd.ms-visio.viewer',
- '.vsx' => 'application/vnd.ms-visio.viewer',
- '.vtx' => 'application/vnd.ms-visio.viewer',
- '.wav' => 'audio/wav',
- '.wax' => 'audio/x-ms-wax',
- '.wbk' => 'application/msword',
- '.wdp' => 'image/vnd.ms-photo',
- '.wiz' => 'application/msword',
- '.wm' => 'video/x-ms-wm',
- '.wma' => 'audio/x-ms-wma',
- '.wmd' => 'application/x-ms-wmd',
- '.wmv' => 'video/x-ms-wmv',
- '.wmx' => 'video/x-ms-wmx',
- '.wmz' => 'application/x-ms-wmz',
- '.wpl' => 'application/vnd.ms-wpl',
- '.wsc' => 'text/scriptlet',
- '.wvx' => 'video/x-ms-wvx',
- '.xaml' => 'application/xaml+xml',
- '.xbap' => 'application/x-ms-xbap',
- '.xdp' => 'application/vnd.adobe.xdp+xml',
- '.xfdf' => 'application/vnd.adobe.xfdf',
- '.xht' => 'application/xhtml+xml',
- '.xhtml' => 'application/xhtml+xml',
- '.xla' => 'application/vnd.ms-excel',
- '.xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
- '.xlk' => 'application/vnd.ms-excel',
- '.xll' => 'application/vnd.ms-excel',
- '.xlm' => 'application/vnd.ms-excel',
- '.xls' => 'application/vnd.ms-excel',
- '.xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
- '.xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',
- '.xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
- '.xlt' => 'application/vnd.ms-excel',
- '.xltm' => 'application/vnd.ms-excel.template.macroEnabled.12',
- '.xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
- '.xlw' => 'application/vnd.ms-excel',
- '.xml' => 'text/xml',
- '.xps' => 'application/vnd.ms-xpsdocument',
- '.xsl' => 'text/xml',
- );
-
- /**
- * IE versions which have been analysed to bring you this class, and for
- * which some substantive difference exists. These will appear as keys
- * in the return value of getRealMimesFromData(). The names are chosen to sort correctly.
- */
- protected $versions = array( 'ie05', 'ie06', 'ie07', 'ie07.strict', 'ie07.nohtml' );
-
- /**
- * Type table with versions expanded
- */
- protected $typeTable = array();
-
- /** constructor */
- function __construct() {
- // Construct versioned type arrays from the base type array plus additions
- $types = $this->baseTypeTable;
- foreach ( $this->versions as $version ) {
- if ( isset( $this->addedTypes[$version] ) ) {
- foreach ( $this->addedTypes[$version] as $format => $addedTypes ) {
- $types[$format] = array_merge( $types[$format], $addedTypes );
- }
- }
- $this->typeTable[$version] = $types;
- }
- }
-
- /**
- * Get the MIME types from getMimesFromData(), but convert the result from IE's
- * idiosyncratic private types into something other apps will understand.
- *
- * @param string $fileName the file name (unused at present)
- * @param string $chunk the first 256 bytes of the file
- * @param string $proposed the MIME type proposed by the server
- *
- * @return Array: map of IE version to detected MIME type
- */
- public function getRealMimesFromData( $fileName, $chunk, $proposed ) {
- $types = $this->getMimesFromData( $fileName, $chunk, $proposed );
- $types = array_map( array( $this, 'translateMimeType' ), $types );
- return $types;
- }
-
- /**
- * Translate a MIME type from IE's idiosyncratic private types into
- * more commonly understood type strings
- * @param $type
- * @return string
- */
- public function translateMimeType( $type ) {
- static $table = array(
- 'image/pjpeg' => 'image/jpeg',
- 'image/x-png' => 'image/png',
- 'image/x-wmf' => 'application/x-msmetafile',
- 'image/bmp' => 'image/x-bmp',
- 'application/x-zip-compressed' => 'application/zip',
- 'application/x-compressed' => 'application/x-compress',
- 'application/x-gzip-compressed' => 'application/x-gzip',
- 'audio/mid' => 'audio/midi',
- );
- if ( isset( $table[$type] ) ) {
- $type = $table[$type];
- }
- return $type;
- }
-
- /**
- * Get the untranslated MIME types for all known versions
- *
- * @param string $fileName the file name (unused at present)
- * @param string $chunk the first 256 bytes of the file
- * @param string $proposed the MIME type proposed by the server
- *
- * @return Array: map of IE version to detected MIME type
- */
- public function getMimesFromData( $fileName, $chunk, $proposed ) {
- $types = array();
- foreach ( $this->versions as $version ) {
- $types[$version] = $this->getMimeTypeForVersion( $version, $fileName, $chunk, $proposed );
- }
- return $types;
- }
-
- /**
- * Get the MIME type for a given named version
- * @param $version
- * @param $fileName
- * @param $chunk
- * @param $proposed
- * @return bool|string
- */
- protected function getMimeTypeForVersion( $version, $fileName, $chunk, $proposed ) {
- // Strip text after a semicolon
- $semiPos = strpos( $proposed, ';' );
- if ( $semiPos !== false ) {
- $proposed = substr( $proposed, 0, $semiPos );
- }
-
- $proposedFormat = $this->getDataFormat( $version, $proposed );
- if ( $proposedFormat == 'unknown'
- && $proposed != 'multipart/mixed'
- && $proposed != 'multipart/x-mixed-replace' )
- {
- return $proposed;
- }
- if ( strval( $chunk ) === '' ) {
- return $proposed;
- }
-
- // Truncate chunk at 255 bytes
- $chunk = substr( $chunk, 0, 255 );
-
- // IE does the Check*Headers() calls last, and instead does the following image
- // type checks by directly looking for the magic numbers. What I do here should
- // have the same effect since the magic number checks are identical in both cases.
- $result = $this->sampleData( $version, $chunk );
- $sampleFound = $result['found'];
- $counters = $result['counters'];
- $binaryType = $this->checkBinaryHeaders( $version, $chunk );
- $textType = $this->checkTextHeaders( $version, $chunk );
-
- if ( $proposed == 'text/html' && isset( $sampleFound['html'] ) ) {
- return 'text/html';
- }
- if ( $proposed == 'image/gif' && $binaryType == 'image/gif' ) {
- return 'image/gif';
- }
- if ( ( $proposed == 'image/pjpeg' || $proposed == 'image/jpeg' )
- && $binaryType == 'image/pjpeg' )
- {
- return $proposed;
- }
- // PNG check added in IE 7
- if ( $version >= 'ie07'
- && ( $proposed == 'image/x-png' || $proposed == 'image/png' )
- && $binaryType == 'image/x-png' )
- {
- return $proposed;
- }
-
- // CDF was removed in IE 7 so it won't be in $sampleFound for later versions
- if ( isset( $sampleFound['cdf'] ) ) {
- return 'application/x-cdf';
- }
-
- // RSS and Atom were added in IE 7 so they won't be in $sampleFound for
- // previous versions
- if ( isset( $sampleFound['rss'] ) ) {
- return 'application/rss+xml';
- }
- if ( isset( $sampleFound['rdf-tag'] )
- && isset( $sampleFound['rdf-url'] )
- && isset( $sampleFound['rdf-purl'] ) )
- {
- return 'application/rss+xml';
- }
- if ( isset( $sampleFound['atom'] ) ) {
- return 'application/atom+xml';
- }
-
- if ( isset( $sampleFound['xml'] ) ) {
- // TODO: I'm not sure under what circumstances this flag is enabled
- if ( strpos( $version, 'strict' ) !== false ) {
- if ( $proposed == 'text/html' || $proposed == 'text/xml' ) {
- return 'text/xml';
- }
- } else {
- return 'text/xml';
- }
- }
- if ( isset( $sampleFound['html'] ) ) {
- // TODO: I'm not sure under what circumstances this flag is enabled
- if ( strpos( $version, 'nohtml' ) !== false ) {
- if ( $proposed == 'text/plain' ) {
- return 'text/html';
- }
- } else {
- return 'text/html';
- }
- }
- if ( isset( $sampleFound['xbm'] ) ) {
- return 'image/x-bitmap';
- }
- if ( isset( $sampleFound['binhex'] ) ) {
- return 'application/macbinhex40';
- }
- if ( isset( $sampleFound['scriptlet'] ) ) {
- if ( strpos( $version, 'strict' ) !== false ) {
- if ( $proposed == 'text/plain' || $proposed == 'text/scriptlet' ) {
- return 'text/scriptlet';
- }
- } else {
- return 'text/scriptlet';
- }
- }
-
- // Freaky heuristics to determine if the data is text or binary
- // The heuristic is of course broken for non-ASCII text
- if ( $counters['ctrl'] != 0 && ( $counters['ff'] + $counters['low'] )
- < ( $counters['ctrl'] + $counters['high'] ) * 16 )
- {
- $kindOfBinary = true;
- $type = $binaryType ? $binaryType : $textType;
- if ( $type === false ) {
- $type = 'application/octet-stream';
- }
- } else {
- $kindOfBinary = false;
- $type = $textType ? $textType : $binaryType;
- if ( $type === false ) {
- $type = 'text/plain';
- }
- }
-
- // Check if the output format is ambiguous
- // This generally means that detection failed, real types aren't ambiguous
- $detectedFormat = $this->getDataFormat( $version, $type );
- if ( $detectedFormat != 'ambiguous' ) {
- return $type;
- }
-
- if ( $proposedFormat != 'ambiguous' ) {
- // FormatAgreesWithData()
- if ( $proposedFormat == 'text' && !$kindOfBinary ) {
- return $proposed;
- }
- if ( $proposedFormat == 'binary' && $kindOfBinary ) {
- return $proposed;
- }
- if ( $proposedFormat == 'html' ) {
- return $proposed;
- }
- }
-
- // Find a MIME type by searching the registry for the file extension.
- $dotPos = strrpos( $fileName, '.' );
- if ( $dotPos === false ) {
- return $type;
- }
- $ext = substr( $fileName, $dotPos );
- if ( isset( $this->registry[$ext] ) ) {
- return $this->registry[$ext];
- }
-
- // TODO: If the extension has an application registered to it, IE will return
- // application/octet-stream. We'll skip that, so we could erroneously
- // return text/plain or application/x-netcdf where application/octet-stream
- // would be correct.
-
- return $type;
- }
-
- /**
- * Check for text headers at the start of the chunk
- * Confirmed same in 5 and 7.
- * @param $version
- * @param $chunk
- * @return bool|string
- */
- private function checkTextHeaders( $version, $chunk ) {
- $chunk2 = substr( $chunk, 0, 2 );
- $chunk4 = substr( $chunk, 0, 4 );
- $chunk5 = substr( $chunk, 0, 5 );
- if ( $chunk4 == '%PDF' ) {
- return 'application/pdf';
- }
- if ( $chunk2 == '%!' ) {
- return 'application/postscript';
- }
- if ( $chunk5 == '{\\rtf' ) {
- return 'text/richtext';
- }
- if ( $chunk5 == 'begin' ) {
- return 'application/base64';
- }
- return false;
- }
-
- /**
- * Check for binary headers at the start of the chunk
- * Confirmed same in 5 and 7.
- * @param $version
- * @param $chunk
- * @return bool|string
- */
- private function checkBinaryHeaders( $version, $chunk ) {
- $chunk2 = substr( $chunk, 0, 2 );
- $chunk3 = substr( $chunk, 0, 3 );
- $chunk4 = substr( $chunk, 0, 4 );
- $chunk5 = substr( $chunk, 0, 5 );
- $chunk5uc = strtoupper( $chunk5 );
- $chunk8 = substr( $chunk, 0, 8 );
- if ( $chunk5uc == 'GIF87' || $chunk5uc == 'GIF89' ) {
- return 'image/gif';
- }
- if ( $chunk2 == "\xff\xd8" ) {
- return 'image/pjpeg'; // actually plain JPEG but this is what IE returns
- }
-
- if ( $chunk2 == 'BM'
- && substr( $chunk, 6, 2 ) == "\000\000"
- && substr( $chunk, 8, 2 ) == "\000\000" )
- {
- return 'image/bmp'; // another non-standard MIME
- }
- if ( $chunk4 == 'RIFF'
- && substr( $chunk, 8, 4 ) == 'WAVE' )
- {
- return 'audio/wav';
- }
- // These were integer literals in IE
- // Perhaps the author was not sure what the target endianness was
- if ( $chunk4 == ".sd\000"
- || $chunk4 == ".snd"
- || $chunk4 == "\000ds."
- || $chunk4 == "dns." )
- {
- return 'audio/basic';
- }
- if ( $chunk3 == "MM\000" ) {
- return 'image/tiff';
- }
- if ( $chunk2 == 'MZ' ) {
- return 'application/x-msdownload';
- }
- if ( $chunk8 == "\x89PNG\x0d\x0a\x1a\x0a" ) {
- return 'image/x-png'; // [sic]
- }
- if ( strlen( $chunk ) >= 5 ) {
- $byte2 = ord( $chunk[2] );
- $byte4 = ord( $chunk[4] );
- if ( $byte2 >= 3 && $byte2 <= 31 && $byte4 == 0 && $chunk2 == 'JG' ) {
- return 'image/x-jg';
- }
- }
- // More endian confusion?
- if ( $chunk4 == 'MROF' ) {
- return 'audio/x-aiff';
- }
- $chunk4_8 = substr( $chunk, 8, 4 );
- if ( $chunk4 == 'FORM' && ( $chunk4_8 == 'AIFF' || $chunk4_8 == 'AIFC' ) ) {
- return 'audio/x-aiff';
- }
- if ( $chunk4 == 'RIFF' && $chunk4_8 == 'AVI ' ) {
- return 'video/avi';
- }
- if ( $chunk4 == "\x00\x00\x01\xb3" || $chunk4 == "\x00\x00\x01\xba" ) {
- return 'video/mpeg';
- }
- if ( $chunk4 == "\001\000\000\000"
- && substr( $chunk, 40, 4 ) == ' EMF' )
- {
- return 'image/x-emf';
- }
- if ( $chunk4 == "\xd7\xcd\xc6\x9a" ) {
- return 'image/x-wmf';
- }
- if ( $chunk4 == "\xca\xfe\xba\xbe" ) {
- return 'application/java';
- }
- if ( $chunk2 == 'PK' ) {
- return 'application/x-zip-compressed';
- }
- if ( $chunk2 == "\x1f\x9d" ) {
- return 'application/x-compressed';
- }
- if ( $chunk2 == "\x1f\x8b" ) {
- return 'application/x-gzip-compressed';
- }
- // Skip redundant check for ZIP
- if ( $chunk5 == "MThd\000" ) {
- return 'audio/mid';
- }
- if ( $chunk4 == '%PDF' ) {
- return 'application/pdf';
- }
- return false;
- }
-
- /**
- * Do heuristic checks on the bulk of the data sample.
- * Search for HTML tags.
- * @param $version
- * @param $chunk
- * @return array
- */
- protected function sampleData( $version, $chunk ) {
- $found = array();
- $counters = array(
- 'ctrl' => 0,
- 'high' => 0,
- 'low' => 0,
- 'lf' => 0,
- 'cr' => 0,
- 'ff' => 0
- );
- $htmlTags = array(
- 'html',
- 'head',
- 'title',
- 'body',
- 'script',
- 'a href',
- 'pre',
- 'img',
- 'plaintext',
- 'table'
- );
- $rdfUrl = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
- $rdfPurl = 'http://purl.org/rss/1.0/';
- $xbmMagic1 = '#define';
- $xbmMagic2 = '_width';
- $xbmMagic3 = '_bits';
- $binhexMagic = 'converted with BinHex';
- $chunkLength = strlen( $chunk );
-
- for ( $offset = 0; $offset < $chunkLength; $offset++ ) {
- $curChar = $chunk[$offset];
- if ( $curChar == "\x0a" ) {
- $counters['lf']++;
- continue;
- } elseif ( $curChar == "\x0d" ) {
- $counters['cr']++;
- continue;
- } elseif ( $curChar == "\x0c" ) {
- $counters['ff']++;
- continue;
- } elseif ( $curChar == "\t" ) {
- $counters['low']++;
- continue;
- } elseif ( ord( $curChar ) < 32 ) {
- $counters['ctrl']++;
- continue;
- } elseif ( ord( $curChar ) >= 128 ) {
- $counters['high']++;
- continue;
- }
-
- $counters['low']++;
- if ( $curChar == '<' ) {
- // XML
- $remainder = substr( $chunk, $offset + 1 );
- if ( !strncasecmp( $remainder, '?XML', 4 ) ) {
- $nextChar = substr( $chunk, $offset + 5, 1 );
- if ( $nextChar == ':' || $nextChar == ' ' || $nextChar == "\t" ) {
- $found['xml'] = true;
- }
- }
- // Scriptlet (JSP)
- if ( !strncasecmp( $remainder, 'SCRIPTLET', 9 ) ) {
- $found['scriptlet'] = true;
- break;
- }
- // HTML
- foreach ( $htmlTags as $tag ) {
- if ( !strncasecmp( $remainder, $tag, strlen( $tag ) ) ) {
- $found['html'] = true;
- }
- }
- // Skip broken check for additional tags (HR etc.)
-
- // CHANNEL replaced by RSS, RDF and FEED in IE 7
- if ( $version < 'ie07' ) {
- if ( !strncasecmp( $remainder, 'CHANNEL', 7 ) ) {
- $found['cdf'] = true;
- }
- } else {
- // RSS
- if ( !strncasecmp( $remainder, 'RSS', 3 ) ) {
- $found['rss'] = true;
- break; // return from SampleData
- }
- if ( !strncasecmp( $remainder, 'rdf:RDF', 7 ) ) {
- $found['rdf-tag'] = true;
- // no break
- }
- if ( !strncasecmp( $remainder, 'FEED', 4 ) ) {
- $found['atom'] = true;
- break;
- }
- }
- continue;
- }
- // Skip broken check for -->
-
- // RSS URL checks
- // For some reason both URLs must appear before it is recognised
- $remainder = substr( $chunk, $offset );
- if ( !strncasecmp( $remainder, $rdfUrl, strlen( $rdfUrl ) ) ) {
- $found['rdf-url'] = true;
- if ( isset( $found['rdf-tag'] )
- && isset( $found['rdf-purl'] ) ) // [sic]
- {
- break;
- }
- continue;
- }
-
- if ( !strncasecmp( $remainder, $rdfPurl, strlen( $rdfPurl ) ) ) {
- if ( isset( $found['rdf-tag'] )
- && isset( $found['rdf-url'] ) ) // [sic]
- {
- break;
- }
- continue;
- }
-
- // XBM checks
- if ( !strncasecmp( $remainder, $xbmMagic1, strlen( $xbmMagic1 ) ) ) {
- $found['xbm1'] = true;
- continue;
- }
- if ( $curChar == '_' ) {
- if ( isset( $found['xbm2'] ) ) {
- if ( !strncasecmp( $remainder, $xbmMagic3, strlen( $xbmMagic3 ) ) ) {
- $found['xbm'] = true;
- break;
- }
- } elseif ( isset( $found['xbm1'] ) ) {
- if ( !strncasecmp( $remainder, $xbmMagic2, strlen( $xbmMagic2 ) ) ) {
- $found['xbm2'] = true;
- }
- }
- }
-
- // BinHex
- if ( !strncmp( $remainder, $binhexMagic, strlen( $binhexMagic ) ) ) {
- $found['binhex'] = true;
- }
- }
- return array( 'found' => $found, 'counters' => $counters );
- }
-
- /**
- * @param $version
- * @param $type
- * @return int|string
- */
- protected function getDataFormat( $version, $type ) {
- $types = $this->typeTable[$version];
- if ( $type == '(null)' || strval( $type ) === '' ) {
- return 'ambiguous';
- }
- foreach ( $types as $format => $list ) {
- if ( in_array( $type, $list ) ) {
- return $format;
- }
- }
- return 'unknown';
- }
-}
diff --git a/includes/libs/IEUrlExtension.php b/includes/libs/IEUrlExtension.php
deleted file mode 100644
index 49d05d4b..00000000
--- a/includes/libs/IEUrlExtension.php
+++ /dev/null
@@ -1,271 +0,0 @@
-<?php
-/**
- * Checks for validity of requested URL's extension.
- *
- * 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
- */
-
-/**
- * Internet Explorer derives a cache filename from a URL, and then in certain
- * circumstances, uses the extension of the resulting file to determine the
- * content type of the data, ignoring the Content-Type header.
- *
- * This can be a problem, especially when non-HTML content is sent by MediaWiki,
- * and Internet Explorer interprets it as HTML, exposing an XSS vulnerability.
- *
- * Usually the script filename (e.g. api.php) is present in the URL, and this
- * makes Internet Explorer think the extension is a harmless script extension.
- * But Internet Explorer 6 and earlier allows the script extension to be
- * obscured by encoding the dot as "%2E".
- *
- * This class contains functions which help in detecting and dealing with this
- * situation.
- *
- * Checking the URL for a bad extension is somewhat complicated due to the fact
- * that CGI doesn't provide a standard method to determine the URL. Instead it
- * is necessary to pass a subset of $_SERVER variables, which we then attempt
- * to use to guess parts of the URL.
- */
-class IEUrlExtension {
- /**
- * Check a subset of $_SERVER (or the whole of $_SERVER if you like)
- * to see if it indicates that the request was sent with a bad file
- * extension. Returns true if the request should be denied or modified,
- * false otherwise. The relevant $_SERVER elements are:
- *
- * - SERVER_SOFTWARE
- * - REQUEST_URI
- * - QUERY_STRING
- * - PATH_INFO
- *
- * If the a variable is unset in $_SERVER, it should be unset in $vars.
- *
- * @param array $vars A subset of $_SERVER.
- * @param array $extWhitelist Extensions which are allowed, assumed harmless.
- * @return bool
- */
- public static function areServerVarsBad( $vars, $extWhitelist = array() ) {
- // Check QUERY_STRING or REQUEST_URI
- if ( isset( $vars['SERVER_SOFTWARE'] )
- && isset( $vars['REQUEST_URI'] )
- && self::haveUndecodedRequestUri( $vars['SERVER_SOFTWARE'] ) )
- {
- $urlPart = $vars['REQUEST_URI'];
- } elseif ( isset( $vars['QUERY_STRING'] ) ) {
- $urlPart = $vars['QUERY_STRING'];
- } else {
- $urlPart = '';
- }
-
- if ( self::isUrlExtensionBad( $urlPart, $extWhitelist ) ) {
- return true;
- }
-
- // Some servers have PATH_INFO but not REQUEST_URI, so we check both
- // to be on the safe side.
- if ( isset( $vars['PATH_INFO'] )
- && self::isUrlExtensionBad( $vars['PATH_INFO'], $extWhitelist ) )
- {
- return true;
- }
-
- // All checks passed
- return false;
- }
-
- /**
- * Given a right-hand portion of a URL, determine whether IE would detect
- * a potentially harmful file extension.
- *
- * @param string $urlPart The right-hand portion of a URL
- * @param array $extWhitelist An array of file extensions which may occur in this
- * URL, and which should be allowed.
- * @return bool
- */
- public static function isUrlExtensionBad( $urlPart, $extWhitelist = array() ) {
- if ( strval( $urlPart ) === '' ) {
- return false;
- }
-
- $extension = self::findIE6Extension( $urlPart );
- if ( strval( $extension ) === '' ) {
- // No extension or empty extension
- return false;
- }
-
- if ( in_array( $extension, array( 'php', 'php5' ) ) ) {
- // Script extension, OK
- return false;
- }
- if ( in_array( $extension, $extWhitelist ) ) {
- // Whitelisted extension
- return false;
- }
-
- if ( !preg_match( '/^[a-zA-Z0-9_-]+$/', $extension ) ) {
- // Non-alphanumeric extension, unlikely to be registered.
- //
- // The regex above is known to match all registered file extensions
- // in a default Windows XP installation. It's important to allow
- // extensions with ampersands and percent signs, since that reduces
- // the number of false positives substantially.
- return false;
- }
-
- // Possibly bad extension
- return true;
- }
-
- /**
- * Returns a variant of $url which will pass isUrlExtensionBad() but has the
- * same GET parameters, or false if it can't figure one out.
- * @param $url
- * @param $extWhitelist array
- * @return bool|string
- */
- public static function fixUrlForIE6( $url, $extWhitelist = array() ) {
- $questionPos = strpos( $url, '?' );
- if ( $questionPos === false ) {
- $beforeQuery = $url . '?';
- $query = '';
- } elseif ( $questionPos === strlen( $url ) - 1 ) {
- $beforeQuery = $url;
- $query = '';
- } else {
- $beforeQuery = substr( $url, 0, $questionPos + 1 );
- $query = substr( $url, $questionPos + 1 );
- }
-
- // Multiple question marks cause problems. Encode the second and
- // subsequent question mark.
- $query = str_replace( '?', '%3E', $query );
- // Append an invalid path character so that IE6 won't see the end of the
- // query string as an extension
- $query .= '&*';
- // Put the URL back together
- $url = $beforeQuery . $query;
- if ( self::isUrlExtensionBad( $url, $extWhitelist ) ) {
- // Avoid a redirect loop
- return false;
- }
- return $url;
- }
-
- /**
- * Determine what extension IE6 will infer from a certain query string.
- * If the URL has an extension before the question mark, IE6 will use
- * that and ignore the query string, but per the comment at
- * isPathInfoBad() we don't have a reliable way to determine the URL,
- * so isPathInfoBad() just passes in the query string for $url.
- * All entry points have safe extensions (php, php5) anyway, so
- * checking the query string is possibly overly paranoid but never
- * insecure.
- *
- * The criteria for finding an extension are as follows:
- * - a possible extension is a dot followed by one or more characters not
- * in <>\"/:|?.#
- * - if we find a possible extension followed by the end of the string or
- * a #, that's our extension
- * - if we find a possible extension followed by a ?, that's our extension
- * - UNLESS it's exe, dll or cgi, in which case we ignore it and continue
- * searching for another possible extension
- * - if we find a possible extension followed by a dot or another illegal
- * character, we ignore it and continue searching
- *
- * @param string $url URL
- * @return mixed Detected extension (string), or false if none found
- */
- public static function findIE6Extension( $url ) {
- $pos = 0;
- $hashPos = strpos( $url, '#' );
- if ( $hashPos !== false ) {
- $urlLength = $hashPos;
- } else {
- $urlLength = strlen( $url );
- }
- $remainingLength = $urlLength;
- while ( $remainingLength > 0 ) {
- // Skip ahead to the next dot
- $pos += strcspn( $url, '.', $pos, $remainingLength );
- if ( $pos >= $urlLength ) {
- // End of string, we're done
- return false;
- }
-
- // We found a dot. Skip past it
- $pos++;
- $remainingLength = $urlLength - $pos;
-
- // Check for illegal characters in our prospective extension,
- // or for another dot
- $nextPos = $pos + strcspn( $url, "<>\\\"/:|?*.", $pos, $remainingLength );
- if ( $nextPos >= $urlLength ) {
- // No illegal character or next dot
- // We have our extension
- return substr( $url, $pos, $urlLength - $pos );
- }
- if ( $url[$nextPos] === '?' ) {
- // We've found a legal extension followed by a question mark
- // If the extension is NOT exe, dll or cgi, return it
- $extension = substr( $url, $pos, $nextPos - $pos );
- if ( strcasecmp( $extension, 'exe' ) && strcasecmp( $extension, 'dll' ) &&
- strcasecmp( $extension, 'cgi' ) )
- {
- return $extension;
- }
- // Else continue looking
- }
- // We found an illegal character or another dot
- // Skip to that character and continue the loop
- $pos = $nextPos;
- $remainingLength = $urlLength - $pos;
- }
- return false;
- }
-
- /**
- * When passed the value of $_SERVER['SERVER_SOFTWARE'], this function
- * returns true if that server is known to have a REQUEST_URI variable
- * with %2E not decoded to ".". On such a server, it is possible to detect
- * whether the script filename has been obscured.
- *
- * The function returns false if the server is not known to have this
- * behavior. Microsoft IIS in particular is known to decode escaped script
- * filenames.
- *
- * SERVER_SOFTWARE typically contains either a plain string such as "Zeus",
- * or a specification in the style of a User-Agent header, such as
- * "Apache/1.3.34 (Unix) mod_ssl/2.8.25 OpenSSL/0.9.8a PHP/4.4.2"
- *
- * @param $serverSoftware
- * @return bool
- *
- */
- public static function haveUndecodedRequestUri( $serverSoftware ) {
- static $whitelist = array(
- 'Apache',
- 'Zeus',
- 'LiteSpeed' );
- if ( preg_match( '/^(.*?)($|\/| )/', $serverSoftware, $m ) ) {
- return in_array( $m[1], $whitelist );
- } else {
- return false;
- }
- }
-
-}
diff --git a/includes/search/SearchMssql.php b/includes/search/SearchMssql.php
deleted file mode 100644
index 0d7970de..00000000
--- a/includes/search/SearchMssql.php
+++ /dev/null
@@ -1,210 +0,0 @@
-<?php
-/**
- * Mssql search engine
- *
- * 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 Search
- */
-
-/**
- * Search engine hook base class for Mssql (ConText).
- * @ingroup Search
- */
-class SearchMssql extends SearchDatabase {
- /**
- * Perform a full text search query and return a result set.
- *
- * @param string $term Raw search term
- * @return SqlSearchResultSet
- * @access public
- */
- function searchText( $term ) {
- $resultSet = $this->db->query( $this->getQuery( $this->filter( $term ), true ) );
- return new SqlSearchResultSet( $resultSet, $this->searchTerms );
- }
-
- /**
- * Perform a title-only search query and return a result set.
- *
- * @param string $term Raw search term
- * @return SqlSearchResultSet
- * @access public
- */
- function searchTitle( $term ) {
- $resultSet = $this->db->query( $this->getQuery( $this->filter( $term ), false ) );
- return new SqlSearchResultSet( $resultSet, $this->searchTerms );
- }
-
- /**
- * Return a partial WHERE clause to limit the search to the given namespaces
- *
- * @return string
- * @private
- */
- function queryNamespaces() {
- $namespaces = implode( ',', $this->namespaces );
- if ( $namespaces == '' ) {
- $namespaces = '0';
- }
- return 'AND page_namespace IN (' . $namespaces . ')';
- }
-
- /**
- * Return a LIMIT clause to limit results on the query.
- *
- * @param string $sql
- *
- * @return string
- */
- function queryLimit( $sql ) {
- return $this->db->limitResult( $sql, $this->limit, $this->offset );
- }
-
- /**
- * Does not do anything for generic search engine
- * subclasses may define this though
- *
- * @param string $filteredTerm
- * @param bool $fulltext
- * @return string
- */
- function queryRanking( $filteredTerm, $fulltext ) {
- return ' ORDER BY ftindex.[RANK] DESC'; // return ' ORDER BY score(1)';
- }
-
- /**
- * Construct the full SQL query to do the search.
- * The guts shoulds be constructed in queryMain()
- *
- * @param string $filteredTerm
- * @param bool $fulltext
- * @return string
- */
- function getQuery( $filteredTerm, $fulltext ) {
- return $this->queryLimit( $this->queryMain( $filteredTerm, $fulltext ) . ' ' .
- $this->queryNamespaces() . ' ' .
- $this->queryRanking( $filteredTerm, $fulltext ) . ' ' );
- }
-
- /**
- * Picks which field to index on, depending on what type of query.
- *
- * @param bool $fulltext
- * @return string
- */
- function getIndexField( $fulltext ) {
- return $fulltext ? 'si_text' : 'si_title';
- }
-
- /**
- * Get the base part of the search query.
- *
- * @param string $filteredTerm
- * @param bool $fulltext
- * @return string
- * @private
- */
- function queryMain( $filteredTerm, $fulltext ) {
- $match = $this->parseQuery( $filteredTerm, $fulltext );
- $page = $this->db->tableName( 'page' );
- $searchindex = $this->db->tableName( 'searchindex' );
-
- return 'SELECT page_id, page_namespace, page_title, ftindex.[RANK]' .
- "FROM $page,FREETEXTTABLE($searchindex , $match, LANGUAGE 'English') as ftindex " .
- 'WHERE page_id=ftindex.[KEY] ';
- }
-
- /** @todo document
- * @param string $filteredText
- * @param bool $fulltext
- * @return string
- */
- function parseQuery( $filteredText, $fulltext ) {
- global $wgContLang;
- $lc = $this->legalSearchChars();
- $this->searchTerms = array();
-
- # @todo FIXME: This doesn't handle parenthetical expressions.
- $m = array();
- $q = array();
-
- if ( preg_match_all( '/([-+<>~]?)(([' . $lc . ']+)(\*?)|"[^"]*")/',
- $filteredText, $m, PREG_SET_ORDER ) ) {
- foreach ( $m as $terms ) {
- $q[] = $terms[1] . $wgContLang->normalizeForSearch( $terms[2] );
-
- if ( !empty( $terms[3] ) ) {
- $regexp = preg_quote( $terms[3], '/' );
- if ( $terms[4] ) {
- $regexp .= "[0-9A-Za-z_]+";
- }
- } else {
- $regexp = preg_quote( str_replace( '"', '', $terms[2] ), '/' );
- }
- $this->searchTerms[] = $regexp;
- }
- }
-
- $searchon = $this->db->addQuotes( join( ',', $q ) );
- $field = $this->getIndexField( $fulltext );
- return "$field, $searchon";
- }
-
- /**
- * Create or update the search index record for the given page.
- * Title and text should be pre-processed.
- *
- * @param int $id
- * @param string $title
- * @param string $text
- * @return bool|ResultWrapper
- */
- function update( $id, $title, $text ) {
- // We store the column data as UTF-8 byte order marked binary stream
- // because we are invoking the plain text IFilter on it so that, and we want it
- // to properly decode the stream as UTF-8. SQL doesn't support UTF8 as a data type
- // but the indexer will correctly handle it by this method. Since all we are doing
- // is passing this data to the indexer and never retrieving it via PHP, this will save space
- $table = $this->db->tableName( 'searchindex' );
- $utf8bom = '0xEFBBBF';
- $si_title = $utf8bom . bin2hex( $title );
- $si_text = $utf8bom . bin2hex( $text );
- $sql = "DELETE FROM $table WHERE si_page = $id;";
- $sql .= "INSERT INTO $table (si_page, si_title, si_text) VALUES ($id, $si_title, $si_text)";
- return $this->db->query( $sql, 'SearchMssql::update' );
- }
-
- /**
- * Update a search index record's title only.
- * Title should be pre-processed.
- *
- * @param int $id
- * @param string $title
- * @return bool|ResultWrapper
- */
- function updateTitle( $id, $title ) {
- $table = $this->db->tableName( 'searchindex' );
-
- // see update for why we are using the utf8bom
- $utf8bom = '0xEFBBBF';
- $si_title = $utf8bom . bin2hex( $title );
- $sql = "DELETE FROM $table WHERE si_page = $id;";
- $sql .= "INSERT INTO $table (si_page, si_title, si_text) VALUES ($id, $si_title, 0x00)";
- return $this->db->query( $sql, 'SearchMssql::updateTitle' );
- }
-}
diff --git a/includes/search/SearchOracle.php b/includes/search/SearchOracle.php
deleted file mode 100644
index 58211484..00000000
--- a/includes/search/SearchOracle.php
+++ /dev/null
@@ -1,273 +0,0 @@
-<?php
-/**
- * Oracle search engine
- *
- * Copyright © 2004 Brion Vibber <brion@pobox.com>
- * https://www.mediawiki.org/
- *
- * 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 Search
- */
-
-/**
- * Search engine hook base class for Oracle (ConText).
- * @ingroup Search
- */
-class SearchOracle extends SearchDatabase {
- private $reservedWords = array(
- 'ABOUT' => 1,
- 'ACCUM' => 1,
- 'AND' => 1,
- 'BT' => 1,
- 'BTG' => 1,
- 'BTI' => 1,
- 'BTP' => 1,
- 'FUZZY' => 1,
- 'HASPATH' => 1,
- 'INPATH' => 1,
- 'MINUS' => 1,
- 'NEAR' => 1,
- 'NOT' => 1,
- 'NT' => 1,
- 'NTG' => 1,
- 'NTI' => 1,
- 'NTP' => 1,
- 'OR' => 1,
- 'PT' => 1,
- 'RT' => 1,
- 'SQE' => 1,
- 'SYN' => 1,
- 'TR' => 1,
- 'TRSYN' => 1,
- 'TT' => 1,
- 'WITHIN' => 1,
- );
-
- /**
- * Perform a full text search query and return a result set.
- *
- * @param string $term Raw search term
- * @return SqlSearchResultSet
- */
- function searchText( $term ) {
- if ( $term == '' ) {
- return new SqlSearchResultSet( false, '' );
- }
-
- $resultSet = $this->db->query( $this->getQuery( $this->filter( $term ), true ) );
- return new SqlSearchResultSet( $resultSet, $this->searchTerms );
- }
-
- /**
- * Perform a title-only search query and return a result set.
- *
- * @param string $term Raw search term
- * @return SqlSearchResultSet
- */
- function searchTitle( $term ) {
- if ( $term == '' ) {
- return new SqlSearchResultSet( false, '' );
- }
-
- $resultSet = $this->db->query( $this->getQuery( $this->filter( $term ), false ) );
- return new SqlSearchResultSet( $resultSet, $this->searchTerms );
- }
-
- /**
- * Return a partial WHERE clause to limit the search to the given namespaces
- * @return string
- */
- function queryNamespaces() {
- if ( is_null( $this->namespaces ) ) {
- return '';
- }
- if ( !count( $this->namespaces ) ) {
- $namespaces = '0';
- } else {
- $namespaces = $this->db->makeList( $this->namespaces );
- }
- return 'AND page_namespace IN (' . $namespaces . ')';
- }
-
- /**
- * Return a LIMIT clause to limit results on the query.
- *
- * @param string $sql
- *
- * @return string
- */
- function queryLimit( $sql ) {
- return $this->db->limitResult( $sql, $this->limit, $this->offset );
- }
-
- /**
- * Does not do anything for generic search engine
- * subclasses may define this though
- *
- * @param string $filteredTerm
- * @param bool $fulltext
- * @return string
- */
- function queryRanking( $filteredTerm, $fulltext ) {
- return ' ORDER BY score(1)';
- }
-
- /**
- * Construct the full SQL query to do the search.
- * The guts shoulds be constructed in queryMain()
- * @param string $filteredTerm
- * @param bool $fulltext
- * @return string
- */
- function getQuery( $filteredTerm, $fulltext ) {
- return $this->queryLimit( $this->queryMain( $filteredTerm, $fulltext ) . ' ' .
- $this->queryNamespaces() . ' ' .
- $this->queryRanking( $filteredTerm, $fulltext ) . ' ' );
- }
-
- /**
- * Picks which field to index on, depending on what type of query.
- * @param bool $fulltext
- * @return string
- */
- function getIndexField( $fulltext ) {
- return $fulltext ? 'si_text' : 'si_title';
- }
-
- /**
- * Get the base part of the search query.
- *
- * @param string $filteredTerm
- * @param bool $fulltext
- * @return string
- */
- function queryMain( $filteredTerm, $fulltext ) {
- $match = $this->parseQuery( $filteredTerm, $fulltext );
- $page = $this->db->tableName( 'page' );
- $searchindex = $this->db->tableName( 'searchindex' );
- return 'SELECT page_id, page_namespace, page_title ' .
- "FROM $page,$searchindex " .
- 'WHERE page_id=si_page AND ' . $match;
- }
-
- /**
- * Parse a user input search string, and return an SQL fragment to be used
- * as part of a WHERE clause
- * @param string $filteredText
- * @param bool $fulltext
- * @return string
- */
- function parseQuery( $filteredText, $fulltext ) {
- global $wgContLang;
- $lc = $this->legalSearchChars();
- $this->searchTerms = array();
-
- # @todo FIXME: This doesn't handle parenthetical expressions.
- $m = array();
- $searchon = '';
- if ( preg_match_all( '/([-+<>~]?)(([' . $lc . ']+)(\*?)|"[^"]*")/',
- $filteredText, $m, PREG_SET_ORDER ) ) {
- foreach ( $m as $terms ) {
- // Search terms in all variant forms, only
- // apply on wiki with LanguageConverter
- $temp_terms = $wgContLang->autoConvertToAllVariants( $terms[2] );
- if ( is_array( $temp_terms ) ) {
- $temp_terms = array_unique( array_values( $temp_terms ) );
- foreach ( $temp_terms as $t ) {
- $searchon .= ( $terms[1] == '-' ? ' ~' : ' & ' ) . $this->escapeTerm( $t );
- }
- }
- else {
- $searchon .= ( $terms[1] == '-' ? ' ~' : ' & ' ) . $this->escapeTerm( $terms[2] );
- }
- if ( !empty( $terms[3] ) ) {
- $regexp = preg_quote( $terms[3], '/' );
- if ( $terms[4] ) {
- $regexp .= "[0-9A-Za-z_]+";
- }
- } else {
- $regexp = preg_quote( str_replace( '"', '', $terms[2] ), '/' );
- }
- $this->searchTerms[] = $regexp;
- }
- }
-
- $searchon = $this->db->addQuotes( ltrim( $searchon, ' &' ) );
- $field = $this->getIndexField( $fulltext );
- return " CONTAINS($field, $searchon, 1) > 0 ";
- }
-
- private function escapeTerm( $t ) {
- global $wgContLang;
- $t = $wgContLang->normalizeForSearch( $t );
- $t = isset( $this->reservedWords[strtoupper( $t )] ) ? '{' . $t . '}' : $t;
- $t = preg_replace( '/^"(.*)"$/', '($1)', $t );
- $t = preg_replace( '/([-&|])/', '\\\\$1', $t );
- return $t;
- }
-
- /**
- * Create or update the search index record for the given page.
- * Title and text should be pre-processed.
- *
- * @param int $id
- * @param string $title
- * @param string $text
- */
- function update( $id, $title, $text ) {
- $dbw = wfGetDB( DB_MASTER );
- $dbw->replace( 'searchindex',
- array( 'si_page' ),
- array(
- 'si_page' => $id,
- 'si_title' => $title,
- 'si_text' => $text
- ), 'SearchOracle::update' );
-
- // Sync the index
- // We need to specify the DB name (i.e. user/schema) here so that
- // it can work from the installer, where
- // ALTER SESSION SET CURRENT_SCHEMA = ...
- // was used.
- $dbw->query( "CALL ctx_ddl.sync_index(" .
- $dbw->addQuotes( $dbw->getDBname() . '.' . $dbw->tableName( 'si_text_idx', 'raw' ) ) . ")" );
- $dbw->query( "CALL ctx_ddl.sync_index(" .
- $dbw->addQuotes( $dbw->getDBname() . '.' . $dbw->tableName( 'si_title_idx', 'raw' ) ) . ")" );
- }
-
- /**
- * Update a search index record's title only.
- * Title should be pre-processed.
- *
- * @param int $id
- * @param string $title
- */
- function updateTitle( $id, $title ) {
- $dbw = wfGetDB( DB_MASTER );
-
- $dbw->update( 'searchindex',
- array( 'si_title' => $title ),
- array( 'si_page' => $id ),
- 'SearchOracle::updateTitle',
- array() );
- }
-
- public static function legalSearchChars() {
- return "\"" . parent::legalSearchChars();
- }
-}
diff --git a/maintenance/dictionary/mediawiki.dic b/maintenance/dictionary/mediawiki.dic
index 8e4e5314..fd67fa63 100644
--- a/maintenance/dictionary/mediawiki.dic
+++ b/maintenance/dictionary/mediawiki.dic
@@ -187,7 +187,6 @@ Mostlinkedcategories
Mostlinkedtemplates
Mostrevisions
Move
-Mssql
Mwstore
Myuploads
NEWPAGE
@@ -2495,7 +2494,6 @@ msgtext
msie
msmetafile
msnbot
-mssql
msvideo
msword
mtime
diff --git a/maintenance/mssql/archives/named_constraints.sql b/maintenance/mssql/archives/named_constraints.sql
deleted file mode 100644
index 94b77ea7..00000000
--- a/maintenance/mssql/archives/named_constraints.sql
+++ /dev/null
@@ -1,38 +0,0 @@
-DECLARE @fullyQualifiedTableName nvarchar(max),
-@tableName sysname,
-@fieldName sysname,
-@constr sysname,
-@constrNew sysname,
-@sqlcmd nvarchar(max),
-@sqlcreate nvarchar(max)
-
-SET @fullyQualifiedTableName = '/*_*//*$tableName*/'
-SET @tableName = '/*$tableName*/'
-SET @fieldName = '/*$fieldName*/'
-
-SELECT @constr = CONSTRAINT_NAME
-FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
-WHERE TABLE_NAME = @tableName
-AND CONSTRAINT_CATALOG = '/*$wgDBname*/'
-AND CONSTRAINT_SCHEMA = '/*$wgDBmwschema*/'
-AND CONSTRAINT_TYPE = 'CHECK'
-AND CONSTRAINT_NAME LIKE ('CK__' + left(@tableName,9) + '__' + left(@fieldName,5) + '%')
-
-SELECT @constrNew = CONSTRAINT_NAME
-FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
-WHERE TABLE_NAME = @tableName
-AND CONSTRAINT_CATALOG = '/*$wgDBname*/'
-AND CONSTRAINT_SCHEMA = '/*$wgDBmwschema*/'
-AND CONSTRAINT_TYPE = 'CHECK'
-AND CONSTRAINT_NAME = (@fieldName + '_ckc')
-
-IF @constr IS NOT NULL
-BEGIN
- SET @sqlcmd = 'ALTER TABLE ' + @fullyQualifiedTableName + ' DROP CONSTRAINT [' + @constr + ']'
- EXECUTE sp_executesql @sqlcmd
-END
-IF @constrNew IS NULL
-BEGIN
- SET @sqlcreate = 'ALTER TABLE ' + @fullyQualifiedTableName + ' WITH NOCHECK ADD CONSTRAINT ' + @fieldName + '_ckc CHECK /*$checkConstraint*/;'
- EXECUTE sp_executesql @sqlcreate
-END \ No newline at end of file
diff --git a/maintenance/mssql/archives/patch-fa_major_mime-chemical.sql b/maintenance/mssql/archives/patch-fa_major_mime-chemical.sql
deleted file mode 100644
index 18368087..00000000
--- a/maintenance/mssql/archives/patch-fa_major_mime-chemical.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-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
diff --git a/maintenance/mssql/archives/patch-img_major_mime-chemical.sql b/maintenance/mssql/archives/patch-img_major_mime-chemical.sql
deleted file mode 100644
index eed07869..00000000
--- a/maintenance/mssql/archives/patch-img_major_mime-chemical.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-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
diff --git a/maintenance/mssql/archives/patch-oi_major_mime-chemical.sql b/maintenance/mssql/archives/patch-oi_major_mime-chemical.sql
deleted file mode 100644
index 35482edc..00000000
--- a/maintenance/mssql/archives/patch-oi_major_mime-chemical.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-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
diff --git a/maintenance/mssql/archives/patch-page_page_lang.sql b/maintenance/mssql/archives/patch-page_page_lang.sql
deleted file mode 100644
index d2f537b0..00000000
--- a/maintenance/mssql/archives/patch-page_page_lang.sql
+++ /dev/null
@@ -1 +0,0 @@
-ALTER TABLE /*_*/page ADD page_lang VARBINARY(35) DEFAULT NULL
diff --git a/maintenance/mssql/archives/patch-user_password_expires.sql b/maintenance/mssql/archives/patch-user_password_expires.sql
deleted file mode 100644
index c22b10c7..00000000
--- a/maintenance/mssql/archives/patch-user_password_expires.sql
+++ /dev/null
@@ -1 +0,0 @@
-ALTER TABLE /*_*/mwuser ADD user_password_expires VARCHAR(14) DEFAULT NULL \ No newline at end of file
diff --git a/maintenance/mssql/tables.sql b/maintenance/mssql/tables.sql
deleted file mode 100644
index 5b09ffdc..00000000
--- a/maintenance/mssql/tables.sql
+++ /dev/null
@@ -1,1324 +0,0 @@
--- 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_options NVARCHAR(MAX) 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##');
-
---
--- 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 '',
-);
-CREATE UNIQUE clustered INDEX /*i*/ug_user_group ON /*_*/user_groups (ug_user, ug_group);
-CREATE INDEX /*i*/ug_group ON /*_*/user_groups(ug_group);
-
--- 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);
-
-
---
--- 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, -- FK added later
- rev_comment NVARCHAR(255) NOT NULL,
- 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);
-
---
--- 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_text NVARCHAR(MAX) NOT NULL,
- ar_comment NVARCHAR(255) NOT NULL,
- ar_user INT REFERENCES /*_*/mwuser(user_id) ON DELETE SET NULL,
- ar_user_text NVARCHAR(255) NOT NULL,
- ar_timestamp varchar(14) NOT NULL default '',
- ar_minor_edit BIT NOT NULL DEFAULT 0,
- ar_flags NVARCHAR(255) NOT NULL,
- ar_rev_id INT NULL, -- NOT a FK, the row gets deleted from revision and moved here
- ar_text_id INT 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 REFERENCES /*_*/revision(rev_id),
- 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_revid ON /*_*/archive (ar_rev_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_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);
-
-
---
--- Track template inclusions.
---
-CREATE TABLE /*_*/templatelinks (
- tl_from int NOT NULL REFERENCES /*_*/page(page_id) ON DELETE CASCADE,
- 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);
-
-
---
--- 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,
-
- -- 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);
-
---
--- 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 bug 25254.
- 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);
-
--- FIXME: Not used, delete this
-CREATE INDEX /*i*/cl_collation ON /*_*/categorylinks (cl_collation);
-
---
--- Track all existing categories. Something is a category if 1) it has an en-
--- try somewhere in categorylinks, or 2) it once did. 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);
-
-
---
--- 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.%'
- el_index nvarchar(450) NOT NULL
-);
-
-CREATE INDEX /*i*/el_from ON /*_*/externallinks (el_from);
-CREATE INDEX /*i*/el_index ON /*_*/externallinks (el_index);
-
---
--- 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,
-
- -- Total number of edits performed.
- ss_total_edits bigint default 0,
-
- -- An approximate count of pages matching the following criteria:
- -- * in namespace 0
- -- * not a redirect
- -- * contains the text '[['
- -- See Article::isCountable() in includes/Article.php
- ss_good_articles bigint default 0,
-
- -- Total pages, theoretically equal to SELECT COUNT(*) FROM page; except faster
- ss_total_pages bigint default '-1',
-
- -- Number of users, theoretically equal to SELECT COUNT(*) FROM user;
- ss_users bigint default '-1',
-
- -- Number of users that still edit
- ss_active_users bigint default '-1',
-
- -- Number of images, equivalent to SELECT COUNT(*) FROM image
- ss_images int default 0
-);
-
--- Pointless index to assuage developer superstitions
-CREATE UNIQUE INDEX /*i*/ss_row_id ON /*_*/site_stats (ss_row_id);
-
-
---
--- 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,
-
- -- User name of blocker
- ipb_by_text nvarchar(255) NOT NULL default '',
-
- -- Text comment made by blocker.
- ipb_reason nvarchar(255) NOT NULL,
-
- -- 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 (bug 49504).
- 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)
-
-);
-
--- 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);
-
-
---
--- 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 varbinary(255) NOT NULL default 0x 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 http://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 http://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 nvarchar(255) NOT NULL,
-
- -- 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,
-
- -- 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'))
-);
-
-CREATE INDEX /*i*/img_usertext_timestamp ON /*_*/image (img_user_text,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
- oi_name varbinary(255) NOT NULL default 0x REFERENCES /*_*/image(img_name) ON DELETE CASCADE ON UPDATE CASCADE,
-
- -- Filename of the archived file.
- -- This is generally a timestamp and '!' prepended to the base name.
- oi_archive_name varbinary(255) NOT NULL default 0x,
-
- -- 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 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 nvarchar(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);
--- oi_archive_name truncated to 14 to avoid key length overflow
-CREATE INDEX /*i*/oi_name_archive_name ON /*_*/oldimage (oi_name,oi_archive_name);
-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 nvarchar(max),
-
- -- Duped fields from image
- fa_size int default 0,
- fa_width int default 0,
- fa_height int default 0,
- fa_metadata nvarchar(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 '',
-
- -- 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'))
-);
-
--- 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);
--- 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'))
-);
-
--- 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 PRIMARY KEY IDENTITY,
- rc_timestamp varchar(14) not null default '',
-
- -- This is no longer used
- -- Field kept in database for downgrades
- -- @todo: add drop patch with 1.24
- rc_cur_time varchar(14) NOT NULL default '',
-
- -- As in revision
- rc_user int NOT NULL default 0 REFERENCES /*_*/mwuser(user_id),
- rc_user_text nvarchar(255) NOT NULL,
-
- -- 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 nvarchar(255) NOT NULL default '',
- 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 REFERENCES /*_*/page(page_id),
-
- -- rev_id of the given revision
- rc_this_oldid int REFERENCES /*_*/revision(rev_id),
-
- -- rev_id of the prior revision, for generating diff links.
- rc_last_oldid int REFERENCES /*_*/revision(rev_id),
-
- -- 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.
- rc_patrolled bit NOT NULL 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 ON /*_*/recentchanges (rc_namespace, rc_title);
-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 TABLE /*_*/watchlist (
- -- 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,
-
- -- 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 wfGetLB( '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
-);
-
-CREATE UNIQUE INDEX /*i*/iw_prefix ON /*_*/interwiki (iw_prefix);
-
-
---
--- 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);
-
-
---
--- Cache of interwiki transclusion
---
-CREATE TABLE /*_*/transcache (
- tc_url nvarchar(255) NOT NULL,
- tc_contents nvarchar(max),
- tc_time varchar(14) NOT NULL
-);
-
-CREATE UNIQUE INDEX /*i*/tc_url_idx ON /*_*/transcache (tc_url);
-
-
-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 REFERENCES /*_*/mwuser(user_id) ON DELETE SET NULL,
-
- -- Name of the user who performed this action
- log_user_text nvarchar(255) NOT NULL default '',
-
- -- 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 REFERENCES /*_*/page(page_id) ON DELETE SET NULL,
-
- -- Freeform text. Interpreted as edit history comments.
- log_comment nvarchar(255) NOT NULL default '',
-
- -- 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*/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);
-
-INSERT INTO /*_*/logging (log_user,log_page,log_params) VALUES(0,0,'');
-
-ALTER TABLE /*_*/recentchanges ADD CONSTRAINT FK_rc_logid_log_id 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 nvarchar(255),
- pt_timestamp varchar(14) NOT NULL,
- pt_expiry varchar(14) NOT NULL,
- pt_create_perm nvarchar(60) NOT NULL
-);
-
-CREATE UNIQUE INDEX /*i*/pt_namespace_title ON /*_*/protected_titles (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
-);
-
-CREATE UNIQUE INDEX /*i*/pp_page_propname ON /*_*/page_props (pp_page,pp_propname);
-CREATE UNIQUE INDEX /*i*/pp_propname_page ON /*_*/page_props (pp_propname,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 (
- -- 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),
- -- Tag applied
- ct_tag nvarchar(255) NOT NULL,
- -- Parameters for the tag, presently unused
- ct_params nvarchar(max) NULL
-);
-
-CREATE UNIQUE INDEX /*i*/change_tag_rc_tag ON /*_*/change_tag (ct_rc_id,ct_tag);
-CREATE UNIQUE INDEX /*i*/change_tag_log_tag ON /*_*/change_tag (ct_log_id,ct_tag);
-CREATE UNIQUE INDEX /*i*/change_tag_rev_tag ON /*_*/change_tag (ct_rev_id,ct_tag);
--- Covering index, so we can pull all the info only out of the index.
-CREATE INDEX /*i*/change_tag_tag_id ON /*_*/change_tag (ct_tag,ct_rc_id,ct_rev_id,ct_log_id);
-
-
--- Rollup table to pull a LIST of tags simply without ugly GROUP_CONCAT
--- that only works on MySQL 4.1+
-CREATE TABLE /*_*/tag_summary (
- -- RCID for the change
- ts_rc_id int NULL REFERENCES /*_*/recentchanges(rc_id),
- -- LOGID for the change
- ts_log_id int NULL REFERENCES /*_*/logging(log_id),
- -- REVID for the change
- ts_rev_id int NULL REFERENCES /*_*/revision(rev_id),
- -- Comma-separated list of tags
- ts_tags nvarchar(max) NOT NULL
-);
-
-CREATE UNIQUE INDEX /*i*/tag_summary_rc_id ON /*_*/tag_summary (ts_rc_id);
-CREATE UNIQUE INDEX /*i*/tag_summary_log_id ON /*_*/tag_summary (ts_log_id);
-CREATE UNIQUE INDEX /*i*/tag_summary_rev_id ON /*_*/tag_summary (ts_rev_id);
-
-
-CREATE TABLE /*_*/valid_tag (
- vt_tag nvarchar(255) NOT NULL PRIMARY KEY
-);
-
--- 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 for caching JSON message texts for the resource loader
-CREATE TABLE /*_*/msg_resource (
- -- Resource name
- mr_resource nvarchar(255) NOT NULL,
- -- Language code
- mr_lang nvarchar(32) NOT NULL,
- -- JSON blob
- mr_blob varbinary(max) NOT NULL,
- -- Timestamp of last update
- mr_timestamp varchar(14) NOT NULL
-);
-CREATE UNIQUE INDEX /*i*/mr_resource_lang ON /*_*/msg_resource (mr_resource, mr_lang);
-
--- Table for administering which message is contained in which resource
-CREATE TABLE /*_*/msg_resource_links (
- mrl_resource varbinary(255) NOT NULL,
- -- Message key
- mrl_message varbinary(255) NOT NULL
-);
-CREATE UNIQUE INDEX /*i*/mrl_message_resource ON /*_*/msg_resource_links (mrl_message, mrl_resource);
-
--- 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
-);
-
-CREATE UNIQUE INDEX /*i*/site_ids_type ON /*_*/site_identifiers (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);
diff --git a/maintenance/mssql/update-keys.sql b/maintenance/mssql/update-keys.sql
deleted file mode 100644
index 4d2c1c12..00000000
--- a/maintenance/mssql/update-keys.sql
+++ /dev/null
@@ -1,31 +0,0 @@
--- 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
diff --git a/maintenance/oracle/alterSharedConstraints.php b/maintenance/oracle/alterSharedConstraints.php
deleted file mode 100644
index eea6f7b1..00000000
--- a/maintenance/oracle/alterSharedConstraints.php
+++ /dev/null
@@ -1,95 +0,0 @@
-<?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
- */
-
-/**
- * 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->mDescription = "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 = wfGetDB( 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";
-require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/maintenance/oracle/archives/patch-ar_sha1_field.sql b/maintenance/oracle/archives/patch-ar_sha1_field.sql
deleted file mode 100644
index de723ce7..00000000
--- a/maintenance/oracle/archives/patch-ar_sha1_field.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.archive ADD ar_sha1 VARCHAR2(32);
diff --git a/maintenance/oracle/archives/patch-archive-ar_content_format.sql b/maintenance/oracle/archives/patch-archive-ar_content_format.sql
deleted file mode 100644
index 0c0c0d94..00000000
--- a/maintenance/oracle/archives/patch-archive-ar_content_format.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.archive ADD ar_content_format VARCHAR2(64);
diff --git a/maintenance/oracle/archives/patch-archive-ar_content_model.sql b/maintenance/oracle/archives/patch-archive-ar_content_model.sql
deleted file mode 100644
index d18fc9e4..00000000
--- a/maintenance/oracle/archives/patch-archive-ar_content_model.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.archive ADD ar_content_model VARCHAR2(32);
diff --git a/maintenance/oracle/archives/patch-archive-ar_id.sql b/maintenance/oracle/archives/patch-archive-ar_id.sql
deleted file mode 100644
index a43f7602..00000000
--- a/maintenance/oracle/archives/patch-archive-ar_id.sql
+++ /dev/null
@@ -1,6 +0,0 @@
-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);
diff --git a/maintenance/oracle/archives/patch-cat_hidden.sql b/maintenance/oracle/archives/patch-cat_hidden.sql
deleted file mode 100644
index d1649c7c..00000000
--- a/maintenance/oracle/archives/patch-cat_hidden.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.category DROP COLUMN cat_hidden;
-
diff --git a/maintenance/oracle/archives/patch-externallinks-el_id.sql b/maintenance/oracle/archives/patch-externallinks-el_id.sql
deleted file mode 100644
index a8c443f4..00000000
--- a/maintenance/oracle/archives/patch-externallinks-el_id.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-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
diff --git a/maintenance/oracle/archives/patch-fa_sha1.sql b/maintenance/oracle/archives/patch-fa_sha1.sql
deleted file mode 100644
index 70c9e60c..00000000
--- a/maintenance/oracle/archives/patch-fa_sha1.sql
+++ /dev/null
@@ -1,5 +0,0 @@
-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);
-
diff --git a/maintenance/oracle/archives/patch-ipblocks_i05_index.sql b/maintenance/oracle/archives/patch-ipblocks_i05_index.sql
deleted file mode 100644
index 14275383..00000000
--- a/maintenance/oracle/archives/patch-ipblocks_i05_index.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-CREATE INDEX &mw_prefix.ipblocks_i05 ON &mw_prefix.ipblocks (ipb_parent_block_id);
-
diff --git a/maintenance/oracle/archives/patch-job_attempts.sql b/maintenance/oracle/archives/patch-job_attempts.sql
deleted file mode 100644
index b05c8779..00000000
--- a/maintenance/oracle/archives/patch-job_attempts.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-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);
diff --git a/maintenance/oracle/archives/patch-job_timestamp_field.sql b/maintenance/oracle/archives/patch-job_timestamp_field.sql
deleted file mode 100644
index 4901c87c..00000000
--- a/maintenance/oracle/archives/patch-job_timestamp_field.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.job ADD job_timestamp TIMESTAMP(6) WITH TIME ZONE NULL;
-
diff --git a/maintenance/oracle/archives/patch-job_timestamp_index.sql b/maintenance/oracle/archives/patch-job_timestamp_index.sql
deleted file mode 100644
index 6db43046..00000000
--- a/maintenance/oracle/archives/patch-job_timestamp_index.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-CREATE INDEX &mw_prefix.job_i02 ON &mw_prefix.job (job_timestamp);
-
diff --git a/maintenance/oracle/archives/patch-job_token.sql b/maintenance/oracle/archives/patch-job_token.sql
deleted file mode 100644
index 1a730e95..00000000
--- a/maintenance/oracle/archives/patch-job_token.sql
+++ /dev/null
@@ -1,12 +0,0 @@
-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);
-
diff --git a/maintenance/oracle/archives/patch-logging_type_action_index.sql b/maintenance/oracle/archives/patch-logging_type_action_index.sql
deleted file mode 100644
index d30e0cfc..00000000
--- a/maintenance/oracle/archives/patch-logging_type_action_index.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-CREATE INDEX &mw_prefix.logging_i05 ON &mw_prefix.logging (log_type, log_action, log_timestamp);
-
diff --git a/maintenance/oracle/archives/patch-logging_user_text_time_index.sql b/maintenance/oracle/archives/patch-logging_user_text_time_index.sql
deleted file mode 100644
index e04abf5f..00000000
--- a/maintenance/oracle/archives/patch-logging_user_text_time_index.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-CREATE INDEX &mw_prefix.logging_i07 ON &mw_prefix.logging (log_user_text, log_timestamp);
-
diff --git a/maintenance/oracle/archives/patch-logging_user_text_type_time_index.sql b/maintenance/oracle/archives/patch-logging_user_text_type_time_index.sql
deleted file mode 100644
index c1c0d4f2..00000000
--- a/maintenance/oracle/archives/patch-logging_user_text_type_time_index.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-CREATE INDEX &mw_prefix.logging_i06 ON &mw_prefix.logging (log_user_text, log_type, log_timestamp);
-
diff --git a/maintenance/oracle/archives/patch-page-page_content_model.sql b/maintenance/oracle/archives/patch-page-page_content_model.sql
deleted file mode 100644
index e5839d9a..00000000
--- a/maintenance/oracle/archives/patch-page-page_content_model.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.page ADD page_content_model VARCHAR2(32);
diff --git a/maintenance/oracle/archives/patch-page-page_lang.sql b/maintenance/oracle/archives/patch-page-page_lang.sql
deleted file mode 100644
index cae7cf90..00000000
--- a/maintenance/oracle/archives/patch-page-page_lang.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.page ADD page_lang VARCHAR2(35);
diff --git a/maintenance/oracle/archives/patch-page_links_updated.sql b/maintenance/oracle/archives/patch-page_links_updated.sql
deleted file mode 100644
index 53603294..00000000
--- a/maintenance/oracle/archives/patch-page_links_updated.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.page ADD page_links_updated TIMESTAMP(6) WITH TIME ZONE;
-
diff --git a/maintenance/oracle/archives/patch-page_redirect_namespace_len.sql b/maintenance/oracle/archives/patch-page_redirect_namespace_len.sql
deleted file mode 100644
index 1f8b9d9a..00000000
--- a/maintenance/oracle/archives/patch-page_redirect_namespace_len.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-CREATE INDEX &mw_prefix.page_i03 ON &mw_prefix.page (page_is_redirect, page_namespace, page_len);
-
diff --git a/maintenance/oracle/archives/patch-page_restrictions_pkuk_fix.sql b/maintenance/oracle/archives/patch-page_restrictions_pkuk_fix.sql
deleted file mode 100644
index 56c392c1..00000000
--- a/maintenance/oracle/archives/patch-page_restrictions_pkuk_fix.sql
+++ /dev/null
@@ -1,7 +0,0 @@
-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);
diff --git a/maintenance/oracle/archives/patch-rc_moved.sql b/maintenance/oracle/archives/patch-rc_moved.sql
deleted file mode 100644
index 2a71315d..00000000
--- a/maintenance/oracle/archives/patch-rc_moved.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.recentchanges DROP ( rc_moved_to_ns, rc_moved_to_title );
-
diff --git a/maintenance/oracle/archives/patch-rc_source.sql b/maintenance/oracle/archives/patch-rc_source.sql
deleted file mode 100644
index 0c80afab..00000000
--- a/maintenance/oracle/archives/patch-rc_source.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.recentchanges ADD rc_source VARCHAR2(16);
diff --git a/maintenance/oracle/archives/patch-rev_sha1_field.sql b/maintenance/oracle/archives/patch-rev_sha1_field.sql
deleted file mode 100644
index 80544e89..00000000
--- a/maintenance/oracle/archives/patch-rev_sha1_field.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.revision ADD rev_sha1 VARCHAR2(32);
-
diff --git a/maintenance/oracle/archives/patch-revision-rev_content_format.sql b/maintenance/oracle/archives/patch-revision-rev_content_format.sql
deleted file mode 100644
index ebde71c9..00000000
--- a/maintenance/oracle/archives/patch-revision-rev_content_format.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.revision ADD rev_content_format VARCHAR2(64);
diff --git a/maintenance/oracle/archives/patch-revision-rev_content_model.sql b/maintenance/oracle/archives/patch-revision-rev_content_model.sql
deleted file mode 100644
index dd226423..00000000
--- a/maintenance/oracle/archives/patch-revision-rev_content_model.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.revision ADD rev_content_model VARCHAR2(32);
diff --git a/maintenance/oracle/archives/patch-revision_i05_index.sql b/maintenance/oracle/archives/patch-revision_i05_index.sql
deleted file mode 100644
index 929c7b31..00000000
--- a/maintenance/oracle/archives/patch-revision_i05_index.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-CREATE INDEX &mw_prefix.revision_i05 ON &mw_prefix.revision (rev_page,rev_user,rev_timestamp);
-
diff --git a/maintenance/oracle/archives/patch-sites.sql b/maintenance/oracle/archives/patch-sites.sql
deleted file mode 100644
index 868b210f..00000000
--- a/maintenance/oracle/archives/patch-sites.sql
+++ /dev/null
@@ -1,34 +0,0 @@
-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);
diff --git a/maintenance/oracle/archives/patch-ss_admins.sql b/maintenance/oracle/archives/patch-ss_admins.sql
deleted file mode 100644
index c2e9242e..00000000
--- a/maintenance/oracle/archives/patch-ss_admins.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.site_stats DROP COLUMN ss_admins;
-
diff --git a/maintenance/oracle/archives/patch-testrun.sql b/maintenance/oracle/archives/patch-testrun.sql
deleted file mode 100644
index 84facabc..00000000
--- a/maintenance/oracle/archives/patch-testrun.sql
+++ /dev/null
@@ -1,37 +0,0 @@
---
--- 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);
-
diff --git a/maintenance/oracle/archives/patch-ufg_group-length-increase-255.sql b/maintenance/oracle/archives/patch-ufg_group-length-increase-255.sql
deleted file mode 100644
index 6a4a7517..00000000
--- a/maintenance/oracle/archives/patch-ufg_group-length-increase-255.sql
+++ /dev/null
@@ -1,9 +0,0 @@
-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$*/
diff --git a/maintenance/oracle/archives/patch-ug_group-length-increase-255.sql b/maintenance/oracle/archives/patch-ug_group-length-increase-255.sql
deleted file mode 100644
index 00a5e7b2..00000000
--- a/maintenance/oracle/archives/patch-ug_group-length-increase-255.sql
+++ /dev/null
@@ -1,9 +0,0 @@
-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$*/
diff --git a/maintenance/oracle/archives/patch-up_property.sql b/maintenance/oracle/archives/patch-up_property.sql
deleted file mode 100644
index c8e2dd95..00000000
--- a/maintenance/oracle/archives/patch-up_property.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.user_properties MODIFY up_property varchar2(255);
diff --git a/maintenance/oracle/archives/patch-uploadstash-us_props.sql b/maintenance/oracle/archives/patch-uploadstash-us_props.sql
deleted file mode 100644
index 8962dc7c..00000000
--- a/maintenance/oracle/archives/patch-uploadstash-us_props.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.uploadstash ADD us_props BLOB;
-
diff --git a/maintenance/oracle/archives/patch-uploadstash.sql b/maintenance/oracle/archives/patch-uploadstash.sql
deleted file mode 100644
index 3e37ceff..00000000
--- a/maintenance/oracle/archives/patch-uploadstash.sql
+++ /dev/null
@@ -1,25 +0,0 @@
-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);
diff --git a/maintenance/oracle/archives/patch-us_chunk_inx_field.sql b/maintenance/oracle/archives/patch-us_chunk_inx_field.sql
deleted file mode 100644
index 43ee16ec..00000000
--- a/maintenance/oracle/archives/patch-us_chunk_inx_field.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.uploadstash ADD us_chunk_inx NUMBER;
-
diff --git a/maintenance/oracle/archives/patch-user_email_index.sql b/maintenance/oracle/archives/patch-user_email_index.sql
deleted file mode 100644
index e34d8656..00000000
--- a/maintenance/oracle/archives/patch-user_email_index.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-CREATE INDEX &mw_prefix.mwuser_i02 ON &mw_prefix.mwuser (user_email);
-
diff --git a/maintenance/oracle/archives/patch-user_former_groups.sql b/maintenance/oracle/archives/patch-user_former_groups.sql
deleted file mode 100644
index c14824eb..00000000
--- a/maintenance/oracle/archives/patch-user_former_groups.sql
+++ /dev/null
@@ -1,9 +0,0 @@
-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);
-
diff --git a/maintenance/oracle/archives/patch-user_password_expire.sql b/maintenance/oracle/archives/patch-user_password_expire.sql
deleted file mode 100644
index 824cc820..00000000
--- a/maintenance/oracle/archives/patch-user_password_expire.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.mwuser ADD user_password_expires TIMESTAMP(6) WITH TIME ZONE;
diff --git a/maintenance/oracle/archives/patch_16_17_schema_changes.sql b/maintenance/oracle/archives/patch_16_17_schema_changes.sql
deleted file mode 100644
index cd99f7cc..00000000
--- a/maintenance/oracle/archives/patch_16_17_schema_changes.sql
+++ /dev/null
@@ -1,98 +0,0 @@
-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);
-
-CREATE TABLE &mw_prefix.msg_resource_links (
- mrl_resource VARCHAR2(255) NOT NULL,
- mrl_message VARCHAR2(255) NOT NULL
-);
-CREATE UNIQUE INDEX &mw_prefix.msg_resource_links_u01 ON &mw_prefix.msg_resource_links (mrl_message, mrl_resource);
-
-CREATE TABLE &mw_prefix.msg_resource (
- mr_resource VARCHAR2(255) NOT NULL,
- mr_lang varchar2(32) NOT NULL,
- mr_blob BLOB NOT NULL,
- mr_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL
-);
-CREATE UNIQUE INDEX &mw_prefix.msg_resource_u01 ON &mw_prefix.msg_resource (mr_resource, mr_lang);
-
-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;
-
diff --git a/maintenance/oracle/archives/patch_create_17_functions.sql b/maintenance/oracle/archives/patch_create_17_functions.sql
deleted file mode 100644
index 6c9c9542..00000000
--- a/maintenance/oracle/archives/patch_create_17_functions.sql
+++ /dev/null
@@ -1,125 +0,0 @@
-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$*/
-
diff --git a/maintenance/oracle/archives/patch_fk_rename_deferred.sql b/maintenance/oracle/archives/patch_fk_rename_deferred.sql
deleted file mode 100644
index ca9c997f..00000000
--- a/maintenance/oracle/archives/patch_fk_rename_deferred.sql
+++ /dev/null
@@ -1,40 +0,0 @@
-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;
-
diff --git a/maintenance/oracle/archives/patch_namespace_defaults.sql b/maintenance/oracle/archives/patch_namespace_defaults.sql
deleted file mode 100644
index 24c95643..00000000
--- a/maintenance/oracle/archives/patch_namespace_defaults.sql
+++ /dev/null
@@ -1,17 +0,0 @@
-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;
-
diff --git a/maintenance/oracle/archives/patch_rebuild_dupfunc.sql b/maintenance/oracle/archives/patch_rebuild_dupfunc.sql
deleted file mode 100644
index 56ee5b3e..00000000
--- a/maintenance/oracle/archives/patch_rebuild_dupfunc.sql
+++ /dev/null
@@ -1,149 +0,0 @@
-/*$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$*/
-
diff --git a/maintenance/oracle/archives/patch_recentchanges_fk2_cascade.sql b/maintenance/oracle/archives/patch_recentchanges_fk2_cascade.sql
deleted file mode 100644
index 45509518..00000000
--- a/maintenance/oracle/archives/patch_recentchanges_fk2_cascade.sql
+++ /dev/null
@@ -1,5 +0,0 @@
-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;
-
diff --git a/maintenance/oracle/archives/patch_remove_not_null_empty_defs.sql b/maintenance/oracle/archives/patch_remove_not_null_empty_defs.sql
deleted file mode 100644
index 76e50a0a..00000000
--- a/maintenance/oracle/archives/patch_remove_not_null_empty_defs.sql
+++ /dev/null
@@ -1,9 +0,0 @@
-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;
diff --git a/maintenance/oracle/archives/patch_remove_not_null_empty_defs2.sql b/maintenance/oracle/archives/patch_remove_not_null_empty_defs2.sql
deleted file mode 100644
index f7a38a05..00000000
--- a/maintenance/oracle/archives/patch_remove_not_null_empty_defs2.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-ALTER TABLE &mw_prefix.ipblocks MODIFY ipb_by_text DEFAULT NULL NULL;
diff --git a/maintenance/oracle/patch_seq_names_pre1.16.sql b/maintenance/oracle/patch_seq_names_pre1.16.sql
deleted file mode 100644
index 5346b141..00000000
--- a/maintenance/oracle/patch_seq_names_pre1.16.sql
+++ /dev/null
@@ -1,8 +0,0 @@
--- 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
diff --git a/maintenance/oracle/tables.sql b/maintenance/oracle/tables.sql
deleted file mode 100644
index 12f6518a..00000000
--- a/maintenance/oracle/tables.sql
+++ /dev/null
@@ -1,971 +0,0 @@
--- defines must comply with ^define\s*([^\s=]*)\s*=\s?'\{\$([^\}]*)\}';
-define mw_prefix='{$wgDBprefix}';
-
-
-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);
-
--- 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 TABLE &mw_prefix.user_groups (
- ug_user NUMBER DEFAULT 0 NOT NULL,
- ug_group VARCHAR2(255) NOT NULL
-);
-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 UNIQUE INDEX &mw_prefix.user_groups_u01 ON &mw_prefix.user_groups (ug_user,ug_group);
-CREATE INDEX &mw_prefix.user_groups_i01 ON &mw_prefix.user_groups (ug_group);
-
-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);
-
--- Create a dummy page to satisfy fk contraints especially with revisions
-INSERT INTO &mw_prefix.page
- VALUES (0, 0, ' ', NULL, 0, 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 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);
-
-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);
-
-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_text CLOB,
- ar_comment VARCHAR2(255),
- ar_user NUMBER DEFAULT 0 NOT NULL,
- ar_user_text VARCHAR2(255) NOT NULL,
- ar_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL,
- ar_minor_edit CHAR(1) DEFAULT '0' NOT NULL,
- ar_flags VARCHAR2(255),
- ar_rev_id NUMBER,
- ar_text_id NUMBER,
- 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;
-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.archive_i03 ON &mw_prefix.archive (ar_rev_id);
-
-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);
-
-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
-);
-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 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 ,
- ss_total_edits NUMBER DEFAULT 0,
- ss_good_articles NUMBER DEFAULT 0,
- ss_total_pages NUMBER DEFAULT -1,
- ss_users NUMBER DEFAULT -1,
- ss_active_users NUMBER DEFAULT -1,
- ss_images NUMBER DEFAULT 0
-);
-CREATE UNIQUE INDEX &mw_prefix.site_stats_u01 ON &mw_prefix.site_stats (ss_row_id);
-
-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_reason VARCHAR2(255) 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
-);
-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;
-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);
-
-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 VARCHAR2(255),
- img_user NUMBER DEFAULT 0 NOT NULL,
- img_user_text VARCHAR2(255) 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;
-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 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 VARCHAR2(255),
- oi_user NUMBER DEFAULT 0 NOT NULL,
- oi_user_text VARCHAR2(255) 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;
-CREATE INDEX &mw_prefix.oldimage_i01 ON &mw_prefix.oldimage (oi_user_text,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 CLOB,
- 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 VARCHAR2(255),
- fa_user NUMBER DEFAULT 0 NOT NULL,
- fa_user_text VARCHAR2(255) 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;
-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.filearchive_i05 ON &mw_prefix.filearchive (fa_sha1);
-
-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);
-
-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) NOT NULL,
- rc_namespace NUMBER DEFAULT 0 NOT NULL,
- rc_title VARCHAR2(255) NOT NULL,
- rc_comment VARCHAR2(255),
- 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;
-CREATE INDEX &mw_prefix.recentchanges_i01 ON &mw_prefix.recentchanges (rc_timestamp);
-CREATE INDEX &mw_prefix.recentchanges_i02 ON &mw_prefix.recentchanges (rc_namespace, rc_title);
-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 TABLE &mw_prefix.watchlist (
- 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_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 TABLE &mw_prefix.transcache (
- tc_url VARCHAR2(255) NOT NULL,
- tc_contents CLOB NOT NULL,
- tc_time TIMESTAMP(6) WITH TIME ZONE NOT NULL
-);
-CREATE UNIQUE INDEX &mw_prefix.transcache_u01 ON &mw_prefix.transcache (tc_url);
-
-
-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_namespace NUMBER DEFAULT 0 NOT NULL,
- log_title VARCHAR2(255) NOT NULL,
- log_page NUMBER,
- log_comment VARCHAR2(255),
- 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;
-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 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);
-
-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);
-
-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 VARCHAR2(255),
- pt_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL,
- pt_expiry VARCHAR2(14) NOT NULL,
- pt_create_perm VARCHAR2(60) NOT NULL
-);
-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_rc_id NUMBER NULL,
- ct_log_id NUMBER NULL,
- ct_rev_id NUMBER NULL,
- ct_tag VARCHAR2(255) NOT NULL,
- ct_params BLOB NULL
-);
-CREATE UNIQUE INDEX &mw_prefix.change_tag_u01 ON &mw_prefix.change_tag (ct_rc_id,ct_tag);
-CREATE UNIQUE INDEX &mw_prefix.change_tag_u02 ON &mw_prefix.change_tag (ct_log_id,ct_tag);
-CREATE UNIQUE INDEX &mw_prefix.change_tag_u03 ON &mw_prefix.change_tag (ct_rev_id,ct_tag);
-CREATE INDEX &mw_prefix.change_tag_i01 ON &mw_prefix.change_tag (ct_tag,ct_rc_id,ct_rev_id,ct_log_id);
-
-CREATE TABLE &mw_prefix.tag_summary (
- ts_rc_id NUMBER NULL,
- ts_log_id NUMBER NULL,
- ts_rev_id NUMBER NULL,
- ts_tags BLOB NOT NULL
-);
-CREATE UNIQUE INDEX &mw_prefix.tag_summary_u01 ON &mw_prefix.tag_summary (ts_rc_id);
-CREATE UNIQUE INDEX &mw_prefix.tag_summary_u02 ON &mw_prefix.tag_summary (ts_log_id);
-CREATE UNIQUE INDEX &mw_prefix.tag_summary_u03 ON &mw_prefix.tag_summary (ts_rev_id);
-
-CREATE TABLE &mw_prefix.valid_tag (
- vt_tag VARCHAR2(255) NOT NULL
-);
-ALTER TABLE &mw_prefix.valid_tag ADD CONSTRAINT &mw_prefix.valid_tag_pk PRIMARY KEY (vt_tag);
-
--- 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.msg_resource (
- mr_resource VARCHAR2(255) NOT NULL,
- mr_lang varchar2(32) NOT NULL,
- mr_blob BLOB NOT NULL,
- mr_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL
-);
-CREATE UNIQUE INDEX &mw_prefix.msg_resource_u01 ON &mw_prefix.msg_resource (mr_resource, mr_lang);
-
-CREATE TABLE &mw_prefix.msg_resource_links (
- mrl_resource VARCHAR2(255) NOT NULL,
- mrl_message VARCHAR2(255) NOT NULL
-);
-CREATE UNIQUE INDEX &mw_prefix.msg_resource_links_u01 ON &mw_prefix.msg_resource_links (mrl_message, mrl_resource);
-
-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);
-
-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$*/
diff --git a/maintenance/oracle/update-keys.sql b/maintenance/oracle/update-keys.sql
deleted file mode 100644
index 7761d0c5..00000000
--- a/maintenance/oracle/update-keys.sql
+++ /dev/null
@@ -1,29 +0,0 @@
--- 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 );
diff --git a/maintenance/oracle/user.sql b/maintenance/oracle/user.sql
deleted file mode 100644
index 57688eae..00000000
--- a/maintenance/oracle/user.sql
+++ /dev/null
@@ -1,16 +0,0 @@
--- 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.;
diff --git a/tests/phpunit/includes/installer/OracleInstallerTest.php b/tests/phpunit/includes/installer/OracleInstallerTest.php
deleted file mode 100644
index fdcecf9e..00000000
--- a/tests/phpunit/includes/installer/OracleInstallerTest.php
+++ /dev/null
@@ -1,52 +0,0 @@
-<?php
-
-/**
- * Tests for OracleInstaller
- *
- * @group Database
- * @group Installer
- */
-
-class OracleInstallerTest extends MediaWikiTestCase {
-
- /**
- * @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 array(
- array( true, 'simple_01', 'Simple TNS name' ),
- array( true, 'simple_01.world', 'TNS name with domain' ),
- array( true, 'simple_01.domain.net', 'TNS name with domain' ),
- array( true, 'host123', 'Host only' ),
- array( true, 'host123.domain.net', 'FQDN only' ),
- array( true, '//host123.domain.net', 'FQDN URL only' ),
- array( true, '123.223.213.132', 'Host IP only' ),
- array( true, 'host:1521', 'Host and port' ),
- array( true, 'host:1521/service', 'Host, port and service' ),
- array( true, 'host:1521/service:shared', 'Host, port, service and shared server type' ),
- array( true, 'host:1521/service:dedicated', 'Host, port, service and dedicated server type' ),
- array( true, 'host:1521/service:pooled', 'Host, port, service and pooled server type' ),
- array(
- true,
- 'host:1521/service:shared/instance1',
- 'Host, port, service, server type and instance'
- ),
- array( true, 'host:1521//instance1', 'Host, port and instance' ),
- );
- }
-
-}