* fixed table duplication for unit tests
authorJure Kajzer <freakolowsky@users.mediawiki.org>
Tue, 7 Jun 2011 05:09:32 +0000 (05:09 +0000)
committerJure Kajzer <freakolowsky@users.mediawiki.org>
Tue, 7 Jun 2011 05:09:32 +0000 (05:09 +0000)
* fixed sequence handling when using DB prefix
* deferring constraints on transaction, switching back to immediate on commit/rollback
* hardcoded NLS_NUMERIC_CHARACTERS as it breaks using floats in sql if connection is in a non-US-like NLS_LANG (all vars are bound as chars)

includes/db/DatabaseOracle.php
maintenance/oracle/archives/patch_rebuild_dupfunc.sql
maintenance/oracle/tables.sql

index 23d7249..b298545 100644 (file)
@@ -278,6 +278,7 @@ class DatabaseOracle extends DatabaseBase {
                # removed putenv calls because they interfere with the system globaly
                $this->doQuery( 'ALTER SESSION SET NLS_TIMESTAMP_FORMAT=\'DD-MM-YYYY HH24:MI:SS.FF6\'' );
                $this->doQuery( 'ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT=\'DD-MM-YYYY HH24:MI:SS.FF6\'' );
+               $this->doQuery( 'ALTER SESSION SET NLS_NUMERIC_CHARACTERS=\'.,\'' );
                return $this->mConn;
        }
 
