544 lines
19 KiB
PHP
544 lines
19 KiB
PHP
<?php
|
|
|
|
namespace App;
|
|
|
|
class Schema extends Controller
|
|
{
|
|
|
|
private
|
|
$roundTime = 0,
|
|
$current_test = 1,
|
|
$current_engine,
|
|
$f3,
|
|
$test,
|
|
$tname;
|
|
|
|
private function getTime()
|
|
{
|
|
$time = microtime(TRUE) - $this->f3->get('timer') - $this->roundTime;
|
|
$this->roundTime = microtime(TRUE) - $this->f3->get('timer');
|
|
return ' [ '.sprintf('%.3f', $time).'s ]';
|
|
}
|
|
|
|
private function getTestDesc($text)
|
|
{
|
|
return $this->getTime().' '.$this->current_engine.': #'.$this->current_test++.' - '.$text;
|
|
}
|
|
|
|
function get()
|
|
{
|
|
$this->f3 = \Base::instance();
|
|
$this->test = new \Test;
|
|
|
|
$this->f3->set('QUIET', false);
|
|
$this->f3->set('CACHE', false);
|
|
|
|
$dbs = array(
|
|
/*'mysql' => new \DB\SQL(
|
|
'mysql:host=localhost;port=3306;dbname=fatfree', 'fatfree', ''
|
|
),*/
|
|
'sqlite' => new \DB\SQL(
|
|
'sqlite::memory:'
|
|
// 'sqlite:db/sqlite.db'
|
|
),
|
|
/*'pgsql' => new \DB\SQL(
|
|
'pgsql:host=localhost;dbname=fatfree', 'fatfree', 'fatfree'
|
|
),*/
|
|
/*'sqlsrv2012' => new \DB\SQL(
|
|
'sqlsrv:SERVER=LOCALHOST\SQLEXPRESS2012;Database=fatfree','fatfree', 'fatfree'
|
|
),*/
|
|
/*'sqlsrv2008' => new \DB\SQL(
|
|
'sqlsrv:SERVER=LOCALHOST\SQLEXPRESS2008;Database=fatfree','fatfree', 'fatfree'
|
|
)*/
|
|
);
|
|
|
|
$this->roundTime = microtime(TRUE) - \Base::instance()->get('timer');
|
|
$this->tname = 'test_table';
|
|
|
|
foreach ($dbs as $type => $db) {
|
|
$this->current_engine = $type;
|
|
$this->runTestSuite($db);
|
|
$this->current_test = 1;
|
|
}
|
|
$this->f3->set('results', $this->test->results());
|
|
}
|
|
|
|
private function runTestSuite($db)
|
|
{
|
|
$schema = new \DB\SQL\Schema($db);
|
|
|
|
$schema->dropTable($this->tname);
|
|
|
|
// create table
|
|
$table = $schema->createTable($this->tname);
|
|
$table = $table->build();
|
|
$result = $schema->getTables();
|
|
$this->test->expect(
|
|
in_array($this->tname, $result),
|
|
$this->getTestDesc('create default table')
|
|
);
|
|
unset($result);
|
|
|
|
$this->test->expect(
|
|
$table instanceof \DB\SQL\TableModifier,
|
|
$this->getTestDesc('$table->build() returns TableModifier')
|
|
);
|
|
|
|
// drop table
|
|
$table->drop();
|
|
$this->test->expect(
|
|
in_array($this->tname, $schema->getTables()) == false,
|
|
$this->getTestDesc('drop table')
|
|
);
|
|
unset($table);
|
|
|
|
// create table with columns
|
|
$table = $schema->createTable($this->tname);
|
|
$table->addColumn('title')->type($schema::DT_VARCHAR128);
|
|
$table->addColumn('number')->type($schema::DT_INT4);
|
|
$table = $table->build();
|
|
$r1 = $schema->getTables();
|
|
$r2 = $table->getCols();
|
|
$this->test->expect(
|
|
in_array($this->tname, $r1) && in_array('id', $r2)
|
|
&& in_array('title', $r2) && in_array('number', $r2),
|
|
$this->getTestDesc('create new table with additional columns')
|
|
);
|
|
unset($r1,$r2);
|
|
|
|
// testing all datatypes
|
|
foreach (array_keys($schema->dataTypes) as $index => $field) {
|
|
// testing column type
|
|
$table->addColumn('column_'.$index)->type($field);
|
|
$table->build();
|
|
$r1 = $table->getCols();
|
|
$this->test->expect(
|
|
in_array('column_'.$index, $r1),
|
|
$this->getTestDesc('adding column ['.$field.'], nullable')
|
|
);
|
|
}
|
|
unset($r1);
|
|
|
|
// adding some testing data
|
|
$mapper = new \DB\SQL\Mapper($db, $this->tname);
|
|
$mapper->column_7 = 'hello world';
|
|
$mapper->save();
|
|
$mapper->reset();
|
|
$result = $mapper->findone(array('column_7 = ?', 'hello world'))->cast();
|
|
unset($mapper);
|
|
$this->test->expect(
|
|
$result['column_7'] == 'hello world',
|
|
$this->getTestDesc('mapping dummy data')
|
|
);
|
|
|
|
// default value text, not nullable
|
|
$table->addColumn('text_default_not_null')
|
|
->type($schema::DT_VARCHAR128)
|
|
->nullable(false)->defaults('foo bar');
|
|
$table->build();
|
|
$r1 = $table->getCols(true);
|
|
$this->test->expect(
|
|
in_array('text_default_not_null', array_keys($r1)) &&
|
|
$r1['text_default_not_null']['default'] == 'foo bar' &&
|
|
$r1['text_default_not_null']['nullable'] == false,
|
|
$this->getTestDesc('adding column [VARCHAR128], not nullable with default value')
|
|
);
|
|
unset($r1);
|
|
|
|
// some testing dummy data
|
|
$mapper = new \DB\SQL\Mapper($db, $this->tname);
|
|
$mapper->column_7 = 'tanduay';
|
|
$mapper->save();
|
|
$mapper->reset();
|
|
$result = $mapper->findone(array('column_7 = ?','tanduay'))->cast();
|
|
$this->test->expect(
|
|
$result['column_7'] == 'tanduay' &&
|
|
$result['text_default_not_null'] == 'foo bar',
|
|
$this->getTestDesc('mapping dummy data')
|
|
);
|
|
unset($mapper,$result);
|
|
|
|
// default value numeric, not nullable
|
|
$table->addColumn('int_default_not_null')
|
|
->type($schema::DT_INT4)->nullable(false)->defaults(123);
|
|
$table->build();
|
|
$r1 = $table->getCols(true);
|
|
$this->test->expect(
|
|
in_array('int_default_not_null', array_keys($r1)) &&
|
|
$r1['int_default_not_null']['default'] == 123 &&
|
|
$r1['int_default_not_null']['nullable'] == false,
|
|
$this->getTestDesc('adding column [INT4], not nullable with default value')
|
|
);
|
|
unset($r1);
|
|
|
|
// adding testing data
|
|
$mapper = new \DB\SQL\Mapper($db, $this->tname);
|
|
$mapper->column_7 = 'test3';
|
|
$mapper->save();
|
|
$mapper->reset();
|
|
$r1 = $mapper->findone(array('column_7 = ?','test3'))->cast();
|
|
$this->test->expect(
|
|
$r1['column_7'] == 'test3' &&
|
|
$r1['int_default_not_null'] == 123,
|
|
$this->getTestDesc('mapping dummy data')
|
|
);
|
|
unset($mapper,$r1);
|
|
|
|
|
|
// default value text, nullable
|
|
$table->addColumn('text_default_nullable')
|
|
->type($schema::DT_VARCHAR128)
|
|
->defaults('foo bar');
|
|
$table->build();
|
|
$r1 = $table->getCols(true);
|
|
$this->test->expect(
|
|
in_array('text_default_nullable', array_keys($r1)) &&
|
|
$r1['text_default_nullable']['default'] == 'foo bar',
|
|
$this->getTestDesc('adding column [VARCHAR128], nullable with default value')
|
|
);
|
|
unset($r1);
|
|
|
|
// adding some dummy data
|
|
$mapper = new \DB\SQL\Mapper($db, $this->tname);
|
|
$mapper->column_7 = 'test4';
|
|
$mapper->save();
|
|
$mapper->reset();
|
|
$mapper->column_7 = 'test5';
|
|
$mapper->text_default_nullable = null;
|
|
$mapper->save();
|
|
$mapper->reset();
|
|
$result = $mapper->find(array('column_7 = ? OR column_7 = ?','test4','test5'));
|
|
foreach ($result as &$r)
|
|
$r = $r->cast();
|
|
|
|
$this->test->expect(
|
|
array_key_exists(0, $result) && array_key_exists(1, $result) &&
|
|
$result[0]['column_7'] == 'test4' && $result[0]['text_default_nullable'] == 'foo bar' &&
|
|
$result[1]['column_7'] == 'test5' && $result[1]['text_default_nullable'] === null,
|
|
$this->getTestDesc('mapping dummy data')
|
|
);
|
|
unset($mapper, $result);
|
|
|
|
// default value numeric, nullable
|
|
$table->addColumn('int_default_nullable')->type($schema::DT_INT4)->defaults(123);
|
|
$table->build();
|
|
$r1 = $table->getCols(true);
|
|
$this->test->expect(
|
|
in_array('int_default_nullable', array_keys($r1)) == true &&
|
|
$r1['int_default_nullable']['default'] == 123,
|
|
$this->getTestDesc('adding column [INT4], nullable with default value')
|
|
);
|
|
unset($r1);
|
|
|
|
// adding dummy data
|
|
$mapper = new \DB\SQL\Mapper($db, $this->tname);
|
|
$mapper->column_7 = 'test6';
|
|
$mapper->save();
|
|
$mapper->reset();
|
|
$mapper->column_7 = 'test7';
|
|
$mapper->int_default_nullable = null;
|
|
$mapper->save();
|
|
$mapper->reset();
|
|
$result = $mapper->find(array('column_7 = ? OR column_7 = ?', 'test6', 'test7'));
|
|
foreach ($result as &$r)
|
|
$r = $r->cast();
|
|
|
|
$this->test->expect(
|
|
array_key_exists(0, $result) && array_key_exists(1, $result) &&
|
|
$result[0]['column_7'] == 'test6' && $result[0]['int_default_nullable'] === 123 &&
|
|
$result[1]['column_7'] == 'test7' && $result[1]['int_default_nullable'] === null,
|
|
$this->getTestDesc('mapping dummy data')
|
|
);
|
|
unset($mapper, $result);
|
|
|
|
// current timestamp
|
|
$table->addColumn('stamp')
|
|
->type($schema::DT_TIMESTAMP)
|
|
->nullable(false)
|
|
->defaults($schema::DF_CURRENT_TIMESTAMP);
|
|
$table->build();
|
|
$r1 = $table->getCols(true);
|
|
$this->test->expect(
|
|
in_array('stamp', array_keys($r1)) &&
|
|
$r1['stamp']['default'] == $schema::DF_CURRENT_TIMESTAMP,
|
|
$this->getTestDesc(
|
|
'adding column [TIMESTAMP], not nullable with current_timestamp default value')
|
|
);
|
|
unset($r1);
|
|
|
|
|
|
// datetime nullable
|
|
$table->addColumn('datetime')->type_datetime()->nullable(true);
|
|
$table->build();
|
|
$r1 = $table->getCols(true);
|
|
$this->test->expect(
|
|
in_array('datetime', array_keys($r1)) &&
|
|
$r1['datetime']['nullable'] == true,
|
|
$this->getTestDesc(
|
|
'adding column [DATETIME], nullable, no default')
|
|
);
|
|
unset($r1);
|
|
|
|
|
|
// adding dummy data
|
|
$mapper = new \DB\SQL\Mapper($db, $this->tname);
|
|
$mapper->column_7 = 'test_datetime';
|
|
$mapper->datetime = NULL;
|
|
$mapper->save();
|
|
$mapper->reset();
|
|
$result = $mapper->find(array('column_7 = ?', 'test_datetime'));
|
|
foreach ($result as &$r)
|
|
$r = $r->cast();
|
|
|
|
$this->test->expect(
|
|
array_key_exists(0, $result) && $result[0]['column_7'] == 'test_datetime' &&
|
|
$result[0]['datetime'] === null,
|
|
$this->getTestDesc('mapping dummy data')
|
|
);
|
|
unset($mapper, $result);
|
|
|
|
|
|
// rename column
|
|
$table->renameColumn('text_default_not_null', 'title123');
|
|
$table->build();
|
|
$r1 = $table->getCols();
|
|
$this->test->expect(
|
|
in_array('title123', $r1) && !in_array('text_default_not_null', $r1),
|
|
$this->getTestDesc('renaming column')
|
|
);
|
|
unset($r1);
|
|
|
|
// adding dummy data
|
|
$mapper = new \DB\SQL\Mapper($db, $this->tname);
|
|
$mapper->title123 = 'test8';
|
|
$mapper->save();
|
|
$mapper->reset();
|
|
$result = $mapper->findone(array('title123 = ?','test8'));
|
|
$this->test->expect(
|
|
!$result->dry(),
|
|
$this->getTestDesc('mapping dummy data')
|
|
);
|
|
$table->renameColumn('title123', 'text_default_not_null');
|
|
$table->build();
|
|
unset($result,$mapper);
|
|
|
|
// remove column
|
|
$table->dropColumn('column_1');
|
|
$table->build();
|
|
$r1 = $table->getCols();
|
|
$this->test->expect(
|
|
!in_array('column_1', $r1),
|
|
$this->getTestDesc('removing column')
|
|
);
|
|
unset($r1);
|
|
|
|
// rename table
|
|
$schema->dropTable('test123');
|
|
$table->rename('test123');
|
|
$result = $schema->getTables();
|
|
$this->test->expect(
|
|
in_array('test123', $result) && !in_array($this->tname, $result),
|
|
$this->getTestDesc('renaming table')
|
|
);
|
|
$table->rename($this->tname);
|
|
unset($result);
|
|
|
|
// check record count
|
|
$mapper = new \DB\SQL\Mapper($db, $this->tname);
|
|
$this->test->expect(
|
|
count($mapper->find()) == 9,
|
|
$this->getTestDesc('check record count')
|
|
);
|
|
unset($mapper);
|
|
|
|
// adding composite primary keys
|
|
$table->addColumn('version')->type($schema::DT_INT4)->nullable(false)->defaults(1);
|
|
$table->primary(array('id', 'version'));
|
|
$table->build();
|
|
$r1 = $table->getCols(true);
|
|
$this->test->expect(!empty($r1) && isset($r1['version']) &&
|
|
$r1['id']['pkey'] == true && $r1['version']['pkey'] == true,
|
|
$this->getTestDesc('adding composite primary-keys')
|
|
);
|
|
unset($r1);
|
|
|
|
// check record count
|
|
$mapper = new \DB\SQL\Mapper($db, $this->tname);
|
|
$this->test->expect(
|
|
count($mapper->find()) == 9,
|
|
$this->getTestDesc('check record count')
|
|
);
|
|
unset($mapper);
|
|
|
|
// drop table
|
|
$schema->dropTable($this->tname);
|
|
$this->test->expect(
|
|
!in_array($this->tname, $schema->getTables()),
|
|
$this->getTestDesc('drop table')
|
|
);
|
|
|
|
// adding composite primary keys
|
|
$table = $schema->createTable($this->tname);
|
|
$table->addColumn('version')->type($schema::DT_INT4)
|
|
->defaults(1)->nullable(false);
|
|
$table->primary(array('id', 'version'));
|
|
$table = $table->build();
|
|
$r1 = $table->getCols(true);
|
|
|
|
$this->test->expect(!empty($r1) &&
|
|
$r1['id']['pkey'] == true && $r1['version']['pkey'] == true,
|
|
$this->getTestDesc('creating new table with composite key')
|
|
);
|
|
$this->test->expect(!empty($r1) &&
|
|
$r1['version']['default'] == '1',
|
|
$this->getTestDesc('default value on composite primary key')
|
|
);
|
|
unset($r1);
|
|
|
|
// more fields to composite primary key table
|
|
$table->addColumn('title')->type($schema::DT_VARCHAR256);
|
|
$table->addColumn('title2')->type($schema::DT_TEXT);
|
|
$table->addColumn('title_notnull')
|
|
->type($schema::DT_VARCHAR128)->nullable(false)->defaults("foo");
|
|
$table->build();
|
|
$r1 = $table->getCols(true);
|
|
$this->test->expect(
|
|
array_key_exists('title', $r1) &&
|
|
array_key_exists('title_notnull', $r1) &&
|
|
$r1['id']['pkey'] == true && $r1['version']['pkey'] == true,
|
|
$this->getTestDesc('adding more fields to composite pk table')
|
|
);
|
|
unset($r1);
|
|
|
|
// testing primary keys with inserted data
|
|
$mapper = new \DB\SQL\Mapper($db, $this->tname);
|
|
$mapper->title = 'test1';
|
|
$mapper->save();
|
|
$mapper->reset();
|
|
|
|
$mapper->id = 1;
|
|
$mapper->title = 'nullable';
|
|
$mapper->version = 2;
|
|
$mapper->save();
|
|
$mapper->reset();
|
|
|
|
$mapper->title = 'test3';
|
|
$mapper->title2 = 'foobar';
|
|
$mapper->title_notnull = 'bar';
|
|
$mapper->save();
|
|
|
|
$result = array_map(array($mapper,'cast'),$mapper->find());
|
|
|
|
$cpk_expected = array(
|
|
0=>array(
|
|
'id' => 1,
|
|
'version' => 1,
|
|
'title' => 'test1',
|
|
'title2' => NULL,
|
|
'title_notnull' => 'foo',
|
|
),
|
|
1=>array(
|
|
'id' => 1,
|
|
'version' => 2,
|
|
'title' => 'nullable',
|
|
'title2' => NULL,
|
|
'title_notnull' => 'foo',
|
|
),
|
|
2=>array(
|
|
'id' => 2,
|
|
'version' => 1,
|
|
'title' => 'test3',
|
|
'title2' => 'foobar',
|
|
'title_notnull' => 'bar',
|
|
),
|
|
);
|
|
foreach ($result as &$r)
|
|
ksort($r);
|
|
foreach ($cpk_expected as &$r)
|
|
ksort($r);
|
|
$this->test->expect(
|
|
json_encode($result) == json_encode($cpk_expected),
|
|
$this->getTestDesc('adding items with composite primary-keys')
|
|
);
|
|
|
|
$schema->dropTable($this->tname);
|
|
|
|
// indexes
|
|
$table = $schema->createTable($this->tname);
|
|
$table->addColumn('rawtest', array('type' => $schema::DT_VARCHAR256, 'default' => 'foo'));
|
|
$table->addColumn('text')->type($schema::DT_TEXT);
|
|
$table->addColumn('foo')->type($schema::DT_VARCHAR128)->index();
|
|
$table = $table->build();
|
|
$r1 = $table->getCols(true);
|
|
$this->test->expect(
|
|
isset($r1['rawtest']) && $r1['rawtest']['default'] = 'foo',
|
|
$this->getTestDesc('adding column with options array')
|
|
);
|
|
$indexes = $table->listIndex();
|
|
$this->test->expect(
|
|
isset($indexes[$table->name.'___foo']),
|
|
$this->getTestDesc('column index on table creation')
|
|
);
|
|
$table->addColumn('bar')->type($schema::DT_VARCHAR128)->index(true);
|
|
$table->addColumn('baz')->type($schema::DT_VARCHAR128);
|
|
$table->addIndex(array('foo', 'baz'));
|
|
$table->build();
|
|
$indexes = $table->listIndex();
|
|
$this->test->expect(
|
|
isset($indexes[$table->name.'___bar']),
|
|
$this->getTestDesc('column index on table alteration')
|
|
);
|
|
$this->test->expect(
|
|
isset($indexes[$table->name.'___bar']) && $indexes[$table->name.'___bar']['unique'] == true,
|
|
$this->getTestDesc('unique index')
|
|
);
|
|
$this->test->expect(
|
|
isset($indexes[$table->name.'___foo__baz']),
|
|
$this->getTestDesc('index on combined columns')
|
|
);
|
|
|
|
if($this->current_engine == 'sqlite') {
|
|
$table->dropColumn('rawtest');
|
|
$table->build();
|
|
$indexes = $table->listIndex();
|
|
$this->test->expect(
|
|
isset($indexes[$table->name.'___foo__baz']) && isset($indexes[$table->name.'___bar'])
|
|
&& $indexes[$table->name.'___bar']['unique'],
|
|
$this->getTestDesc('preserve indexes after table rebuild')
|
|
);
|
|
}
|
|
|
|
$table->dropIndex($table->name.'___bar');
|
|
$table->build();
|
|
$indexes = $table->listIndex();
|
|
$this->test->expect(
|
|
!array_key_exists($table->name.'___bar',$indexes),
|
|
$this->getTestDesc('drop index')
|
|
);
|
|
|
|
// update column
|
|
$table->updateColumn('bar',$schema::DT_TEXT);
|
|
$table->build();
|
|
$r1 = $table->getCols(true);
|
|
$this->test->expect(
|
|
array_key_exists('bar', $r1) && $r1['bar']['type'] == 'text',
|
|
$this->getTestDesc('update column')
|
|
);
|
|
|
|
// create table with text not nullable column
|
|
$table2 = $schema->createTable($this->tname.'_notnulltext');
|
|
$table2->addColumn('desc')->type($schema::DT_TEXT)->nullable(false);
|
|
$table2 = $table2->build();
|
|
$r1 = $schema->getTables();
|
|
$r2 = $table2->getCols(true);
|
|
$this->test->expect(
|
|
in_array($this->tname.'_notnulltext', $r1) && array_key_exists('desc', $r2)
|
|
&& $r2['desc']['nullable']==false,
|
|
$this->getTestDesc('create new table with not nullable text column')
|
|
);
|
|
$table2->drop();
|
|
|
|
|
|
}
|
|
|
|
} |