From e45a03408d86a0711edd7f8b5744bc218eb959cb Mon Sep 17 00:00:00 2001 From: Yurun Date: Thu, 31 Aug 2023 10:09:29 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=BC=BA=20whereBrackets=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=9F=A5=E8=AF=A2=E6=9D=A1=E4=BB=B6=E6=94=B6?= =?UTF-8?q?=E9=9B=86=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/components/db/index.md | 19 +- .../Query/Interfaces/IBaseWhereCollector.php | 190 ++++++++++++++++ src/Db/Query/Interfaces/IQuery.php | 184 +--------------- src/Db/Query/Interfaces/IWhereCollector.php | 13 ++ src/Db/Query/Query.php | 197 +---------------- src/Db/Query/Traits/TWhereCollector.php | 207 ++++++++++++++++++ src/Db/Query/Where/WhereBrackets.php | 22 +- src/Db/Query/WhereCollector.php | 98 +++++++++ .../Component/Tests/Db/QueryCurdBaseTest.php | 63 ++++++ 9 files changed, 611 insertions(+), 382 deletions(-) create mode 100644 src/Db/Query/Interfaces/IBaseWhereCollector.php create mode 100644 src/Db/Query/Interfaces/IWhereCollector.php create mode 100644 src/Db/Query/Traits/TWhereCollector.php create mode 100644 src/Db/Query/WhereCollector.php diff --git a/doc/components/db/index.md b/doc/components/db/index.md index 4720ed91ef..a55d8e9b88 100644 --- a/doc/components/db/index.md +++ b/doc/components/db/index.md @@ -453,26 +453,37 @@ Db::query()->orWhereRaw('id >= :value', [':value' => 1]); #### whereBrackets ```php +// 查询条件收集器:where (age < 14 or age > 60) +Db::query()->where('id', '=', 1)->whereBrackets(function(\Imi\Db\Query\Interfaces\IQuery $query, \Imi\Db\Query\Interfaces\IWhereCollector $where) { + // 注意:使用第 2 个参数 $where,而不是 $query + $where->where('age', '<', 14)->orWhere('age', '>', 60); + // 不要有返回值 +}, 'or'); + // where id = 1 or (age < 14) Db::query()->where('id', '=', 1)->whereBrackets(function(\Imi\Db\Query\Interfaces\IQuery $query) { - // 直接返回字符串 + // 返回条件字符串 return 'age < 14'; }, 'or'); + // 支持使用 sql 语句: where id = 1 or (age > 10 and age < 14) Db::query()->where('id', '=', 1)->whereBrackets(function(\Imi\Db\Query\Interfaces\IQuery $query) { - // 直接返回字符串 + // 返回 Where 系列数组 return [ \Imi\Db\Query\Where\Where::raw('age > 10'), new \Imi\Db\Query\Where\Where('age', '<', 14), ]; }, 'or'); + // where id = 1 or (age < 14) Db::query()->where('id', '=', 1)->whereBrackets(function(\Imi\Db\Query\Interfaces\IQuery $query) { - // 直接返回字符串 + // 返回 Where 系列对象 return new \Imi\Db\Query\Where\Where('age', '<', 14); }, 'or'); + +// OR 条件 Db::query()->where('id', '=', 1)->orWhereBrackets(function(\Imi\Db\Query\Interfaces\IQuery $query) { - // 直接返回字符串 + // 返回 Where 系列对象 return new \Imi\Db\Query\Where\Where('age', '<', 14); }); ``` diff --git a/src/Db/Query/Interfaces/IBaseWhereCollector.php b/src/Db/Query/Interfaces/IBaseWhereCollector.php new file mode 100644 index 0000000000..c601e2888d --- /dev/null +++ b/src/Db/Query/Interfaces/IBaseWhereCollector.php @@ -0,0 +1,190 @@ +、<、like等. + * + * @param mixed $value + * + * @return static + */ + public function where(string $fieldName, string $operation, $value, string $logicalOperator = 'and'): self; + + /** + * 设置 where 条件,用原生语句. + * + * @return static + */ + public function whereRaw(string $raw, string $logicalOperator = 'and', array $binds = []): self; + + /** + * 设置 where 条件,传入回调,回调中的条件加括号. + * + * @return static + */ + public function whereBrackets(callable $callback, string $logicalOperator = 'and'): self; + + /** + * 设置 where 条件,使用 IBaseWhere 结构. + * + * @return static + */ + public function whereStruct(IBaseWhere $where, string $logicalOperator = 'and'): self; + + /** + * 设置 where 条件,支持语法如下:. + * + * [ + * 'id' => 1, + * 'or' => [ + * 'id' => 2, + * ], + * 'title' => ['like', '%test%'], + * 'age' => ['>', 18], + * 'age' => ['between', 19, 29] + * ] + * + * SQL: id = 1 or (id = 2) and title like '%test%' and age > 18 and age between 19 and 29 + * + * @return static + */ + public function whereEx(array $condition, string $logicalOperator = 'and'): self; + + /** + * where between $begin end $end. + * + * @param mixed $begin + * @param mixed $end + * + * @return static + */ + public function whereBetween(string $fieldName, $begin, $end, string $logicalOperator = 'and'): self; + + /** + * or where between $begin end $end. + * + * @param mixed $begin + * @param mixed $end + * + * @return static + */ + public function orWhereBetween(string $fieldName, $begin, $end): self; + + /** + * where not between $begin end $end. + * + * @param mixed $begin + * @param mixed $end + * + * @return static + */ + public function whereNotBetween(string $fieldName, $begin, $end, string $logicalOperator = 'and'): self; + + /** + * or where not between $begin end $end. + * + * @param mixed $begin + * @param mixed $end + * + * @return static + */ + public function orWhereNotBetween(string $fieldName, $begin, $end): self; + + /** + * 设置 where or 条件. + * + * @param mixed $value + * + * @return static + */ + public function orWhere(string $fieldName, string $operation, $value): self; + + /** + * 设置 where or 条件,用原生语句. + * + * @return static + */ + public function orWhereRaw(string $where, array $binds = []): self; + + /** + * 设置 where or 条件,传入回调,回调中的条件加括号. + * + * @return static + */ + public function orWhereBrackets(callable $callback): self; + + /** + * 设置 where or 条件,使用 IBaseWhere 结构. + * + * @return static + */ + public function orWhereStruct(IBaseWhere $where): self; + + /** + * 设置 where or 条件,支持语法参考 whereEx 方法. + * + * @return static + */ + public function orWhereEx(array $condition): self; + + /** + * where field in (list). + * + * @return static + */ + public function whereIn(string $fieldName, array $list, string $logicalOperator = 'and'): self; + + /** + * or where field in (list). + * + * @return static + */ + public function orWhereIn(string $fieldName, array $list): self; + + /** + * where field not in (list). + * + * @return static + */ + public function whereNotIn(string $fieldName, array $list, string $logicalOperator = 'and'): self; + + /** + * or where field not in (list). + * + * @return static + */ + public function orWhereNotIn(string $fieldName, array $list): self; + + /** + * where field is null. + * + * @return static + */ + public function whereIsNull(string $fieldName, string $logicalOperator = 'and'): self; + + /** + * or where field is null. + * + * @return static + */ + public function orWhereIsNull(string $fieldName): self; + + /** + * where field is not null. + * + * @return static + */ + public function whereIsNotNull(string $fieldName, string $logicalOperator = 'and'): self; + + /** + * or where field is not null. + * + * @return static + */ + public function orWhereIsNotNull(string $fieldName): self; +} diff --git a/src/Db/Query/Interfaces/IQuery.php b/src/Db/Query/Interfaces/IQuery.php index 0ca2a6108d..f00441b205 100644 --- a/src/Db/Query/Interfaces/IQuery.php +++ b/src/Db/Query/Interfaces/IQuery.php @@ -13,7 +13,7 @@ /** * 查询器接口. */ -interface IQuery +interface IQuery extends IBaseWhereCollector { /** * 获取所有操作的记录. @@ -112,188 +112,6 @@ public function field(string ...$fields): self; */ public function fieldRaw(string $raw, ?string $alias = null, array $binds = []): self; - /** - * 设置 where 条件,一般用于 =、>、<、like等. - * - * @param mixed $value - * - * @return static - */ - public function where(string $fieldName, string $operation, $value, string $logicalOperator = 'and'): self; - - /** - * 设置 where 条件,用原生语句. - * - * @return static - */ - public function whereRaw(string $raw, string $logicalOperator = 'and', array $binds = []): self; - - /** - * 设置 where 条件,传入回调,回调中的条件加括号. - * - * @return static - */ - public function whereBrackets(callable $callback, string $logicalOperator = 'and'): self; - - /** - * 设置 where 条件,使用 IBaseWhere 结构. - * - * @return static - */ - public function whereStruct(IBaseWhere $where, string $logicalOperator = 'and'): self; - - /** - * 设置 where 条件,支持语法如下:. - * - * [ - * 'id' => 1, - * 'or' => [ - * 'id' => 2, - * ], - * 'title' => ['like', '%test%'], - * 'age' => ['>', 18], - * 'age' => ['between', 19, 29] - * ] - * - * SQL: id = 1 or (id = 2) and title like '%test%' and age > 18 and age between 19 and 29 - * - * @return static - */ - public function whereEx(array $condition, string $logicalOperator = 'and'): self; - - /** - * where between $begin end $end. - * - * @param mixed $begin - * @param mixed $end - * - * @return static - */ - public function whereBetween(string $fieldName, $begin, $end, string $logicalOperator = 'and'): self; - - /** - * or where between $begin end $end. - * - * @param mixed $begin - * @param mixed $end - * - * @return static - */ - public function orWhereBetween(string $fieldName, $begin, $end): self; - - /** - * where not between $begin end $end. - * - * @param mixed $begin - * @param mixed $end - * - * @return static - */ - public function whereNotBetween(string $fieldName, $begin, $end, string $logicalOperator = 'and'): self; - - /** - * or where not between $begin end $end. - * - * @param mixed $begin - * @param mixed $end - * - * @return static - */ - public function orWhereNotBetween(string $fieldName, $begin, $end): self; - - /** - * 设置 where or 条件. - * - * @param mixed $value - * - * @return static - */ - public function orWhere(string $fieldName, string $operation, $value): self; - - /** - * 设置 where or 条件,用原生语句. - * - * @return static - */ - public function orWhereRaw(string $where, array $binds = []): self; - - /** - * 设置 where or 条件,传入回调,回调中的条件加括号. - * - * @return static - */ - public function orWhereBrackets(callable $callback): self; - - /** - * 设置 where or 条件,使用 IBaseWhere 结构. - * - * @return static - */ - public function orWhereStruct(IBaseWhere $where): self; - - /** - * 设置 where or 条件,支持语法参考 whereEx 方法. - * - * @return static - */ - public function orWhereEx(array $condition): self; - - /** - * where field in (list). - * - * @return static - */ - public function whereIn(string $fieldName, array $list, string $logicalOperator = 'and'): self; - - /** - * or where field in (list). - * - * @return static - */ - public function orWhereIn(string $fieldName, array $list): self; - - /** - * where field not in (list). - * - * @return static - */ - public function whereNotIn(string $fieldName, array $list, string $logicalOperator = 'and'): self; - - /** - * or where field not in (list). - * - * @return static - */ - public function orWhereNotIn(string $fieldName, array $list): self; - - /** - * where field is null. - * - * @return static - */ - public function whereIsNull(string $fieldName, string $logicalOperator = 'and'): self; - - /** - * or where field is null. - * - * @return static - */ - public function orWhereIsNull(string $fieldName): self; - - /** - * where field is not null. - * - * @return static - */ - public function whereIsNotNull(string $fieldName, string $logicalOperator = 'and'): self; - - /** - * or where field is not null. - * - * @return static - */ - public function orWhereIsNotNull(string $fieldName): self; - /** * join. * diff --git a/src/Db/Query/Interfaces/IWhereCollector.php b/src/Db/Query/Interfaces/IWhereCollector.php new file mode 100644 index 0000000000..452efc7ef6 --- /dev/null +++ b/src/Db/Query/Interfaces/IWhereCollector.php @@ -0,0 +1,13 @@ +whereBrackets(fn () => $this->parseWhereEx($condition), $logicalOperator); - } - - protected function parseWhereEx(array $condition): array - { - $result = []; - foreach ($condition as $key => $value) - { - if (null === LogicalOperator::getText(strtolower($key))) - { - // 条件 k => v - if (\is_array($value)) - { - $operator = strtolower($value[0] ?? ''); - switch ($operator) - { - case 'between': - if (!isset($value[2])) - { - throw new \RuntimeException('Between must have 3 params'); - } - $result[] = new Where($key, 'between', [$value[1], $value[2]]); - break; - case 'not between': - if (!isset($value[2])) - { - throw new \RuntimeException('Not between must have 3 params'); - } - $result[] = new Where($key, 'not between', [$value[1], $value[2]]); - break; - case 'in': - if (!isset($value[1])) - { - throw new \RuntimeException('In must have 3 params'); - } - $result[] = new Where($key, 'in', $value[1]); - break; - case 'not in': - if (!isset($value[1])) - { - throw new \RuntimeException('Not in must have 3 params'); - } - $result[] = new Where($key, 'not in', $value[1]); - break; - default: - $result[] = new Where($key, $operator, $value[1]); - break; - } - } - else - { - $result[] = new Where($key, '=', $value); - } - } - else - { - // 逻辑运算符 - $result[] = new WhereBrackets(fn () => $this->parseWhereEx($value), $key); - } - } - - return $result; - } - - /** - * {@inheritDoc} - */ - public function whereBetween(string $fieldName, $begin, $end, string $logicalOperator = LogicalOperator::AND): self - { - return $this->where($fieldName, 'between', [$begin, $end], $logicalOperator); - } - - /** - * {@inheritDoc} - */ - public function orWhereBetween(string $fieldName, $begin, $end): self - { - return $this->where($fieldName, 'between', [$begin, $end], LogicalOperator::OR); - } - - /** - * {@inheritDoc} - */ - public function whereNotBetween(string $fieldName, $begin, $end, string $logicalOperator = LogicalOperator::AND): self - { - return $this->where($fieldName, 'not between', [$begin, $end], $logicalOperator); - } - - /** - * {@inheritDoc} - */ - public function orWhereNotBetween(string $fieldName, $begin, $end): self - { - return $this->where($fieldName, 'not between', [$begin, $end], LogicalOperator::OR); - } - - /** - * {@inheritDoc} - */ - public function orWhere(string $fieldName, string $operation, $value): self - { - return $this->where($fieldName, $operation, $value, LogicalOperator::OR); - } - - /** - * {@inheritDoc} - */ - public function orWhereRaw(string $where, array $binds = []): self - { - return $this->whereRaw($where, LogicalOperator::OR, $binds); - } - - /** - * {@inheritDoc} - */ - public function orWhereBrackets(callable $callback): self - { - return $this->whereBrackets($callback, LogicalOperator::OR); - } - - /** - * {@inheritDoc} - */ - public function orWhereStruct(IBaseWhere $where): self - { - return $this->whereStruct($where, LogicalOperator::OR); - } - - /** - * {@inheritDoc} - */ - public function orWhereEx(array $condition): self - { - return $this->whereEx($condition, LogicalOperator::OR); - } - - /** - * {@inheritDoc} - */ - public function whereIn(string $fieldName, array $list, string $logicalOperator = LogicalOperator::AND): self - { - return $this->where($fieldName, 'in', $list, $logicalOperator); - } - - /** - * {@inheritDoc} - */ - public function orWhereIn(string $fieldName, array $list): self - { - return $this->where($fieldName, 'in', $list, LogicalOperator::OR); - } - - /** - * {@inheritDoc} - */ - public function whereNotIn(string $fieldName, array $list, string $logicalOperator = LogicalOperator::AND): self - { - return $this->where($fieldName, 'not in', $list, $logicalOperator); - } - - /** - * {@inheritDoc} - */ - public function orWhereNotIn(string $fieldName, array $list): self - { - return $this->where($fieldName, 'not in', $list, LogicalOperator::OR); - } - /** * {@inheritDoc} */ @@ -555,14 +380,6 @@ public function whereIsNull(string $fieldName, string $logicalOperator = Logical return $this->whereRaw($this->fieldQuote($fieldName) . ' is null', $logicalOperator); } - /** - * {@inheritDoc} - */ - public function orWhereIsNull(string $fieldName): self - { - return $this->whereIsNull($fieldName, LogicalOperator::OR); - } - /** * {@inheritDoc} */ @@ -571,14 +388,6 @@ public function whereIsNotNull(string $fieldName, string $logicalOperator = Logi return $this->whereRaw($this->fieldQuote($fieldName) . ' is not null', $logicalOperator); } - /** - * {@inheritDoc} - */ - public function orWhereIsNotNull(string $fieldName): self - { - return $this->whereIsNotNull($fieldName, LogicalOperator::OR); - } - /** * {@inheritDoc} */ diff --git a/src/Db/Query/Traits/TWhereCollector.php b/src/Db/Query/Traits/TWhereCollector.php new file mode 100644 index 0000000000..ef58622a1b --- /dev/null +++ b/src/Db/Query/Traits/TWhereCollector.php @@ -0,0 +1,207 @@ +whereBrackets(fn () => $this->parseWhereEx($condition), $logicalOperator); + } + + /** + * {@inheritDoc} + */ + public function whereBetween(string $fieldName, $begin, $end, string $logicalOperator = LogicalOperator::AND): self + { + return $this->where($fieldName, 'between', [$begin, $end], $logicalOperator); + } + + /** + * {@inheritDoc} + */ + public function orWhereBetween(string $fieldName, $begin, $end): self + { + return $this->where($fieldName, 'between', [$begin, $end], LogicalOperator::OR); + } + + /** + * {@inheritDoc} + */ + public function whereNotBetween(string $fieldName, $begin, $end, string $logicalOperator = LogicalOperator::AND): self + { + return $this->where($fieldName, 'not between', [$begin, $end], $logicalOperator); + } + + /** + * {@inheritDoc} + */ + public function orWhereNotBetween(string $fieldName, $begin, $end): self + { + return $this->where($fieldName, 'not between', [$begin, $end], LogicalOperator::OR); + } + + /** + * {@inheritDoc} + */ + public function orWhere(string $fieldName, string $operation, $value): self + { + return $this->where($fieldName, $operation, $value, LogicalOperator::OR); + } + + /** + * {@inheritDoc} + */ + public function orWhereRaw(string $where, array $binds = []): self + { + return $this->whereRaw($where, LogicalOperator::OR, $binds); + } + + /** + * {@inheritDoc} + */ + public function orWhereBrackets(callable $callback): self + { + return $this->whereBrackets($callback, LogicalOperator::OR); + } + + /** + * {@inheritDoc} + */ + public function orWhereStruct(IBaseWhere $where): self + { + return $this->whereStruct($where, LogicalOperator::OR); + } + + /** + * {@inheritDoc} + */ + public function orWhereEx(array $condition): self + { + return $this->whereEx($condition, LogicalOperator::OR); + } + + /** + * {@inheritDoc} + */ + public function whereIn(string $fieldName, array $list, string $logicalOperator = LogicalOperator::AND): self + { + return $this->where($fieldName, 'in', $list, $logicalOperator); + } + + /** + * {@inheritDoc} + */ + public function orWhereIn(string $fieldName, array $list): self + { + return $this->where($fieldName, 'in', $list, LogicalOperator::OR); + } + + /** + * {@inheritDoc} + */ + public function whereNotIn(string $fieldName, array $list, string $logicalOperator = LogicalOperator::AND): self + { + return $this->where($fieldName, 'not in', $list, $logicalOperator); + } + + /** + * {@inheritDoc} + */ + public function orWhereNotIn(string $fieldName, array $list): self + { + return $this->where($fieldName, 'not in', $list, LogicalOperator::OR); + } + + /** + * {@inheritDoc} + */ + public function orWhereIsNull(string $fieldName): self + { + return $this->whereIsNull($fieldName, LogicalOperator::OR); + } + + /** + * {@inheritDoc} + */ + public function orWhereIsNotNull(string $fieldName): self + { + return $this->whereIsNotNull($fieldName, LogicalOperator::OR); + } + + protected function parseWhereEx(array $condition): array + { + $result = []; + foreach ($condition as $key => $value) + { + if (null === LogicalOperator::getText(strtolower($key))) + { + // 条件 k => v + if (\is_array($value)) + { + $operator = strtolower($value[0] ?? ''); + switch ($operator) + { + case 'between': + if (!isset($value[2])) + { + throw new \RuntimeException('Between must have 3 params'); + } + $result[] = new Where($key, 'between', [$value[1], $value[2]]); + break; + case 'not between': + if (!isset($value[2])) + { + throw new \RuntimeException('Not between must have 3 params'); + } + $result[] = new Where($key, 'not between', [$value[1], $value[2]]); + break; + case 'in': + if (!isset($value[1])) + { + throw new \RuntimeException('In must have 3 params'); + } + $result[] = new Where($key, 'in', $value[1]); + break; + case 'not in': + if (!isset($value[1])) + { + throw new \RuntimeException('Not in must have 3 params'); + } + $result[] = new Where($key, 'not in', $value[1]); + break; + default: + $result[] = new Where($key, $operator, $value[1]); + break; + } + } + else + { + $result[] = new Where($key, '=', $value); + } + } + else + { + // 逻辑运算符 + $result[] = new WhereBrackets(fn () => $this->parseWhereEx($value), $key); + } + } + + return $result; + } +} diff --git a/src/Db/Query/Where/WhereBrackets.php b/src/Db/Query/Where/WhereBrackets.php index 8a8392763b..b51a65479f 100644 --- a/src/Db/Query/Where/WhereBrackets.php +++ b/src/Db/Query/Where/WhereBrackets.php @@ -9,6 +9,7 @@ use Imi\Db\Query\Interfaces\IQuery; use Imi\Db\Query\Interfaces\IWhereBrackets; use Imi\Db\Query\Traits\TRaw; +use Imi\Db\Query\WhereCollector; class WhereBrackets extends BaseWhere implements IWhereBrackets { @@ -53,7 +54,8 @@ public function toStringWithoutLogic(IQuery $query): string return $this->rawSQL; } $binds = &$this->binds; - $callResult = ($this->callback)($query); + $whereCollector = new WhereCollector($query); + $callResult = ($this->callback)($query, $whereCollector); if (\is_array($callResult)) { if (empty($callResult)) @@ -91,6 +93,24 @@ public function toStringWithoutLogic(IQuery $query): string return '(' . $result . ')'; } + elseif (null === $callResult) + { + $result = '('; + foreach ($whereCollector->getWhere() as $i => $where) + { + if (0 === $i) + { + $result .= $where->toStringWithoutLogic($query); + } + else + { + $result .= ' ' . $where->getLogicalOperator() . ' ' . $where->toStringWithoutLogic($query); + } + $binds = array_merge($binds, $where->getBinds()); + } + + return $result . ')'; + } else { return '(' . $callResult . ')'; diff --git a/src/Db/Query/WhereCollector.php b/src/Db/Query/WhereCollector.php new file mode 100644 index 0000000000..8412f922cd --- /dev/null +++ b/src/Db/Query/WhereCollector.php @@ -0,0 +1,98 @@ +query = $query; + } + + /** + * @return IBaseWhere[] + */ + public function getWhere(): array + { + return $this->where; + } + + /** + * {@inheritDoc} + */ + public function where(string $fieldName, string $operation, $value, string $logicalOperator = LogicalOperator::AND): self + { + $this->where[] = new Where($fieldName, $operation, $value, $logicalOperator); + + return $this; + } + + /** + * {@inheritDoc} + */ + public function whereRaw(string $raw, string $logicalOperator = LogicalOperator::AND, array $binds = []): self + { + $where = new Where(); + $where->useRaw(); + $where->setRawSQL($raw, $binds); + $where->setLogicalOperator($logicalOperator); + $this->where[] = $where; + + return $this; + } + + /** + * {@inheritDoc} + */ + public function whereBrackets(callable $callback, string $logicalOperator = LogicalOperator::AND): self + { + $this->where[] = new WhereBrackets($callback, $logicalOperator); + + return $this; + } + + /** + * {@inheritDoc} + */ + public function whereStruct(IBaseWhere $where, string $logicalOperator = LogicalOperator::AND): self + { + $this->where[] = $where; + + return $this; + } + + /** + * {@inheritDoc} + */ + public function whereIsNull(string $fieldName, string $logicalOperator = LogicalOperator::AND): self + { + return $this->whereRaw($this->query->fieldQuote($fieldName) . ' is null', $logicalOperator); + } + + /** + * {@inheritDoc} + */ + public function whereIsNotNull(string $fieldName, string $logicalOperator = LogicalOperator::AND): self + { + return $this->whereRaw($this->query->fieldQuote($fieldName) . ' is not null', $logicalOperator); + } +} diff --git a/tests/unit/Component/Tests/Db/QueryCurdBaseTest.php b/tests/unit/Component/Tests/Db/QueryCurdBaseTest.php index 3be958e0e2..8daf910ec1 100644 --- a/tests/unit/Component/Tests/Db/QueryCurdBaseTest.php +++ b/tests/unit/Component/Tests/Db/QueryCurdBaseTest.php @@ -10,6 +10,8 @@ use Imi\Db\Mysql\Query\Lock\MysqlLock; use Imi\Db\Mysql\Query\Pagination\BigTablePagination; use Imi\Db\Query\Database; +use Imi\Db\Query\Interfaces\IQuery; +use Imi\Db\Query\Interfaces\IWhereCollector; use Imi\Db\Query\Raw; use Imi\Db\Query\Where\Where; use Imi\Test\BaseTest; @@ -459,6 +461,67 @@ public function testWhereEx(array $args): void Assert::assertEquals('select * from `' . $this->fullTableArticle . '`', Db::query($this->poolName)->from($this->tableArticle)->whereEx([])->select()->getSql()); } + /** + * @depends testInsert + */ + public function testWhereBrackets(array $args): void + { + ['ids' => $ids] = $args; + $id = $ids[1]; + + // 字符串 + $query = Db::query($this->poolName); + $result = $query->from($this->tableArticle)->whereBrackets(static fn () => 'id=' . $id)->select(); + $record = $result->get(); + Assert::assertEquals([ + 'id' => $id, + 'title' => 'title-insert', + 'content' => 'content-insert', + 'time' => '2019-06-21 00:00:00', + 'member_id' => 0, + ], $record); + + // Where 数组 + $query = Db::query($this->poolName); + $result = $query->from($this->tableArticle)->whereBrackets(static fn () => [ + new Where('id', '=', $id), + ])->select(); + $record = $result->get(); + Assert::assertEquals([ + 'id' => $id, + 'title' => 'title-insert', + 'content' => 'content-insert', + 'time' => '2019-06-21 00:00:00', + 'member_id' => 0, + ], $record); + + // Where 对象 + $query = Db::query($this->poolName); + $result = $query->from($this->tableArticle)->whereBrackets(static fn () => new Where('id', '=', $id))->select(); + $record = $result->get(); + Assert::assertEquals([ + 'id' => $id, + 'title' => 'title-insert', + 'content' => 'content-insert', + 'time' => '2019-06-21 00:00:00', + 'member_id' => 0, + ], $record); + + // Where 收集器 + $query = Db::query($this->poolName); + $result = $query->from($this->tableArticle)->whereBrackets(static function (IQuery $query, IWhereCollector $where) use ($id) { + $where->where('id', '=', $id); + })->select(); + $record = $result->get(); + Assert::assertEquals([ + 'id' => $id, + 'title' => 'title-insert', + 'content' => 'content-insert', + 'time' => '2019-06-21 00:00:00', + 'member_id' => 0, + ], $record); + } + /** * @depends testInsert */