@@ -298,7 +299,7 @@ class DatabaseOracle extends DatabaseBase {
        }
 
        function execFlags() {
-               return $this->mTrxLevel ? OCI_DEFAULT : OCI_COMMIT_ON_SUCCESS;
+               return $this->mTrxLevel ? OCI_NO_AUTO_COMMIT : OCI_COMMIT_ON_SUCCESS;
        }
 
        function doQuery( $sql ) {
@@ -548,7 +549,7 @@ class DatabaseOracle extends DatabaseBase {
                                }
 
                                $val = ( $wgContLang != null ) ? $wgContLang->checkTitleEncoding( $val ) : $val;
-                               if ( oci_bind_by_name( $stmt, ":$col", $val ) === false ) {
+                               if ( oci_bind_by_name( $stmt, ":$col", $val, -1, SQLT_CHR ) === false ) {
                                        $e = oci_error( $stmt );
                                        $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
                                        return false;
@@ -686,7 +687,14 @@ class DatabaseOracle extends DatabaseBase {
         */
        private function getSequenceData( $table ) {
                if ( $this->sequenceData == null ) {
-                       $result = $this->doQuery( 'SELECT lower(us.sequence_name), lower(utc.table_name), lower(utc.column_name) from user_sequences us, user_tab_columns utc where us.sequence_name = utc.table_name||\'_\'||utc.column_name||\'_SEQ\'' );
+                       $result = $this->doQuery( "SELECT lower(asq.sequence_name),
+                                  lower(atc.table_name),
+                                  lower(atc.column_name)
+                         FROM all_sequences asq, all_tab_columns atc
+                        WHERE decode(atc.table_name, '{$this->mTablePrefix}MWUSER', '{$this->mTablePrefix}USER', atc.table_name) || '_' ||
+                                  atc.column_name || '_SEQ' = '{$this->mTablePrefix}' || asq.sequence_name
+                          AND asq.sequence_owner = '{$this->mDBname}'
+                          AND atc.owner = '{$this->mDBname}'" );
 
                        while ( ( $row = $result->fetchRow() ) !== false ) {
                                $this->sequenceData[$this->tableName( $row[1] )] = array(
@@ -695,7 +703,7 @@ class DatabaseOracle extends DatabaseBase {
                                );
                        }
                }
-
+               $table = strtolower( $this->removeIdentifierQuotes( $this->tableName( $table ) ) );
                return ( isset( $this->sequenceData[$table] ) ) ? $this->sequenceData[$table] : false;
        }
 
@@ -810,19 +818,15 @@ class DatabaseOracle extends DatabaseBase {
        }
 
        function duplicateTableStructure( $oldName, $newName, $temporary = false, $fname = 'DatabaseOracle::duplicateTableStructure' ) {
-               global $wgDBprefix;
-               $this->setFlag( DBO_DDLMODE );
-               
                $temporary = $temporary ? 'TRUE' : 'FALSE';
 
                $newName = strtoupper( $newName );
                $oldName = strtoupper( $oldName );
 
-               $tabName = substr( $newName, strlen( $wgDBprefix ) );
+               $tabName = substr( $newName, strlen( $this->mTablePrefix ) );
                $oldPrefix = substr( $oldName, 0, strlen( $oldName ) - strlen( $tabName ) );
-               $newPrefix = strtoupper( $wgDBprefix );
+               $newPrefix = strtoupper( $this->mTablePrefix );
 
-               $this->clearFlag( DBO_DDLMODE );
                return $this->doQuery( "BEGIN DUPLICATE_TABLE( '$tabName', '$oldPrefix', '$newPrefix', $temporary ); END;" );
        }
 
@@ -936,7 +940,7 @@ class DatabaseOracle extends DatabaseBase {
                } else {
                        $count = 0;
                }
-               return $count != 0;
+               return $count;
        }
 
        /**
@@ -1010,12 +1014,17 @@ class DatabaseOracle extends DatabaseBase {
 
        function begin( $fname = 'DatabaseOracle::begin' ) {
                $this->mTrxLevel = 1;
+               $this->doQuery( 'SET CONSTRAINTS ALL DEFERRED' );
        }
 
        function commit( $fname = 'DatabaseOracle::commit' ) {
                if ( $this->mTrxLevel ) {
-                       oci_commit( $this->mConn );
+                       $ret = oci_commit( $this->mConn );
+                       if ( !$ret ) {
+                               throw new DBUnexpectedError( $this, $this->lastError() );
+                       }
                        $this->mTrxLevel = 0;
+                       $this->doQuery( 'SET CONSTRAINTS ALL IMMEDIATE' );
                }
        }
 
@@ -1023,6 +1032,7 @@ class DatabaseOracle extends DatabaseBase {
                if ( $this->mTrxLevel ) {
                        oci_rollback( $this->mConn );
                        $this->mTrxLevel = 0;
+                       $this->doQuery( 'SET CONSTRAINTS ALL IMMEDIATE' );
                }
        }
 
index 7d637da..0a232db 100644 (file)
@@ -6,6 +6,7 @@ CREATE OR REPLACE PROCEDURE duplicate_table(p_tabname   IN VARCHAR2,
   e_table_not_exist EXCEPTION;
   PRAGMA EXCEPTION_INIT(e_table_not_exist, -00942);
   l_temp_ei_sql VARCHAR2(2000);
+  l_temporary   BOOLEAN := p_temporary;
 BEGIN
   BEGIN
     EXECUTE IMMEDIATE 'DROP TABLE ' || p_newprefix || p_tabname ||
@@ -14,7 +15,10 @@ BEGIN
     WHEN e_table_not_exist THEN
       NULL;
   END;
-  IF (p_temporary) THEN
+  IF (p_tabname = 'SEARCHINDEX') THEN
+    l_temporary := FALSE;
+  END IF;
+  IF (l_temporary) THEN
     EXECUTE IMMEDIATE 'CREATE GLOBAL TEMPORARY TABLE ' || p_newprefix ||
                       p_tabname || ' AS SELECT * FROM ' || p_oldprefix ||
                       p_tabname || ' WHERE ROWNUM = 0';
@@ -53,7 +57,7 @@ BEGIN
       EXECUTE IMMEDIATE l_temp_ei_sql;
     END IF;
   END LOOP;
-  IF (NOT p_temporary) THEN
+  IF (NOT l_temporary) THEN
     FOR rc IN (SELECT REPLACE(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl('REF_CONSTRAINT',
                                                                     constraint_name),
                                               32767,
@@ -98,6 +102,29 @@ BEGIN
       EXECUTE IMMEDIATE l_temp_ei_sql;
     END IF;
   END LOOP;
+  FOR rc IN (SELECT REPLACE(REPLACE(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl('INDEX',
+                                                                          index_name),
+                                                    32767,
+                                                    1),
+                                    USER || '"."' || p_oldprefix,
+                                    USER || '"."' || p_newprefix),
+                            '"' || index_name || '"',
+                            '"' || p_newprefix || index_name || '"') DDLVC2,
+                    index_name,
+                    index_type
+               FROM user_indexes ui
+              WHERE table_name = p_oldprefix || p_tabname
+                AND index_type = 'DOMAIN'
+                AND NOT EXISTS
+              (SELECT NULL
+                       FROM user_constraints
+                      WHERE table_name = ui.table_name
+                        AND constraint_name = ui.index_name)) LOOP
+    l_temp_ei_sql := rc.ddlvc2;
+    IF nvl(length(l_temp_ei_sql), 0) > 0 THEN
+      EXECUTE IMMEDIATE l_temp_ei_sql;
+    END IF;
+  END LOOP;
   FOR rc IN (SELECT REPLACE(REPLACE(UPPER(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl('TRIGGER',
                                                                                 trigger_name),
                                                           32767,
index 53979d2..54bafd0 100644 (file)
@@ -718,6 +718,7 @@ CREATE OR REPLACE PROCEDURE duplicate_table(p_tabname   IN VARCHAR2,
   e_table_not_exist EXCEPTION;
   PRAGMA EXCEPTION_INIT(e_table_not_exist, -00942);
   l_temp_ei_sql VARCHAR2(2000);
+  l_temporary   BOOLEAN := p_temporary;
 BEGIN
   BEGIN
     EXECUTE IMMEDIATE 'DROP TABLE ' || p_newprefix || p_tabname ||
@@ -726,7 +727,10 @@ BEGIN
     WHEN e_table_not_exist THEN
       NULL;
   END;
-  IF (p_temporary) THEN
+  IF (p_tabname = 'SEARCHINDEX') THEN
+    l_temporary := FALSE;
+  END IF;
+  IF (l_temporary) THEN
     EXECUTE IMMEDIATE 'CREATE GLOBAL TEMPORARY TABLE ' || p_newprefix ||
                       p_tabname || ' AS SELECT * FROM ' || p_oldprefix ||
                       p_tabname || ' WHERE ROWNUM = 0';
@@ -765,7 +769,7 @@ BEGIN
       EXECUTE IMMEDIATE l_temp_ei_sql;
     END IF;
   END LOOP;
-  IF (NOT p_temporary) THEN
+  IF (NOT l_temporary) THEN
     FOR rc IN (SELECT REPLACE(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl('REF_CONSTRAINT',
                                                                     constraint_name),
                                               32767,
@@ -810,6 +814,29 @@ BEGIN
       EXECUTE IMMEDIATE l_temp_ei_sql;
     END IF;
   END LOOP;
+  FOR rc IN (SELECT REPLACE(REPLACE(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl('INDEX',
+                                                                          index_name),
+                                                    32767,
+                                                    1),
+                                    USER || '"."' || p_oldprefix,
+                                    USER || '"."' || p_newprefix),
+                            '"' || index_name || '"',
+                            '"' || p_newprefix || index_name || '"') DDLVC2,
+                    index_name,
+                    index_type
+               FROM user_indexes ui
+              WHERE table_name = p_oldprefix || p_tabname
+                AND index_type = 'DOMAIN'
+                AND NOT EXISTS
+              (SELECT NULL
+                       FROM user_constraints
+                      WHERE table_name = ui.table_name
+                        AND constraint_name = ui.index_name)) LOOP
+    l_temp_ei_sql := rc.ddlvc2;
+    IF nvl(length(l_temp_ei_sql), 0) > 0 THEN
+      EXECUTE IMMEDIATE l_temp_ei_sql;
+    END IF;
+  END LOOP;
   FOR rc IN (SELECT REPLACE(REPLACE(UPPER(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl('TRIGGER',
                                                                                 trigger_name),
                                                           32767,
@@ -827,6 +854,7 @@ BEGIN
     END IF;
   END LOOP;
 END;
+
 /*$mw$*/
 
 /*$mw$*/