PageRenderTime 51ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/code/ryzom/tools/server/www/webtt/cake/tests/cases/libs/model/datasources/dbo/dbo_postgres.test.php

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