def _build_criterion_expression(
         self, operator_: str, left: Term,
         right: Term) -> Union[BasicCriterion, Not, NullCriterion]:
     if operator_ == "equals":
         return left.eq(right)
     elif operator_ == "not-equals":
         return left.ne(right)
     elif operator_ == 'empty':
         return left.isnull()
     elif operator_ == 'not-empty':
         return left.notnull()
     elif operator_ == "more":
         return left.gt(right)
     elif operator_ == "more-equals":
         return left.gte(right)
     elif operator_ == "less":
         return left.lt(right)
     elif operator_ == "less-equals":
         return left.lte(right)
     elif operator_ == 'in':
         return left.isin(right)
     elif operator_ == 'not-in':
         return left.notin(right)
     else:
         # TODO more operator support
         raise NotImplementedError("filter operator is not supported")
 def constant_handler(self) -> Tuple[CustomFunction, ParameterValueType]:
     param = self.param
     if param.value.strip().startswith("{&"):
         result, value_type = self.match_function()
         return result, value_type
     else:
         return Term.wrap_constant(param.value), ParameterValueType.TEXT
コード例 #3
0
 def _validate_returning_term(self, term: Term) -> None:
     for field in term.fields_():
         if not any(
             [self._insert_table, self._update_table, self._delete_from]):
             raise QueryException("Returning can't be used in this query")
         if (field.table not in {self._insert_table, self._update_table}
                 and term not in self._from):
             raise QueryException("You can't return from other tables")
コード例 #4
0
    def _validate_returning_term(self, term: Term) -> None:
        for field in term.fields_():
            if not any([self._insert_table, self._update_table, self._delete_from]):
                raise QueryException("Returning can't be used in this query")

            table_is_insert_or_update_table = field.table in {self._insert_table, self._update_table}
            join_tables = set(itertools.chain.from_iterable([j.criterion.tables_ for j in self._joins]))
            join_and_base_tables = set(self._from) | join_tables
            table_not_base_or_join = bool(term.tables_ - join_and_base_tables)
            if not table_is_insert_or_update_table and table_not_base_or_join:
                raise QueryException("You can't return from other tables")
コード例 #5
0
ファイル: expressions.py プロジェクト: tortoise/tortoise-orm
    def resolver_arithmetic_expression(
        cls,
        model: "Type[Model]",
        arithmetic_expression_or_field: Term,
    ) -> Tuple[Term, Optional[PypikaField]]:
        field_object = None

        if isinstance(arithmetic_expression_or_field, PypikaField):
            name = arithmetic_expression_or_field.name
            try:
                arithmetic_expression_or_field.name = model._meta.fields_db_projection[
                    name]

                field_object = model._meta.fields_map.get(name, None)
                if field_object:
                    func = field_object.get_for_dialect(
                        model._meta.db.capabilities.dialect, "function_cast")
                    if func:
                        arithmetic_expression_or_field = func(
                            field_object, arithmetic_expression_or_field)
            except KeyError:
                raise FieldError(
                    f"There is no non-virtual field {name} on Model {model.__name__}"
                )
        elif isinstance(arithmetic_expression_or_field, ArithmeticExpression):
            left = arithmetic_expression_or_field.left
            right = arithmetic_expression_or_field.right
            (
                arithmetic_expression_or_field.left,
                left_field_object,
            ) = cls.resolver_arithmetic_expression(model, left)
            if left_field_object:
                if field_object and type(field_object) != type(
                        left_field_object):
                    raise FieldError(
                        "Cannot use arithmetic expression between different field type"
                    )
                field_object = left_field_object

            (
                arithmetic_expression_or_field.right,
                right_field_object,
            ) = cls.resolver_arithmetic_expression(model, right)
            if right_field_object:
                if field_object and type(field_object) != type(
                        right_field_object):
                    raise FieldError(
                        "Cannot use arithmetic expression between different field type"
                    )
                field_object = right_field_object

        return arithmetic_expression_or_field, field_object
