r58631 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r58630‎ | r58631 | r58632 >
Date:10:17, 6 November 2009
Author:maxsem
Status:ok (Comments)
Tags:
Comment:
Abstracted some parts of database interaction for parser tests, needs verification on Postgres. SQLite still doesn't work, though fails much later
Modified paths:
  • /trunk/phase3/includes/db/Database.php (modified) (history)
  • /trunk/phase3/includes/db/DatabaseMysql.php (modified) (history)
  • /trunk/phase3/includes/db/DatabasePostgres.php (modified) (history)
  • /trunk/phase3/includes/db/DatabaseSqlite.php (modified) (history)
  • /trunk/phase3/maintenance/parserTests.inc (modified) (history)
  • /trunk/phase3/maintenance/parserTests.php (modified) (history)

Diff [purge]

Index: trunk/phase3/maintenance/parserTests.inc
@@ -735,56 +735,27 @@
736736 $this->useTemporaryTables = false;
737737 }
738738
739 - $temporary = $this->useTemporaryTables ? 'TEMPORARY' : '';
 739+ $temporary = $this->useTemporaryTables || $wgDBtype == 'postgres';
740740
741741 $db = wfGetDB( DB_MASTER );
742742 $tables = $this->listTables();
743743
744 - if ( !( $wgDBtype == 'mysql' && strcmp( $db->getServerVersion(), '4.1' ) < 0 ) ) {
745 - # Database that supports CREATE TABLE ... LIKE
746 -
747 - if( $wgDBtype == 'postgres' ) {
748 - $def = 'INCLUDING DEFAULTS';
749 - $temporary = 'TEMPORARY';
750 - } else {
751 - $def = '';
752 - }
753 - foreach ( $tables as $tbl ) {
754 - # Clean up from previous aborted run. So that table escaping
755 - # works correctly across DB engines, we need to change the pre-
756 - # fix back and forth so tableName() works right.
757 - $this->changePrefix( $this->oldTablePrefix );
758 - $oldTableName = $db->tableName( $tbl );
759 - $this->changePrefix( 'parsertest_' );
760 - $newTableName = $db->tableName( $tbl );
 744+ foreach ( $tables as $tbl ) {
 745+ # Clean up from previous aborted run. So that table escaping
 746+ # works correctly across DB engines, we need to change the pre-
 747+ # fix back and forth so tableName() works right.
 748+ $this->changePrefix( $this->oldTablePrefix );
 749+ $oldTableName = $db->tableName( $tbl );
 750+ $this->changePrefix( 'parsertest_' );
 751+ $newTableName = $db->tableName( $tbl );
761752
762 - if ( $db->tableExists( $tbl ) && $wgDBtype != 'postgres' ) {
763 - $db->query( "DROP TABLE $newTableName" );
764 - }
765 - # Create new table
766 - $db->query( "CREATE $temporary TABLE $newTableName (LIKE $oldTableName $def)" );
 753+ if ( $db->tableExists( $tbl ) && $wgDBtype != 'postgres' ) {
 754+ $db->query( "DROP TABLE $newTableName" );
767755 }
768 - } else {
769 - # Hack for MySQL versions < 4.1, which don't support
770 - # "CREATE TABLE ... LIKE". Note that
771 - # "CREATE TEMPORARY TABLE ... SELECT * FROM ... LIMIT 0"
772 - # would not create the indexes we need....
773 - #
774 - # Note that we don't bother changing around the prefixes here be-
775 - # cause we know we're using MySQL anyway.
776 - foreach ($tables as $tbl) {
777 - $oldTableName = $db->tableName( $tbl );
778 - $res = $db->query("SHOW CREATE TABLE $oldTableName");
779 - $row = $db->fetchRow($res);
780 - $create = $row[1];
781 - $create_tmp = preg_replace('/CREATE TABLE `(.*?)`/',
782 - "CREATE $temporary TABLE `parsertest_$tbl`", $create);
783 - if ($create === $create_tmp) {
784 - # Couldn't do replacement
785 - wfDie("could not create temporary table $tbl");
786 - }
787 - $db->query($create_tmp);
788 - }
 756+ # Create new table
 757+ $db->begin();
 758+ $db->duplicateTableStructure( $oldTableName, $newTableName, $temporary );
 759+ $db->commit();
789760 }
790761
791762 $this->changePrefix( 'parsertest_' );
Index: trunk/phase3/maintenance/parserTests.php
@@ -53,6 +53,16 @@
5454 exit( 0 );
5555 }
5656
 57+# Cases of weird db corruption were encountered when running tests on earlyish
 58+# versions of SQLite
 59+if ( $wgDBtype == 'sqlite' ) {
 60+ $db = wfGetDB( DB_MASTER );
 61+ $version = $db->getServerVersion();
 62+ if ( version_compare( $version, '3.6' ) < 0 ) {
 63+ die( "Parser tests require SQLite version 3.6 or later, you have $version\n" );
 64+ }
 65+}
 66+
5767 # There is a convention that the parser should never
5868 # refer to $wgTitle directly, but instead use the title
5969 # passed to it.
Index: trunk/phase3/includes/db/DatabaseMysql.php
@@ -402,6 +402,31 @@
403403 ( $this->lastErrno() == 1290 && strpos( $this->lastError(), '--read-only' ) !== false );
404404 }
405405
 406+ function duplicateTableStructure( $oldName, $newName, $temporary = false, $fname = 'DatabaseMysql::duplicateTableStructure' ) {
 407+ if ( strcmp( $this->getServerVersion(), '4.1' ) < 0 ) {
 408+ # Hack for MySQL versions < 4.1, which don't support
 409+ # "CREATE TABLE ... LIKE". Note that
 410+ # "CREATE TEMPORARY TABLE ... SELECT * FROM ... LIMIT 0"
 411+ # would not create the indexes we need....
 412+ #
 413+ # Note that we don't bother changing around the prefixes here be-
 414+ # cause we know we're using MySQL anyway.
 415+
 416+ $res = $this->query( "SHOW CREATE TABLE $oldName" );
 417+ $row = $this->fetchRow( $res );
 418+ $create = $row[1];
 419+ $create_tmp = preg_replace( '/CREATE TABLE `(.*?)`/',
 420+ 'CREATE ' . ( $temporary ? 'TEMPORARY ' : '' ) . "TABLE `$newName`", $create );
 421+ if ($create === $create_tmp) {
 422+ # Couldn't do replacement
 423+ throw new MWException( "could not create temporary table $newName" );
 424+ }
 425+ $this->query( $create_tmp, $fname );
 426+ } else {
 427+ return parent::duplicateTableStructure( $oldName, $newName, $temporary );
 428+ }
 429+ }
 430+
