コード例 #1
0
    def test_batches_strip_comments(self):
        """Test that we do not attempt to execute a batch consisting only of comments"""
        full_query = '''select * from t1;
-- test
-- test
;select * from t1;
-- test
-- test;'''

        # If I build a query that contains a batch consisting of only comments, in addition to other valid batches
        query = Query('test_uri', full_query,
                      QueryExecutionSettings(ExecutionPlanOptions(), None),
                      QueryEvents())

        # Then there is only a batch for each non-comment statement
        self.assertEqual(len(query.batches), 2)

        # And each batch should have the correct location information
        expected_selections = [
            SelectionData(start_line=0,
                          start_column=0,
                          end_line=0,
                          end_column=17),
            SelectionData(start_line=3,
                          start_column=1,
                          end_line=3,
                          end_column=18)
        ]

        for index, batch in enumerate(query.batches):
            self.assertEqual(
                _tuple_from_selection_data(batch.selection),
                _tuple_from_selection_data(expected_selections[index]))
コード例 #2
0
    def setUp(self):
        """Set up the test by creating a query with multiple batches"""
        self.statement_list = statement_list = [
            'select version;', 'select * from t1;'
        ]
        self.statement_str = ''.join(statement_list)
        self.query_uri = 'test_uri'
        self.query = Query(
            self.query_uri, self.statement_str,
            QueryExecutionSettings(ExecutionPlanOptions(),
                                   ResultSetStorageType.FILE_STORAGE),
            QueryEvents())

        self.mock_query_results = [('Id1', 'Value1'), ('Id2', 'Value2')]
        self.cursor = MockCursor(self.mock_query_results)
        self.connection = MockPGServerConnection(cur=self.cursor)

        self.columns_info = []
        db_column_id = DbColumn()
        db_column_id.data_type = 'text'
        db_column_id.column_name = 'Id'
        db_column_id.provider = PG_PROVIDER_NAME
        db_column_value = DbColumn()
        db_column_value.data_type = 'text'
        db_column_value.column_name = 'Value'
        db_column_value.provider = PG_PROVIDER_NAME
        self.columns_info = [db_column_id, db_column_value]
        self.get_columns_info_mock = mock.Mock(return_value=self.columns_info)
コード例 #3
0
    def test_batch_selections_do_block(self):
        """Test that the query sets up batch objects with correct selection information for blocks containing statements"""
        full_query = '''DO $$
BEGIN
RAISE NOTICE 'Hello world 1';
RAISE NOTICE 'Hello world 2';
END $$;
select * from t1;'''

        # If I build a query that contains a block that contains several statements
        query = Query('test_uri', full_query,
                      QueryExecutionSettings(ExecutionPlanOptions(), None),
                      QueryEvents())

        # Then there is a batch for each top-level statement
        self.assertEqual(len(query.batches), 2)

        # And each batch should have the correct location information
        expected_selections = [
            SelectionData(start_line=0,
                          start_column=0,
                          end_line=4,
                          end_column=7),
            SelectionData(start_line=5,
                          start_column=0,
                          end_line=5,
                          end_column=17)
        ]
        for index, batch in enumerate(query.batches):
            self.assertEqual(
                _tuple_from_selection_data(batch.selection),
                _tuple_from_selection_data(expected_selections[index]))
コード例 #4
0
    def test_hash_character_processed_correctly(self):
        """Test that xor operator is not taken for an inline comment delimiter"""
        full_query = "select 42 # 24;"
        query = Query('test_uri', full_query,
                      QueryExecutionSettings(ExecutionPlanOptions(), None),
                      QueryEvents())

        self.assertEqual(len(query.batches), 1)
        self.assertEqual(full_query, query.batches[0].batch_text)
コード例 #5
0
    def execute_get_subset_raises_error_when_index_not_in_range(
            self, batch_index: int):
        full_query = 'Select * from t1;'
        query = Query('test_uri', full_query,
                      QueryExecutionSettings(ExecutionPlanOptions(), None),
                      QueryEvents())

        with self.assertRaises(IndexError) as context_manager:
            query.get_subset(batch_index, 0, 10)
            self.assertEquals(
                'Batch index cannot be less than 0 or greater than the number of batches',
                context_manager.exception.args[0])
