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(SelectingQuery $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([$expr1, $expr2, ...])` * * `select([[$expr1, $alias1], [$expr2, $alias2], ...])` * * `select(string|Expression $expression)` * * `select(string|Expression $expression, string $alias)` * * @param array|string|Expression $select An array of attributes or one attribute. * @param string|null $alias An alias. Actual if the first parameter is a string. */ public function select($select, ?string $alias = null): self { if (is_array($select)) { $this->params['select'] = $this->normilizeExpressionItemArray($select); return $this; } if ($select instanceof Expression) { $select = $select->getValue(); } if (is_string($select)) { $this->params['select'] = $this->params['select'] ?? []; $this->params['select'][] = $alias ? [$select, $alias] : $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([$expr1, $expr2, ...])` * * `groupBy(string|Expression $expression)` * * @param string|Expression|array $groupBy */ public function groupBy($groupBy): self { if (is_array($groupBy)) { $this->params['groupBy'] = $this->normilizeExpressionItemArray($groupBy); return $this; } if ($groupBy instanceof Expression) { $groupBy = $groupBy->getValue(); } 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. * * Usage options: * * `having(WhereItem $clause)` * * `having(array $clause)` * * `having(string $key, string $value)` * * @param WhereItem|array|string $clause A key or where clause. * @param array|string|null $value A value. Omitted if the first argument is not string. */ public function having($clause, $value = null): self { $this->applyWhereClause('havingClause', $clause, $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 together."); } $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 together."); } $this->params['forUpdate'] = true; return $this; } /** * @todo Remove? */ public function withDeleted(): self { $this->params['withDeleted'] = true; return $this; } }