QueryBuilder.php 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Joas Schilling <coding@schilljs.com>
  6. * @author Lukas Reschke <lukas@statuscode.ch>
  7. * @author Robin Appelman <robin@icewind.nl>
  8. * @author Thomas Müller <thomas.mueller@tmit.eu>
  9. *
  10. * @license AGPL-3.0
  11. *
  12. * This code is free software: you can redistribute it and/or modify
  13. * it under the terms of the GNU Affero General Public License, version 3,
  14. * as published by the Free Software Foundation.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU Affero General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU Affero General Public License, version 3,
  22. * along with this program. If not, see <http://www.gnu.org/licenses/>
  23. *
  24. */
  25. namespace OC\DB\QueryBuilder;
  26. use Doctrine\DBAL\Platforms\MySqlPlatform;
  27. use Doctrine\DBAL\Platforms\PostgreSqlPlatform;
  28. use Doctrine\DBAL\Platforms\SqlitePlatform;
  29. use OC\DB\OracleConnection;
  30. use OC\DB\QueryBuilder\ExpressionBuilder\ExpressionBuilder;
  31. use OC\DB\QueryBuilder\ExpressionBuilder\MySqlExpressionBuilder;
  32. use OC\DB\QueryBuilder\ExpressionBuilder\OCIExpressionBuilder;
  33. use OC\DB\QueryBuilder\ExpressionBuilder\PgSqlExpressionBuilder;
  34. use OC\DB\QueryBuilder\ExpressionBuilder\SqliteExpressionBuilder;
  35. use OC\DB\QueryBuilder\FunctionBuilder\FunctionBuilder;
  36. use OC\DB\QueryBuilder\FunctionBuilder\OCIFunctionBuilder;
  37. use OC\DB\QueryBuilder\FunctionBuilder\PgSqlFunctionBuilder;
  38. use OC\DB\QueryBuilder\FunctionBuilder\SqliteFunctionBuilder;
  39. use OC\SystemConfig;
  40. use OCP\DB\QueryBuilder\IQueryBuilder;
  41. use OCP\DB\QueryBuilder\IQueryFunction;
  42. use OCP\DB\QueryBuilder\IParameter;
  43. use OCP\IDBConnection;
  44. use OCP\ILogger;
  45. class QueryBuilder implements IQueryBuilder {
  46. /** @var \OCP\IDBConnection */
  47. private $connection;
  48. /** @var SystemConfig */
  49. private $systemConfig;
  50. /** @var ILogger */
  51. private $logger;
  52. /** @var \Doctrine\DBAL\Query\QueryBuilder */
  53. private $queryBuilder;
  54. /** @var QuoteHelper */
  55. private $helper;
  56. /** @var bool */
  57. private $automaticTablePrefix = true;
  58. /** @var string */
  59. protected $lastInsertedTable;
  60. /**
  61. * Initializes a new QueryBuilder.
  62. *
  63. * @param IDBConnection $connection
  64. * @param SystemConfig $systemConfig
  65. * @param ILogger $logger
  66. */
  67. public function __construct(IDBConnection $connection, SystemConfig $systemConfig, ILogger $logger) {
  68. $this->connection = $connection;
  69. $this->systemConfig = $systemConfig;
  70. $this->logger = $logger;
  71. $this->queryBuilder = new \Doctrine\DBAL\Query\QueryBuilder($this->connection);
  72. $this->helper = new QuoteHelper();
  73. }
  74. /**
  75. * Enable/disable automatic prefixing of table names with the oc_ prefix
  76. *
  77. * @param bool $enabled If set to true table names will be prefixed with the
  78. * owncloud database prefix automatically.
  79. * @since 8.2.0
  80. */
  81. public function automaticTablePrefix($enabled) {
  82. $this->automaticTablePrefix = (bool) $enabled;
  83. }
  84. /**
  85. * Gets an ExpressionBuilder used for object-oriented construction of query expressions.
  86. * This producer method is intended for convenient inline usage. Example:
  87. *
  88. * <code>
  89. * $qb = $conn->getQueryBuilder()
  90. * ->select('u')
  91. * ->from('users', 'u')
  92. * ->where($qb->expr()->eq('u.id', 1));
  93. * </code>
  94. *
  95. * For more complex expression construction, consider storing the expression
  96. * builder object in a local variable.
  97. *
  98. * @return \OCP\DB\QueryBuilder\IExpressionBuilder
  99. */
  100. public function expr() {
  101. if ($this->connection instanceof OracleConnection) {
  102. return new OCIExpressionBuilder($this->connection, $this);
  103. } else if ($this->connection->getDatabasePlatform() instanceof PostgreSqlPlatform) {
  104. return new PgSqlExpressionBuilder($this->connection, $this);
  105. } else if ($this->connection->getDatabasePlatform() instanceof MySqlPlatform) {
  106. return new MySqlExpressionBuilder($this->connection, $this);
  107. } else if ($this->connection->getDatabasePlatform() instanceof SqlitePlatform) {
  108. return new SqliteExpressionBuilder($this->connection, $this);
  109. } else {
  110. return new ExpressionBuilder($this->connection, $this);
  111. }
  112. }
  113. /**
  114. * Gets an FunctionBuilder used for object-oriented construction of query functions.
  115. * This producer method is intended for convenient inline usage. Example:
  116. *
  117. * <code>
  118. * $qb = $conn->getQueryBuilder()
  119. * ->select('u')
  120. * ->from('users', 'u')
  121. * ->where($qb->fun()->md5('u.id'));
  122. * </code>
  123. *
  124. * For more complex function construction, consider storing the function
  125. * builder object in a local variable.
  126. *
  127. * @return \OCP\DB\QueryBuilder\IFunctionBuilder
  128. */
  129. public function func() {
  130. if ($this->connection instanceof OracleConnection) {
  131. return new OCIFunctionBuilder($this->helper);
  132. } else if ($this->connection->getDatabasePlatform() instanceof SqlitePlatform) {
  133. return new SqliteFunctionBuilder($this->helper);
  134. } else if ($this->connection->getDatabasePlatform() instanceof PostgreSqlPlatform) {
  135. return new PgSqlFunctionBuilder($this->helper);
  136. } else {
  137. return new FunctionBuilder($this->helper);
  138. }
  139. }
  140. /**
  141. * Gets the type of the currently built query.
  142. *
  143. * @return integer
  144. */
  145. public function getType() {
  146. return $this->queryBuilder->getType();
  147. }
  148. /**
  149. * Gets the associated DBAL Connection for this query builder.
  150. *
  151. * @return \OCP\IDBConnection
  152. */
  153. public function getConnection() {
  154. return $this->connection;
  155. }
  156. /**
  157. * Gets the state of this query builder instance.
  158. *
  159. * @return integer Either QueryBuilder::STATE_DIRTY or QueryBuilder::STATE_CLEAN.
  160. */
  161. public function getState() {
  162. return $this->queryBuilder->getState();
  163. }
  164. /**
  165. * Executes this query using the bound parameters and their types.
  166. *
  167. * Uses {@see Connection::executeQuery} for select statements and {@see Connection::executeUpdate}
  168. * for insert, update and delete statements.
  169. *
  170. * @return \Doctrine\DBAL\Driver\Statement|int
  171. */
  172. public function execute() {
  173. if ($this->systemConfig->getValue('log_query', false)) {
  174. $params = [];
  175. foreach ($this->getParameters() as $placeholder => $value) {
  176. if (is_array($value)) {
  177. $params[] = $placeholder . ' => (\'' . implode('\', \'', $value) . '\')';
  178. } else {
  179. $params[] = $placeholder . ' => \'' . $value . '\'';
  180. }
  181. }
  182. if (empty($params)) {
  183. $this->logger->debug('DB QueryBuilder: \'{query}\'', [
  184. 'query' => $this->getSQL(),
  185. 'app' => 'core',
  186. ]);
  187. } else {
  188. $this->logger->debug('DB QueryBuilder: \'{query}\' with parameters: {params}', [
  189. 'query' => $this->getSQL(),
  190. 'params' => implode(', ', $params),
  191. 'app' => 'core',
  192. ]);
  193. }
  194. }
  195. return $this->queryBuilder->execute();
  196. }
  197. /**
  198. * Gets the complete SQL string formed by the current specifications of this QueryBuilder.
  199. *
  200. * <code>
  201. * $qb = $conn->getQueryBuilder()
  202. * ->select('u')
  203. * ->from('User', 'u')
  204. * echo $qb->getSQL(); // SELECT u FROM User u
  205. * </code>
  206. *
  207. * @return string The SQL query string.
  208. */
  209. public function getSQL() {
  210. return $this->queryBuilder->getSQL();
  211. }
  212. /**
  213. * Sets a query parameter for the query being constructed.
  214. *
  215. * <code>
  216. * $qb = $conn->getQueryBuilder()
  217. * ->select('u')
  218. * ->from('users', 'u')
  219. * ->where('u.id = :user_id')
  220. * ->setParameter(':user_id', 1);
  221. * </code>
  222. *
  223. * @param string|integer $key The parameter position or name.
  224. * @param mixed $value The parameter value.
  225. * @param string|null|int $type One of the IQueryBuilder::PARAM_* constants.
  226. *
  227. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  228. */
  229. public function setParameter($key, $value, $type = null) {
  230. $this->queryBuilder->setParameter($key, $value, $type);
  231. return $this;
  232. }
  233. /**
  234. * Sets a collection of query parameters for the query being constructed.
  235. *
  236. * <code>
  237. * $qb = $conn->getQueryBuilder()
  238. * ->select('u')
  239. * ->from('users', 'u')
  240. * ->where('u.id = :user_id1 OR u.id = :user_id2')
  241. * ->setParameters(array(
  242. * ':user_id1' => 1,
  243. * ':user_id2' => 2
  244. * ));
  245. * </code>
  246. *
  247. * @param array $params The query parameters to set.
  248. * @param array $types The query parameters types to set.
  249. *
  250. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  251. */
  252. public function setParameters(array $params, array $types = array()) {
  253. $this->queryBuilder->setParameters($params, $types);
  254. return $this;
  255. }
  256. /**
  257. * Gets all defined query parameters for the query being constructed indexed by parameter index or name.
  258. *
  259. * @return array The currently defined query parameters indexed by parameter index or name.
  260. */
  261. public function getParameters() {
  262. return $this->queryBuilder->getParameters();
  263. }
  264. /**
  265. * Gets a (previously set) query parameter of the query being constructed.
  266. *
  267. * @param mixed $key The key (index or name) of the bound parameter.
  268. *
  269. * @return mixed The value of the bound parameter.
  270. */
  271. public function getParameter($key) {
  272. return $this->queryBuilder->getParameter($key);
  273. }
  274. /**
  275. * Gets all defined query parameter types for the query being constructed indexed by parameter index or name.
  276. *
  277. * @return array The currently defined query parameter types indexed by parameter index or name.
  278. */
  279. public function getParameterTypes() {
  280. return $this->queryBuilder->getParameterTypes();
  281. }
  282. /**
  283. * Gets a (previously set) query parameter type of the query being constructed.
  284. *
  285. * @param mixed $key The key (index or name) of the bound parameter type.
  286. *
  287. * @return mixed The value of the bound parameter type.
  288. */
  289. public function getParameterType($key) {
  290. return $this->queryBuilder->getParameterType($key);
  291. }
  292. /**
  293. * Sets the position of the first result to retrieve (the "offset").
  294. *
  295. * @param integer $firstResult The first result to return.
  296. *
  297. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  298. */
  299. public function setFirstResult($firstResult) {
  300. $this->queryBuilder->setFirstResult($firstResult);
  301. return $this;
  302. }
  303. /**
  304. * Gets the position of the first result the query object was set to retrieve (the "offset").
  305. * Returns NULL if {@link setFirstResult} was not applied to this QueryBuilder.
  306. *
  307. * @return integer The position of the first result.
  308. */
  309. public function getFirstResult() {
  310. return $this->queryBuilder->getFirstResult();
  311. }
  312. /**
  313. * Sets the maximum number of results to retrieve (the "limit").
  314. *
  315. * NOTE: Setting max results to "0" will cause mixed behaviour. While most
  316. * of the databases will just return an empty result set, Oracle will return
  317. * all entries.
  318. *
  319. * @param integer $maxResults The maximum number of results to retrieve.
  320. *
  321. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  322. */
  323. public function setMaxResults($maxResults) {
  324. $this->queryBuilder->setMaxResults($maxResults);
  325. return $this;
  326. }
  327. /**
  328. * Gets the maximum number of results the query object was set to retrieve (the "limit").
  329. * Returns NULL if {@link setMaxResults} was not applied to this query builder.
  330. *
  331. * @return integer The maximum number of results.
  332. */
  333. public function getMaxResults() {
  334. return $this->queryBuilder->getMaxResults();
  335. }
  336. /**
  337. * Specifies an item that is to be returned in the query result.
  338. * Replaces any previously specified selections, if any.
  339. *
  340. * <code>
  341. * $qb = $conn->getQueryBuilder()
  342. * ->select('u.id', 'p.id')
  343. * ->from('users', 'u')
  344. * ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id');
  345. * </code>
  346. *
  347. * @param mixed ...$selects The selection expressions.
  348. *
  349. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  350. */
  351. public function select(...$selects) {
  352. if (count($selects) === 1 && is_array($selects[0])) {
  353. $selects = $selects[0];
  354. }
  355. $this->queryBuilder->select(
  356. $this->helper->quoteColumnNames($selects)
  357. );
  358. return $this;
  359. }
  360. /**
  361. * Specifies an item that is to be returned with a different name in the query result.
  362. *
  363. * <code>
  364. * $qb = $conn->getQueryBuilder()
  365. * ->selectAlias('u.id', 'user_id')
  366. * ->from('users', 'u')
  367. * ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id');
  368. * </code>
  369. *
  370. * @param mixed $select The selection expressions.
  371. * @param string $alias The column alias used in the constructed query.
  372. *
  373. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  374. */
  375. public function selectAlias($select, $alias) {
  376. $this->queryBuilder->addSelect(
  377. $this->helper->quoteColumnName($select) . ' AS ' . $this->helper->quoteColumnName($alias)
  378. );
  379. return $this;
  380. }
  381. /**
  382. * Specifies an item that is to be returned uniquely in the query result.
  383. *
  384. * <code>
  385. * $qb = $conn->getQueryBuilder()
  386. * ->selectDistinct('type')
  387. * ->from('users');
  388. * </code>
  389. *
  390. * @param mixed $select The selection expressions.
  391. *
  392. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  393. */
  394. public function selectDistinct($select) {
  395. $this->queryBuilder->addSelect(
  396. 'DISTINCT ' . $this->helper->quoteColumnName($select)
  397. );
  398. return $this;
  399. }
  400. /**
  401. * Adds an item that is to be returned in the query result.
  402. *
  403. * <code>
  404. * $qb = $conn->getQueryBuilder()
  405. * ->select('u.id')
  406. * ->addSelect('p.id')
  407. * ->from('users', 'u')
  408. * ->leftJoin('u', 'phonenumbers', 'u.id = p.user_id');
  409. * </code>
  410. *
  411. * @param mixed ...$selects The selection expression.
  412. *
  413. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  414. */
  415. public function addSelect(...$selects) {
  416. if (count($selects) === 1 && is_array($selects[0])) {
  417. $selects = $selects[0];
  418. }
  419. $this->queryBuilder->addSelect(
  420. $this->helper->quoteColumnNames($selects)
  421. );
  422. return $this;
  423. }
  424. /**
  425. * Turns the query being built into a bulk delete query that ranges over
  426. * a certain table.
  427. *
  428. * <code>
  429. * $qb = $conn->getQueryBuilder()
  430. * ->delete('users', 'u')
  431. * ->where('u.id = :user_id');
  432. * ->setParameter(':user_id', 1);
  433. * </code>
  434. *
  435. * @param string $delete The table whose rows are subject to the deletion.
  436. * @param string $alias The table alias used in the constructed query.
  437. *
  438. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  439. */
  440. public function delete($delete = null, $alias = null) {
  441. $this->queryBuilder->delete(
  442. $this->getTableName($delete),
  443. $alias
  444. );
  445. return $this;
  446. }
  447. /**
  448. * Turns the query being built into a bulk update query that ranges over
  449. * a certain table
  450. *
  451. * <code>
  452. * $qb = $conn->getQueryBuilder()
  453. * ->update('users', 'u')
  454. * ->set('u.password', md5('password'))
  455. * ->where('u.id = ?');
  456. * </code>
  457. *
  458. * @param string $update The table whose rows are subject to the update.
  459. * @param string $alias The table alias used in the constructed query.
  460. *
  461. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  462. */
  463. public function update($update = null, $alias = null) {
  464. $this->queryBuilder->update(
  465. $this->getTableName($update),
  466. $alias
  467. );
  468. return $this;
  469. }
  470. /**
  471. * Turns the query being built into an insert query that inserts into
  472. * a certain table
  473. *
  474. * <code>
  475. * $qb = $conn->getQueryBuilder()
  476. * ->insert('users')
  477. * ->values(
  478. * array(
  479. * 'name' => '?',
  480. * 'password' => '?'
  481. * )
  482. * );
  483. * </code>
  484. *
  485. * @param string $insert The table into which the rows should be inserted.
  486. *
  487. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  488. */
  489. public function insert($insert = null) {
  490. $this->queryBuilder->insert(
  491. $this->getTableName($insert)
  492. );
  493. $this->lastInsertedTable = $insert;
  494. return $this;
  495. }
  496. /**
  497. * Creates and adds a query root corresponding to the table identified by the
  498. * given alias, forming a cartesian product with any existing query roots.
  499. *
  500. * <code>
  501. * $qb = $conn->getQueryBuilder()
  502. * ->select('u.id')
  503. * ->from('users', 'u')
  504. * </code>
  505. *
  506. * @param string $from The table.
  507. * @param string|null $alias The alias of the table.
  508. *
  509. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  510. */
  511. public function from($from, $alias = null) {
  512. $this->queryBuilder->from(
  513. $this->getTableName($from),
  514. $this->quoteAlias($alias)
  515. );
  516. return $this;
  517. }
  518. /**
  519. * Creates and adds a join to the query.
  520. *
  521. * <code>
  522. * $qb = $conn->getQueryBuilder()
  523. * ->select('u.name')
  524. * ->from('users', 'u')
  525. * ->join('u', 'phonenumbers', 'p', 'p.is_primary = 1');
  526. * </code>
  527. *
  528. * @param string $fromAlias The alias that points to a from clause.
  529. * @param string $join The table name to join.
  530. * @param string $alias The alias of the join table.
  531. * @param string $condition The condition for the join.
  532. *
  533. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  534. */
  535. public function join($fromAlias, $join, $alias, $condition = null) {
  536. $this->queryBuilder->join(
  537. $this->quoteAlias($fromAlias),
  538. $this->getTableName($join),
  539. $this->quoteAlias($alias),
  540. $condition
  541. );
  542. return $this;
  543. }
  544. /**
  545. * Creates and adds a join to the query.
  546. *
  547. * <code>
  548. * $qb = $conn->getQueryBuilder()
  549. * ->select('u.name')
  550. * ->from('users', 'u')
  551. * ->innerJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1');
  552. * </code>
  553. *
  554. * @param string $fromAlias The alias that points to a from clause.
  555. * @param string $join The table name to join.
  556. * @param string $alias The alias of the join table.
  557. * @param string $condition The condition for the join.
  558. *
  559. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  560. */
  561. public function innerJoin($fromAlias, $join, $alias, $condition = null) {
  562. $this->queryBuilder->innerJoin(
  563. $this->quoteAlias($fromAlias),
  564. $this->getTableName($join),
  565. $this->quoteAlias($alias),
  566. $condition
  567. );
  568. return $this;
  569. }
  570. /**
  571. * Creates and adds a left join to the query.
  572. *
  573. * <code>
  574. * $qb = $conn->getQueryBuilder()
  575. * ->select('u.name')
  576. * ->from('users', 'u')
  577. * ->leftJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1');
  578. * </code>
  579. *
  580. * @param string $fromAlias The alias that points to a from clause.
  581. * @param string $join The table name to join.
  582. * @param string $alias The alias of the join table.
  583. * @param string $condition The condition for the join.
  584. *
  585. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  586. */
  587. public function leftJoin($fromAlias, $join, $alias, $condition = null) {
  588. $this->queryBuilder->leftJoin(
  589. $this->quoteAlias($fromAlias),
  590. $this->getTableName($join),
  591. $this->quoteAlias($alias),
  592. $condition
  593. );
  594. return $this;
  595. }
  596. /**
  597. * Creates and adds a right join to the query.
  598. *
  599. * <code>
  600. * $qb = $conn->getQueryBuilder()
  601. * ->select('u.name')
  602. * ->from('users', 'u')
  603. * ->rightJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1');
  604. * </code>
  605. *
  606. * @param string $fromAlias The alias that points to a from clause.
  607. * @param string $join The table name to join.
  608. * @param string $alias The alias of the join table.
  609. * @param string $condition The condition for the join.
  610. *
  611. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  612. */
  613. public function rightJoin($fromAlias, $join, $alias, $condition = null) {
  614. $this->queryBuilder->rightJoin(
  615. $this->quoteAlias($fromAlias),
  616. $this->getTableName($join),
  617. $this->quoteAlias($alias),
  618. $condition
  619. );
  620. return $this;
  621. }
  622. /**
  623. * Sets a new value for a column in a bulk update query.
  624. *
  625. * <code>
  626. * $qb = $conn->getQueryBuilder()
  627. * ->update('users', 'u')
  628. * ->set('u.password', md5('password'))
  629. * ->where('u.id = ?');
  630. * </code>
  631. *
  632. * @param string $key The column to set.
  633. * @param string $value The value, expression, placeholder, etc.
  634. *
  635. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  636. */
  637. public function set($key, $value) {
  638. $this->queryBuilder->set(
  639. $this->helper->quoteColumnName($key),
  640. $this->helper->quoteColumnName($value)
  641. );
  642. return $this;
  643. }
  644. /**
  645. * Specifies one or more restrictions to the query result.
  646. * Replaces any previously specified restrictions, if any.
  647. *
  648. * <code>
  649. * $qb = $conn->getQueryBuilder()
  650. * ->select('u.name')
  651. * ->from('users', 'u')
  652. * ->where('u.id = ?');
  653. *
  654. * // You can optionally programatically build and/or expressions
  655. * $qb = $conn->getQueryBuilder();
  656. *
  657. * $or = $qb->expr()->orx();
  658. * $or->add($qb->expr()->eq('u.id', 1));
  659. * $or->add($qb->expr()->eq('u.id', 2));
  660. *
  661. * $qb->update('users', 'u')
  662. * ->set('u.password', md5('password'))
  663. * ->where($or);
  664. * </code>
  665. *
  666. * @param mixed ...$predicates The restriction predicates.
  667. *
  668. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  669. */
  670. public function where(...$predicates) {
  671. call_user_func_array(
  672. [$this->queryBuilder, 'where'],
  673. $predicates
  674. );
  675. return $this;
  676. }
  677. /**
  678. * Adds one or more restrictions to the query results, forming a logical
  679. * conjunction with any previously specified restrictions.
  680. *
  681. * <code>
  682. * $qb = $conn->getQueryBuilder()
  683. * ->select('u')
  684. * ->from('users', 'u')
  685. * ->where('u.username LIKE ?')
  686. * ->andWhere('u.is_active = 1');
  687. * </code>
  688. *
  689. * @param mixed ...$where The query restrictions.
  690. *
  691. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  692. *
  693. * @see where()
  694. */
  695. public function andWhere(...$where) {
  696. call_user_func_array(
  697. [$this->queryBuilder, 'andWhere'],
  698. $where
  699. );
  700. return $this;
  701. }
  702. /**
  703. * Adds one or more restrictions to the query results, forming a logical
  704. * disjunction with any previously specified restrictions.
  705. *
  706. * <code>
  707. * $qb = $conn->getQueryBuilder()
  708. * ->select('u.name')
  709. * ->from('users', 'u')
  710. * ->where('u.id = 1')
  711. * ->orWhere('u.id = 2');
  712. * </code>
  713. *
  714. * @param mixed ...$where The WHERE statement.
  715. *
  716. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  717. *
  718. * @see where()
  719. */
  720. public function orWhere(...$where) {
  721. call_user_func_array(
  722. [$this->queryBuilder, 'orWhere'],
  723. $where
  724. );
  725. return $this;
  726. }
  727. /**
  728. * Specifies a grouping over the results of the query.
  729. * Replaces any previously specified groupings, if any.
  730. *
  731. * <code>
  732. * $qb = $conn->getQueryBuilder()
  733. * ->select('u.name')
  734. * ->from('users', 'u')
  735. * ->groupBy('u.id');
  736. * </code>
  737. *
  738. * @param mixed ...$groupBys The grouping expression.
  739. *
  740. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  741. */
  742. public function groupBy(...$groupBys) {
  743. if (count($groupBys) === 1 && is_array($groupBys[0])) {
  744. $groupBys = $groupBys[0];
  745. }
  746. call_user_func_array(
  747. [$this->queryBuilder, 'groupBy'],
  748. $this->helper->quoteColumnNames($groupBys)
  749. );
  750. return $this;
  751. }
  752. /**
  753. * Adds a grouping expression to the query.
  754. *
  755. * <code>
  756. * $qb = $conn->getQueryBuilder()
  757. * ->select('u.name')
  758. * ->from('users', 'u')
  759. * ->groupBy('u.lastLogin');
  760. * ->addGroupBy('u.createdAt')
  761. * </code>
  762. *
  763. * @param mixed ...$groupBy The grouping expression.
  764. *
  765. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  766. */
  767. public function addGroupBy(...$groupBys) {
  768. if (count($groupBys) === 1 && is_array($groupBys[0])) {
  769. $$groupBys = $groupBys[0];
  770. }
  771. call_user_func_array(
  772. [$this->queryBuilder, 'addGroupBy'],
  773. $this->helper->quoteColumnNames($groupBys)
  774. );
  775. return $this;
  776. }
  777. /**
  778. * Sets a value for a column in an insert query.
  779. *
  780. * <code>
  781. * $qb = $conn->getQueryBuilder()
  782. * ->insert('users')
  783. * ->values(
  784. * array(
  785. * 'name' => '?'
  786. * )
  787. * )
  788. * ->setValue('password', '?');
  789. * </code>
  790. *
  791. * @param string $column The column into which the value should be inserted.
  792. * @param string $value The value that should be inserted into the column.
  793. *
  794. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  795. */
  796. public function setValue($column, $value) {
  797. $this->queryBuilder->setValue(
  798. $this->helper->quoteColumnName($column),
  799. $value
  800. );
  801. return $this;
  802. }
  803. /**
  804. * Specifies values for an insert query indexed by column names.
  805. * Replaces any previous values, if any.
  806. *
  807. * <code>
  808. * $qb = $conn->getQueryBuilder()
  809. * ->insert('users')
  810. * ->values(
  811. * array(
  812. * 'name' => '?',
  813. * 'password' => '?'
  814. * )
  815. * );
  816. * </code>
  817. *
  818. * @param array $values The values to specify for the insert query indexed by column names.
  819. *
  820. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  821. */
  822. public function values(array $values) {
  823. $quotedValues = [];
  824. foreach ($values as $key => $value) {
  825. $quotedValues[$this->helper->quoteColumnName($key)] = $value;
  826. }
  827. $this->queryBuilder->values($quotedValues);
  828. return $this;
  829. }
  830. /**
  831. * Specifies a restriction over the groups of the query.
  832. * Replaces any previous having restrictions, if any.
  833. *
  834. * @param mixed ...$having The restriction over the groups.
  835. *
  836. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  837. */
  838. public function having(...$having) {
  839. call_user_func_array(
  840. [$this->queryBuilder, 'having'],
  841. $having
  842. );
  843. return $this;
  844. }
  845. /**
  846. * Adds a restriction over the groups of the query, forming a logical
  847. * conjunction with any existing having restrictions.
  848. *
  849. * @param mixed ...$having The restriction to append.
  850. *
  851. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  852. */
  853. public function andHaving(...$having) {
  854. call_user_func_array(
  855. [$this->queryBuilder, 'andHaving'],
  856. $having
  857. );
  858. return $this;
  859. }
  860. /**
  861. * Adds a restriction over the groups of the query, forming a logical
  862. * disjunction with any existing having restrictions.
  863. *
  864. * @param mixed ...$having The restriction to add.
  865. *
  866. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  867. */
  868. public function orHaving(...$having) {
  869. call_user_func_array(
  870. [$this->queryBuilder, 'orHaving'],
  871. $having
  872. );
  873. return $this;
  874. }
  875. /**
  876. * Specifies an ordering for the query results.
  877. * Replaces any previously specified orderings, if any.
  878. *
  879. * @param string $sort The ordering expression.
  880. * @param string $order The ordering direction.
  881. *
  882. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  883. */
  884. public function orderBy($sort, $order = null) {
  885. $this->queryBuilder->orderBy(
  886. $this->helper->quoteColumnName($sort),
  887. $order
  888. );
  889. return $this;
  890. }
  891. /**
  892. * Adds an ordering to the query results.
  893. *
  894. * @param string $sort The ordering expression.
  895. * @param string $order The ordering direction.
  896. *
  897. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  898. */
  899. public function addOrderBy($sort, $order = null) {
  900. $this->queryBuilder->addOrderBy(
  901. $this->helper->quoteColumnName($sort),
  902. $order
  903. );
  904. return $this;
  905. }
  906. /**
  907. * Gets a query part by its name.
  908. *
  909. * @param string $queryPartName
  910. *
  911. * @return mixed
  912. */
  913. public function getQueryPart($queryPartName) {
  914. return $this->queryBuilder->getQueryPart($queryPartName);
  915. }
  916. /**
  917. * Gets all query parts.
  918. *
  919. * @return array
  920. */
  921. public function getQueryParts() {
  922. return $this->queryBuilder->getQueryParts();
  923. }
  924. /**
  925. * Resets SQL parts.
  926. *
  927. * @param array|null $queryPartNames
  928. *
  929. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  930. */
  931. public function resetQueryParts($queryPartNames = null) {
  932. $this->queryBuilder->resetQueryParts($queryPartNames);
  933. return $this;
  934. }
  935. /**
  936. * Resets a single SQL part.
  937. *
  938. * @param string $queryPartName
  939. *
  940. * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
  941. */
  942. public function resetQueryPart($queryPartName) {
  943. $this->queryBuilder->resetQueryPart($queryPartName);
  944. return $this;
  945. }
  946. /**
  947. * Creates a new named parameter and bind the value $value to it.
  948. *
  949. * This method provides a shortcut for PDOStatement::bindValue
  950. * when using prepared statements.
  951. *
  952. * The parameter $value specifies the value that you want to bind. If
  953. * $placeholder is not provided bindValue() will automatically create a
  954. * placeholder for you. An automatic placeholder will be of the name
  955. * ':dcValue1', ':dcValue2' etc.
  956. *
  957. * For more information see {@link http://php.net/pdostatement-bindparam}
  958. *
  959. * Example:
  960. * <code>
  961. * $value = 2;
  962. * $q->eq( 'id', $q->bindValue( $value ) );
  963. * $stmt = $q->executeQuery(); // executed with 'id = 2'
  964. * </code>
  965. *
  966. * @license New BSD License
  967. * @link http://www.zetacomponents.org
  968. *
  969. * @param mixed $value
  970. * @param mixed $type
  971. * @param string $placeHolder The name to bind with. The string must start with a colon ':'.
  972. *
  973. * @return IParameter the placeholder name used.
  974. */
  975. public function createNamedParameter($value, $type = IQueryBuilder::PARAM_STR, $placeHolder = null) {
  976. return new Parameter($this->queryBuilder->createNamedParameter($value, $type, $placeHolder));
  977. }
  978. /**
  979. * Creates a new positional parameter and bind the given value to it.
  980. *
  981. * Attention: If you are using positional parameters with the query builder you have
  982. * to be very careful to bind all parameters in the order they appear in the SQL
  983. * statement , otherwise they get bound in the wrong order which can lead to serious
  984. * bugs in your code.
  985. *
  986. * Example:
  987. * <code>
  988. * $qb = $conn->getQueryBuilder();
  989. * $qb->select('u.*')
  990. * ->from('users', 'u')
  991. * ->where('u.username = ' . $qb->createPositionalParameter('Foo', IQueryBuilder::PARAM_STR))
  992. * ->orWhere('u.username = ' . $qb->createPositionalParameter('Bar', IQueryBuilder::PARAM_STR))
  993. * </code>
  994. *
  995. * @param mixed $value
  996. * @param integer $type
  997. *
  998. * @return IParameter
  999. */
  1000. public function createPositionalParameter($value, $type = IQueryBuilder::PARAM_STR) {
  1001. return new Parameter($this->queryBuilder->createPositionalParameter($value, $type));
  1002. }
  1003. /**
  1004. * Creates a new parameter
  1005. *
  1006. * Example:
  1007. * <code>
  1008. * $qb = $conn->getQueryBuilder();
  1009. * $qb->select('u.*')
  1010. * ->from('users', 'u')
  1011. * ->where('u.username = ' . $qb->createParameter('name'))
  1012. * ->setParameter('name', 'Bar', IQueryBuilder::PARAM_STR))
  1013. * </code>
  1014. *
  1015. * @param string $name
  1016. *
  1017. * @return IParameter
  1018. */
  1019. public function createParameter($name) {
  1020. return new Parameter(':' . $name);
  1021. }
  1022. /**
  1023. * Creates a new function
  1024. *
  1025. * Attention: Column names inside the call have to be quoted before hand
  1026. *
  1027. * Example:
  1028. * <code>
  1029. * $qb = $conn->getQueryBuilder();
  1030. * $qb->select($qb->createFunction('COUNT(*)'))
  1031. * ->from('users', 'u')
  1032. * echo $qb->getSQL(); // SELECT COUNT(*) FROM `users` u
  1033. * </code>
  1034. * <code>
  1035. * $qb = $conn->getQueryBuilder();
  1036. * $qb->select($qb->createFunction('COUNT(`column`)'))
  1037. * ->from('users', 'u')
  1038. * echo $qb->getSQL(); // SELECT COUNT(`column`) FROM `users` u
  1039. * </code>
  1040. *
  1041. * @param string $call
  1042. *
  1043. * @return IQueryFunction
  1044. */
  1045. public function createFunction($call) {
  1046. return new QueryFunction($call);
  1047. }
  1048. /**
  1049. * Used to get the id of the last inserted element
  1050. * @return int
  1051. * @throws \BadMethodCallException When being called before an insert query has been run.
  1052. */
  1053. public function getLastInsertId() {
  1054. if ($this->getType() === \Doctrine\DBAL\Query\QueryBuilder::INSERT && $this->lastInsertedTable) {
  1055. // lastInsertId() needs the prefix but no quotes
  1056. $table = $this->prefixTableName($this->lastInsertedTable);
  1057. return (int) $this->connection->lastInsertId($table);
  1058. }
  1059. throw new \BadMethodCallException('Invalid call to getLastInsertId without using insert() before.');
  1060. }
  1061. /**
  1062. * Returns the table name quoted and with database prefix as needed by the implementation
  1063. *
  1064. * @param string $table
  1065. * @return string
  1066. */
  1067. public function getTableName($table) {
  1068. $table = $this->prefixTableName($table);
  1069. return $this->helper->quoteColumnName($table);
  1070. }
  1071. /**
  1072. * Returns the table name with database prefix as needed by the implementation
  1073. *
  1074. * @param string $table
  1075. * @return string
  1076. */
  1077. protected function prefixTableName($table) {
  1078. if ($this->automaticTablePrefix === false || strpos($table, '*PREFIX*') === 0) {
  1079. return $table;
  1080. }
  1081. return '*PREFIX*' . $table;
  1082. }
  1083. /**
  1084. * Returns the column name quoted and with table alias prefix as needed by the implementation
  1085. *
  1086. * @param string $column
  1087. * @param string $tableAlias
  1088. * @return string
  1089. */
  1090. public function getColumnName($column, $tableAlias = '') {
  1091. if ($tableAlias !== '') {
  1092. $tableAlias .= '.';
  1093. }
  1094. return $this->helper->quoteColumnName($tableAlias . $column);
  1095. }
  1096. /**
  1097. * Returns the column name quoted and with table alias prefix as needed by the implementation
  1098. *
  1099. * @param string $alias
  1100. * @return string
  1101. */
  1102. public function quoteAlias($alias) {
  1103. if ($alias === '' || $alias === null) {
  1104. return $alias;
  1105. }
  1106. return $this->helper->quoteColumnName($alias);
  1107. }
  1108. }