python-oracledb/tests/test_5200_sql_parser.py

164 lines
6.7 KiB
Python

#------------------------------------------------------------------------------
# Copyright (c) 2023, Oracle and/or its affiliates.
#
# This software is dual-licensed to you under the Universal Permissive License
# (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
# 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
# either license.
#
# If you elect to accept the software under the Apache License, Version 2.0,
# the following applies:
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#------------------------------------------------------------------------------
"""
5200 - Module for testing the SQL parser.
"""
import oracledb
import test_env
class TestCase(test_env.BaseTestCase):
def test_5200_single_line_comment(self):
"5200 - single line comment"
self.cursor.prepare("""--begin :value2 := :a + :b + :c +:a +3; end;
begin :value2 := :a + :c +3; end;""")
self.assertEqual(self.cursor.bindnames(), ["VALUE2", "A", "C"])
def test_5201_multiple_line_comment(self):
"5201 - multiple line comment"
self.cursor.prepare("""/*--select * from :a where :a = 1
select * from table_names where :a = 1*/
select :table_name, :value from dual""")
self.assertEqual(self.cursor.bindnames(), ["TABLE_NAME", "VALUE"])
def test_5202_constant_strings(self):
"5202 - constant strings"
statement = """
begin
:value := to_date('20021231 12:31:00', :format);
end;"""
self.cursor.prepare(statement)
self.assertEqual(self.cursor.bindnames(), ["VALUE", "FORMAT"])
def test_5203_multiple_division_operators(self):
"5203 - multiple division operators"
self.cursor.prepare("""
select :a / :b, :c / :d
from dual""")
self.assertEqual(self.cursor.bindnames(), ["A", "B", "C", "D"])
def test_5204_opening_parentheses(self):
"5204 - starting with parentheses"
sql = "(select :a from dual) union (select :b from dual)"
self.cursor.prepare(sql)
self.assertEqual(self.cursor.bindnames(), ["A", "B"])
def test_5205_invalid_quoted_bind(self):
"5205 - invalid quoted bind"
sql = 'select ":test", :a from dual'
self.cursor.prepare(sql)
self.assertEqual(self.cursor.bindnames(), ["A"])
def test_5206_non_ascii_bind_name(self):
"5206 - non-ascii character in the bind name"
sql = 'select :méil$ from dual'
self.cursor.prepare(sql)
self.assertEqual(self.cursor.bindnames(), ['MÉIL$'])
def test_5207_various_quoted_binds(self):
"5207 - various quoted bind names"
tests = [
('select :"percent%" from dual', ["percent%"]),
('select : "q?marks" from dual', ["q?marks"]),
('select :"percent%(ens)yah" from dual', ["percent%(ens)yah"]),
('select : "per % cent" from dual', ["per % cent"]),
('select :"per cent" from dual', ["per cent"]),
('select :"par(ens)" from dual', ["par(ens)"]),
('select :"more/slashes" from dual', ["more/slashes"]),
('select :"%percent" from dual', ["%percent"]),
('select :"/slashes/" from dual', ["/slashes/"]),
('select :"1col:on" from dual', ["1col:on"]),
('select :"col:ons" from dual', ["col:ons"]),
('select :"more :: %colons%" from dual', ["more :: %colons%"]),
('select :"more/slashes" from dual', ["more/slashes"]),
('select :"spaces % spaces" from dual', ["spaces % spaces"]),
('select "col:nns", :"col:ons", :id from dual', ["col:ons", "ID"])
]
for sql, expected in tests:
with self.subTest(sql=sql, expected=expected):
self.cursor.prepare(sql)
self.assertEqual(self.cursor.bindnames(), expected)
def test_5208_sql_with_quoted_identifiers_and_strings(self):
"5208 - sql contaiting quoted identifiers and strings"
sql = 'select "/*_value1" + : "VaLue_2" + :"*/3VALUE" from dual'
self.cursor.prepare(sql)
self.assertEqual(self.cursor.bindnames(), ["VaLue_2", "*/3VALUE"])
def test_5209_single_strings(self):
"5209 - statement containing simple strings"
sql = '''select '"string_1"', :bind_1, ':string_2' from dual'''
self.cursor.prepare(sql)
self.assertEqual(self.cursor.bindnames(), ['BIND_1'])
def test_5210_binds_between_comment_blocks(self):
"5210 - bind variables between comment blocks"
self.cursor.prepare("""
select
/* comment 1 with /* */
:a,
/* comment 2 with another /* */
:b
/* comment 3 * * * / */,
:c
from dual""")
self.assertEqual(self.cursor.bindnames(), ["A", "B", "C"])
def test_5211_binds_between_qstrings(self):
"5211 - bind variables between q-strings"
self.cursor.prepare("""
select
:a,
q'{This contains ' and " and : just fine}',
:b,
q'[This contains ' and " and : just fine]',
:c,
q'<This contains ' and " and : just fine>',
:d,
q'(This contains ' and " and : just fine)',
:e,
q'$This contains ' and " and : just fine$',
:f
from dual""")
self.assertEqual(self.cursor.bindnames(),
["A", "B", "C", "D", "E", "F"])
def test_5212_binds_between_json_constants(self):
"5212 - bind variables between JSON constants"
self.cursor.prepare("""
select
json_object('foo':dummy),
:bv1,
json_object('foo'::bv2),
:bv3,
json { 'key1': 57, 'key2' : 58 },
:bv4
from dual""")
self.assertEqual(self.cursor.bindnames(), ["BV1", "BV2", "BV3", "BV4"])
if __name__ == "__main__":
test_env.run_test_cases()