Index: trunk/phase3/maintenance/oracle/tables.sql |
— | — | @@ -803,7 +803,6 @@ |
804 | 804 | FROM user_triggers |
805 | 805 | WHERE table_name = p_oldprefix || p_tabname) LOOP |
806 | 806 | l_temp_ei_sql := SUBSTR(rc.ddlvc2, 1, INSTR(rc.ddlvc2, 'ALTER ') - 1); |
807 | | - dbms_output.put_line(l_temp_ei_sql); |
808 | 807 | EXECUTE IMMEDIATE l_temp_ei_sql; |
809 | 808 | END LOOP; |
810 | 809 | END; |
Index: trunk/phase3/tests/phpunit/MediaWikiTestCase.php |
— | — | @@ -18,7 +18,8 @@ |
19 | 19 | |
20 | 20 | protected $supportedDBs = array( |
21 | 21 | 'mysql', |
22 | | - 'sqlite' |
| 22 | + 'sqlite', |
| 23 | + 'oracle' |
23 | 24 | ); |
24 | 25 | |
25 | 26 | function __construct( $name = null, array $data = array(), $dataName = '' ) { |
— | — | @@ -155,7 +156,7 @@ |
156 | 157 | |
157 | 158 | foreach ( $tables as $table ) { |
158 | 159 | try { |
159 | | - $sql = $this->db->getType() == 'oracle' ? "DROP TABLE $table DROP CONSTRAINTS" : "DROP TABLE `$table`"; |
| 160 | + $sql = $this->db->getType() == 'oracle' ? "DROP TABLE $table CASCADE CONSTRAINTS PURGE" : "DROP TABLE `$table`"; |
160 | 161 | $this->db->query( $sql, __METHOD__ ); |
161 | 162 | } catch( Exception $e ) { |
162 | 163 | } |
Index: trunk/phase3/includes/db/DatabaseOracle.php |
— | — | @@ -7,21 +7,6 @@ |
8 | 8 | */ |
9 | 9 | |
10 | 10 | /** |
11 | | - * @ingroup Database |
12 | | - */ |
13 | | -class ORABlob { |
14 | | - var $mData; |
15 | | - |
16 | | - function __construct( $data ) { |
17 | | - $this->mData = $data; |
18 | | - } |
19 | | - |
20 | | - function getData() { |
21 | | - return $this->mData; |
22 | | - } |
23 | | -} |
24 | | - |
25 | | -/** |
26 | 11 | * The oci8 extension is fairly weak and doesn't support oci_num_rows, among |
27 | 12 | * other things. We use a wrapper class to handle that and other |
28 | 13 | * Oracle-specific bits, like converting column names back to lowercase. |
— | — | @@ -491,7 +476,7 @@ |
492 | 477 | } |
493 | 478 | |
494 | 479 | if ( $val === null ) { |
495 | | - if ( $col_info != false && $col_info->nullable() == 0 && $col_info->defaultValue() != null ) { |
| 480 | + if ( $col_info != false && $col_info->isNullable() == 0 && $col_info->defaultValue() != null ) { |
496 | 481 | $bind .= 'DEFAULT'; |
497 | 482 | } else { |
498 | 483 | $bind .= 'NULL'; |
— | — | @@ -853,6 +838,37 @@ |
854 | 839 | return $this->doQuery( 'BEGIN DUPLICATE_TABLE(\'' . $tabName . '\', \'' . $oldPrefix . '\', \'' . strtoupper( $wgDBprefix ) . '\', ' . $temporary . '); END;' ); |
855 | 840 | } |
856 | 841 | |
| 842 | + function listTables( $prefix = null, $fname = 'DatabaseOracle::listTables' ) { |
| 843 | + $listWhere = ''; |
| 844 | + if (!empty($prefix)) { |
| 845 | + $listWhere = ' AND table_name LIKE \''.strtoupper($prefix).'%\''; |
| 846 | + } |
| 847 | + |
| 848 | + $result = $this->doQuery( "SELECT table_name FROM user_tables WHERE table_name NOT LIKE '%!_IDX$_' ESCAPE '!' $listWhere" ); |
| 849 | + |
| 850 | + // dirty code ... i know |
| 851 | + $endArray = array(); |
| 852 | + $endArray[] = $prefix.'MWUSER'; |
| 853 | + $endArray[] = $prefix.'PAGE'; |
| 854 | + $endArray[] = $prefix.'IMAGE'; |
| 855 | + $fixedOrderTabs = $endArray; |
| 856 | + while (($row = $result->fetchRow()) !== false) { |
| 857 | + if (!in_array($row['table_name'], $fixedOrderTabs)) |
| 858 | + $endArray[] = $row['table_name']; |
| 859 | + } |
| 860 | + |
| 861 | + return $endArray; |
| 862 | + } |
| 863 | + |
| 864 | + public function dropTable( $tableName, $fName = 'DatabaseOracle::dropTable' ) { |
| 865 | + $tableName = $this->tableName($tableName); |
| 866 | + if( !$this->tableExists( $tableName ) ) { |
| 867 | + return false; |
| 868 | + } |
| 869 | + |
| 870 | + return $this->doQuery( "DROP TABLE $tableName CASCADE CONSTRAINTS PURGE" ); |
| 871 | + } |
| 872 | + |
857 | 873 | function timestamp( $ts = 0 ) { |
858 | 874 | return wfTimestamp( TS_ORACLE, $ts ); |
859 | 875 | } |
— | — | @@ -1046,7 +1062,7 @@ |
1047 | 1063 | } |
1048 | 1064 | } else { |
1049 | 1065 | foreach ( $replacements as $mwVar => $scVar ) { |
1050 | | - $cmd = str_replace( '&' . $scVar . '.', '{$' . $mwVar . '}', $cmd ); |
| 1066 | + $cmd = str_replace( '&' . $scVar . '.', '`{$' . $mwVar . '}`', $cmd ); |
1051 | 1067 | } |
1052 | 1068 | |
1053 | 1069 | $cmd = $this->replaceVars( $cmd ); |
— | — | @@ -1094,24 +1110,35 @@ |
1095 | 1111 | return "'" . $this->strencode( $s ) . "'"; |
1096 | 1112 | } |
1097 | 1113 | |
| 1114 | + public function addIdentifierQuotes( $s ) { |
| 1115 | + if ( !$this->mFlags & DBO_DDLMODE ) { |
| 1116 | + $s = '"' . str_replace( '"', '""', $s ) . '"'; |
| 1117 | + } |
| 1118 | + return $s; |
| 1119 | + } |
| 1120 | + |
1098 | 1121 | function selectRow( $table, $vars, $conds, $fname = 'DatabaseOracle::selectRow', $options = array(), $join_conds = array() ) { |
1099 | 1122 | global $wgContLang; |
1100 | 1123 | |
1101 | | - $conds2 = array(); |
1102 | | - $conds = ( $conds != null && !is_array( $conds ) ) ? array( $conds ) : $conds; |
1103 | | - foreach ( $conds as $col => $val ) { |
1104 | | - $col_info = $this->fieldInfoMulti( $table, $col ); |
1105 | | - $col_type = $col_info != false ? $col_info->type() : 'CONSTANT'; |
1106 | | - if ( $col_type == 'CLOB' ) { |
1107 | | - $conds2['TO_CHAR(' . $col . ')'] = $wgContLang->checkTitleEncoding( $val ); |
1108 | | - } elseif ( $col_type == 'VARCHAR2' && !mb_check_encoding( $val ) ) { |
1109 | | - $conds2[$col] = $wgContLang->checkTitleEncoding( $val ); |
1110 | | - } else { |
1111 | | - $conds2[$col] = $val; |
| 1124 | + if ($conds != null) { |
| 1125 | + $conds2 = array(); |
| 1126 | + $conds = ( !is_array( $conds ) ) ? array( $conds ) : $conds; |
| 1127 | + foreach ( $conds as $col => $val ) { |
| 1128 | + $col_info = $this->fieldInfoMulti( $table, $col ); |
| 1129 | + $col_type = $col_info != false ? $col_info->type() : 'CONSTANT'; |
| 1130 | + if ( $col_type == 'CLOB' ) { |
| 1131 | + $conds2['TO_CHAR(' . $col . ')'] = $wgContLang->checkTitleEncoding( $val ); |
| 1132 | + } elseif ( $col_type == 'VARCHAR2' && !mb_check_encoding( $val ) ) { |
| 1133 | + $conds2[$col] = $wgContLang->checkTitleEncoding( $val ); |
| 1134 | + } else { |
| 1135 | + $conds2[$col] = $val; |
| 1136 | + } |
1112 | 1137 | } |
| 1138 | + |
| 1139 | + return parent::selectRow( $table, $vars, $conds2, $fname, $options, $join_conds ); |
| 1140 | + } else { |
| 1141 | + return parent::selectRow( $table, $vars, $conds, $fname, $options, $join_conds ); |
1113 | 1142 | } |
1114 | | - |
1115 | | - return parent::selectRow( $table, $vars, $conds2, $fname, $options, $join_conds ); |
1116 | 1143 | } |
1117 | 1144 | |
1118 | 1145 | /** |
— | — | @@ -1160,9 +1187,9 @@ |
1161 | 1188 | public function delete( $table, $conds, $fname = 'DatabaseOracle::delete' ) { |
1162 | 1189 | global $wgContLang; |
1163 | 1190 | |
1164 | | - if ( $wgContLang != null && $conds != '*' ) { |
| 1191 | + if ( $wgContLang != null && $conds != null && $conds != '*' ) { |
1165 | 1192 | $conds2 = array(); |
1166 | | - $conds = ( $conds != null && !is_array( $conds ) ) ? array( $conds ) : $conds; |
| 1193 | + $conds = ( !is_array( $conds ) ) ? array( $conds ) : $conds; |
1167 | 1194 | foreach ( $conds as $col => $val ) { |
1168 | 1195 | $col_info = $this->fieldInfoMulti( $table, $col ); |
1169 | 1196 | $col_type = $col_info != false ? $col_info->type() : 'CONSTANT'; |
Index: trunk/phase3/includes/installer/DatabaseInstaller.php |
— | — | @@ -129,6 +129,7 @@ |
130 | 130 | return $status; |
131 | 131 | } |
132 | 132 | |
| 133 | + $this->db->setFlag( DBO_DDLMODE ); // For Oracle's handling of schema files |
133 | 134 | $error = $this->db->sourceFile( $this->db->getSchema() ); |
134 | 135 | if( $error !== true ) { |
135 | 136 | $this->db->reportQueryError( $error, 0, '', __METHOD__ ); |
Index: trunk/phase3/includes/installer/OracleInstaller.php |
— | — | @@ -24,9 +24,10 @@ |
25 | 25 | |
26 | 26 | protected $internalDefaults = array( |
27 | 27 | '_OracleDefTS' => 'USERS', |
28 | | - '_OracleTempTS' => 'TEMP', |
29 | | - '_OracleUseSysdba' => true |
| 28 | + '_OracleTempTS' => 'TEMP' |
30 | 29 | ); |
| 30 | + |
| 31 | + protected $useSysDBA = false; |
31 | 32 | |
32 | 33 | public $minimumVersion = '9.0.1'; // 9iR1 |
33 | 34 | |
— | — | @@ -92,6 +93,7 @@ |
93 | 94 | } |
94 | 95 | |
95 | 96 | // Try to connect |
| 97 | + $this->useSysDBA = true; |
96 | 98 | $status = $this->getConnection(); |
97 | 99 | if ( !$status->isOK() ) { |
98 | 100 | return $status; |
— | — | @@ -110,13 +112,13 @@ |
111 | 113 | public function getConnection() { |
112 | 114 | $status = Status::newGood(); |
113 | 115 | try { |
114 | | - if ( $this->getVar( '_OracleUseSysdba' ) ) { |
| 116 | + if ( $this->useSysDBA ) { |
115 | 117 | $this->db = new DatabaseOracle( |
116 | 118 | $this->getVar( 'wgDBserver' ), |
117 | 119 | $this->getVar( '_InstallUser' ), |
118 | 120 | $this->getVar( '_InstallPassword' ), |
119 | 121 | $this->getVar( 'wgDBname' ), |
120 | | - DBO_SYSDBA, |
| 122 | + DBO_SYSDBA | DBO_DDLMODE, |
121 | 123 | $this->getVar( 'wgDBprefix' ) |
122 | 124 | ); |
123 | 125 | } else { |
— | — | @@ -147,17 +149,15 @@ |
148 | 150 | public function preInstall() { |
149 | 151 | # Add our user callback to installSteps, right before the tables are created. |
150 | 152 | $callback = array( |
151 | | - array( |
152 | | - 'name' => 'user', |
153 | | - 'callback' => array( $this, 'setupUser' ), |
154 | | - ) |
| 153 | + 'name' => 'user', |
| 154 | + 'callback' => array( $this, 'setupUser' ) |
155 | 155 | ); |
156 | 156 | $this->parent->addInstallStep( $callback, 'database' ); |
157 | 157 | } |
158 | 158 | |
159 | 159 | |
160 | 160 | public function setupDatabase() { |
161 | | - $this->parent->setVar( '_OracleUseSysdba', false ); |
| 161 | + $this->useSysDBA = false; |
162 | 162 | $status = Status::newGood(); |
163 | 163 | return $status; |
164 | 164 | } |
— | — | @@ -168,6 +168,8 @@ |
169 | 169 | if ( !$this->getVar( '_CreateDBAccount' ) ) { |
170 | 170 | return Status::newGood(); |
171 | 171 | } |
| 172 | + |
| 173 | + $this->useSysDBA = true; |
172 | 174 | $status = $this->getConnection(); |
173 | 175 | if ( !$status->isOK() ) { |
174 | 176 | return $status; |
— | — | @@ -180,6 +182,7 @@ |
181 | 183 | */ |
182 | 184 | $GLOBALS['_OracleDefTS'] = $this->getVar( '_OracleDefTS' ); |
183 | 185 | $GLOBALS['_OracleTempTS'] = $this->getVar( '_OracleTempTS' ); |
| 186 | + $this->db->setFlag( DBO_DDLMODE ); |
184 | 187 | $error = $this->db->sourceFile( "$IP/maintenance/oracle/user.sql" ); |
185 | 188 | if ( $error !== true || !$this->db->selectDB( $this->getVar( 'wgDBuser' ) ) ) { |
186 | 189 | $status->fatal( 'config-install-user-failed', $this->getVar( 'wgDBuser' ), $error ); |
Index: trunk/phase3/includes/AutoLoader.php |
— | — | @@ -397,7 +397,6 @@ |
398 | 398 | 'LoadMonitor_MySQL' => 'includes/db/LoadMonitor.php', |
399 | 399 | 'MySQLField' => 'includes/db/DatabaseMysql.php', |
400 | 400 | 'MySQLMasterPos' => 'includes/db/DatabaseMysql.php', |
401 | | - 'ORABlob' => 'includes/db/DatabaseOracle.php', |
402 | 401 | 'ORAField' => 'includes/db/DatabaseOracle.php', |
403 | 402 | 'ORAResult' => 'includes/db/DatabaseOracle.php', |
404 | 403 | 'PostgresField' => 'includes/db/DatabasePostgres.php', |