コード例 #6
0
ファイル: expressions.py プロジェクト: tortoise/tortoise-orm
    def resolve(self, model: "Type[Model]", table: Table) -> tuple:
        q_objects = self._resolve_q_objects()

        modifier = QueryModifier()
        for node in q_objects:
            modifier &= node.resolve(model, model._meta.basetable)

        if isinstance(self.then, Function):
            then = self.then.resolve(model, table)["field"]
        elif isinstance(self.then, Term):
            then = F.resolver_arithmetic_expression(model, self.then)[0]
        else:
            then = Term.wrap_constant(self.then)

        return modifier.where_criterion, then
コード例 #7
0
ファイル: queryset.py プロジェクト: wankata/tortoise-orm
 def _resolve_group_bys(self, *field_names: str):
     group_bys = []
     for field_name in field_names:
         if field_name in self._annotations:
             group_bys.append(Term(field_name))
             continue
         field_split = field_name.split("__")
         related_table, related_db_field = self._join_table_with_forwarded_fields(
             model=self.model,
             table=self.model._meta.basetable,
             field=field_split[0],
             forwarded_fields="__".join(field_split[1:])
             if len(field_split) > 1 else "",
         )
         field = related_table[related_db_field].as_(field_name)
         group_bys.append(field)
     return group_bys
コード例 #8
0
def not_in(field: Term, value: Any) -> Criterion:
    if value:
        return field.notin(value) | field.isnull()
    return BasicCriterion(Equality.eq, ValueWrapper(1), ValueWrapper(1))
コード例 #9
0
def is_in(field: Term, value: Any) -> Criterion:
    if value:
        return field.isin(value)
    return BasicCriterion(Equality.eq, ValueWrapper(1), ValueWrapper(0))
コード例 #10
0
ファイル: filters.py プロジェクト: sm0k/tortoise-orm
def not_in(field: Term, value: Any) -> Criterion:
    return field.notin(value) | field.isnull()
コード例 #11
0
def not_null(field: Term, value: Any) -> Criterion:
    if value:
        return field.notnull()
    return field.isnull()
コード例 #12
0
def is_in(field: Term, value: Any) -> Criterion:
    if value:
        return field.isin(value)
    # SQL has no False, so we return 1=0
    return BasicCriterion(Equality.eq, ValueWrapper(1), ValueWrapper(0))
コード例 #13
0
	UNION ALL
		SELECT
			0 AS permissions,
			allow,
			deny
		FROM page_permissions
		WHERE entity = ANY ($2) OR page_id = $1)
SELECT bit_or(permissions) | bit_or(allow) | (coalesce((SELECT * FROM everyone_perms), $3)) & ~bit_or(deny)
FROM all_permissions
"""
"""pypika attempt:"""
q = (Query.with_(
    Query.select(rp.permissions).from_(rp).where(rp.entity == entity_id),
    'everyone_perms').with_(
        Query.select(rp.permissions,
                     Term(0).as_('allow'),
                     Term(0).as_('deny')).from_(rp).where(
                         rp.entity.isin(role_ids)).union_all(
                             Query.select(
                                 Term(0).as_('permissions'), pp.allow,
                                 pp.deny).from_(pp).where(
                                     pp.entity.isin(role_ids)
                                     | pp.page_id == entity_id)),
        'all_permissions').select(
            bit_or('permissions') | bit_or('allow') | bit_or('deny')
            | Coalesce(
                Query.select(pypika.Table('everyone_perms').star).from_(
                    pypika.Table('everyone_perms')), default_permissions)
            & ~bit_or('deny')).from_('all_permissions'))

print(q)
コード例 #14
0
ファイル: expressions.py プロジェクト: tortoise/tortoise-orm
    Case expression.

    :param args: When objects
    :param default: value for 'CASE WHEN ... THEN ... ELSE <default> END'
    """
    def __init__(
            self,
            *args: When,
            default: Union[str, F, ArithmeticExpression,
                           Function] = None) -> None:
        self.args = args
        self.default = default

    def resolve(self, model: "Type[Model]", table: Table) -> dict:
        case = PypikaCase()
        for arg in self.args:
            if not isinstance(arg, When):
                raise TypeError("expected When objects as args")
            criterion, term = arg.resolve(model, table)
            case = case.when(criterion, term)

        if isinstance(self.default, Function):
            case = case.else_(self.default.resolve(model, table)["field"])
        elif isinstance(self.default, Term):
            case = case.else_(
                F.resolver_arithmetic_expression(model, self.default)[0])
        else:
            case = case.else_(Term.wrap_constant(self.default))

        return {"joins": [], "field": case}
