CakeSchemaTest.php 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107
  1. <?php
  2. /**
  3. * Test for Schema database management
  4. *
  5. *
  6. * PHP 5
  7. *
  8. * CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
  9. * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
  10. *
  11. * Licensed under The MIT License
  12. * Redistributions of files must retain the above copyright notice
  13. *
  14. * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
  15. * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
  16. * @package Cake.Test.Case.Model
  17. * @since CakePHP(tm) v 1.2.0.5550
  18. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  19. */
  20. App::uses('CakeSchema', 'Model');
  21. App::uses('CakeTestFixture', 'TestSuite/Fixture');
  22. /**
  23. * Test for Schema database management
  24. *
  25. * @package Cake.Test.Case.Model
  26. */
  27. class MyAppSchema extends CakeSchema {
  28. /**
  29. * name property
  30. *
  31. * @var string 'MyApp'
  32. */
  33. public $name = 'MyApp';
  34. /**
  35. * connection property
  36. *
  37. * @var string 'test'
  38. */
  39. public $connection = 'test';
  40. /**
  41. * comments property
  42. *
  43. * @var array
  44. */
  45. public $comments = array(
  46. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  47. 'post_id' => array('type' => 'integer', 'null' => false, 'default' => 0),
  48. 'user_id' => array('type' => 'integer', 'null' => false),
  49. 'title' => array('type' => 'string', 'null' => false, 'length' => 100),
  50. 'comment' => array('type' => 'text', 'null' => false, 'default' => null),
  51. 'published' => array('type' => 'string', 'null' => true, 'default' => 'N', 'length' => 1),
  52. 'created' => array('type' => 'datetime', 'null' => true, 'default' => null),
  53. 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null),
  54. 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)),
  55. );
  56. /**
  57. * posts property
  58. *
  59. * @var array
  60. */
  61. public $posts = array(
  62. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  63. 'author_id' => array('type' => 'integer', 'null' => true, 'default' => ''),
  64. 'title' => array('type' => 'string', 'null' => false, 'default' => 'Title'),
  65. 'body' => array('type' => 'text', 'null' => true, 'default' => null),
  66. 'summary' => array('type' => 'text', 'null' => true),
  67. 'published' => array('type' => 'string', 'null' => true, 'default' => 'Y', 'length' => 1),
  68. 'created' => array('type' => 'datetime', 'null' => true, 'default' => null),
  69. 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null),
  70. 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)),
  71. );
  72. /**
  73. * _foo property
  74. *
  75. * @var array
  76. */
  77. protected $_foo = array('bar');
  78. /**
  79. * setup method
  80. *
  81. * @param mixed $version
  82. * @return void
  83. */
  84. public function setup($version) {
  85. }
  86. /**
  87. * teardown method
  88. *
  89. * @param mixed $version
  90. * @return void
  91. */
  92. public function teardown($version) {
  93. }
  94. /**
  95. * getVar method
  96. *
  97. * @param string $var Name of var
  98. * @return mixed
  99. */
  100. public function getVar($var) {
  101. if (!isset($this->$var)) {
  102. return null;
  103. }
  104. return $this->$var;
  105. }
  106. }
  107. /**
  108. * TestAppSchema class
  109. *
  110. * @package Cake.Test.Case.Model
  111. */
  112. class TestAppSchema extends CakeSchema {
  113. /**
  114. * name property
  115. *
  116. * @var string 'MyApp'
  117. */
  118. public $name = 'MyApp';
  119. /**
  120. * comments property
  121. *
  122. * @var array
  123. */
  124. public $comments = array(
  125. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0,'key' => 'primary'),
  126. 'article_id' => array('type' => 'integer', 'null' => false),
  127. 'user_id' => array('type' => 'integer', 'null' => false),
  128. 'comment' => array('type' => 'text', 'null' => true, 'default' => null),
  129. 'published' => array('type' => 'string', 'null' => true, 'default' => 'N', 'length' => 1),
  130. 'created' => array('type' => 'datetime', 'null' => true, 'default' => null),
  131. 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null),
  132. 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)),
  133. 'tableParameters' => array(),
  134. );
  135. /**
  136. * posts property
  137. *
  138. * @var array
  139. */
  140. public $posts = array(
  141. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  142. 'author_id' => array('type' => 'integer', 'null' => false),
  143. 'title' => array('type' => 'string', 'null' => false),
  144. 'body' => array('type' => 'text', 'null' => true, 'default' => null),
  145. 'published' => array('type' => 'string', 'null' => true, 'default' => 'N', 'length' => 1),
  146. 'created' => array('type' => 'datetime', 'null' => true, 'default' => null),
  147. 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null),
  148. 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)),
  149. 'tableParameters' => array(),
  150. );
  151. /**
  152. * posts_tags property
  153. *
  154. * @var array
  155. */
  156. public $posts_tags = array(
  157. 'post_id' => array('type' => 'integer', 'null' => false, 'key' => 'primary'),
  158. 'tag_id' => array('type' => 'string', 'null' => false, 'key' => 'primary'),
  159. 'indexes' => array('posts_tag' => array('column' => array('tag_id', 'post_id'), 'unique' => 1)),
  160. 'tableParameters' => array()
  161. );
  162. /**
  163. * tags property
  164. *
  165. * @var array
  166. */
  167. public $tags = array(
  168. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  169. 'tag' => array('type' => 'string', 'null' => false),
  170. 'created' => array('type' => 'datetime', 'null' => true, 'default' => null),
  171. 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null),
  172. 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)),
  173. 'tableParameters' => array()
  174. );
  175. /**
  176. * datatypes property
  177. *
  178. * @var array
  179. */
  180. public $datatypes = array(
  181. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  182. 'float_field' => array('type' => 'float', 'null' => false, 'length' => '5,2', 'default' => ''),
  183. 'huge_int' => array('type' => 'biginteger'),
  184. 'bool' => array('type' => 'boolean', 'null' => false, 'default' => false),
  185. 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)),
  186. 'tableParameters' => array()
  187. );
  188. /**
  189. * setup method
  190. *
  191. * @param mixed $version
  192. * @return void
  193. */
  194. public function setup($version) {
  195. }
  196. /**
  197. * teardown method
  198. *
  199. * @param mixed $version
  200. * @return void
  201. */
  202. public function teardown($version) {
  203. }
  204. }
  205. /**
  206. * SchemaPost class
  207. *
  208. * @package Cake.Test.Case.Model
  209. */
  210. class SchemaPost extends CakeTestModel {
  211. /**
  212. * name property
  213. *
  214. * @var string 'SchemaPost'
  215. */
  216. public $name = 'SchemaPost';
  217. /**
  218. * useTable property
  219. *
  220. * @var string 'posts'
  221. */
  222. public $useTable = 'posts';
  223. /**
  224. * hasMany property
  225. *
  226. * @var array
  227. */
  228. public $hasMany = array('SchemaComment');
  229. /**
  230. * hasAndBelongsToMany property
  231. *
  232. * @var array
  233. */
  234. public $hasAndBelongsToMany = array('SchemaTag');
  235. }
  236. /**
  237. * SchemaComment class
  238. *
  239. * @package Cake.Test.Case.Model
  240. */
  241. class SchemaComment extends CakeTestModel {
  242. /**
  243. * name property
  244. *
  245. * @var string 'SchemaComment'
  246. */
  247. public $name = 'SchemaComment';
  248. /**
  249. * useTable property
  250. *
  251. * @var string 'comments'
  252. */
  253. public $useTable = 'comments';
  254. /**
  255. * belongsTo property
  256. *
  257. * @var array
  258. */
  259. public $belongsTo = array('SchemaPost');
  260. }
  261. /**
  262. * SchemaTag class
  263. *
  264. * @package Cake.Test.Case.Model
  265. */
  266. class SchemaTag extends CakeTestModel {
  267. /**
  268. * name property
  269. *
  270. * @var string 'SchemaTag'
  271. */
  272. public $name = 'SchemaTag';
  273. /**
  274. * useTable property
  275. *
  276. * @var string 'tags'
  277. */
  278. public $useTable = 'tags';
  279. /**
  280. * hasAndBelongsToMany property
  281. *
  282. * @var array
  283. */
  284. public $hasAndBelongsToMany = array('SchemaPost');
  285. }
  286. /**
  287. * SchemaDatatype class
  288. *
  289. * @package Cake.Test.Case.Model
  290. */
  291. class SchemaDatatype extends CakeTestModel {
  292. /**
  293. * name property
  294. *
  295. * @var string 'SchemaDatatype'
  296. */
  297. public $name = 'SchemaDatatype';
  298. /**
  299. * useTable property
  300. *
  301. * @var string 'datatypes'
  302. */
  303. public $useTable = 'datatypes';
  304. }
  305. /**
  306. * Testdescribe class
  307. *
  308. * This class is defined purely to inherit the cacheSources variable otherwise
  309. * testSchemaCreateTable will fail if listSources has already been called and
  310. * its source cache populated - I.e. if the test is run within a group
  311. *
  312. * @uses CakeTestModel
  313. * @package
  314. * @package Cake.Test.Case.Model
  315. */
  316. class Testdescribe extends CakeTestModel {
  317. /**
  318. * name property
  319. *
  320. * @var string 'Testdescribe'
  321. */
  322. public $name = 'Testdescribe';
  323. }
  324. /**
  325. * SchemaCrossDatabase class
  326. *
  327. * @package Cake.Test.Case.Model
  328. */
  329. class SchemaCrossDatabase extends CakeTestModel {
  330. /**
  331. * name property
  332. *
  333. * @var string 'SchemaCrossDatabase'
  334. */
  335. public $name = 'SchemaCrossDatabase';
  336. /**
  337. * useTable property
  338. *
  339. * @var string 'posts'
  340. */
  341. public $useTable = 'cross_database';
  342. /**
  343. * useDbConfig property
  344. *
  345. * @var string 'test2'
  346. */
  347. public $useDbConfig = 'test2';
  348. }
  349. /**
  350. * SchemaCrossDatabaseFixture class
  351. *
  352. * @package Cake.Test.Case.Model
  353. */
  354. class SchemaCrossDatabaseFixture extends CakeTestFixture {
  355. /**
  356. * name property
  357. *
  358. * @var string 'CrossDatabase'
  359. */
  360. public $name = 'CrossDatabase';
  361. /**
  362. * table property
  363. *
  364. */
  365. public $table = 'cross_database';
  366. /**
  367. * fields property
  368. *
  369. * @var array
  370. */
  371. public $fields = array(
  372. 'id' => array('type' => 'integer', 'key' => 'primary'),
  373. 'name' => 'string'
  374. );
  375. /**
  376. * records property
  377. *
  378. * @var array
  379. */
  380. public $records = array(
  381. array('id' => 1, 'name' => 'First'),
  382. array('id' => 2, 'name' => 'Second'),
  383. );
  384. }
  385. /**
  386. * SchemaPrefixAuthUser class
  387. *
  388. * @package Cake.Test.Case.Model
  389. */
  390. class SchemaPrefixAuthUser extends CakeTestModel {
  391. /**
  392. * name property
  393. *
  394. * @var string
  395. */
  396. public $name = 'SchemaPrefixAuthUser';
  397. /**
  398. * table prefix
  399. *
  400. * @var string
  401. */
  402. public $tablePrefix = 'auth_';
  403. /**
  404. * useTable
  405. *
  406. * @var string
  407. */
  408. public $useTable = 'users';
  409. }
  410. /**
  411. * CakeSchemaTest
  412. *
  413. * @package Cake.Test.Case.Model
  414. */
  415. class CakeSchemaTest extends CakeTestCase {
  416. /**
  417. * fixtures property
  418. *
  419. * @var array
  420. */
  421. public $fixtures = array(
  422. 'core.post', 'core.tag', 'core.posts_tag', 'core.test_plugin_comment',
  423. 'core.datatype', 'core.auth_user', 'core.author',
  424. 'core.test_plugin_article', 'core.user', 'core.comment',
  425. 'core.prefix_test'
  426. );
  427. /**
  428. * setUp method
  429. *
  430. * @return void
  431. */
  432. public function setUp() {
  433. parent::setUp();
  434. ConnectionManager::getDataSource('test')->cacheSources = false;
  435. $this->Schema = new TestAppSchema();
  436. }
  437. /**
  438. * tearDown method
  439. *
  440. * @return void
  441. */
  442. public function tearDown() {
  443. parent::tearDown();
  444. if (file_exists(TMP . 'tests' . DS . 'schema.php')) {
  445. unlink(TMP . 'tests' . DS . 'schema.php');
  446. }
  447. unset($this->Schema);
  448. CakePlugin::unload();
  449. }
  450. /**
  451. * testSchemaName method
  452. *
  453. * @return void
  454. */
  455. public function testSchemaName() {
  456. $Schema = new CakeSchema();
  457. $this->assertEquals(Inflector::camelize(Inflector::slug(APP_DIR)), $Schema->name);
  458. Configure::write('App.dir', 'Some.name.with.dots');
  459. $Schema = new CakeSchema();
  460. $this->assertEquals('SomeNameWithDots', $Schema->name);
  461. Configure::write('App.dir', 'Some-name-with-dashes');
  462. $Schema = new CakeSchema();
  463. $this->assertEquals('SomeNameWithDashes', $Schema->name);
  464. Configure::write('App.dir', 'Some name with spaces');
  465. $Schema = new CakeSchema();
  466. $this->assertEquals('SomeNameWithSpaces', $Schema->name);
  467. Configure::write('App.dir', 'Some,name;with&weird=characters');
  468. $Schema = new CakeSchema();
  469. $this->assertEquals('SomeNameWithWeirdCharacters', $Schema->name);
  470. Configure::write('App.dir', 'app');
  471. }
  472. /**
  473. * testSchemaRead method
  474. *
  475. * @return void
  476. */
  477. public function testSchemaRead() {
  478. $read = $this->Schema->read(array(
  479. 'connection' => 'test',
  480. 'name' => 'TestApp',
  481. 'models' => array('SchemaPost', 'SchemaComment', 'SchemaTag', 'SchemaDatatype')
  482. ));
  483. unset($read['tables']['missing']);
  484. $expected = array('comments', 'datatypes', 'posts', 'posts_tags', 'tags');
  485. foreach ($expected as $table) {
  486. $this->assertTrue(isset($read['tables'][$table]), 'Missing table ' . $table);
  487. }
  488. foreach ($this->Schema->tables as $table => $fields) {
  489. $this->assertEquals(array_keys($fields), array_keys($read['tables'][$table]));
  490. }
  491. if (isset($read['tables']['datatypes']['float_field']['length'])) {
  492. $this->assertEquals(
  493. $read['tables']['datatypes']['float_field']['length'],
  494. $this->Schema->tables['datatypes']['float_field']['length']
  495. );
  496. }
  497. $this->assertEquals(
  498. $read['tables']['datatypes']['float_field']['type'],
  499. $this->Schema->tables['datatypes']['float_field']['type']
  500. );
  501. $this->assertEquals(
  502. $read['tables']['datatypes']['float_field']['null'],
  503. $this->Schema->tables['datatypes']['float_field']['null']
  504. );
  505. $db = ConnectionManager::getDataSource('test');
  506. $config = $db->config;
  507. $config['prefix'] = 'schema_test_prefix_';
  508. ConnectionManager::create('schema_prefix', $config);
  509. $read = $this->Schema->read(array('connection' => 'schema_prefix', 'models' => false));
  510. $this->assertTrue(empty($read['tables']));
  511. $read = $this->Schema->read(array(
  512. 'connection' => 'test',
  513. 'name' => 'TestApp',
  514. 'models' => array('SchemaComment', 'SchemaTag', 'SchemaPost')
  515. ));
  516. $this->assertFalse(isset($read['tables']['missing']['posts_tags']), 'Join table marked as missing');
  517. }
  518. /**
  519. * testSchemaReadWithAppModel method
  520. *
  521. * @access public
  522. * @return void
  523. */
  524. public function testSchemaReadWithAppModel() {
  525. $connections = ConnectionManager::enumConnectionObjects();
  526. ConnectionManager::drop('default');
  527. ConnectionManager::create('default', $connections['test']);
  528. try {
  529. $this->Schema->read(array(
  530. 'connection' => 'default',
  531. 'name' => 'TestApp',
  532. 'models' => array('AppModel')
  533. ));
  534. } catch(MissingTableException $mte) {
  535. ConnectionManager::drop('default');
  536. $this->fail($mte->getMessage());
  537. }
  538. ConnectionManager::drop('default');
  539. }
  540. /**
  541. * testSchemaReadWithOddTablePrefix method
  542. *
  543. * @return void
  544. */
  545. public function testSchemaReadWithOddTablePrefix() {
  546. $config = ConnectionManager::getDataSource('test')->config;
  547. $this->skipIf(!empty($config['prefix']), 'This test can not be executed with datasource prefix set.');
  548. $SchemaPost = ClassRegistry::init('SchemaPost');
  549. $SchemaPost->tablePrefix = 'po';
  550. $SchemaPost->useTable = 'sts';
  551. $read = $this->Schema->read(array(
  552. 'connection' => 'test',
  553. 'name' => 'TestApp',
  554. 'models' => array('SchemaPost')
  555. ));
  556. $this->assertFalse(isset($read['tables']['missing']['posts']), 'Posts table was not read from tablePrefix');
  557. }
  558. /**
  559. * test read() with tablePrefix properties.
  560. *
  561. * @return void
  562. */
  563. public function testSchemaReadWithTablePrefix() {
  564. $config = ConnectionManager::getDataSource('test')->config;
  565. $this->skipIf(!empty($config['prefix']), 'This test can not be executed with datasource prefix set.');
  566. $Schema = new CakeSchema();
  567. $read = $Schema->read(array(
  568. 'connection' => 'test',
  569. 'name' => 'TestApp',
  570. 'models' => array('SchemaPrefixAuthUser')
  571. ));
  572. unset($read['tables']['missing']);
  573. $this->assertTrue(isset($read['tables']['auth_users']), 'auth_users key missing %s');
  574. }
  575. /**
  576. * test reading schema with config prefix.
  577. *
  578. * @return void
  579. */
  580. public function testSchemaReadWithConfigPrefix() {
  581. $this->skipIf($this->db instanceof Sqlite, 'Cannot open 2 connections to Sqlite');
  582. $db = ConnectionManager::getDataSource('test');
  583. $config = $db->config;
  584. $this->skipIf(!empty($config['prefix']), 'This test can not be executed with datasource prefix set.');
  585. $config['prefix'] = 'schema_test_prefix_';
  586. ConnectionManager::create('schema_prefix', $config);
  587. $read = $this->Schema->read(array('connection' => 'schema_prefix', 'models' => false));
  588. $this->assertTrue(empty($read['tables']));
  589. $config['prefix'] = 'prefix_';
  590. ConnectionManager::create('schema_prefix2', $config);
  591. $read = $this->Schema->read(array(
  592. 'connection' => 'schema_prefix2',
  593. 'name' => 'TestApp',
  594. 'models' => false));
  595. $this->assertTrue(isset($read['tables']['prefix_tests']));
  596. }
  597. /**
  598. * test reading schema from plugins.
  599. *
  600. * @return void
  601. */
  602. public function testSchemaReadWithPlugins() {
  603. App::objects('model', null, false);
  604. App::build(array(
  605. 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS)
  606. ));
  607. CakePlugin::load('TestPlugin');
  608. $Schema = new CakeSchema();
  609. $Schema->plugin = 'TestPlugin';
  610. $read = $Schema->read(array(
  611. 'connection' => 'test',
  612. 'name' => 'TestApp',
  613. 'models' => true
  614. ));
  615. unset($read['tables']['missing']);
  616. $this->assertTrue(isset($read['tables']['auth_users']));
  617. $this->assertTrue(isset($read['tables']['authors']));
  618. $this->assertTrue(isset($read['tables']['test_plugin_comments']));
  619. $this->assertTrue(isset($read['tables']['posts']));
  620. $this->assertTrue(count($read['tables']) >= 4);
  621. App::build();
  622. }
  623. /**
  624. * test reading schema with tables from another database.
  625. *
  626. * @return void
  627. */
  628. public function testSchemaReadWithCrossDatabase() {
  629. $config = ConnectionManager::enumConnectionObjects();
  630. $this->skipIf(
  631. !isset($config['test']) || !isset($config['test2']),
  632. 'Primary and secondary test databases not configured, ' .
  633. 'skipping cross-database join tests. ' .
  634. 'To run these tests, you must define $test and $test2 in your database configuration.'
  635. );
  636. $db = ConnectionManager::getDataSource('test2');
  637. $fixture = new SchemaCrossDatabaseFixture();
  638. $fixture->create($db);
  639. $fixture->insert($db);
  640. $read = $this->Schema->read(array(
  641. 'connection' => 'test',
  642. 'name' => 'TestApp',
  643. 'models' => array('SchemaCrossDatabase', 'SchemaPost')
  644. ));
  645. $this->assertTrue(isset($read['tables']['posts']));
  646. $this->assertFalse(isset($read['tables']['cross_database']), 'Cross database should not appear');
  647. $this->assertFalse(isset($read['tables']['missing']['cross_database']), 'Cross database should not appear');
  648. $read = $this->Schema->read(array(
  649. 'connection' => 'test2',
  650. 'name' => 'TestApp',
  651. 'models' => array('SchemaCrossDatabase', 'SchemaPost')
  652. ));
  653. $this->assertFalse(isset($read['tables']['posts']), 'Posts should not appear');
  654. $this->assertFalse(isset($read['tables']['posts']), 'Posts should not appear');
  655. $this->assertTrue(isset($read['tables']['cross_database']));
  656. $fixture->drop($db);
  657. }
  658. /**
  659. * test that tables are generated correctly
  660. *
  661. * @return void
  662. */
  663. public function testGenerateTable() {
  664. $posts = array(
  665. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  666. 'author_id' => array('type' => 'integer', 'null' => false),
  667. 'title' => array('type' => 'string', 'null' => false),
  668. 'body' => array('type' => 'text', 'null' => true, 'default' => null),
  669. 'published' => array('type' => 'string', 'null' => true, 'default' => 'N', 'length' => 1),
  670. 'created' => array('type' => 'datetime', 'null' => true, 'default' => null),
  671. 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null),
  672. 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)),
  673. );
  674. $result = $this->Schema->generateTable('posts', $posts);
  675. $this->assertRegExp('/public \$posts/', $result);
  676. $posts = array(
  677. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  678. 'author_id' => array('type' => 'integer', 'null' => false),
  679. 'title' => array('type' => 'string', 'null' => false),
  680. 'body' => array('type' => 'text', 'null' => true, 'default' => null),
  681. 'published' => array('type' => 'string', 'null' => true, 'default' => 'N', 'length' => 1),
  682. 'created' => array('type' => 'datetime', 'null' => true, 'default' => null),
  683. 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null),
  684. 'indexes' => array(
  685. 'PRIMARY' => array('column' => 'id', 'unique' => true),
  686. 'MyFtIndex' => array('column' => array('title', 'body'), 'type' => 'fulltext')
  687. )
  688. );
  689. $result = $this->Schema->generateTable('fields', $posts);
  690. $this->assertRegExp('/public \$fields/', $result);
  691. $this->assertPattern('/\'type\' \=\> \'fulltext\'/', $result);
  692. }
  693. /**
  694. * testSchemaWrite method
  695. *
  696. * @return void
  697. */
  698. public function testSchemaWrite() {
  699. $write = $this->Schema->write(array(
  700. 'name' => 'MyOtherApp',
  701. 'tables' => $this->Schema->tables,
  702. 'path' => TMP . 'tests'
  703. ));
  704. $file = file_get_contents(TMP . 'tests' . DS . 'schema.php');
  705. $this->assertEquals($write, $file);
  706. require_once TMP . 'tests' . DS . 'schema.php';
  707. $OtherSchema = new MyOtherAppSchema();
  708. $this->assertEquals($this->Schema->tables, $OtherSchema->tables);
  709. }
  710. /**
  711. * testSchemaComparison method
  712. *
  713. * @return void
  714. */
  715. public function testSchemaComparison() {
  716. $New = new MyAppSchema();
  717. $compare = $New->compare($this->Schema);
  718. $expected = array(
  719. 'comments' => array(
  720. 'add' => array(
  721. 'post_id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'after' => 'id'),
  722. 'title' => array('type' => 'string', 'null' => false, 'length' => 100, 'after' => 'user_id'),
  723. ),
  724. 'drop' => array(
  725. 'article_id' => array('type' => 'integer', 'null' => false),
  726. 'tableParameters' => array(),
  727. ),
  728. 'change' => array(
  729. 'comment' => array('type' => 'text', 'null' => false, 'default' => null),
  730. )
  731. ),
  732. 'posts' => array(
  733. 'add' => array(
  734. 'summary' => array('type' => 'text', 'null' => true, 'after' => 'body'),
  735. ),
  736. 'drop' => array(
  737. 'tableParameters' => array(),
  738. ),
  739. 'change' => array(
  740. 'author_id' => array('type' => 'integer', 'null' => true, 'default' => ''),
  741. 'title' => array('type' => 'string', 'null' => false, 'default' => 'Title'),
  742. 'published' => array('type' => 'string', 'null' => true, 'default' => 'Y', 'length' => 1)
  743. )
  744. ),
  745. );
  746. $this->assertEquals($expected, $compare);
  747. $this->assertNull($New->getVar('comments'));
  748. $this->assertEquals(array('bar'), $New->getVar('_foo'));
  749. $tables = array(
  750. 'missing' => array(
  751. 'categories' => array(
  752. 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary'),
  753. 'created' => array('type' => 'datetime', 'null' => false, 'default' => null),
  754. 'modified' => array('type' => 'datetime', 'null' => false, 'default' => null),
  755. 'name' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 100),
  756. 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1)),
  757. 'tableParameters' => array('charset' => 'latin1', 'collate' => 'latin1_swedish_ci', 'engine' => 'MyISAM')
  758. )
  759. ),
  760. 'ratings' => array(
  761. 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary'),
  762. 'foreign_key' => array('type' => 'integer', 'null' => false, 'default' => null),
  763. 'model' => array('type' => 'varchar', 'null' => false, 'default' => null),
  764. 'value' => array('type' => 'float', 'null' => false, 'length' => '5,2', 'default' => null),
  765. 'created' => array('type' => 'datetime', 'null' => false, 'default' => null),
  766. 'modified' => array('type' => 'datetime', 'null' => false, 'default' => null),
  767. 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1)),
  768. 'tableParameters' => array('charset' => 'latin1', 'collate' => 'latin1_swedish_ci', 'engine' => 'MyISAM')
  769. )
  770. );
  771. $compare = $New->compare($this->Schema, $tables);
  772. $expected = array(
  773. 'ratings' => array(
  774. 'add' => array(
  775. 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary'),
  776. 'foreign_key' => array('type' => 'integer', 'null' => false, 'default' => null, 'after' => 'id'),
  777. 'model' => array('type' => 'varchar', 'null' => false, 'default' => null, 'after' => 'foreign_key'),
  778. 'value' => array('type' => 'float', 'null' => false, 'length' => '5,2', 'default' => null, 'after' => 'model'),
  779. 'created' => array('type' => 'datetime', 'null' => false, 'default' => null, 'after' => 'value'),
  780. 'modified' => array('type' => 'datetime', 'null' => false, 'default' => null, 'after' => 'created'),
  781. 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1)),
  782. 'tableParameters' => array('charset' => 'latin1', 'collate' => 'latin1_swedish_ci', 'engine' => 'MyISAM')
  783. )
  784. )
  785. );
  786. $this->assertEquals($expected, $compare);
  787. }
  788. /**
  789. * test comparing '' and null and making sure they are different.
  790. *
  791. * @return void
  792. */
  793. public function testCompareEmptyStringAndNull() {
  794. $One = new CakeSchema(array(
  795. 'posts' => array(
  796. 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary'),
  797. 'name' => array('type' => 'string', 'null' => false, 'default' => '')
  798. )
  799. ));
  800. $Two = new CakeSchema(array(
  801. 'posts' => array(
  802. 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary'),
  803. 'name' => array('type' => 'string', 'null' => false, 'default' => null)
  804. )
  805. ));
  806. $compare = $One->compare($Two);
  807. $expected = array(
  808. 'posts' => array(
  809. 'change' => array(
  810. 'name' => array('type' => 'string', 'null' => false, 'default' => null)
  811. )
  812. )
  813. );
  814. $this->assertEquals($expected, $compare);
  815. }
  816. /**
  817. * Test comparing tableParameters and indexes.
  818. *
  819. * @return void
  820. */
  821. public function testTableParametersAndIndexComparison() {
  822. $old = array(
  823. 'posts' => array(
  824. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  825. 'author_id' => array('type' => 'integer', 'null' => false),
  826. 'title' => array('type' => 'string', 'null' => false),
  827. 'indexes' => array(
  828. 'PRIMARY' => array('column' => 'id', 'unique' => true)
  829. ),
  830. 'tableParameters' => array(
  831. 'charset' => 'latin1',
  832. 'collate' => 'latin1_general_ci'
  833. )
  834. ),
  835. 'comments' => array(
  836. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  837. 'post_id' => array('type' => 'integer', 'null' => false, 'default' => 0),
  838. 'comment' => array('type' => 'text'),
  839. 'indexes' => array(
  840. 'PRIMARY' => array('column' => 'id', 'unique' => true),
  841. 'post_id' => array('column' => 'post_id'),
  842. ),
  843. 'tableParameters' => array(
  844. 'engine' => 'InnoDB',
  845. 'charset' => 'latin1',
  846. 'collate' => 'latin1_general_ci'
  847. )
  848. )
  849. );
  850. $new = array(
  851. 'posts' => array(
  852. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  853. 'author_id' => array('type' => 'integer', 'null' => false),
  854. 'title' => array('type' => 'string', 'null' => false),
  855. 'indexes' => array(
  856. 'PRIMARY' => array('column' => 'id', 'unique' => true),
  857. 'author_id' => array('column' => 'author_id'),
  858. ),
  859. 'tableParameters' => array(
  860. 'charset' => 'utf8',
  861. 'collate' => 'utf8_general_ci',
  862. 'engine' => 'MyISAM'
  863. )
  864. ),
  865. 'comments' => array(
  866. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  867. 'post_id' => array('type' => 'integer', 'null' => false, 'default' => 0),
  868. 'comment' => array('type' => 'text'),
  869. 'indexes' => array(
  870. 'PRIMARY' => array('column' => 'id', 'unique' => true),
  871. ),
  872. 'tableParameters' => array(
  873. 'charset' => 'utf8',
  874. 'collate' => 'utf8_general_ci'
  875. )
  876. )
  877. );
  878. $compare = $this->Schema->compare($old, $new);
  879. $expected = array(
  880. 'posts' => array(
  881. 'add' => array(
  882. 'indexes' => array('author_id' => array('column' => 'author_id')),
  883. ),
  884. 'change' => array(
  885. 'tableParameters' => array(
  886. 'charset' => 'utf8',
  887. 'collate' => 'utf8_general_ci',
  888. 'engine' => 'MyISAM'
  889. )
  890. )
  891. ),
  892. 'comments' => array(
  893. 'drop' => array(
  894. 'indexes' => array('post_id' => array('column' => 'post_id')),
  895. ),
  896. 'change' => array(
  897. 'tableParameters' => array(
  898. 'charset' => 'utf8',
  899. 'collate' => 'utf8_general_ci',
  900. )
  901. )
  902. )
  903. );
  904. $this->assertEquals($expected, $compare);
  905. }
  906. /**
  907. * Test comparing with field changed from VARCHAR to DATETIME
  908. *
  909. * @return void
  910. */
  911. public function testCompareVarcharToDatetime() {
  912. $old = array(
  913. 'posts' => array(
  914. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  915. 'author_id' => array('type' => 'integer', 'null' => false),
  916. 'title' => array('type' => 'string', 'null' => true, 'length' => 45),
  917. 'indexes' => array(
  918. 'PRIMARY' => array('column' => 'id', 'unique' => true)
  919. ),
  920. 'tableParameters' => array(
  921. 'charset' => 'latin1',
  922. 'collate' => 'latin1_general_ci'
  923. )
  924. ),
  925. );
  926. $new = array(
  927. 'posts' => array(
  928. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  929. 'author_id' => array('type' => 'integer', 'null' => false),
  930. 'title' => array('type' => 'datetime', 'null' => false),
  931. 'indexes' => array(
  932. 'PRIMARY' => array('column' => 'id', 'unique' => true)
  933. ),
  934. 'tableParameters' => array(
  935. 'charset' => 'latin1',
  936. 'collate' => 'latin1_general_ci'
  937. )
  938. ),
  939. );
  940. $compare = $this->Schema->compare($old, $new);
  941. $expected = array(
  942. 'posts' => array(
  943. 'change' => array(
  944. 'title' => array(
  945. 'type' => 'datetime',
  946. 'null' => false,
  947. )
  948. )
  949. ),
  950. );
  951. $this->assertEquals($expected, $compare, 'Invalid SQL, datetime does not have length');
  952. }
  953. /**
  954. * testSchemaLoading method
  955. *
  956. * @return void
  957. */
  958. public function testSchemaLoading() {
  959. $Other = $this->Schema->load(array('name' => 'MyOtherApp', 'path' => TMP . 'tests'));
  960. $this->assertEquals('MyOtherApp', $Other->name);
  961. $this->assertEquals($Other->tables, $this->Schema->tables);
  962. }
  963. /**
  964. * test loading schema files inside of plugins.
  965. *
  966. * @return void
  967. */
  968. public function testSchemaLoadingFromPlugin() {
  969. App::build(array(
  970. 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS)
  971. ));
  972. CakePlugin::load('TestPlugin');
  973. $Other = $this->Schema->load(array('name' => 'TestPluginApp', 'plugin' => 'TestPlugin'));
  974. $this->assertEquals('TestPluginApp', $Other->name);
  975. $this->assertEquals(array('test_plugin_acos'), array_keys($Other->tables));
  976. App::build();
  977. }
  978. /**
  979. * testSchemaCreateTable method
  980. *
  981. * @return void
  982. */
  983. public function testSchemaCreateTable() {
  984. $db = ConnectionManager::getDataSource('test');
  985. $db->cacheSources = false;
  986. $Schema = new CakeSchema(array(
  987. 'connection' => 'test',
  988. 'testdescribes' => array(
  989. 'id' => array('type' => 'integer', 'key' => 'primary'),
  990. 'int_null' => array('type' => 'integer', 'null' => true),
  991. 'int_not_null' => array('type' => 'integer', 'null' => false),
  992. ),
  993. ));
  994. $sql = $db->createSchema($Schema);
  995. $col = $Schema->tables['testdescribes']['int_null'];
  996. $col['name'] = 'int_null';
  997. $column = $this->db->buildColumn($col);
  998. $this->assertRegExp('/' . preg_quote($column, '/') . '/', $sql);
  999. $col = $Schema->tables['testdescribes']['int_not_null'];
  1000. $col['name'] = 'int_not_null';
  1001. $column = $this->db->buildColumn($col);
  1002. $this->assertRegExp('/' . preg_quote($column, '/') . '/', $sql);
  1003. }
  1004. }