From: skodak Date: Thu, 12 Jun 2008 15:18:11 +0000 (+0000) Subject: MDL-14905 towards functional DB tests X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=5fe3f5c3770cde7d712a25cf45a4efbd67269e85;p=moodle.git MDL-14905 towards functional DB tests --- diff --git a/lib/ddl/simpletest/testddllib.php b/lib/ddl/simpletest/testddllib.php index 5f8faff52b..57d9b63975 100755 --- a/lib/ddl/simpletest/testddllib.php +++ b/lib/ddl/simpletest/testddllib.php @@ -94,22 +94,6 @@ class ddllib_test extends UnitTestCase { } } - public function testTableExists() { - $dbmanager = $this->db->get_manager(); -// TODO: this should be done with $this->db object - - $table = $this->create_deftable('test_table0'); - // Test giving a string - $this->assertFalse($dbmanager->table_exists('nonexistenttable')); - $this->assertTrue($dbmanager->table_exists('test_table0')); - - // Test giving a table object - $nonexistenttable = new xmldb_table('nonexistenttable'); - $this->assertFalse($dbmanager->table_exists($nonexistenttable)); - $this->assertTrue($dbmanager->table_exists($table)); - } - - private function create_deftable($tablename) { $dbmanager = $this->db->get_manager(); @@ -122,21 +106,37 @@ class ddllib_test extends UnitTestCase { if ($dbmanager->table_exists($table)) { $dbmanager->drop_table($table, true, false); } - $dbmanager->create_table($table); + $dbmanager->create_table($table, true, false); return $table; } - public function testCreateTable() { + public function testTableExists() { + $DB = $this->db; // do not use global $DB! $dbmanager = $this->db->get_manager(); -// TODO: add all data types, comments, keys and indexes + // first make sure it returns false if table does not exist $table = $this->tables['test_table0']; + ob_start(); // hide debug warning + $this->assertFalse($DB->get_records('test_table0')); + ob_end_clean(); + $this->assertFalse($dbmanager->table_exists('test_table0')); + $this->assertFalse($dbmanager->table_exists($table)); - $this->assertTrue($dbmanager->create_table($table)); + // create table and test again + $this->assertTrue($dbmanager->create_table($table, true, false)); + $this->assertTrue($DB->get_records('test_table0') !== false); $this->assertTrue($dbmanager->table_exists('test_table0')); - $dbmanager->drop_table($table); - $this->assertFalse($dbmanager->table_exists('test_table0')); + $this->assertTrue($dbmanager->table_exists($table)); + + // Test giving a string + $this->assertFalse($dbmanager->table_exists('nonexistenttable')); + $this->assertTrue($dbmanager->table_exists('test_table0')); + } + + public function testCreateTable() { + $DB = $this->db; // do not use global $DB! + $dbmanager = $this->db->get_manager(); // Give a wrong table param (expect a debugging message) $table = 'string'; @@ -144,19 +144,36 @@ class ddllib_test extends UnitTestCase { $this->assertFalse($dbmanager->create_table($table)); ob_end_clean(); + // create table and do basic column tests + $table = $this->tables['test_table1']; + + $this->assertTrue($dbmanager->create_table($table)); + $this->assertTrue($dbmanager->table_exists($table)); + + $columns = $DB->get_columns('test_table1'); + + $this->assertEqual($columns['id']->meta_type, 'R'); + $this->assertEqual($columns['course']->meta_type, 'I'); + $this->assertEqual($columns['name']->meta_type, 'C'); + $this->assertEqual($columns['secondname']->meta_type, 'C'); + $this->assertEqual($columns['intro']->meta_type, 'X'); + $this->assertEqual($columns['avatar']->meta_type, 'B'); + $this->assertEqual($columns['grade']->meta_type, 'N'); + } public function testDropTable() { $dbmanager = $this->db->get_manager(); $table = $this->create_deftable('test_table0'); + $this->assertTrue($dbmanager->drop_table($table, true, false)); $this->assertFalse($dbmanager->table_exists('test_table0')); // Try dropping non-existent table $table = new xmldb_table('nonexistenttable'); ob_start(); // hide debug warning - $this->assertFalse($dbmanager->drop_table($table, true, false)); + $this->assertTrue($dbmanager->drop_table($table, true, false)); ob_end_clean(); // Give a wrong table param @@ -168,24 +185,70 @@ class ddllib_test extends UnitTestCase { public function testAddEnumField() { + $DB = $this->db; // do not use global $DB! $dbmanager = $this->db->get_manager(); -// TODO: verify the type in DB - $table = $this->create_deftable('test_table0'); + $table = new xmldb_table('test_table_cust0'); + $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); + $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); + $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); + $this->assertTrue($dbmanager->create_table($table, true, false)); + + $enums = array('single', 'news', 'general'); /// Create a new field with complex specs (enums are good candidates) + $field = new xmldb_field('type1'); + $field->set_attributes(XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, XMLDB_ENUM, $enums, 'general', 'course'); + $this->assertTrue($dbmanager->add_field($table, $field)); + $this->assertTrue($dbmanager->field_exists($table, 'type1')); + $field = new xmldb_field('type2'); - $field->set_attributes(XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, XMLDB_ENUM, - array('single', 'news', 'general', 'social', 'eachuser', 'teacher', 'qanda'), 'general', 'course'); + $field->set_attributes(XMLDB_TYPE_CHAR, '20', null, null, null, XMLDB_ENUM, $enums, 'general', 'course'); $this->assertTrue($dbmanager->add_field($table, $field)); $this->assertTrue($dbmanager->field_exists($table, 'type2')); + /// try inserting a good record + $record = new object(); + $record->course = 666; + $record->type1 = 'news'; + $record->type2 = NULL; + $this->assertTrue($DB->insert_record('test_table_cust0', $record, false)); + + /// try inserting a bad record + $record = new object(); + $record->course = 666; + $record->type1 = 'xxxxxxxx'; + $record->type2 = 'news'; + ob_start(); // hide debug warning + $this->assertFalse($DB->insert_record('test_table_cust0', $record)); + ob_end_clean(); + + /// try inserting a bad record + $record = new object(); + $record->course = 666; + $record->type1 = 'news'; + $record->type2 = 'xxxx'; + ob_start(); // hide debug warning + $this->assertFalse($DB->insert_record('test_table_cust0', $record)); + ob_end_clean(); + + $columns = $DB->get_columns('test_table_cust0'); + $this->assertEqual($columns['type1']->meta_type, 'C'); + + // enums field is optional + $result = $columns['type1']->enums; + if (!is_null($result)) { + $this->assertEqual($result, $enums); + } + + /// cleanup $dbmanager->drop_field($table, $field); + $dbmanager->drop_table($table); } public function testAddNumericField() { + $DB = $this->db; // do not use global $DB! $dbmanager = $this->db->get_manager(); -// TODO: verify the type in DB $table = $this->create_deftable('test_table0'); /// Create a new field with complex specs (enums are good candidates) @@ -194,10 +257,12 @@ class ddllib_test extends UnitTestCase { $this->assertTrue($dbmanager->add_field($table, $field)); $this->assertTrue($dbmanager->field_exists($table, 'onenumber')); + $columns = $DB->get_columns('test_table0'); + $this->assertEqual($columns['onenumber']->meta_type, 'I'); + $dbmanager->drop_field($table, $field); } - public function testDropField() { $dbmanager = $this->db->get_manager(); @@ -206,39 +271,67 @@ class ddllib_test extends UnitTestCase { $this->assertTrue($dbmanager->field_exists($table, $field)); $this->assertTrue($dbmanager->field_exists($table, 'type')); + $this->assertTrue($dbmanager->drop_field($table, $field)); + $this->assertFalse($dbmanager->field_exists($table, 'type')); } - public function testChangeFieldType() { + $DB = $this->db; // do not use global $DB! $dbmanager = $this->db->get_manager(); -// TODO: verify the type is changed in db - $table = $this->create_deftable('test_table1'); - $field = new xmldb_field('course'); + $table = new xmldb_table('test_table_cust0'); + $table->add_field('id', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); + $table->add_field('onenumber', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); + $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); + $dbmanager->create_table($table, true, false); + + $record = new object(); + $recorf->course = 2; + $DB->insert_record('test_table_cust0', $record); + + $field = new xmldb_field('onenumber'); $field->set_attributes(XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, null, null, '0'); $this->assertTrue($dbmanager->change_field_type($table, $field)); - $field = new xmldb_field('course'); + $columns = $DB->get_columns('test_table_cust0'); + $this->assertEqual($columns['onenumber']->meta_type, 'C'); + + $field = new xmldb_field('onenumber'); $field->set_attributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $this->assertTrue($dbmanager->change_field_type($table, $field)); - $field = new xmldb_field('grade'); + $columns = $DB->get_columns('test_table_cust0'); + $this->assertEqual($columns['onenumber']->meta_type, 'I'); + + $field = new xmldb_field('onenumber'); $field->set_attributes(XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, null, null, "test'n drop"); $this->assertTrue($dbmanager->change_field_type($table, $field)); - $field = new xmldb_field('grade'); + $columns = $DB->get_columns('test_table_cust0'); + $this->assertEqual($columns['onenumber']->meta_type, 'C'); + + $field = new xmldb_field('onenumber'); $field->set_attributes(XMLDB_TYPE_FLOAT, '20,10', XMLDB_UNSIGNED, null, null, null, null, null); $this->assertTrue($dbmanager->change_field_type($table, $field)); - $field = new xmldb_field('grade'); + $columns = $DB->get_columns('test_table_cust0'); + $this->assertEqual($columns['onenumber']->meta_type, 'N'); + + $field = new xmldb_field('onenumber'); $field->set_attributes(XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, null, null, 'test'); $this->assertTrue($dbmanager->change_field_type($table, $field)); - $field = new xmldb_field('grade'); + $columns = $DB->get_columns('test_table_cust0'); + $this->assertEqual($columns['onenumber']->meta_type, 'C'); + + $field = new xmldb_field('onenumber'); $field->set_attributes(XMLDB_TYPE_NUMBER, '20,10', XMLDB_UNSIGNED, null, null, null, null, null); $this->assertTrue($dbmanager->change_field_type($table, $field)); + + $columns = $DB->get_columns('test_table_cust0'); + $this->assertEqual($columns['onenumber']->meta_type, 'N'); } public function testChangeFieldPrecision() { @@ -431,29 +524,6 @@ class ddllib_test extends UnitTestCase { array('single', 'news', 'general', 'social', 'eachuser', 'teacher', 'qanda'), 'general', 'course'); $this->assertTrue($dbmanager->change_field_enum($table, $field)); } -/* - public function testRenameIndex() { - // unsupported! - $dbmanager = $this->db->get_manager(); - - $table = $this->create_deftable('test_table0'); - $index = new xmldb_index('course'); - $index->set_attributes(XMLDB_INDEX_UNIQUE, array('course')); - - $this->assertTrue($dbmanager->rename_index($table, $index, 'newindexname')); - } - - public function testRenameKey() { - //unsupported - $dbmanager = $this->db->get_manager(); - - $table = $this->create_deftable('test_table0'); - $key = new xmldb_key('course'); - $key->set_attributes(XMLDB_KEY_UNIQUE, array('course')); - - $this->assertTrue($dbmanager->rename_key($table, $key, 'newkeyname')); - } -*/ public function testRenameField() { $dbmanager = $this->db->get_manager(); @@ -639,5 +709,31 @@ class ddllib_test extends UnitTestCase { $this->assertFalse($dbmanager->table_exists('test_table1', true)); } + + // Following methods are not supported == Do not test +/* + public function testRenameIndex() { + // unsupported! + $dbmanager = $this->db->get_manager(); + + $table = $this->create_deftable('test_table0'); + $index = new xmldb_index('course'); + $index->set_attributes(XMLDB_INDEX_UNIQUE, array('course')); + + $this->assertTrue($dbmanager->rename_index($table, $index, 'newindexname')); + } + + public function testRenameKey() { + //unsupported + $dbmanager = $this->db->get_manager(); + + $table = $this->create_deftable('test_table0'); + $key = new xmldb_key('course'); + $key->set_attributes(XMLDB_KEY_UNIQUE, array('course')); + + $this->assertTrue($dbmanager->rename_key($table, $key, 'newkeyname')); + } +*/ + } ?> diff --git a/lib/dml/adodb_moodle_database.php b/lib/dml/adodb_moodle_database.php index 3ab3a0d900..406c2aba9d 100644 --- a/lib/dml/adodb_moodle_database.php +++ b/lib/dml/adodb_moodle_database.php @@ -154,6 +154,14 @@ abstract class adodb_moodle_database extends moodle_database { foreach ($columns as $column) { // colum names must be lowercase $column->meta_type = substr($this->db->MetaType($column), 0 ,1); // only 1 character + if (!empty($column->enums)) { + // hack: fix the 'quotes' surrounding the values itroduced by adodb + foreach ($column->enums as $key=>$value) { + if (strpos($value, "'") === 0 and strlen($value) > 2) { + $column->enums[$key] = substr($value, 1, strlen($value)-2); + } + } + } $this->columns[$table][$column->name] = new database_column_info($column); } diff --git a/lib/dml/database_column_info.php b/lib/dml/database_column_info.php index 452dad03ca..6bc7b53af2 100644 --- a/lib/dml/database_column_info.php +++ b/lib/dml/database_column_info.php @@ -36,8 +36,11 @@ class database_column_info { public $scale; /** - * Enumerated filed options, + * Enumerated field options, * null if not enum type + * + * For performance reasons this field is optional! + * You can use DDL sql_generator::getCheckConstraintsFromDB() if needed. */ public $enums; diff --git a/lib/dml/moodle_database.php b/lib/dml/moodle_database.php index 7593d5ffb3..93e5cd88aa 100644 --- a/lib/dml/moodle_database.php +++ b/lib/dml/moodle_database.php @@ -369,7 +369,7 @@ abstract class moodle_database { * @return void */ public function reset_columns() { - $this->columns[] = array(); + $this->columns = array(); } /** diff --git a/lib/dml/mysqli_adodb_moodle_database.php b/lib/dml/mysqli_adodb_moodle_database.php index 176a109776..80021cc609 100644 --- a/lib/dml/mysqli_adodb_moodle_database.php +++ b/lib/dml/mysqli_adodb_moodle_database.php @@ -150,9 +150,21 @@ class mysqli_adodb_moodle_database extends adodb_moodle_database { if (!isset($columns[$field])) { continue; } + $column = $columns[$field]; if (is_bool($value)) { $value = (int)$value; // prevent "false" problems } + if (!empty($column->enums)) { + // workaround for problem with wrong enums in mysql + if (is_null($value) and !$column->not_null) { + // ok - nulls allowed + } else { + if (!in_array((string)$value, $column->enums)) { + debugging('Enum value '.s($value).' not allowed in field '.$field.' table '.$table.'.'); + return false; + } + } + } $cleaned[$field] = $value; }