コード例 #15
0
def between_and(field: Term, value: Tuple[Any, Any]) -> Criterion:
    return field.between(value[0], value[1])
コード例 #16
0
def ends_with(field: Term, value: str) -> Criterion:
    return Like(Cast(field, SqlTypes.VARCHAR),
                field.wrap_constant(f"%{escape_like(value)}"))
コード例 #17
0
def not_equal(field: Term, value: Any) -> Criterion:
    return field.ne(value) | field.isnull()
コード例 #18
0
def insensitive_ends_with(field: Term, value: str) -> Criterion:
    return Like(Upper(Cast(field, SqlTypes.VARCHAR)),
                field.wrap_constant(Upper(f"%{escape_like(value)}")))
コード例 #19
0
def _definition_field_for_data_blending(
    target_dataset_definition: Union[Field, terms.Term],
    target_dataset_leaf_definition: terms.Field,
    definition: terms.Term,
) -> terms.Term:
    """
    When using data blending, the dataset table of the set filter needs to be re-mapped to the table in the
    target dataset (i.e. primary or secondary). The easiest way to do that is to select the field in the
    target dataset directly. Otherwise table not found issues would pop up when resolving the joins.

    :param target_dataset_definition: The definition for a field in the target dataset.
    :param target_dataset_leaf_definition: The leaf definition for a field in the target dataset.
                                           Given sometimes a fireant's Field might have nested fireant's
                                           Fields.
    :param definition: A definition that might have its sub-parts (e.g. term, left, right) replaced.
                       That's likely the case for Criterion sub-classes and so on.
    :return: A term sub-class to be used in place of the provided definition argument, when applicable.
    """
    if isinstance(definition, (terms.ValueWrapper, )):
        # Constant values can be returned as is.
        return definition

    if isinstance(
            definition,
        (terms.Field, )) and definition == target_dataset_leaf_definition:
        target_dataset_leaf_definition.replace_table(
            target_dataset_leaf_definition.table, definition.table)
        return target_dataset_definition

    # Function, ...
    if hasattr(definition, 'args'):
        definition.args = [
            _definition_field_for_data_blending(
                target_dataset_definition, target_dataset_leaf_definition, arg)
            for arg in definition.args
        ]

    # CustomFunction, ...
    if hasattr(definition, 'params'):
        definition.params = [
            _definition_field_for_data_blending(
                target_dataset_definition, target_dataset_leaf_definition,
                param) for param in definition.params
        ]

    # RangeCriterion, ContainsCriterion, Not, All,
    if hasattr(definition, 'term'):
        definition.term = _definition_field_for_data_blending(
            target_dataset_definition, target_dataset_leaf_definition,
            definition.term)

    # BasicCriterion, ComplexCriterion, ...
    if hasattr(definition, 'left'):
        definition.left = _definition_field_for_data_blending(
            target_dataset_definition, target_dataset_leaf_definition,
            definition.left)

    if hasattr(definition, 'right'):
        definition.right = _definition_field_for_data_blending(
            target_dataset_definition, target_dataset_leaf_definition,
            definition.right)

    # Case
    if hasattr(definition, '_cases'):
        definition._cases = [
            _definition_field_for_data_blending(
                target_dataset_definition, target_dataset_leaf_definition,
                case) for case in definition._cases
        ]

    if hasattr(definition, '_else'):
        definition._else = _definition_field_for_data_blending(
            target_dataset_definition, target_dataset_leaf_definition,
            definition._else)

    return definition
コード例 #20
0
ファイル: filters.py プロジェクト: sm0k/tortoise-orm
def is_in(field: Term, value: Any) -> Criterion:
    return field.isin(value)