2018-03-18 00:29:31 +00:00
|
|
|
<?php
|
|
|
|
|
|
2019-03-26 06:54:39 +00:00
|
|
|
use Wikimedia\Rdbms\Database;
|
2018-03-18 00:29:31 +00:00
|
|
|
use Wikimedia\Rdbms\DatabasePostgres;
|
2022-05-27 20:38:32 +00:00
|
|
|
use Wikimedia\Rdbms\DBQueryError;
|
2020-01-10 00:00:51 +00:00
|
|
|
use Wikimedia\Rdbms\IDatabase;
|
2018-03-18 00:29:31 +00:00
|
|
|
use Wikimedia\ScopedCallback;
|
|
|
|
|
use Wikimedia\TestingAccessWrapper;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @group Database
|
|
|
|
|
*/
|
2020-06-30 15:09:24 +00:00
|
|
|
class DatabasePostgresTest extends MediaWikiIntegrationTestCase {
|
2018-03-18 00:29:31 +00:00
|
|
|
|
2021-07-22 03:11:47 +00:00
|
|
|
protected function setUp(): void {
|
2020-12-23 10:03:34 +00:00
|
|
|
parent::setUp();
|
|
|
|
|
if ( !$this->db instanceof DatabasePostgres ) {
|
|
|
|
|
$this->markTestSkipped( 'Not PostgreSQL' );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-18 00:29:31 +00:00
|
|
|
private function doTestInsertIgnore() {
|
2018-09-30 15:14:16 +00:00
|
|
|
$fname = __METHOD__;
|
|
|
|
|
$reset = new ScopedCallback( function () use ( $fname ) {
|
2018-03-18 00:29:31 +00:00
|
|
|
if ( $this->db->explicitTrxActive() ) {
|
2018-09-30 15:14:16 +00:00
|
|
|
$this->db->rollback( $fname );
|
2018-03-18 00:29:31 +00:00
|
|
|
}
|
2018-09-30 15:14:16 +00:00
|
|
|
$this->db->query( 'DROP TABLE IF EXISTS ' . $this->db->tableName( 'foo' ), $fname );
|
2018-03-18 00:29:31 +00:00
|
|
|
} );
|
|
|
|
|
|
|
|
|
|
$this->db->query(
|
2018-09-30 15:14:16 +00:00
|
|
|
"CREATE TEMPORARY TABLE {$this->db->tableName( 'foo' )} (i INTEGER NOT NULL PRIMARY KEY)",
|
|
|
|
|
__METHOD__
|
2018-03-18 00:29:31 +00:00
|
|
|
);
|
|
|
|
|
$this->db->insert( 'foo', [ [ 'i' => 1 ], [ 'i' => 2 ] ], __METHOD__ );
|
|
|
|
|
|
|
|
|
|
// Normal INSERT IGNORE
|
|
|
|
|
$this->db->begin( __METHOD__ );
|
|
|
|
|
$this->db->insert(
|
|
|
|
|
'foo', [ [ 'i' => 3 ], [ 'i' => 2 ], [ 'i' => 5 ] ], __METHOD__, [ 'IGNORE' ]
|
|
|
|
|
);
|
|
|
|
|
$this->assertSame( 2, $this->db->affectedRows() );
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
[ '1', '2', '3', '5' ],
|
|
|
|
|
$this->db->selectFieldValues( 'foo', 'i', [], __METHOD__, [ 'ORDER BY' => 'i' ] )
|
|
|
|
|
);
|
|
|
|
|
$this->db->rollback( __METHOD__ );
|
|
|
|
|
|
|
|
|
|
// INSERT IGNORE doesn't ignore stuff like NOT NULL violations
|
|
|
|
|
$this->db->begin( __METHOD__ );
|
|
|
|
|
$this->db->startAtomic( __METHOD__, IDatabase::ATOMIC_CANCELABLE );
|
|
|
|
|
try {
|
|
|
|
|
$this->db->insert(
|
|
|
|
|
'foo', [ [ 'i' => 7 ], [ 'i' => null ] ], __METHOD__, [ 'IGNORE' ]
|
|
|
|
|
);
|
|
|
|
|
$this->db->endAtomic( __METHOD__ );
|
|
|
|
|
$this->fail( 'Expected exception not thrown' );
|
|
|
|
|
} catch ( DBQueryError $e ) {
|
|
|
|
|
$this->assertSame( 0, $this->db->affectedRows() );
|
|
|
|
|
$this->db->cancelAtomic( __METHOD__ );
|
|
|
|
|
}
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
[ '1', '2' ],
|
|
|
|
|
$this->db->selectFieldValues( 'foo', 'i', [], __METHOD__, [ 'ORDER BY' => 'i' ] )
|
|
|
|
|
);
|
|
|
|
|
$this->db->rollback( __METHOD__ );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2020-07-28 23:22:34 +00:00
|
|
|
* FIXME: See https://phabricator.wikimedia.org/T259084.
|
|
|
|
|
* @group Broken
|
2018-03-18 00:29:31 +00:00
|
|
|
* @covers Wikimedia\Rdbms\DatabasePostgres::insert
|
|
|
|
|
*/
|
|
|
|
|
public function testInsertIgnoreOld() {
|
|
|
|
|
if ( $this->db->getServerVersion() < 9.5 ) {
|
|
|
|
|
$this->doTestInsertIgnore();
|
|
|
|
|
} else {
|
|
|
|
|
// Hack version to make it take the old code path
|
|
|
|
|
$w = TestingAccessWrapper::newFromObject( $this->db );
|
|
|
|
|
$oldVer = $w->numericVersion;
|
|
|
|
|
$w->numericVersion = 9.4;
|
|
|
|
|
try {
|
|
|
|
|
$this->doTestInsertIgnore();
|
|
|
|
|
} finally {
|
|
|
|
|
$w->numericVersion = $oldVer;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2020-07-28 23:22:34 +00:00
|
|
|
* FIXME: See https://phabricator.wikimedia.org/T259084.
|
|
|
|
|
* @group Broken
|
2018-03-18 00:29:31 +00:00
|
|
|
* @covers Wikimedia\Rdbms\DatabasePostgres::insert
|
|
|
|
|
*/
|
|
|
|
|
public function testInsertIgnoreNew() {
|
|
|
|
|
if ( $this->db->getServerVersion() < 9.5 ) {
|
|
|
|
|
$this->markTestSkipped( 'PostgreSQL version is ' . $this->db->getServerVersion() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->doTestInsertIgnore();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function doTestInsertSelectIgnore() {
|
2018-09-30 15:14:16 +00:00
|
|
|
$fname = __METHOD__;
|
|
|
|
|
$reset = new ScopedCallback( function () use ( $fname ) {
|
2018-03-18 00:29:31 +00:00
|
|
|
if ( $this->db->explicitTrxActive() ) {
|
2018-09-30 15:14:16 +00:00
|
|
|
$this->db->rollback( $fname );
|
2018-03-18 00:29:31 +00:00
|
|
|
}
|
2018-09-30 15:14:16 +00:00
|
|
|
$this->db->query( 'DROP TABLE IF EXISTS ' . $this->db->tableName( 'foo' ), $fname );
|
|
|
|
|
$this->db->query( 'DROP TABLE IF EXISTS ' . $this->db->tableName( 'bar' ), $fname );
|
2018-03-18 00:29:31 +00:00
|
|
|
} );
|
|
|
|
|
|
|
|
|
|
$this->db->query(
|
2018-09-30 15:14:16 +00:00
|
|
|
"CREATE TEMPORARY TABLE {$this->db->tableName( 'foo' )} (i INTEGER)",
|
|
|
|
|
__METHOD__
|
2018-03-18 00:29:31 +00:00
|
|
|
);
|
|
|
|
|
$this->db->query(
|
2018-09-30 15:14:16 +00:00
|
|
|
"CREATE TEMPORARY TABLE {$this->db->tableName( 'bar' )} (i INTEGER NOT NULL PRIMARY KEY)",
|
|
|
|
|
__METHOD__
|
2018-03-18 00:29:31 +00:00
|
|
|
);
|
|
|
|
|
$this->db->insert( 'bar', [ [ 'i' => 1 ], [ 'i' => 2 ] ], __METHOD__ );
|
|
|
|
|
|
|
|
|
|
// Normal INSERT IGNORE
|
|
|
|
|
$this->db->begin( __METHOD__ );
|
|
|
|
|
$this->db->insert( 'foo', [ [ 'i' => 3 ], [ 'i' => 2 ], [ 'i' => 5 ] ], __METHOD__ );
|
|
|
|
|
$this->db->insertSelect( 'bar', 'foo', [ 'i' => 'i' ], [], __METHOD__, [ 'IGNORE' ] );
|
|
|
|
|
$this->assertSame( 2, $this->db->affectedRows() );
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
[ '1', '2', '3', '5' ],
|
|
|
|
|
$this->db->selectFieldValues( 'bar', 'i', [], __METHOD__, [ 'ORDER BY' => 'i' ] )
|
|
|
|
|
);
|
|
|
|
|
$this->db->rollback( __METHOD__ );
|
|
|
|
|
|
|
|
|
|
// INSERT IGNORE doesn't ignore stuff like NOT NULL violations
|
|
|
|
|
$this->db->begin( __METHOD__ );
|
|
|
|
|
$this->db->insert( 'foo', [ [ 'i' => 7 ], [ 'i' => null ] ], __METHOD__ );
|
|
|
|
|
$this->db->startAtomic( __METHOD__, IDatabase::ATOMIC_CANCELABLE );
|
|
|
|
|
try {
|
|
|
|
|
$this->db->insertSelect( 'bar', 'foo', [ 'i' => 'i' ], [], __METHOD__, [ 'IGNORE' ] );
|
|
|
|
|
$this->db->endAtomic( __METHOD__ );
|
|
|
|
|
$this->fail( 'Expected exception not thrown' );
|
|
|
|
|
} catch ( DBQueryError $e ) {
|
|
|
|
|
$this->assertSame( 0, $this->db->affectedRows() );
|
|
|
|
|
$this->db->cancelAtomic( __METHOD__ );
|
|
|
|
|
}
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
[ '1', '2' ],
|
|
|
|
|
$this->db->selectFieldValues( 'bar', 'i', [], __METHOD__, [ 'ORDER BY' => 'i' ] )
|
|
|
|
|
);
|
|
|
|
|
$this->db->rollback( __METHOD__ );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2020-07-28 23:22:34 +00:00
|
|
|
* FIXME: See https://phabricator.wikimedia.org/T259084.
|
|
|
|
|
* @group Broken
|
2020-03-02 22:20:09 +00:00
|
|
|
* @covers Wikimedia\Rdbms\DatabasePostgres::doInsertSelectNative
|
2018-03-18 00:29:31 +00:00
|
|
|
*/
|
|
|
|
|
public function testInsertSelectIgnoreOld() {
|
|
|
|
|
if ( $this->db->getServerVersion() < 9.5 ) {
|
|
|
|
|
$this->doTestInsertSelectIgnore();
|
|
|
|
|
} else {
|
|
|
|
|
// Hack version to make it take the old code path
|
|
|
|
|
$w = TestingAccessWrapper::newFromObject( $this->db );
|
|
|
|
|
$oldVer = $w->numericVersion;
|
|
|
|
|
$w->numericVersion = 9.4;
|
|
|
|
|
try {
|
|
|
|
|
$this->doTestInsertSelectIgnore();
|
|
|
|
|
} finally {
|
|
|
|
|
$w->numericVersion = $oldVer;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2020-07-28 23:22:34 +00:00
|
|
|
* FIXME: See https://phabricator.wikimedia.org/T259084.
|
|
|
|
|
* @group Broken
|
2020-03-02 22:20:09 +00:00
|
|
|
* @covers Wikimedia\Rdbms\DatabasePostgres::doInsertSelectNative
|
2018-03-18 00:29:31 +00:00
|
|
|
*/
|
|
|
|
|
public function testInsertSelectIgnoreNew() {
|
|
|
|
|
if ( $this->db->getServerVersion() < 9.5 ) {
|
|
|
|
|
$this->markTestSkipped( 'PostgreSQL version is ' . $this->db->getServerVersion() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->doTestInsertSelectIgnore();
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-26 06:54:39 +00:00
|
|
|
/**
|
|
|
|
|
* @covers \Wikimedia\Rdbms\DatabasePostgres::getAttributes
|
|
|
|
|
*/
|
|
|
|
|
public function testAttributes() {
|
2023-02-23 17:56:12 +00:00
|
|
|
$dbFactory = $this->getServiceContainer()->getDatabaseFactory();
|
2019-07-14 22:43:26 +00:00
|
|
|
$this->assertTrue(
|
2023-02-23 17:56:12 +00:00
|
|
|
$dbFactory->attributesFromType( 'postgres' )[Database::ATTR_SCHEMAS_AS_TABLE_GROUPS]
|
2019-07-14 22:43:26 +00:00
|
|
|
);
|
2019-03-26 06:54:39 +00:00
|
|
|
}
|
2022-07-28 22:10:31 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers \Wikimedia\Rdbms\Database::insert()
|
|
|
|
|
* @covers \Wikimedia\Rdbms\Database::insertId()
|
|
|
|
|
*/
|
|
|
|
|
public function testInsertIdAfterInsert() {
|
|
|
|
|
$dTable = $this->createDestTable();
|
|
|
|
|
|
|
|
|
|
$rows = [ [ 'k' => 'Luca', 'v' => mt_rand( 1, 100 ), 't' => time() ] ];
|
|
|
|
|
|
|
|
|
|
$this->db->insert( $dTable, $rows, __METHOD__ );
|
|
|
|
|
$this->assertSame( 1, $this->db->affectedRows() );
|
|
|
|
|
$this->assertSame( 1, $this->db->insertId() );
|
|
|
|
|
|
|
|
|
|
$this->assertSame( 1, (int)$this->db->selectField( $dTable, 'n', [ 'k' => 'Luca' ] ) );
|
|
|
|
|
$this->assertSame( 1, $this->db->affectedRows() );
|
|
|
|
|
|
|
|
|
|
$this->dropDestTable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers \Wikimedia\Rdbms\Database::insert()
|
|
|
|
|
* @covers \Wikimedia\Rdbms\Database::insertId()
|
|
|
|
|
*/
|
|
|
|
|
public function testInsertIdAfterInsertIgnore() {
|
|
|
|
|
$dTable = $this->createDestTable();
|
|
|
|
|
|
|
|
|
|
$rows = [ [ 'k' => 'Luca', 'v' => mt_rand( 1, 100 ), 't' => time() ] ];
|
|
|
|
|
|
|
|
|
|
$this->db->insert( $dTable, $rows, __METHOD__, 'IGNORE' );
|
|
|
|
|
$this->assertSame( 1, $this->db->affectedRows() );
|
|
|
|
|
$this->assertSame( 1, $this->db->insertId() );
|
|
|
|
|
$this->assertSame( 1, (int)$this->db->selectField( $dTable, 'n', [ 'k' => 'Luca' ] ) );
|
|
|
|
|
|
|
|
|
|
$this->db->insert( $dTable, $rows, __METHOD__, 'IGNORE' );
|
|
|
|
|
$this->assertSame( 0, $this->db->affectedRows() );
|
|
|
|
|
$this->assertSame( 0, $this->db->insertId() );
|
|
|
|
|
|
|
|
|
|
$this->assertSame( 1, (int)$this->db->selectField( $dTable, 'n', [ 'k' => 'Luca' ] ) );
|
|
|
|
|
$this->assertSame( 1, $this->db->affectedRows() );
|
|
|
|
|
|
|
|
|
|
$this->dropDestTable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers \Wikimedia\Rdbms\Database::replace()
|
|
|
|
|
* @covers \Wikimedia\Rdbms\Database::insertId()
|
|
|
|
|
*/
|
|
|
|
|
public function testInsertIdAfterReplace() {
|
|
|
|
|
$dTable = $this->createDestTable();
|
|
|
|
|
|
|
|
|
|
$rows = [ [ 'k' => 'Luca', 'v' => mt_rand( 1, 100 ), 't' => time() ] ];
|
|
|
|
|
|
|
|
|
|
$this->db->replace( $dTable, 'k', $rows, __METHOD__ );
|
|
|
|
|
$this->assertSame( 1, $this->db->affectedRows() );
|
|
|
|
|
$this->assertSame( 1, $this->db->insertId() );
|
|
|
|
|
$this->assertSame( 1, (int)$this->db->selectField( $dTable, 'n', [ 'k' => 'Luca' ] ) );
|
|
|
|
|
|
|
|
|
|
$this->db->replace( $dTable, 'k', $rows, __METHOD__ );
|
|
|
|
|
$this->assertSame( 2, $this->db->affectedRows() );
|
|
|
|
|
$this->assertSame( 2, $this->db->insertId() );
|
|
|
|
|
|
|
|
|
|
$this->assertSame( 2, (int)$this->db->selectField( $dTable, 'n', [ 'k' => 'Luca' ] ) );
|
|
|
|
|
$this->assertSame( 1, $this->db->affectedRows() );
|
|
|
|
|
|
|
|
|
|
$this->dropDestTable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers \Wikimedia\Rdbms\Database::upsert()
|
|
|
|
|
* @covers \Wikimedia\Rdbms\Database::insertId()
|
|
|
|
|
*/
|
|
|
|
|
public function testInsertIdAfterUpsert() {
|
|
|
|
|
$dTable = $this->createDestTable();
|
|
|
|
|
|
|
|
|
|
$rows = [ [ 'k' => 'Luca', 'v' => mt_rand( 1, 100 ), 't' => time() ] ];
|
|
|
|
|
$set = [
|
|
|
|
|
'v = ' . $this->db->buildExcludedValue( 'v' ),
|
|
|
|
|
't = ' . $this->db->buildExcludedValue( 't' ) . ' + 1'
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$this->db->upsert( $dTable, $rows, 'k', $set, __METHOD__ );
|
|
|
|
|
$this->assertSame( 1, $this->db->affectedRows() );
|
|
|
|
|
$this->assertSame( 1, $this->db->insertId() );
|
|
|
|
|
$this->assertSame( 1, (int)$this->db->selectField( $dTable, 'n', [ 'k' => 'Luca' ] ) );
|
|
|
|
|
|
|
|
|
|
$this->db->upsert( $dTable, $rows, 'k', $set, __METHOD__ );
|
|
|
|
|
$this->assertSame( 1, $this->db->affectedRows() );
|
|
|
|
|
$this->assertSame( 1, $this->db->insertId() );
|
|
|
|
|
|
|
|
|
|
$this->assertSame( 1, (int)$this->db->selectField( $dTable, 'n', [ 'k' => 'Luca' ] ) );
|
|
|
|
|
$this->assertSame( 1, $this->db->affectedRows() );
|
|
|
|
|
|
|
|
|
|
$this->dropDestTable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers \Wikimedia\Rdbms\Database::insertSelect()
|
|
|
|
|
* @covers \Wikimedia\Rdbms\Database::insertId()
|
|
|
|
|
*/
|
|
|
|
|
public function testInsertIdAfterInsertSelect() {
|
|
|
|
|
$sTable = $this->createSourceTable();
|
|
|
|
|
$dTable = $this->createDestTable();
|
|
|
|
|
|
|
|
|
|
$rows = [ [ 'sk' => 'Luca', 'sv' => mt_rand( 1, 100 ), 'st' => time() ] ];
|
|
|
|
|
$this->db->insert( $sTable, $rows, __METHOD__, 'IGNORE' );
|
|
|
|
|
$this->assertSame( 1, $this->db->affectedRows() );
|
|
|
|
|
$this->assertSame( 1, $this->db->insertId() );
|
|
|
|
|
$this->assertSame( 1, (int)$this->db->selectField( $sTable, 'sn', [ 'sk' => 'Luca' ] ) );
|
|
|
|
|
|
|
|
|
|
$this->db->insertSelect(
|
|
|
|
|
$dTable,
|
|
|
|
|
$sTable,
|
|
|
|
|
[ 'k' => 'sk', 'v' => 'sv', 't' => 'st' ],
|
|
|
|
|
[ 'sk' => 'Luca' ],
|
|
|
|
|
__METHOD__,
|
|
|
|
|
'IGNORE'
|
|
|
|
|
);
|
|
|
|
|
$this->assertSame( 1, $this->db->affectedRows() );
|
|
|
|
|
$this->assertSame( 1, $this->db->insertId() );
|
|
|
|
|
|
|
|
|
|
$this->assertSame( 1, (int)$this->db->selectField( $dTable, 'n', [ 'k' => 'Luca' ] ) );
|
|
|
|
|
$this->assertSame( 1, $this->db->affectedRows() );
|
|
|
|
|
|
|
|
|
|
$this->dropSourceTable();
|
|
|
|
|
$this->dropDestTable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers \Wikimedia\Rdbms\Database::insertSelect()
|
|
|
|
|
* @covers \Wikimedia\Rdbms\Database::insertId()
|
|
|
|
|
*/
|
|
|
|
|
public function testInsertIdAfterInsertSelectIgnore() {
|
|
|
|
|
$sTable = $this->createSourceTable();
|
|
|
|
|
$dTable = $this->createDestTable();
|
|
|
|
|
|
|
|
|
|
$rows = [ [ 'sk' => 'Luca', 'sv' => mt_rand( 1, 100 ), 'st' => time() ] ];
|
|
|
|
|
$this->db->insert( $sTable, $rows, __METHOD__, 'IGNORE' );
|
|
|
|
|
$this->assertSame( 1, $this->db->affectedRows() );
|
|
|
|
|
$this->assertSame( 1, $this->db->insertId() );
|
|
|
|
|
$this->assertSame( 1, (int)$this->db->selectField( $sTable, 'sn', [ 'sk' => 'Luca' ] ) );
|
|
|
|
|
|
|
|
|
|
$this->db->insertSelect(
|
|
|
|
|
$dTable,
|
|
|
|
|
$sTable,
|
|
|
|
|
[ 'k' => 'sk', 'v' => 'sv', 't' => 'st' ],
|
|
|
|
|
[ 'sk' => 'Luca' ],
|
|
|
|
|
__METHOD__,
|
|
|
|
|
'IGNORE'
|
|
|
|
|
);
|
|
|
|
|
$this->assertSame( 1, $this->db->affectedRows() );
|
|
|
|
|
$this->assertSame( 1, $this->db->insertId() );
|
|
|
|
|
$this->assertSame( 1, (int)$this->db->selectField( $dTable, 'n', [ 'k' => 'Luca' ] ) );
|
|
|
|
|
|
|
|
|
|
$this->db->insertSelect(
|
|
|
|
|
$dTable,
|
|
|
|
|
$sTable,
|
|
|
|
|
[ 'k' => 'sk', 'v' => 'sv', 't' => 'st' ],
|
|
|
|
|
[ 'sk' => 'Luca' ],
|
|
|
|
|
__METHOD__,
|
|
|
|
|
'IGNORE'
|
|
|
|
|
);
|
|
|
|
|
$this->assertSame( 0, $this->db->affectedRows() );
|
|
|
|
|
$this->assertSame( 0, $this->db->insertId() );
|
|
|
|
|
|
|
|
|
|
$this->assertSame( 1, (int)$this->db->selectField( $dTable, 'n', [ 'k' => 'Luca' ] ) );
|
|
|
|
|
$this->assertSame( 1, $this->db->affectedRows() );
|
|
|
|
|
|
|
|
|
|
$this->dropSourceTable();
|
|
|
|
|
$this->dropDestTable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function createSourceTable() {
|
|
|
|
|
$prefix = self::getTestPrefixFor( $this->db );
|
|
|
|
|
|
|
|
|
|
$this->db->query( "DROP TABLE IF EXISTS ${prefix}tmp_src_tbl" );
|
|
|
|
|
$this->db->query(
|
|
|
|
|
"CREATE TEMPORARY TABLE ${prefix}tmp_src_tbl (" .
|
|
|
|
|
"sn serial not null, " .
|
|
|
|
|
"sk text unique, " .
|
|
|
|
|
"sv integer, " .
|
|
|
|
|
"st integer, " .
|
|
|
|
|
"PRIMARY KEY(sn)" .
|
|
|
|
|
")"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return "tmp_src_tbl";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function createDestTable() {
|
|
|
|
|
$prefix = self::getTestPrefixFor( $this->db );
|
|
|
|
|
|
|
|
|
|
$this->db->query( "DROP TABLE IF EXISTS ${prefix}tmp_dst_tbl" );
|
|
|
|
|
$this->db->query(
|
|
|
|
|
"CREATE TEMPORARY TABLE ${prefix}tmp_dst_tbl (" .
|
|
|
|
|
"n serial not null, " .
|
|
|
|
|
"k text unique, " .
|
|
|
|
|
"v integer, " .
|
|
|
|
|
"t integer, " .
|
|
|
|
|
"PRIMARY KEY(n)" .
|
|
|
|
|
")"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return "tmp_dst_tbl";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function dropSourceTable() {
|
|
|
|
|
$prefix = self::getTestPrefixFor( $this->db );
|
|
|
|
|
|
|
|
|
|
$this->db->query( "DROP TABLE IF EXISTS ${prefix}tmp_src_tbl" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function dropDestTable() {
|
|
|
|
|
$prefix = self::getTestPrefixFor( $this->db );
|
|
|
|
|
|
|
|
|
|
$this->db->query( "DROP TABLE IF EXISTS ${prefix}tmp_dst_tbl" );
|
|
|
|
|
}
|
2018-03-18 00:29:31 +00:00
|
|
|
}
|