From: Max Semenik Date: Fri, 6 Nov 2009 10:17:44 +0000 (+0000) Subject: Abstracted some parts of database interaction for parser tests, needs verification... X-Git-Tag: 1.31.0-rc.0~38952 X-Git-Url: https://git.heureux-cyclage.org/?a=commitdiff_plain;h=1e3b2b8d5dfda15b059bd920f5723e1be1911cc4;p=lhc%2Fweb%2Fwiklou.git Abstracted some parts of database interaction for parser tests, needs verification on Postgres. SQLite still doesn't work, though fails much later --- diff --git a/includes/db/Database.php b/includes/db/Database.php index e3d390653e..21049b6f55 100644 --- a/includes/db/Database.php +++ b/includes/db/Database.php @@ -1990,6 +1990,21 @@ abstract class DatabaseBase { $this->commit(); } + /** + * Creates a new table with structure copied from existing table + * Note that unlike most database abstraction functions, this function does not + * automatically append database prefix, because it works at a lower + * abstraction level. + * + * @param $oldName String: name of table whose structure should be copied + * @param $newName String: name of table to be created + * @param $temporary Boolean: whether the new table should be temporary + * @return Boolean: true if operation was successful + */ + function duplicateTableStructure( $oldName, $newName, $temporary = false, $fname = 'Database::duplicateTableStructure' ) { + return $this->query( 'CREATE ' . ( $temporary ? 'TEMPORARY ' : '' ) . " TABLE $newName (LIKE $oldName)", $fname ); + } + /** * Return MW-style timestamp used for MySQL schema */ diff --git a/includes/db/DatabaseMysql.php b/includes/db/DatabaseMysql.php index 48b21a2486..f2c8508ff7 100644 --- a/includes/db/DatabaseMysql.php +++ b/includes/db/DatabaseMysql.php @@ -402,6 +402,31 @@ class DatabaseMysql extends DatabaseBase { ( $this->lastErrno() == 1290 && strpos( $this->lastError(), '--read-only' ) !== false ); } + function duplicateTableStructure( $oldName, $newName, $temporary = false, $fname = 'DatabaseMysql::duplicateTableStructure' ) { + if ( strcmp( $this->getServerVersion(), '4.1' ) < 0 ) { + # Hack for MySQL versions < 4.1, which don't support + # "CREATE TABLE ... LIKE". Note that + # "CREATE TEMPORARY TABLE ... SELECT * FROM ... LIMIT 0" + # would not create the indexes we need.... + # + # Note that we don't bother changing around the prefixes here be- + # cause we know we're using MySQL anyway. + + $res = $this->query( "SHOW CREATE TABLE $oldName" ); + $row = $this->fetchRow( $res ); + $create = $row[1]; + $create_tmp = preg_replace( '/CREATE TABLE `(.*?)`/', + 'CREATE ' . ( $temporary ? 'TEMPORARY ' : '' ) . "TABLE `$newName`", $create ); + if ($create === $create_tmp) { + # Couldn't do replacement + throw new MWException( "could not create temporary table $newName" ); + } + $this->query( $create_tmp, $fname ); + } else { + return parent::duplicateTableStructure( $oldName, $newName, $temporary ); + } + } + } /** diff --git a/includes/db/DatabasePostgres.php b/includes/db/DatabasePostgres.php index fcdb94fb5f..cd1e0285bb 100644 --- a/includes/db/DatabasePostgres.php +++ b/includes/db/DatabasePostgres.php @@ -1085,6 +1085,10 @@ class DatabasePostgres extends DatabaseBase { return $this->lastErrno() == '40P01'; } + function duplicateTableStructure( $oldName, $newName, $temporary = false, $fname = 'DatabasePostgres::duplicateTableStructure' ) { + return $this->query( 'CREATE ' . ( $temporary ? 'TEMPORARY ' : '' ) . " TABLE $newName (LIKE $oldName INCLUDING DEFAULTS)", $fname ); + } + function timestamp( $ts=0 ) { return wfTimestamp(TS_POSTGRES,$ts); } diff --git a/includes/db/DatabaseSqlite.php b/includes/db/DatabaseSqlite.php index 996a16e1dd..bab37cd8fa 100644 --- a/includes/db/DatabaseSqlite.php +++ b/includes/db/DatabaseSqlite.php @@ -520,6 +520,10 @@ class DatabaseSqlite extends DatabaseBase { return '(' . implode( ') || (', $stringList ) . ')'; } + function duplicateTableStructure( $oldName, $newName, $temporary = false, $fname = 'DatabaseSqlite::duplicateTableStructure' ) { + return $this->query( 'CREATE ' . ( $temporary ? 'TEMPORARY ' : '' ) . " TABLE $newName AS SELECT * FROM $oldName LIMIT 0", $fname ); + } + } // end DatabaseSqlite class /** diff --git a/maintenance/parserTests.inc b/maintenance/parserTests.inc index 924310a420..d24dc6f886 100644 --- a/maintenance/parserTests.inc +++ b/maintenance/parserTests.inc @@ -735,56 +735,27 @@ class ParserTest { $this->useTemporaryTables = false; } - $temporary = $this->useTemporaryTables ? 'TEMPORARY' : ''; + $temporary = $this->useTemporaryTables || $wgDBtype == 'postgres'; $db = wfGetDB( DB_MASTER ); $tables = $this->listTables(); - if ( !( $wgDBtype == 'mysql' && strcmp( $db->getServerVersion(), '4.1' ) < 0 ) ) { - # Database that supports CREATE TABLE ... LIKE - - if( $wgDBtype == 'postgres' ) { - $def = 'INCLUDING DEFAULTS'; - $temporary = 'TEMPORARY'; - } else { - $def = ''; - } - foreach ( $tables as $tbl ) { - # Clean up from previous aborted run. So that table escaping - # works correctly across DB engines, we need to change the pre- - # fix back and forth so tableName() works right. - $this->changePrefix( $this->oldTablePrefix ); - $oldTableName = $db->tableName( $tbl ); - $this->changePrefix( 'parsertest_' ); - $newTableName = $db->tableName( $tbl ); - - if ( $db->tableExists( $tbl ) && $wgDBtype != 'postgres' ) { - $db->query( "DROP TABLE $newTableName" ); - } - # Create new table - $db->query( "CREATE $temporary TABLE $newTableName (LIKE $oldTableName $def)" ); - } - } else { - # Hack for MySQL versions < 4.1, which don't support - # "CREATE TABLE ... LIKE". Note that - # "CREATE TEMPORARY TABLE ... SELECT * FROM ... LIMIT 0" - # would not create the indexes we need.... - # - # Note that we don't bother changing around the prefixes here be- - # cause we know we're using MySQL anyway. - foreach ($tables as $tbl) { - $oldTableName = $db->tableName( $tbl ); - $res = $db->query("SHOW CREATE TABLE $oldTableName"); - $row = $db->fetchRow($res); - $create = $row[1]; - $create_tmp = preg_replace('/CREATE TABLE `(.*?)`/', - "CREATE $temporary TABLE `parsertest_$tbl`", $create); - if ($create === $create_tmp) { - # Couldn't do replacement - wfDie("could not create temporary table $tbl"); - } - $db->query($create_tmp); + foreach ( $tables as $tbl ) { + # Clean up from previous aborted run. So that table escaping + # works correctly across DB engines, we need to change the pre- + # fix back and forth so tableName() works right. + $this->changePrefix( $this->oldTablePrefix ); + $oldTableName = $db->tableName( $tbl ); + $this->changePrefix( 'parsertest_' ); + $newTableName = $db->tableName( $tbl ); + + if ( $db->tableExists( $tbl ) && $wgDBtype != 'postgres' ) { + $db->query( "DROP TABLE $newTableName" ); } + # Create new table + $db->begin(); + $db->duplicateTableStructure( $oldTableName, $newTableName, $temporary ); + $db->commit(); } $this->changePrefix( 'parsertest_' ); diff --git a/maintenance/parserTests.php b/maintenance/parserTests.php index 83bc1f90f5..7853071682 100644 --- a/maintenance/parserTests.php +++ b/maintenance/parserTests.php @@ -53,6 +53,16 @@ ENDS; exit( 0 ); } +# Cases of weird db corruption were encountered when running tests on earlyish +# versions of SQLite +if ( $wgDBtype == 'sqlite' ) { + $db = wfGetDB( DB_MASTER ); + $version = $db->getServerVersion(); + if ( version_compare( $version, '3.6' ) < 0 ) { + die( "Parser tests require SQLite version 3.6 or later, you have $version\n" ); + } +} + # There is a convention that the parser should never # refer to $wgTitle directly, but instead use the title # passed to it.