PageRenderTime 41ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/core/src/test/php/net/xp_framework/unittest/rdbms/SQLFunctionTest.class.php

http://github.com/xp-framework/xp-framework
PHP | 395 lines | 337 code | 16 blank | 42 comment | 0 complexity | 167ad77349cddd1513a262e47ea87d5a MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php namespace net\xp_framework\unittest\rdbms;
  2. use unittest\TestCase;
  3. use util\Date;
  4. use rdbms\sybase\SybaseConnection;
  5. use rdbms\mysql\MySQLConnection;
  6. use rdbms\pgsql\PostgreSQLConnection;
  7. use rdbms\sqlite\SQLiteConnection;
  8. use rdbms\criterion\Restrictions;
  9. use rdbms\SQLFunctions;
  10. use net\xp_framework\unittest\rdbms\dataset\Job;
  11. /**
  12. * TestCase
  13. *
  14. * @see xp://rdbms.SQLFunction
  15. */
  16. class SQLFunctionTest extends TestCase {
  17. public
  18. $syconn = null,
  19. $myconn = null,
  20. $sqconn = null,
  21. $pgconn = null,
  22. $peer = null;
  23. /**
  24. * Sets up a Database Object for the test
  25. *
  26. */
  27. public function setUp() {
  28. $this->syconn= new SybaseConnection(new \rdbms\DSN('sybase://localhost:1999/'));
  29. $this->myconn= new MySQLConnection(new \rdbms\DSN('mysql://localhost/'));
  30. $this->pgconn= new PostgreSQLConnection(new \rdbms\DSN('pgsql://localhost/'));
  31. $this->sqconn= new SQliteConnection(new \rdbms\DSN('sqlite://tmpdir/tmpdb'));
  32. $this->peer= Job::getPeer();
  33. }
  34. /**
  35. * Helper method that will call toSQL() on the passed criteria and
  36. * compare the resulting string to the expected string.
  37. *
  38. * @param string mysql
  39. * @param string sysql
  40. * @param string pgsql
  41. * @param string sqlite
  42. * @param rdbms.Criteria criteria
  43. * @throws unittest.AssertionFailedError
  44. */
  45. protected function assertSql($mysql, $sysql, $pgsql, $sqlite, $criteria) {
  46. $this->assertEquals('mysql: '.$mysql, 'mysql: '.trim($criteria->toSQL($this->myconn, $this->peer), ' '));
  47. $this->assertEquals('sybase: '.$sysql, 'sybase: '.trim($criteria->toSQL($this->syconn, $this->peer), ' '));
  48. $this->assertEquals('pgsql: '.$pgsql, 'pgsql: '.trim($criteria->toSQL($this->pgconn, $this->peer), ' '));
  49. $this->assertEquals('sqlite: '.$sqlite, 'sqlite: '.trim($criteria->toSQL($this->sqconn, $this->peer), ' '));
  50. }
  51. /**
  52. * Helper method that will call projection() on the passed criteria and
  53. * compare the resulting string to the expected string.
  54. *
  55. * @param string mysql
  56. * @param string sysql
  57. * @param string pgsql
  58. * @param string sqlite
  59. * @param rdbms.Criteria criteria
  60. * @throws unittest.AssertionFailedError
  61. */
  62. protected function assertProjection($mysql, $sysql, $pgsql, $sqlite, $criteria) {
  63. $this->assertEquals('mysql: '.$mysql, 'mysql: '.trim($criteria->projections($this->myconn, $this->peer), ' '));
  64. $this->assertEquals('sybase: '.$sysql, 'sybase: '.trim($criteria->projections($this->syconn, $this->peer), ' '));
  65. $this->assertEquals('pgsql: '.$pgsql, 'pgsql: '.trim($criteria->projections($this->pgconn, $this->peer), ' '));
  66. $this->assertEquals('sqlite: '.$sqlite, 'sqlite: '.trim($criteria->projections($this->sqconn, $this->peer), ' '));
  67. }
  68. #[@test]
  69. function columnTest() {
  70. $this->assertEquals(
  71. 'job_id',
  72. Job::column('job_id')->getName()
  73. );
  74. }
  75. #[@test]
  76. function projectionTest() {
  77. $this->assertProjection(
  78. 'day(valid_from)',
  79. 'day(valid_from)',
  80. 'day(valid_from)',
  81. 'php(\'idate\', \'d\', php(\'strtotime\', valid_from))',
  82. create(new \rdbms\Criteria())->setProjection(SQLFunctions::day(Job::column('valid_from')))
  83. );
  84. }
  85. #[@test]
  86. function prepareProjectionTest() {
  87. $this->assertEquals(
  88. '- datepart(hour, valid_from) -',
  89. $this->syconn->prepare('- %s -', SQLFunctions::datepart('hour', Job::column('valid_from')))
  90. );
  91. $this->assertEquals(
  92. '- extract(hour from valid_from) -',
  93. $this->myconn->prepare('- %s -', SQLFunctions::datepart('hour', Job::column('valid_from')))
  94. );
  95. $this->assertEquals(
  96. '- datepart(hour, valid_from) -',
  97. $this->pgconn->prepare('- %s -', SQLFunctions::datepart('hour', Job::column('valid_from')))
  98. );
  99. $this->assertEquals(
  100. '- php(\'idate\', "H", php(\'strtotime\', valid_from)) -',
  101. $this->sqconn->prepare('- %s -', SQLFunctions::datepart('hour', Job::column('valid_from')))
  102. );
  103. }
  104. #[@test]
  105. function stringFunctionTest() {
  106. $this->assertProjection(
  107. 'ascii(\'a\') as `asciiTest`',
  108. 'ascii(\'a\') as \'asciiTest\'',
  109. 'ascii(\'a\') as "asciiTest"',
  110. 'php(\'ord\', \'a\') as \'asciiTest\'',
  111. create(new \rdbms\Criteria())->setProjection(SQLFunctions::ascii('a'), 'asciiTest')
  112. );
  113. $this->assertProjection(
  114. 'char(97)',
  115. 'char(97)',
  116. 'char(97)',
  117. 'php(\'chr\', 97)',
  118. create(new \rdbms\Criteria())->setProjection(SQLFunctions::char('97'))
  119. );
  120. $this->assertProjection(
  121. 'length(\'aaaaaaa\')',
  122. 'len(\'aaaaaaa\')',
  123. 'len(\'aaaaaaa\')',
  124. 'php(\'strlen\', \'aaaaaaa\')',
  125. create(new \rdbms\Criteria())->setProjection(SQLFunctions::len('aaaaaaa'))
  126. );
  127. $this->assertProjection(
  128. 'reverse(\'abcdefg\')',
  129. 'reverse(\'abcdefg\')',
  130. 'reverse(\'abcdefg\')',
  131. 'php(\'strrev\', \'abcdefg\')',
  132. create(new \rdbms\Criteria())->setProjection(SQLFunctions::reverse('abcdefg'))
  133. );
  134. $this->assertProjection(
  135. 'space(4)',
  136. 'space(4)',
  137. 'space(4)',
  138. 'php(\'str_repeat\', \' \', 4)',
  139. create(new \rdbms\Criteria())->setProjection(SQLFunctions::space(4))
  140. );
  141. $this->assertProjection(
  142. 'soundex(\'kawabanga\')',
  143. 'soundex(\'kawabanga\')',
  144. 'soundex(\'kawabanga\')',
  145. 'php(\'soundex\', \'kawabanga\')',
  146. create(new \rdbms\Criteria())->setProjection(SQLFunctions::soundex('kawabanga'))
  147. );
  148. }
  149. #[@test]
  150. function concatStringTest() {
  151. $this->assertProjection(
  152. 'concat(\'aa\', cast(sysdate() as char), \'cc\') as `concatTest`',
  153. '(\'aa\' + convert(varchar, getdate()) + \'cc\') as \'concatTest\'',
  154. '(\'aa\' || str(getdate()) || \'cc\') as "concatTest"',
  155. '\'aa\' || php(\'strval\', php(\'date\', \'Y-m-d H:i:s\', php(\'time\'))) || \'cc\' as \'concatTest\'',
  156. create(new \rdbms\Criteria())->setProjection(SQLFunctions::concat('aa', SQLFunctions::str(SQLFunctions::getdate()), 'cc'), 'concatTest')
  157. );
  158. }
  159. #[@test]
  160. function dateFunctionTest() {
  161. $date= new Date();
  162. $myDate= $date->toString($this->myconn->getFormatter()->dialect->dateFormat);
  163. $syDate= $date->toString($this->syconn->getFormatter()->dialect->dateFormat);
  164. $pgDate= $date->toString($this->pgconn->getFormatter()->dialect->dateFormat);
  165. $sqDate= $date->toString($this->sqconn->getFormatter()->dialect->dateFormat);
  166. $this->assertProjection(
  167. 'cast(sysdate() as char)',
  168. 'convert(varchar, getdate())',
  169. 'str(getdate())',
  170. 'php(\'strval\', php(\'date\', \'Y-m-d H:i:s\', php(\'time\')))',
  171. create(new \rdbms\Criteria())->setProjection(SQLFunctions::str(SQLFunctions::getdate()))
  172. );
  173. $this->assertProjection(
  174. 'cast(timestampadd(month, -4, sysdate()) as char)',
  175. 'convert(varchar, dateadd(month, -4, getdate()))',
  176. 'str(dateadd(month, -4, getdate()))',
  177. 'php(\'strval\', dateadd("m", -4, php(\'date\', \'Y-m-d H:i:s\', php(\'time\'))))',
  178. create(new \rdbms\Criteria())->setProjection(SQLFunctions::str(SQLFunctions::dateadd('month', '-4', SQLFunctions::getdate())))
  179. );
  180. $this->assertProjection(
  181. 'timestampdiff(second, timestampadd(day, -4, sysdate()), sysdate())',
  182. 'datediff(second, dateadd(day, -4, getdate()), getdate())',
  183. 'datediff(second, dateadd(day, -4, getdate()), getdate())',
  184. 'datediff_not_implemented',
  185. create(new \rdbms\Criteria())->setProjection(SQLFunctions::datediff('second', SQLFunctions::dateadd('day', '-4', SQLFunctions::getdate()), SQLFunctions::getdate()))
  186. );
  187. $this->assertProjection(
  188. 'cast(extract(hour from sysdate()) as char)',
  189. 'datename(hour, getdate())',
  190. 'datename(hour, getdate())',
  191. 'php(\'strval\', php(\'idate\', "H", php(\'strtotime\', php(\'date\', \'Y-m-d H:i:s\', php(\'time\')))))',
  192. create(new \rdbms\Criteria())->setProjection(SQLFunctions::datename('hour', SQLFunctions::getdate()))
  193. );
  194. $this->assertProjection(
  195. 'extract(hour from \''.$myDate.'\')',
  196. 'datepart(hour, \''.$syDate.'\')',
  197. 'datepart(hour, \''.$pgDate.'\')',
  198. 'php(\'idate\', "H", php(\'strtotime\', \''.$sqDate.'\'))',
  199. create(new \rdbms\Criteria())->setProjection(SQLFunctions::datepart('hour', $date))
  200. );
  201. }
  202. #[@test]
  203. function mathArithFunctionTest() {
  204. $this->assertProjection(
  205. 'abs(-6)',
  206. 'abs(-6)',
  207. 'abs(-6)',
  208. 'php(\'abs\', -6)',
  209. create(new \rdbms\Criteria())->setProjection(SQLFunctions::abs(-6))
  210. );
  211. $this->assertProjection(
  212. 'ceil(5.1)',
  213. 'ceiling(5.1)',
  214. 'ceil(5.1)',
  215. 'php(\'ceil\', 5.1)',
  216. create(new \rdbms\Criteria())->setProjection(SQLFunctions::ceil(5.1))
  217. );
  218. $this->assertProjection(
  219. 'floor(5.7)',
  220. 'floor(5.7)',
  221. 'floor(5.7)',
  222. 'php(\'floor\', 5.7)',
  223. create(new \rdbms\Criteria())->setProjection(SQLFunctions::floor(5.7))
  224. );
  225. $this->assertProjection(
  226. 'exp(log(1))',
  227. 'exp(log(1))',
  228. 'exp(log(1))',
  229. 'php(\'exp\', php(\'log\', 1))',
  230. create(new \rdbms\Criteria())->setProjection(SQLFunctions::exp(SQLFunctions::log(1)))
  231. );
  232. $this->assertProjection(
  233. 'log10(power(10, 5))',
  234. 'log10(power(10, 5))',
  235. 'log10(power(10, 5))',
  236. 'php(\'log10\', php(\'pow\', 10, 5))',
  237. create(new \rdbms\Criteria())->setProjection(SQLFunctions::log10(SQLFunctions::power(10, 5)))
  238. );
  239. $this->assertProjection(
  240. 'power(10, log10(5))',
  241. 'power(10, log10(5))',
  242. 'power(10, log10(5))',
  243. 'php(\'pow\', 10, php(\'log10\', 5))',
  244. create(new \rdbms\Criteria())->setProjection(SQLFunctions::power(10, SQLFunctions::log10(5)))
  245. );
  246. $this->assertProjection(
  247. 'round(1.5, 0) as `roundtest1`, round(1.49, 0) as `roundtest2`, round(1.49, 1) as `roundtest3`',
  248. 'round(1.5, 0) as \'roundtest1\', round(1.49, 0) as \'roundtest2\', round(1.49, 1) as \'roundtest3\'',
  249. 'round(1.5, 0) as "roundtest1", round(1.49, 0) as "roundtest2", round(1.49, 1) as "roundtest3"',
  250. 'php(\'round\', 1.5, 0) as \'roundtest1\', php(\'round\', 1.49, 0) as \'roundtest2\', php(\'round\', 1.49, 1) as \'roundtest3\'',
  251. create(new \rdbms\Criteria())->setProjection(\rdbms\criterion\Projections::ProjectionList()
  252. ->add(SQLFunctions::round(1.50), 'roundtest1')
  253. ->add(SQLFunctions::round(1.49), 'roundtest2')
  254. ->add(SQLFunctions::round(1.49, 1), 'roundtest3')
  255. )
  256. );
  257. $this->assertProjection(
  258. 'sign(-7) as `signTest1`, sign(0) as `signTest2`, sign(4) as `signTest3`',
  259. 'convert(int, sign(-7)) as \'signTest1\', convert(int, sign(0)) as \'signTest2\', convert(int, sign(4)) as \'signTest3\'',
  260. 'sign(-7) as "signTest1", sign(0) as "signTest2", sign(4) as "signTest3"',
  261. 'sign(-7) as \'signTest1\', sign(0) as \'signTest2\', sign(4) as \'signTest3\'',
  262. create(new \rdbms\Criteria())->setProjection(\rdbms\criterion\Projections::ProjectionList()
  263. ->add(SQLFunctions::sign(-7), 'signTest1')
  264. ->add(SQLFunctions::sign(0), 'signTest2')
  265. ->add(SQLFunctions::sign(4), 'signTest3')
  266. )
  267. );
  268. }
  269. #[@test]
  270. function mathTrigFunctionTest() {
  271. $this->assertProjection(
  272. 'cot(45)',
  273. 'cot(45)',
  274. 'cot(45)',
  275. 'php(\'tan\', php(\'pi\') / 2 - 45)',
  276. create(new \rdbms\Criteria())->setProjection(SQLFunctions::cot(45))
  277. );
  278. $this->assertProjection(
  279. 'pi()',
  280. 'pi()',
  281. 'pi()',
  282. 'php(\'pi\')',
  283. create(new \rdbms\Criteria())->setProjection(SQLFunctions::pi())
  284. );
  285. $this->assertProjection(
  286. 'acos(cos(0.125))',
  287. 'acos(cos(0.125))',
  288. 'acos(cos(0.125))',
  289. 'php(\'acos\', php(\'cos\', 0.125))',
  290. create(new \rdbms\Criteria())->setProjection(SQLFunctions::acos(SQLFunctions::cos(0.125)))
  291. );
  292. $this->assertProjection(
  293. 'asin(sin(0.125))',
  294. 'asin(sin(0.125))',
  295. 'asin(sin(0.125))',
  296. 'php(\'asin\', php(\'sin\', 0.125))',
  297. create(new \rdbms\Criteria())->setProjection(SQLFunctions::asin(SQLFunctions::sin(0.125)))
  298. );
  299. $this->assertProjection(
  300. 'atan(tan(0.125))',
  301. 'atan(tan(0.125))',
  302. 'atan(tan(0.125))',
  303. 'php(\'atan\', php(\'tan\', 0.125))',
  304. create(new \rdbms\Criteria())->setProjection(SQLFunctions::atan(SQLFunctions::tan(0.125)))
  305. );
  306. $this->assertProjection(
  307. 'atan2(tan(0.125), 0)',
  308. 'atn2(tan(0.125), 0)',
  309. 'atan2(tan(0.125), 0)',
  310. 'php(\'atan2\', php(\'tan\', 0.125), 0)',
  311. create(new \rdbms\Criteria())->setProjection(SQLFunctions::atan(SQLFunctions::tan(0.125), 0))
  312. );
  313. $this->assertProjection(
  314. 'degrees(pi())',
  315. 'convert(float, degrees(pi()))',
  316. 'degrees(pi())',
  317. 'php(\'rad2deg\', php(\'pi\'))',
  318. create(new \rdbms\Criteria())->setProjection(SQLFunctions::degrees(SQLFunctions::pi()))
  319. );
  320. $this->assertProjection(
  321. 'radians(degrees(90))',
  322. 'convert(float, radians(convert(float, degrees(90))))',
  323. 'radians(degrees(90))',
  324. 'php(\'deg2rad\', php(\'rad2deg\', 90))',
  325. create(new \rdbms\Criteria())->setProjection(SQLFunctions::radians(SQLFunctions::degrees(90)))
  326. );
  327. $this->assertProjection(
  328. 'radians(degrees(90))',
  329. 'convert(float, radians(convert(float, degrees(90))))',
  330. 'radians(degrees(90))',
  331. 'php(\'deg2rad\', php(\'rad2deg\', 90))',
  332. create(new \rdbms\Criteria())->setProjection(SQLFunctions::radians(SQLFunctions::degrees(90)))
  333. );
  334. }
  335. #[@test]
  336. function randFunctionTest() {
  337. $this->assertProjection(
  338. 'rand()',
  339. 'rand()',
  340. 'random()',
  341. 'php(\'rand\')',
  342. create(new \rdbms\Criteria())->setProjection(SQLFunctions::rand())
  343. );
  344. }
  345. #[@test]
  346. function castFunctionTest() {
  347. $this->assertProjection(
  348. 'cast(\'345\' as decimal)',
  349. 'convert(decimal, \'345\')',
  350. 'cast(\'345\' as decimal)',
  351. 'cast(\'345\' as decimal)',
  352. create(new \rdbms\Criteria())->setProjection(SQLFunctions::cast('345', 'decimal'))
  353. );
  354. $this->assertProjection(
  355. 'cast(job_id as char)',
  356. 'convert(char, job_id)',
  357. 'cast(job_id as char)',
  358. 'cast(job_id as char)',
  359. create(new \rdbms\Criteria())->setProjection(SQLFunctions::cast(Job::column('job_id'), 'char'))
  360. );
  361. }
  362. #[@test]
  363. function restrictionTest() {
  364. $this->assertSQL(
  365. 'where job_id = ceil(asin(sin(0.125)))',
  366. 'where job_id = ceiling(asin(sin(0.125)))',
  367. 'where job_id = ceil(asin(sin(0.125)))',
  368. 'where job_id = php(\'ceil\', php(\'asin\', php(\'sin\', 0.125)))',
  369. create(new \rdbms\Criteria())->add(Restrictions::equal('job_id', SQLFunctions::ceil(SQLFunctions::asin(SQLFunctions::sin(0.125)))))
  370. );
  371. $this->assertSQL(
  372. 'where job_id = ceil(asin(sin(0.125)))',
  373. 'where job_id = ceiling(asin(sin(0.125)))',
  374. 'where job_id = ceil(asin(sin(0.125)))',
  375. 'where job_id = php(\'ceil\', php(\'asin\', php(\'sin\', 0.125)))',
  376. create(new \rdbms\Criteria())->add(Restrictions::equal(Job::column('job_id'), SQLFunctions::ceil(SQLFunctions::asin(SQLFunctions::sin(0.125)))))
  377. );
  378. }
  379. }