def __init__(self, is_interactive, loadfun, outfile, default_format='text', do_numberify=False): super().__init__(is_interactive, query_parser.Parser(), outfile, default_format, do_numberify) self.loadfun = loadfun self.entries = None self.errors = None self.options_map = None self.env_targets = query_env.TargetsEnvironment() self.env_entries = query_env.FilterEntriesEnvironment() self.env_postings = query_env.FilterPostingsEnvironment()
def run_query(entries, options_map, query, *format_args, numberify=False): """Compile and execute a query, return the result types and rows. Args: entries: A list of entries, as produced by the loader. options_map: A dict of options, as produced by the loader. query: A string, a single BQL query, optionally containing some new-style (e.g., {}) formatting specifications. format_args: A tuple of arguments to be formatted in the query. This is just provided as a convenience. numberify: If true, numberify the results before returning them. Returns: A pair of result types and result rows. Raises: ParseError: If the statement cannot be parsed. CompilationError: If the statement cannot be compiled. """ env_targets = query_env.TargetsEnvironment() env_entries = query_env.FilterEntriesEnvironment() env_postings = query_env.FilterPostingsEnvironment() # Apply formatting to the query. formatted_query = query.format(*format_args) # Parse the statement. parser = query_parser.Parser() statement = parser.parse(formatted_query) # Compile the SELECT statement. c_query = query_compile.compile(statement, env_targets, env_postings, env_entries) # Execute it to obtain the result rows. rtypes, rrows = query_execute.execute_query(c_query, entries, options_map) # Numberify the results, if requested. if numberify: dformat = options_map['dcontext'].build() rtypes, rrows = numberify_lib.numberify_results(rtypes, rrows, dformat) return rtypes, rrows
class CompileSelectBase(unittest.TestCase): maxDiff = 8192 # Default execution contexts. xcontext_entries = qe.FilterEntriesEnvironment() xcontext_targets = qe.TargetsEnvironment() xcontext_postings = qe.FilterPostingsEnvironment() def setUp(self): self.parser = qp.Parser() def parse(self, query): return self.parser.parse(query.strip()) def compile(self, query): """Parse one query and compile it. Args: query: An SQL query to be parsed. Returns: The AST. """ statement = self.parse(query) c_query = qc.compile(statement, self.xcontext_targets, self.xcontext_postings, self.xcontext_entries) if isinstance(c_query, qp.Select): self.assertSelectInvariants(c_query) return c_query def assertSelectInvariants(self, query): """Assert the invariants on the query. Args: query: An instance of EvalQuery, a compiled query statement. Raises: AssertionError: if the check fails. """ # Check that the group references cover all the simple indexes. if query.group_indexes is not None: non_aggregate_indexes = [ index for index, c_target in enumerate(query.c_targets) if not qc.is_aggregate(c_target.c_expr) ] self.assertEqual(set(non_aggregate_indexes), set(query.group_indexes), "Invalid indexes: {}".format(query)) def assertIndexes(self, query, expected_simple_indexes, expected_aggregate_indexes, expected_group_indexes, expected_order_indexes): """Check the four lists of indexes for comparison. Args: query: An instance of EvalQuery, a compiled query statement. expected_simple_indexes: The expected visible non-aggregate indexes. expected_aggregate_indexes: The expected visible aggregate indexes. expected_group_indexes: The expected group_indexes. expected_order_indexes: The expected order_indexes. Raises: AssertionError: if the check fails. """ # Compute the list of _visible_ aggregates and non-aggregates. simple_indexes = [ index for index, c_target in enumerate(query.c_targets) if c_target.name and not qc.is_aggregate(c_target.expression) ] aggregate_indexes = [ index for index, c_target in enumerate(query.c_targets) if c_target.name and qc.is_aggregate(c_target.expression) ] self.assertEqual(set(expected_simple_indexes), set(simple_indexes)) self.assertEqual(set(expected_aggregate_indexes), set(aggregate_indexes)) self.assertEqual( set(expected_group_indexes) if expected_group_indexes is not None else None, set(query.group_indexes) if query.group_indexes is not None else None) self.assertEqual( set(expected_order_indexes) if expected_order_indexes is not None else None, set(query.order_indexes) if query.order_indexes is not None else None) def assertCompile(self, expected, query, debug=False): """Assert parsed and compiled contents from 'query' is 'expected'. Args: expected: An expected AST to compare against the parsed value. query: An SQL query to be parsed. debug: A boolean, if true, print extra debugging information on the console. Raises: AssertionError: If the actual AST does not match the expected one. """ actual = self.compile(query) if debug: print() print() print(actual) print() try: self.assertEqual(expected, actual) return actual except AssertionError: print() print("Expected: {}".format(expected)) print("Actual : {}".format(actual)) raise
class QueryBase(cmptest.TestCase): maxDiff = 8192 # Default execution contexts. xcontext_entries = qe.FilterEntriesEnvironment() xcontext_targets = qe.TargetsEnvironment() xcontext_postings = qe.FilterPostingsEnvironment() def setUp(self): super().setUp() self.parser = qp.Parser() def parse(self, bql_string): """Parse a query. Args: bql_string: An SQL query to be parsed. Returns: A parsed statement (Select() node). """ return self.parser.parse(bql_string.strip()) def compile(self, bql_string): """Parse a query and compile it. Args: bql_string: An SQL query to be parsed. Returns: A compiled EvalQuery node. """ return qc.compile_select(self.parse(bql_string), self.xcontext_targets, self.xcontext_postings, self.xcontext_entries) def check_query(self, input_string, bql_string, expected_types, expected_rows, sort_rows=False, debug=False): entries, _, options_map = loader.load_string(input_string) query = self.compile(bql_string) result_types, result_rows = qx.execute_query(query, entries, options_map) if debug: with misc_utils.box('result_types'): print(result_types) with misc_utils.box('result_rows'): print(result_rows) self.assertEqual(expected_types, result_types) if sort_rows: result_rows.sort() self.assertEqual(expected_rows, result_rows) def check_sorted_query(self, input_string, bql_string, expected_types, expected_rows): return self.check_query(input_string, bql_string, expected_types, expected_rows, True)