Beispiel #1
0
    def test_expr_function_arity(self):
        # Compile with the correct number of arguments.
        qc.compile_expression(qp.Function('sum', [qp.Column('number')]),
                              qe.TargetsEnvironment())

        # Compile with an incorrect number of arguments.
        with self.assertRaises(qc.CompilationError):
            qc.compile_expression(
                qp.Function('sum', [qp.Column('date'),
                                    qp.Column('account')]),
                qe.TargetsEnvironment())
Beispiel #2
0
 def test_expr_binaryop(self):
     self.assertEqual(
         qc.EvalEqual(qe.DateColumn(),
                      qc.EvalConstant(datetime.date(2014, 1, 1))),
         qc.compile_expression(
             qp.Equal(qp.Column('date'),
                      qp.Constant(datetime.date(2014, 1, 1))),
             qe.TargetsEnvironment()))
Beispiel #3
0
    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()
Beispiel #4
0
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
Beispiel #5
0
 def test_expr_constant(self):
     self.assertEqual(
         qc.EvalConstant(D(17)),
         qc.compile_expression(qp.Constant(D(17)), qe.TargetsEnvironment()))
Beispiel #6
0
 def test_expr_unaryop(self):
     self.assertEqual(
         qc.EvalNot(qe.AccountColumn()),
         qc.compile_expression(qp.Not(qp.Column('account')),
                               qe.TargetsEnvironment()))
Beispiel #7
0
 def test_expr_function(self):
     self.assertEqual(
         qe.SumPosition([qe.PositionColumn()]),
         qc.compile_expression(qp.Function('sum', [qp.Column('position')]),
                               qe.TargetsEnvironment()))
Beispiel #8
0
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
Beispiel #9
0
 def test_expr_column(self):
     self.assertEqual(
         qe.FilenameColumn(),
         qc.compile_expression(qp.Column('filename'),
                               qe.TargetsEnvironment()))
Beispiel #10
0
 def test_expr_invalid(self):
     with self.assertRaises(qc.CompilationError):
         qc.compile_expression(qp.Column('invalid'),
                               qe.TargetsEnvironment())
Beispiel #11
0
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)