| 560 | |
| 561 | |
| 562 | class FrontendExceptionSearcher(object): |
| 563 | |
| 564 | def __init__(self, query_profile, ref_conn, test_conn): |
| 565 | '''query_profile should be an instance of one of the profiles in query_profile.py''' |
| 566 | self.query_profile = query_profile |
| 567 | self.ref_conn = ref_conn |
| 568 | self.test_conn = test_conn |
| 569 | self.ref_sql_writer = SqlWriter.create(dialect=ref_conn.db_type) |
| 570 | self.test_sql_writer = SqlWriter.create(dialect=test_conn.db_type) |
| 571 | with ref_conn.cursor() as ref_cursor: |
| 572 | with test_conn.cursor() as test_cursor: |
| 573 | self.common_tables = DbCursor.describe_common_tables([ref_cursor, test_cursor]) |
| 574 | if not self.common_tables: |
| 575 | raise Exception("Unable to find a common set of tables in both databases") |
| 576 | |
| 577 | def search(self, number_of_test_queries): |
| 578 | |
| 579 | def on_ref_db_error(e, sql): |
| 580 | LOG.warn("Error generating explain plan for reference db:\n%s\n%s" % (e, sql)) |
| 581 | |
| 582 | def on_test_db_error(e, sql): |
| 583 | LOG.error("Error generating explain plan for test db:\n%s" % sql) |
| 584 | raise e |
| 585 | |
| 586 | for idx in range(number_of_test_queries): |
| 587 | LOG.info("Explaining query #%s" % (idx + 1)) |
| 588 | statement_type = self.query_profile.choose_statement() |
| 589 | statement_generator = get_generator(statement_type)(self.query_profile) |
| 590 | if issubclass(statement_type, (InsertStatement,)): |
| 591 | dml_table = self.query_profile.choose_table(self.common_tables) |
| 592 | else: |
| 593 | dml_table = None |
| 594 | query = statement_generator.generate_statement( |
| 595 | self.common_tables, dml_table=dml_table) |
| 596 | if not self._explain_query(self.ref_conn, self.ref_sql_writer, query, |
| 597 | on_ref_db_error): |
| 598 | continue |
| 599 | self._explain_query(self.test_conn, self.test_sql_writer, query, |
| 600 | on_test_db_error) |
| 601 | |
| 602 | def _explain_query(self, conn, writer, query, exception_handler): |
| 603 | sql = writer.write_query(query) |
| 604 | try: |
| 605 | with conn.cursor() as cursor: |
| 606 | cursor.execute("EXPLAIN %s" % sql) |
| 607 | return True |
| 608 | except Exception as e: |
| 609 | exception_handler(e, sql) |
| 610 | return False |
| 611 | |
| 612 | |
| 613 | class QueryResultDiffSearcher(object): |
no outgoing calls
no test coverage detected