From cf330463785b34a58cc6f9bb4b600368322151fd Mon Sep 17 00:00:00 2001 From: Aron Podrigal Date: Sun, 16 Jun 2019 18:14:27 -0700 Subject: [PATCH] Added `where_expression(query, operator, query)` --- orator/orm/builder.py | 8 ++----- orator/query/builder.py | 40 ++++++++++++++++++++++++++++++++ orator/query/grammars/grammar.py | 15 ++++++++++++ 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/orator/orm/builder.py b/orator/orm/builder.py index 72a7441e..4bbe8ce3 100644 --- a/orator/orm/builder.py +++ b/orator/orm/builder.py @@ -827,9 +827,7 @@ def _add_has_where(self, has_query, relation, operator, count, boolean): if isinstance(count, basestring) and count.isdigit(): count = QueryExpression(count) - return self.where( - QueryExpression("(%s)" % has_query.to_sql()), operator, count, boolean - ) + return self._query.where_expression(has_query._query, operator, count, boolean) def _merge_model_defined_relation_wheres_to_has_query(self, has_query, relation): """ @@ -843,9 +841,7 @@ def _merge_model_defined_relation_wheres_to_has_query(self, has_query, relation) """ relation_query = relation.get_base_query() - has_query.merge_wheres(relation_query.wheres, relation_query.get_bindings()) - - self._query.add_binding(has_query.get_query().get_bindings(), "where") + has_query.merge_wheres(relation_query.wheres) def _get_has_relation_query(self, relation): """ diff --git a/orator/query/builder.py b/orator/query/builder.py index 2b5d0f08..f0952ca4 100644 --- a/orator/query/builder.py +++ b/orator/query/builder.py @@ -506,6 +506,46 @@ def _where_sub(self, column, operator, query, boolean): return self + def where_expression( + self, left_expression, operator, right_expression, boolean="and" + ): + type = "expression" + + bindings = [] + + if isinstance(left_expression, QueryBuilder): + self.merge_bindings(left_expression) + bindings += left_expression.get_bindings() + left_expression = QueryExpression("(%s)" % left_expression.to_sql()) + elif not isinstance(left_expression, QueryExpression): + if not isinstance(left_expression, list): + bindings.append(left_expression) + else: + bindings += left_expression + + if isinstance(right_expression, QueryBuilder): + self.merge_bindings(right_expression) + bindings += right_expression.get_bindings() + right_expression = QueryExpression("(%s)" % right_expression.to_sql()) + elif not isinstance(right_expression, QueryExpression): + if not isinstance(right_expression, list): + bindings.append(right_expression) + else: + bindings += right_expression + + self.wheres.append( + { + "type": type, + "lhs": left_expression, + "operator": operator, + "rhs": right_expression, + "boolean": boolean, + "bindings": bindings, + } + ) + + return self + def where_exists(self, query, boolean="and", negate=False): """ Add an exists clause to the query. diff --git a/orator/query/grammars/grammar.py b/orator/query/grammars/grammar.py index ffd1d74d..43d4c704 100644 --- a/orator/query/grammars/grammar.py +++ b/orator/query/grammars/grammar.py @@ -157,6 +157,21 @@ def _where_sub(self, query, where): return "%s %s (%s)" % (self.wrap(where["column"]), where["operator"], select) + def _where_expression(self, query, where): + lhs = where["lhs"] + rhs = where["rhs"] + if isinstance(lhs, list): + lhs = "(%s)" % self.parameterize(lhs) + else: + lhs = self.parameter(lhs) + + if isinstance(rhs, list): + rhs = "(%s)" % self.parameterize(rhs) + else: + rhs = self.parameter(rhs) + + return "%s %s %s" % (lhs, where["operator"], rhs) + def _where_basic(self, query, where): value = self.parameter(where["value"])