PageRenderTime 51ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/Cake/Test/Case/Model/Datasource/Database/PostgresTest.php

https://bitbucket.org/udeshika/fake_twitter
PHP | 874 lines | 528 code | 97 blank | 249 comment | 0 complexity | 79a42d47a363d4976586ed2b4b20d437 MD5 | raw file
  1. <?php
  2. /**
  3. * DboPostgresTest file
  4. *
  5. * PHP 5
  6. *
  7. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  8. * Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
  9. *
  10. * Licensed under The MIT License
  11. * Redistributions of files must retain the above copyright notice.
  12. *
  13. * @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
  14. * @link http://cakephp.org CakePHP(tm) Project
  15. * @package Cake.Test.Case.Model.Datasource.Database
  16. * @since CakePHP(tm) v 1.2.0
  17. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  18. */
  19. App::uses('Model', 'Model');
  20. App::uses('AppModel', 'Model');
  21. App::uses('Postgres', 'Model/Datasource/Database');
  22. require_once dirname(dirname(dirname(__FILE__))) . DS . 'models.php';
  23. /**
  24. * DboPostgresTestDb class
  25. *
  26. * @package Cake.Test.Case.Model.Datasource.Database
  27. */
  28. class DboPostgresTestDb extends Postgres {
  29. /**
  30. * simulated property
  31. *
  32. * @var array
  33. */
  34. public $simulated = array();
  35. /**
  36. * execute method
  37. *
  38. * @param mixed $sql
  39. * @return void
  40. */
  41. function _execute($sql, $params = array(), $prepareOptions = array()) {
  42. $this->simulated[] = $sql;
  43. return null;
  44. }
  45. /**
  46. * getLastQuery method
  47. *
  48. * @return void
  49. */
  50. public function getLastQuery() {
  51. return $this->simulated[count($this->simulated) - 1];
  52. }
  53. }
  54. /**
  55. * PostgresTestModel class
  56. *
  57. * @package Cake.Test.Case.Model.Datasource.Database
  58. */
  59. class PostgresTestModel extends Model {
  60. /**
  61. * name property
  62. *
  63. * @var string 'PostgresTestModel'
  64. */
  65. public $name = 'PostgresTestModel';
  66. /**
  67. * useTable property
  68. *
  69. * @var bool false
  70. */
  71. public $useTable = false;
  72. /**
  73. * belongsTo property
  74. *
  75. * @var array
  76. */
  77. public $belongsTo = array(
  78. 'PostgresClientTestModel' => array(
  79. 'foreignKey' => 'client_id'
  80. )
  81. );
  82. /**
  83. * find method
  84. *
  85. * @param mixed $conditions
  86. * @param mixed $fields
  87. * @param mixed $order
  88. * @param mixed $recursive
  89. * @return void
  90. */
  91. public function find($conditions = null, $fields = null, $order = null, $recursive = null) {
  92. return $conditions;
  93. }
  94. /**
  95. * findAll method
  96. *
  97. * @param mixed $conditions
  98. * @param mixed $fields
  99. * @param mixed $order
  100. * @param mixed $recursive
  101. * @return void
  102. */
  103. public function findAll($conditions = null, $fields = null, $order = null, $recursive = null) {
  104. return $conditions;
  105. }
  106. /**
  107. * schema method
  108. *
  109. * @return void
  110. */
  111. public function schema($field = false) {
  112. return array(
  113. 'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'),
  114. 'client_id' => array('type' => 'integer', 'null' => '', 'default' => '0', 'length' => '11'),
  115. 'name' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'),
  116. 'login' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'),
  117. 'passwd' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '255'),
  118. 'addr_1' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '255'),
  119. 'addr_2' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '25'),
  120. 'zip_code' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'),
  121. 'city' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'),
  122. 'country' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'),
  123. 'phone' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'),
  124. 'fax' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'),
  125. 'url' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '255'),
  126. 'email' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'),
  127. 'comments' => array('type' => 'text', 'null' => '1', 'default' => '', 'length' => ''),
  128. 'last_login'=> array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => ''),
  129. 'created' => array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''),
  130. 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null)
  131. );
  132. }
  133. }
  134. /**
  135. * PostgresClientTestModel class
  136. *
  137. * @package Cake.Test.Case.Model.Datasource.Database
  138. */
  139. class PostgresClientTestModel extends Model {
  140. /**
  141. * name property
  142. *
  143. * @var string 'PostgresClientTestModel'
  144. */
  145. public $name = 'PostgresClientTestModel';
  146. /**
  147. * useTable property
  148. *
  149. * @var bool false
  150. */
  151. public $useTable = false;
  152. /**
  153. * schema method
  154. *
  155. * @return void
  156. */
  157. public function schema($field = false) {
  158. return array(
  159. 'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8', 'key' => 'primary'),
  160. 'name' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'),
  161. 'email' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'),
  162. 'created' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => ''),
  163. 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null)
  164. );
  165. }
  166. }
  167. /**
  168. * PostgresTest class
  169. *
  170. * @package Cake.Test.Case.Model.Datasource.Database
  171. */
  172. class PostgresTest extends CakeTestCase {
  173. /**
  174. * Do not automatically load fixtures for each test, they will be loaded manually
  175. * using CakeTestCase::loadFixtures
  176. *
  177. * @var boolean
  178. */
  179. public $autoFixtures = false;
  180. /**
  181. * Fixtures
  182. *
  183. * @var object
  184. */
  185. public $fixtures = array('core.user', 'core.binary_test', 'core.comment', 'core.article',
  186. 'core.tag', 'core.articles_tag', 'core.attachment', 'core.person', 'core.post', 'core.author',
  187. 'core.datatype',
  188. );
  189. /**
  190. * Actual DB connection used in testing
  191. *
  192. * @var DboSource
  193. */
  194. public $Dbo = null;
  195. /**
  196. * Simulated DB connection used in testing
  197. *
  198. * @var DboSource
  199. */
  200. public $Dbo2 = null;
  201. /**
  202. * Sets up a Dbo class instance for testing
  203. *
  204. */
  205. public function setUp() {
  206. Configure::write('Cache.disable', true);
  207. $this->Dbo = ConnectionManager::getDataSource('test');
  208. $this->skipIf(!($this->Dbo instanceof Postgres));
  209. $this->Dbo2 = new DboPostgresTestDb($this->Dbo->config, false);
  210. $this->model = new PostgresTestModel();
  211. }
  212. /**
  213. * Sets up a Dbo class instance for testing
  214. *
  215. */
  216. public function tearDown() {
  217. Configure::write('Cache.disable', false);
  218. unset($this->Dbo2);
  219. }
  220. /**
  221. * Test field quoting method
  222. *
  223. */
  224. public function testFieldQuoting() {
  225. $fields = array(
  226. '"PostgresTestModel"."id" AS "PostgresTestModel__id"',
  227. '"PostgresTestModel"."client_id" AS "PostgresTestModel__client_id"',
  228. '"PostgresTestModel"."name" AS "PostgresTestModel__name"',
  229. '"PostgresTestModel"."login" AS "PostgresTestModel__login"',
  230. '"PostgresTestModel"."passwd" AS "PostgresTestModel__passwd"',
  231. '"PostgresTestModel"."addr_1" AS "PostgresTestModel__addr_1"',
  232. '"PostgresTestModel"."addr_2" AS "PostgresTestModel__addr_2"',
  233. '"PostgresTestModel"."zip_code" AS "PostgresTestModel__zip_code"',
  234. '"PostgresTestModel"."city" AS "PostgresTestModel__city"',
  235. '"PostgresTestModel"."country" AS "PostgresTestModel__country"',
  236. '"PostgresTestModel"."phone" AS "PostgresTestModel__phone"',
  237. '"PostgresTestModel"."fax" AS "PostgresTestModel__fax"',
  238. '"PostgresTestModel"."url" AS "PostgresTestModel__url"',
  239. '"PostgresTestModel"."email" AS "PostgresTestModel__email"',
  240. '"PostgresTestModel"."comments" AS "PostgresTestModel__comments"',
  241. '"PostgresTestModel"."last_login" AS "PostgresTestModel__last_login"',
  242. '"PostgresTestModel"."created" AS "PostgresTestModel__created"',
  243. '"PostgresTestModel"."updated" AS "PostgresTestModel__updated"'
  244. );
  245. $result = $this->Dbo->fields($this->model);
  246. $expected = $fields;
  247. $this->assertEquals($expected, $result);
  248. $result = $this->Dbo->fields($this->model, null, 'PostgresTestModel.*');
  249. $expected = $fields;
  250. $this->assertEquals($expected, $result);
  251. $result = $this->Dbo->fields($this->model, null, array('*', 'AnotherModel.id', 'AnotherModel.name'));
  252. $expected = array_merge($fields, array(
  253. '"AnotherModel"."id" AS "AnotherModel__id"',
  254. '"AnotherModel"."name" AS "AnotherModel__name"'));
  255. $this->assertEquals($expected, $result);
  256. $result = $this->Dbo->fields($this->model, null, array('*', 'PostgresClientTestModel.*'));
  257. $expected = array_merge($fields, array(
  258. '"PostgresClientTestModel"."id" AS "PostgresClientTestModel__id"',
  259. '"PostgresClientTestModel"."name" AS "PostgresClientTestModel__name"',
  260. '"PostgresClientTestModel"."email" AS "PostgresClientTestModel__email"',
  261. '"PostgresClientTestModel"."created" AS "PostgresClientTestModel__created"',
  262. '"PostgresClientTestModel"."updated" AS "PostgresClientTestModel__updated"'));
  263. $this->assertEquals($expected, $result);
  264. }
  265. /**
  266. * testColumnParsing method
  267. *
  268. * @return void
  269. */
  270. public function testColumnParsing() {
  271. $this->assertEquals($this->Dbo2->column('text'), 'text');
  272. $this->assertEquals($this->Dbo2->column('date'), 'date');
  273. $this->assertEquals($this->Dbo2->column('boolean'), 'boolean');
  274. $this->assertEquals($this->Dbo2->column('character varying'), 'string');
  275. $this->assertEquals($this->Dbo2->column('time without time zone'), 'time');
  276. $this->assertEquals($this->Dbo2->column('timestamp without time zone'), 'datetime');
  277. }
  278. /**
  279. * testValueQuoting method
  280. *
  281. * @return void
  282. */
  283. public function testValueQuoting() {
  284. $this->assertEquals($this->Dbo->value(1.2, 'float'), "1.200000");
  285. $this->assertEquals($this->Dbo->value('1,2', 'float'), "'1,2'");
  286. $this->assertEquals($this->Dbo->value('0', 'integer'), "0");
  287. $this->assertEquals($this->Dbo->value('', 'integer'), 'NULL');
  288. $this->assertEquals($this->Dbo->value('', 'float'), 'NULL');
  289. $this->assertEquals($this->Dbo->value('', 'integer', false), "NULL");
  290. $this->assertEquals($this->Dbo->value('', 'float', false), "NULL");
  291. $this->assertEquals($this->Dbo->value('0.0', 'float'), "'0.0'");
  292. $this->assertEquals($this->Dbo->value('t', 'boolean'), "'TRUE'");
  293. $this->assertEquals($this->Dbo->value('f', 'boolean'), "'FALSE'");
  294. $this->assertEquals($this->Dbo->value(true), "'TRUE'");
  295. $this->assertEquals($this->Dbo->value(false), "'FALSE'");
  296. $this->assertEquals($this->Dbo->value('t'), "'t'");
  297. $this->assertEquals($this->Dbo->value('f'), "'f'");
  298. $this->assertEquals($this->Dbo->value('true', 'boolean'), "'TRUE'");
  299. $this->assertEquals($this->Dbo->value('false', 'boolean'), "'FALSE'");
  300. $this->assertEquals($this->Dbo->value('', 'boolean'), "'FALSE'");
  301. $this->assertEquals($this->Dbo->value(0, 'boolean'), "'FALSE'");
  302. $this->assertEquals($this->Dbo->value(1, 'boolean'), "'TRUE'");
  303. $this->assertEquals($this->Dbo->value('1', 'boolean'), "'TRUE'");
  304. $this->assertEquals($this->Dbo->value(null, 'boolean'), "NULL");
  305. $this->assertEquals($this->Dbo->value(array()), "NULL");
  306. }
  307. /**
  308. * test that localized floats don't cause trouble.
  309. *
  310. * @return void
  311. */
  312. public function testLocalizedFloats() {
  313. $restore = setlocale(LC_ALL, null);
  314. setlocale(LC_ALL, 'de_DE');
  315. $result = $this->db->value(3.141593, 'float');
  316. $this->assertEquals($result, "3.141593");
  317. $result = $this->db->value(3.14);
  318. $this->assertEquals($result, "3.140000");
  319. setlocale(LC_ALL, $restore);
  320. }
  321. /**
  322. * test that date and time columns do not generate errors with null and nullish values.
  323. *
  324. * @return void
  325. */
  326. public function testDateAndTimeAsNull() {
  327. $this->assertEquals($this->Dbo->value(null, 'date'), 'NULL');
  328. $this->assertEquals($this->Dbo->value('', 'date'), 'NULL');
  329. $this->assertEquals($this->Dbo->value('', 'datetime'), 'NULL');
  330. $this->assertEquals($this->Dbo->value(null, 'datetime'), 'NULL');
  331. $this->assertEquals($this->Dbo->value('', 'timestamp'), 'NULL');
  332. $this->assertEquals($this->Dbo->value(null, 'timestamp'), 'NULL');
  333. $this->assertEquals($this->Dbo->value('', 'time'), 'NULL');
  334. $this->assertEquals($this->Dbo->value(null, 'time'), 'NULL');
  335. }
  336. /**
  337. * Tests that different Postgres boolean 'flavors' are properly returned as native PHP booleans
  338. *
  339. * @return void
  340. */
  341. public function testBooleanNormalization() {
  342. $this->assertEquals(true, $this->Dbo2->boolean('t', false));
  343. $this->assertEquals(true, $this->Dbo2->boolean('true', false));
  344. $this->assertEquals(true, $this->Dbo2->boolean('TRUE', false));
  345. $this->assertEquals(true, $this->Dbo2->boolean(true, false));
  346. $this->assertEquals(true, $this->Dbo2->boolean(1, false));
  347. $this->assertEquals(true, $this->Dbo2->boolean(" ", false));
  348. $this->assertEquals(false, $this->Dbo2->boolean('f', false));
  349. $this->assertEquals(false, $this->Dbo2->boolean('false', false));
  350. $this->assertEquals(false, $this->Dbo2->boolean('FALSE', false));
  351. $this->assertEquals(false, $this->Dbo2->boolean(false, false));
  352. $this->assertEquals(false, $this->Dbo2->boolean(0, false));
  353. $this->assertEquals(false, $this->Dbo2->boolean('', false));
  354. }
  355. /**
  356. * test that default -> false in schemas works correctly.
  357. *
  358. * @return void
  359. */
  360. public function testBooleanDefaultFalseInSchema() {
  361. $this->loadFixtures('Datatype');
  362. $model = new Model(array('name' => 'Datatype', 'table' => 'datatypes', 'ds' => 'test'));
  363. $model->create();
  364. $this->assertSame(false, $model->data['Datatype']['bool']);
  365. }
  366. /**
  367. * testLastInsertIdMultipleInsert method
  368. *
  369. * @return void
  370. */
  371. public function testLastInsertIdMultipleInsert() {
  372. $this->loadFixtures('User');
  373. $db1 = ConnectionManager::getDataSource('test');
  374. $table = $db1->fullTableName('users', false);
  375. $password = '5f4dcc3b5aa765d61d8327deb882cf99';
  376. $db1->execute(
  377. "INSERT INTO {$table} (\"user\", password) VALUES ('mariano', '{$password}')"
  378. );
  379. $this->assertEquals($db1->lastInsertId($table), 5);
  380. $db1->execute("INSERT INTO {$table} (\"user\", password) VALUES ('hoge', '{$password}')");
  381. $this->assertEquals($db1->lastInsertId($table), 6);
  382. }
  383. /**
  384. * Tests that column types without default lengths in $columns do not have length values
  385. * applied when generating schemas.
  386. *
  387. * @return void
  388. */
  389. public function testColumnUseLength() {
  390. $result = array('name' => 'foo', 'type' => 'string', 'length' => 100, 'default' => 'FOO');
  391. $expected = '"foo" varchar(100) DEFAULT \'FOO\'';
  392. $this->assertEquals($this->Dbo->buildColumn($result), $expected);
  393. $result = array('name' => 'foo', 'type' => 'text', 'length' => 100, 'default' => 'FOO');
  394. $expected = '"foo" text DEFAULT \'FOO\'';
  395. $this->assertEquals($this->Dbo->buildColumn($result), $expected);
  396. }
  397. /**
  398. * Tests that binary data is escaped/unescaped properly on reads and writes
  399. *
  400. * @return void
  401. */
  402. public function testBinaryDataIntegrity() {
  403. $this->loadFixtures('BinaryTest');
  404. $data = '%PDF-1.3
  405. %ƒÂÚÂÎßÛ†–ƒ∆
  406. 4 0 obj
  407. << /Length 5 0 R /Filter /FlateDecode >>
  408. stream
  409. xÂľYMì€∆Ω„ƒ%)nĂŻ0ÂŻĂŽâ-ÂŤĂŠ]Q"πXµáÿ•Ip - P V,]Ú#c˚ˇ‰ut¥†∏Ti9 Ü=”›Ø_˜4>à∑‚ÉpcĂŠ¢PxĂŚÂŽ2q\'
  410. 1UÂŞbU ᡒ+ö«√[ıµ⁄ão"R∑"HiGĂŚä€(å≠≈^Ãøsm?YlƒÃõªfi‹âšB&‚Î◊7’^¸°ĂˇË›?2¹Ø€œďŹu#ÂŽU√ˇúág¼C;ä")n})JÂşIÔ3ËSnÑÎ¥≤ıD∆¢∂Msx1ĂźèG˚±Œ™⁄>ÂśySĂŻufØ ˝¸?UπÃã√6flÌÚC=øK?˝…s
  411. ˛§¯ˇ:-˜ò7€ÓFæ∂∑Õ˛∆“€™>ÄąlflëÅd«ÜQdI ›ÎB%W¿ΊıÉn~h vĂŞCS>ÂŤĂŠ˛(ØôK!€¡zB!√
  412. [œÜ"ûß ·iH¸[Àºæ∑¯¡L,ÀÚAlS∫ˆ=∫Œ≤cÄr&ˆÈ:√ÿ£˚È«4fl•À]vc›bÅôÿî=siXe4/¡p]ã]ôÆIœ™ Ωflà_ƒ‚G?«7 ùÿ ı¯K4ïIpV◊÷·\'éµóªÚæ>î
  413. ;›sĂş!2flÂŹF•/ˆ‘jÂŁ
  414. dw"IÊÜπ<ôÿˆ%IG1ytÛDflXg|Éòa§˜}C˛¿ÿe°G´Ú±jÍm~¿/∂hã<#-¥•ıùe87€t˜õ6w}´{æ
  415. €šĂŞâ€“ ∆¡ 6⁄\
  416. rAÀBĂšZ3aË‚r$G¡$Ăł0Ñ ßâUY4È™¡%ˆ‘Ÿ2rc<IĂľ-cĂŻ.
  417. [ŒöâF€ Ă‰â€Ą+QglMÉîÉÄúÌ|¸#x7ÂĽÂŤMgVÎ-Gšâ€˘Â I?Á‘”Lzw∞pHů◊nefqCĂŽ.•¨∆ÿÛyÂĄ˙fb≤üŒœAëÕNq=´@ ’cQdÖúAÉIqùŸ˘+2&∏ Àù.…‚ƒœ3E’Oi—‰:>ͤĹ
  418. =Õec=ĂŤR˝”eĂą=<V$ì˙+x+¢ïÒÕ<Ă eWĂĽÂť–˚∫Õ §&ÂŁĂ  ]fPA´âtĂŤnöå∏◊ó „Ë@∆≠´ĂˇË˜}a_CI˚ŠyòHg,Ă´SSVĂŹBƒl4 L.ÈY…á,2∂íäÙ.$ó¸¤Ĺ¸*€óy
  419. π?G,ˆšÂˇĂ†ĂŽĂ§=^Vkvo¹ó{§ƒ2¹¨ÏüoÍD-ãÊ ó¼cVÙ\'™G~\'p¢%* ã˚÷
  420. ÂŞÂşnh˚ºO^∏…®[Ó“‚ÅfıÌ≥∫F!“(π∑T6`ÂŹtΩÆ0ĂŹÂťrTÎ`»Ñ«
  421. ]Ōp˝)=¿Ô0∆öV‡ˆ„ø~¯ÁÔ∏b*fc»‡Îı„Ú}∆“ˆ‚ˆŤĂœ†˙ˆ~<ÿ·Ù vĂŠ1‹pÂżTD∆ÔîÄ“úhˆ*Ú€îe)K –¨ĂšJ3Ÿ∞ã>ÊuNĂŞ°“√Ü ‹Ê9iÙ0˙AAEÍ ˙`∂£\'Ăťce•åƒX›ŸÁ´1SK{qdĂĄ"tÏ[wQ#SÂľBe∞∑µó…ÌV`B"Ñ≥„!è_Óφ-Âş*Âşú¿Ë0ˆeê∂´ë+HFj…‡zvHÓN|ÔLáÝù3ĂľÜ$z%sá…pÎóV38âs Çoµ•ß3†<9B¡¨Ý~¢3)ÂxóÿÁCÕòÆ ∫Í=ÿSπS;∆~±êÆTEp∑óÈ÷ÀuĂŹDHÈ $ÉõæÜjݧ"≤ÃONMÂŽRËíRr{ĂľS ∏Ê™opÂąW;” ˆŤkÔˇflTæ∑óflË” ÆC©Ô[≥◊ËšÂ¨hĂŞ"ÆbF?Ăş%h˙ˇ4xèÕ(Ăł2ÙáíM])Ñd|=fĂŤ-cI0ĂąL¢kÖêk‰Rƒ«ıÄWĂą8mO3∏&√æËXÂŻHĂł—ì]yF2»–˜ádàà‡‹Çο„≥7mÂŞHAS∑¶.;Œx(1} _kdŠ.dç48M\'Ă ĂĄÂŞCp^KrĂ­<ɉXÓıĂŻl!Ì$N<ı∞BÂťG]…∂Ó¯>˛ÔbõÒπÀ•:Ă´O<j∂™œ%âÏ—>@È$pÖu‹Ê´-QqV ?V≥JÆÍqÛX8(lπï@zgÖ}Fe<ˇ‡Sñ“ÿ˜ê?6‡L∍Oß~Âľ –?ËeäÚ®YîÕ =Ü=¢DÁu*GvBk;)LÂŹNÂŤĂŽ:flö∂≠ÇΩq„Ñm하Ë∂‚"û≥§:±≤i^ΩÑ!)WĹyŧĂ´ á„„áÒĂ´€™â‰ â€”„˘rĹ‚PdĂŞĂŁh˘ßHVç5ȂŹĂ§ĂŒĂ›§Ă–/M=gĂŤ¾¹ÿGĂť1coÔuñæ‘zÂŽ. õ∑7ÉÏÜÆ,°’€ ĂĂ‰ĂŒâˆ‚7e º® íˆ⁄◊øNWK”ÂYµ‚ñé;¾œgV-fl>ÂľtË¥áßN2 ÂŻÂśBaP-)eW.Ă Ă´t^∏1›C∑Ö?€ž&”5’4jvã–ªZ á+4% ´0€ŚÂťĂş^°´Š Ýiπ∑é®óܱÒÿ‰ïˆÌ–†â—ŠĂ†19rQ=Í|ı•rMĂŚÂŹ;ò‰€°ĂŠ9.” ‹˝V«ã¯∏,+ĂŤÂŽj*¥¡/';
  422. $model = new AppModel(array('name' => 'BinaryTest', 'ds' => 'test'));
  423. $model->save(compact('data'));
  424. $result = $model->find('first');
  425. $this->assertEquals($result['BinaryTest']['data'], $data);
  426. }
  427. /**
  428. * Tests the syntax of generated schema indexes
  429. *
  430. * @return void
  431. */
  432. public function testSchemaIndexSyntax() {
  433. $schema = new CakeSchema();
  434. $schema->tables = array('i18n' => array(
  435. 'id' => array(
  436. 'type' => 'integer', 'null' => false, 'default' => null,
  437. 'length' => 10, 'key' => 'primary'
  438. ),
  439. 'locale' => array('type' => 'string', 'null' => false, 'length' => 6, 'key' => 'index'),
  440. 'model' => array('type' => 'string', 'null' => false, 'key' => 'index'),
  441. 'foreign_key' => array(
  442. 'type' => 'integer', 'null' => false, 'length' => 10, 'key' => 'index'
  443. ),
  444. 'field' => array('type' => 'string', 'null' => false, 'key' => 'index'),
  445. 'content' => array('type' => 'text', 'null' => true, 'default' => null),
  446. 'indexes' => array(
  447. 'PRIMARY' => array('column' => 'id', 'unique' => 1),
  448. 'locale' => array('column' => 'locale', 'unique' => 0),
  449. 'model' => array('column' => 'model', 'unique' => 0),
  450. 'row_id' => array('column' => 'foreign_key', 'unique' => 0),
  451. 'field' => array('column' => 'field', 'unique' => 0)
  452. )
  453. ));
  454. $result = $this->Dbo->createSchema($schema);
  455. $this->assertNotRegExp('/^CREATE INDEX(.+);,$/', $result);
  456. }
  457. /**
  458. * testCakeSchema method
  459. *
  460. * Test that schema generated postgresql queries are valid. ref #5696
  461. * Check that the create statement for a schema generated table is the same as the original sql
  462. *
  463. * @return void
  464. */
  465. public function testCakeSchema() {
  466. $db1 = ConnectionManager::getDataSource('test');
  467. $db1->cacheSources = false;
  468. $db1->rawQuery('CREATE TABLE ' . $db1->fullTableName('datatype_tests') . ' (
  469. id serial NOT NULL,
  470. "varchar" character varying(40) NOT NULL,
  471. "full_length" character varying NOT NULL,
  472. "timestamp" timestamp without time zone,
  473. "date" date,
  474. CONSTRAINT test_data_types_pkey PRIMARY KEY (id)
  475. )');
  476. $model = new Model(array('name' => 'DatatypeTest', 'ds' => 'test'));
  477. $schema = new CakeSchema(array('connection' => 'test'));
  478. $result = $schema->read(array(
  479. 'connection' => 'test',
  480. 'models' => array('DatatypeTest')
  481. ));
  482. $schema->tables = array('datatype_tests' => $result['tables']['missing']['datatype_tests']);
  483. $result = $db1->createSchema($schema, 'datatype_tests');
  484. $this->assertNotRegExp('/timestamp DEFAULT/', $result);
  485. $this->assertRegExp('/\"full_length\"\s*text\s.*,/', $result);
  486. $this->assertRegExp('/timestamp\s*,/', $result);
  487. $db1->query('DROP TABLE ' . $db1->fullTableName('datatype_tests'));
  488. $db1->query($result);
  489. $result2 = $schema->read(array(
  490. 'connection' => 'test',
  491. 'models' => array('DatatypeTest')
  492. ));
  493. $schema->tables = array('datatype_tests' => $result2['tables']['missing']['datatype_tests']);
  494. $result2 = $db1->createSchema($schema, 'datatype_tests');
  495. $this->assertEquals($result, $result2);
  496. $db1->query('DROP TABLE ' . $db1->fullTableName('datatype_tests'));
  497. }
  498. /**
  499. * Test index generation from table info.
  500. *
  501. * @return void
  502. */
  503. public function testIndexGeneration() {
  504. $name = $this->Dbo->fullTableName('index_test', false);
  505. $this->Dbo->query('CREATE TABLE ' . $name . ' ("id" serial NOT NULL PRIMARY KEY, "bool" integer, "small_char" varchar(50), "description" varchar(40) )');
  506. $this->Dbo->query('CREATE INDEX pointless_bool ON ' . $name . '("bool")');
  507. $this->Dbo->query('CREATE UNIQUE INDEX char_index ON ' . $name . '("small_char")');
  508. $expected = array(
  509. 'PRIMARY' => array('unique' => true, 'column' => 'id'),
  510. 'pointless_bool' => array('unique' => false, 'column' => 'bool'),
  511. 'char_index' => array('unique' => true, 'column' => 'small_char'),
  512. );
  513. $result = $this->Dbo->index($name);
  514. $this->Dbo->query('DROP TABLE ' . $name);
  515. $this->assertEquals($expected, $result);
  516. $name = $this->Dbo->fullTableName('index_test_2', false);
  517. $this->Dbo->query('CREATE TABLE ' . $name . ' ("id" serial NOT NULL PRIMARY KEY, "bool" integer, "small_char" varchar(50), "description" varchar(40) )');
  518. $this->Dbo->query('CREATE UNIQUE INDEX multi_col ON ' . $name . '("small_char", "bool")');
  519. $expected = array(
  520. 'PRIMARY' => array('unique' => true, 'column' => 'id'),
  521. 'multi_col' => array('unique' => true, 'column' => array('small_char', 'bool')),
  522. );
  523. $result = $this->Dbo->index($name);
  524. $this->Dbo->query('DROP TABLE ' . $name);
  525. $this->assertEquals($expected, $result);
  526. }
  527. /**
  528. * Test the alterSchema capabilities of postgres
  529. *
  530. * @return void
  531. */
  532. public function testAlterSchema() {
  533. $Old = new CakeSchema(array(
  534. 'connection' => 'test',
  535. 'name' => 'AlterPosts',
  536. 'alter_posts' => array(
  537. 'id' => array('type' => 'integer', 'key' => 'primary'),
  538. 'author_id' => array('type' => 'integer', 'null' => false),
  539. 'title' => array('type' => 'string', 'null' => true),
  540. 'body' => array('type' => 'text'),
  541. 'published' => array('type' => 'string', 'length' => 1, 'default' => 'N'),
  542. 'created' => array('type' => 'datetime'),
  543. 'updated' => array('type' => 'datetime'),
  544. )
  545. ));
  546. $this->Dbo->query($this->Dbo->createSchema($Old));
  547. $New = new CakeSchema(array(
  548. 'connection' => 'test',
  549. 'name' => 'AlterPosts',
  550. 'alter_posts' => array(
  551. 'id' => array('type' => 'integer', 'key' => 'primary'),
  552. 'author_id' => array('type' => 'integer', 'null' => true),
  553. 'title' => array('type' => 'string', 'null' => false, 'default' => 'my title'),
  554. 'body' => array('type' => 'string', 'length' => 500),
  555. 'status' => array('type' => 'integer', 'length' => 3, 'default' => 1),
  556. 'created' => array('type' => 'datetime'),
  557. 'updated' => array('type' => 'datetime'),
  558. )
  559. ));
  560. $this->Dbo->query($this->Dbo->alterSchema($New->compare($Old), 'alter_posts'));
  561. $model = new CakeTestModel(array('table' => 'alter_posts', 'ds' => 'test'));
  562. $result = $model->schema();
  563. $this->assertTrue(isset($result['status']));
  564. $this->assertFalse(isset($result['published']));
  565. $this->assertEquals($result['body']['type'], 'string');
  566. $this->assertEquals($result['status']['default'], 1);
  567. $this->assertEquals($result['author_id']['null'], true);
  568. $this->assertEquals($result['title']['null'], false);
  569. $this->Dbo->query($this->Dbo->dropSchema($New));
  570. $New = new CakeSchema(array(
  571. 'connection' => 'test_suite',
  572. 'name' => 'AlterPosts',
  573. 'alter_posts' => array(
  574. 'id' => array('type' => 'string', 'length' => 36, 'key' => 'primary'),
  575. 'author_id' => array('type' => 'integer', 'null' => false),
  576. 'title' => array('type' => 'string', 'null' => true),
  577. 'body' => array('type' => 'text'),
  578. 'published' => array('type' => 'string', 'length' => 1, 'default' => 'N'),
  579. 'created' => array('type' => 'datetime'),
  580. 'updated' => array('type' => 'datetime'),
  581. )
  582. ));
  583. $result = $this->Dbo->alterSchema($New->compare($Old), 'alter_posts');
  584. $this->assertNotRegExp('/varchar\(36\) NOT NULL/i', $result);
  585. }
  586. /**
  587. * Test the alter index capabilities of postgres
  588. *
  589. * @return void
  590. */
  591. public function testAlterIndexes() {
  592. $this->Dbo->cacheSources = false;
  593. $schema1 = new CakeSchema(array(
  594. 'name' => 'AlterTest1',
  595. 'connection' => 'test',
  596. 'altertest' => array(
  597. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0),
  598. 'name' => array('type' => 'string', 'null' => false, 'length' => 50),
  599. 'group1' => array('type' => 'integer', 'null' => true),
  600. 'group2' => array('type' => 'integer', 'null' => true)
  601. )
  602. ));
  603. $this->Dbo->rawQuery($this->Dbo->createSchema($schema1));
  604. $schema2 = new CakeSchema(array(
  605. 'name' => 'AlterTest2',
  606. 'connection' => 'test',
  607. 'altertest' => array(
  608. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0),
  609. 'name' => array('type' => 'string', 'null' => false, 'length' => 50),
  610. 'group1' => array('type' => 'integer', 'null' => true),
  611. 'group2' => array('type' => 'integer', 'null' => true),
  612. 'indexes' => array(
  613. 'name_idx' => array('unique' => false, 'column' => 'name'),
  614. 'group_idx' => array('unique' => false, 'column' => 'group1'),
  615. 'compound_idx' => array('unique' => false, 'column' => array('group1', 'group2')),
  616. 'PRIMARY' => array('unique' => true, 'column' => 'id')
  617. )
  618. )
  619. ));
  620. $this->Dbo->query($this->Dbo->alterSchema($schema2->compare($schema1)));
  621. $indexes = $this->Dbo->index('altertest');
  622. $this->assertEquals($schema2->tables['altertest']['indexes'], $indexes);
  623. // Change three indexes, delete one and add another one
  624. $schema3 = new CakeSchema(array(
  625. 'name' => 'AlterTest3',
  626. 'connection' => 'test',
  627. 'altertest' => array(
  628. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0),
  629. 'name' => array('type' => 'string', 'null' => false, 'length' => 50),
  630. 'group1' => array('type' => 'integer', 'null' => true),
  631. 'group2' => array('type' => 'integer', 'null' => true),
  632. 'indexes' => array(
  633. 'name_idx' => array('unique' => true, 'column' => 'name'),
  634. 'group_idx' => array('unique' => false, 'column' => 'group2'),
  635. 'compound_idx' => array('unique' => false, 'column' => array('group2', 'group1')),
  636. 'another_idx' => array('unique' => false, 'column' => array('group1', 'name')))
  637. )));
  638. $this->Dbo->query($this->Dbo->alterSchema($schema3->compare($schema2)));
  639. $indexes = $this->Dbo->index('altertest');
  640. $this->assertEquals($schema3->tables['altertest']['indexes'], $indexes);
  641. // Compare us to ourself.
  642. $this->assertEquals($schema3->compare($schema3), array());
  643. // Drop the indexes
  644. $this->Dbo->query($this->Dbo->alterSchema($schema1->compare($schema3)));
  645. $indexes = $this->Dbo->index('altertest');
  646. $this->assertEquals(array(), $indexes);
  647. $this->Dbo->query($this->Dbo->dropSchema($schema1));
  648. }
  649. /*
  650. * Test it is possible to use virtual field with postgresql
  651. *
  652. * @return void
  653. */
  654. public function testVirtualFields() {
  655. $this->loadFixtures('Article', 'Comment', 'User', 'Attachment', 'Tag', 'ArticlesTag');
  656. $Article = new Article;
  657. $Article->virtualFields = array(
  658. 'next_id' => 'Article.id + 1',
  659. 'complex' => 'Article.title || Article.body',
  660. 'functional' => 'COALESCE(User.user, Article.title)',
  661. 'subquery' => 'SELECT count(*) FROM ' . $Article->Comment->table
  662. );
  663. $result = $Article->find('first');
  664. $this->assertEquals($result['Article']['next_id'], 2);
  665. $this->assertEquals($result['Article']['complex'], $result['Article']['title'] . $result['Article']['body']);
  666. $this->assertEquals($result['Article']['functional'], $result['User']['user']);
  667. $this->assertEquals($result['Article']['subquery'], 6);
  668. }
  669. /**
  670. * Test that virtual fields work with SQL constants
  671. *
  672. * @return void
  673. */
  674. function testVirtualFieldAsAConstant() {
  675. $this->loadFixtures('Article', 'Comment');
  676. $Article =& ClassRegistry::init('Article');
  677. $Article->virtualFields = array(
  678. 'empty' => "NULL",
  679. 'number' => 43,
  680. 'truth' => 'TRUE'
  681. );
  682. $result = $Article->find('first');
  683. $this->assertNull($result['Article']['empty']);
  684. $this->assertTrue($result['Article']['truth']);
  685. $this->assertEquals(43, $result['Article']['number']);
  686. }
  687. /**
  688. * Tests additional order options for postgres
  689. *
  690. * @return void
  691. */
  692. public function testOrderAdditionalParams() {
  693. $result = $this->Dbo->order(array('title' => 'DESC NULLS FIRST', 'body' => 'DESC'));
  694. $expected = ' ORDER BY "title" DESC NULLS FIRST, "body" DESC';
  695. $this->assertEquals($expected, $result);
  696. }
  697. /**
  698. * Test it is possible to do a SELECT COUNT(DISTINCT Model.field) query in postgres and it gets correctly quoted
  699. */
  700. public function testQuoteDistinctInFunction() {
  701. $this->loadFixtures('Article');
  702. $Article = new Article;
  703. $result = $this->Dbo->fields($Article, null, array('COUNT(DISTINCT Article.id)'));
  704. $expected = array('COUNT(DISTINCT "Article"."id")');
  705. $this->assertEquals($expected, $result);
  706. $result = $this->Dbo->fields($Article, null, array('COUNT(DISTINCT id)'));
  707. $expected = array('COUNT(DISTINCT "id")');
  708. $this->assertEquals($expected, $result);
  709. $result = $this->Dbo->fields($Article, null, array('COUNT(DISTINCT FUNC(id))'));
  710. $expected = array('COUNT(DISTINCT FUNC("id"))');
  711. $this->assertEquals($expected, $result);
  712. }
  713. /**
  714. * test that saveAll works even with conditions that lack a model name.
  715. *
  716. * @return void
  717. */
  718. public function testUpdateAllWithNonQualifiedConditions() {
  719. $this->loadFixtures('Article');
  720. $Article = new Article();
  721. $result = $Article->updateAll(array('title' => "'Awesome'"), array('title' => 'Third Article'));
  722. $this->assertTrue($result);
  723. $result = $Article->find('count', array(
  724. 'conditions' => array('Article.title' => 'Awesome')
  725. ));
  726. $this->assertEquals($result, 1, 'Article count is wrong or fixture has changed.');
  727. }
  728. /**
  729. * test alterSchema on two tables.
  730. *
  731. * @return void
  732. */
  733. public function testAlteringTwoTables() {
  734. $schema1 = new CakeSchema(array(
  735. 'name' => 'AlterTest1',
  736. 'connection' => 'test',
  737. 'altertest' => array(
  738. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0),
  739. 'name' => array('type' => 'string', 'null' => false, 'length' => 50),
  740. ),
  741. 'other_table' => array(
  742. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0),
  743. 'name' => array('type' => 'string', 'null' => false, 'length' => 50),
  744. )
  745. ));
  746. $schema2 = new CakeSchema(array(
  747. 'name' => 'AlterTest1',
  748. 'connection' => 'test',
  749. 'altertest' => array(
  750. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0),
  751. 'field_two' => array('type' => 'string', 'null' => false, 'length' => 50),
  752. ),
  753. 'other_table' => array(
  754. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0),
  755. 'field_two' => array('type' => 'string', 'null' => false, 'length' => 50),
  756. )
  757. ));
  758. $result = $this->db->alterSchema($schema2->compare($schema1));
  759. $this->assertEquals(2, substr_count($result, 'field_two'), 'Too many fields');
  760. $this->assertFalse(strpos(';ALTER', $result), 'Too many semi colons');
  761. }
  762. /**
  763. * test encoding setting.
  764. *
  765. * @return void
  766. */
  767. public function testEncoding() {
  768. $result = $this->Dbo->setEncoding('utf8');
  769. $this->assertTrue($result) ;
  770. $result = $this->Dbo->getEncoding();
  771. $this->assertEquals('utf8', $result) ;
  772. $result = $this->Dbo->setEncoding('EUC-JP');
  773. $this->assertTrue($result) ;
  774. $result = $this->Dbo->getEncoding();
  775. $this->assertEquals('EUC-JP', $result) ;
  776. }
  777. }