1
0

QueryBuilderTest.php 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. namespace Test\DB\QueryBuilder;
  8. use Doctrine\DBAL\Query\Expression\CompositeExpression;
  9. use Doctrine\DBAL\Query\QueryException;
  10. use Doctrine\DBAL\Result;
  11. use OC\DB\QueryBuilder\Literal;
  12. use OC\DB\QueryBuilder\Parameter;
  13. use OC\DB\QueryBuilder\QueryBuilder;
  14. use OC\SystemConfig;
  15. use OCP\DB\QueryBuilder\IQueryFunction;
  16. use OCP\IDBConnection;
  17. use Psr\Log\LoggerInterface;
  18. /**
  19. * Class QueryBuilderTest
  20. *
  21. * @group DB
  22. *
  23. * @package Test\DB\QueryBuilder
  24. */
  25. class QueryBuilderTest extends \Test\TestCase {
  26. /** @var QueryBuilder */
  27. protected $queryBuilder;
  28. /** @var IDBConnection */
  29. protected $connection;
  30. /** @var SystemConfig|\PHPUnit\Framework\MockObject\MockObject */
  31. protected $config;
  32. /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
  33. protected $logger;
  34. protected function setUp(): void {
  35. parent::setUp();
  36. $this->connection = \OC::$server->getDatabaseConnection();
  37. $this->config = $this->createMock(SystemConfig::class);
  38. $this->logger = $this->createMock(LoggerInterface::class);
  39. $this->queryBuilder = new QueryBuilder($this->connection, $this->config, $this->logger);
  40. }
  41. protected function createTestingRows($appId = 'testFirstResult') {
  42. $qB = $this->connection->getQueryBuilder();
  43. for ($i = 1; $i < 10; $i++) {
  44. $qB->insert('*PREFIX*appconfig')
  45. ->values([
  46. 'appid' => $qB->expr()->literal($appId),
  47. 'configkey' => $qB->expr()->literal('testing' . $i),
  48. 'configvalue' => $qB->expr()->literal(100 - $i),
  49. ])
  50. ->execute();
  51. }
  52. }
  53. protected function getTestingRows(QueryBuilder $queryBuilder) {
  54. $queryBuilder->select('configvalue')
  55. ->from('*PREFIX*appconfig')
  56. ->where($queryBuilder->expr()->eq(
  57. 'appid',
  58. $queryBuilder->expr()->literal('testFirstResult')
  59. ))
  60. ->orderBy('configkey', 'ASC');
  61. $query = $queryBuilder->execute();
  62. $rows = [];
  63. while ($row = $query->fetch()) {
  64. $rows[] = $row['configvalue'];
  65. }
  66. $query->closeCursor();
  67. return $rows;
  68. }
  69. protected function deleteTestingRows($appId = 'testFirstResult') {
  70. $qB = $this->connection->getQueryBuilder();
  71. $qB->delete('*PREFIX*appconfig')
  72. ->where($qB->expr()->eq('appid', $qB->expr()->literal($appId)))
  73. ->execute();
  74. }
  75. public function dataFirstResult() {
  76. return [
  77. [0, [99, 98, 97, 96, 95, 94, 93, 92, 91]],
  78. [0, [99, 98, 97, 96, 95, 94, 93, 92, 91]],
  79. [1, [98, 97, 96, 95, 94, 93, 92, 91]],
  80. [5, [94, 93, 92, 91]],
  81. ];
  82. }
  83. /**
  84. * @dataProvider dataFirstResult
  85. *
  86. * @param int|null $firstResult
  87. * @param array $expectedSet
  88. */
  89. public function testFirstResult($firstResult, $expectedSet) {
  90. $this->deleteTestingRows();
  91. $this->createTestingRows();
  92. if ($firstResult !== null) {
  93. $this->queryBuilder->setFirstResult($firstResult);
  94. }
  95. $this->assertSame(
  96. $firstResult ?? 0,
  97. $this->queryBuilder->getFirstResult()
  98. );
  99. $rows = $this->getTestingRows($this->queryBuilder);
  100. $this->assertCount(sizeof($expectedSet), $rows);
  101. $this->assertEquals($expectedSet, $rows);
  102. $this->deleteTestingRows();
  103. }
  104. public function dataMaxResults() {
  105. return [
  106. [null, [99, 98, 97, 96, 95, 94, 93, 92, 91]],
  107. // Limit 0 gives mixed results: either all entries or none is returned
  108. //[0, []],
  109. [1, [99]],
  110. [5, [99, 98, 97, 96, 95]],
  111. ];
  112. }
  113. /**
  114. * @dataProvider dataMaxResults
  115. *
  116. * @param int $maxResult
  117. * @param array $expectedSet
  118. */
  119. public function testMaxResults($maxResult, $expectedSet) {
  120. $this->deleteTestingRows();
  121. $this->createTestingRows();
  122. if ($maxResult !== null) {
  123. $this->queryBuilder->setMaxResults($maxResult);
  124. }
  125. $this->assertSame(
  126. $maxResult,
  127. $this->queryBuilder->getMaxResults()
  128. );
  129. $rows = $this->getTestingRows($this->queryBuilder);
  130. $this->assertCount(sizeof($expectedSet), $rows);
  131. $this->assertEquals($expectedSet, $rows);
  132. $this->deleteTestingRows();
  133. }
  134. public function dataSelect() {
  135. $config = $this->createMock(SystemConfig::class);
  136. $logger = $this->createMock(LoggerInterface::class);
  137. $queryBuilder = new QueryBuilder(\OC::$server->getDatabaseConnection(), $config, $logger);
  138. return [
  139. // select('column1')
  140. [['configvalue'], ['configvalue' => '99']],
  141. // select('column1', 'column2')
  142. [['configvalue', 'configkey'], ['configvalue' => '99', 'configkey' => 'testing1']],
  143. // select(['column1', 'column2'])
  144. [[['configvalue', 'configkey']], ['configvalue' => '99', 'configkey' => 'testing1']],
  145. // select(new Literal('column1'))
  146. [[$queryBuilder->expr()->literal('column1')], [], 'column1'],
  147. // select('column1', 'column2')
  148. [[$queryBuilder->expr()->literal('column1'), 'configkey'], ['configkey' => 'testing1'], 'column1'],
  149. // select(['column1', 'column2'])
  150. [[[$queryBuilder->expr()->literal('column1'), 'configkey']], ['configkey' => 'testing1'], 'column1'],
  151. ];
  152. }
  153. /**
  154. * @dataProvider dataSelect
  155. *
  156. * @param array $selectArguments
  157. * @param array $expected
  158. * @param string $expectedLiteral
  159. */
  160. public function testSelect($selectArguments, $expected, $expectedLiteral = '') {
  161. $this->deleteTestingRows();
  162. $this->createTestingRows();
  163. call_user_func_array(
  164. [$this->queryBuilder, 'select'],
  165. $selectArguments
  166. );
  167. $this->queryBuilder->from('*PREFIX*appconfig')
  168. ->where($this->queryBuilder->expr()->eq(
  169. 'appid',
  170. $this->queryBuilder->expr()->literal('testFirstResult')
  171. ))
  172. ->orderBy('configkey', 'ASC')
  173. ->setMaxResults(1);
  174. $query = $this->queryBuilder->execute();
  175. $row = $query->fetch();
  176. $query->closeCursor();
  177. foreach ($expected as $key => $value) {
  178. $this->assertArrayHasKey($key, $row);
  179. $this->assertEquals($value, $row[$key]);
  180. unset($row[$key]);
  181. }
  182. if ($expectedLiteral) {
  183. $this->assertEquals([$expectedLiteral], array_values($row));
  184. } else {
  185. $this->assertEmpty($row);
  186. }
  187. $this->deleteTestingRows();
  188. }
  189. public function dataSelectAlias() {
  190. $config = $this->createMock(SystemConfig::class);
  191. $logger = $this->createMock(LoggerInterface::class);
  192. $queryBuilder = new QueryBuilder(\OC::$server->getDatabaseConnection(), $config, $logger);
  193. return [
  194. ['configvalue', 'cv', ['cv' => '99']],
  195. [$queryBuilder->expr()->literal('column1'), 'thing', ['thing' => 'column1']],
  196. ];
  197. }
  198. /**
  199. * @dataProvider dataSelectAlias
  200. *
  201. * @param mixed $select
  202. * @param array $alias
  203. * @param array $expected
  204. */
  205. public function testSelectAlias($select, $alias, $expected) {
  206. $this->deleteTestingRows();
  207. $this->createTestingRows();
  208. $this->queryBuilder->selectAlias($select, $alias);
  209. $this->queryBuilder->from('*PREFIX*appconfig')
  210. ->where($this->queryBuilder->expr()->eq(
  211. 'appid',
  212. $this->queryBuilder->expr()->literal('testFirstResult')
  213. ))
  214. ->orderBy('configkey', 'ASC')
  215. ->setMaxResults(1);
  216. $query = $this->queryBuilder->execute();
  217. $row = $query->fetch();
  218. $query->closeCursor();
  219. $this->assertEquals(
  220. $expected,
  221. $row
  222. );
  223. $this->deleteTestingRows();
  224. }
  225. public function testSelectDistinct() {
  226. $this->deleteTestingRows('testFirstResult1');
  227. $this->deleteTestingRows('testFirstResult2');
  228. $this->createTestingRows('testFirstResult1');
  229. $this->createTestingRows('testFirstResult2');
  230. $this->queryBuilder->selectDistinct('appid');
  231. $this->queryBuilder->from('*PREFIX*appconfig')
  232. ->where($this->queryBuilder->expr()->in(
  233. 'appid',
  234. [$this->queryBuilder->expr()->literal('testFirstResult1'), $this->queryBuilder->expr()->literal('testFirstResult2')]
  235. ))
  236. ->orderBy('appid', 'DESC');
  237. $query = $this->queryBuilder->execute();
  238. $rows = $query->fetchAll();
  239. $query->closeCursor();
  240. $this->assertEquals(
  241. [['appid' => 'testFirstResult2'], ['appid' => 'testFirstResult1']],
  242. $rows
  243. );
  244. $this->deleteTestingRows('testFirstResult1');
  245. $this->deleteTestingRows('testFirstResult2');
  246. }
  247. public function testSelectDistinctMultiple() {
  248. $this->deleteTestingRows('testFirstResult1');
  249. $this->deleteTestingRows('testFirstResult2');
  250. $this->createTestingRows('testFirstResult1');
  251. $this->createTestingRows('testFirstResult2');
  252. $this->queryBuilder->selectDistinct(['appid', 'configkey']);
  253. $this->queryBuilder->from('*PREFIX*appconfig')
  254. ->where($this->queryBuilder->expr()->eq(
  255. 'appid',
  256. $this->queryBuilder->expr()->literal('testFirstResult1')
  257. ))
  258. ->orderBy('configkey', 'ASC');
  259. $query = $this->queryBuilder->execute();
  260. $rows = $query->fetchAll();
  261. $query->closeCursor();
  262. $this->assertEquals(
  263. [
  264. ['appid' => 'testFirstResult1', 'configkey' => 'testing1'],
  265. ['appid' => 'testFirstResult1', 'configkey' => 'testing2'],
  266. ['appid' => 'testFirstResult1', 'configkey' => 'testing3'],
  267. ['appid' => 'testFirstResult1', 'configkey' => 'testing4'],
  268. ['appid' => 'testFirstResult1', 'configkey' => 'testing5'],
  269. ['appid' => 'testFirstResult1', 'configkey' => 'testing6'],
  270. ['appid' => 'testFirstResult1', 'configkey' => 'testing7'],
  271. ['appid' => 'testFirstResult1', 'configkey' => 'testing8'],
  272. ['appid' => 'testFirstResult1', 'configkey' => 'testing9'],
  273. ],
  274. $rows
  275. );
  276. $this->deleteTestingRows('testFirstResult1');
  277. $this->deleteTestingRows('testFirstResult2');
  278. }
  279. public function dataAddSelect() {
  280. $config = $this->createMock(SystemConfig::class);
  281. $logger = $this->createMock(LoggerInterface::class);
  282. $queryBuilder = new QueryBuilder(\OC::$server->getDatabaseConnection(), $config, $logger);
  283. return [
  284. // addSelect('column1')
  285. [['configvalue'], ['appid' => 'testFirstResult', 'configvalue' => '99']],
  286. // addSelect('column1', 'column2')
  287. [['configvalue', 'configkey'], ['appid' => 'testFirstResult', 'configvalue' => '99', 'configkey' => 'testing1']],
  288. // addSelect(['column1', 'column2'])
  289. [[['configvalue', 'configkey']], ['appid' => 'testFirstResult', 'configvalue' => '99', 'configkey' => 'testing1']],
  290. // select(new Literal('column1'))
  291. [[$queryBuilder->expr()->literal('column1')], ['appid' => 'testFirstResult'], 'column1'],
  292. // select('column1', 'column2')
  293. [[$queryBuilder->expr()->literal('column1'), 'configkey'], ['appid' => 'testFirstResult', 'configkey' => 'testing1'], 'column1'],
  294. // select(['column1', 'column2'])
  295. [[[$queryBuilder->expr()->literal('column1'), 'configkey']], ['appid' => 'testFirstResult', 'configkey' => 'testing1'], 'column1'],
  296. ];
  297. }
  298. /**
  299. * @dataProvider dataAddSelect
  300. *
  301. * @param array $selectArguments
  302. * @param array $expected
  303. * @param string $expectedLiteral
  304. */
  305. public function testAddSelect($selectArguments, $expected, $expectedLiteral = '') {
  306. $this->deleteTestingRows();
  307. $this->createTestingRows();
  308. $this->queryBuilder->select('appid');
  309. call_user_func_array(
  310. [$this->queryBuilder, 'addSelect'],
  311. $selectArguments
  312. );
  313. $this->queryBuilder->from('*PREFIX*appconfig')
  314. ->where($this->queryBuilder->expr()->eq(
  315. 'appid',
  316. $this->queryBuilder->expr()->literal('testFirstResult')
  317. ))
  318. ->orderBy('configkey', 'ASC')
  319. ->setMaxResults(1);
  320. $query = $this->queryBuilder->execute();
  321. $row = $query->fetch();
  322. $query->closeCursor();
  323. foreach ($expected as $key => $value) {
  324. $this->assertArrayHasKey($key, $row);
  325. $this->assertEquals($value, $row[$key]);
  326. unset($row[$key]);
  327. }
  328. if ($expectedLiteral) {
  329. $this->assertEquals([$expectedLiteral], array_values($row));
  330. } else {
  331. $this->assertEmpty($row);
  332. }
  333. $this->deleteTestingRows();
  334. }
  335. public function dataDelete() {
  336. return [
  337. ['data', null, ['table' => '`*PREFIX*data`', 'alias' => null], '`*PREFIX*data`'],
  338. ['data', 't', ['table' => '`*PREFIX*data`', 'alias' => 't'], '`*PREFIX*data` t'],
  339. ];
  340. }
  341. /**
  342. * @dataProvider dataDelete
  343. *
  344. * @param string $tableName
  345. * @param string $tableAlias
  346. * @param array $expectedQueryPart
  347. * @param string $expectedQuery
  348. */
  349. public function testDelete($tableName, $tableAlias, $expectedQueryPart, $expectedQuery) {
  350. $this->queryBuilder->delete($tableName, $tableAlias);
  351. $this->assertSame(
  352. $expectedQueryPart,
  353. $this->queryBuilder->getQueryPart('from')
  354. );
  355. $this->assertSame(
  356. 'DELETE FROM ' . $expectedQuery,
  357. $this->queryBuilder->getSQL()
  358. );
  359. }
  360. public function dataUpdate() {
  361. return [
  362. ['data', null, ['table' => '`*PREFIX*data`', 'alias' => null], '`*PREFIX*data`'],
  363. ['data', 't', ['table' => '`*PREFIX*data`', 'alias' => 't'], '`*PREFIX*data` t'],
  364. ];
  365. }
  366. /**
  367. * @dataProvider dataUpdate
  368. *
  369. * @param string $tableName
  370. * @param string $tableAlias
  371. * @param array $expectedQueryPart
  372. * @param string $expectedQuery
  373. */
  374. public function testUpdate($tableName, $tableAlias, $expectedQueryPart, $expectedQuery) {
  375. $this->queryBuilder->update($tableName, $tableAlias);
  376. $this->assertSame(
  377. $expectedQueryPart,
  378. $this->queryBuilder->getQueryPart('from')
  379. );
  380. $this->assertSame(
  381. 'UPDATE ' . $expectedQuery . ' SET ',
  382. $this->queryBuilder->getSQL()
  383. );
  384. }
  385. public function dataInsert() {
  386. return [
  387. ['data', ['table' => '`*PREFIX*data`'], '`*PREFIX*data`'],
  388. ];
  389. }
  390. /**
  391. * @dataProvider dataInsert
  392. *
  393. * @param string $tableName
  394. * @param array $expectedQueryPart
  395. * @param string $expectedQuery
  396. */
  397. public function testInsert($tableName, $expectedQueryPart, $expectedQuery) {
  398. $this->queryBuilder->insert($tableName);
  399. $this->assertSame(
  400. $expectedQueryPart,
  401. $this->queryBuilder->getQueryPart('from')
  402. );
  403. $this->assertSame(
  404. 'INSERT INTO ' . $expectedQuery . ' () VALUES()',
  405. $this->queryBuilder->getSQL()
  406. );
  407. }
  408. public function dataFrom() {
  409. $config = $this->createMock(SystemConfig::class);
  410. $logger = $this->createMock(LoggerInterface::class);
  411. $qb = new QueryBuilder(\OC::$server->getDatabaseConnection(), $config, $logger);
  412. return [
  413. [$qb->createFunction('(' . $qb->select('*')->from('test')->getSQL() . ')'), 'q', null, null, [
  414. ['table' => '(SELECT * FROM `*PREFIX*test`)', 'alias' => '`q`']
  415. ], '(SELECT * FROM `*PREFIX*test`) `q`'],
  416. ['data', null, null, null, [['table' => '`*PREFIX*data`', 'alias' => null]], '`*PREFIX*data`'],
  417. ['data', 't', null, null, [['table' => '`*PREFIX*data`', 'alias' => '`t`']], '`*PREFIX*data` `t`'],
  418. ['data1', null, 'data2', null, [
  419. ['table' => '`*PREFIX*data1`', 'alias' => null],
  420. ['table' => '`*PREFIX*data2`', 'alias' => null]
  421. ], '`*PREFIX*data1`, `*PREFIX*data2`'],
  422. ['data', 't1', 'data', 't2', [
  423. ['table' => '`*PREFIX*data`', 'alias' => '`t1`'],
  424. ['table' => '`*PREFIX*data`', 'alias' => '`t2`']
  425. ], '`*PREFIX*data` `t1`, `*PREFIX*data` `t2`'],
  426. ];
  427. }
  428. /**
  429. * @dataProvider dataFrom
  430. *
  431. * @param string|IQueryFunction $table1Name
  432. * @param string $table1Alias
  433. * @param string|IQueryFunction $table2Name
  434. * @param string $table2Alias
  435. * @param array $expectedQueryPart
  436. * @param string $expectedQuery
  437. */
  438. public function testFrom($table1Name, $table1Alias, $table2Name, $table2Alias, $expectedQueryPart, $expectedQuery) {
  439. $this->queryBuilder->from($table1Name, $table1Alias);
  440. if ($table2Name !== null) {
  441. $this->queryBuilder->from($table2Name, $table2Alias);
  442. }
  443. $this->assertSame(
  444. $expectedQueryPart,
  445. $this->queryBuilder->getQueryPart('from')
  446. );
  447. $this->assertSame(
  448. 'SELECT FROM ' . $expectedQuery,
  449. $this->queryBuilder->getSQL()
  450. );
  451. }
  452. public function dataJoin() {
  453. return [
  454. [
  455. 'd1', 'data2', null, null,
  456. ['`d1`' => [['joinType' => 'inner', 'joinTable' => '`*PREFIX*data2`', 'joinAlias' => null, 'joinCondition' => null]]],
  457. '`*PREFIX*data1` `d1` INNER JOIN `*PREFIX*data2` '
  458. ],
  459. [
  460. 'd1', 'data2', 'd2', null,
  461. ['`d1`' => [['joinType' => 'inner', 'joinTable' => '`*PREFIX*data2`', 'joinAlias' => '`d2`', 'joinCondition' => null]]],
  462. '`*PREFIX*data1` `d1` INNER JOIN `*PREFIX*data2` `d2`'
  463. ],
  464. [
  465. 'd1', 'data2', 'd2', '`d1`.`field1` = `d2`.`field2`',
  466. ['`d1`' => [['joinType' => 'inner', 'joinTable' => '`*PREFIX*data2`', 'joinAlias' => '`d2`', 'joinCondition' => '`d1`.`field1` = `d2`.`field2`']]],
  467. '`*PREFIX*data1` `d1` INNER JOIN `*PREFIX*data2` `d2` ON `d1`.`field1` = `d2`.`field2`'
  468. ],
  469. ];
  470. }
  471. /**
  472. * @dataProvider dataJoin
  473. *
  474. * @param string $fromAlias
  475. * @param string $tableName
  476. * @param string $tableAlias
  477. * @param string $condition
  478. * @param array $expectedQueryPart
  479. * @param string $expectedQuery
  480. */
  481. public function testJoin($fromAlias, $tableName, $tableAlias, $condition, $expectedQueryPart, $expectedQuery) {
  482. $this->queryBuilder->from('data1', 'd1');
  483. $this->queryBuilder->join(
  484. $fromAlias,
  485. $tableName,
  486. $tableAlias,
  487. $condition
  488. );
  489. $this->assertSame(
  490. $expectedQueryPart,
  491. $this->queryBuilder->getQueryPart('join')
  492. );
  493. $this->assertSame(
  494. 'SELECT FROM ' . $expectedQuery,
  495. $this->queryBuilder->getSQL()
  496. );
  497. }
  498. /**
  499. * @dataProvider dataJoin
  500. *
  501. * @param string $fromAlias
  502. * @param string $tableName
  503. * @param string $tableAlias
  504. * @param string $condition
  505. * @param array $expectedQueryPart
  506. * @param string $expectedQuery
  507. */
  508. public function testInnerJoin($fromAlias, $tableName, $tableAlias, $condition, $expectedQueryPart, $expectedQuery) {
  509. $this->queryBuilder->from('data1', 'd1');
  510. $this->queryBuilder->innerJoin(
  511. $fromAlias,
  512. $tableName,
  513. $tableAlias,
  514. $condition
  515. );
  516. $this->assertSame(
  517. $expectedQueryPart,
  518. $this->queryBuilder->getQueryPart('join')
  519. );
  520. $this->assertSame(
  521. 'SELECT FROM ' . $expectedQuery,
  522. $this->queryBuilder->getSQL()
  523. );
  524. }
  525. public function dataLeftJoin() {
  526. return [
  527. [
  528. 'd1', 'data2', null, null,
  529. ['`d1`' => [['joinType' => 'left', 'joinTable' => '`*PREFIX*data2`', 'joinAlias' => null, 'joinCondition' => null]]],
  530. '`*PREFIX*data1` `d1` LEFT JOIN `*PREFIX*data2` '
  531. ],
  532. [
  533. 'd1', 'data2', 'd2', null,
  534. ['`d1`' => [['joinType' => 'left', 'joinTable' => '`*PREFIX*data2`', 'joinAlias' => '`d2`', 'joinCondition' => null]]],
  535. '`*PREFIX*data1` `d1` LEFT JOIN `*PREFIX*data2` `d2`'
  536. ],
  537. [
  538. 'd1', 'data2', 'd2', '`d1`.`field1` = `d2`.`field2`',
  539. ['`d1`' => [['joinType' => 'left', 'joinTable' => '`*PREFIX*data2`', 'joinAlias' => '`d2`', 'joinCondition' => '`d1`.`field1` = `d2`.`field2`']]],
  540. '`*PREFIX*data1` `d1` LEFT JOIN `*PREFIX*data2` `d2` ON `d1`.`field1` = `d2`.`field2`'
  541. ],
  542. ];
  543. }
  544. /**
  545. * @dataProvider dataLeftJoin
  546. *
  547. * @param string $fromAlias
  548. * @param string $tableName
  549. * @param string $tableAlias
  550. * @param string $condition
  551. * @param array $expectedQueryPart
  552. * @param string $expectedQuery
  553. */
  554. public function testLeftJoin($fromAlias, $tableName, $tableAlias, $condition, $expectedQueryPart, $expectedQuery) {
  555. $this->queryBuilder->from('data1', 'd1');
  556. $this->queryBuilder->leftJoin(
  557. $fromAlias,
  558. $tableName,
  559. $tableAlias,
  560. $condition
  561. );
  562. $this->assertSame(
  563. $expectedQueryPart,
  564. $this->queryBuilder->getQueryPart('join')
  565. );
  566. $this->assertSame(
  567. 'SELECT FROM ' . $expectedQuery,
  568. $this->queryBuilder->getSQL()
  569. );
  570. }
  571. public function dataRightJoin() {
  572. return [
  573. [
  574. 'd1', 'data2', null, null,
  575. ['`d1`' => [['joinType' => 'right', 'joinTable' => '`*PREFIX*data2`', 'joinAlias' => null, 'joinCondition' => null]]],
  576. '`*PREFIX*data1` `d1` RIGHT JOIN `*PREFIX*data2` '
  577. ],
  578. [
  579. 'd1', 'data2', 'd2', null,
  580. ['`d1`' => [['joinType' => 'right', 'joinTable' => '`*PREFIX*data2`', 'joinAlias' => '`d2`', 'joinCondition' => null]]],
  581. '`*PREFIX*data1` `d1` RIGHT JOIN `*PREFIX*data2` `d2`'
  582. ],
  583. [
  584. 'd1', 'data2', 'd2', '`d1`.`field1` = `d2`.`field2`',
  585. ['`d1`' => [['joinType' => 'right', 'joinTable' => '`*PREFIX*data2`', 'joinAlias' => '`d2`', 'joinCondition' => '`d1`.`field1` = `d2`.`field2`']]],
  586. '`*PREFIX*data1` `d1` RIGHT JOIN `*PREFIX*data2` `d2` ON `d1`.`field1` = `d2`.`field2`'
  587. ],
  588. ];
  589. }
  590. /**
  591. * @dataProvider dataRightJoin
  592. *
  593. * @param string $fromAlias
  594. * @param string $tableName
  595. * @param string $tableAlias
  596. * @param string $condition
  597. * @param array $expectedQueryPart
  598. * @param string $expectedQuery
  599. */
  600. public function testRightJoin($fromAlias, $tableName, $tableAlias, $condition, $expectedQueryPart, $expectedQuery) {
  601. $this->queryBuilder->from('data1', 'd1');
  602. $this->queryBuilder->rightJoin(
  603. $fromAlias,
  604. $tableName,
  605. $tableAlias,
  606. $condition
  607. );
  608. $this->assertSame(
  609. $expectedQueryPart,
  610. $this->queryBuilder->getQueryPart('join')
  611. );
  612. $this->assertSame(
  613. 'SELECT FROM ' . $expectedQuery,
  614. $this->queryBuilder->getSQL()
  615. );
  616. }
  617. public function dataSet() {
  618. return [
  619. ['column1', new Literal('value'), null, null, ['`column1` = value'], '`column1` = value'],
  620. ['column1', new Parameter(':param'), null, null, ['`column1` = :param'], '`column1` = :param'],
  621. ['column1', 'column2', null, null, ['`column1` = `column2`'], '`column1` = `column2`'],
  622. ['column1', 'column2', 'column3', new Literal('value'), ['`column1` = `column2`', '`column3` = value'], '`column1` = `column2`, `column3` = value'],
  623. ];
  624. }
  625. /**
  626. * @dataProvider dataSet
  627. *
  628. * @param string $partOne1
  629. * @param string $partOne2
  630. * @param string $partTwo1
  631. * @param string $partTwo2
  632. * @param array $expectedQueryPart
  633. * @param string $expectedQuery
  634. */
  635. public function testSet($partOne1, $partOne2, $partTwo1, $partTwo2, $expectedQueryPart, $expectedQuery) {
  636. $this->queryBuilder->update('data');
  637. $this->queryBuilder->set($partOne1, $partOne2);
  638. if ($partTwo1 !== null) {
  639. $this->queryBuilder->set($partTwo1, $partTwo2);
  640. }
  641. $this->assertSame(
  642. $expectedQueryPart,
  643. $this->queryBuilder->getQueryPart('set')
  644. );
  645. $this->assertSame(
  646. 'UPDATE `*PREFIX*data` SET ' . $expectedQuery,
  647. $this->queryBuilder->getSQL()
  648. );
  649. }
  650. public function dataWhere() {
  651. return [
  652. [['where1'], new CompositeExpression('AND', ['where1']), 'where1'],
  653. [['where1', 'where2'], new CompositeExpression('AND', ['where1', 'where2']), '(where1) AND (where2)'],
  654. ];
  655. }
  656. /**
  657. * @dataProvider dataWhere
  658. *
  659. * @param array $whereArguments
  660. * @param array $expectedQueryPart
  661. * @param string $expectedQuery
  662. */
  663. public function testWhere($whereArguments, $expectedQueryPart, $expectedQuery) {
  664. $this->queryBuilder->select('column');
  665. call_user_func_array(
  666. [$this->queryBuilder, 'where'],
  667. $whereArguments
  668. );
  669. $this->assertEquals(
  670. $expectedQueryPart,
  671. $this->queryBuilder->getQueryPart('where')
  672. );
  673. $this->assertSame(
  674. 'SELECT `column` WHERE ' . $expectedQuery,
  675. $this->queryBuilder->getSQL()
  676. );
  677. }
  678. /**
  679. * @dataProvider dataWhere
  680. *
  681. * @param array $whereArguments
  682. * @param array $expectedQueryPart
  683. * @param string $expectedQuery
  684. */
  685. public function testAndWhere($whereArguments, $expectedQueryPart, $expectedQuery) {
  686. $this->queryBuilder->select('column');
  687. call_user_func_array(
  688. [$this->queryBuilder, 'andWhere'],
  689. $whereArguments
  690. );
  691. $this->assertEquals(
  692. $expectedQueryPart,
  693. $this->queryBuilder->getQueryPart('where')
  694. );
  695. $this->assertSame(
  696. 'SELECT `column` WHERE ' . $expectedQuery,
  697. $this->queryBuilder->getSQL()
  698. );
  699. }
  700. public function dataOrWhere() {
  701. return [
  702. [['where1'], new CompositeExpression('OR', ['where1']), 'where1'],
  703. [['where1', 'where2'], new CompositeExpression('OR', ['where1', 'where2']), '(where1) OR (where2)'],
  704. ];
  705. }
  706. /**
  707. * @dataProvider dataOrWhere
  708. *
  709. * @param array $whereArguments
  710. * @param array $expectedQueryPart
  711. * @param string $expectedQuery
  712. */
  713. public function testOrWhere($whereArguments, $expectedQueryPart, $expectedQuery) {
  714. $this->queryBuilder->select('column');
  715. call_user_func_array(
  716. [$this->queryBuilder, 'orWhere'],
  717. $whereArguments
  718. );
  719. $this->assertEquals(
  720. $expectedQueryPart,
  721. $this->queryBuilder->getQueryPart('where')
  722. );
  723. $this->assertSame(
  724. 'SELECT `column` WHERE ' . $expectedQuery,
  725. $this->queryBuilder->getSQL()
  726. );
  727. }
  728. public function dataGroupBy() {
  729. return [
  730. [['column1'], ['`column1`'], '`column1`'],
  731. [['column1', 'column2'], ['`column1`', '`column2`'], '`column1`, `column2`'],
  732. ];
  733. }
  734. /**
  735. * @dataProvider dataGroupBy
  736. *
  737. * @param array $groupByArguments
  738. * @param array $expectedQueryPart
  739. * @param string $expectedQuery
  740. */
  741. public function testGroupBy($groupByArguments, $expectedQueryPart, $expectedQuery) {
  742. $this->queryBuilder->select('column');
  743. call_user_func_array(
  744. [$this->queryBuilder, 'groupBy'],
  745. $groupByArguments
  746. );
  747. $this->assertEquals(
  748. $expectedQueryPart,
  749. $this->queryBuilder->getQueryPart('groupBy')
  750. );
  751. $this->assertSame(
  752. 'SELECT `column` GROUP BY ' . $expectedQuery,
  753. $this->queryBuilder->getSQL()
  754. );
  755. }
  756. public function dataAddGroupBy() {
  757. return [
  758. [['column2'], ['`column1`', '`column2`'], '`column1`, `column2`'],
  759. [['column2', 'column3'], ['`column1`', '`column2`', '`column3`'], '`column1`, `column2`, `column3`'],
  760. ];
  761. }
  762. /**
  763. * @dataProvider dataAddGroupBy
  764. *
  765. * @param array $groupByArguments
  766. * @param array $expectedQueryPart
  767. * @param string $expectedQuery
  768. */
  769. public function testAddGroupBy($groupByArguments, $expectedQueryPart, $expectedQuery) {
  770. $this->queryBuilder->select('column');
  771. $this->queryBuilder->groupBy('column1');
  772. call_user_func_array(
  773. [$this->queryBuilder, 'addGroupBy'],
  774. $groupByArguments
  775. );
  776. $this->assertEquals(
  777. $expectedQueryPart,
  778. $this->queryBuilder->getQueryPart('groupBy')
  779. );
  780. $this->assertSame(
  781. 'SELECT `column` GROUP BY ' . $expectedQuery,
  782. $this->queryBuilder->getSQL()
  783. );
  784. }
  785. public function dataSetValue() {
  786. return [
  787. ['column', 'value', ['`column`' => 'value'], '(`column`) VALUES(value)'],
  788. ];
  789. }
  790. /**
  791. * @dataProvider dataSetValue
  792. *
  793. * @param string $column
  794. * @param string $value
  795. * @param array $expectedQueryPart
  796. * @param string $expectedQuery
  797. */
  798. public function testSetValue($column, $value, $expectedQueryPart, $expectedQuery) {
  799. $this->queryBuilder->insert('data');
  800. $this->queryBuilder->setValue($column, $value);
  801. $this->assertEquals(
  802. $expectedQueryPart,
  803. $this->queryBuilder->getQueryPart('values')
  804. );
  805. $this->assertSame(
  806. 'INSERT INTO `*PREFIX*data` ' . $expectedQuery,
  807. $this->queryBuilder->getSQL()
  808. );
  809. }
  810. /**
  811. * @dataProvider dataSetValue
  812. *
  813. * @param string $column
  814. * @param string $value
  815. * @param array $expectedQueryPart
  816. * @param string $expectedQuery
  817. */
  818. public function testValues($column, $value, $expectedQueryPart, $expectedQuery) {
  819. $this->queryBuilder->insert('data');
  820. $this->queryBuilder->values([
  821. $column => $value,
  822. ]);
  823. $this->assertEquals(
  824. $expectedQueryPart,
  825. $this->queryBuilder->getQueryPart('values')
  826. );
  827. $this->assertSame(
  828. 'INSERT INTO `*PREFIX*data` ' . $expectedQuery,
  829. $this->queryBuilder->getSQL()
  830. );
  831. }
  832. public function dataHaving() {
  833. return [
  834. [['condition1'], new CompositeExpression('AND', ['condition1']), 'HAVING condition1'],
  835. [['condition1', 'condition2'], new CompositeExpression('AND', ['condition1', 'condition2']), 'HAVING (condition1) AND (condition2)'],
  836. [
  837. [new CompositeExpression('OR', ['condition1', 'condition2'])],
  838. new CompositeExpression('OR', ['condition1', 'condition2']),
  839. 'HAVING (condition1) OR (condition2)'
  840. ],
  841. [
  842. [new CompositeExpression('AND', ['condition1', 'condition2'])],
  843. new CompositeExpression('AND', ['condition1', 'condition2']),
  844. 'HAVING (condition1) AND (condition2)'
  845. ],
  846. ];
  847. }
  848. /**
  849. * @dataProvider dataHaving
  850. *
  851. * @param array $havingArguments
  852. * @param array $expectedQueryPart
  853. * @param string $expectedQuery
  854. */
  855. public function testHaving($havingArguments, $expectedQueryPart, $expectedQuery) {
  856. call_user_func_array(
  857. [$this->queryBuilder, 'having'],
  858. $havingArguments
  859. );
  860. $this->assertEquals(
  861. $expectedQueryPart,
  862. $this->queryBuilder->getQueryPart('having')
  863. );
  864. $this->assertSame(
  865. 'SELECT ' . $expectedQuery,
  866. $this->queryBuilder->getSQL()
  867. );
  868. }
  869. public function dataAndHaving() {
  870. return [
  871. [['condition2'], new CompositeExpression('AND', ['condition1', 'condition2']), 'HAVING (condition1) AND (condition2)'],
  872. [['condition2', 'condition3'], new CompositeExpression('AND', ['condition1', 'condition2', 'condition3']), 'HAVING (condition1) AND (condition2) AND (condition3)'],
  873. [
  874. [new CompositeExpression('OR', ['condition2', 'condition3'])],
  875. new CompositeExpression('AND', ['condition1', new CompositeExpression('OR', ['condition2', 'condition3'])]),
  876. 'HAVING (condition1) AND ((condition2) OR (condition3))'
  877. ],
  878. [
  879. [new CompositeExpression('AND', ['condition2', 'condition3'])],
  880. new CompositeExpression('AND', ['condition1', new CompositeExpression('AND', ['condition2', 'condition3'])]),
  881. 'HAVING (condition1) AND ((condition2) AND (condition3))'
  882. ],
  883. ];
  884. }
  885. /**
  886. * @dataProvider dataAndHaving
  887. *
  888. * @param array $havingArguments
  889. * @param array $expectedQueryPart
  890. * @param string $expectedQuery
  891. */
  892. public function testAndHaving($havingArguments, $expectedQueryPart, $expectedQuery) {
  893. $this->queryBuilder->having('condition1');
  894. call_user_func_array(
  895. [$this->queryBuilder, 'andHaving'],
  896. $havingArguments
  897. );
  898. $this->assertEquals(
  899. $expectedQueryPart,
  900. $this->queryBuilder->getQueryPart('having')
  901. );
  902. $this->assertSame(
  903. 'SELECT ' . $expectedQuery,
  904. $this->queryBuilder->getSQL()
  905. );
  906. }
  907. public function dataOrHaving() {
  908. return [
  909. [['condition2'], new CompositeExpression('OR', ['condition1', 'condition2']), 'HAVING (condition1) OR (condition2)'],
  910. [['condition2', 'condition3'], new CompositeExpression('OR', ['condition1', 'condition2', 'condition3']), 'HAVING (condition1) OR (condition2) OR (condition3)'],
  911. [
  912. [new CompositeExpression('OR', ['condition2', 'condition3'])],
  913. new CompositeExpression('OR', ['condition1', new CompositeExpression('OR', ['condition2', 'condition3'])]),
  914. 'HAVING (condition1) OR ((condition2) OR (condition3))'
  915. ],
  916. [
  917. [new CompositeExpression('AND', ['condition2', 'condition3'])],
  918. new CompositeExpression('OR', ['condition1', new CompositeExpression('AND', ['condition2', 'condition3'])]),
  919. 'HAVING (condition1) OR ((condition2) AND (condition3))'
  920. ],
  921. ];
  922. }
  923. /**
  924. * @dataProvider dataOrHaving
  925. *
  926. * @param array $havingArguments
  927. * @param array $expectedQueryPart
  928. * @param string $expectedQuery
  929. */
  930. public function testOrHaving($havingArguments, $expectedQueryPart, $expectedQuery) {
  931. $this->queryBuilder->having('condition1');
  932. call_user_func_array(
  933. [$this->queryBuilder, 'orHaving'],
  934. $havingArguments
  935. );
  936. $this->assertEquals(
  937. $expectedQueryPart,
  938. $this->queryBuilder->getQueryPart('having')
  939. );
  940. $this->assertSame(
  941. 'SELECT ' . $expectedQuery,
  942. $this->queryBuilder->getSQL()
  943. );
  944. }
  945. public function dataOrderBy() {
  946. return [
  947. ['column', null, ['`column` ASC'], 'ORDER BY `column` ASC'],
  948. ['column', 'ASC', ['`column` ASC'], 'ORDER BY `column` ASC'],
  949. ['column', 'DESC', ['`column` DESC'], 'ORDER BY `column` DESC'],
  950. ];
  951. }
  952. /**
  953. * @dataProvider dataOrderBy
  954. *
  955. * @param string $sort
  956. * @param string $order
  957. * @param array $expectedQueryPart
  958. * @param string $expectedQuery
  959. */
  960. public function testOrderBy($sort, $order, $expectedQueryPart, $expectedQuery) {
  961. $this->queryBuilder->orderBy($sort, $order);
  962. $this->assertEquals(
  963. $expectedQueryPart,
  964. $this->queryBuilder->getQueryPart('orderBy')
  965. );
  966. $this->assertSame(
  967. 'SELECT ' . $expectedQuery,
  968. $this->queryBuilder->getSQL()
  969. );
  970. }
  971. public function dataAddOrderBy() {
  972. return [
  973. ['column2', null, null, ['`column1` ASC', '`column2` ASC'], 'ORDER BY `column1` ASC, `column2` ASC'],
  974. ['column2', null, 'ASC', ['`column1` ASC', '`column2` ASC'], 'ORDER BY `column1` ASC, `column2` ASC'],
  975. ['column2', null, 'DESC', ['`column1` DESC', '`column2` ASC'], 'ORDER BY `column1` DESC, `column2` ASC'],
  976. ['column2', 'ASC', null, ['`column1` ASC', '`column2` ASC'], 'ORDER BY `column1` ASC, `column2` ASC'],
  977. ['column2', 'ASC', 'ASC', ['`column1` ASC', '`column2` ASC'], 'ORDER BY `column1` ASC, `column2` ASC'],
  978. ['column2', 'ASC', 'DESC', ['`column1` DESC', '`column2` ASC'], 'ORDER BY `column1` DESC, `column2` ASC'],
  979. ['column2', 'DESC', null, ['`column1` ASC', '`column2` DESC'], 'ORDER BY `column1` ASC, `column2` DESC'],
  980. ['column2', 'DESC', 'ASC', ['`column1` ASC', '`column2` DESC'], 'ORDER BY `column1` ASC, `column2` DESC'],
  981. ['column2', 'DESC', 'DESC', ['`column1` DESC', '`column2` DESC'], 'ORDER BY `column1` DESC, `column2` DESC'],
  982. ];
  983. }
  984. /**
  985. * @dataProvider dataAddOrderBy
  986. *
  987. * @param string $sort2
  988. * @param string $order2
  989. * @param string $order1
  990. * @param array $expectedQueryPart
  991. * @param string $expectedQuery
  992. */
  993. public function testAddOrderBy($sort2, $order2, $order1, $expectedQueryPart, $expectedQuery) {
  994. $this->queryBuilder->orderBy('column1', $order1);
  995. $this->queryBuilder->addOrderBy($sort2, $order2);
  996. $this->assertEquals(
  997. $expectedQueryPart,
  998. $this->queryBuilder->getQueryPart('orderBy')
  999. );
  1000. $this->assertSame(
  1001. 'SELECT ' . $expectedQuery,
  1002. $this->queryBuilder->getSQL()
  1003. );
  1004. }
  1005. public function testGetLastInsertId() {
  1006. $qB = $this->connection->getQueryBuilder();
  1007. try {
  1008. $qB->getLastInsertId();
  1009. $this->fail('getLastInsertId() should throw an exception, when being called before insert()');
  1010. } catch (\BadMethodCallException $e) {
  1011. $this->addToAssertionCount(1);
  1012. }
  1013. $qB->insert('properties')
  1014. ->values([
  1015. 'userid' => $qB->expr()->literal('testFirstResult'),
  1016. 'propertypath' => $qB->expr()->literal('testing'),
  1017. 'propertyname' => $qB->expr()->literal('testing'),
  1018. 'propertyvalue' => $qB->expr()->literal('testing'),
  1019. ])
  1020. ->execute();
  1021. $actual = $qB->getLastInsertId();
  1022. $this->assertNotNull($actual);
  1023. $this->assertIsInt($actual);
  1024. $this->assertEquals($this->connection->lastInsertId('*PREFIX*properties'), $actual);
  1025. $qB->delete('properties')
  1026. ->where($qB->expr()->eq('userid', $qB->expr()->literal('testFirstResult')))
  1027. ->execute();
  1028. try {
  1029. $qB->getLastInsertId();
  1030. $this->fail('getLastInsertId() should throw an exception, when being called after delete()');
  1031. } catch (\BadMethodCallException $e) {
  1032. $this->addToAssertionCount(1);
  1033. }
  1034. }
  1035. public function dataGetTableName() {
  1036. $config = $this->createMock(SystemConfig::class);
  1037. $logger = $this->createMock(LoggerInterface::class);
  1038. $qb = new QueryBuilder(\OC::$server->getDatabaseConnection(), $config, $logger);
  1039. return [
  1040. ['*PREFIX*table', null, '`*PREFIX*table`'],
  1041. ['*PREFIX*table', true, '`*PREFIX*table`'],
  1042. ['*PREFIX*table', false, '`*PREFIX*table`'],
  1043. ['table', null, '`*PREFIX*table`'],
  1044. ['table', true, '`*PREFIX*table`'],
  1045. ['table', false, '`table`'],
  1046. [$qb->createFunction('(' . $qb->select('*')->from('table')->getSQL() . ')'), null, '(SELECT * FROM `*PREFIX*table`)'],
  1047. [$qb->createFunction('(' . $qb->select('*')->from('table')->getSQL() . ')'), true, '(SELECT * FROM `*PREFIX*table`)'],
  1048. [$qb->createFunction('(' . $qb->select('*')->from('table')->getSQL() . ')'), false, '(SELECT * FROM `*PREFIX*table`)'],
  1049. ];
  1050. }
  1051. /**
  1052. * @dataProvider dataGetTableName
  1053. *
  1054. * @param string|IQueryFunction $tableName
  1055. * @param bool $automatic
  1056. * @param string $expected
  1057. */
  1058. public function testGetTableName($tableName, $automatic, $expected) {
  1059. if ($automatic !== null) {
  1060. $this->queryBuilder->automaticTablePrefix($automatic);
  1061. }
  1062. $this->assertSame(
  1063. $expected,
  1064. $this->queryBuilder->getTableName($tableName)
  1065. );
  1066. }
  1067. public function dataGetColumnName() {
  1068. return [
  1069. ['column', '', '`column`'],
  1070. ['column', 'a', '`a`.`column`'],
  1071. ];
  1072. }
  1073. /**
  1074. * @dataProvider dataGetColumnName
  1075. * @param string $column
  1076. * @param string $prefix
  1077. * @param string $expected
  1078. */
  1079. public function testGetColumnName($column, $prefix, $expected) {
  1080. $this->assertSame(
  1081. $expected,
  1082. $this->queryBuilder->getColumnName($column, $prefix)
  1083. );
  1084. }
  1085. public function testExecuteWithoutLogger() {
  1086. $queryBuilder = $this->createMock(\Doctrine\DBAL\Query\QueryBuilder::class);
  1087. $queryBuilder
  1088. ->expects($this->once())
  1089. ->method('execute')
  1090. ->willReturn(3);
  1091. $queryBuilder
  1092. ->expects($this->any())
  1093. ->method('getParameters')
  1094. ->willReturn([]);
  1095. $this->logger
  1096. ->expects($this->never())
  1097. ->method('debug');
  1098. $this->config
  1099. ->expects($this->once())
  1100. ->method('getValue')
  1101. ->with('log_query', false)
  1102. ->willReturn(false);
  1103. $this->invokePrivate($this->queryBuilder, 'queryBuilder', [$queryBuilder]);
  1104. $this->assertEquals(3, $this->queryBuilder->execute());
  1105. }
  1106. public function testExecuteWithLoggerAndNamedArray() {
  1107. $queryBuilder = $this->createMock(\Doctrine\DBAL\Query\QueryBuilder::class);
  1108. $queryBuilder
  1109. ->expects($this->any())
  1110. ->method('getParameters')
  1111. ->willReturn([
  1112. 'foo' => 'bar',
  1113. 'key' => 'value',
  1114. ]);
  1115. $queryBuilder
  1116. ->expects($this->any())
  1117. ->method('getSQL')
  1118. ->willReturn('SELECT * FROM FOO WHERE BAR = ?');
  1119. $queryBuilder
  1120. ->expects($this->once())
  1121. ->method('execute')
  1122. ->willReturn(3);
  1123. $this->logger
  1124. ->expects($this->once())
  1125. ->method('debug')
  1126. ->with(
  1127. 'DB QueryBuilder: \'{query}\' with parameters: {params}',
  1128. [
  1129. 'query' => 'SELECT * FROM FOO WHERE BAR = ?',
  1130. 'params' => 'foo => \'bar\', key => \'value\'',
  1131. 'app' => 'core',
  1132. ]
  1133. );
  1134. $this->config
  1135. ->expects($this->once())
  1136. ->method('getValue')
  1137. ->with('log_query', false)
  1138. ->willReturn(true);
  1139. $this->invokePrivate($this->queryBuilder, 'queryBuilder', [$queryBuilder]);
  1140. $this->assertEquals(3, $this->queryBuilder->execute());
  1141. }
  1142. public function testExecuteWithLoggerAndUnnamedArray() {
  1143. $queryBuilder = $this->createMock(\Doctrine\DBAL\Query\QueryBuilder::class);
  1144. $queryBuilder
  1145. ->expects($this->any())
  1146. ->method('getParameters')
  1147. ->willReturn(['Bar']);
  1148. $queryBuilder
  1149. ->expects($this->any())
  1150. ->method('getSQL')
  1151. ->willReturn('SELECT * FROM FOO WHERE BAR = ?');
  1152. $queryBuilder
  1153. ->expects($this->once())
  1154. ->method('execute')
  1155. ->willReturn(3);
  1156. $this->logger
  1157. ->expects($this->once())
  1158. ->method('debug')
  1159. ->with(
  1160. 'DB QueryBuilder: \'{query}\' with parameters: {params}',
  1161. [
  1162. 'query' => 'SELECT * FROM FOO WHERE BAR = ?',
  1163. 'params' => '0 => \'Bar\'',
  1164. 'app' => 'core',
  1165. ]
  1166. );
  1167. $this->config
  1168. ->expects($this->once())
  1169. ->method('getValue')
  1170. ->with('log_query', false)
  1171. ->willReturn(true);
  1172. $this->invokePrivate($this->queryBuilder, 'queryBuilder', [$queryBuilder]);
  1173. $this->assertEquals(3, $this->queryBuilder->execute());
  1174. }
  1175. public function testExecuteWithLoggerAndNoParams() {
  1176. $queryBuilder = $this->createMock(\Doctrine\DBAL\Query\QueryBuilder::class);
  1177. $queryBuilder
  1178. ->expects($this->any())
  1179. ->method('getParameters')
  1180. ->willReturn([]);
  1181. $queryBuilder
  1182. ->expects($this->any())
  1183. ->method('getSQL')
  1184. ->willReturn('SELECT * FROM FOO WHERE BAR = ?');
  1185. $queryBuilder
  1186. ->expects($this->once())
  1187. ->method('execute')
  1188. ->willReturn(3);
  1189. $this->logger
  1190. ->expects($this->once())
  1191. ->method('debug')
  1192. ->with(
  1193. 'DB QueryBuilder: \'{query}\'',
  1194. [
  1195. 'query' => 'SELECT * FROM FOO WHERE BAR = ?',
  1196. 'app' => 'core',
  1197. ]
  1198. );
  1199. $this->config
  1200. ->expects($this->once())
  1201. ->method('getValue')
  1202. ->with('log_query', false)
  1203. ->willReturn(true);
  1204. $this->invokePrivate($this->queryBuilder, 'queryBuilder', [$queryBuilder]);
  1205. $this->assertEquals(3, $this->queryBuilder->execute());
  1206. }
  1207. public function testExecuteWithParameterTooLarge() {
  1208. $queryBuilder = $this->createMock(\Doctrine\DBAL\Query\QueryBuilder::class);
  1209. $p = array_fill(0, 1001, 'foo');
  1210. $queryBuilder
  1211. ->expects($this->any())
  1212. ->method('getParameters')
  1213. ->willReturn([$p]);
  1214. $queryBuilder
  1215. ->expects($this->any())
  1216. ->method('getSQL')
  1217. ->willReturn('SELECT * FROM FOO WHERE BAR IN (?)');
  1218. $queryBuilder
  1219. ->expects($this->once())
  1220. ->method('execute')
  1221. ->willReturn($this->createMock(Result::class));
  1222. $this->logger
  1223. ->expects($this->once())
  1224. ->method('error')
  1225. ->willReturnCallback(function ($message, $parameters) {
  1226. $this->assertInstanceOf(QueryException::class, $parameters['exception']);
  1227. $this->assertSame(
  1228. 'More than 1000 expressions in a list are not allowed on Oracle.',
  1229. $message
  1230. );
  1231. });
  1232. $this->config
  1233. ->expects($this->once())
  1234. ->method('getValue')
  1235. ->with('log_query', false)
  1236. ->willReturn(false);
  1237. $this->invokePrivate($this->queryBuilder, 'queryBuilder', [$queryBuilder]);
  1238. $this->queryBuilder->execute();
  1239. }
  1240. public function testExecuteWithParametersTooMany() {
  1241. $queryBuilder = $this->createMock(\Doctrine\DBAL\Query\QueryBuilder::class);
  1242. $p = array_fill(0, 999, 'foo');
  1243. $queryBuilder
  1244. ->expects($this->any())
  1245. ->method('getParameters')
  1246. ->willReturn(array_fill(0, 66, $p));
  1247. $queryBuilder
  1248. ->expects($this->any())
  1249. ->method('getSQL')
  1250. ->willReturn('SELECT * FROM FOO WHERE BAR IN (?) OR BAR IN (?)');
  1251. $queryBuilder
  1252. ->expects($this->once())
  1253. ->method('execute')
  1254. ->willReturn($this->createMock(Result::class));
  1255. $this->logger
  1256. ->expects($this->once())
  1257. ->method('error')
  1258. ->willReturnCallback(function ($message, $parameters) {
  1259. $this->assertInstanceOf(QueryException::class, $parameters['exception']);
  1260. $this->assertSame(
  1261. 'The number of parameters must not exceed 65535. Restriction by PostgreSQL.',
  1262. $message
  1263. );
  1264. });
  1265. $this->config
  1266. ->expects($this->once())
  1267. ->method('getValue')
  1268. ->with('log_query', false)
  1269. ->willReturn(false);
  1270. $this->invokePrivate($this->queryBuilder, 'queryBuilder', [$queryBuilder]);
  1271. $this->queryBuilder->execute();
  1272. }
  1273. }