params); } /** * Clone an existing query for a subsequent modifying and building. */ public function clone(Select $query) : self { $this->cloneInternal($query); return $this; } /** * Set FROM. For what entity type to build a query. */ public function from(string $entityType, ?string $alias = null) : self { if (isset($this->params['from'])) { throw new RuntimeException("Method 'from' can be called only once."); } if (isset($this->params['fromQuery'])) { throw new RuntimeException("Method 'from' can't be if 'fromQuery' is set."); } $this->params['from'] = $entityType; if ($alias) { $this->params['fromAlias'] = $alias; } return $this; } /** * Set FROM sub-query. */ public function fromQuery(Selecting $query, string $alias) : self { if (isset($this->params['from'])) { throw new RuntimeException("Method 'fromQuery' can be called only once."); } if (isset($this->params['fromQuery'])) { throw new RuntimeException("Method 'fromQuery' can't be if 'from' is set."); } if ($alias === '') { throw new RuntimeException("Alias can't be empty."); } $this->params['fromQuery'] = $query; $this->params['fromAlias'] = $alias; return $this; } /** * Set DISTINCT parameter. */ public function distinct() : self { $this->params['distinct'] = true; return $this; } /** * Apply OFFSET and LIMIT. */ public function limit(?int $offset = null, ?int $limit = null) : self { $this->params['offset'] = $offset; $this->params['limit'] = $limit; return $this; } /** * Specify SELECT. Columns and expressions to be selected. If not called, then all entity attributes will be selected. * Passing an array will reset previously set items. * Passing a string will append an item. * * Usage options: * * `select([$item1, $item2, ...])` * * `select(string $expression)` * * `select(string $expression, string $alias)` * * @param array|string $select */ public function select($select, ?string $alias = null) : self { if (is_array($select)) { $this->params['select'] = $select; return $this; } if (is_string($select)) { $this->params['select'] = $this->params['select'] ?? []; if ($alias) { $this->params['select'][] = [$select, $alias]; } else { $this->params['select'][] = $select; } return $this; } throw new InvalidArgumentException(); } /** * Specify GROUP BY. * Passing an array will reset previously set items. * Passing a string will append an item. * * Usage options: * * `groupBy([$item1, $item2, ...])` * * `groupBy(string $expression)` * * @param array|string $groupBy */ public function groupBy($groupBy) : self { if (is_array($groupBy)) { $this->params['groupBy'] = $groupBy; return $this; } if (is_string($groupBy)) { $this->params['groupBy'] = $this->params['groupBy'] ?? []; $this->params['groupBy'][] = $groupBy; return $this; } throw new InvalidArgumentException(); } /** * Use index. */ public function useIndex(string $index) : self { $this->params['useIndex'] = $this->params['useIndex'] ?? []; $this->params['useIndex'][] = $index; return $this; } /** * Add a HAVING clause. * * Two usage options: * * `having(array $havingClause)` * * `having(string $key, string $value)` * * @param array|string $keyOrClause * @param ?array|string $value */ public function having($keyOrClause = [], $value = null) : self { $this->applyWhereClause('havingClause', $keyOrClause, $value); return $this; } /** * Lock selected rows in shared mode. To be used within a transaction. */ public function forShare() : self { if (isset($this->params['forUpdate'])) { throw new RuntimeException("Can't use two lock modes togather."); } $this->params['forShare'] = true; return $this; } /** * Lock selected rows. To be used within a transaction. */ public function forUpdate() : self { if (isset($this->params['forShare'])) { throw new RuntimeException("Can't use two lock modes togather."); } $this->params['forUpdate'] = true; return $this; } /** * @todo Remove? */ public function withDeleted() : self { $this->params['withDeleted'] = true; return $this; } }