406431 }
407432
408433 /**
Index: trunk/phase3/includes/db/DatabasePostgres.php
@@ -1085,6 +1085,10 @@
10861086 return $this->lastErrno() == '40P01';
10871087 }
10881088
 1089+ function duplicateTableStructure( $oldName, $newName, $temporary = false, $fname = 'DatabasePostgres::duplicateTableStructure' ) {
 1090+ return $this->query( 'CREATE ' . ( $temporary ? 'TEMPORARY ' : '' ) . " TABLE $newName (LIKE $oldName INCLUDING DEFAULTS)", $fname );
 1091+ }
 1092+
10891093 function timestamp( $ts=0 ) {
10901094 return wfTimestamp(TS_POSTGRES,$ts);
10911095 }
Index: trunk/phase3/includes/db/Database.php
@@ -1991,6 +1991,21 @@
19921992 }
19931993
19941994 /**
 1995+ * Creates a new table with structure copied from existing table
 1996+ * Note that unlike most database abstraction functions, this function does not
 1997+ * automatically append database prefix, because it works at a lower
 1998+ * abstraction level.
 1999+ *
 2000+ * @param $oldName String: name of table whose structure should be copied
 2001+ * @param $newName String: name of table to be created
 2002+ * @param $temporary Boolean: whether the new table should be temporary
 2003+ * @return Boolean: true if operation was successful
 2004+ */
 2005+ function duplicateTableStructure( $oldName, $newName, $temporary = false, $fname = 'Database::duplicateTableStructure' ) {
 2006+ return $this->query( 'CREATE ' . ( $temporary ? 'TEMPORARY ' : '' ) . " TABLE $newName (LIKE $oldName)", $fname );
 2007+ }
 2008+
 2009+ /**
19952010 * Return MW-style timestamp used for MySQL schema
19962011 */
19972012 function timestamp( $ts=0 ) {
Index: trunk/phase3/includes/db/DatabaseSqlite.php
@@ -520,6 +520,10 @@
521521 return '(' . implode( ') || (', $stringList ) . ')';
522522 }
523523
 524+ function duplicateTableStructure( $oldName, $newName, $temporary = false, $fname = 'DatabaseSqlite::duplicateTableStructure' ) {
 525+ return $this->query( 'CREATE ' . ( $temporary ? 'TEMPORARY ' : '' ) . " TABLE $newName AS SELECT * FROM $oldName LIMIT 0", $fname );
 526+ }
 527+
524528 } // end DatabaseSqlite class
525529
526530 /**

Follow-up revisions

RevisionCommit summaryAuthorDate
r58668Removed extra transactions on table creation introduced in r58631, makes no d...maxsem17:10, 6 November 2009
r59965Per CR for r58631, moved default duplicateTableStructure() implementation to ...maxsem19:53, 11 December 2009

Comments

#Comment by Simetrical (talk | contribs)   23:34, 10 December 2009

There's no point in having a method defined in DatabaseBase if only one child class uses it. The parent method should just throw an exception or something, and the DatabaseBase code should be moved into DatabaseMysql. Unless the DatabaseBase code actually works in DB2 or Oracle, which will currently try to execute it?

(Why do we need indexes on parser test tables?)

#Comment by MaxSem (talk | contribs)   19:58, 11 December 2009

There's no point in having a method defined in DatabaseBase if only one child class uses it. The parent method should just throw an exception or something, and the DatabaseBase code should be moved into DatabaseMysql.

Done.

Unless the DatabaseBase code actually works in DB2 or Oracle, which will currently try to execute it?

Already overridden in Oracle. Things that failed before this commit continue doing so after it.

Why do we need indexes on parser test tables?

Due to USING INDEX?
#Comment by Simetrical (talk | contribs)   20:52, 11 December 2009

Didn't think of USING INDEX, good point.

#Comment by Tim Starling (talk | contribs)   05:42, 21 December 2009

Works for me on PG.

Status & tagging log