コード例 #6
0
    def test_get_subset(self):
        full_query = 'Select * from t1;'
        query = Query('test_uri', full_query,
                      QueryExecutionSettings(ExecutionPlanOptions(), None),
                      QueryEvents())
        expected_subset = []

        mock_batch = mock.MagicMock()
        mock_batch.get_subset = mock.Mock(return_value=expected_subset)

        query._batches = [mock_batch]

        subset = query.get_subset(0, 0, 10)

        self.assertEqual(expected_subset, subset)
        mock_batch.get_subset.assert_called_once_with(0, 10)
コード例 #7
0
    def test_batch_selections(self):
        """Test that the query sets up batch objects with correct selection information"""
        full_query = '''select * from
t1;
select * from t2;;;
;  ;
select version(); select * from
t3 ;
select * from t2
'''

        # If I build a query that contains several statements
        query = Query('test_uri', full_query,
                      QueryExecutionSettings(ExecutionPlanOptions(), None),
                      QueryEvents())

        # Then there is a batch for each non-empty statement
        self.assertEqual(len(query.batches), 5)

        # And each batch should have the correct location information
        expected_selections = [
            SelectionData(start_line=0,
                          start_column=0,
                          end_line=1,
                          end_column=3),
            SelectionData(start_line=2,
                          start_column=0,
                          end_line=2,
                          end_column=17),
            SelectionData(start_line=4,
                          start_column=0,
                          end_line=4,
                          end_column=17),
            SelectionData(start_line=4,
                          start_column=18,
                          end_line=5,
                          end_column=4),
            SelectionData(start_line=6,
                          start_column=0,
                          end_line=6,
                          end_column=16)
        ]
        for index, batch in enumerate(query.batches):
            self.assertEqual(
                _tuple_from_selection_data(batch.selection),
                _tuple_from_selection_data(expected_selections[index]))
コード例 #8
0
    def _resolve_query_exception(self, e: Exception, query: Query, worker_args: ExecuteRequestWorkerArgs, is_rollback_error=False):
        utils.log.log_debug(self._service_provider.logger, f'Query execution failed for following query: {query.query_text}\n {e}')

        # If the error relates to the database, display the appropriate error message based on the provider
        if isinstance(e, worker_args.connection.database_error) or isinstance(e, worker_args.connection.query_canceled_error):
            # get_error_message may return None so ensure error_message is str type
            error_message = str(worker_args.connection.get_error_message(e))

        elif isinstance(e, RuntimeError):
            error_message = str(e)

        else:
            error_message = 'Unhandled exception while executing query: {}'.format(str(e))  # TODO: Localize
            if self._service_provider.logger is not None:
                self._service_provider.logger.exception('Unhandled exception while executing query')

        # If the error occured during rollback, add a note about it
        if is_rollback_error:
            error_message = 'Error while rolling back open transaction due to previous failure: ' + error_message  # TODO: Localize

        # Send a message with the error to the client
        result_message_params = self.build_message_params(query.owner_uri, query.batches[query.current_batch_index].id, error_message, True)
        _check_and_fire(worker_args.on_message_notification, result_message_params)

        # If there was a failure in the middle of a transaction, roll it back.
        # Note that conn.rollback() won't work since the connection is in autocommit mode
        if not is_rollback_error and worker_args.connection.transaction_in_error:
            rollback_query = Query(query.owner_uri, 'ROLLBACK', QueryExecutionSettings(ExecutionPlanOptions(), None), QueryEvents())
            try:
                rollback_query.execute(worker_args.connection)
            except Exception as rollback_exception:
                # If the rollback failed, handle the error as usual but don't try to roll back again
                self._resolve_query_exception(rollback_exception, rollback_query, worker_args, True)