$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
*/
( $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 );
+ }
+ }
+
}
/**
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);
}
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
/**
$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_' );
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.