<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Database\Query;
use Closure;
use DateTimeInterface;
use Hyperf\Contract\LengthAwarePaginatorInterface;
use Hyperf\Contract\PaginatorInterface;
use Hyperf\Database\Concerns\BuildsQueries;
use Hyperf\Database\ConnectionInterface;
use Hyperf\Database\Exception\InvalidBindingException;
use Hyperf\Database\Model\Builder as ModelBuilder;
use Hyperf\Database\Query\Grammars\Grammar;
use Hyperf\Database\Query\Processors\Processor;
use Hyperf\Paginator\Paginator;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Utils\Arr;
use Hyperf\Utils\Collection;
use Hyperf\Utils\Contracts\Arrayable;
use Hyperf\Utils\Str;
use Hyperf\Utils\Traits\ForwardsCalls;
use Hyperf\Utils\Traits\Macroable;
use InvalidArgumentException;
use RuntimeException;
class Builder
{
use BuildsQueries, ForwardsCalls, Macroable {
__call as macroCall;
}
/**
* The database connection instance.
*
* @var ConnectionInterface
*/
public $connection;
/**
* The database query grammar instance.
*
* @var \Hyperf\Database\Query\Grammars\Grammar
*/
public $grammar;
/**
* The database query post processor instance.
*
* @var \Hyperf\Database\Query\Processors\Processor
*/
public $processor;
/**
* The current query value bindings.
*
* @var array
*/
public $bindings
= [
'select' => [],
'from' => [],
'join' => [],
'where' => [],
'having' => [],
'order' => [],
'union' => [],
];
/**
* An aggregate function and column to be run.
*
* @var array
*/
public $aggregate;
/**
* The columns that should be returned.
*
* @var array
*/
public $columns;
/**
* Indicates if the query returns distinct results.
*
* @var bool
*/
public $distinct = false;
/**
* The table which the query is targeting.
*
* @var string
*/
public $from;
/**
* The table joins for the query.
*
* @var array
*/
public $joins;
/**
* The where constraints for the query.
*
* @var array
*/
public $wheres = [];
/**
* The groupings for the query.
*
* @var array
*/
public $groups;
/**
* The having constraints for the query.
*
* @var array
*/
public $havings;
/**
* The orderings for the query.
*
* @var array
*/
public $orders;
/**
* The maximum number of records to return.
*
* @var int
*/
public $limit;
/**
* The number of records to skip.
*
* @var int
*/
public $offset;
/**
* The query union statements.
*
* @var array
*/
public $unions;
/**
* The maximum number of union records to return.
*
* @var int
*/
public $unionLimit;
/**
* The number of union records to skip.
*
* @var int
*/
public $unionOffset;
/**
* The orderings for the union query.
*
* @var array
*/
public $unionOrders;
/**
* Indicates whether row locking is being used.
*
* @var bool|string
*/
public $lock;
/**
* All of the available clause operators.
*
* @var array
*/
public $operators
= [
'=',
'<',
'>',
'<=',
'>=',
'<>',
'!=',
'<=>',
'like',
'like binary',
'not like',
'ilike',
'&',
'|',
'^',
'<<',
'>>',
'rlike',
'regexp',
'not regexp',
'~',
'~*',
'!~',
'!~*',
'similar to',
'not similar to',
'not ilike',
'~~*',
'!~~*',
];
/**
* Whether use write pdo for select.
*
* @var bool
*/
public $useWritePdo = false;
/**
* Create a new query builder instance.
*
* @param \Hyperf\Database\Query\Grammars\Grammar $grammar
* @param \Hyperf\Database\Query\Processors\Processor $processor
*/
public function __construct(
ConnectionInterface $connection,
Grammar $grammar = null,
Processor $processor = null
) {
$this->connection = $connection;
$this->grammar = $grammar ?: $connection->getQueryGrammar();
$this->processor = $processor ?: $connection->getPostProcessor();
}
/**
* Handle dynamic method calls into the method.
*
* @param string $method
* @param array $parameters
* @throws \BadMethodCallException
*/
public function __call($method, $parameters)
{
if (static::hasMacro($method)) {
return $this->macroCall($method, $parameters);
}
if (Str::startsWith($method, 'where')) {
return $this->dynamicWhere($method, $parameters);
}
static::throwBadMethodCallException($method);
}
/**
* Set the columns to be selected.
*
* @param array|mixed $columns
* @return $this
*/
public function select($columns = ['*'])
{
$this->columns = is_array($columns) ? $columns : func_get_args();
return $this;
}
/**
* Add a subselect expression to the query.
*
* @param \Closure|\Hyperf\Database\Query\Builder|string $query
* @param string $as
* @throws \InvalidArgumentException
* @return \Hyperf\Database\Query\Builder|static
*/
public function selectSub($query, $as)
{
[$query, $bindings] = $this->createSub($query);
return $this->selectRaw('(' . $query . ') as ' . $this->grammar->wrap($as), $bindings);
}
/**
* Add a new "raw" select expression to the query.
*
* @param string $expression
* @return \Hyperf\Database\Query\Builder|static
*/
public function selectRaw($expression, array $bindings = [])
{
$this->addSelect(new Expression($expression));
if ($bindings) {
$this->addBinding($bindings, 'select');
}
return $this;
}
/**
* Makes "from" fetch from a subquery.
*
* @param \Closure|\Hyperf\Database\Query\Builder|string $query
* @param string $as
* @throws \InvalidArgumentException
* @return \Hyperf\Database\Query\Builder|static
*/
public function fromSub($query, $as)
{
[$query, $bindings] = $this->createSub($query);
return $this->fromRaw('(' . $query . ') as ' . $this->grammar->wrapTable($as), $bindings);
}
/**
* Add a raw from clause to the query.
*
* @param string $expression
* @param mixed $bindings
* @return \Hyperf\Database\Query\Builder|static
*/
public function fromRaw($expression, $bindings = [])
{
$this->from = new Expression($expression);
$this->addBinding($bindings, 'from');
return $this;
}
/**
* Add a new select column to the query.
*
* @param array|mixed $column
* @return $this
*/
public function addSelect($column)
{
$column = is_array($column) ? $column : func_get_args();
$this->columns = array_merge((array) $this->columns, $column);
return $this;
}
/**
* Force the query to only return distinct results.
*
* @return $this
*/
public function distinct()
{
$this->distinct = true;
return $this;
}
/**
* Set the table which the