def test_order_by(self): """ Order by in Snuba are represented as -COL_NAME when ordering DESC. since the column is provided with the `-` character in front when reaching the column_expr call, this can introduce a ton of corner cases depending whether the column is aliased, whether it gets processed into something else or whether it is escaped. This test is supposed to cover those cases. """ source = self.dataset.get_dataset_schemas().get_read_schema().get_data_source() query = Query({}, source) # Columns that start with a negative sign (used in orderby to signify # sort order) retain the '-' sign outside the escaping backticks (if any) assert ( column_expr(self.dataset, "-timestamp", deepcopy(query), ParsingContext()) == "-timestamp" ) assert ( column_expr( self.dataset, "-sentry:release", deepcopy(query), ParsingContext() ) == "-`sentry:release`" ) context = ParsingContext() context.add_alias("al1") assert ( column_expr(self.dataset, "-timestamp", deepcopy(query), context, "al1") == "-al1" ) assert ( column_expr( self.dataset, "-timestamp", deepcopy(query), ParsingContext(), "al1" ) == "-(timestamp AS al1)" ) assert ( column_expr( self.dataset, "-exception_stacks.type", deepcopy(query), ParsingContext(), ) == "-(exception_stacks.type AS `exception_stacks.type`)" ) context = ParsingContext() context.add_alias("`exception_stacks.type`") assert ( column_expr( self.dataset, "-exception_stacks.type", deepcopy(query), context, ) == "-`exception_stacks.type`" )
def test_order_by(): dataset = get_dataset("groups") source = dataset.get_dataset_schemas().get_read_schema().get_data_source() body = {} query = Query(body, source) assert ( column_expr(dataset, "-events.event_id", deepcopy(query), ParsingContext()) == "-(events.event_id AS `events.event_id`)" ) context = ParsingContext() context.add_alias("`events.event_id`") assert ( column_expr(dataset, "-events.event_id", deepcopy(query), context,) == "-`events.event_id`" )
def alias_expr(expr: str, alias: str, parsing_context: ParsingContext) -> str: """ Return the correct expression to use in the final SQL. Keeps a cache of the previously created expressions and aliases, so it knows when it can subsequently replace a redundant expression with an alias. 1. If the expression and alias are equal, just return that. 2. Otherwise, if the expression is new, add it to the cache and its alias so it can be reused later and return `expr AS alias` 3. If the expression has been aliased before, return the alias """ if expr == alias: return expr elif parsing_context.is_alias_present(alias): return alias else: parsing_context.add_alias(alias) return "({} AS {})".format(expr, alias)