From fd63c9c9d81571130c6388083cbe66cfcf52d566 Mon Sep 17 00:00:00 2001 From: Jure Kajzer Date: Fri, 6 Nov 2009 17:12:18 +0000 Subject: [PATCH] Started working on parserTests Oracle compatibility, still getting FK violations --- includes/db/DatabaseOracle.php | 14 ++++++-- maintenance/ora/tables.sql | 60 ++++++++++++++++++++++++++++++++++ maintenance/ora/user.sql | 1 + maintenance/parserTests.inc | 29 +++++++++++----- maintenance/testRunner.ora.sql | 37 +++++++++++++++++++++ 5 files changed, 131 insertions(+), 10 deletions(-) create mode 100644 maintenance/testRunner.ora.sql diff --git a/includes/db/DatabaseOracle.php b/includes/db/DatabaseOracle.php index 546536b744..283421560b 100644 --- a/includes/db/DatabaseOracle.php +++ b/includes/db/DatabaseOracle.php @@ -282,7 +282,8 @@ class DatabaseOracle extends DatabaseBase { //handle some oracle specifics //remove AS column/table/subquery namings - $sql = preg_replace('/ as /i', ' ', $sql); + if(!defined('MEDIAWIKI_INSTALL')) + $sql = preg_replace('/ as /i', ' ', $sql); // Oracle has issues with UNION clause if the statement includes LOB fields // So we do a UNION ALL and then filter the results array with array_unique $union_unique = (preg_match('/\/\* UNION_UNIQUE \*\/ /', $sql) != 0); @@ -746,6 +747,12 @@ class DatabaseOracle extends DatabaseBase { return $this->lastErrno() == 'OCI-00060'; } + + function duplicateTableStructure( $oldName, $newName, $temporary = false, $fname = 'DatabaseOracle::duplicateTableStructure' ) { + $temporary = $temporary ? 'TRUE' : 'FALSE'; + return $this->query( 'BEGIN DUPLICATE_TABLE(\''.$oldName.'\', \''.$newName.'\', '.$temporary.'); END;', $fname ); + } + function timestamp($ts = 0) { return wfTimestamp(TS_ORACLE, $ts); } @@ -986,8 +993,11 @@ class DatabaseOracle extends DatabaseBase { $col_type=$this->fieldInfo($this->tableName($table), $col)->type(); if ($col_type == 'CLOB') $conds2['TO_CHAR('.$col.')'] = $wgLang->checkTitleEncoding($val); - else + elseif ($col_type == 'VARCHAR2' && !mb_check_encoding($val)) { $conds2[$col] = $wgLang->checkTitleEncoding($val); + } else { + $conds2[$col] = $val; + } } if (is_array($table)) diff --git a/maintenance/ora/tables.sql b/maintenance/ora/tables.sql index d32503308a..fd0296dbe5 100644 --- a/maintenance/ora/tables.sql +++ b/maintenance/ora/tables.sql @@ -638,6 +638,66 @@ CREATE PROCEDURE &mw_prefix.fill_wiki_info IS END; /*$mw$*/ +/*$mw$*/ +CREATE OR REPLACE PROCEDURE duplicate_table(p_oldname IN VARCHAR2, p_newname IN VARCHAR2, p_temporary IN BOOLEAN) +IS + v_oldname VARCHAR2(32) := RTRIM(LTRIM(p_oldname, '"'), '"'); + v_newname VARCHAR2(32) := RTRIM(LTRIM(p_newname, '"'), '"'); + + e_table_not_exist EXCEPTION; + PRAGMA EXCEPTION_INIT(e_table_not_exist, -00942); +BEGIN + BEGIN + EXECUTE IMMEDIATE 'DROP TABLE '||v_newname||' CASCADE CONSTRAINTS'; + EXCEPTION WHEN e_table_not_exist THEN NULL; END; + + IF (p_temporary) THEN + EXECUTE IMMEDIATE 'CREATE GLOBAL TEMPORARY TABLE '||v_newname|| + ' AS SELECT * FROM '||v_oldname||' WHERE ROWNUM = 0'; + ELSE + EXECUTE IMMEDIATE 'CREATE TABLE '||v_newname|| + ' AS SELECT * FROM '||v_oldname||' WHERE ROWNUM = 0'; + END IF; + + FOR rc IN (SELECT column_name, data_default + FROM user_tab_columns + WHERE table_name = v_oldname + AND data_default IS NOT NULL) LOOP + EXECUTE IMMEDIATE 'ALTER TABLE '||v_newname||' MODIFY '||rc.column_name||' DEFAULT '||substr(rc.data_default, 1, 2000); + END LOOP; + + FOR rc IN (SELECT REPLACE(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl ('INDEX', index_name), 32767, 1), + USER||'"."'||v_oldname, USER||'"."'||v_newname) DDLVC2 + , index_name + FROM user_indexes ui + WHERE table_name = v_oldname + AND index_type != 'LOB') LOOP + EXECUTE IMMEDIATE SUBSTR(rc.ddlvc2, 1, INSTR(rc.ddlvc2, 'PCTFREE')-1); + END LOOP; + + FOR rc IN (SELECT REPLACE(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl ('CONSTRAINT', constraint_name), 32767, 1), + USER||'"."'||v_oldname, USER||'"."'||v_newname) DDLVC2 + , constraint_name + FROM user_constraints uc + WHERE table_name = v_oldname + AND constraint_type NOT IN ('C', 'P') + AND NOT EXISTS (SELECT NULL FROM user_indexes + WHERE table_name = uc.table_name + AND index_name = uc.constraint_name)) LOOP + EXECUTE IMMEDIATE SUBSTR(rc.ddlvc2, 1, INSTR(rc.ddlvc2, 'PCTFREE')-1); + END LOOP; + + FOR rc IN (SELECT REPLACE(REPLACE(UPPER(DBMS_LOB.SUBSTR(DBMS_METADATA.get_ddl ('TRIGGER', trigger_name), 32767, 1)), + USER||'"."'||v_oldname, USER||'"."'||v_newname), + ' ON '||v_oldname, ' ON '||v_newname) DDLVC2 + , trigger_name + FROM user_triggers + WHERE table_name = v_oldname) LOOP + EXECUTE IMMEDIATE SUBSTR(rc.ddlvc2, 1, INSTR(rc.ddlvc2, 'ALTER ')-1); + END LOOP; +END; +/*$mw$*/ + /*$mw$*/ BEGIN &mw_prefix.fill_wiki_info; diff --git a/maintenance/ora/user.sql b/maintenance/ora/user.sql index e3f377f7da..d54acf396f 100644 --- a/maintenance/ora/user.sql +++ b/maintenance/ora/user.sql @@ -13,3 +13,4 @@ grant create view to &wiki_user.; grant create synonym to &wiki_user.; grant create table to &wiki_user.; grant create sequence to &wiki_user.; +grant create trigger to &wiki_user.; diff --git a/maintenance/parserTests.inc b/maintenance/parserTests.inc index 64b41cc8da..c357f88da9 100644 --- a/maintenance/parserTests.inc +++ b/maintenance/parserTests.inc @@ -589,6 +589,7 @@ class ParserTest { * Ideally this should replace the global configuration entirely. */ private function setupGlobals($opts = '', $config = '') { + global $wgDBtype; if( !isset( $this->uploadDir ) ) { $this->uploadDir = $this->setupUploadDir(); } @@ -623,7 +624,7 @@ class ParserTest { 'wgServerName' => 'Britney-Spears', 'wgLanguageCode' => $lang, 'wgContLanguageCode' => $lang, - 'wgDBprefix' => 'parsertest_', + 'wgDBprefix' => $wgDBtype != 'oracle' ? 'parsertest_' : 'pt_', 'wgRawHtml' => isset( $opts['rawhtml'] ), 'wgLang' => null, 'wgContLang' => null, @@ -722,7 +723,7 @@ class ParserTest { if ( $this->databaseSetupDone ) { return; } - if ( $wgDBprefix === 'parsertest_' ) { + if ( $wgDBprefix === 'parsertest_' || ($wgDBtype == 'oracle' && $wgDBprefix === 'pt_')) { throw new MWException( 'setupDatabase should be called before setupGlobals' ); } $this->databaseSetupDone = true; @@ -746,17 +747,19 @@ class ParserTest { # fix back and forth so tableName() works right. $this->changePrefix( $this->oldTablePrefix ); $oldTableName = $db->tableName( $tbl ); - $this->changePrefix( 'parsertest_' ); + $this->changePrefix( $wgDBtype != 'oracle' ? 'parsertest_' : 'pt_' ); $newTableName = $db->tableName( $tbl ); - if ( $db->tableExists( $tbl ) && $wgDBtype != 'postgres' ) { + if ( $db->tableExists( $tbl ) && $wgDBtype != 'postgres' && $wgDBtype != 'oracle' ) { $db->query( "DROP TABLE $newTableName" ); } # Create new table $db->duplicateTableStructure( $oldTableName, $newTableName, $temporary ); } + if ($wgDBtype == 'oracle') + $db->query('BEGIN FILL_WIKI_INFO; END;'); - $this->changePrefix( 'parsertest_' ); + $this->changePrefix( $wgDBtype != 'oracle' ? 'parsertest_' : 'pt_' ); # Hack: insert a few Wikipedia in-project interwiki prefixes, # for testing inter-language links @@ -780,6 +783,10 @@ class ParserTest { 'iw_url' => 'http://ru.wikipedia.org/wiki/$1', 'iw_local' => 1 ), ) ); + # Hack-on-Hack: Insert a test user to be able to insert an image + $db->insert( 'user', array( + 'user_id' => 1, + 'user_name' => 'Tester') ); # Hack: Insert an image to work with $db->insert( 'image', array( @@ -823,7 +830,7 @@ class ParserTest { } private function teardownDatabase() { - global $wgDBprefix; + global $wgDBprefix, $wgDBtype; if ( !$this->databaseSetupDone ) { return; } @@ -838,8 +845,12 @@ class ParserTest { $tables = $this->listTables(); $db = wfGetDB( DB_MASTER ); foreach ( $tables as $table ) { - $db->query( "DROP TABLE `parsertest_$table`" ); - }*/ + $sql = $wgDBtype == 'oracle' ? "DROP TABLE pt_$table DROP CONSTRAINTS" : "DROP TABLE `parsertest_$table`"; + $db->query( $sql ); + } + if ($wgDBtype == 'oracle') + $db->query('BEGIN FILL_WIKI_INFO; END;'); + */ } /** @@ -1463,6 +1474,8 @@ class DbTestRecorder extends DbTestPreviewer { print "WARNING> `testrun` table not found in database. Trying to create table.\n"; if ($wgDBtype === 'postgres') $this->db->sourceFile( dirname(__FILE__) . '/testRunner.postgres.sql' ); + elseif ($wgDBtype === 'oracle') + $this->db->sourceFile( dirname(__FILE__) . '/testRunner.ora.sql' ); else $this->db->sourceFile( dirname(__FILE__) . '/testRunner.sql' ); echo "OK, resuming.\n"; diff --git a/maintenance/testRunner.ora.sql b/maintenance/testRunner.ora.sql new file mode 100644 index 0000000000..6e3e1b7c1b --- /dev/null +++ b/maintenance/testRunner.ora.sql @@ -0,0 +1,37 @@ +-- +-- Optional tables for parserTests recording mode +-- With --record option, success data will be saved to these tables, +-- and comparisons of what's changed from the previous run will be +-- displayed at the end of each run. +-- +-- defines must comply with ^define\s*([^\s=]*)\s*=\s?'\{\$([^\}]*)\}'; +define mw_prefix='{$wgDBprefix}'; + +DROP TABLE &mw_prefix.testitem CASCADE CONSTRAINTS; +DROP TABLE &mw_prefix.testrun CASCADE CONSTRAINTS; + +CREATE SEQUENCE testrun_tr_id_seq; +CREATE TABLE &mw_prefix.testrun ( + tr_id NUMBER NOT NULL, + tr_date DATE, + tr_mw_version BLOB, + tr_php_version BLOB, + tr_db_version BLOB, + tr_uname BLOB, +); +ALTER TABLE &mw_prefix.testrun ADD CONSTRAINT &mw_prefix.testrun_pk PRIMARY KEY (tr_id); +CREATE OR REPLACE TRIGGER &mw_prefix.testrun_bir +BEFORE UPDATE FOR EACH ROW +ON &mw_prefix.testrun +BEGIN + SELECT testrun_tr_id_seq.NEXTVAL into :NEW.tr_id FROM dual; +END; + +CREATE TABLE /*$wgDBprefix*/testitem ( + ti_run NUMBER NOT NULL REFERENCES &mw_prefix.testrun (tr_id) ON DELETE CASCADE, + ti_name VARCHAR22(255), + ti_success NUMBER(1) +); +CREATE UNIQUE INDEX &mw_prefix.testitem_u01 ON &mw_prefix.testitem (ti_run, ti_name); +CREATE UNIQUE INDEX &mw_prefix.testitem_u01 ON &mw_prefix.testitem (ti_run, ti_success); + -- 2.20.1