CakeSchemaTest.php 29 KB

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