PageRenderTime 60ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/Doctrine/Tests/DBAL/Functional/Schema/SchemaManagerFunctionalTestCase.php

https://github.com/mridgway/dbal
PHP | 486 lines | 477 code | 6 blank | 3 comment | 1 complexity | 4297db41a67fccfc183859432a88743c MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. namespace Doctrine\Tests\DBAL\Functional\Schema;
  3. use Doctrine\DBAL\Types\Type,
  4. Doctrine\DBAL\Schema\AbstractSchemaManager;
  5. require_once __DIR__ . '/../../../TestInit.php';
  6. class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTestCase
  7. {
  8. /**
  9. * @var \Doctrine\DBAL\Schema\AbstractSchemaManager
  10. */
  11. protected $_sm;
  12. protected function setUp()
  13. {
  14. parent::setUp();
  15. $class = get_class($this);
  16. $e = explode('\\', $class);
  17. $testClass = end($e);
  18. $dbms = strtolower(str_replace('SchemaManagerTest', null, $testClass));
  19. if ($this->_conn->getDatabasePlatform()->getName() !== $dbms) {
  20. $this->markTestSkipped('The ' . $testClass .' requires the use of ' . $dbms);
  21. }
  22. $this->_sm = $this->_conn->getSchemaManager();
  23. }
  24. public function testListSequences()
  25. {
  26. if(!$this->_conn->getDatabasePlatform()->supportsSequences()) {
  27. $this->markTestSkipped($this->_conn->getDriver()->getName().' does not support sequences.');
  28. }
  29. $sequence = new \Doctrine\DBAL\Schema\Sequence('list_sequences_test_seq', 20, 10);
  30. $this->_sm->createSequence($sequence);
  31. $sequences = $this->_sm->listSequences();
  32. $this->assertInternalType('array', $sequences, 'listSequences() should return an array.');
  33. $foundSequence = null;
  34. foreach($sequences AS $sequence) {
  35. $this->assertInstanceOf('Doctrine\DBAL\Schema\Sequence', $sequence, 'Array elements of listSequences() should be Sequence instances.');
  36. if(strtolower($sequence->getName()) == 'list_sequences_test_seq') {
  37. $foundSequence = $sequence;
  38. }
  39. }
  40. $this->assertNotNull($foundSequence, "Sequence with name 'list_sequences_test_seq' was not found.");
  41. $this->assertEquals(20, $foundSequence->getAllocationSize(), "Allocation Size is expected to be 20.");
  42. $this->assertEquals(10, $foundSequence->getInitialValue(), "Initial Value is expected to be 10.");
  43. }
  44. public function testListDatabases()
  45. {
  46. if (!$this->_sm->getDatabasePlatform()->supportsCreateDropDatabase()) {
  47. $this->markTestSkipped('Cannot drop Database client side with this Driver.');
  48. }
  49. $this->_sm->dropAndCreateDatabase('test_create_database');
  50. $databases = $this->_sm->listDatabases();
  51. $databases = \array_map('strtolower', $databases);
  52. $this->assertEquals(true, \in_array('test_create_database', $databases));
  53. }
  54. public function testListTables()
  55. {
  56. $this->createTestTable('list_tables_test');
  57. $tables = $this->_sm->listTables();
  58. $this->assertInternalType('array', $tables);
  59. $this->assertTrue(count($tables) > 0, "List Tables has to find at least one table named 'list_tables_test'.");
  60. $foundTable = false;
  61. foreach ($tables AS $table) {
  62. $this->assertInstanceOf('Doctrine\DBAL\Schema\Table', $table);
  63. if (strtolower($table->getName()) == 'list_tables_test') {
  64. $foundTable = true;
  65. $this->assertTrue($table->hasColumn('id'));
  66. $this->assertTrue($table->hasColumn('test'));
  67. $this->assertTrue($table->hasColumn('foreign_key_test'));
  68. }
  69. }
  70. $this->assertTrue( $foundTable , "The 'list_tables_test' table has to be found.");
  71. }
  72. public function createListTableColumns()
  73. {
  74. $table = new \Doctrine\DBAL\Schema\Table('list_table_columns');
  75. $table->addColumn('id', 'integer', array('notnull' => true));
  76. $table->addColumn('test', 'string', array('length' => 255, 'notnull' => false));
  77. $table->addColumn('foo', 'text', array('notnull' => true));
  78. $table->addColumn('bar', 'decimal', array('precision' => 10, 'scale' => 4, 'notnull' => false));
  79. $table->addColumn('baz1', 'datetime');
  80. $table->addColumn('baz2', 'time');
  81. $table->addColumn('baz3', 'date');
  82. return $table;
  83. }
  84. public function testListTableColumns()
  85. {
  86. $table = $this->createListTableColumns();
  87. $this->_sm->dropAndCreateTable($table);
  88. $columns = $this->_sm->listTableColumns('list_table_columns');
  89. $this->assertArrayHasKey('id', $columns);
  90. $this->assertEquals('id', strtolower($columns['id']->getname()));
  91. $this->assertInstanceOf('Doctrine\DBAL\Types\IntegerType', $columns['id']->gettype());
  92. $this->assertEquals(false, $columns['id']->getunsigned());
  93. $this->assertEquals(true, $columns['id']->getnotnull());
  94. $this->assertEquals(null, $columns['id']->getdefault());
  95. $this->assertInternalType('array', $columns['id']->getPlatformOptions());
  96. $this->assertArrayHasKey('test', $columns);
  97. $this->assertEquals('test', strtolower($columns['test']->getname()));
  98. $this->assertInstanceOf('Doctrine\DBAL\Types\StringType', $columns['test']->gettype());
  99. $this->assertEquals(255, $columns['test']->getlength());
  100. $this->assertEquals(false, $columns['test']->getfixed());
  101. $this->assertEquals(false, $columns['test']->getnotnull());
  102. $this->assertEquals(null, $columns['test']->getdefault());
  103. $this->assertInternalType('array', $columns['test']->getPlatformOptions());
  104. $this->assertEquals('foo', strtolower($columns['foo']->getname()));
  105. $this->assertInstanceOf('Doctrine\DBAL\Types\TextType', $columns['foo']->gettype());
  106. $this->assertEquals(false, $columns['foo']->getunsigned());
  107. $this->assertEquals(false, $columns['foo']->getfixed());
  108. $this->assertEquals(true, $columns['foo']->getnotnull());
  109. $this->assertEquals(null, $columns['foo']->getdefault());
  110. $this->assertInternalType('array', $columns['foo']->getPlatformOptions());
  111. $this->assertEquals('bar', strtolower($columns['bar']->getname()));
  112. $this->assertInstanceOf('Doctrine\DBAL\Types\DecimalType', $columns['bar']->gettype());
  113. $this->assertEquals(null, $columns['bar']->getlength());
  114. $this->assertEquals(10, $columns['bar']->getprecision());
  115. $this->assertEquals(4, $columns['bar']->getscale());
  116. $this->assertEquals(false, $columns['bar']->getunsigned());
  117. $this->assertEquals(false, $columns['bar']->getfixed());
  118. $this->assertEquals(false, $columns['bar']->getnotnull());
  119. $this->assertEquals(null, $columns['bar']->getdefault());
  120. $this->assertInternalType('array', $columns['bar']->getPlatformOptions());
  121. $this->assertEquals('baz1', strtolower($columns['baz1']->getname()));
  122. $this->assertInstanceOf('Doctrine\DBAL\Types\DateTimeType', $columns['baz1']->gettype());
  123. $this->assertEquals(true, $columns['baz1']->getnotnull());
  124. $this->assertEquals(null, $columns['baz1']->getdefault());
  125. $this->assertInternalType('array', $columns['baz1']->getPlatformOptions());
  126. $this->assertEquals('baz2', strtolower($columns['baz2']->getname()));
  127. $this->assertContains($columns['baz2']->gettype()->getName(), array('time', 'date', 'datetime'));
  128. $this->assertEquals(true, $columns['baz2']->getnotnull());
  129. $this->assertEquals(null, $columns['baz2']->getdefault());
  130. $this->assertInternalType('array', $columns['baz2']->getPlatformOptions());
  131. $this->assertEquals('baz3', strtolower($columns['baz3']->getname()));
  132. $this->assertContains($columns['baz2']->gettype()->getName(), array('time', 'date', 'datetime'));
  133. $this->assertEquals(true, $columns['baz3']->getnotnull());
  134. $this->assertEquals(null, $columns['baz3']->getdefault());
  135. $this->assertInternalType('array', $columns['baz3']->getPlatformOptions());
  136. }
  137. public function testDiffListTableColumns()
  138. {
  139. if ($this->_sm->getDatabasePlatform()->getName() == 'oracle') {
  140. $this->markTestSkipped('Does not work with Oracle, since it cannot detect DateTime, Date and Time differenecs (at the moment).');
  141. }
  142. $offlineTable = $this->createListTableColumns();
  143. $onlineTable = $this->_sm->listTableDetails('list_table_columns');
  144. $comparator = new \Doctrine\DBAL\Schema\Comparator();
  145. $diff = $comparator->diffTable($offlineTable, $onlineTable);
  146. $this->assertFalse($diff, "No differences should be detected with the offline vs online schema.");
  147. }
  148. public function testListTableIndexes()
  149. {
  150. $table = $this->getTestTable('list_table_indexes_test');
  151. $table->addUniqueIndex(array('test'), 'test_index_name');
  152. $table->addIndex(array('id', 'test'), 'test_composite_idx');
  153. $this->_sm->createTable($table);
  154. $tableIndexes = $this->_sm->listTableIndexes('list_table_indexes_test');
  155. $this->assertEquals(3, count($tableIndexes));
  156. $this->assertArrayHasKey('primary', $tableIndexes, 'listTableIndexes() has to return a "primary" array key.');
  157. $this->assertEquals(array('id'), array_map('strtolower', $tableIndexes['primary']->getColumns()));
  158. $this->assertTrue($tableIndexes['primary']->isUnique());
  159. $this->assertTrue($tableIndexes['primary']->isPrimary());
  160. $this->assertEquals('test_index_name', $tableIndexes['test_index_name']->getName());
  161. $this->assertEquals(array('test'), array_map('strtolower', $tableIndexes['test_index_name']->getColumns()));
  162. $this->assertTrue($tableIndexes['test_index_name']->isUnique());
  163. $this->assertFalse($tableIndexes['test_index_name']->isPrimary());
  164. $this->assertEquals('test_composite_idx', $tableIndexes['test_composite_idx']->getName());
  165. $this->assertEquals(array('id', 'test'), array_map('strtolower', $tableIndexes['test_composite_idx']->getColumns()));
  166. $this->assertFalse($tableIndexes['test_composite_idx']->isUnique());
  167. $this->assertFalse($tableIndexes['test_composite_idx']->isPrimary());
  168. }
  169. public function testDropAndCreateIndex()
  170. {
  171. $table = $this->getTestTable('test_create_index');
  172. $table->addUniqueIndex(array('test'), 'test');
  173. $this->_sm->dropAndCreateTable($table);
  174. $this->_sm->dropAndCreateIndex($table->getIndex('test'), $table);
  175. $tableIndexes = $this->_sm->listTableIndexes('test_create_index');
  176. $this->assertInternalType('array', $tableIndexes);
  177. $this->assertEquals('test', strtolower($tableIndexes['test']->getName()));
  178. $this->assertEquals(array('test'), array_map('strtolower', $tableIndexes['test']->getColumns()));
  179. $this->assertTrue($tableIndexes['test']->isUnique());
  180. $this->assertFalse($tableIndexes['test']->isPrimary());
  181. }
  182. public function testCreateTableWithForeignKeys()
  183. {
  184. if(!$this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) {
  185. $this->markTestSkipped('Platform does not support foreign keys.');
  186. }
  187. $tableB = $this->getTestTable('test_foreign');
  188. $this->_sm->dropAndCreateTable($tableB);
  189. $tableA = $this->getTestTable('test_create_fk');
  190. $tableA->addForeignKeyConstraint('test_foreign', array('foreign_key_test'), array('id'));
  191. $this->_sm->dropAndCreateTable($tableA);
  192. $fkTable = $this->_sm->listTableDetails('test_create_fk');
  193. $fkConstraints = $fkTable->getForeignKeys();
  194. $this->assertEquals(1, count($fkConstraints), "Table 'test_create_fk1' has to have one foreign key.");
  195. $fkConstraint = current($fkConstraints);
  196. $this->assertType('\Doctrine\DBAL\Schema\ForeignKeyConstraint', $fkConstraint);
  197. $this->assertEquals('test_foreign', strtolower($fkConstraint->getForeignTableName()));
  198. $this->assertEquals(array('foreign_key_test'), array_map('strtolower', $fkConstraint->getColumns()));
  199. $this->assertEquals(array('id'), array_map('strtolower', $fkConstraint->getForeignColumns()));
  200. $this->assertTrue($fkTable->columnsAreIndexed($fkConstraint->getColumns()), "The columns of a foreign key constraint should always be indexed.");
  201. }
  202. public function testListForeignKeys()
  203. {
  204. if(!$this->_conn->getDatabasePlatform()->supportsForeignKeyConstraints()) {
  205. $this->markTestSkipped('Does not support foreign key constraints.');
  206. }
  207. $this->createTestTable('test_create_fk1');
  208. $this->createTestTable('test_create_fk2');
  209. $foreignKey = new \Doctrine\DBAL\Schema\ForeignKeyConstraint(
  210. array('foreign_key_test'), 'test_create_fk2', array('id'), 'foreign_key_test_fk', array('onDelete' => 'CASCADE')
  211. );
  212. $this->_sm->createForeignKey($foreignKey, 'test_create_fk1');
  213. $fkeys = $this->_sm->listTableForeignKeys('test_create_fk1');
  214. $this->assertEquals(1, count($fkeys), "Table 'test_create_fk1' has to have one foreign key.");
  215. $this->assertInstanceOf('Doctrine\DBAL\Schema\ForeignKeyConstraint', $fkeys[0]);
  216. $this->assertEquals(array('foreign_key_test'), array_map('strtolower', $fkeys[0]->getLocalColumns()));
  217. $this->assertEquals(array('id'), array_map('strtolower', $fkeys[0]->getForeignColumns()));
  218. $this->assertEquals('test_create_fk2', strtolower($fkeys[0]->getForeignTableName()));
  219. if($fkeys[0]->hasOption('onDelete')) {
  220. $this->assertEquals('CASCADE', $fkeys[0]->getOption('onDelete'));
  221. }
  222. }
  223. protected function getCreateExampleViewSql()
  224. {
  225. $this->markTestSkipped('No Create Example View SQL was defined for this SchemaManager');
  226. }
  227. public function testCreateSchema()
  228. {
  229. $this->createTestTable('test_table');
  230. $schema = $this->_sm->createSchema();
  231. $this->assertTrue($schema->hasTable('test_table'));
  232. }
  233. public function testAlterTableScenario()
  234. {
  235. if(!$this->_sm->getDatabasePlatform()->supportsAlterTable()) {
  236. $this->markTestSkipped('Alter Table is not supported by this platform.');
  237. }
  238. $this->createTestTable('alter_table');
  239. $this->createTestTable('alter_table_foreign');
  240. $table = $this->_sm->listTableDetails('alter_table');
  241. $this->assertTrue($table->hasColumn('id'));
  242. $this->assertTrue($table->hasColumn('test'));
  243. $this->assertTrue($table->hasColumn('foreign_key_test'));
  244. $this->assertEquals(0, count($table->getForeignKeys()));
  245. $this->assertEquals(1, count($table->getIndexes()));
  246. $tableDiff = new \Doctrine\DBAL\Schema\TableDiff("alter_table");
  247. $tableDiff->addedColumns['foo'] = new \Doctrine\DBAL\Schema\Column('foo', Type::getType('integer'));
  248. $tableDiff->removedColumns['test'] = $table->getColumn('test');
  249. $this->_sm->alterTable($tableDiff);
  250. $table = $this->_sm->listTableDetails('alter_table');
  251. $this->assertFalse($table->hasColumn('test'));
  252. $this->assertTrue($table->hasColumn('foo'));
  253. $tableDiff = new \Doctrine\DBAL\Schema\TableDiff("alter_table");
  254. $tableDiff->addedIndexes[] = new \Doctrine\DBAL\Schema\Index('foo_idx', array('foo'));
  255. $this->_sm->alterTable($tableDiff);
  256. $table = $this->_sm->listTableDetails('alter_table');
  257. $this->assertEquals(2, count($table->getIndexes()));
  258. $this->assertTrue($table->hasIndex('foo_idx'));
  259. $this->assertEquals(array('foo'), array_map('strtolower', $table->getIndex('foo_idx')->getColumns()));
  260. $this->assertFalse($table->getIndex('foo_idx')->isPrimary());
  261. $this->assertFalse($table->getIndex('foo_idx')->isUnique());
  262. $tableDiff = new \Doctrine\DBAL\Schema\TableDiff("alter_table");
  263. $tableDiff->changedIndexes[] = new \Doctrine\DBAL\Schema\Index('foo_idx', array('foo', 'foreign_key_test'));
  264. $this->_sm->alterTable($tableDiff);
  265. $table = $this->_sm->listTableDetails('alter_table');
  266. $this->assertEquals(2, count($table->getIndexes()));
  267. $this->assertTrue($table->hasIndex('foo_idx'));
  268. $this->assertEquals(array('foo', 'foreign_key_test'), array_map('strtolower', $table->getIndex('foo_idx')->getColumns()));
  269. $tableDiff = new \Doctrine\DBAL\Schema\TableDiff("alter_table");
  270. $tableDiff->removedIndexes[] = new \Doctrine\DBAL\Schema\Index('foo_idx', array('foo', 'foreign_key_test'));
  271. $fk = new \Doctrine\DBAL\Schema\ForeignKeyConstraint(array('foreign_key_test'), 'alter_table_foreign', array('id'));
  272. $tableDiff->addedForeignKeys[] = $fk;
  273. $this->_sm->alterTable($tableDiff);
  274. $table = $this->_sm->listTableDetails('alter_table');
  275. // dont check for index size here, some platforms automatically add indexes for foreign keys.
  276. $this->assertFalse($table->hasIndex('foo_idx'));
  277. $this->assertEquals(1, count($table->getForeignKeys()));
  278. $fks = $table->getForeignKeys();
  279. $foreignKey = current($fks);
  280. $this->assertEquals('alter_table_foreign', strtolower($foreignKey->getForeignTableName()));
  281. $this->assertEquals(array('foreign_key_test'), array_map('strtolower', $foreignKey->getColumns()));
  282. $this->assertEquals(array('id'), array_map('strtolower', $foreignKey->getForeignColumns()));
  283. }
  284. public function testCreateAndListViews()
  285. {
  286. $this->createTestTable('view_test_table');
  287. $name = "doctrine_test_view";
  288. $sql = "SELECT * FROM view_test_table";
  289. $view = new \Doctrine\DBAL\Schema\View($name, $sql);
  290. $this->_sm->dropAndCreateView($view);
  291. $views = $this->_sm->listViews();
  292. }
  293. public function testAutoincrementDetection()
  294. {
  295. if (!$this->_sm->getDatabasePlatform()->supportsIdentityColumns()) {
  296. $this->markTestSkipped('This test is only supported on platforms that have autoincrement');
  297. }
  298. $table = new \Doctrine\DBAL\Schema\Table('test_autoincrement');
  299. $table->setSchemaConfig($this->_sm->createSchemaConfig());
  300. $table->addColumn('id', 'integer', array('autoincrement' => true));
  301. $table->setPrimaryKey(array('id'));
  302. $this->_sm->createTable($table);
  303. $inferredTable = $this->_sm->listTableDetails('test_autoincrement');
  304. $this->assertTrue($inferredTable->hasColumn('id'));
  305. $this->assertTrue($inferredTable->getColumn('id')->getAutoincrement());
  306. }
  307. /**
  308. * @group DBAL-42
  309. */
  310. public function testGetColumnComment()
  311. {
  312. if (!$this->_conn->getDatabasePlatform()->supportsInlineColumnComments() && !$this->_conn->getDatabasePlatform()->supportsCommentOnStatement()) {
  313. $this->markTestSkipped('Database does not support column comments.');
  314. }
  315. $table = new \Doctrine\DBAL\Schema\Table('column_comment_test');
  316. $table->addColumn('id', 'integer', array('comment' => 'This is a comment'));
  317. $table->setPrimaryKey(array('id'));
  318. $this->_sm->createTable($table);
  319. $columns = $this->_sm->listTableColumns("column_comment_test");
  320. $this->assertEquals(1, count($columns));
  321. $this->assertEquals('This is a comment', $columns['id']->getComment());
  322. }
  323. /**
  324. * @group DBAL-42
  325. */
  326. public function testAutomaticallyAppendCommentOnMarkedColumns()
  327. {
  328. if (!$this->_conn->getDatabasePlatform()->supportsInlineColumnComments() && !$this->_conn->getDatabasePlatform()->supportsCommentOnStatement()) {
  329. $this->markTestSkipped('Database does not support column comments.');
  330. }
  331. $table = new \Doctrine\DBAL\Schema\Table('column_comment_test2');
  332. $table->addColumn('id', 'integer', array('comment' => 'This is a comment'));
  333. $table->addColumn('obj', 'object', array('comment' => 'This is a comment'));
  334. $table->addColumn('arr', 'array', array('comment' => 'This is a comment'));
  335. $table->setPrimaryKey(array('id'));
  336. $this->_sm->createTable($table);
  337. $columns = $this->_sm->listTableColumns("column_comment_test2");
  338. $this->assertEquals(3, count($columns));
  339. $this->assertEquals('This is a comment', $columns['id']->getComment());
  340. $this->assertEquals('This is a comment', $columns['obj']->getComment(), "The Doctrine2 Typehint should be stripped from comment.");
  341. $this->assertInstanceOf('Doctrine\DBAL\Types\ObjectType', $columns['obj']->getType(), "The Doctrine2 should be detected from comment hint.");
  342. $this->assertEquals('This is a comment', $columns['arr']->getComment(), "The Doctrine2 Typehint should be stripped from comment.");
  343. $this->assertInstanceOf('Doctrine\DBAL\Types\ArrayType', $columns['arr']->getType(), "The Doctrine2 should be detected from comment hint.");
  344. }
  345. /**
  346. * @param string $name
  347. * @param array $data
  348. */
  349. protected function createTestTable($name = 'test_table', $data = array())
  350. {
  351. $options = array();
  352. if (isset($data['options'])) {
  353. $options = $data['options'];
  354. }
  355. $table = $this->getTestTable($name, $options);
  356. $this->_sm->dropAndCreateTable($table);
  357. }
  358. protected function getTestTable($name, $options=array())
  359. {
  360. $table = new \Doctrine\DBAL\Schema\Table($name, array(), array(), array(), false, $options);
  361. $table->setSchemaConfig($this->_sm->createSchemaConfig());
  362. $table->addColumn('id', 'integer', array('notnull' => true));
  363. $table->setPrimaryKey(array('id'));
  364. $table->addColumn('test', 'string', array('length' => 255));
  365. $table->addColumn('foreign_key_test', 'integer');
  366. return $table;
  367. }
  368. protected function assertHasTable($tables, $tableName)
  369. {
  370. $foundTable = false;
  371. foreach ($tables AS $table) {
  372. $this->assertInstanceOf('Doctrine\DBAL\Schema\Table', $table, 'No Table instance was found in tables array.');
  373. if (strtolower($table->getName()) == 'list_tables_test_new_name') {
  374. $foundTable = true;
  375. }
  376. }
  377. $this->assertTrue($foundTable, "Could not find new table");
  378. }
  379. }