were using it, you have to either copy it to your extension, or install the
Vector extension (and possibly disable its features using config settings if
you don't want them).
+* Experimental IBM DB2 support was removed due to lack of interest and maintainership
== Compatibility ==
MediaWiki 1.21 requires PHP 5.3.2 or later.
MySQL is the recommended DBMS. PostgreSQL or SQLite can also be used, but
-support for them is somewhat less mature. There is experimental support for IBM
-DB2 and Oracle.
+support for them is somewhat less mature. There is experimental support for
+Oracle.
The supported versions are:
* PostgreSQL
* SQLite
* Oracle
-* IBM DB2
* MSSQL
More information can be found about each of these databases (known issues,
+++ /dev/null
-== See also ==
-*[http://www.mediawiki.org/wiki/Manual:IBM_DB2 Installation instructions]
-*[http://ca.php.net/manual/en/function.db2-connect.php PHP Manual for DB2 functions]
\ No newline at end of file
'ChronologyProtector' => 'includes/db/LBFactory.php',
'CloneDatabase' => 'includes/db/CloneDatabase.php',
'DatabaseBase' => 'includes/db/Database.php',
- 'DatabaseIbm_db2' => 'includes/db/DatabaseIbm_db2.php',
'DatabaseMssql' => 'includes/db/DatabaseMssql.php',
'DatabaseMysql' => 'includes/db/DatabaseMysql.php',
'DatabaseOracle' => 'includes/db/DatabaseOracle.php',
'DBUnexpectedError' => 'includes/db/DatabaseError.php',
'FakeResultWrapper' => 'includes/db/DatabaseUtility.php',
'Field' => 'includes/db/DatabaseUtility.php',
- 'IBM_DB2Blob' => 'includes/db/DatabaseIbm_db2.php',
- 'IBM_DB2Field' => 'includes/db/DatabaseIbm_db2.php',
- 'IBM_DB2Helper' => 'includes/db/DatabaseIbm_db2.php',
- 'IBM_DB2Result' => 'includes/db/DatabaseIbm_db2.php',
'LBFactory' => 'includes/db/LBFactory.php',
'LBFactory_Fake' => 'includes/db/LBFactory.php',
'LBFactory_Multi' => 'includes/db/LBFactory_Multi.php',
'CliInstaller' => 'includes/installer/CliInstaller.php',
'DatabaseInstaller' => 'includes/installer/DatabaseInstaller.php',
'DatabaseUpdater' => 'includes/installer/DatabaseUpdater.php',
- 'Ibm_db2Installer' => 'includes/installer/Ibm_db2Installer.php',
- 'Ibm_db2Updater' => 'includes/installer/Ibm_db2Updater.php',
'InstallDocFormatter' => 'includes/installer/InstallDocFormatter.php',
'Installer' => 'includes/installer/Installer.php',
'LocalSettingsGenerator' => 'includes/installer/LocalSettingsGenerator.php',
'SearchEngine' => 'includes/search/SearchEngine.php',
'SearchEngineDummy' => 'includes/search/SearchEngine.php',
'SearchHighlighter' => 'includes/search/SearchEngine.php',
- 'SearchIBM_DB2' => 'includes/search/SearchIBM_DB2.php',
'SearchMssql' => 'includes/search/SearchMssql.php',
'SearchMySQL' => 'includes/search/SearchMySQL.php',
'SearchNearMatchResultSet' => 'includes/search/SearchEngine.php',
define( 'LIST_SET', 2 );
define( 'LIST_NAMES', 3);
define( 'LIST_OR', 4);
-define( 'LIST_SET_PREPARED', 8); // List of (?, ?, ?) for DatabaseIbm_db2
/**@}*/
/**
*/
define( 'TS_POSTGRES', 7 );
-/**
- * DB2 format time
- */
-define( 'TS_DB2', 8 );
-
/**
* ISO 8601 basic format with no timezone: 19860209T200000Z. This is used by ResourceLoader
*/
*/
static function getTimestampFromId( $title, $id ) {
$dbr = wfGetDB( DB_SLAVE );
- // Casting fix for DB2
+ // Casting fix for databases that can't take '' for rev_id
if ( $id == '' ) {
$id = 0;
}
TS_RFC2822 => 'D, d M Y H:i:s',
TS_ORACLE => 'd-m-Y H:i:s.000000', // Was 'd-M-y h.i.s A' . ' +00:00' before r51500
TS_POSTGRES => 'Y-m-d H:i:s',
- TS_DB2 => 'Y-m-d H:i:s',
);
/**
# TS_POSTGRES
} elseif ( preg_match( '/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)\.*\d* GMT$/', $ts, $da ) ) {
# TS_POSTGRES
- } elseif (preg_match( '/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)\.\d\d\d$/', $ts, $da ) ) {
- # TS_DB2
} elseif ( preg_match( '/^[ \t\r\n]*([A-Z][a-z]{2},[ \t\r\n]*)?' . # Day of week
'\d\d?[ \t\r\n]*[A-Z][a-z]{2}[ \t\r\n]*\d{2}(?:\d{2})?' . # dd Mon yyyy
'[ \t\r\n]*\d\d[ \t\r\n]*:[ \t\r\n]*\d\d[ \t\r\n]*:[ \t\r\n]*\d\d/S', $ts ) ) { # hh:mm:ss
*/
final public static function factory( $dbType, $p = array() ) {
$canonicalDBTypes = array(
- 'mysql', 'postgres', 'sqlite', 'oracle', 'mssql', 'ibm_db2'
+ 'mysql', 'postgres', 'sqlite', 'oracle', 'mssql'
);
$dbType = strtolower( $dbType );
$class = 'Database' . ucfirst( $dbType );
+++ /dev/null
-<?php
-/**
- * This is the IBM DB2 database abstraction layer.
- * See maintenance/ibm_db2/README for development notes
- * and other specific information.
- *
- * 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 leo.petr+mediawiki@gmail.com
- */
-
-/**
- * This represents a column in a DB2 database
- * @ingroup Database
- */
-class IBM_DB2Field implements Field {
- private $name = '';
- private $tablename = '';
- private $type = '';
- private $nullable = false;
- private $max_length = 0;
-
- /**
- * Builder method for the class
- * @param $db DatabaseIbm_db2: Database interface
- * @param $table String: table name
- * @param $field String: column name
- * @return IBM_DB2Field
- */
- static function fromText( $db, $table, $field ) {
- global $wgDBmwschema;
-
- $q = <<<SQL
-SELECT
-lcase( coltype ) AS typname,
-nulls AS attnotnull, length AS attlen
-FROM sysibm.syscolumns
-WHERE tbcreator=%s AND tbname=%s AND name=%s;
-SQL;
- $res = $db->query(
- sprintf( $q,
- $db->addQuotes( $wgDBmwschema ),
- $db->addQuotes( $table ),
- $db->addQuotes( $field )
- )
- );
- $row = $db->fetchObject( $res );
- if ( !$row ) {
- return null;
- }
- $n = new IBM_DB2Field;
- $n->type = $row->typname;
- $n->nullable = ( $row->attnotnull == 'N' );
- $n->name = $field;
- $n->tablename = $table;
- $n->max_length = $row->attlen;
- return $n;
- }
- /**
- * Get column name
- * @return string column name
- */
- function name() { return $this->name; }
- /**
- * Get table name
- * @return string table name
- */
- function tableName() { return $this->tablename; }
- /**
- * Get column type
- * @return string column type
- */
- function type() { return $this->type; }
- /**
- * Can column be null?
- * @return bool true or false
- */
- function isNullable() { return $this->nullable; }
- /**
- * How much can you fit in the column per row?
- * @return int length
- */
- function maxLength() { return $this->max_length; }
-}
-
-/**
- * Wrapper around binary large objects
- * @ingroup Database
- */
-class IBM_DB2Blob {
- private $mData;
-
- public function __construct( $data ) {
- $this->mData = $data;
- }
-
- public function getData() {
- return $this->mData;
- }
-
- public function __toString() {
- return $this->mData;
- }
-}
-
-/**
- * Wrapper to address lack of certain operations in the DB2 driver
- * ( seek, num_rows )
- * @ingroup Database
- * @since 1.19
- */
-class IBM_DB2Result{
- private $db;
- private $result;
- private $num_rows;
- private $current_pos;
- private $columns = array();
- private $sql;
-
- private $resultSet = array();
- private $loadedLines = 0;
-
- /**
- * Construct and initialize a wrapper for DB2 query results
- * @param $db DatabaseBase
- * @param $result Object
- * @param $num_rows Integer
- * @param $sql String
- * @param $columns Array
- */
- public function __construct( $db, $result, $num_rows, $sql, $columns ) {
- $this->db = $db;
-
- if( $result instanceof ResultWrapper ) {
- $this->result = $result->result;
- } else {
- $this->result = $result;
- }
-
- $this->num_rows = $num_rows;
- $this->current_pos = 0;
- if ( $this->num_rows > 0 ) {
- // Make a lower-case list of the column names
- // By default, DB2 column names are capitalized
- // while MySQL column names are lowercase
-
- // Is there a reasonable maximum value for $i?
- // Setting to 2048 to prevent an infinite loop
- for( $i = 0; $i < 2048; $i++ ) {
- $name = db2_field_name( $this->result, $i );
- if ( $name != false ) {
- continue;
- }
- else {
- return false;
- }
-
- $this->columns[$i] = strtolower( $name );
- }
- }
-
- $this->sql = $sql;
- }
-
- /**
- * Unwrap the DB2 query results
- * @return mixed Object on success, false on failure
- */
- public function getResult() {
- if ( $this->result ) {
- return $this->result;
- }
- else return false;
- }
-
- /**
- * Get the number of rows in the result set
- * @return integer
- */
- public function getNum_rows() {
- return $this->num_rows;
- }
-
- /**
- * Return a row from the result set in object format
- * @return mixed Object on success, false on failure.
- */
- public function fetchObject() {
- if ( $this->result
- && $this->num_rows > 0
- && $this->current_pos >= 0
- && $this->current_pos < $this->num_rows )
- {
- $row = $this->fetchRow();
- $ret = new stdClass();
-
- foreach ( $row as $k => $v ) {
- $lc = $this->columns[$k];
- $ret->$lc = $v;
- }
- return $ret;
- }
- return false;
- }
-
- /**
- * Return a row form the result set in array format
- * @return mixed Array on success, false on failure
- * @throws DBUnexpectedError
- */
- public function fetchRow() {
- if ( $this->result
- && $this->num_rows > 0
- && $this->current_pos >= 0
- && $this->current_pos < $this->num_rows )
- {
- if ( $this->loadedLines <= $this->current_pos ) {
- $row = db2_fetch_array( $this->result );
- $this->resultSet[$this->loadedLines++] = $row;
- if ( $this->db->lastErrno() ) {
- throw new DBUnexpectedError( $this->db, 'Error in fetchRow(): '
- . htmlspecialchars( $this->db->lastError() ) );
- }
- }
-
- if ( $this->loadedLines > $this->current_pos ) {
- return $this->resultSet[$this->current_pos++];
- }
-
- }
- return false;
- }
-
- /**
- * Free a DB2 result object
- * @throws DBUnexpectedError
- */
- public function freeResult() {
- unset( $this->resultSet );
- if ( !@db2_free_result( $this->result ) ) {
- throw new DBUnexpectedError( $this, "Unable to free DB2 result\n" );
- }
- }
-}
-
-/**
- * Primary database interface
- * @ingroup Database
- */
-class DatabaseIbm_db2 extends DatabaseBase {
- /*
- * Inherited members
- protected $mLastQuery = '';
- protected $mPHPError = false;
-
- protected $mServer, $mUser, $mPassword, $mConn = null, $mDBname;
- protected $mOpened = false;
-
- protected $mTablePrefix;
- protected $mFlags;
- protected $mTrxLevel = 0;
- protected $mErrorCount = 0;
- protected $mLBInfo = array();
- protected $mFakeSlaveLag = null, $mFakeMaster = false;
- *
- */
-
- /** Database server port */
- protected $mPort = null;
- /** Schema for tables, stored procedures, triggers */
- protected $mSchema = null;
- /** Whether the schema has been applied in this session */
- protected $mSchemaSet = false;
- /** Result of last query */
- protected $mLastResult = null;
- /** Number of rows affected by last INSERT/UPDATE/DELETE */
- protected $mAffectedRows = null;
- /** Number of rows returned by last SELECT */
- protected $mNumRows = null;
- /** Current row number on the cursor of the last SELECT */
- protected $currentRow = 0;
-
- /** Connection config options - see constructor */
- public $mConnOptions = array();
- /** Statement config options -- see constructor */
- public $mStmtOptions = array();
-
- /** Default schema */
- const USE_GLOBAL = 'get from global';
-
- /** Option that applies to nothing */
- const NONE_OPTION = 0x00;
- /** Option that applies to connection objects */
- const CONN_OPTION = 0x01;
- /** Option that applies to statement objects */
- const STMT_OPTION = 0x02;
-
- /** Regular operation mode -- minimal debug messages */
- const REGULAR_MODE = 'regular';
- /** Installation mode -- lots of debug messages */
- const INSTALL_MODE = 'install';
-
- /** Controls the level of debug message output */
- protected $mMode = self::REGULAR_MODE;
-
- /** Last sequence value used for a primary key */
- protected $mInsertId = null;
-
- ######################################
- # Getters and Setters
- ######################################
-
- /**
- * Returns true if this database supports (and uses) cascading deletes
- * @return bool
- */
- function cascadingDeletes() {
- return true;
- }
-
- /**
- * Returns true if this database supports (and uses) triggers (e.g. on the
- * page table)
- * @return bool
- */
- function cleanupTriggers() {
- return true;
- }
-
- /**
- * Returns true if this database is strict about what can be put into an
- * IP field.
- * Specifically, it uses a NULL value instead of an empty string.
- * @return bool
- */
- function strictIPs() {
- return true;
- }
-
- /**
- * Returns true if this database uses timestamps rather than integers
- * @return bool
- */
- function realTimestamps() {
- return true;
- }
-
- /**
- * Returns true if this database does an implicit sort when doing GROUP BY
- * @return bool
- */
- function implicitGroupby() {
- return false;
- }
-
- /**
- * Returns true if this database does an implicit order by when the column
- * has an index
- * For example: SELECT page_title FROM page LIMIT 1
- * @return bool
- */
- function implicitOrderby() {
- return false;
- }
-
- /**
- * Returns true if this database can do a native search on IP columns
- * e.g. this works as expected: .. WHERE rc_ip = '127.42.12.102/32';
- * @return bool
- */
- function searchableIPs() {
- return true;
- }
-
- /**
- * Returns true if this database can use functional indexes
- * @return bool
- */
- function functionalIndexes() {
- return true;
- }
-
- /**
- * Returns a unique string representing the wiki on the server
- * @return string
- */
- public function getWikiID() {
- if( $this->mSchema ) {
- return "{$this->mDBname}-{$this->mSchema}";
- } else {
- return $this->mDBname;
- }
- }
-
- /**
- * Returns the database software identifieir
- * @return string
- */
- public function getType() {
- return 'ibm_db2';
- }
-
- /**
- * Returns the database connection object
- * @return Object
- */
- public function getDb() {
- return $this->mConn;
- }
-
- /**
- *
- * @param $server String: hostname of database server
- * @param $user String: username
- * @param $password String: password
- * @param $dbName String: database name on the server
- * @param $flags Integer: database behaviour flags (optional, unused)
- * @param $schema String
- */
- public function __construct( $server = false, $user = false,
- $password = false,
- $dbName = false, $flags = 0,
- $schema = self::USE_GLOBAL )
- {
- global $wgDBmwschema;
-
- if ( $schema == self::USE_GLOBAL ) {
- $this->mSchema = $wgDBmwschema;
- } else {
- $this->mSchema = $schema;
- }
-
- // configure the connection and statement objects
- $this->setDB2Option( 'db2_attr_case', 'DB2_CASE_LOWER',
- self::CONN_OPTION | self::STMT_OPTION );
- $this->setDB2Option( 'deferred_prepare', 'DB2_DEFERRED_PREPARE_ON',
- self::STMT_OPTION );
- $this->setDB2Option( 'rowcount', 'DB2_ROWCOUNT_PREFETCH_ON',
- self::STMT_OPTION );
- parent::__construct( $server, $user, $password, $dbName, DBO_TRX | $flags );
- }
-
- /**
- * Enables options only if the ibm_db2 extension version supports them
- * @param $name String: name of the option in the options array
- * @param $const String: name of the constant holding the right option value
- * @param $type Integer: whether this is a Connection or Statement otion
- */
- private function setDB2Option( $name, $const, $type ) {
- if ( defined( $const ) ) {
- if ( $type & self::CONN_OPTION ) {
- $this->mConnOptions[$name] = constant( $const );
- }
- if ( $type & self::STMT_OPTION ) {
- $this->mStmtOptions[$name] = constant( $const );
- }
- } else {
- $this->installPrint(
- "$const is not defined. ibm_db2 version is likely too low." );
- }
- }
-
- /**
- * Outputs debug information in the appropriate place
- * @param $string String: the relevant debug message
- */
- private function installPrint( $string ) {
- wfDebug( "$string\n" );
- if ( $this->mMode == self::INSTALL_MODE ) {
- print "<li><pre>$string</pre></li>";
- flush();
- }
- }
-
- /**
- * Opens a database connection and returns it
- * Closes any existing connection
- *
- * @param $server String: hostname
- * @param $user String
- * @param $password String
- * @param $dbName String: database name
- * @throws DBConnectionError
- * @return DatabaseBase a fresh connection
- */
- public function open( $server, $user, $password, $dbName ) {
- wfProfileIn( __METHOD__ );
-
- # Load IBM DB2 driver if missing
- wfDl( 'ibm_db2' );
-
- # Test for IBM DB2 support, to avoid suppressed fatal error
- if ( !function_exists( 'db2_connect' ) ) {
- throw new DBConnectionError( $this, "DB2 functions missing, have you enabled the ibm_db2 extension for PHP?" );
- }
-
- global $wgDBport;
-
- // Close existing connection
- $this->close();
- // Cache conn info
- $this->mServer = $server;
- $this->mPort = $port = $wgDBport;
- $this->mUser = $user;
- $this->mPassword = $password;
- $this->mDBname = $dbName;
-
- $this->openUncataloged( $dbName, $user, $password, $server, $port );
-
- if ( !$this->mConn ) {
- $this->installPrint( "DB connection error\n" );
- $this->installPrint(
- "Server: $server, Database: $dbName, User: $user, Password: "
- . substr( $password, 0, 3 ) . "...\n" );
- $this->installPrint( $this->lastError() . "\n" );
- wfProfileOut( __METHOD__ );
- wfDebug( "DB connection error\n" );
- wfDebug( "Server: $server, Database: $dbName, User: $user, Password: " . substr( $password, 0, 3 ) . "...\n" );
- wfDebug( $this->lastError() . "\n" );
- throw new DBConnectionError( $this, $this->lastError() );
- }
-
- // Some MediaWiki code is still transaction-less (?).
- // The strategy is to keep AutoCommit on for that code
- // but switch it off whenever a transaction is begun.
- db2_autocommit( $this->mConn, DB2_AUTOCOMMIT_ON );
-
- $this->mOpened = true;
- $this->applySchema();
-
- wfProfileOut( __METHOD__ );
- return $this->mConn;
- }
-
- /**
- * Opens a cataloged database connection, sets mConn
- */
- protected function openCataloged( $dbName, $user, $password ) {
- wfSuppressWarnings();
- $this->mConn = db2_pconnect( $dbName, $user, $password );
- wfRestoreWarnings();
- }
-
- /**
- * Opens an uncataloged database connection, sets mConn
- */
- protected function openUncataloged( $dbName, $user, $password, $server, $port )
- {
- $dsn = "DRIVER={IBM DB2 ODBC DRIVER};DATABASE=$dbName;CHARSET=UTF-8;HOSTNAME=$server;PORT=$port;PROTOCOL=TCPIP;UID=$user;PWD=$password;";
- wfSuppressWarnings();
- $this->mConn = db2_pconnect( $dsn, "", "", array() );
- wfRestoreWarnings();
- }
-
- /**
- * Closes a database connection, if it is open
- * Returns success, true if already closed
- * @return bool
- */
- protected function closeConnection() {
- return db2_close( $this->mConn );
- }
-
- /**
- * Retrieves the most current database error
- * Forces a database rollback
- * @return bool|string
- */
- public function lastError() {
- $connerr = db2_conn_errormsg();
- if ( $connerr ) {
- //$this->rollback( __METHOD__ );
- return $connerr;
- }
- $stmterr = db2_stmt_errormsg();
- if ( $stmterr ) {
- //$this->rollback( __METHOD__ );
- return $stmterr;
- }
-
- return false;
- }
-
- /**
- * Get the last error number
- * Return 0 if no error
- * @return integer
- */
- public function lastErrno() {
- $connerr = db2_conn_error();
- if ( $connerr ) {
- return $connerr;
- }
- $stmterr = db2_stmt_error();
- if ( $stmterr ) {
- return $stmterr;
- }
- return 0;
- }
-
- /**
- * Is a database connection open?
- * @return
- */
- public function isOpen() { return $this->mOpened; }
-
- /**
- * The DBMS-dependent part of query()
- * @param $sql String: SQL query.
- * @throws DBUnexpectedError
- * @return object Result object for fetch functions or false on failure
- */
- protected function doQuery( $sql ) {
- $this->applySchema();
-
- // Needed to handle any UTF-8 encoding issues in the raw sql
- // Note that we fully support prepared statements for DB2
- // prepare() and execute() should be used instead of doQuery() whenever possible
- $sql = utf8_decode( $sql );
-
- $ret = db2_exec( $this->mConn, $sql, $this->mStmtOptions );
- if( $ret == false ) {
- $error = db2_stmt_errormsg();
-
- $this->installPrint( "<pre>$sql</pre>" );
- $this->installPrint( $error );
- throw new DBUnexpectedError( $this, 'SQL error: '
- . htmlspecialchars( $error ) );
- }
- $this->mLastResult = $ret;
- $this->mAffectedRows = null; // Not calculated until asked for
- return $ret;
- }
-
- /**
- * @return string Version information from the database
- */
- public function getServerVersion() {
- $info = db2_server_info( $this->mConn );
- return $info->DBMS_VER;
- }
-
- /**
- * Queries whether a given table exists
- * @return boolean
- */
- public function tableExists( $table, $fname = __METHOD__ ) {
- $schema = $this->mSchema;
-
- $sql = "SELECT COUNT( * ) FROM SYSIBM.SYSTABLES ST WHERE ST.NAME = '" .
- strtoupper( $table ) .
- "' AND ST.CREATOR = '" .
- strtoupper( $schema ) . "'";
- $res = $this->query( $sql );
- if ( !$res ) {
- return false;
- }
-
- // If the table exists, there should be one of it
- $row = $this->fetchRow( $res );
- $count = $row[0];
- if ( $count == '1' || $count == 1 ) {
- return true;
- }
-
- return false;
- }
-
- /**
- * Fetch the next row from the given result object, in object form.
- * Fields can be retrieved with $row->fieldname, with fields acting like
- * member variables.
- * If no more rows are available, false is returned.
- *
- * @param $res array|ResultWrapper SQL result object as returned from Database::query(), etc.
- * @return object|bool
- * @throws DBUnexpectedError Thrown if the database returns an error
- */
- public function fetchObject( $res ) {
- if ( $res instanceof ResultWrapper ) {
- $res = $res->result;
- }
- wfSuppressWarnings();
- $row = db2_fetch_object( $res );
- wfRestoreWarnings();
- if( $this->lastErrno() ) {
- throw new DBUnexpectedError( $this, 'Error in fetchObject(): '
- . htmlspecialchars( $this->lastError() ) );
- }
- return $row;
- }
-
- /**
- * Fetch the next row from the given result object, in associative array
- * form. Fields are retrieved with $row['fieldname'].
- * If no more rows are available, false is returned.
- *
- * @param $res array|ResultWrapper SQL result object as returned from Database::query(), etc.
- * @return array|bool
- * @throws DBUnexpectedError Thrown if the database returns an error
- */
- public function fetchRow( $res ) {
- if ( $res instanceof ResultWrapper ) {
- $res = $res->result;
- }
- if ( db2_num_rows( $res ) > 0) {
- wfSuppressWarnings();
- $row = db2_fetch_array( $res );
- wfRestoreWarnings();
- if ( $this->lastErrno() ) {
- throw new DBUnexpectedError( $this, 'Error in fetchRow(): '
- . htmlspecialchars( $this->lastError() ) );
- }
- return $row;
- }
- return false;
- }
-
- /**
- * Escapes strings
- * Doesn't escape numbers
- *
- * @param $s String: string to escape
- * @return string escaped string
- */
- public function addQuotes( $s ) {
- //$this->installPrint( "DB2::addQuotes( $s )\n" );
- if ( is_null( $s ) ) {
- return 'NULL';
- } elseif ( $s instanceof Blob ) {
- return "'" . $s->fetch( $s ) . "'";
- } elseif ( $s instanceof IBM_DB2Blob ) {
- return "'" . $this->decodeBlob( $s ) . "'";
- }
- $s = $this->strencode( $s );
- if ( is_numeric( $s ) ) {
- return $s;
- } else {
- return "'$s'";
- }
- }
-
- /**
- * Verifies that a DB2 column/field type is numeric
- *
- * @param $type String: DB2 column type
- * @return Boolean: true if numeric
- */
- public function is_numeric_type( $type ) {
- switch ( strtoupper( $type ) ) {
- case 'SMALLINT':
- case 'INTEGER':
- case 'INT':
- case 'BIGINT':
- case 'DECIMAL':
- case 'REAL':
- case 'DOUBLE':
- case 'DECFLOAT':
- return true;
- }
- return false;
- }
-
- /**
- * Alias for addQuotes()
- * @param $s String: string to escape
- * @return string escaped string
- */
- public function strencode( $s ) {
- // Bloody useless function
- // Prepends backslashes to \x00, \n, \r, \, ', " and \x1a.
- // But also necessary
- $s = db2_escape_string( $s );
- // Wide characters are evil -- some of them look like '
- $s = utf8_encode( $s );
- // Fix its stupidity
- $from = array( "\\\\", "\\'", '\\n', '\\t', '\\"', '\\r' );
- $to = array( "\\", "''", "\n", "\t", '"', "\r" );
- $s = str_replace( $from, $to, $s ); // DB2 expects '', not \' escaping
- return $s;
- }
-
- /**
- * Switch into the database schema
- */
- protected function applySchema() {
- if ( !( $this->mSchemaSet ) ) {
- $this->mSchemaSet = true;
- $this->begin( __METHOD__ );
- $this->doQuery( "SET SCHEMA = $this->mSchema" );
- $this->commit( __METHOD__ );
- }
- }
-
- /**
- * Start a transaction (mandatory)
- */
- protected function doBegin( $fname = 'DatabaseIbm_db2::begin' ) {
- // BEGIN is implicit for DB2
- // However, it requires that AutoCommit be off.
-
- // Some MediaWiki code is still transaction-less (?).
- // The strategy is to keep AutoCommit on for that code
- // but switch it off whenever a transaction is begun.
- db2_autocommit( $this->mConn, DB2_AUTOCOMMIT_OFF );
-
- $this->mTrxLevel = 1;
- }
-
- /**
- * End a transaction
- * Must have a preceding begin()
- */
- protected function doCommit( $fname = 'DatabaseIbm_db2::commit' ) {
- db2_commit( $this->mConn );
-
- // Some MediaWiki code is still transaction-less (?).
- // The strategy is to keep AutoCommit on for that code
- // but switch it off whenever a transaction is begun.
- db2_autocommit( $this->mConn, DB2_AUTOCOMMIT_ON );
-
- $this->mTrxLevel = 0;
- }
-
- /**
- * Cancel a transaction
- */
- protected function doRollback( $fname = 'DatabaseIbm_db2::rollback' ) {
- db2_rollback( $this->mConn );
- // turn auto-commit back on
- // not sure if this is appropriate
- db2_autocommit( $this->mConn, DB2_AUTOCOMMIT_ON );
- $this->mTrxLevel = 0;
- }
-
- /**
- * Makes an encoded list of strings from an array
- * $mode:
- * LIST_COMMA - comma separated, no field names
- * LIST_AND - ANDed WHERE clause (without the WHERE)
- * 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
- * LIST_SET_PREPARED - like LIST_SET, except with ? tokens as values
- * @param array $a
- * @param int $mode
- * @throws DBUnexpectedError
- * @return string
- */
- function makeList( $a, $mode = LIST_COMMA ) {
- if ( !is_array( $a ) ) {
- throw new DBUnexpectedError( $this,
- 'DatabaseIbm_db2::makeList called with incorrect parameters' );
- }
-
- // if this is for a prepared UPDATE statement
- // (this should be promoted to the parent class
- // once other databases use prepared statements)
- if ( $mode == LIST_SET_PREPARED ) {
- $first = true;
- $list = '';
- foreach ( $a as $field => $value ) {
- if ( !$first ) {
- $list .= ", $field = ?";
- } else {
- $list .= "$field = ?";
- $first = false;
- }
- }
- $list .= '';
-
- return $list;
- }
-
- // otherwise, call the usual function
- return parent::makeList( $a, $mode );
- }
-
- /**
- * Construct a LIMIT query with optional offset
- * This is used for query pages
- *
- * @param $sql string SQL query we will append the limit too
- * @param $limit integer the SQL limit
- * @param bool|int $offset SQL offset (default false)
- * @throws DBUnexpectedError
- * @return string
- */
- public function limitResult( $sql, $limit, $offset=false ) {
- if( !is_numeric( $limit ) ) {
- throw new DBUnexpectedError( $this,
- "Invalid non-numeric limit passed to limitResult()\n" );
- }
- if( $offset ) {
- if ( stripos( $sql, 'where' ) === false ) {
- return "$sql AND ( ROWNUM BETWEEN $offset AND $offset+$limit )";
- } else {
- return "$sql WHERE ( ROWNUM BETWEEN $offset AND $offset+$limit )";
- }
- }
- return "$sql FETCH FIRST $limit ROWS ONLY ";
- }
-
- /**
- * Handle reserved keyword replacement in table names
- *
- * @param $name Object
- * @param $format String Ignored parameter Default 'quoted'Boolean
- * @return String
- */
- public function tableName( $name, $format = 'quoted' ) {
- // we want maximum compatibility with MySQL schema
- return $name;
- }
-
- /**
- * Generates a timestamp in an insertable format
- *
- * @param $ts string timestamp
- * @return String: timestamp value
- */
- public function timestamp( $ts = 0 ) {
- // TS_MW cannot be easily distinguished from an integer
- return wfTimestamp( TS_DB2, $ts );
- }
-
- /**
- * Return the next in a sequence, save the value for retrieval via insertId()
- * @param $seqName String: name of a defined sequence in the database
- * @return int next value in that sequence
- */
- public function nextSequenceValue( $seqName ) {
- // Not using sequences in the primary schema to allow for easier migration
- // from MySQL
- // Emulating MySQL behaviour of using NULL to signal that sequences
- // aren't used
- /*
- $safeseq = preg_replace( "/'/", "''", $seqName );
- $res = $this->query( "VALUES NEXTVAL FOR $safeseq" );
- $row = $this->fetchRow( $res );
- $this->mInsertId = $row[0];
- return $this->mInsertId;
- */
- return null;
- }
-
- /**
- * This must be called after nextSequenceVal
- * @return int Last sequence value used as a primary key
- */
- public function insertId() {
- return $this->mInsertId;
- }
-
- /**
- * Updates the mInsertId property with the value of the last insert
- * into a generated column
- *
- * @param $table String: sanitized table name
- * @param $primaryKey Mixed: string name of the primary key
- * @param $stmt Resource: prepared statement resource
- * of the SELECT primary_key FROM FINAL TABLE ( INSERT ... ) form
- */
- private function calcInsertId( $table, $primaryKey, $stmt ) {
- if ( $primaryKey ) {
- $this->mInsertId = db2_last_insert_id( $this->mConn );
- }
- }
-
- /**
- * INSERT wrapper, inserts an array into a table
- *
- * $args may be a single associative array, or an array of arrays
- * with numeric keys, for multi-row insert
- *
- * @param $table String: Name of the table to insert to.
- * @param $args Array: Items to insert into the table.
- * @param $fname String: Name of the function, for profiling
- * @param $options String or Array. Valid options: IGNORE
- *
- * @return bool Success of insert operation. IGNORE always returns true.
- */
- public function insert( $table, $args, $fname = 'DatabaseIbm_db2::insert',
- $options = array() )
- {
- if ( !count( $args ) ) {
- return true;
- }
- // get database-specific table name (not used)
- $table = $this->tableName( $table );
- // format options as an array
- $options = IBM_DB2Helper::makeArray( $options );
- // format args as an array of arrays
- if ( !( isset( $args[0] ) && is_array( $args[0] ) ) ) {
- $args = array( $args );
- }
-
- // prevent insertion of NULL into primary key columns
- list( $args, $primaryKeys ) = $this->removeNullPrimaryKeys( $table, $args );
- // if there's only one primary key
- // we'll be able to read its value after insertion
- $primaryKey = false;
- if ( count( $primaryKeys ) == 1 ) {
- $primaryKey = $primaryKeys[0];
- }
-
- // get column names
- $keys = array_keys( $args[0] );
- $key_count = count( $keys );
-
- // If IGNORE is set, we use savepoints to emulate mysql's behavior
- $ignore = in_array( 'IGNORE', $options ) ? 'mw' : '';
-
- // assume success
- $res = true;
- // If we are not in a transaction, we need to be for savepoint trickery
- if ( !$this->mTrxLevel ) {
- $this->begin( __METHOD__ );
- }
-
- $sql = "INSERT INTO $table ( " . implode( ',', $keys ) . ' ) VALUES ';
- if ( $key_count == 1 ) {
- $sql .= '( ? )';
- } else {
- $sql .= '( ?' . str_repeat( ',?', $key_count-1 ) . ' )';
- }
- $this->installPrint( "Preparing the following SQL:" );
- $this->installPrint( "$sql" );
- $this->installPrint( print_r( $args, true ));
- $stmt = $this->prepare( $sql );
-
- // start a transaction/enter transaction mode
- $this->begin( __METHOD__ );
-
- if ( !$ignore ) {
- //$first = true;
- foreach ( $args as $row ) {
- //$this->installPrint( "Inserting " . print_r( $row, true ));
- // insert each row into the database
- $res = $res & $this->execute( $stmt, $row );
- if ( !$res ) {
- $this->installPrint( 'Last error:' );
- $this->installPrint( $this->lastError() );
- }
- // get the last inserted value into a generated column
- $this->calcInsertId( $table, $primaryKey, $stmt );
- }
- } else {
- $olde = error_reporting( 0 );
- // For future use, we may want to track the number of actual inserts
- // Right now, insert (all writes) simply return true/false
- $numrowsinserted = 0;
-
- // always return true
- $res = true;
-
- foreach ( $args as $row ) {
- $overhead = "SAVEPOINT $ignore ON ROLLBACK RETAIN CURSORS";
- db2_exec( $this->mConn, $overhead, $this->mStmtOptions );
-
- $res2 = $this->execute( $stmt, $row );
-
- if ( !$res2 ) {
- $this->installPrint( 'Last error:' );
- $this->installPrint( $this->lastError() );
- }
- // get the last inserted value into a generated column
- $this->calcInsertId( $table, $primaryKey, $stmt );
-
- $errNum = $this->lastErrno();
- if ( $errNum ) {
- db2_exec( $this->mConn, "ROLLBACK TO SAVEPOINT $ignore",
- $this->mStmtOptions );
- } else {
- db2_exec( $this->mConn, "RELEASE SAVEPOINT $ignore",
- $this->mStmtOptions );
- $numrowsinserted++;
- }
- }
-
- $olde = error_reporting( $olde );
- // Set the affected row count for the whole operation
- $this->mAffectedRows = $numrowsinserted;
- }
- // commit either way
- $this->commit( __METHOD__ );
- $this->freePrepared( $stmt );
-
- return $res;
- }
-
- /**
- * Given a table name and a hash of columns with values
- * Removes primary key columns from the hash where the value is NULL
- *
- * @param $table String: name of the table
- * @param $args Array of hashes of column names with values
- * @return Array: tuple( filtered array of columns, array of primary keys )
- */
- private function removeNullPrimaryKeys( $table, $args ) {
- $schema = $this->mSchema;
-
- // find out the primary keys
- $keyres = $this->doQuery( "SELECT NAME FROM SYSIBM.SYSCOLUMNS WHERE TBNAME = '"
- . strtoupper( $table )
- . "' AND TBCREATOR = '"
- . strtoupper( $schema )
- . "' AND KEYSEQ > 0" );
-
- $keys = array();
- for (
- $row = $this->fetchRow( $keyres );
- $row != null;
- $row = $this->fetchRow( $keyres )
- )
- {
- $keys[] = strtolower( $row[0] );
- }
- // remove primary keys
- foreach ( $args as $ai => $row ) {
- foreach ( $keys as $key ) {
- if ( $row[$key] == null ) {
- unset( $row[$key] );
- }
- }
- $args[$ai] = $row;
- }
- // return modified hash
- return array( $args, $keys );
- }
-
- /**
- * UPDATE wrapper, takes a condition array and a SET array
- *
- * @param $table String: The table to UPDATE
- * @param $values array An array of values to SET
- * @param $conds array An array of conditions ( WHERE ). Use '*' to update all rows.
- * @param $fname String: The Class::Function calling this function
- * ( for the log )
- * @param $options array An array of UPDATE options, can be one or
- * more of IGNORE, LOW_PRIORITY
- * @return Boolean
- */
- public function update( $table, $values, $conds, $fname = 'DatabaseIbm_db2::update',
- $options = array() )
- {
- $table = $this->tableName( $table );
- $opts = $this->makeUpdateOptions( $options );
- $sql = "UPDATE $opts $table SET "
- . $this->makeList( $values, LIST_SET_PREPARED );
- if ( $conds != '*' ) {
- $sql .= " WHERE " . $this->makeList( $conds, LIST_AND );
- }
- $stmt = $this->prepare( $sql );
- $this->installPrint( 'UPDATE: ' . print_r( $values, true ) );
- // assuming for now that an array with string keys will work
- // if not, convert to simple array first
- $result = $this->execute( $stmt, $values );
- $this->freePrepared( $stmt );
-
- return $result;
- }
-
- /**
- * DELETE query wrapper
- *
- * Use $conds == "*" to delete all rows
- * @param array $table
- * @param array|string $conds
- * @param string $fname
- * @throws DBUnexpectedError
- * @return bool|ResultWrapper
- */
- public function delete( $table, $conds, $fname = 'DatabaseIbm_db2::delete' ) {
- if ( !$conds ) {
- throw new DBUnexpectedError( $this,
- 'DatabaseIbm_db2::delete() called with no conditions' );
- }
- $table = $this->tableName( $table );
- $sql = "DELETE FROM $table";
- if ( $conds != '*' ) {
- $sql .= ' WHERE ' . $this->makeList( $conds, LIST_AND );
- }
- $result = $this->query( $sql, $fname );
-
- return $result;
- }
-
- /**
- * Returns the number of rows affected by the last query or 0
- * @return Integer: the number of rows affected by the last query
- */
- public function affectedRows() {
- if ( !is_null( $this->mAffectedRows ) ) {
- // Forced result for simulated queries
- return $this->mAffectedRows;
- }
- if( empty( $this->mLastResult ) ) {
- return 0;
- }
- return db2_num_rows( $this->mLastResult );
- }
-
- /**
- * Returns the number of rows in the result set
- * Has to be called right after the corresponding select query
- * @param $res Object result set
- * @return Integer: number of rows
- */
- public function numRows( $res ) {
- if ( $res instanceof ResultWrapper ) {
- $res = $res->result;
- }
-
- if ( $this->mNumRows ) {
- return $this->mNumRows;
- } else {
- return 0;
- }
- }
-
- /**
- * Moves the row pointer of the result set
- * @param $res Object: result set
- * @param $row Integer: row number
- * @return bool success or failure
- */
- public function dataSeek( $res, $row ) {
- if ( $res instanceof ResultWrapper ) {
- return $res = $res->result;
- }
- if ( $res instanceof IBM_DB2Result ) {
- return $res->dataSeek( $row );
- }
- wfDebug( "dataSeek operation in DB2 database\n" );
- return false;
- }
-
- ###
- # Fix notices in Block.php
- ###
-
- /**
- * Frees memory associated with a statement resource
- * @param $res Object: statement resource to free
- * @throws DBUnexpectedError
- * @return Boolean success or failure
- */
- public function freeResult( $res ) {
- if ( $res instanceof ResultWrapper ) {
- $res = $res->result;
- }
- wfSuppressWarnings();
- $ok = db2_free_result( $res );
- wfRestoreWarnings();
- if ( !$ok ) {
- throw new DBUnexpectedError( $this, "Unable to free DB2 result\n" );
- }
- }
-
- /**
- * Returns the number of columns in a resource
- * @param $res Object: statement resource
- * @return Number of fields/columns in resource
- */
- public function numFields( $res ) {
- if ( $res instanceof ResultWrapper ) {
- $res = $res->result;
- }
- if ( $res instanceof IBM_DB2Result ) {
- $res = $res->getResult();
- }
- return db2_num_fields( $res );
- }
-
- /**
- * Returns the nth column name
- * @param $res Object: statement resource
- * @param $n Integer: Index of field or column
- * @return String name of nth column
- */
- public function fieldName( $res, $n ) {
- if ( $res instanceof ResultWrapper ) {
- $res = $res->result;
- }
- if ( $res instanceof IBM_DB2Result ) {
- $res = $res->getResult();
- }
- return db2_field_name( $res, $n );
- }
-
- /**
- * SELECT wrapper
- *
- * @param $table Array or string, table name(s) (prefix auto-added)
- * @param $vars Array or string, field name(s) to be retrieved
- * @param $conds Array or string, condition(s) for WHERE
- * @param $fname String: calling function name (use __METHOD__)
- * for logs/profiling
- * @param $options array Associative array of options
- * (e.g. array( 'GROUP BY' => 'page_title' )),
- * see Database::makeSelectOptions code for list of
- * supported stuff
- * @param $join_conds array Associative array of table join conditions (optional)
- * (e.g. array( 'page' => array('LEFT JOIN',
- * 'page_latest=rev_id') )
- * @return Mixed: database result resource for fetch functions or false
- * on failure
- */
- public function select( $table, $vars, $conds = '', $fname = 'DatabaseIbm_db2::select', $options = array(), $join_conds = array() )
- {
- $res = parent::select( $table, $vars, $conds, $fname, $options,
- $join_conds );
- $sql = $this->selectSQLText( $table, $vars, $conds, $fname, $options, $join_conds );
-
- // We must adjust for offset
- if ( isset( $options['LIMIT'] ) && isset ( $options['OFFSET'] ) ) {
- $limit = $options['LIMIT'];
- $offset = $options['OFFSET'];
- }
-
- // DB2 does not have a proper num_rows() function yet, so we must emulate
- // DB2 9.5.4 and the corresponding ibm_db2 driver will introduce
- // a working one
- // TODO: Yay!
-
- // we want the count
- $vars2 = array( 'count( * ) as num_rows' );
- // respecting just the limit option
- $options2 = array();
- if ( isset( $options['LIMIT'] ) ) {
- $options2['LIMIT'] = $options['LIMIT'];
- }
- // but don't try to emulate for GROUP BY
- if ( isset( $options['GROUP BY'] ) ) {
- return $res;
- }
-
- $res2 = parent::select( $table, $vars2, $conds, $fname, $options2,
- $join_conds );
-
- $obj = $this->fetchObject( $res2 );
- $this->mNumRows = $obj->num_rows;
-
- return new ResultWrapper( $this, new IBM_DB2Result( $this, $res, $obj->num_rows, $vars, $sql ) );
- }
-
- /**
- * Handles ordering, grouping, and having options ('GROUP BY' => colname)
- * Has limited support for per-column options (colnum => 'DISTINCT')
- *
- * @private
- *
- * @param $options array 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['DISTINCT'] )
- || isset( $noKeyOptions['DISTINCTROW'] ) )
- {
- $startOpts .= 'DISTINCT';
- }
-
- return array( $startOpts, '', $preLimitTail, $postLimitTail );
- }
-
- /**
- * Returns link to IBM DB2 free download
- * @return String: wikitext of a link to the server software's web site
- */
- public static function getSoftwareLink() {
- return '[http://www.ibm.com/db2/express/ IBM DB2]';
- }
-
- /**
- * Get search engine class. All subclasses of this
- * need to implement this if they wish to use searching.
- *
- * @return String
- */
- public function getSearchEngine() {
- return 'SearchIBM_DB2';
- }
-
- /**
- * Did the last database access fail because of deadlock?
- * @return Boolean
- */
- public function wasDeadlock() {
- // get SQLSTATE
- $err = $this->lastErrno();
- switch( $err ) {
- // This is literal port of the MySQL logic and may be wrong for DB2
- case '40001': // sql0911n, Deadlock or timeout, rollback
- case '57011': // sql0904n, Resource unavailable, no rollback
- case '57033': // sql0913n, Deadlock or timeout, no rollback
- $this->installPrint( "In a deadlock because of SQLSTATE $err" );
- return true;
- }
- return false;
- }
-
- /**
- * Ping the server and try to reconnect if it there is no connection
- * The connection may be closed and reopened while this happens
- * @return Boolean: whether the connection exists
- */
- public function ping() {
- // db2_ping() doesn't exist
- // Emulate
- $this->close();
- $this->openUncataloged( $this->mDBName, $this->mUser,
- $this->mPassword, $this->mServer, $this->mPort );
-
- return false;
- }
- ######################################
- # Unimplemented and not applicable
- ######################################
-
- /**
- * Only useful with fake prepare like in base Database class
- * @return string
- */
- public function fillPreparedArg( $matches ) {
- $this->installPrint( 'Not useful for DB2: fillPreparedArg()' );
- return '';
- }
-
- ######################################
- # Reflection
- ######################################
-
- /**
- * Returns information about an index
- * If errors are explicitly ignored, returns NULL on failure
- * @param $table String: table name
- * @param $index String: index name
- * @param $fname String: function name for logging and profiling
- * @return Object query row in object form
- */
- public function indexInfo( $table, $index,
- $fname = 'DatabaseIbm_db2::indexExists' )
- {
- $table = $this->tableName( $table );
- $sql = <<<SQL
-SELECT name as indexname
-FROM sysibm.sysindexes si
-WHERE si.name='$index' AND si.tbname='$table'
-AND sc.tbcreator='$this->mSchema'
-SQL;
- $res = $this->query( $sql, $fname );
- if ( !$res ) {
- return null;
- }
- $row = $this->fetchObject( $res );
- if ( $row != null ) {
- return $row;
- } else {
- return false;
- }
- }
-
- /**
- * Returns an information object on a table column
- * @param $table String: table name
- * @param $field String: column name
- * @return IBM_DB2Field
- */
- public function fieldInfo( $table, $field ) {
- return IBM_DB2Field::fromText( $this, $table, $field );
- }
-
- /**
- * db2_field_type() wrapper
- * @param $res Object: result of executed statement
- * @param $index Mixed: number or name of the column
- * @return String column type
- */
- public function fieldType( $res, $index ) {
- if ( $res instanceof ResultWrapper ) {
- $res = $res->result;
- }
- if ( $res instanceof IBM_DB2Result ) {
- $res = $res->getResult();
- }
- return db2_field_type( $res, $index );
- }
-
- /**
- * Verifies that an index was created as unique
- * @param $table String: table name
- * @param $index String: index name
- * @param $fname string function name for profiling
- * @return Bool
- */
- public function indexUnique ( $table, $index,
- $fname = 'DatabaseIbm_db2::indexUnique' )
- {
- $table = $this->tableName( $table );
- $sql = <<<SQL
-SELECT si.name as indexname
-FROM sysibm.sysindexes si
-WHERE si.name='$index' AND si.tbname='$table'
-AND sc.tbcreator='$this->mSchema'
-AND si.uniquerule IN ( 'U', 'P' )
-SQL;
- $res = $this->query( $sql, $fname );
- if ( !$res ) {
- return null;
- }
- if ( $this->fetchObject( $res ) ) {
- return true;
- }
- return false;
-
- }
-
- /**
- * Returns the size of a text field, or -1 for "unlimited"
- * @param $table String: table name
- * @param $field String: column name
- * @return Integer: length or -1 for unlimited
- */
- public function textFieldSize( $table, $field ) {
- $table = $this->tableName( $table );
- $sql = <<<SQL
-SELECT length as size
-FROM sysibm.syscolumns sc
-WHERE sc.name='$field' AND sc.tbname='$table'
-AND sc.tbcreator='$this->mSchema'
-SQL;
- $res = $this->query( $sql );
- $row = $this->fetchObject( $res );
- $size = $row->size;
- return $size;
- }
-
- /**
- * Description is left as an exercise for the reader
- * @param $b Mixed: data to be encoded
- * @return IBM_DB2Blob
- */
- public function encodeBlob( $b ) {
- return new IBM_DB2Blob( $b );
- }
-
- /**
- * Description is left as an exercise for the reader
- * @param $b IBM_DB2Blob: data to be decoded
- * @return mixed
- */
- public function decodeBlob( $b ) {
- return "$b";
- }
-
- /**
- * Convert into a list of string being concatenated
- * @param $stringList Array: strings that need to be joined together
- * by the SQL engine
- * @return String: joined by the concatenation operator
- */
- public function buildConcat( $stringList ) {
- // || is equivalent to CONCAT
- // Sample query: VALUES 'foo' CONCAT 'bar' CONCAT 'baz'
- return implode( ' || ', $stringList );
- }
-
- /**
- * Generates the SQL required to convert a DB2 timestamp into a Unix epoch
- * @param $column String: name of timestamp column
- * @return String: SQL code
- */
- public function extractUnixEpoch( $column ) {
- // TODO
- // see SpecialAncientpages
- }
-
- ######################################
- # Prepared statements
- ######################################
-
- /**
- * Intended to be compatible with the PEAR::DB wrapper functions.
- * http://pear.php.net/manual/en/package.database.db.intro-execute.php
- *
- * ? = scalar value, quoted as necessary
- * ! = raw SQL bit (a function for instance)
- * & = filename; reads the file and inserts as a blob
- * (we don't use this though...)
- * @param $sql String: SQL statement with appropriate markers
- * @param $func String: Name of the function, for profiling
- * @return resource a prepared DB2 SQL statement
- */
- public function prepare( $sql, $func = 'DB2::prepare' ) {
- $stmt = db2_prepare( $this->mConn, $sql, $this->mStmtOptions );
- return $stmt;
- }
-
- /**
- * Frees resources associated with a prepared statement
- * @return Boolean success or failure
- */
- public function freePrepared( $prepared ) {
- return db2_free_stmt( $prepared );
- }
-
- /**
- * Execute a prepared query with the various arguments
- * @param $prepared String: the prepared sql
- * @param $args Mixed: either an array here, or put scalars as varargs
- * @return Resource: results object
- */
- public function execute( $prepared, $args = null ) {
- if( !is_array( $args ) ) {
- # Pull the var args
- $args = func_get_args();
- array_shift( $args );
- }
- $res = db2_execute( $prepared, $args );
- if ( !$res ) {
- $this->installPrint( db2_stmt_errormsg() );
- }
- return $res;
- }
-
- /**
- * For faking prepared SQL statements on DBs that don't support
- * it directly.
- * @param $preparedQuery String: a 'preparable' SQL statement
- * @param $args Array of arguments to fill it with
- * @return String: executable statement
- */
- public function fillPrepared( $preparedQuery, $args ) {
- reset( $args );
- $this->preparedArgs =& $args;
-
- foreach ( $args as $i => $arg ) {
- db2_bind_param( $preparedQuery, $i+1, $args[$i] );
- }
-
- return $preparedQuery;
- }
-
- /**
- * Switches module between regular and install modes
- * @return string
- */
- public function setMode( $mode ) {
- $old = $this->mMode;
- $this->mMode = $mode;
- return $old;
- }
-
- /**
- * Bitwise negation of a column or value in SQL
- * Same as (~field) in C
- * @param $field String
- * @return String
- */
- function bitNot( $field ) {
- // expecting bit-fields smaller than 4bytes
- return "BITNOT( $field )";
- }
-
- /**
- * Bitwise AND of two columns or values in SQL
- * Same as (fieldLeft & fieldRight) in C
- * @param $fieldLeft String
- * @param $fieldRight String
- * @return String
- */
- function bitAnd( $fieldLeft, $fieldRight ) {
- return "BITAND( $fieldLeft, $fieldRight )";
- }
-
- /**
- * Bitwise OR of two columns or values in SQL
- * Same as (fieldLeft | fieldRight) in C
- * @param $fieldLeft String
- * @param $fieldRight String
- * @return String
- */
- function bitOr( $fieldLeft, $fieldRight ) {
- return "BITOR( $fieldLeft, $fieldRight )";
- }
-}
-
-class IBM_DB2Helper {
- public static function makeArray( $maybeArray ) {
- if ( !is_array( $maybeArray ) ) {
- return array( $maybeArray );
- }
-
- return $maybeArray;
- }
-}
+++ /dev/null
-<?php
-/**
- * IBM_DB2-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 IBM_DB2.
- *
- * @ingroup Deployment
- * @since 1.17
- */
-class Ibm_db2Installer extends DatabaseInstaller {
-
-
- protected $globalNames = array(
- 'wgDBserver',
- 'wgDBport',
- 'wgDBname',
- 'wgDBuser',
- 'wgDBpassword',
- 'wgDBmwschema',
- );
-
- protected $internalDefaults = array(
- '_InstallUser' => 'db2admin'
- );
-
- /**
- * Get the DB2 database extension name
- * @return string
- */
- public function getName() {
- return 'ibm_db2';
- }
-
- /**
- * Determine whether the DB2 database extension is currently available in PHP
- * @return boolean
- */
- public function isCompiled() {
- return self::checkExtension( 'ibm_db2' );
- }
-
- /**
- * Generate a connection form for a DB2 database
- * @return string
- */
- public function getConnectForm() {
- return
- $this->getTextBox( 'wgDBserver', 'config-db-host', array(), $this->parent->getHelpBox( 'config-db-host-help' ) ) .
- $this->getTextBox( 'wgDBport', 'config-db-port', array(), $this->parent->getHelpBox( 'config-db-port' ) ) .
- Html::openElement( 'fieldset' ) .
- Html::element( 'legend', array(), wfMessage( 'config-db-wiki-settings' )->text() ) .
- $this->getTextBox( 'wgDBname', 'config-db-name', array(), $this->parent->getHelpBox( 'config-db-name-help' ) ) .
- $this->getTextBox( 'wgDBmwschema', 'config-db-schema', array(), $this->parent->getHelpBox( 'config-db-schema-help' ) ) .
- Html::closeElement( 'fieldset' ) .
- $this->getInstallUserBox();
- }
-
- /**
- * Validate and then execute the connection form for a DB2 database
- * @return Status
- */
- public function submitConnectForm() {
- // Get variables from the request
- $newValues = $this->setVarsFromRequest(
- array( 'wgDBserver', 'wgDBport', 'wgDBname',
- 'wgDBmwschema', 'wgDBuser', 'wgDBpassword' ) );
-
- // Validate them
- $status = Status::newGood();
- if ( !strlen( $newValues['wgDBname'] ) ) {
- $status->fatal( 'config-missing-db-name' );
- } elseif ( !preg_match( '/^[a-zA-Z0-9_]+$/', $newValues['wgDBname'] ) ) {
- $status->fatal( 'config-invalid-db-name', $newValues['wgDBname'] );
- }
- if ( !strlen( $newValues['wgDBmwschema'] ) ) {
- $status->fatal( 'config-invalid-schema' );
- }
- elseif ( !preg_match( '/^[a-zA-Z0-9_]*$/', $newValues['wgDBmwschema'] ) ) {
- $status->fatal( 'config-invalid-schema', $newValues['wgDBmwschema'] );
- }
- if ( !strlen( $newValues['wgDBport'] ) ) {
- $status->fatal( 'config-invalid-port' );
- }
- elseif ( !preg_match( '/^[0-9_]*$/', $newValues['wgDBport'] ) ) {
- $status->fatal( 'config-invalid-port', $newValues['wgDBport'] );
- }
-
- // Submit user box
- if ( $status->isOK() ) {
- $status->merge( $this->submitInstallUserBox() );
- }
- if ( !$status->isOK() ) {
- return $status;
- }
-
- global $wgDBport;
- $wgDBport = $newValues['wgDBport'];
-
- // Try to connect
- $status->merge( $this->getConnection() );
- if ( !$status->isOK() ) {
- return $status;
- }
-
- $this->parent->setVar( 'wgDBuser', $this->getVar( '_InstallUser' ) );
- $this->parent->setVar( 'wgDBpassword', $this->getVar( '_InstallPassword' ) );
-
- return $status;
- }
-
- /**
- * Open a DB2 database connection
- * @return Status
- */
- public function openConnection() {
- $status = Status::newGood();
- try {
- $db = new DatabaseIbm_db2(
- $this->getVar( 'wgDBserver' ),
- $this->getVar( '_InstallUser' ),
- $this->getVar( '_InstallPassword' ),
- $this->getVar( 'wgDBname' ),
- 0,
- $this->getVar( 'wgDBmwschema' )
- );
- $status->value = $db;
- } catch ( DBConnectionError $e ) {
- $status->fatal( 'config-connection-error', $e->getMessage() );
- }
- return $status;
- }
-
- /**
- * Create a DB2 database for MediaWiki
- * @return Status
- */
- public function setupDatabase() {
- $status = $this->getConnection();
- if ( !$status->isOK() ) {
- return $status;
- }
- /**
- * @var $conn DatabaseBase
- */
- $conn = $status->value;
- $dbName = $this->getVar( 'wgDBname' );
- if( !$conn->selectDB( $dbName ) ) {
- $conn->query( "CREATE DATABASE "
- . $conn->addIdentifierQuotes( $dbName )
- . " AUTOMATIC STORAGE YES"
- . " USING CODESET UTF-8 TERRITORY US COLLATE USING SYSTEM"
- . " PAGESIZE 32768", __METHOD__ );
- $conn->selectDB( $dbName );
- }
- $this->setupSchemaVars();
- return $status;
- }
-
- /**
- * Create tables from scratch.
- * First check if pagesize >= 32k.
- *
- * @return Status
- */
- public function createTables() {
- $status = $this->getConnection();
- if ( !$status->isOK() ) {
- return $status;
- }
- $this->db->selectDB( $this->getVar( 'wgDBname' ) );
-
- if( $this->db->tableExists( 'user' ) ) {
- $status->warning( 'config-install-tables-exist' );
- return $status;
- }
-
- /* Check for pagesize */
- $status = $this->checkPageSize();
- if ( !$status->isOK() ) {
- return $status;
- }
-
- $this->db->setFlag( DBO_DDLMODE ); // For Oracle's handling of schema files
- $this->db->begin( __METHOD__ );
-
- $error = $this->db->sourceFile( $this->db->getSchemaPath() );
- if( $error !== true ) {
- $this->db->reportQueryError( $error, 0, '', __METHOD__ );
- $this->db->rollback( __METHOD__ );
- $status->fatal( 'config-install-tables-failed', $error );
- } else {
- $this->db->commit( __METHOD__ );
- }
- // Resume normal operations
- if( $status->isOk() ) {
- $this->enableLB();
- }
- return $status;
- }
-
- /**
- * Check if database has a tablspace with pagesize >= 32k.
- *
- * @return Status
- */
- public function checkPageSize() {
- $status = $this->getConnection();
- if ( !$status->isOK() ) {
- return $status;
- }
- $this->db->selectDB( $this->getVar( 'wgDBname' ) );
-
- try {
- $result = $this->db->query( 'SELECT PAGESIZE FROM SYSCAT.TABLESPACES FOR READ ONLY' );
- if( $result == false ) {
- $status->fatal( 'config-connection-error', '' );
- } else {
- $row = $this->db->fetchRow( $result );
- while ( $row ) {
- if( $row[0] >= 32768 ) {
- return $status;
- }
- $row = $this->db->fetchRow( $result );
- }
- $status->fatal( 'config-ibm_db2-low-db-pagesize', '' );
- }
- } catch ( DBUnexpectedError $e ) {
- $status->fatal( 'config-connection-error', $e->getMessage() );
- }
-
- return $status;
- }
-
- /**
- * Generate the code to store the DB2-specific settings defined by the configuration form
- * @return string
- */
- public function getLocalSettings() {
- $schema = LocalSettingsGenerator::escapePhpString( $this->getVar( 'wgDBmwschema' ) );
- $port = LocalSettingsGenerator::escapePhpString( $this->getVar( 'wgDBport' ) );
- return
-"# IBM_DB2 specific settings
-\$wgDBmwschema = \"{$schema}\";
-\$wgDBport = \"{$port}\";";
- }
-
- public function __construct( $parent ) {
- parent::__construct( $parent );
- }
-}
+++ /dev/null
-<?php
-/**
- * IBM_DB2-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 IBM_DB2 databases.
- *
- * @ingroup Deployment
- * @since 1.17
- */
-class Ibm_db2Updater extends DatabaseUpdater {
-
- /**
- * Get the changes in the DB2 database scheme since MediaWiki 1.14
- * @return array
- */
- protected function getCoreUpdateList() {
- return array(
- // 1.14
- array( 'addField', 'site_stats', 'ss_active_users', 'patch-ss_active_users.sql' ),
- array( 'addField', 'ipblocks', 'ipb_allow_usertalk', 'patch-ipb_allow_usertalk.sql' ),
-
- // 1.15
- array( 'addTable', 'change_tag', 'patch-change_tag.sql' ),
- array( 'addTable', 'tag_summary', 'patch-change_tag_summary.sql' ),
- array( 'addTable', 'valid_tag', 'patch-change_valid_tag.sql' ),
-
- // 1.16
- array( 'addTable', 'user_properties', 'patch-user_properties.sql' ),
- array( 'addTable', 'log_search', 'patch-log_search.sql' ),
- array( 'addField', 'logging', 'log_user_text', 'patch-log_user_text.sql' ),
- array( 'addTable', 'l10n_cache', 'patch-l10n_cache.sql' ),
- array( 'addTable', 'external_user', 'patch-external_user.sql' ),
- array( 'addIndex', 'log_search', 'ls_field_val', 'patch-log_search-rename-index.sql' ),
- array( 'addIndex', 'change_tag', 'change_tag_rc_tag', 'patch-change_tag-indexes.sql' ),
- array( 'addField', 'redirect', 'rd_interwiki', 'patch-rd_interwiki.sql' ),
-
- // 1.17
- array( 'addTable', 'iwlinks', 'patch-iwlinks.sql' ),
- array( 'addField', 'updatelog', 'ul_value', 'patch-ul_value.sql' ),
- array( 'addField', 'interwiki', 'iw_api', 'patch-iw_api_and_wikiid.sql' ),
- array( 'addField', 'categorylinks', 'cl_collation', 'patch-categorylinks-better-collation.sql' ),
- array( 'addTable', 'msg_resource', 'patch-msg_resource.sql' ),
- array( 'addTable', 'msg_resource_links', 'patch-msg_resource_links.sql' ),
- array( 'addIndex', 'msg_resource_links', 'uq61_msg_resource_links', 'patch-uq_61_msg_resource_links.sql' ),
- array( 'addIndex', 'msg_resource', 'uq81_msg_resource', 'patch-uq_81_msg_resource.sql' ),
- array( 'addTable', 'module_deps', 'patch-module_deps.sql' ),
- array( 'addIndex', 'module_deps', 'uq96_module_deps', 'patch-uq_96_module_deps.sql' ),
- array( 'addField', 'interwiki', 'iw_api', 'patch-iw_api-field.sql' ),
- array( 'addField', 'interwiki', 'iw_wikiid', 'patch-iw_wikiid-field.sql' ),
- array( 'addField', 'categorylinks', 'cl_sortkey_prefix', 'patch-cl_sortkey_prefix-field.sql' ),
- array( 'addField', 'categorylinks', 'cl_collation', 'patch-cl_collation-field.sql' ),
- array( 'addField', 'categorylinks', 'cl_type', 'patch-cl_type-field.sql' ),
-
- //1.18
- array( 'doUserNewTalkTimestampNotNull' ),
- array( 'addIndex', 'user', 'user_email', 'patch-user_email_index.sql' ),
- array( 'modifyField', 'user_properties', 'up_property', 'patch-up_property.sql' ),
- array( 'addTable', 'uploadstash', 'patch-uploadstash.sql' ),
- array( 'addTable', 'user_former_groups', 'patch-user_former_groups.sql'),
- array( 'doRebuildLocalisationCache' ),
-
- // 1.19
- array( 'addIndex', 'logging', 'type_action', 'patch-logging-type-action-index.sql'),
- array( 'dropField', 'user', 'user_options', 'patch-drop-user_options.sql' ),
- array( 'addField', 'revision', 'rev_sha1', 'patch-rev_sha1.sql' ),
- array( 'addField', 'archive', 'ar_sha1', 'patch-ar_sha1.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', 'page', 'page_content_model', 'patch-page-page_content_model.sql' ),
- );
- }
-}
'config-type-postgres' => 'PostgreSQL',
'config-type-sqlite' => 'SQLite',
'config-type-oracle' => 'Oracle',
- 'config-type-ibm_db2' => 'IBM DB2',
'config-support-info' => 'MediaWiki supports the following database systems:
$1
'config-support-postgres' => '* $1 is a popular open source database system as an alternative to MySQL ([http://www.php.net/manual/en/pgsql.installation.php how to compile PHP with PostgreSQL support]). There may be some minor outstanding bugs, and it is not recommended for use in a production environment.',
'config-support-sqlite' => '* $1 is a lightweight database system which is very well supported. ([http://www.php.net/manual/en/pdo.installation.php How to compile PHP with SQLite support], uses PDO)',
'config-support-oracle' => '* $1 is a commercial enterprise database. ([http://www.php.net/manual/en/oci8.installation.php How to compile PHP with OCI8 support])',
- 'config-support-ibm_db2' => '* $1 is a commercial enterprise database. ([http://www.php.net/manual/en/ibm-db2.installation.php How to compile PHP with IBM DB2 support])',
'config-header-mysql' => 'MySQL settings',
'config-header-postgres' => 'PostgreSQL settings',
'config-header-sqlite' => 'SQLite settings',
'config-header-oracle' => 'Oracle settings',
- 'config-header-ibm_db2' => 'IBM DB2 settings',
'config-invalid-db-type' => 'Invalid database type',
'config-missing-db-name' => 'You must enter a value for "Database name"',
'config-missing-db-host' => 'You must enter a value for "Database host"',
In '''UTF-8 mode''', MySQL will know what character set your data is in, and can present and convert it appropriately, but it will not let you store characters above the [//en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes Basic Multilingual Plane].",
- 'config-ibm_db2-low-db-pagesize' => "Your DB2 database has a default tablespace with an insufficient pagesize. The pagesize has to be '''32K''' or greater.",
-
'config-site-name' => 'Name of wiki:',
'config-site-name-help' => "This will appear in the title bar of the browser and in various other places.",
'config-site-name-blank' => 'Enter a site name.',
'postgres',
'oracle',
'sqlite',
- 'ibm_db2',
);
/**
+++ /dev/null
-<?php
-/**
- * IBM DB2 search engine
- *
- * Copyright © 2004 Brion Vibber <brion@pobox.com>
- * http://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 IBM DB2
- * @ingroup Search
- */
-class SearchIBM_DB2 extends SearchEngine {
-
- /**
- * Creates an instance of this class
- * @param $db DatabaseIbm_db2: database object
- */
- function __construct( $db ) {
- parent::__construct( $db );
- }
-
- /**
- * Perform a full text search query and return a result set.
- *
- * @param $term String: raw search term
- * @return SqlSearchResultSet
- */
- function searchText( $term ) {
- $resultSet = $this->db->resultObject( $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 $term String: taw search term
- * @return SqlSearchResultSet
- */
- function searchTitle( $term ) {
- $resultSet = $this->db->resultObject( $this->db->query( $this->getQuery( $this->filter( $term ), false ) ) );
- return new SqlSearchResultSet( $resultSet, $this->searchTerms );
- }
-
-
- /**
- * Return a partial WHERE clause to exclude redirects, if so set
- * @return String
- */
- function queryRedirect() {
- if ( $this->showRedirects ) {
- return '';
- } else {
- return 'AND page_is_redirect=0';
- }
- }
-
- /**
- * Return a partial WHERE clause to limit the search to the given namespaces
- * @return String
- */
- function queryNamespaces() {
- if( is_null( $this->namespaces ) )
- return '';
- $namespaces = implode( ',', $this->namespaces );
- if ( $namespaces == '' ) {
- $namespaces = '0';
- }
- return 'AND page_namespace IN (' . $namespaces . ')';
- }
-
- /**
- * Return a LIMIT clause to limit results on the query.
- * @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
- * @return String
- */
- function queryRanking( $filteredTerm, $fulltext ) {
- // requires Net Search Extender or equivalent
- // return ' ORDER BY score(1)';
- return '';
- }
-
- /**
- * Construct the full SQL query to do the search.
- * The guts shoulds be constructed in queryMain()
- * @param $filteredTerm String
- * @param $fulltext Boolean
- * @return String
- */
- function getQuery( $filteredTerm, $fulltext ) {
- return $this->queryLimit( $this->queryMain( $filteredTerm, $fulltext ) . ' ' .
- $this->queryRedirect() . ' ' .
- $this->queryNamespaces() . ' ' .
- $this->queryRanking( $filteredTerm, $fulltext ) . ' ' );
- }
-
-
- /**
- * Picks which field to index on, depending on what type of query.
- * @param $fulltext Boolean
- * @return String
- */
- function getIndexField( $fulltext ) {
- return $fulltext ? 'si_text' : 'si_title';
- }
-
- /**
- * Get the base part of the search query.
- *
- * @param $filteredTerm String
- * @param $fulltext Boolean
- * @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;
- }
-
- /** @todo document
- * @return string
- */
- function parseQuery( $filteredText, $fulltext ) {
- global $wgContLang;
- $lc = SearchEngine::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 ) {
-
- // 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 )
- $q[] = $terms[1] . $wgContLang->normalizeForSearch( $t );
- }
- else
- $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->strencode( join( ',', $q ) );
- $field = $this->getIndexField( $fulltext );
-
- // requires Net Search Extender or equivalent
- //return " CONTAINS($field, '$searchon') > 0 ";
-
- return " lcase($field) LIKE lcase('%$searchon%')";
- }
-
- /**
- * Create or update the search index record for the given page.
- * Title and text should be pre-processed.
- *
- * @param $id Integer
- * @param $title String
- * @param $text String
- */
- 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
- ), 'SearchIBM_DB2::update' );
- // ?
- //$dbw->query( "CALL ctx_ddl.sync_index('si_text_idx')" );
- //$dbw->query( "CALL ctx_ddl.sync_index('si_title_idx')" );
- }
-
- /**
- * Update a search index record's title only.
- * Title should be pre-processed.
- *
- * @param $id Integer
- * @param $title String
- */
- function updateTitle( $id, $title ) {
- $dbw = wfGetDB( DB_MASTER );
-
- $dbw->update( 'searchindex',
- array( 'si_title' => $title ),
- array( 'si_page' => $id ),
- 'SearchIBM_DB2::updateTitle',
- array() );
- }
-}
+++ /dev/null
--- good
-ALTER TABLE user_groups ADD CONSTRAINT USER_GROUPS_FK1 FOREIGN KEY (ug_user) REFERENCES user(user_id) ON DELETE CASCADE
-;
-
--- good
-ALTER TABLE user_newtalk ADD CONSTRAINT USER_NEWTALK_FK1 FOREIGN KEY (user_id) REFERENCES user(user_id) ON DELETE CASCADE
-;
-
--- referenced value not found
-ALTER TABLE revision ADD CONSTRAINT REVISION_PAGE_FK FOREIGN KEY (rev_page) REFERENCES page(page_id) ON DELETE CASCADE
-;
--- referenced value not found
-ALTER TABLE revision ADD CONSTRAINT REVISION_USER_FK FOREIGN KEY (rev_user) REFERENCES user(user_id) ON DELETE RESTRICT
-;
-
--- good
-ALTER TABLE page_restrictions ADD CONSTRAINT PAGE_RESTRICTIONS_PAGE_FK FOREIGN KEY (pr_page) REFERENCES page(page_id) ON DELETE CASCADE
-;
-
--- good
-ALTER TABLE page_props ADD CONSTRAINT PAGE_PROPS_PAGE_FK FOREIGN KEY (pp_page) REFERENCES page(page_id) ON DELETE CASCADE
-;
-
--- cannot contain null values
--- ALTER TABLE archive ADD CONSTRAINT ARCHIVE_USER_FK FOREIGN KEY (ar_user) REFERENCES user(user_id) ON DELETE SET NULL
---;
-
--- referenced value not found
-ALTER TABLE redirect ADD CONSTRAINT REDIRECT_FROM_FK FOREIGN KEY (rd_from) REFERENCES page(page_id) ON DELETE CASCADE
-;
-
--- referenced value not found
-ALTER TABLE pagelinks ADD CONSTRAINT PAGELINKS_FROM_FK FOREIGN KEY (pl_from) REFERENCES page(page_id) ON DELETE CASCADE
-;
-
--- good
-ALTER TABLE templatelinks ADD CONSTRAINT TEMPLATELINKS_FROM_FK FOREIGN KEY (tl_from) REFERENCES page(page_id) ON DELETE CASCADE
-;
-
--- good
-ALTER TABLE imagelinks ADD CONSTRAINT IMAGELINKS_FROM_FK FOREIGN KEY (il_from) REFERENCES page(page_id) ON DELETE CASCADE
-;
-
--- good
-ALTER TABLE categorylinks ADD CONSTRAINT CATEGORYLINKS_FROM_FK FOREIGN KEY (cl_from) REFERENCES page(page_id) ON DELETE CASCADE
-;
-
--- good
-ALTER TABLE externallinks ADD CONSTRAINT EXTERNALLINKS_FROM_FK FOREIGN KEY (el_from) REFERENCES page(page_id) ON DELETE CASCADE
-;
-
--- good
-ALTER TABLE langlinks ADD CONSTRAINT LANGLINKS_FROM_FK FOREIGN KEY (ll_from) REFERENCES page(page_id) ON DELETE CASCADE
-;
-
--- cannot contain null values
--- ALTER TABLE ipblocks ADD CONSTRAINT IPBLOCKS_USER_FK FOREIGN KEY (ipb_user) REFERENCES user(user_id) ON DELETE SET NULL
---;
-
--- good
-ALTER TABLE ipblocks ADD CONSTRAINT IPBLOCKS_BY_FK FOREIGN KEY (ipb_by) REFERENCES user(user_id) ON DELETE CASCADE
-;
-
--- cannot contain null values
--- ALTER TABLE image ADD CONSTRAINT IMAGE_USER_FK FOREIGN KEY (img_user) REFERENCES user(user_id) ON DELETE SET NULL
---;
-
--- cannot contain null values
--- ALTER TABLE oldimage ADD CONSTRAINT OLDIMAGE_USER_FK FOREIGN KEY (oi_user) REFERENCES user(user_id) ON DELETE SET NULL
---;
-
--- good
-ALTER TABLE oldimage ADD CONSTRAINT OLDIMAGE_NAME_FK FOREIGN KEY (oi_name) REFERENCES image(img_name) ON DELETE CASCADE
-;
-
--- cannot contain null values
--- ALTER TABLE filearchive ADD CONSTRAINT FILEARCHIVE_DELETED_USER_FK FOREIGN KEY (fa_deleted_user) REFERENCES user(user_id) ON DELETE SET NULL
---;
-
--- cannot contain null values
--- ALTER TABLE filearchive ADD CONSTRAINT FILEARCHIVE_USER_FK FOREIGN KEY (fa_user) REFERENCES user(user_id) ON DELETE SET NULL
---;
-
--- cannot contain null values
--- ALTER TABLE recentchanges ADD CONSTRAINT RECENTCHANGES_USER_FK FOREIGN KEY (rc_user) REFERENCES user(user_id) ON DELETE SET NULL
---;
-
--- cannot contain null values
--- ALTER TABLE recentchanges ADD CONSTRAINT RECENTCHANGES_CUR_ID_FK FOREIGN KEY (rc_cur_id) REFERENCES page(page_id) ON DELETE SET NULL
---;
-
--- good
-ALTER TABLE watchlist ADD CONSTRAINT WATCHLIST_USER_FK FOREIGN KEY (wl_user) REFERENCES user(user_id) ON DELETE CASCADE
-;
-
--- cannot contain null values
--- ALTER TABLE protected_titles ADD CONSTRAINT PROTECTED_TITLES_USER_FK FOREIGN KEY (pt_user) REFERENCES user(user_id) ON DELETE SET NULL
---;
-
--- cannot contain null values
--- ALTER TABLE logging ADD CONSTRAINT LOGGING_USER_FK FOREIGN KEY (log_user) REFERENCES user(user_id) ON DELETE SET NULL
---;
\ No newline at end of file
+++ /dev/null
---
--- patch-categorylinks-better-collation.sql
---
---
--- Track category inclusions *used inline*
--- This tracks a single level of category membership
--- (folksonomic tagging, really).
---
-CREATE TABLE categorylinks (
- cl_from BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES page(page_id) ON DELETE CASCADE,
- cl_to VARCHAR(255) NOT NULL,
- -- cl_sortkey has to be at least 86 wide
- -- in order to be compatible with the old MySQL schema from MW 1.10
- --cl_sortkey VARCHAR(86),
- cl_sortkey VARCHAR(230) FOR BIT DATA NOT NULL ,
- cl_sortkey_prefix VARCHAR(255) FOR BIT DATA NOT NULL ,
- cl_timestamp TIMESTAMP(3) NOT NULL,
- cl_collation VARCHAR(32) FOR BIT DATA NOT NULL ,
- cl_type VARCHAR(6) FOR BIT DATA NOT NULL
-);
+++ /dev/null
-CREATE UNIQUE INDEX change_tag_rc_tag ON change_tag (ct_rc_id,ct_tag);
-CREATE UNIQUE INDEX change_tag_log_tag ON change_tag (ct_log_id,ct_tag);
-CREATE UNIQUE INDEX 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 change_tag_tag_id ON change_tag (ct_tag,ct_rc_id,ct_rev_id,ct_log_id);
+++ /dev/null
--- A table to track tags for revisions, logs and recent changes.
-CREATE TABLE change_tag (
- ct_rc_id INTEGER,
- ct_log_id INTEGER,
- ct_rev_id INTEGER,
- ct_tag varchar(255) NOT NULL,
- ct_params CLOB(64K) INLINE LENGTH 4096
-);
+++ /dev/null
--- Rollup table to pull a LIST of tags simply
-CREATE TABLE tag_summary (
- ts_rc_id INTEGER,
- ts_log_id INTEGER,
- ts_rev_id INTEGER,
- ts_tags CLOB(64K) INLINE LENGTH 4096 NOT NULL
-);
+++ /dev/null
-CREATE TABLE valid_tag (
- vt_tag varchar(255) NOT NULL PRIMARY KEY
-);
+++ /dev/null
-ALTER TABLE categorylinks ADD cl_collation VARCHAR(32) FOR BIT DATA NOT NULL
+++ /dev/null
-ALTER TABLE categorylinks ADD cl_sortkey_prefix VARCHAR(255) FOR BIT DATA NOT NULL
+++ /dev/null
-ALTER TABLE categorylinks ADD cl_type VARCHAR(6) FOR BIT DATA NOT NULL
+++ /dev/null
-CREATE TABLE external_user (
- -- Foreign key to user_id
- eu_local_id BIGINT NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
-
- -- Some opaque identifier provided by the external database
- eu_external_id VARCHAR(255) NOT NULL
-);
+++ /dev/null
-CREATE TABLE ipblocks (
- ipb_id INTEGER NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- --DEFAULT nextval('ipblocks_ipb_id_val'),
- ipb_address VARCHAR(1024),
- ipb_user BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES user(user_id) ON DELETE SET NULL,
- ipb_by BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES user(user_id) ON DELETE CASCADE,
- ipb_by_text VARCHAR(255) NOT NULL DEFAULT '',
- ipb_reason VARCHAR(1024) NOT NULL,
- ipb_timestamp TIMESTAMP(3) NOT NULL,
- ipb_auto SMALLINT NOT NULL DEFAULT 0,
- ipb_anon_only SMALLINT NOT NULL DEFAULT 0,
- ipb_create_account SMALLINT NOT NULL DEFAULT 1,
- ipb_enable_autoblock SMALLINT NOT NULL DEFAULT 1,
- ipb_expiry TIMESTAMP(3) NOT NULL,
- ipb_range_start VARCHAR(1024),
- ipb_range_end VARCHAR(1024),
- ipb_deleted SMALLINT NOT NULL DEFAULT 0,
- ipb_block_email SMALLINT NOT NULL DEFAULT 0,
- ipb_allow_usertalk SMALLINT NOT NULL DEFAULT 0
-
-);
+++ /dev/null
-ALTER TABLE interwiki ADD iw_api CLOB(64K) INLINE LENGTH 4096 NOT NULL
+++ /dev/null
-CREATE TABLE interwiki (
- iw_prefix VARCHAR(32) NOT NULL UNIQUE,
- iw_url CLOB(64K) INLINE LENGTH 4096 NOT NULL,
- iw_api CLOB(64K) INLINE LENGTH 4096 NOT NULL,
- iw_wikiid varchar(64) NOT NULL,
- iw_local SMALLINT NOT NULL,
- iw_trans SMALLINT NOT NULL DEFAULT 0
-);
+++ /dev/null
-ALTER TABLE interwiki ADD iw_wikiid varchar(64) NOT NULL
+++ /dev/null
-CREATE TABLE "IWLINKS"
-(
-"IWL_FROM" INT NOT NULL ,
-"IWL_PREFIX" VARCHAR(20) FOR BIT DATA NOT NULL ,
-"IWL_TITLE" VARCHAR(255) FOR BIT DATA NOT NULL
-)
-;
+++ /dev/null
-CREATE TABLE l10n_cache (
- -- Language code
- lc_lang VARCHAR(32) NOT NULL,
- -- Cache key
- lc_key VARCHAR(255) NOT NULL,
- -- Value
- lc_value CLOB(16M) INLINE LENGTH 4096 NOT NULL
-);
+++ /dev/null
-CREATE TABLE log_search (
- -- The type of ID (rev ID, log ID, rev TIMESTAMP(3), username)
- ls_field VARCHAR(32) FOR BIT DATA NOT NULL,
- -- The value of the ID
- ls_value varchar(255) NOT NULL,
- -- Key to log_id
- ls_log_id BIGINT NOT NULL default 0
-);
+++ /dev/null
-CREATE TABLE log_search (
- -- The type of ID (rev ID, log ID, rev TIMESTAMP(3), username)
- ls_field VARCHAR(32) FOR BIT DATA NOT NULL,
- -- The value of the ID
- ls_value varchar(255) NOT NULL,
- -- Key to log_id
- ls_log_id BIGINT NOT NULL default 0
-);
+++ /dev/null
-CREATE TABLE logging (
- log_id BIGINT NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- --PRIMARY KEY DEFAULT nextval('log_log_id_seq'),
- log_type VARCHAR(32) NOT NULL,
- log_action VARCHAR(32) NOT NULL,
- log_timestamp TIMESTAMP(3) NOT NULL,
- log_user BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES user(user_id) ON DELETE SET NULL,
- -- Name of the user who performed this action
- log_user_text VARCHAR(255) NOT NULL default '',
- log_namespace SMALLINT NOT NULL,
- log_title VARCHAR(255) NOT NULL,
- log_page BIGINT,
- log_comment VARCHAR(255),
- log_params CLOB(64K) INLINE LENGTH 4096,
- log_deleted SMALLINT NOT NULL DEFAULT 0
-);
+++ /dev/null
-CREATE TABLE "MODULE_DEPS" (
-"MD_MODULE" VARCHAR(255) FOR BIT DATA NOT NULL ,
-"MD_SKIN" VARCHAR(32) FOR BIT DATA NOT NULL ,
-"MD_DEPS" CLOB(16M) INLINE LENGTH 4096 NOT NULL
-)
-;
+++ /dev/null
-CREATE TABLE "MSG_RESOURCE"
-(
-"MR_RESOURCE" VARCHAR(255) FOR BIT DATA NOT NULL ,
-"MR_LANG" VARCHAR(32) FOR BIT DATA NOT NULL ,
-"MR_BLOB" BLOB NOT NULL ,
-"MR_TIMESTAMP" TIMESTAMP(3) NOT NULL
-)
-;
+++ /dev/null
-CREATE TABLE "MSG_RESOURCE_LINKS"
-(
-"MRL_RESOURCE" VARCHAR(255) FOR BIT DATA NOT NULL ,
-"MRL_MESSAGE" VARCHAR(255) FOR BIT DATA NOT NULL
-)
-;
+++ /dev/null
-CREATE TABLE redirect (
- rd_from BIGINT NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- --REFERENCES page(page_id) ON DELETE CASCADE,
- rd_namespace SMALLINT NOT NULL DEFAULT 0,
- rd_title VARCHAR(255) NOT NULL DEFAULT '',
- rd_interwiki varchar(32),
- rd_fragment VARCHAR(255)
-);
+++ /dev/null
-CREATE TABLE site_stats (
- ss_row_id BIGINT NOT NULL UNIQUE,
- ss_total_views BIGINT DEFAULT 0,
- ss_total_edits BIGINT DEFAULT 0,
- ss_good_articles BIGINT DEFAULT 0,
- ss_total_pages INTEGER DEFAULT -1,
- ss_users INTEGER DEFAULT -1,
- ss_active_users INTEGER DEFAULT -1,
- ss_admins INTEGER DEFAULT -1,
- ss_images INTEGER DEFAULT 0
-);
+++ /dev/null
-CREATE TABLE updatelog (
- ul_key VARCHAR(255) NOT NULL PRIMARY KEY
-);
+++ /dev/null
-CREATE UNIQUE INDEX "UQ61_MSG_RESOURCE_LINKS" ON "MSG_RESOURCE_LINKS"
-(
-"MRL_MESSAGE",
-"MRL_RESOURCE"
-)
-ALLOW REVERSE SCANS
-;
+++ /dev/null
-CREATE UNIQUE INDEX "UQ81_MSG_RESOURCE" ON "MSG_RESOURCE"
-(
-"MR_RESOURCE"
-,"MR_LANG"
-)
-ALLOW REVERSE SCANS
-;
+++ /dev/null
-CREATE UNIQUE INDEX "UQ96_MODULE_DEPS" ON "MODULE_DEPS"
-(
-"MD_MODULE"
-,"MD_SKIN"
-)
-ALLOW REVERSE SCANS
-;
+++ /dev/null
-CREATE TABLE user_properties (
- -- Foreign key to user.user_id
- up_user BIGINT NOT NULL,
-
- -- Name of the option being saved. This is indexed for bulk lookup.
- up_property VARCHAR(32) FOR BIT DATA NOT NULL,
-
- -- Property value as a string.
- up_value CLOB(64K) INLINE LENGTH 4096
-);
+++ /dev/null
--- IBM DB2
-
--- 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.
-
--- Notes:
--- * DB2 will convert all table and column names to all caps internally.
--- * DB2 has a 32k limit on SQL filesize, so it may be necessary
--- to split this into two files soon.
-
-
-CREATE TABLE user (
- -- Needs to start with 0
- user_id BIGINT
- PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 0),
- user_name VARCHAR(255) NOT NULL UNIQUE,
- user_real_name VARCHAR(255),
- user_password VARCHAR(1024),
- user_newpassword VARCHAR(1024),
- user_newpass_time TIMESTAMP(3),
- user_token VARCHAR(255),
- user_email VARCHAR(1024),
- user_email_token VARCHAR(255),
- user_email_token_expires TIMESTAMP(3),
- user_email_authenticated TIMESTAMP(3),
- -- obsolete, replace by user_properties table
- -- user_options CLOB(64K) INLINE LENGTH 4096,
- user_touched TIMESTAMP(3),
- user_registration TIMESTAMP(3),
- user_editcount INTEGER
-);
-CREATE INDEX user_email_token_idx
- ON user (user_email_token);
-CREATE UNIQUE INDEX user_include_idx
- ON user (user_id)
- INCLUDE (user_name, user_real_name, user_password, user_newpassword,
- user_newpass_time, user_token,
- user_email, user_email_token, user_email_token_expires,
- user_email_authenticated,
- user_touched, user_registration, user_editcount);
-CREATE UNIQUE INDEX user_email
- ON user (user_email);
-
-
-
--- Create a dummy user to satisfy fk contraints especially with revisions
-INSERT INTO user(
- user_name, user_real_name, user_password, user_newpassword, user_newpass_time,
- user_email, user_email_authenticated, user_token, user_registration, user_editcount
-)
-VALUES (
- 'Anonymous', '', NULL, NULL, CURRENT_TIMESTAMP,
- NULL, NULL, NULL, CURRENT_TIMESTAMP, 0
-);
-
-
-
-CREATE TABLE user_groups (
- ug_user BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES user(user_id) ON DELETE CASCADE,
- ug_group VARCHAR(255) NOT NULL
-);
-CREATE INDEX user_groups_unique
- ON user_groups (ug_user, ug_group);
-
-
-
-CREATE TABLE user_newtalk (
- -- registered users key
- user_id BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES user(user_id) ON DELETE CASCADE,
- -- anonymous users key
- user_ip VARCHAR(40),
- user_last_timestamp TIMESTAMP(3)
-);
-CREATE INDEX user_newtalk_id_idx
- ON user_newtalk (user_id);
-CREATE INDEX user_newtalk_ip_idx
- ON user_newtalk (user_ip);
-CREATE UNIQUE INDEX user_newtalk_include_idx
- ON user_newtalk (user_id, user_ip)
- INCLUDE (user_last_timestamp);
-
-
-
-CREATE TABLE page (
- page_id BIGINT
- PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- page_namespace SMALLINT NOT NULL,
- page_title VARCHAR(255) NOT NULL,
- page_restrictions VARCHAR(1024),
- page_counter BIGINT NOT NULL DEFAULT 0,
- page_is_redirect SMALLINT NOT NULL DEFAULT 0,
- page_is_new SMALLINT NOT NULL DEFAULT 0,
- page_random NUMERIC(15,14) NOT NULL,
- page_touched TIMESTAMP(3),
- page_latest BIGINT NOT NULL, -- FK?
- page_len BIGINT NOT NULL
-);
-CREATE UNIQUE INDEX page_unique_name
- ON page (page_namespace, page_title);
-CREATE INDEX page_random_idx
- ON page (page_random);
-CREATE INDEX page_len_idx
- ON page (page_len);
-CREATE UNIQUE INDEX page_id_include
- ON page (page_id)
- INCLUDE (page_namespace, page_title, page_restrictions, page_counter, page_is_redirect, page_is_new, page_random, page_touched, page_latest, page_len);
-CREATE UNIQUE INDEX page_name_include
- ON page (page_namespace, page_title)
- INCLUDE (page_id, page_restrictions, page_counter, page_is_redirect, page_is_new, page_random, page_touched, page_latest, page_len);
-
-
-
-CREATE TABLE revision (
- rev_id BIGINT
- PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- rev_page BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES page (page_id) ON DELETE CASCADE,
- rev_text_id BIGINT, -- FK
- rev_comment VARCHAR(1024),
- rev_user BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES user(user_id) ON DELETE RESTRICT,
- rev_user_text VARCHAR(255) NOT NULL,
- rev_timestamp TIMESTAMP(3) NOT NULL,
- rev_minor_edit SMALLINT NOT NULL DEFAULT 0,
- rev_deleted SMALLINT NOT NULL DEFAULT 0,
- rev_len BIGINT,
- rev_parent_id BIGINT DEFAULT NULL,
- rev_sha1 VARCHAR(255) NOT NULL DEFAULT ''
-);
-CREATE UNIQUE INDEX revision_unique
- ON revision (rev_page, rev_id);
-CREATE INDEX rev_text_id_idx
- ON revision (rev_text_id);
-CREATE INDEX rev_timestamp_idx
- ON revision (rev_timestamp);
-CREATE INDEX rev_user_idx
- ON revision (rev_user);
-CREATE INDEX rev_user_text_idx
- ON revision (rev_user_text);
-
-
-
-CREATE TABLE text ( -- replaces reserved word 'text'
- old_id INTEGER
- PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- old_text CLOB(16M) INLINE LENGTH 4096,
- old_flags VARCHAR(1024)
-);
-
-
-
-CREATE TABLE page_restrictions (
- pr_id BIGINT
- PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- pr_page INTEGER NOT NULL DEFAULT 0,
- --(used to be nullable)
- -- REFERENCES page (page_id) ON DELETE CASCADE,
- pr_type VARCHAR(60) NOT NULL,
- pr_level VARCHAR(60) NOT NULL,
- pr_cascade SMALLINT NOT NULL,
- pr_user INTEGER,
- pr_expiry TIMESTAMP(3)
- --PRIMARY KEY (pr_page, pr_type)
-);
---ALTER TABLE page_restrictions ADD CONSTRAINT page_restrictions_pk PRIMARY KEY (pr_page, pr_type);
-CREATE UNIQUE INDEX pr_pagetype
- ON page_restrictions (pr_page, pr_type);
-CREATE INDEX pr_typelevel
- ON page_restrictions (pr_type, pr_level);
-CREATE INDEX pr_level
- ON page_restrictions (pr_level);
-CREATE INDEX pr_cascade
- ON page_restrictions (pr_cascade);
-
-
-
-CREATE TABLE page_props (
- pp_page INTEGER NOT NULL DEFAULT 0,
- -- REFERENCES page (page_id) ON DELETE CASCADE,
- pp_propname VARCHAR(255) NOT NULL,
- pp_value CLOB(64K) INLINE LENGTH 4096 NOT NULL,
- PRIMARY KEY (pp_page, pp_propname)
-);
-CREATE INDEX page_props_propname
- ON page_props (pp_propname);
-
-
-
-CREATE TABLE archive (
- ar_namespace SMALLINT NOT NULL,
- ar_title VARCHAR(255) NOT NULL,
- ar_text CLOB(16M) INLINE LENGTH 4096,
- ar_comment VARCHAR(1024),
- ar_user BIGINT NOT NULL,
- -- no foreign keys in MySQL
- -- REFERENCES user(user_id) ON DELETE SET NULL,
- ar_user_text VARCHAR(255) NOT NULL,
- ar_timestamp TIMESTAMP(3) NOT NULL,
- ar_minor_edit SMALLINT NOT NULL DEFAULT 0,
- ar_flags VARCHAR(1024),
- ar_rev_id INTEGER,
- ar_text_id INTEGER,
- ar_deleted SMALLINT NOT NULL DEFAULT 0,
- ar_len INTEGER,
- ar_page_id INTEGER,
- ar_parent_id INTEGER,
- ar_sha1 VARCHAR(255) NOT NULL DEFAULT ''
-);
-CREATE INDEX archive_name_title_timestamp
- ON archive (ar_namespace, ar_title, ar_timestamp);
-CREATE INDEX archive_user_text
- ON archive (ar_user_text);
-
-
-
-CREATE TABLE redirect (
- rd_from BIGINT NOT NULL
- PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- --REFERENCES page(page_id) ON DELETE CASCADE,
- rd_namespace SMALLINT NOT NULL DEFAULT 0,
- rd_title VARCHAR(255) NOT NULL DEFAULT '',
- rd_interwiki VARCHAR(32),
- rd_fragment VARCHAR(255)
-);
-CREATE INDEX redirect_ns_title
- ON redirect (rd_namespace, rd_title, rd_from);
-
-
-CREATE TABLE pagelinks (
- pl_from BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES page(page_id) ON DELETE CASCADE,
- pl_namespace SMALLINT NOT NULL,
- pl_title VARCHAR(255) NOT NULL
-);
-CREATE UNIQUE INDEX pagelink_unique
- ON pagelinks (pl_from, pl_namespace, pl_title);
-
-
-
-CREATE TABLE templatelinks (
- tl_from BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES page(page_id) ON DELETE CASCADE,
- tl_namespace SMALLINT NOT NULL,
- tl_title VARCHAR(255) NOT NULL
-);
-CREATE UNIQUE INDEX templatelinks_unique
- ON templatelinks (tl_namespace, tl_title, tl_from);
-CREATE UNIQUE INDEX tl_from_idx
- ON templatelinks (tl_from, tl_namespace, tl_title);
-
-
-
-CREATE TABLE imagelinks (
- il_from BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES page(page_id) ON DELETE CASCADE,
- il_to VARCHAR(255) NOT NULL
-);
-CREATE UNIQUE INDEX il_from_idx
- ON imagelinks (il_to, il_from);
-CREATE UNIQUE INDEX il_to_idx
- ON imagelinks (il_from, il_to);
-
-
-
-CREATE TABLE categorylinks (
- cl_from BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES page(page_id) ON DELETE CASCADE,
- cl_to VARCHAR(255) NOT NULL,
- -- cl_sortkey has to be at least 86 wide
- -- in order to be compatible with the old MySQL schema from MW 1.10
- --cl_sortkey VARCHAR(86),
- cl_sortkey VARCHAR(230) FOR BIT DATA NOT NULL,
- cl_sortkey_prefix VARCHAR(255) FOR BIT DATA NOT NULL,
- cl_timestamp TIMESTAMP(3) NOT NULL,
- cl_collation VARCHAR(32) FOR BIT DATA NOT NULL,
- cl_type VARCHAR(6) FOR BIT DATA NOT NULL
-);
-CREATE UNIQUE INDEX cl_from
- ON categorylinks (cl_from, cl_to);
-CREATE INDEX cl_sortkey
- ON categorylinks (cl_to, cl_sortkey, cl_from);
-
-
-
-CREATE TABLE externallinks (
- el_from BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES page(page_id) ON DELETE CASCADE,
- el_to VARCHAR(1024) NOT NULL,
- el_index VARCHAR(1024) NOT NULL
-);
-CREATE INDEX externallinks_from_to
- ON externallinks (el_from, el_to);
-CREATE INDEX externallinks_index
- ON externallinks (el_index);
-
-
-
---
--- Track external user accounts, if ExternalAuth is used
---
-CREATE TABLE external_user (
- -- Foreign key to user_id
- eu_local_id BIGINT NOT NULL
- PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
-
- -- Some opaque identifier provided by the external database
- eu_external_id VARCHAR(255) NOT NULL
-);
-CREATE UNIQUE INDEX eu_external_id_idx
- ON external_user (eu_external_id)
- INCLUDE (eu_local_id);
-CREATE UNIQUE INDEX eu_local_id_idx
- ON external_user (eu_local_id)
- INCLUDE (eu_external_id);
-
-
-
-CREATE TABLE langlinks (
- ll_from BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES page (page_id) ON DELETE CASCADE,
- ll_lang VARCHAR(20),
- ll_title VARCHAR(255)
-);
-CREATE UNIQUE INDEX langlinks_unique
- ON langlinks (ll_from, ll_lang);
-CREATE INDEX langlinks_lang_title
- ON langlinks (ll_lang, ll_title);
-
-
-
-CREATE TABLE site_stats (
- ss_row_id BIGINT NOT NULL UNIQUE,
- ss_total_views BIGINT DEFAULT 0,
- ss_total_edits BIGINT DEFAULT 0,
- ss_good_articles BIGINT DEFAULT 0,
- ss_total_pages INTEGER DEFAULT -1,
- ss_users INTEGER DEFAULT -1,
- ss_active_users INTEGER DEFAULT -1,
- ss_admins INTEGER DEFAULT -1,
- ss_images INTEGER DEFAULT 0
-);
-
-
-
-CREATE TABLE hitcounter (
- hc_id BIGINT NOT NULL
-);
-
-
-
-CREATE TABLE ipblocks (
- ipb_id INTEGER NOT NULL
- PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- ipb_address VARCHAR(1024),
- ipb_user BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES user(user_id) ON DELETE SET NULL,
- ipb_by BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES user(user_id) ON DELETE CASCADE,
- ipb_by_text VARCHAR(255) NOT NULL DEFAULT '',
- ipb_reason VARCHAR(1024) NOT NULL,
- ipb_timestamp TIMESTAMP(3) NOT NULL,
- ipb_auto SMALLINT NOT NULL DEFAULT 0,
- ipb_anon_only SMALLINT NOT NULL DEFAULT 0,
- ipb_create_account SMALLINT NOT NULL DEFAULT 1,
- ipb_enable_autoblock SMALLINT NOT NULL DEFAULT 1,
- ipb_expiry TIMESTAMP(3) NOT NULL,
- ipb_range_start VARCHAR(1024),
- ipb_range_end VARCHAR(1024),
- ipb_deleted SMALLINT NOT NULL DEFAULT 0,
- ipb_block_email SMALLINT NOT NULL DEFAULT 0,
- ipb_allow_usertalk SMALLINT NOT NULL DEFAULT 0,
- ipb_parent_block_id INTEGER DEFAULT NULL
- -- REFERENCES ipblocks(ipb_id) ON DELETE SET NULL
-
-);
-CREATE INDEX ipb_address
- ON ipblocks (ipb_address);
-CREATE INDEX ipb_user
- ON ipblocks (ipb_user);
-CREATE INDEX ipb_range
- ON ipblocks (ipb_range_start, ipb_range_end);
-
-
-
-CREATE TABLE image (
- img_name VARCHAR(255) NOT NULL
- PRIMARY KEY,
- img_size BIGINT NOT NULL,
- img_width INTEGER NOT NULL,
- img_height INTEGER NOT NULL,
- img_metadata CLOB(16M) INLINE LENGTH 4096 NOT NULL DEFAULT '',
- img_bits SMALLINT,
- img_media_type VARCHAR(255),
- img_major_mime VARCHAR(255) DEFAULT 'unknown',
- img_minor_mime VARCHAR(32) DEFAULT 'unknown',
- img_description VARCHAR(1024) NOT NULL DEFAULT '',
- img_user BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES user(user_id) ON DELETE SET NULL,
- img_user_text VARCHAR(255) NOT NULL DEFAULT '',
- img_timestamp TIMESTAMP(3),
- img_sha1 VARCHAR(255) NOT NULL DEFAULT ''
-);
-CREATE INDEX img_size_idx
- ON image (img_size);
-CREATE INDEX img_timestamp_idx
- ON image (img_timestamp);
-CREATE INDEX img_sha1
- ON image (img_sha1);
-
-
-CREATE TABLE oldimage (
- oi_name VARCHAR(255) NOT NULL DEFAULT '',
- oi_archive_name VARCHAR(255) NOT NULL,
- oi_size BIGINT NOT NULL,
- oi_width INTEGER NOT NULL,
- oi_height INTEGER NOT NULL,
- oi_bits SMALLINT NOT NULL,
- oi_description VARCHAR(1024),
- oi_user BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES user(user_id) ON DELETE SET NULL,
- oi_user_text VARCHAR(255) NOT NULL,
- oi_timestamp TIMESTAMP(3) NOT NULL,
- oi_metadata CLOB(16M) INLINE LENGTH 4096 NOT NULL DEFAULT '',
- oi_media_type VARCHAR(255),
- oi_major_mime VARCHAR(255) NOT NULL DEFAULT 'unknown',
- oi_minor_mime VARCHAR(255) NOT NULL DEFAULT 'unknown',
- oi_deleted SMALLINT NOT NULL DEFAULT 0,
- oi_sha1 VARCHAR(255) NOT NULL DEFAULT ''
- --FOREIGN KEY (oi_name) REFERENCES image(img_name) ON DELETE CASCADE
-);
-CREATE INDEX oi_name_timestamp
- ON oldimage (oi_name, oi_timestamp);
-CREATE INDEX oi_name_archive_name
- ON oldimage (oi_name, oi_archive_name);
-CREATE INDEX oi_sha1
- ON oldimage (oi_sha1);
-
-
-
-CREATE TABLE filearchive (
- fa_id INTEGER NOT NULL
- PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- fa_name VARCHAR(255) NOT NULL,
- fa_archive_name VARCHAR(255),
- fa_storage_group VARCHAR(255),
- fa_storage_key VARCHAR(64) DEFAULT '',
- fa_deleted_user BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES user(user_id) ON DELETE SET NULL,
- fa_deleted_timestamp TIMESTAMP(3) NOT NULL,
- fa_deleted_reason VARCHAR(255),
- fa_size BIGINT NOT NULL,
- fa_width INTEGER NOT NULL,
- fa_height INTEGER NOT NULL,
- fa_metadata CLOB(16M) INLINE LENGTH 4096 NOT NULL DEFAULT '',
- fa_bits SMALLINT,
- fa_media_type VARCHAR(255),
- fa_major_mime VARCHAR(255) DEFAULT 'unknown',
- fa_minor_mime VARCHAR(255) DEFAULT 'unknown',
- fa_description VARCHAR(1024) NOT NULL,
- fa_user BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES user(user_id) ON DELETE SET NULL,
- fa_user_text VARCHAR(255) NOT NULL,
- fa_timestamp TIMESTAMP(3),
- fa_deleted SMALLINT NOT NULL DEFAULT 0
-);
-CREATE INDEX fa_name_time
- ON filearchive (fa_name, fa_timestamp);
-CREATE INDEX fa_dupe
- ON filearchive (fa_storage_group, fa_storage_key);
-CREATE INDEX fa_notime
- ON filearchive (fa_deleted_timestamp);
-CREATE INDEX fa_nouser
- ON filearchive (fa_deleted_user);
-
-
-
-CREATE TABLE recentchanges (
- rc_id INTEGER NOT NULL
- PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- rc_timestamp TIMESTAMP(3) NOT NULL,
- rc_cur_time TIMESTAMP(3) NOT NULL,
- rc_user BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES user(user_id) ON DELETE SET NULL,
- rc_user_text VARCHAR(255) NOT NULL,
- rc_namespace SMALLINT NOT NULL,
- rc_title VARCHAR(255) NOT NULL,
- rc_comment VARCHAR(255),
- rc_minor SMALLINT NOT NULL DEFAULT 0,
- rc_bot SMALLINT NOT NULL DEFAULT 0,
- rc_new SMALLINT NOT NULL DEFAULT 0,
- rc_cur_id BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES page(page_id) ON DELETE SET NULL,
- rc_this_oldid BIGINT NOT NULL,
- rc_last_oldid BIGINT NOT NULL,
- rc_type SMALLINT NOT NULL DEFAULT 0,
- rc_moved_to_ns SMALLINT,
- rc_moved_to_title VARCHAR(255),
- rc_patrolled SMALLINT NOT NULL DEFAULT 0,
- rc_ip VARCHAR(40), -- was CIDR type
- rc_old_len INTEGER,
- rc_new_len INTEGER,
- rc_deleted SMALLINT NOT NULL DEFAULT 0,
- rc_logid BIGINT NOT NULL DEFAULT 0,
- rc_log_type VARCHAR(255),
- rc_log_action VARCHAR(255),
- rc_params CLOB(64K) INLINE LENGTH 4096
-);
-CREATE INDEX rc_timestamp
- ON recentchanges (rc_timestamp);
-CREATE INDEX rc_namespace_title
- ON recentchanges (rc_namespace, rc_title);
-CREATE INDEX rc_cur_id
- ON recentchanges (rc_cur_id);
-CREATE INDEX new_name_timestamp
- ON recentchanges (rc_new, rc_namespace, rc_timestamp);
-CREATE INDEX rc_ip
- ON recentchanges (rc_ip);
-
-
-
-CREATE TABLE watchlist (
- wl_user BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES user(user_id) ON DELETE CASCADE,
- wl_namespace SMALLINT NOT NULL DEFAULT 0,
- wl_title VARCHAR(255) NOT NULL,
- wl_notificationtimestamp TIMESTAMP(3)
-);
-CREATE UNIQUE INDEX wl_user_namespace_title
- ON watchlist (wl_namespace, wl_title, wl_user);
-
-
-
-CREATE TABLE interwiki (
- iw_prefix VARCHAR(32) NOT NULL UNIQUE,
- iw_url CLOB(64K) INLINE LENGTH 4096 NOT NULL,
- iw_api CLOB(64K) INLINE LENGTH 4096 NOT NULL,
- iw_wikiid VARCHAR(64) NOT NULL,
- iw_local SMALLINT NOT NULL,
- iw_trans SMALLINT NOT NULL DEFAULT 0
-);
-
-
-
-CREATE TABLE querycache (
- qc_type VARCHAR(255) NOT NULL,
- qc_value BIGINT NOT NULL,
- qc_namespace INTEGER NOT NULL,
- qc_title VARCHAR(255) NOT NULL
-);
-CREATE INDEX querycache_type_value
- ON querycache (qc_type, qc_value);
-
-
-
-CREATE TABLE querycache_info (
- qci_type VARCHAR(255) UNIQUE NOT NULL,
- qci_timestamp TIMESTAMP(3)
-);
-
-
-
-CREATE TABLE querycachetwo (
- qcc_type VARCHAR(255) NOT NULL,
- qcc_value BIGINT NOT NULL DEFAULT 0,
- qcc_namespace INTEGER NOT NULL DEFAULT 0,
- qcc_title VARCHAR(255) NOT NULL DEFAULT '',
- qcc_namespacetwo INTEGER NOT NULL DEFAULT 0,
- qcc_titletwo VARCHAR(255) NOT NULL DEFAULT ''
-);
-CREATE INDEX querycachetwo_type_value
- ON querycachetwo (qcc_type, qcc_value);
-CREATE INDEX querycachetwo_title
- ON querycachetwo (qcc_type, qcc_namespace, qcc_title);
-CREATE INDEX querycachetwo_titletwo
- ON querycachetwo (qcc_type, qcc_namespacetwo, qcc_titletwo);
-
-
-
-CREATE TABLE objectcache (
- keyname VARCHAR(255) NOT NULL UNIQUE, -- was nullable
- value CLOB(16M) INLINE LENGTH 4096 NOT NULL DEFAULT '',
- exptime TIMESTAMP(3) NOT NULL
-);
-CREATE INDEX objectcacache_exptime
- ON objectcache (exptime);
-
-
-
-CREATE TABLE transcache (
- tc_url VARCHAR(255) NOT NULL UNIQUE,
- tc_contents CLOB(64K) INLINE LENGTH 4096 NOT NULL,
- tc_time TIMESTAMP(3) NOT NULL
-);
-
-
-
-CREATE TABLE logging (
- log_id BIGINT NOT NULL
- PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- log_type VARCHAR(32) NOT NULL,
- log_action VARCHAR(32) NOT NULL,
- log_timestamp TIMESTAMP(3) NOT NULL,
- log_user BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES user(user_id) ON DELETE SET NULL,
- -- Name of the user who performed this action
- log_user_text VARCHAR(255) NOT NULL DEFAULT '',
- log_namespace SMALLINT NOT NULL,
- log_title VARCHAR(255) NOT NULL,
- log_page BIGINT,
- log_comment VARCHAR(255),
- log_params CLOB(64K) INLINE LENGTH 4096,
- log_deleted SMALLINT NOT NULL DEFAULT 0
-);
-CREATE INDEX logging_type_name
- ON logging (log_type, log_timestamp);
-CREATE INDEX logging_user_time
- ON logging (log_timestamp, log_user);
-CREATE INDEX logging_page_time
- ON logging (log_namespace, log_title, log_timestamp);
-CREATE INDEX log_user_type_time
- ON logging (log_user, log_type, log_timestamp);
-CREATE INDEX log_page_id_time
- ON logging (log_page, log_timestamp);
-CREATE UNIQUE INDEX type_action
- ON logging (log_type, log_action, log_timestamp);
-
-
-
-CREATE TABLE trackbacks (
- tb_id INTEGER NOT NULL
- PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- -- foreign key also in MySQL
- tb_page INTEGER,
- -- REFERENCES page(page_id) ON DELETE CASCADE,
- tb_title VARCHAR(255) NOT NULL,
- tb_url CLOB(64K) INLINE LENGTH 4096 NOT NULL,
- tb_ex CLOB(64K) INLINE LENGTH 4096,
- tb_name VARCHAR(255)
-);
-CREATE INDEX trackback_page
- ON trackbacks (tb_page);
-
-
-
-CREATE TABLE job (
- job_id BIGINT NOT NULL
- PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- job_cmd VARCHAR(255) NOT NULL,
- job_namespace SMALLINT NOT NULL,
- job_title VARCHAR(255) NOT NULL,
- job_params CLOB(64K) INLINE LENGTH 4096 NOT NULL
-);
-CREATE INDEX job_cmd_namespace_title
- ON job (job_cmd, job_namespace, job_title);
-
-
-
---TODO
---CREATE FUNCTION add_interwiki (TEXT, INT, SMALLINT) RETURNS INT LANGUAGE SQL AS
---$mw$
--- INSERT INTO interwiki (iw_prefix, iw_url, iw_local) VALUES ($1,$2,$3);
--- SELECT 1;
---$mw$;
-
-
-
--- hack implementation
--- should be replaced with OmniFind, Contains(), etc
-CREATE TABLE searchindex (
- si_page BIGINT NOT NULL,
- si_title VARCHAR(255) NOT NULL DEFAULT '',
- si_text CLOB NOT NULL
-);
-
-
-
--- This table is not used unless profiling is turned on
-CREATE TABLE profiling (
- pf_count INTEGER NOT NULL DEFAULT 0,
- pf_time NUMERIC(18,10) NOT NULL DEFAULT 0,
- pf_memory NUMERIC(18,10) NOT NULL DEFAULT 0,
- pf_name VARCHAR(255) NOT NULL,
- pf_server VARCHAR(255)
-);
-CREATE UNIQUE INDEX pf_name_server
- ON profiling (pf_name, pf_server);
-
-
-
-CREATE TABLE protected_titles (
- pt_namespace INTEGER NOT NULL,
- pt_title VARCHAR(255) NOT NULL,
- pt_user BIGINT NOT NULL DEFAULT 0,
- -- REFERENCES user(user_id) ON DELETE SET NULL,
- pt_reason VARCHAR(1024),
- pt_timestamp TIMESTAMP(3) NOT NULL,
- pt_expiry TIMESTAMP(3),
- pt_create_perm VARCHAR(60) NOT NULL DEFAULT ''
-);
-CREATE UNIQUE INDEX protected_titles_unique
- ON protected_titles (pt_namespace, pt_title);
-
-
-
-CREATE TABLE updatelog (
- ul_key VARCHAR(255) NOT NULL
- PRIMARY KEY
-);
-
-
-
-CREATE TABLE category (
- cat_id INTEGER NOT NULL
- PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- cat_title VARCHAR(255) NOT NULL,
- cat_pages INTEGER NOT NULL DEFAULT 0,
- cat_subcats INTEGER NOT NULL DEFAULT 0,
- cat_files INTEGER NOT NULL DEFAULT 0,
- cat_hidden SMALLINT NOT NULL DEFAULT 0
-);
-CREATE UNIQUE INDEX category_title
- ON category (cat_title);
-CREATE INDEX category_pages
- ON category (cat_pages);
-
-
-
--- A table to track tags for revisions, logs and recent changes.
-CREATE TABLE change_tag (
- ct_rc_id INTEGER,
- ct_log_id INTEGER,
- ct_rev_id INTEGER,
- ct_tag VARCHAR(255) NOT NULL,
- ct_params CLOB(64K) INLINE LENGTH 4096
-);
-CREATE UNIQUE INDEX change_tag_rc_tag
- ON change_tag (ct_rc_id, ct_tag);
-CREATE UNIQUE INDEX change_tag_log_tag
- ON change_tag (ct_log_id, ct_tag);
-CREATE UNIQUE INDEX 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 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
-CREATE TABLE tag_summary (
- ts_rc_id INTEGER,
- ts_log_id INTEGER,
- ts_rev_id INTEGER,
- ts_tags CLOB(64K) INLINE LENGTH 4096 NOT NULL
-);
-CREATE UNIQUE INDEX tag_summary_rc_id
- ON tag_summary (ts_rc_id);
-CREATE UNIQUE INDEX tag_summary_log_id
- ON tag_summary (ts_log_id);
-CREATE UNIQUE INDEX tag_summary_rev_id
- ON tag_summary (ts_rev_id);
-
-
-
-CREATE TABLE valid_tag (
- vt_tag VARCHAR(255) NOT NULL
- PRIMARY KEY
-);
-
-
-
---
--- User preferences and perhaps other fun stuff. :)
--- Replaces the old user.user_options blob, with a couple nice properties:
---
--- 1) We only store non-default settings, so changes to the DEFAULTs
--- are now reflected for everybody, not just new accounts.
--- 2) We can more easily do bulk lookups, statistics, or modifications of
--- saved options since it's a sane table structure.
---
-CREATE TABLE user_properties (
- -- Foreign key to user.user_id
- up_user BIGINT NOT NULL,
- -- Name of the option being saved. This is indexed for bulk lookup.
- up_property VARCHAR(255) FOR BIT DATA NOT NULL,
- -- Property value as a string.
- up_value CLOB(64K) INLINE LENGTH 4096
-);
-CREATE UNIQUE INDEX user_properties_user_property
- ON user_properties (up_user, up_property);
-CREATE INDEX user_properties_property
- ON user_properties (up_property);
-
-CREATE TABLE log_search (
- -- The type of ID (rev ID, log ID, rev TIMESTAMP(3), username)
- ls_field VARCHAR(32) FOR BIT DATA NOT NULL,
- -- The value of the ID
- ls_value VARCHAR(255) NOT NULL,
- -- Key to log_id
- ls_log_id BIGINT NOT NULL DEFAULT 0
-);
-CREATE UNIQUE INDEX ls_field_val
- ON log_search (ls_field, ls_value, ls_log_id);
-CREATE INDEX ls_log_id
- ON log_search (ls_log_id);
-
-
-
--- Table for storing localisation data
-CREATE TABLE l10n_cache (
- -- Language code
- lc_lang VARCHAR(32) NOT NULL,
- -- Cache key
- lc_key VARCHAR(255) NOT NULL,
- -- Value
- lc_value CLOB(16M) INLINE LENGTH 4096 NOT NULL
-);
-CREATE INDEX lc_lang_key
- ON l10n_cache (lc_lang, lc_key);
-
-
-
-CREATE TABLE msg_resource_links
-(
- mrl_resource VARCHAR(255) FOR BIT DATA NOT NULL,
- mrl_message VARCHAR(255) FOR BIT DATA NOT NULL
-);
-CREATE UNIQUE INDEX uq61_msg_resource_links
- ON msg_resource_links (mrl_message, mrl_resource);
--- All DB2 indexes DEFAULT to allowing reverse scans
-
-
-
-CREATE TABLE msg_resource
-(
- mr_resource VARCHAR(255) FOR BIT DATA NOT NULL,
- mr_lang VARCHAR(32) FOR BIT DATA NOT NULL,
- mr_blob CLOB(64K) INLINE LENGTH 4096 NOT NULL,
- mr_timestamp TIMESTAMP(3) NOT NULL
-);
-CREATE UNIQUE INDEX uq81_msg_resource
- ON msg_resource (mr_resource, mr_lang);
--- All DB2 indexes DEFAULT to allowing reverse scans
-
-
-
-CREATE TABLE module_deps (
- md_module VARCHAR(255) FOR BIT DATA NOT NULL,
- md_skin VARCHAR(32) FOR BIT DATA NOT NULL,
- md_deps CLOB(16M) INLINE LENGTH 4096 NOT NULL
-);
-CREATE UNIQUE INDEX uq96_module_deps
- ON module_deps (md_module, md_skin);
--- All DB2 indexes DEFAULT to allowing reverse scans
-
-
-
-CREATE TABLE iwlinks
-(
- iwl_from INTEGER NOT NULL,
- iwl_prefix VARCHAR(20) FOR BIT DATA NOT NULL,
- iwl_title VARCHAR(255) FOR BIT DATA NOT NULL
-);
-
-
-
---
--- Store information about newly uploaded files before they're
--- moved into the actual filestore
---
-CREATE TABLE uploadstash (
- us_id BIGINT NOT NULL
- PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- -- the user who uploaded the file.
- us_user BIGINT NOT NULL,
- -- file key. this is how applications actually search for the file.
- -- this might go away, or become the primary key.
- us_key VARCHAR(255) NOT NULL,
- -- the original path
- us_orig_path VARCHAR(255) NOT NULL,
- -- the temporary path at which the file is actually stored
- us_path VARCHAR(255) NOT NULL,
- -- which type of upload the file came from (sometimes)
- us_source_type VARCHAR(50),
- -- the date/time on which the file was added
- us_timestamp TIMESTAMP(3) NOT NULL,
- us_status VARCHAR(50) NOT NULL,
- -- file properties from File::getPropsFromPath. these may prove unnecessary.
- --
- us_size BIGINT NOT NULL,
- -- this hash comes from File::sha1Base36(), and is 31 characters
- us_sha1 VARCHAR(31) NOT NULL,
- us_mime VARCHAR(255),
- -- Media type as defined by the MEDIATYPE_xxx constants, should duplicate definition in the image table
- us_media_type VARCHAR(30)
- CONSTRAINT my_constraint
- CHECK (
- us_media_type in (
- 'UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA',
- 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE'
- )
- ) DEFAULT NULL,
- -- image-specific properties
- us_image_width BIGINT,
- us_image_height BIGINT,
- us_image_bits INTEGER
-);
--- sometimes there's a delete for all of a user's stuff.
-CREATE INDEX us_user
- ON uploadstash (us_user);
--- pick out files by key, enforce key UNIQUEness
-CREATE UNIQUE INDEX us_key
- ON uploadstash (us_key);
--- the abandoned upload cleanup script needs this
-CREATE INDEX us_timestamp
- ON uploadstash (us_timestamp);
-
-
-
--- Stores the groups the user has once belonged to.
--- The user may still belong these groups. Check user_groups.
-CREATE TABLE user_former_groups (
- ufg_user BIGINT NOT NULL DEFAULT 0,
- ufg_group VARCHAR(16) FOR BIT DATA NOT NULL
-);
-CREATE UNIQUE INDEX ufg_user_group
- ON user_former_groups (ufg_user, ufg_group);
array( TS_RFC2822, 'Tue, 31 Jul 2012 19:01:08 GMT', '20120731190108' ),
array( TS_ORACLE, '31-07-2012 19:01:08.000000', '20120731190108' ),
array( TS_POSTGRES, '2012-07-31 19:01:08 GMT', '20120731190108' ),
- array( TS_DB2, '2012-07-31 19:01:08', '20120731190108' ),
// Some extremes and weird values
array( TS_ISO_8601, '9999-12-31T23:59:59Z', '99991231235959' ),
array( TS_UNIX, '-62135596801', '00001231235959' )