From 6d11fb986f6821d1b541be0ac391b9c509f76ccd Mon Sep 17 00:00:00 2001 From: Jure Kajzer Date: Mon, 18 Oct 2010 16:09:18 +0000 Subject: [PATCH] * Installer: works (beta). More testing tomorow. * Updater: todo. For now it skips. --- includes/db/DatabaseOracle.php | 51 +++++++-- includes/installer/Installer.i18n.php | 9 ++ includes/installer/Installer.php | 1 + includes/installer/OracleInstaller.php | 140 ++++++++++++++++++------ includes/installer/WebInstallerPage.php | 2 +- maintenance/oracle/tables.sql | 46 +++++++- maintenance/oracle/user.sql | 4 +- 7 files changed, 205 insertions(+), 48 deletions(-) diff --git a/includes/db/DatabaseOracle.php b/includes/db/DatabaseOracle.php index 8b06e2eddf..3fbbd6583a 100644 --- a/includes/db/DatabaseOracle.php +++ b/includes/db/DatabaseOracle.php @@ -218,9 +218,9 @@ class DatabaseOracle extends DatabaseBase { return true; } - static function newFromParams( $server, $user, $password, $dbName, $failFunction = false, $flags = 0 ) + static function newFromParams( $server, $user, $password, $dbName, $failFunction = false, $flags = 0, $tablePrefix ) { - return new DatabaseOracle( $server, $user, $password, $dbName, $failFunction, $flags ); + return new DatabaseOracle( $server, $user, $password, $dbName, $failFunction, $flags, $tablePrefix ); } /** @@ -233,10 +233,23 @@ class DatabaseOracle extends DatabaseBase { } $this->close(); - $this->mServer = $server; $this->mUser = $user; $this->mPassword = $password; - $this->mDBname = $dbName; + // changed internal variables functions + // mServer now holds the TNS endpoint + // mDBname is schema name if different from username + if ($server == null || $server == false) { + // backward compatibillity (server used to be null and TNS was supplied in dbname) + $this->mServer = $dbName; + $this->mDBname = $user; + } else { + $this->mServer = $server; + if ( $dbName == null || $dbName == false ) { + $this->mDBname = $user; + } else { + $this->mDBname = $dbName; + } + } if ( !strlen( $user ) ) { # e.g. the class is being loaded return; @@ -244,9 +257,14 @@ class DatabaseOracle extends DatabaseBase { $session_mode = $this->mFlags & DBO_SYSDBA ? OCI_SYSDBA : OCI_DEFAULT; if ( $this->mFlags & DBO_DEFAULT ) { - $this->mConn = oci_new_connect( $user, $password, $dbName, $this->defaultCharset, $session_mode ); + $this->mConn = oci_new_connect( $this->mUser, $this->mPassword, $this->mServer, $this->defaultCharset, $session_mode ); } else { - $this->mConn = oci_connect( $user, $password, $dbName, $this->defaultCharset, $session_mode ); + $this->mConn = oci_connect( $this->mUser, $this->mPassword, $this->mServer, $this->defaultCharset, $session_mode ); + } + + if ( $this->mUser != $this->mDBname ) { + //change current schema in session + $this->selectDB( $this->mDBname ); } if ( !$this->mConn ) { @@ -1027,6 +1045,21 @@ class DatabaseOracle extends DatabaseBase { echo "
  • Table interwiki successfully populated
  • \n"; } + function selectDB( $db ) { + if ( $db == null || $db == $this->mUser ) { return true; } + $sql = 'ALTER SESSION SET CURRENT_SCHEMA='.strtoupper($db); + $stmt = oci_parse( $this->mConn, 'ALTER SESSION SET CURRENT_SCHEMA='.strtoupper($db) ); + if ( !oci_execute( $stmt ) ) { + $e = oci_error( $stmt ); +// wfDebugDieBacktrace(print_r($e, true)); + if ( $e['code'] != '1435' ) { + $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ ); + } + return false; + } + return true; + } + function strencode( $s ) { return str_replace( "'", "''", $s ); } @@ -1109,7 +1142,7 @@ class DatabaseOracle extends DatabaseBase { public function delete( $table, $conds, $fname = 'DatabaseOracle::delete' ) { global $wgContLang; - if ( $wgContLang != null ) { + if ( $wgContLang != null && $conds != '*' ) { $conds2 = array(); $conds = ( $conds != null && !is_array( $conds ) ) ? array( $conds ) : $conds; foreach ( $conds as $col => $val ) { @@ -1161,8 +1194,8 @@ class DatabaseOracle extends DatabaseBase { public function replaceVars( $ins ) { $varnames = array( 'wgDBprefix' ); if ( $this->mFlags & DBO_SYSDBA ) { - $varnames[] = 'wgDBOracleDefTS'; - $varnames[] = 'wgDBOracleTempTS'; + $varnames[] = '_OracleDefTS'; + $varnames[] = '_OracleTempTS'; } // Ordinary variables diff --git a/includes/installer/Installer.i18n.php b/includes/installer/Installer.i18n.php index 3e083fcc26..d647041ac1 100644 --- a/includes/installer/Installer.i18n.php +++ b/includes/installer/Installer.i18n.php @@ -177,12 +177,15 @@ Although MediaWiki checks all uploaded files for security threats, it is highly If you are using shared web hosting, your hosting provider should give you the correct host name in their documentation. If you are installing on a Windows server and using MySQL, using "localhost" may not work for the server name. If it does not, try "127.0.0.1" for the local IP address.', + 'config-db-host-oracle' => 'Database TNS:', + 'config-db-host-oracle-help' => 'TODO!:', 'config-db-wiki-settings' => 'Identify this wiki', 'config-db-name' => 'Database name:', 'config-db-name-help' => 'Choose a name that identifies your wiki. It should not contain spaces or hyphens. If you are using shared web hosting, your hosting provider will either give you a specific database name to use, or lets you create databases via a control panel.', + 'config-db-name-oracle' => 'Database schema:', 'config-db-install-account' => 'User account for installation', 'config-db-username' => 'Database username:', 'config-db-password' => 'Database password:', @@ -223,6 +226,8 @@ The installer will write a .htaccess file along with it, but if tha That includes raw user data (e-mail addresses, hashed passwords) as well as deleted revisions and other restricted data on the wiki. Consider putting the database somewhere else altogether, for example in /var/lib/mediawiki/yourwiki.", + 'config-oracle-def-ts' => 'Default tablespace:', + 'config-oracle-temp-ts' => 'Temporary tablespace:', 'config-type-mysql' => 'MySQL', 'config-type-postgres' => 'PostgreSQL', 'config-type-sqlite' => 'SQLite', @@ -235,12 +240,16 @@ If you do not see the database system you are trying to use listed below, then f 'config-support-mysql' => '* $1 is the primary target for MediaWiki and is best supported ([http://www.php.net/manual/en/mysql.installation.php how to compile PHP with MySQL support])', '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])', '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 comercial enterprise database. ([http://www.php.net/manual/en/oci8.installation.php How to compile PHP with OCI8 support])', 'config-header-mysql' => 'MySQL settings', 'config-header-postgres' => 'PostgreSQL settings', 'config-header-sqlite' => 'SQLite settings', 'config-header-oracle' => 'Oracle settings', 'config-invalid-db-type' => 'Invalid database type', 'config-missing-db-name' => 'You must enter a value for "Database name"', + 'config-missing-db-server-oracle' => 'You must enter a value for "Database TNS"', + 'config-invalid-db-server-oracle' => 'Invalid database TNS "$1". +Use only ASCII letters (a-z, A-Z), numbers (0-9), underscores (_) and dots (.).', 'config-invalid-db-name' => 'Invalid database name "$1". Use only ASCII letters (a-z, A-Z), numbers (0-9) and underscores (_).', 'config-invalid-db-prefix' => 'Invalid database prefix "$1". diff --git a/includes/installer/Installer.php b/includes/installer/Installer.php index da408cf668..88b8316e50 100644 --- a/includes/installer/Installer.php +++ b/includes/installer/Installer.php @@ -70,6 +70,7 @@ abstract class Installer { protected static $dbTypes = array( 'mysql', 'postgres', + 'oracle', 'sqlite', ); diff --git a/includes/installer/OracleInstaller.php b/includes/installer/OracleInstaller.php index 84d89f56e9..028f28d7b7 100644 --- a/includes/installer/OracleInstaller.php +++ b/includes/installer/OracleInstaller.php @@ -23,8 +23,9 @@ class OracleInstaller extends DatabaseInstaller { ); protected $internalDefaults = array( - '_InstallUser' => 'sys', - '_InstallPassword' => '', + '_OracleDefTS' => 'USERS', + '_OracleTempTS' => 'TEMP', + '_OracleUseSysdba' => true ); public function getName() { @@ -35,54 +36,75 @@ class OracleInstaller extends DatabaseInstaller { return self::checkExtension( 'oci8' ); } + public function getWebUserBox( $noCreateMsg = false ) { + $name = $this->getName(); + $this->parent->setVar( '_SameAccount', false ); + $this->parent->setVar( '_CreateDBAccount', true ); + $this->parent->setVar( 'wgDBname', '' ); + return Xml::openElement( 'fieldset' ) . + Xml::element( 'legend', array(), wfMsg( 'config-db-web-account' ) ) . + Xml::openElement( 'div', array( 'id' => 'dbOtherAccount' ) ) . + $this->getTextBox( 'wgDBuser', 'config-db-username' ) . + $this->getPasswordBox( 'wgDBpassword', 'config-db-password' ) . + $this->parent->getHelpBox( 'config-db-web-help' ). + $this->getCheckBox( '_CreateDBAccount', 'config-db-web-create', array( 'disabled' => true ) ). + Xml::closeElement( 'div' ) . Xml::closeElement( 'fieldset' ); + } + public function getConnectForm() { + $this->parent->setVar( '_InstallUser', 'sys' ); + $this->parent->setVar( 'wgDBserver', '' ); return + $this->getTextBox( 'wgDBserver', 'config-db-host-oracle' ) . + $this->parent->getHelpBox( 'config-db-host-oracle-help' ) . Xml::openElement( 'fieldset' ) . Xml::element( 'legend', array(), wfMsg( 'config-db-wiki-settings' ) ) . - $this->getTextBox( 'wgDBname', 'config-db-name' ) . - $this->parent->getHelpBox( 'config-db-name-help' ) . $this->getTextBox( 'wgDBprefix', 'config-db-prefix' ) . - $this->parent->getHelpBox( 'config-db-prefix-help' ) . + $this->getTextBox( '_OracleDefTS', 'config-oracle-def-ts' ) . + $this->getTextBox( '_OracleTempTS', 'config-oracle-temp-ts' ) . + $this->parent->getHelpBox( 'config-db-oracle-help' ) . Xml::closeElement( 'fieldset' ) . - $this->getInstallUserBox(); + $this->getInstallUserBox(). + $this->getWebUserBox(); } public function submitConnectForm() { // Get variables from the request - $newValues = $this->setVarsFromRequest( array( 'wgDBname', 'wgDBprefix' ) ); + $newValues = $this->setVarsFromRequest( array( 'wgDBserver', 'wgDBprefix', 'wgDBuser', 'wgDBpassword' ) ); + $this->parent->setVar( 'wgDBname', $this->getVar( 'wgDBuser' ) ); // 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['wgDBserver'] ) ) { + $status->fatal( 'config-missing-db-server-oracle' ); + } elseif ( !preg_match( '/^[a-zA-Z0-9_\.]+$/', $newValues['wgDBserver'] ) ) { + $status->fatal( 'config-invalid-db-server-oracle', $newValues['wgDBserver'] ); } if ( !preg_match( '/^[a-zA-Z0-9_]*$/', $newValues['wgDBprefix'] ) ) { $status->fatal( 'config-invalid-schema', $newValues['wgDBprefix'] ); } + if ( !$status->isOK() ) { + return $status; + } // Submit user box - if ( $status->isOK() ) { - $status->merge( $this->submitInstallUserBox() ); - } + $status = $this->submitInstallUserBox(); if ( !$status->isOK() ) { return $status; } // Try to connect - if ( $status->isOK() ) { - $status->merge( $this->attemptConnection() ); - } + $status = $this->getConnection(); if ( !$status->isOK() ) { return $status; } + $conn = $status->value; - // Check version /* - $version = $this->conn->getServerVersion(); + // Check version + $version = $conn->getServerVersion(); if ( version_compare( $version, $this->minimumVersion ) < 0 ) { - return Status::newFatal( 'config-postgres-old', $this->minimumVersion, $version ); + return Status::newFatal( 'config-mysql-old', $this->minimumVersion, $version ); } */ return $status; @@ -91,15 +113,27 @@ class OracleInstaller extends DatabaseInstaller { public function getConnection() { $status = Status::newGood(); try { - $this->db = new DatabaseOracle( - $this->getVar( 'wgDBserver' ), - $this->getVar( '_InstallUser' ), - $this->getVar( '_InstallPassword' ), - false, - false, - 0, - $this->getVar( 'wgDBprefix' ) - ); + if ( $this->getVar( '_OracleUseSysdba' ) ) { + $this->db = new DatabaseOracle( + $this->getVar( 'wgDBserver' ), + $this->getVar( '_InstallUser' ), + $this->getVar( '_InstallPassword' ), + $this->getVar( 'wgDBname' ), + false, + DBO_SYSDBA, + $this->getVar( 'wgDBprefix' ) + ); + } else { + $this->db = new DatabaseOracle( + $this->getVar( 'wgDBserver' ), + $this->getVar( 'wgDBuser' ), + $this->getVar( 'wgDBpassword' ), + $this->getVar( 'wgDBname' ), + false, + 0, + $this->getVar( 'wgDBprefix' ) + ); + } $status->value = $this->db; } catch ( DBConnectionError $e ) { $status->fatal( 'config-connection-error', $e->getMessage() ); @@ -107,10 +141,54 @@ class OracleInstaller extends DatabaseInstaller { return $status; } + public function needsUpgrade() { + $tempDBname = $this->getVar( 'wgDBname' ); + $this->parent->setVar( 'wgDBname', $this->getVar( 'wgDBuser' ) ); + $retVal = parent::needsUpgrade(); + $this->parent->setVar( 'wgDBname', $tempDBname ); + return $retVal; + } + + public function preInstall() { + # Add our user callback to installSteps, right before the tables are created. + $callback = array( + array( + 'name' => 'user', + 'callback' => array( $this, 'setupUser' ), + ) + ); + $this->parent->addInstallStepFollowing( "database", $callback ); + } + + public function setupDatabase() { - // TODO + $this->parent->setVar( '_OracleUseSysdba', false ); + $status = Status::newGood(); + return $status; } + public function setupUser() { + global $IP; + + if ( !$this->getVar( '_CreateDBAccount' ) ) { + return Status::newGood(); + } + $status = $this->getConnection(); + if ( !$status->isOK() ) { + return $status; + } + + global $_OracleDefTS, $_OracleTempTS; + $_OracleDefTS = $this->getVar( '_OracleDefTS' ); + $_OracleTempTS = $this->getVar( '_OracleTempTS' ); + $error = $this->db->sourceFile( "$IP/maintenance/oracle/user.sql" ); + if ( $error !== true || !$this->db->selectDB( $this->getVar( 'wgDBuser' ) ) ) { + $status->fatal( 'config-install-user-failed', $this->getVar( 'wgDBuser' ), $error ); + } + + return $status; + } + public function getLocalSettings() { $prefix = $this->getVar( 'wgDBprefix' ); return @@ -122,4 +200,4 @@ class OracleInstaller extends DatabaseInstaller { // TODO return false; } -} \ No newline at end of file +} diff --git a/includes/installer/WebInstallerPage.php b/includes/installer/WebInstallerPage.php index 93ae6ffc4d..b3738f6bfb 100644 --- a/includes/installer/WebInstallerPage.php +++ b/includes/installer/WebInstallerPage.php @@ -1001,4 +1001,4 @@ class WebInstaller_Copying extends WebInstaller_Document { return "\n" . str_repeat( ' ', strlen( $matches[0] ) ); } -} \ No newline at end of file +} diff --git a/maintenance/oracle/tables.sql b/maintenance/oracle/tables.sql index d2d1a21b14..35b3630778 100644 --- a/maintenance/oracle/tables.sql +++ b/maintenance/oracle/tables.sql @@ -127,7 +127,7 @@ CREATE TABLE &mw_prefix.archive ( ); CREATE INDEX &mw_prefix.archive_i01 ON &mw_prefix.archive (ar_namespace,ar_title,ar_timestamp); CREATE INDEX &mw_prefix.archive_i02 ON &mw_prefix.archive (ar_user_text,ar_timestamp); - +CREATE INDEX &mw_prefix.archive_i03 ON &mw_prefix.archive (ar_namespace, ar_title, ar_rev_id); CREATE TABLE &mw_prefix.pagelinks ( pl_from NUMBER NOT NULL REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE, @@ -156,12 +156,16 @@ CREATE UNIQUE INDEX &mw_prefix.imagelinks_u02 ON &mw_prefix.imagelinks (il_to,il CREATE TABLE &mw_prefix.categorylinks ( cl_from NUMBER NOT NULL REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE, cl_to VARCHAR2(255) NOT NULL, - cl_sortkey VARCHAR2(255), - cl_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL + cl_sortkey VARCHAR2(230), + cl_sortkey_prefix VARCHAR2(255) DEFAULT '' NOT NULL, + cl_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL, + cl_collation VARCHAR2(32) DEFAULT '' NOT NULL, + cl_type VARCHAR2(6) DEFAULT 'page' NOT NULL ); CREATE UNIQUE INDEX &mw_prefix.categorylinks_u01 ON &mw_prefix.categorylinks (cl_from,cl_to); -CREATE INDEX &mw_prefix.categorylinks_i01 ON &mw_prefix.categorylinks (cl_to,cl_sortkey,cl_from); +CREATE INDEX &mw_prefix.categorylinks_i01 ON &mw_prefix.categorylinks (cl_to,cl_type,cl_sortkey,cl_from); CREATE INDEX &mw_prefix.categorylinks_i02 ON &mw_prefix.categorylinks (cl_to,cl_timestamp); +CREATE INDEX &mw_prefix.categorylinks_i03 ON &mw_prefix.categorylinks (cl_collation); CREATE SEQUENCE category_cat_id_seq; CREATE TABLE &mw_prefix.category ( @@ -200,6 +204,14 @@ CREATE TABLE &mw_prefix.langlinks ( CREATE UNIQUE INDEX &mw_prefix.langlinks_u01 ON &mw_prefix.langlinks (ll_from, ll_lang); CREATE INDEX &mw_prefix.langlinks_i01 ON &mw_prefix.langlinks (ll_lang, ll_title); +CREATE TABLE &mw_prefix.iwlinks ( + iwl_from NUMBER DEFAULT 0 NOT NULL, + iwl_prefix VARCHAR2(20) DEFAULT '' NOT NULL, + iwl_title VARCHAR2(255) DEFAULT '' NOT NULL +); +CREATE UNIQUE INDEX &mw_prefix.iwlinks_ui01 ON &mw_prefix.iwlinks (iwl_from, iwl_prefix, iwl_title); +CREATE UNIQUE INDEX &mw_prefix.iwlinks_ui02 ON &mw_prefix.iwlinks (iwl_prefix, iwl_title, iwl_from); + CREATE TABLE &mw_prefix.site_stats ( ss_row_id NUMBER NOT NULL , ss_total_views NUMBER DEFAULT 0, @@ -388,6 +400,8 @@ CREATE UNIQUE INDEX &mw_prefix.searchindex_u01 ON &mw_prefix.searchindex (si_pag CREATE TABLE &mw_prefix.interwiki ( iw_prefix VARCHAR2(32) NOT NULL, iw_url VARCHAR2(127) NOT NULL, + iw_api BLOB NOT NULL, + iw_wikiid VARCHAR2(64), iw_local CHAR(1) NOT NULL, iw_trans CHAR(1) DEFAULT '0' NOT NULL ); @@ -531,7 +545,8 @@ CREATE UNIQUE INDEX &mw_prefix.page_props_u01 ON &mw_prefix.page_props (pp_page, CREATE TABLE &mw_prefix.updatelog ( - ul_key VARCHAR2(255) NOT NULL + ul_key VARCHAR2(255) NOT NULL, + ul_value BLOB ); ALTER TABLE &mw_prefix.updatelog ADD CONSTRAINT &mw_prefix.updatelog_pk PRIMARY KEY (ul_key); @@ -581,6 +596,27 @@ CREATE TABLE &mw_prefix.l10n_cache ( ); CREATE INDEX &mw_prefix.l10n_cache_u01 ON &mw_prefix.l10n_cache (lc_lang, lc_key); +CREATE TABLE &mw_prefix.msg_resource ( + mr_resource VARCHAR2(255) NOT NULL, + mr_lang varchar2(32) NOT NULL, + mr_blob BLOB NOT NULL, + mr_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL +) ; +CREATE UNIQUE INDEX &mw_prefix.msg_resource_u01 ON &mw_prefix.msg_resource (mr_resource, mr_lang); + +CREATE TABLE &mw_prefix.msg_resource_links ( + mrl_resource VARCHAR2(255) NOT NULL, + mrl_message VARCHAR2(255) NOT NULL +); +CREATE UNIQUE INDEX &mw_prefix.msg_resource_links_u01 ON &mw_prefix.msg_resource_links (mrl_message, mrl_resource); + +CREATE TABLE &mw_prefix.module_deps ( + md_module VARCHAR2(255) NOT NULL, + md_skin VARCHAR2(32) NOT NULL, + md_deps BLOB NOT NULL +); +CREATE UNIQUE INDEX &mw_prefix.module_deps_u01 ON &mw_prefix.module_deps (md_module, md_skin); + -- do not prefix this table as it breaks parserTests CREATE TABLE wiki_field_info_full ( table_name VARCHAR2(35) NOT NULL, diff --git a/maintenance/oracle/user.sql b/maintenance/oracle/user.sql index d54acf396f..57688eaeeb 100644 --- a/maintenance/oracle/user.sql +++ b/maintenance/oracle/user.sql @@ -1,8 +1,8 @@ -- defines must comply with ^define\s*([^\s=]*)\s*=\s?'\{\$([^\}]*)\}'; define wiki_user='{$wgDBuser}'; define wiki_pass='{$wgDBpassword}'; -define def_ts='{$wgDBOracleDefTS}'; -define temp_ts='{$wgDBOracleTempTS}'; +define def_ts='{$_OracleDefTS}'; +define temp_ts='{$_OracleTempTS}'; create user &wiki_user. identified by &wiki_pass. default tablespace &def_ts. temporary tablespace &temp_ts. quota unlimited on &def_ts.; grant connect, resource to &wiki_user.; -- 2.20.1