SQLParserUtilsTest.php 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. <?php
  2. namespace Doctrine\Tests\DBAL;
  3. use Doctrine\DBAL\Connection;
  4. use Doctrine\DBAL\SQLParserUtils;
  5. require_once __DIR__ . '/../TestInit.php';
  6. /**
  7. * @group DBAL-78
  8. * @group DDC-1372
  9. */
  10. class SQLParserUtilsTest extends \Doctrine\Tests\DbalTestCase
  11. {
  12. static public function dataGetPlaceholderPositions()
  13. {
  14. return array(
  15. // none
  16. array('SELECT * FROM Foo', true, array()),
  17. array('SELECT * FROM Foo', false, array()),
  18. // Positionals
  19. array('SELECT ?', true, array(7)),
  20. array('SELECT * FROM Foo WHERE bar IN (?, ?, ?)', true, array(32, 35, 38)),
  21. array('SELECT ? FROM ?', true, array(7, 14)),
  22. array('SELECT "?" FROM foo', true, array()),
  23. array("SELECT '?' FROM foo", true, array()),
  24. array('SELECT "?" FROM foo WHERE bar = ?', true, array(32)),
  25. array("SELECT '?' FROM foo WHERE bar = ?", true, array(32)),
  26. array(
  27. <<<'SQLDATA'
  28. SELECT * FROM foo WHERE bar = 'it\'s a trap? \\' OR bar = ?
  29. AND baz = "\"quote\" me on it? \\" OR baz = ?
  30. SQLDATA
  31. , true, array(58, 104)
  32. ),
  33. // named
  34. array('SELECT :foo FROM :bar', false, array(7 => 'foo', 17 => 'bar')),
  35. array('SELECT * FROM Foo WHERE bar IN (:name1, :name2)', false, array(32 => 'name1', 40 => 'name2')),
  36. array('SELECT ":foo" FROM Foo WHERE bar IN (:name1, :name2)', false, array(37 => 'name1', 45 => 'name2')),
  37. array("SELECT ':foo' FROM Foo WHERE bar IN (:name1, :name2)", false, array(37 => 'name1', 45 => 'name2')),
  38. array('SELECT :foo_id', false, array(7 => 'foo_id')), // Ticket DBAL-231
  39. array('SELECT @rank := 1', false, array()), // Ticket DBAL-398
  40. array('SELECT @rank := 1 AS rank, :foo AS foo FROM :bar', false, array(27 => 'foo', 44 => 'bar')), // Ticket DBAL-398
  41. array('SELECT * FROM Foo WHERE bar > :start_date AND baz > :start_date', false, array(30 => 'start_date', 52 => 'start_date')) // Ticket GH-113
  42. );
  43. }
  44. /**
  45. * @dataProvider dataGetPlaceholderPositions
  46. * @param type $query
  47. * @param type $isPositional
  48. * @param type $expectedParamPos
  49. */
  50. public function testGetPlaceholderPositions($query, $isPositional, $expectedParamPos)
  51. {
  52. $actualParamPos = SQLParserUtils::getPlaceholderPositions($query, $isPositional);
  53. $this->assertEquals($expectedParamPos, $actualParamPos);
  54. }
  55. static public function dataExpandListParameters()
  56. {
  57. return array(
  58. // Positional: Very simple with one needle
  59. array(
  60. "SELECT * FROM Foo WHERE foo IN (?)",
  61. array(array(1, 2, 3)),
  62. array(Connection::PARAM_INT_ARRAY),
  63. 'SELECT * FROM Foo WHERE foo IN (?, ?, ?)',
  64. array(1, 2, 3),
  65. array(\PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT)
  66. ),
  67. // Positional: One non-list before d one after list-needle
  68. array(
  69. "SELECT * FROM Foo WHERE foo = ? AND bar IN (?)",
  70. array("string", array(1, 2, 3)),
  71. array(\PDO::PARAM_STR, Connection::PARAM_INT_ARRAY),
  72. 'SELECT * FROM Foo WHERE foo = ? AND bar IN (?, ?, ?)',
  73. array("string", 1, 2, 3),
  74. array(\PDO::PARAM_STR, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT)
  75. ),
  76. // Positional: One non-list after list-needle
  77. array(
  78. "SELECT * FROM Foo WHERE bar IN (?) AND baz = ?",
  79. array(array(1, 2, 3), "foo"),
  80. array(Connection::PARAM_INT_ARRAY, \PDO::PARAM_STR),
  81. 'SELECT * FROM Foo WHERE bar IN (?, ?, ?) AND baz = ?',
  82. array(1, 2, 3, "foo"),
  83. array(\PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_STR)
  84. ),
  85. // Positional: One non-list before and one after list-needle
  86. array(
  87. "SELECT * FROM Foo WHERE foo = ? AND bar IN (?) AND baz = ?",
  88. array(1, array(1, 2, 3), 4),
  89. array(\PDO::PARAM_INT, Connection::PARAM_INT_ARRAY, \PDO::PARAM_INT),
  90. 'SELECT * FROM Foo WHERE foo = ? AND bar IN (?, ?, ?) AND baz = ?',
  91. array(1, 1, 2, 3, 4),
  92. array(\PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT)
  93. ),
  94. // Positional: Two lists
  95. array(
  96. "SELECT * FROM Foo WHERE foo IN (?, ?)",
  97. array(array(1, 2, 3), array(4, 5)),
  98. array(Connection::PARAM_INT_ARRAY, Connection::PARAM_INT_ARRAY),
  99. 'SELECT * FROM Foo WHERE foo IN (?, ?, ?, ?, ?)',
  100. array(1, 2, 3, 4, 5),
  101. array(\PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT)
  102. ),
  103. // Positional : Empty "integer" array DDC-1978
  104. array(
  105. "SELECT * FROM Foo WHERE foo IN (?)",
  106. array('foo'=>array()),
  107. array('foo'=>Connection::PARAM_INT_ARRAY),
  108. 'SELECT * FROM Foo WHERE foo IN (?)',
  109. array(),
  110. array()
  111. ),
  112. // Positional : Empty "str" array DDC-1978
  113. array(
  114. "SELECT * FROM Foo WHERE foo IN (?)",
  115. array('foo'=>array()),
  116. array('foo'=>Connection::PARAM_STR_ARRAY),
  117. 'SELECT * FROM Foo WHERE foo IN (?)',
  118. array(),
  119. array()
  120. ),
  121. // Named parameters : Very simple with param int
  122. array(
  123. "SELECT * FROM Foo WHERE foo = :foo",
  124. array('foo'=>1),
  125. array('foo'=>\PDO::PARAM_INT),
  126. 'SELECT * FROM Foo WHERE foo = ?',
  127. array(1),
  128. array(\PDO::PARAM_INT)
  129. ),
  130. // Named parameters : Very simple with param int and string
  131. array(
  132. "SELECT * FROM Foo WHERE foo = :foo AND bar = :bar",
  133. array('bar'=>'Some String','foo'=>1),
  134. array('foo'=>\PDO::PARAM_INT,'bar'=>\PDO::PARAM_STR),
  135. 'SELECT * FROM Foo WHERE foo = ? AND bar = ?',
  136. array(1,'Some String'),
  137. array(\PDO::PARAM_INT, \PDO::PARAM_STR)
  138. ),
  139. // Named parameters : Very simple with one needle
  140. array(
  141. "SELECT * FROM Foo WHERE foo IN (:foo)",
  142. array('foo'=>array(1, 2, 3)),
  143. array('foo'=>Connection::PARAM_INT_ARRAY),
  144. 'SELECT * FROM Foo WHERE foo IN (?, ?, ?)',
  145. array(1, 2, 3),
  146. array(\PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT)
  147. ),
  148. // Named parameters: One non-list before d one after list-needle
  149. array(
  150. "SELECT * FROM Foo WHERE foo = :foo AND bar IN (:bar)",
  151. array('foo'=>"string", 'bar'=>array(1, 2, 3)),
  152. array('foo'=>\PDO::PARAM_STR, 'bar'=>Connection::PARAM_INT_ARRAY),
  153. 'SELECT * FROM Foo WHERE foo = ? AND bar IN (?, ?, ?)',
  154. array("string", 1, 2, 3),
  155. array(\PDO::PARAM_STR, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT)
  156. ),
  157. // Named parameters: One non-list after list-needle
  158. array(
  159. "SELECT * FROM Foo WHERE bar IN (:bar) AND baz = :baz",
  160. array('bar'=>array(1, 2, 3), 'baz'=>"foo"),
  161. array('bar'=>Connection::PARAM_INT_ARRAY, 'baz'=>\PDO::PARAM_STR),
  162. 'SELECT * FROM Foo WHERE bar IN (?, ?, ?) AND baz = ?',
  163. array(1, 2, 3, "foo"),
  164. array(\PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_STR)
  165. ),
  166. // Named parameters: One non-list before and one after list-needle
  167. array(
  168. "SELECT * FROM Foo WHERE foo = :foo AND bar IN (:bar) AND baz = :baz",
  169. array('bar'=>array(1, 2, 3),'foo'=>1, 'baz'=>4),
  170. array('bar'=>Connection::PARAM_INT_ARRAY, 'foo'=>\PDO::PARAM_INT, 'baz'=>\PDO::PARAM_INT),
  171. 'SELECT * FROM Foo WHERE foo = ? AND bar IN (?, ?, ?) AND baz = ?',
  172. array(1, 1, 2, 3, 4),
  173. array(\PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT)
  174. ),
  175. // Named parameters: Two lists
  176. array(
  177. "SELECT * FROM Foo WHERE foo IN (:a, :b)",
  178. array('b'=>array(4, 5),'a'=>array(1, 2, 3)),
  179. array('a'=>Connection::PARAM_INT_ARRAY, 'b'=>Connection::PARAM_INT_ARRAY),
  180. 'SELECT * FROM Foo WHERE foo IN (?, ?, ?, ?, ?)',
  181. array(1, 2, 3, 4, 5),
  182. array(\PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT)
  183. ),
  184. // Named parameters : With the same name arg type string
  185. array(
  186. "SELECT * FROM Foo WHERE foo <> :arg AND bar = :arg",
  187. array('arg'=>"Some String"),
  188. array('arg'=>\PDO::PARAM_STR),
  189. 'SELECT * FROM Foo WHERE foo <> ? AND bar = ?',
  190. array("Some String","Some String"),
  191. array(\PDO::PARAM_STR,\PDO::PARAM_STR,)
  192. ),
  193. // Named parameters : With the same name arg
  194. array(
  195. "SELECT * FROM Foo WHERE foo IN (:arg) AND NOT bar IN (:arg)",
  196. array('arg'=>array(1, 2, 3)),
  197. array('arg'=>Connection::PARAM_INT_ARRAY),
  198. 'SELECT * FROM Foo WHERE foo IN (?, ?, ?) AND NOT bar IN (?, ?, ?)',
  199. array(1, 2, 3, 1, 2, 3),
  200. array(\PDO::PARAM_INT,\PDO::PARAM_INT, \PDO::PARAM_INT,\PDO::PARAM_INT,\PDO::PARAM_INT, \PDO::PARAM_INT)
  201. ),
  202. // Named parameters : Same name, other name in between DBAL-299
  203. array(
  204. "SELECT * FROM Foo WHERE (:foo = 2) AND (:bar = 3) AND (:foo = 2)",
  205. array('foo'=>2,'bar'=>3),
  206. array('foo'=>\PDO::PARAM_INT,'bar'=>\PDO::PARAM_INT),
  207. 'SELECT * FROM Foo WHERE (? = 2) AND (? = 3) AND (? = 2)',
  208. array(2, 3, 2),
  209. array(\PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT)
  210. ),
  211. // Named parameters : Empty "integer" array DDC-1978
  212. array(
  213. "SELECT * FROM Foo WHERE foo IN (:foo)",
  214. array('foo'=>array()),
  215. array('foo'=>Connection::PARAM_INT_ARRAY),
  216. 'SELECT * FROM Foo WHERE foo IN (?)',
  217. array(),
  218. array()
  219. ),
  220. // Named parameters : Two empty "str" array DDC-1978
  221. array(
  222. "SELECT * FROM Foo WHERE foo IN (:foo) OR bar IN (:bar)",
  223. array('foo'=>array(), 'bar'=>array()),
  224. array('foo'=>Connection::PARAM_STR_ARRAY, 'bar'=>Connection::PARAM_STR_ARRAY),
  225. 'SELECT * FROM Foo WHERE foo IN (?) OR bar IN (?)',
  226. array(),
  227. array()
  228. ),
  229. );
  230. }
  231. /**
  232. * @dataProvider dataExpandListParameters
  233. * @param type $q
  234. * @param type $p
  235. * @param type $t
  236. * @param type $expectedQuery
  237. * @param type $expectedParams
  238. * @param type $expectedTypes
  239. */
  240. public function testExpandListParameters($q, $p, $t, $expectedQuery, $expectedParams, $expectedTypes)
  241. {
  242. list($query, $params, $types) = SQLParserUtils::expandListParameters($q, $p, $t);
  243. $this->assertEquals($expectedQuery, $query, "Query was not rewritten correctly.");
  244. $this->assertEquals($expectedParams, $params, "Params dont match");
  245. $this->assertEquals($expectedTypes, $types, "Types dont match");
  246. }
  247. }