def set_match(self, match: Union[Entity, Join, Query]) -> Query: if not isinstance(match, (Entity, Join, Query)): raise InvalidQueryError(f"{match} must be a valid Entity, Join or Query") elif isinstance(match, Query): try: match.validate() except Exception as e: raise InvalidQueryError(f"inner query is invalid: {e}") from e return self._replace("match", match)
def __post_init__(self) -> None: """ This has a different validation flow from normal expressions, since a query is not necessarily always correct. For example, you can create a Query with no select columns, which will fail in the validate. However it shouldn't fail right away since the select columns can be added later. """ # TODO: Whitelist of Datasets and possible entities if not isinstance(self.dataset, str) or self.dataset == "": raise InvalidQueryError("queries must have a valid dataset") if not isinstance(self.match, (Query, Join, Entity)): raise InvalidQueryError("queries must have a valid Entity, Join or Query") if isinstance(self.match, Query): try: self.match.validate() except Exception as e: raise InvalidQueryError(f"inner query is invalid: {e}") from e
query.validate() invalid_tests = [ pytest.param( Query( dataset="discover", match=Entity("events"), select=None, groupby=None, where=[Condition(Column("timestamp"), Op.GT, NOW)], limit=Limit(10), offset=Offset(1), granularity=Granularity(3600), ), InvalidQueryError("query must have at least one expression in select"), id="missing select", ), pytest.param( Query( dataset="discover", match=Entity("events"), select=[Column("title")], where=[Condition(Column("timestamp"), Op.GT, NOW)], limit=Limit(10), offset=Offset(1), granularity=Granularity(3600), ).set_totals(True), InvalidQueryError("totals is only valid with a groupby"), id="Totals must have a groupby", ),
def set_limitby(self, limitby: LimitBy) -> Query: if not isinstance(limitby, LimitBy): raise InvalidQueryError("limitby clause must be a LimitBy") return self._replace("limitby", limitby)
def set_orderby(self, orderby: Sequence[OrderBy]) -> Query: if not list_type(orderby, (OrderBy,)): raise InvalidQueryError("orderby clause must be a list of OrderBy") return self._replace("orderby", orderby)
def set_having(self, conditions: ConditionGroup) -> Query: if not list_type(conditions, (BooleanCondition, Condition)): raise InvalidQueryError("having clause must be a list of conditions") return self._replace("having", conditions)
def set_array_join(self, array_join: Sequence[Column]) -> Query: if not list_type(array_join, [Column]) or len(array_join) < 1: raise InvalidQueryError("array join must be a non-empty list of Column") return self._replace("array_join", array_join)
def set_groupby(self, groupby: Sequence[SelectableExpression]) -> Query: if not list_type(groupby, SelectableExpressionType): raise InvalidQueryError( "groupby clause must be a list of SelectableExpression" ) return self._replace("groupby", groupby)
def set_select(self, select: Sequence[SelectableExpression]) -> Query: if not list_type(select, SelectableExpressionType) or not select: raise InvalidQueryError( "select clause must be a non-empty list of SelectableExpression" ) return self._replace("select", select)