* Installer: works (beta). More testing tomorow.
authorJure Kajzer <freakolowsky@users.mediawiki.org>
Mon, 18 Oct 2010 16:09:18 +0000 (16:09 +0000)
committerJure Kajzer <freakolowsky@users.mediawiki.org>
Mon, 18 Oct 2010 16:09:18 +0000 (16:09 +0000)
* Updater: todo. For now it skips.

includes/db/DatabaseOracle.php
includes/installer/Installer.i18n.php
includes/installer/Installer.php
includes/installer/OracleInstaller.php
includes/installer/WebInstallerPage.php
maintenance/oracle/tables.sql
maintenance/oracle/user.sql

index 8b06e2e..3fbbd65 100644 (file)
@@ -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 "<li>Table interwiki successfully populated</li>\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
index 3e083fc..d647041 100644 (file)
@@ -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 <code>.htaccess</code> 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 <code>/var/lib/mediawiki/yourwiki</code>.",
+       '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".
index da408cf..88b8316 100644 (file)
@@ -70,6 +70,7 @@ abstract class Installer {
        protected static $dbTypes = array(
                'mysql',
                'postgres',
+               'oracle',
                'sqlite',
        );
 
index 84d89f5..028f28d 100644 (file)
@@ -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
+}
index 93ae6ff..b3738f6 100644 (file)
@@ -1001,4 +1001,4 @@ class WebInstaller_Copying extends WebInstaller_Document {
                return "\n" . str_repeat( '&#160;', strlen( $matches[0] ) );
        }
        
-}
\ No newline at end of file
+}
index d2d1a21..35b3630 100644 (file)
@@ -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,
index d54acf3..57688ea 100644 (file)
@@ -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.;