PageRenderTime 61ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/Pomm/Test/Converter/ConverterTest.php

https://github.com/atstudy007/Pomm
PHP | 861 lines | 706 code | 131 blank | 24 comment | 12 complexity | 171b81ce7d22d9a08400955c1bf3b196 MD5 | raw file
  1. <?php
  2. namespace Pomm\Test\Converter;
  3. use Pomm\Connection\Database;
  4. use Pomm\Object\BaseObject;
  5. use Pomm\Object\BaseObjectMap;
  6. use Pomm\Exception\Exception;
  7. use Pomm\Exception\SqlException;
  8. use Pomm\Converter;
  9. use Pomm\Type;
  10. use Pomm\Type\RangeType;
  11. class ConverterTest extends \PHPUnit_Framework_TestCase
  12. {
  13. protected static $cv_map;
  14. protected static $super_cv_map;
  15. protected static $logger;
  16. protected static $connection;
  17. public static function setUpBeforeClass()
  18. {
  19. $database = new Database(array('dsn' => $GLOBALS['dsn'], 'name' => 'test_db'));
  20. static::$connection = $database->getConnection();
  21. static::$connection->begin();
  22. try
  23. {
  24. $sql = 'CREATE SCHEMA pomm_test';
  25. static::$connection->executeAnonymousQuery($sql);
  26. static::$cv_map = static::$connection->getMapFor('Pomm\Test\Converter\ConverterEntity');
  27. static::$cv_map->createTable();
  28. static::$super_cv_map = static::$connection->getMapFor('Pomm\Test\Converter\SuperConverterEntity');
  29. static::$super_cv_map->createTable(static::$cv_map);
  30. static::$connection->commit();
  31. }
  32. catch (Exception $e)
  33. {
  34. static::$connection->rollback();
  35. throw $e;
  36. }
  37. }
  38. public static function tearDownAfterClass()
  39. {
  40. $sql = 'DROP SCHEMA pomm_test CASCADE';
  41. static::$connection->executeAnonymousQuery($sql);
  42. }
  43. public function testInteger()
  44. {
  45. $entity = static::$cv_map->createObject(array('id' => 1, 'fixed' => 12.345, 'fl' => 0.000001, 'arr_fl' => array(1.0,1.1,1.2,1.3), 'not_null_string' => ''));
  46. static::$cv_map->saveOne($entity);
  47. $this->assertEquals(1, $entity['id'], "PHP int 1 <=> PG int 1");
  48. $this->assertEquals(12.345, $entity['fixed'], "PHP 12.345 <=> PG 12.345 numeric");
  49. $this->assertEquals(0.000001, $entity['fl'], "PHP 0.000001 <=> PG 1e-6");
  50. $this->assertEquals(array(1.0, 1.1, 1.2, 1.3), $entity['arr_fl'], "Float array is preserved.");
  51. $entity['fixed'] = 0.0001;
  52. $entity['fl'] = 1000000.000001;
  53. $entity['arr_fl'] = array(1.0, 1.1, null, 1.3);
  54. static::$cv_map->saveOne($entity);
  55. $this->assertEquals(0.000, $entity['fixed'], "PHP 0.0001 <=> PG 0.000 numeric");
  56. $this->assertEquals(1000000, $entity['fl'], "PHP 1000000.000001 <=> PG 1e+6");
  57. $this->assertEquals(array(1.0, 1.1, null, 1.3), $entity['arr_fl'], "Float array preserves null.");
  58. }
  59. /**
  60. * @depends testInteger
  61. **/
  62. public function testString()
  63. {
  64. static::$cv_map->alterText();
  65. $entity = static::$cv_map->findAll()->current();
  66. $values = array('some_char' => 'abcdefghij', 'some_varchar' => '1234567890 abcdefghij', 'some_text' => 'Lorem Ipsum', 'arr_varchar' => array('pika', '{"a","b b \'c"}'));
  67. $entity->hydrate($values);
  68. static::$cv_map->updateOne($entity, array_keys($values));
  69. $this->assertEquals('abcdefghij', $entity['some_char'], "Chars are ok.");
  70. $this->assertEquals('1234567890 abcdefghij', $entity['some_varchar'], "Varchars are ok.");
  71. $this->assertEquals('Lorem Ipsum', $entity['some_text'], "Text is ok.");
  72. $this->assertEquals(array('pika', '{"a","b b \'c"}'), $entity['arr_varchar'], "Varchar arrays are ok.");
  73. $entity['some_char'] = 'a b';
  74. $entity['some_varchar'] = '&"\'-- =+_-;\\?,{}[]()';
  75. $entity['some_text'] = '';
  76. $entity['arr_varchar'] = array(null, '123', null, '', null, 'abc');
  77. static::$cv_map->updateOne($entity, array_keys($values));
  78. $this->assertEquals('a b', $entity['some_char'], "Chars' length is kept.");
  79. $this->assertEquals('&"\'-- =+_-;\?,{}[]()', $entity['some_varchar'], "Non alpha is escaped.");
  80. $this->assertEquals('', $entity['some_text'], "Empty strings are ok.");
  81. $this->assertEquals(array(null, '123', null, '', null, 'abc'), $entity['arr_varchar'], "Char arrays can contain nulls and emtpy strings.");
  82. if (static::$cv_map->alterJson() !== false)
  83. {
  84. $some_json = array('pika' => 'chu', 'lot of' => array(1, 2, 3, 4, 5), 'weird chain' => 'foo\'s as "fool"');
  85. $entity['some_json'] = $some_json;
  86. $entity['arr_json'] = array($some_json, $some_json);
  87. static::$cv_map->updateOne($entity, array('some_json', 'arr_json'));
  88. $this->assertEquals($some_json, $entity['some_json'], "Json type is kept unchanged.");
  89. $this->assertEquals(array($some_json, $some_json), $entity['arr_json'], "Array of Json types is kept unchanged.");
  90. }
  91. else
  92. {
  93. $this->markTestSkipped("Json type is supported since postgresql 9.2. Test skipped.");
  94. }
  95. $entity['some_char'] = null;
  96. static::$cv_map->saveOne($entity);
  97. $this->assertTrue(is_null($entity['some_char']), "Strings NULL are preserved.");
  98. return $entity;
  99. }
  100. /**
  101. * @depends testInteger
  102. **/
  103. public function testDate()
  104. {
  105. static::$cv_map->alterDate();
  106. $entity = static::$cv_map->findAll()->current();
  107. $values = array(
  108. 'some_ts' => '2012-06-20 18:34:16.640044+10',
  109. 'some_intv' => '37 years 3 months 7 days 2 hours 14 minutes 46 seconds',
  110. 'arr_ts' => array('2015-06-08 03:54:08.880287', '1994-12-16 21:23:50.224208', '1941-02-18 17:29:52.216309')
  111. );
  112. $entity->hydrate($values);
  113. static::$cv_map->saveOne($entity);
  114. $this->assertInstanceOf('\DateTime', $entity['some_ts'], "'some_ts' is a \DateTime instance.");
  115. $entity['some_ts']->setTimeZone(new \DateTimeZone('Etc/GMT0'));
  116. $this->assertEquals( '2012-06-20 08:34:16.640044+00:00', $entity['some_ts']->format('Y-m-d H:i:s.uP'), "Timestamp is preserved.");
  117. $this->assertInstanceOf('\DateInterval', $entity['some_intv'], "'some_intv' is a \DateInterval instance.");
  118. $this->assertEquals('37 years 3 mons 7 days 02:14:46', $entity['some_intv']->format("%y years %m mons %d days %H:%i:%s"), "'some_intv' is '37 years 3 mons 7 days 02:14:46'.");
  119. $this->assertEquals(3, count($entity['arr_ts']), "'arr_ts' is an array of 3 elements.");
  120. $this->assertInstanceOf('\DateTime', $entity['arr_ts'][2], "Third element of 'arr_ts' is a DateTime instance.");
  121. $this->assertEquals('1941-02-18 17:29:52.216309', $entity['arr_ts'][2]->format('Y-m-d H:i:s.u'), "Array timestamp is preserved.");
  122. $entity['arr_ts'] = array('2015-06-08 03:54:08.880287', null, '1941-02-18 17:29:52.216309');
  123. static::$cv_map->updateOne($entity, array('arr_ts'));
  124. $this->assertEquals(3, count($entity['arr_ts']), "'arr_ts' is an array of 3 elements.");
  125. $this->assertTrue(is_null($entity['arr_ts'][1]), "Second element of 'arr_ts' is null.");
  126. return $entity;
  127. }
  128. /**
  129. * @depends testInteger
  130. **/
  131. public function testBool()
  132. {
  133. static::$cv_map->alterBool();
  134. $entity = static::$cv_map->findAll()->current();
  135. $values = array('some_bool' => true, 'arr_bool' => array(true, false, true));
  136. $entity->hydrate($values);
  137. static::$cv_map->saveOne($entity);
  138. $this->assertTrue($entity['some_bool'], "'some_bool' is boolean and TRUE.");
  139. $this->assertEquals(3, count($entity['arr_bool']), "'arr_bool' is an array of 3 elements.");
  140. $this->assertFalse($entity['arr_bool'][1], "Second element of 'arr_bool' is FALSE.");
  141. $entity['arr_bool'] = array(true, false, null, false, null, null);
  142. static::$cv_map->updateOne($entity, array('arr_bool'));
  143. $this->assertEquals(6, count($entity['arr_bool']), "'arr_bool' is 6 elements array.");
  144. $this->assertTrue(is_null($entity['arr_bool'][2]), "3th element is NULL.");
  145. $this->assertFalse($entity['arr_bool'][3], "4th element is FALSE.");
  146. $this->assertTrue(is_null($entity['arr_bool'][4]), "5th element is NULL.");
  147. $this->assertTrue(is_null($entity['arr_bool'][5]), "6th element is NULL.");
  148. return $entity;
  149. }
  150. /**
  151. * @depends testInteger
  152. **/
  153. public function testBinary()
  154. {
  155. static::$cv_map->alterBinary();
  156. $entity = static::$cv_map->findAll()->current();
  157. $binary = chr(0).chr(27).chr(92).chr(39).chr(32).chr(13);
  158. $base64 = <<<_
  159. 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
  160. _;
  161. $values = array('some_bin' => $binary, 'arr_bin' => array($binary, base64_decode($base64)));
  162. $entity->hydrate($values);
  163. static::$cv_map->saveOne($entity);
  164. $this->assertEquals(strlen($binary), strlen($entity['some_bin']), "Binary strings have same length.");
  165. $this->assertEquals(base64_encode($binary), base64_encode($entity['some_bin']), "Small 'some_bin' is preserved.");
  166. $this->assertEquals(2, count($entity['arr_bin']), "The array has 2 elements.");
  167. $this->assertEquals($binary, $entity['arr_bin'][0], "First value in the array is preserved.");
  168. $this->assertEquals($base64, base64_encode($entity['arr_bin'][1]), "Second value in the array is preserved.");
  169. $entity['some_bin'] = base64_decode($base64);
  170. static::$cv_map->updateOne($entity, array('some_bin'));
  171. $this->assertEquals($base64, base64_encode($entity['some_bin']), "Image is preserved.");
  172. return $entity;
  173. }
  174. /**
  175. * @depends testInteger
  176. **/
  177. public function testPoint()
  178. {
  179. static::$cv_map->alterPoint();
  180. $entity = static::$cv_map->findAll()->current();
  181. $values = array(
  182. 'some_point' => new Type\Point(47.21262, -1.55516),
  183. 'arr_point' => array(new Type\Point(6.431264, 3.424915), new Type\Point(-33.969043, 151.187225))
  184. );
  185. $entity->hydrate($values);
  186. static::$cv_map->saveOne($entity);
  187. $this->assertInstanceOf('\Pomm\Type\Point', $entity['some_point'], "'some_point' is a Point instance.");
  188. $this->assertEquals(47.21262, $entity['some_point']->x, "X coordinate is preserved.");
  189. $this->assertEquals(-1.55516, $entity['some_point']->y, "Y coordinate is preserved.");
  190. $this->assertTrue(is_array($entity['arr_point']), "'arr_point' is an array.");
  191. $this->assertEquals(2, count($entity['arr_point']), "Containing 2 elements.");
  192. $this->assertEquals(-33.969043, $entity['arr_point'][1]->x, "X of the 2nd element is preserved.");
  193. $this->assertEquals(151.187225, $entity['arr_point'][1]->y, "Y of the 2nd element is preserved.");
  194. $entity['arr_point'] = array(null, $entity['arr_point'][1], null, $entity['arr_point'][0], null);
  195. $entity['some_point'] = new Type\Point(0.12345E9, -9.87654E-9);
  196. static::$cv_map->updateOne($entity, array('arr_point', 'some_point'));
  197. $this->assertEquals(123450000, $entity['some_point']->x, "X coordinate is preserved.");
  198. $this->assertEquals(-9.87654E-9, $entity['some_point']->y, "Y coordinate is preserved.");
  199. $this->assertTrue(is_array($entity['arr_point']), "'arr_point' is an array.");
  200. $this->assertEquals(5, count($entity['arr_point']), "Containing 5 elements.");
  201. $this->assertTrue(is_null($entity['arr_point'][2]), '3rd element is null');
  202. $this->assertTrue(is_null($entity['arr_point'][4]), '5th element is null');
  203. $this->assertInstanceOf('\Pomm\Type\Point', $entity['arr_point'][1], "2nd element is a Point instance.");
  204. return $entity;
  205. }
  206. /**
  207. * @depends testInteger
  208. **/
  209. public function testCircle()
  210. {
  211. static::$cv_map->alterCircle();
  212. $entity = static::$cv_map->findAll()->current();
  213. $values = array(
  214. 'some_circle' => new Type\Circle(new Type\Point(0.1234E9,-2), 10),
  215. 'arr_circle' => array(new Type\Circle(new Type\Point(2,-2), 10), new Type\Circle(new Type\Point(0,0), 1))
  216. );
  217. $entity->hydrate($values);
  218. static::$cv_map->saveOne($entity);
  219. $this->assertInstanceOf('\Pomm\Type\Circle', $entity['some_circle'], "'some_circle' is a Circle type.");
  220. $this->assertInstanceOf('\Pomm\Type\Point', $entity['some_circle']->center, "'some_circle' center is a type Point.");
  221. $this->assertEquals(10, $entity['some_circle']->radius, "'some_circle' radius is preserved.");
  222. $this->assertTrue(is_array($entity['arr_circle']), "'arr_circle' is an array.");
  223. $this->assertEquals(2, count($entity['arr_circle']), "Containing 2 elements.");
  224. $this->assertInstanceOf('\Pomm\Type\Circle', $entity['arr_circle'][1], "'arr_circle' 2nd element is a Circle type.");
  225. $this->assertInstanceOf('\Pomm\Type\Point', $entity['arr_circle'][1]->center, "'arr_circle' 2nd element's center is a type Point.");
  226. $this->assertEquals(1, $entity['arr_circle'][1]->radius, "'arr_circle' 2nd element's radius is preserved.");
  227. $entity['arr_circle'] = array(null, $entity['arr_circle'][0], null, $entity['arr_circle'][1], null);
  228. static::$cv_map->updateOne($entity, array('arr_circle'));
  229. $this->assertTrue(is_array($entity['arr_circle']), "'arr_circle' is an array.");
  230. $this->assertEquals(5, count($entity['arr_circle']), "Containing 5 elements.");
  231. $this->assertInstanceOf('\Pomm\Type\Circle', $entity['arr_circle'][1], "'arr_circle' 2nd element is a Circle type.");
  232. $this->assertTrue(is_null($entity['arr_circle'][2]), '3rd element is null');
  233. $this->assertTrue(is_null($entity['arr_circle'][4]), '5rd element is null');
  234. return $entity;
  235. }
  236. /**
  237. * @depends testInteger
  238. **/
  239. public function testSegment()
  240. {
  241. static::$cv_map->alterSegment();
  242. $entity = static::$cv_map->findAll()->current();
  243. $values = array(
  244. 'some_lseg' => new Type\Segment(new Type\Point(0.1234E9,-2), new Type\Point(10, -10)),
  245. 'arr_lseg' => array(new Type\Segment(new Type\Point(2,-2), new Type\Point(0,0)), new Type\Segment(new Type\Point(2,-2), new Type\Point(1000,-1000))),
  246. );
  247. $entity->hydrate($values);
  248. static::$cv_map->saveOne($entity);
  249. $this->assertInstanceOf('\Pomm\Type\Segment', $entity['some_lseg'], "'some_lseg' is a lseg type.");
  250. $this->assertInstanceOf('\Pomm\Type\Point', $entity['some_lseg']->point_a, "'some_lseg' point_a is a type Point.");
  251. $this->assertInstanceOf('\Pomm\Type\Point', $entity['some_lseg']->point_b, "'some_lseg' point_b is a type Point.");
  252. $this->assertTrue(is_array($entity['arr_lseg']), "'arr_lseg' is an array.");
  253. $this->assertEquals(2, count($entity['arr_lseg']), "Containing 2 elements.");
  254. $this->assertInstanceOf('\Pomm\Type\Segment', $entity['arr_lseg'][1], "'arr_lseg' 2nd element is a lseg type.");
  255. $this->assertInstanceOf('\Pomm\Type\Point', $entity['arr_lseg'][1]->point_b, "'arr_lseg' 2nd element's point_b is a type Point.");
  256. $entity['arr_lseg'] = array(null, $entity['arr_lseg'][0], null, $entity['arr_lseg'][1], null);
  257. static::$cv_map->updateOne($entity, array('arr_lseg'));
  258. $this->assertTrue(is_array($entity['arr_lseg']), "'arr_lseg' is an array.");
  259. $this->assertEquals(5, count($entity['arr_lseg']), "Containing 5 elements.");
  260. $this->assertInstanceOf('\Pomm\Type\Segment', $entity['arr_lseg'][1], "'arr_lseg' 2nd element is a lseg type.");
  261. $this->assertTrue(is_null($entity['arr_lseg'][2]), '3rd element is null');
  262. $this->assertTrue(is_null($entity['arr_lseg'][4]), '5rd element is null');
  263. }
  264. /**
  265. * @depends testInteger
  266. **/
  267. function testHStore()
  268. {
  269. if (static::$cv_map->alterHStore() === false)
  270. {
  271. $this->markTestSkipped("HStore extension could not be found in Postgres, tests skipped.");
  272. return;
  273. }
  274. $entity = static::$cv_map->findAll()->current();
  275. $values = array('pika' => 'chu', 'plop' => null, 'grum' => '', 'quote' => '"', '"a"=>"b,a"' => '"c" => "d,a"' );
  276. $entity['some_hstore'] = $values;
  277. static::$cv_map->updateOne($entity, array('some_hstore'));
  278. $this->assertTrue(is_array($entity['some_hstore']), "'some_hstore' is an array.");
  279. $this->assertEquals($values, $entity['some_hstore'], "'some_hstore' array is preserved.");
  280. }
  281. /**
  282. * @depends testInteger
  283. **/
  284. public function testLTree()
  285. {
  286. if (static::$cv_map->alterLTree() === false)
  287. {
  288. $this->markTestSkipped("Ltree extension could not be found in Postgres, tests skipped.");
  289. return;
  290. }
  291. $entity = static::$cv_map->findAll()->current();
  292. $values = array(
  293. 'some_ltree' => array('one', 'two', 'three', 'four'),
  294. 'arr_ltree' => array(
  295. array('a', 'b', 'c', 'd'),
  296. array('a', 'b', 'e', 'f')
  297. ));
  298. $entity->hydrate($values);
  299. static::$cv_map->saveOne($entity);
  300. $this->assertTrue(is_array($entity['some_ltree']), "'some_ltree' is an array.");
  301. $this->assertEquals($values['some_ltree'], $entity['some_ltree'], "'some_ltree' is preserved.");
  302. $this->assertEquals($values['arr_ltree'][0], $entity['arr_ltree'][0], "'arr_ltree' 1st element is preserved.");
  303. $entity['arr_ltree'] = array(
  304. array(),
  305. null,
  306. $entity['arr_ltree'][0],
  307. array(),
  308. $entity['arr_ltree'][1],
  309. null);
  310. static::$cv_map->updateOne($entity, array('arr_ltree'));
  311. $this->assertEquals(array(), $entity['arr_ltree'][0], "Empty ltrees are preserved.");
  312. $this->assertTrue(is_null($entity['arr_ltree'][1]), "Nulls are preserved.");
  313. $this->assertTrue(is_array($entity['arr_ltree'][2]), "3rd element is an array.");
  314. $this->assertEquals($values['arr_ltree'][0], $entity['arr_ltree'][2], "Ltree are preserved.");
  315. $this->assertTrue(is_null($entity['arr_ltree'][5]), "5th element is null");
  316. }
  317. /**
  318. * @depends testInteger
  319. **/
  320. public function testTsRange()
  321. {
  322. if (static::$cv_map->alterTsRange() === false)
  323. {
  324. $this->markTestSkipped("tsrange type could not be found, maybe Postgres version < 9.2. Tests skipped.");
  325. return;
  326. }
  327. $entity = static::$cv_map->findAll()->current();
  328. $value = new Type\TsRange(new \DateTime('2012-08-20'), new \DateTime('2012-09-01'), RangeType::EXCL_START);
  329. $entity['some_tsrange'] = $value;
  330. static::$cv_map->updateOne($entity, array('some_tsrange'));
  331. $this->assertInstanceOf('\Pomm\Type\TsRange', $entity['some_tsrange'], "'some_tsrange' is a 'TsRange' type.");
  332. $this->assertEquals($value->start->format('U'), $entity['some_tsrange']->start->format('U'), "Timestamps are equal.");
  333. $this->assertEquals($value->options, RangeType::EXCL_START, 'Start bound is excluded.');
  334. $entity['arr_tsrange'] = array($value, new Type\TsRange(new \DateTime('2012-12-21'), new \DateTime('2012-12-21 12:21:59')));
  335. static::$cv_map->updateOne($entity, array('some_tsrange', 'arr_tsrange'));
  336. $this->assertEquals(2, count($entity['arr_tsrange']), "There are 2 elements in the array.");
  337. $this->assertInstanceOf('\Pomm\Type\TsRange', $entity['arr_tsrange'][1], "'arr_tsrange' element 1 is a 'TsRange' type.");
  338. $this->assertEquals(44519, $entity['arr_tsrange'][1]->end->format('U') - $entity['arr_tsrange'][1]->start->format('U'), "Range is preserved.");
  339. $this->assertEquals(RangeType::INCL_BOUNDS, $entity['arr_tsrange'][1]->options, 'Bounds are preserved.');
  340. return $entity;
  341. }
  342. /**
  343. * @depends testInteger
  344. **/
  345. public function testNumberRangeConverter()
  346. {
  347. if (static::$cv_map->alterNumberRange() === false)
  348. {
  349. $this->markTestSkipped("Range types could not be found, maybe Postgres version < 9.2. Tests skipped.");
  350. return;
  351. }
  352. $entity = static::$cv_map->findAll()->current();
  353. $entity['some_int4range'] = new Type\NumberRange(-5, 45, RangeType::EXCL_END);
  354. $entity['some_int8range'] = new Type\NumberRange(4452940833, 4553946490);
  355. $entity['some_numrange'] = new Type\NumberRange(29.76607095, 30.44125206, RangeType::EXCL_BOTH);
  356. $entity['arr_numrange'] = array(new Type\NumberRange(1.1, 1.2), new Type\NumberRange(2.2, 2.4, RangeType::EXCL_START), new Type\NumberRange(3.3, 3.6, RangeType::EXCL_BOTH));
  357. static::$cv_map->updateOne($entity, array('some_int8range', 'some_int4range', 'some_numrange', 'arr_numrange'));
  358. $this->assertEquals(new Type\NumberRange(-5, 45, RangeType::EXCL_END), $entity['some_int4range'], "Int4range is ok.");
  359. $this->assertEquals(new Type\NumberRange(4452940833, 4553946491, RangeType::EXCL_END), $entity->getSomeInt8range(), "Int8range is ok.");
  360. $this->assertEquals(new Type\NumberRange(29.76607095, 30.44125206, RangeType::EXCL_BOTH), $entity['some_numrange'], "Numrange is ok.");
  361. $this->assertTrue(is_array($entity['arr_numrange']), "'arr_numrange' is an array.");
  362. for($x = 1; $x <= count($entity['arr_numrange']); $x++)
  363. {
  364. $range = $entity['arr_numrange'][$x - 1];
  365. $this->assertInstanceOf('\Pomm\Type\NumberRange', $range, "Instance 'NumberRange'.");
  366. $this->assertEquals((float) $x * 1.1, $range->start, "Range start is ok.");
  367. $this->assertEquals((float) $x * 1.2, $range->end, "Range en is ok.");
  368. }
  369. }
  370. /**
  371. * @depends testInteger
  372. */
  373. public function testRowConverter()
  374. {
  375. static::$cv_map->alterComposite();
  376. $entity = static::$cv_map->findAll()->current();
  377. $test_address = new AddressType(array('place' => '11, impasse juton', 'postal_code' => '44000', 'city' => 'Nantes'));
  378. $entity['a_composite'] = $test_address;
  379. $entity['arr_composite'] = array($test_address, new AddressType(array('place' => 'Middle of nowhere', 'postal_code' => '56590', 'city' => 'Groix')));
  380. static::$cv_map->updateOne($entity, array('a_composite', 'arr_composite'));
  381. $this->assertTrue($entity['a_composite'] instanceOf \Pomm\Test\Converter\AddressType, "Composite data is an object.");
  382. $this->assertEquals((array) $test_address, (array) $entity['a_composite'], "Row is unchanged.");
  383. $this->assertEquals((array) $test_address, (array) $entity['arr_composite'][0], "Array of rows is unchanged.");
  384. }
  385. /**
  386. * @depends testInteger
  387. **/
  388. public function testSuperConverter()
  389. {
  390. $entity = static::$cv_map->findAll()->current();
  391. $super_entity = new SuperConverterEntity(array('cv_entities' => array($entity)));
  392. static::$super_cv_map->saveOne($super_entity);
  393. $this->assertTrue(is_int($super_entity['id']), "'id' has been generated.");
  394. $this->assertTrue(is_array($super_entity['cv_entities']), "'cv_entities' is an array.");
  395. $this->assertInstanceOf('Pomm\Test\Converter\ConverterEntity', $super_entity['cv_entities'][0], "'cv_entities' is an array with first value as ConverterEntity instance.");
  396. $this->assertEquals(1, $super_entity['cv_entities'][0]->get('id'), "'id' is 1.");
  397. $this->assertEquals(array(1.0, 1.1, null, 1.3), $super_entity['cv_entities'][0]->get('arr_fl'), "'arr_fl' of 'cv_entities' is preserved.");
  398. $new_entity = new ConverterEntity(array('some_point' => new Type\Point(12,-3)));
  399. $super_entity->add('cv_entities', $new_entity);
  400. static::$super_cv_map->updateOne($super_entity, array('cv_entities'));
  401. $this->assertInstanceOf('\Pomm\Type\Point', $super_entity['cv_entities'][1]['some_point'], "'some_point' of 2nd element is a Point.");
  402. $this->assertEquals(12, $super_entity['cv_entities'][1]['some_point']->x, "With x = 12");
  403. $this->assertEquals(-3, $super_entity['cv_entities'][1]['some_point']->y, "With y = -3");
  404. $this->assertTrue(is_null($super_entity['cv_entities'][1]['some_bin']), "'some_bin' is null.");
  405. }
  406. /**
  407. * @depends testInteger
  408. **/
  409. public function testTsExtendedEntity()
  410. {
  411. $ts_entity_map = static::$connection
  412. ->getMapFor('\Pomm\Test\Converter\TsEntity');
  413. $ts_entity_map->createTable();
  414. $ts_extended_entity_map = static::$connection
  415. ->getMapFor('\Pomm\Test\Converter\TsExtendedEntity');
  416. $ts_extended_entity_map->createTable($ts_entity_map);
  417. $collection = $ts_extended_entity_map->findAll();
  418. $ts_extended_entity = $collection->current();
  419. $this->assertInstanceOf('\Pomm\Test\Converter\TsEntity', $ts_extended_entity['p1'], "'p1' is a TsEntity instance.");
  420. $this->assertEquals('2000-02-29', $ts_extended_entity['p1']['p1']->format('Y-m-d'), 'Timestamp is preserved.');
  421. foreach (array('1999-12-31 23:59:59.999999', '2005-01-29 23:01:58.000000') AS $key => $ts)
  422. {
  423. $this->assertEquals($ts, $ts_extended_entity['p2'][$key]['p1']->format('Y-m-d H:i:s.u'), 'Timestamp array is preserved.');
  424. }
  425. $ts_over_extended_entity_map = static::$connection
  426. ->getMapFor('\Pomm\Test\Converter\TsOverExtendedEntity');
  427. $ts_over_extended_entity_map->createTable($ts_extended_entity_map);
  428. $collection = $ts_over_extended_entity_map->findAll();
  429. $ts_over_extended_entity = $collection->current();
  430. $this->assertInstanceOf('\Pomm\Test\Converter\TsExtendedEntity', $ts_over_extended_entity['p1'], "'p1' is a TsExtendedEntity instance.");
  431. $this->assertTrue(is_array($ts_over_extended_entity['p2']), "'p2' is an Array.");
  432. $this->assertInstanceOf('\Pomm\Test\Converter\TsExtendedEntity', $ts_over_extended_entity['p2'][0], "Which contains TsExtendedEntity instances.");
  433. }
  434. }
  435. class ConverterEntityMap extends BaseObjectMap
  436. {
  437. protected function initialize()
  438. {
  439. $this->object_class = '\Pomm\Test\Converter\ConverterEntity';
  440. $this->object_name = 'pomm_test.cv_entity';
  441. $this->addField('id', 'int4');
  442. $this->addField('fixed', 'numeric');
  443. $this->addField('fl', 'float4');
  444. $this->addField('arr_fl', 'float4[]');
  445. $this->addField('not_null_string', 'text');
  446. $this->pk_fields = array('id');
  447. }
  448. public function createTable()
  449. {
  450. $sql = sprintf("CREATE TABLE %s (id serial PRIMARY KEY, fixed numeric(5,3), fl float4, arr_fl float4[], not_null_string text NOT NULL)", $this->getTableName());
  451. $this->connection->executeAnonymousQuery($sql);
  452. }
  453. protected function alterTable(Array $fields)
  454. {
  455. $this->connection->begin();
  456. try
  457. {
  458. foreach($fields as $field => $type)
  459. {
  460. $sql = sprintf("ALTER TABLE %s ADD COLUMN %s %s", $this->getTableName(), $field, $type);
  461. if ($ret = $this->connection->executeAnonymousQuery($sql) === false)
  462. {
  463. throw new SqlException($ret, $sql);
  464. }
  465. $this->addField($field, strtok($type, '('));
  466. }
  467. $this->connection->commit();
  468. }
  469. catch(SqlException $e)
  470. {
  471. $this->connection->rollback();
  472. throw $e;
  473. }
  474. }
  475. public function checkType($type)
  476. {
  477. $sql = sprintf("SELECT pg_namespace.nspname FROM pg_type JOIN pg_namespace ON pg_type.typnamespace = pg_namespace.oid WHERE typname = '%s'", $type);
  478. $result = pg_fetch_assoc($this->connection
  479. ->executeAnonymousQuery($sql));
  480. if ($result === false)
  481. {
  482. return false;
  483. }
  484. return $result['nspname'];
  485. }
  486. public function alterText()
  487. {
  488. $this->alterTable(array('some_char' => 'char(10)', 'some_varchar' => 'varchar', 'some_text' => 'text', 'arr_varchar' => 'varchar[]'));
  489. }
  490. public function alterDate()
  491. {
  492. $this->alterTable(array('some_ts' => 'timestamptz', 'some_intv' => 'interval', 'arr_ts' => 'timestamp[]'));
  493. }
  494. public function alterBool()
  495. {
  496. $this->alterTable(array('some_bool' => 'bool', 'arr_bool' => 'bool[]'));
  497. }
  498. public function alterBinary()
  499. {
  500. $this->alterTable(array('some_bin' => 'bytea', 'arr_bin' => 'bytea[]'));
  501. }
  502. public function alterPoint()
  503. {
  504. $this->alterTable(array('some_point' => 'point', 'arr_point' => 'point[]'));
  505. $this->connection->getDatabase()
  506. ->registerConverter('Point', new Converter\PgPoint(), array('point'));
  507. }
  508. public function alterCircle()
  509. {
  510. $this->alterTable(array('some_circle' => 'circle', 'arr_circle' => 'circle[]'));
  511. $this->connection->getDatabase()
  512. ->registerConverter('Circle', new Converter\PgCircle(), array('circle'));
  513. }
  514. public function alterSegment()
  515. {
  516. $this->alterTable(array('some_lseg' => 'lseg', 'arr_lseg' => 'lseg[]'));
  517. $this->connection->getDatabase()
  518. ->registerConverter('Segment', new Converter\PgLseg(), array('lseg'));
  519. }
  520. public function alterHStore()
  521. {
  522. if ($schema = $this->checkType('hstore') === false)
  523. {
  524. return false;
  525. }
  526. $this->alterTable(array('some_hstore' => 'hstore'));
  527. $this->connection->getDatabase()
  528. ->registerConverter('HStore', new Converter\PgHStore(), array('hstore', 'public.hstore', $schema.'.hstore'));
  529. }
  530. public function alterLTree()
  531. {
  532. if ($schema = $this->checkType('ltree') === false)
  533. {
  534. return false;
  535. }
  536. $this->alterTable(array('some_ltree' => 'ltree', 'arr_ltree' => 'ltree[]'));
  537. $this->connection->getDatabase()
  538. ->registerConverter('LTree', new Converter\PgLTree(), array('ltree', 'public.ltree', $schema.'.ltree'));
  539. }
  540. public function alterTsRange()
  541. {
  542. if ($schema = $this->checkType('tsrange') === false)
  543. {
  544. return false;
  545. }
  546. $this->alterTable(array('some_tsrange' => 'tsrange', 'arr_tsrange' => 'tsrange[]'));
  547. $this->connection->getDatabase()
  548. ->registerConverter('tsrange', new Converter\PgTsRange(), array('tsrange', 'public.tsrange', $schema.'.tsrange'));
  549. }
  550. public function alterJson()
  551. {
  552. if ($schema = $this->checkType('json') === false)
  553. {
  554. return false;
  555. }
  556. $this->alterTable(array('some_json' => 'json', 'arr_json' => 'json[]'));
  557. }
  558. public function alterNumberRange()
  559. {
  560. if ($schema = $this->checkType('numrange') === false)
  561. {
  562. return false;
  563. }
  564. $this->alterTable(array('some_int4range' => 'int4range', 'some_int8range' => 'int8range', 'some_numrange' => 'numrange', 'arr_numrange' => 'numrange[]'));
  565. }
  566. public function alterComposite()
  567. {
  568. $this->connection->executeAnonymousQuery("CREATE TYPE pomm_test.address AS (place TEXT, postal_code CHAR(5), city varchar)");
  569. $this->alterTable(array('a_composite' => 'pomm_test.address', 'arr_composite' => 'pomm_test.address[]'));
  570. $this->connection->getDatabase()
  571. ->registerConverter(
  572. 'Address',
  573. new Converter\PgRow(
  574. $this->connection->getDatabase(),
  575. new \Pomm\Object\RowStructure(array('place' => 'text', 'postal_code' => 'char', 'city' => 'varchar')),
  576. '\Pomm\Test\Converter\AddressType'
  577. ),
  578. array('pomm_test.address', 'address'));
  579. }
  580. }
  581. class ConverterEntity extends BaseObject
  582. {
  583. }
  584. class SuperConverterEntityMap extends BaseObjectMap
  585. {
  586. protected function initialize()
  587. {
  588. $this->object_class = '\Pomm\Test\Converter\SuperConverterEntity';
  589. $this->object_name = 'pomm_test.super_cv_entity';
  590. $this->addField('id', 'int4');
  591. $this->addField('cv_entities', 'pomm_test.cv_entity[]');
  592. $this->pk_fields = array('id');
  593. }
  594. public function createTable(ConverterEntityMap $map)
  595. {
  596. $sql = sprintf('CREATE TABLE %s (id serial PRIMARY KEY, cv_entities pomm_test.cv_entity[])', $this->getTableName());
  597. $this->connection
  598. ->executeAnonymousQuery($sql);
  599. $this->connection
  600. ->getDatabase()
  601. ->registerConverter('ConverterEntity', new Converter\PgEntity($map), array('pomm_test.cv_entity'));
  602. }
  603. }
  604. class SuperConverterEntity extends BaseObject
  605. {
  606. }
  607. class TsEntityMap extends BaseObjectMap
  608. {
  609. protected function initialize()
  610. {
  611. $this->object_class = '\Pomm\Test\Converter\TsEntity';
  612. $this->object_name = "( VALUES ('1999-12-31 23:59:59.999999'::timestamp) ) AS ts_entity (p1)";
  613. $this->addField('p1', 'timestamp');
  614. $this->pk_fields = array();
  615. }
  616. public function createTable()
  617. {
  618. $sql = 'CREATE TYPE pomm_test.ts_entity AS (p1 timestamp)';
  619. $this->connection
  620. ->executeAnonymousQuery($sql);
  621. }
  622. }
  623. class TsEntity extends BaseObject
  624. {
  625. }
  626. class TsExtendedEntityMap extends BaseObjectMap
  627. {
  628. protected function initialize()
  629. {
  630. $this->object_class = '\Pomm\Test\Converter\TsExtendedEntity';
  631. $this->object_name = <<<SQL
  632. ( VALUES
  633. ( ROW('2000-02-29'::timestamp)::pomm_test.ts_entity, ARRAY[ROW('1999-12-31 23:59:59.999999'::timestamp)::pomm_test.ts_entity, ROW('2005-01-29 23:01:58'::timestamp)::pomm_test.ts_entity]::pomm_test.ts_entity[] ),
  634. ( ROW('2004-02-29'::timestamp)::pomm_test.ts_entity, ARRAY[ROW('1989-12-31 23:59:59.999999'::timestamp)::pomm_test.ts_entity, ROW('2005-01-29 23:01:58'::timestamp)::pomm_test.ts_entity]::pomm_test.ts_entity[] )
  635. ) ts_extended_entity (p1, p2)
  636. SQL;
  637. $this->addField('p1', 'pomm_test.ts_entity');
  638. $this->addField('p2', 'pomm_test.ts_entity[]');
  639. $this->pk_fields = array();
  640. }
  641. public function createTable(TsEntityMap $map)
  642. {
  643. $sql = 'CREATE TYPE pomm_test.ts_extended_entity AS (p1 pomm_test.ts_entity, p2 pomm_test.ts_entity[])';
  644. $this->connection
  645. ->executeAnonymousQuery($sql);
  646. $this->connection
  647. ->getDatabase()
  648. ->registerConverter('TsEntityConverter', new Converter\PgEntity($map), array('pomm_test.ts_entity', 'ts_entity'));
  649. }
  650. }
  651. class TsExtendedEntity extends BaseObject
  652. {
  653. }
  654. class TsOverExtendedEntityMap extends BaseObjectMap
  655. {
  656. protected function initialize()
  657. {
  658. $this->object_class = '\Pomm\Test\Converter\TsOverExtendedEntity';
  659. $this->object_name = <<<SQL
  660. ( VALUES
  661. ( ROW(ROW('2000-02-29'::timestamp)::pomm_test.ts_entity, ARRAY[ROW('1999-12-31 23:59:59.999999'::timestamp)::pomm_test.ts_entity, ROW('2005-01-29 23:01:58'::timestamp)::pomm_test.ts_entity]::pomm_test.ts_entity[] )::pomm_test.ts_extended_entity, ARRAY[ROW(ROW('2004-02-29'::timestamp)::pomm_test.ts_entity, ARRAY[ROW('1989-12-31 23:59:59.999999'::timestamp)::pomm_test.ts_entity, ROW('2005-01-29 23:01:58'::timestamp)::pomm_test.ts_entity]::pomm_test.ts_entity[])::pomm_test.ts_extended_entity]::pomm_test.ts_extended_entity[] )
  662. ) ts_over_extended_entity (p1, p2)
  663. SQL;
  664. $this->addField('p1', 'pomm_test.ts_extended_entity');
  665. $this->addField('p2', 'pomm_test.ts_extended_entity[]');
  666. $this->pk_fields = array();
  667. }
  668. public function createTable(TsExtendedEntityMap $map)
  669. {
  670. $sql = 'CREATE TYPE pomm_test.ts_over_extended_entity AS (p1 pomm_test.ts_extended_entity, p2 pomm_test.ts_extended_entity[])';
  671. $this->connection
  672. ->executeAnonymousQuery($sql);
  673. $this->connection
  674. ->getDatabase()
  675. ->registerConverter('TsExtendedEntityConverter', new Converter\PgEntity($map), array('pomm_test.ts_extended_entity', 'pomm_test.extended_entity'));
  676. }
  677. }
  678. class TsOverExtendedEntity extends BaseObject
  679. {
  680. }
  681. class AddressType extends \Pomm\Type\Composite
  682. {
  683. public $place;
  684. public $postal_code;
  685. public $city;
  686. public $cedex;
  687. protected $something = 'pika';
  688. }