python-oracledb/tests/test_4300_cursor_other.py

831 lines
36 KiB
Python

#------------------------------------------------------------------------------
# Copyright (c) 2020, 2022, 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.
#------------------------------------------------------------------------------
"""
4300 - Module for testing other cursor methods and attributes.
"""
import decimal
import unittest
import oracledb
import test_env
class TestCase(test_env.BaseTestCase):
def test_4300_prepare(self):
"4300 - test preparing a statement and executing it multiple times"
self.assertEqual(self.cursor.statement, None)
statement = "begin :value := :value + 5; end;"
self.cursor.prepare(statement)
var = self.cursor.var(oracledb.NUMBER)
self.assertEqual(self.cursor.statement, statement)
var.setvalue(0, 2)
self.cursor.execute(None, value = var)
self.assertEqual(var.getvalue(), 7)
self.cursor.execute(None, value = var)
self.assertEqual(var.getvalue(), 12)
self.cursor.execute("begin :value2 := 3; end;", value2 = var)
self.assertEqual(var.getvalue(), 3)
def test_4301_exception_on_close(self):
"4301 - confirm an exception is raised after closing a cursor"
self.cursor.close()
self.assertRaisesRegex(oracledb.InterfaceError, "^DPY-1006:",
self.cursor.execute, "select 1 from dual")
def test_4302_iterators(self):
"4302 - test iterators"
self.cursor.execute("""
select IntCol
from TestNumbers
where IntCol between 1 and 3
order by IntCol""")
rows = [v for v, in self.cursor]
self.assertEqual(rows, [1, 2, 3])
def test_4303_iterators_interrupted(self):
"4303 - test iterators (with intermediate execute)"
self.cursor.execute("truncate table TestTempTable")
self.cursor.execute("""
select IntCol
from TestNumbers
where IntCol between 1 and 3
order by IntCol""")
test_iter = iter(self.cursor)
value, = next(test_iter)
self.cursor.execute("insert into TestTempTable (IntCol) values (1)")
self.assertRaisesRegex(oracledb.InterfaceError, "^DPY-1003:", next,
test_iter)
def test_4304_bind_names(self):
"4304 - test that bindnames() works correctly."
self.assertRaisesRegex(oracledb.ProgrammingError, "^DPY-2002:",
self.cursor.bindnames)
self.cursor.prepare("begin null; end;")
self.assertEqual(self.cursor.bindnames(), [])
self.cursor.prepare("begin :retval := :inval + 5; end;")
self.assertEqual(self.cursor.bindnames(), ["RETVAL", "INVAL"])
self.cursor.prepare("begin :retval := :a * :a + :b * :b; end;")
self.assertEqual(self.cursor.bindnames(), ["RETVAL", "A", "B"])
self.cursor.prepare("begin :a := :b + :c + :d + :e + :f + :g + " + \
":h + :i + :j + :k + :l; end;")
names = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]
self.assertEqual(self.cursor.bindnames(), names)
self.cursor.prepare("select :a * :a + :b * :b from dual")
self.assertEqual(self.cursor.bindnames(), ["A", "B"])
self.cursor.prepare("select :value1 + :VaLue_2 from dual")
self.assertEqual(self.cursor.bindnames(), ["VALUE1", "VALUE_2"])
def test_4305_set_input_sizes_negative(self):
"4305 - test cursor.setinputsizes() with invalid parameters"
val = decimal.Decimal(5)
self.assertRaisesRegex(oracledb.ProgrammingError, "^DPY-2005:",
self.cursor.setinputsizes, val, x=val)
self.assertRaisesRegex(oracledb.ProgrammingError, "^DPY-2007:",
self.cursor.setinputsizes, val)
def test_4306_set_input_sizes_no_parameters(self):
"4306 - test setting input sizes without any parameters"
self.cursor.setinputsizes()
self.cursor.execute("select :val from dual", val="Test Value")
self.assertEqual(self.cursor.fetchall(), [("Test Value",)])
def test_4307_set_input_sizes_empty_dict(self):
"4307 - test setting input sizes with an empty dictionary"
empty_dict = {}
self.cursor.prepare("select 236 from dual")
self.cursor.setinputsizes(**empty_dict)
self.cursor.execute(None, empty_dict)
self.assertEqual(self.cursor.fetchall(), [(236,)])
def test_4308_set_input_sizes_empty_list(self):
"4308 - test setting input sizes with an empty list"
empty_list = []
self.cursor.prepare("select 239 from dual")
self.cursor.setinputsizes(*empty_list)
self.cursor.execute(None, empty_list)
self.assertEqual(self.cursor.fetchall(), [(239,)])
def test_4309_set_input_sizes_by_position(self):
"4309 - test setting input sizes with positional args"
var = self.cursor.var(oracledb.STRING, 100)
self.cursor.setinputsizes(None, 5, None, 10, None, oracledb.NUMBER)
self.cursor.execute("""
begin
:1 := :2 || to_char(:3) || :4 || to_char(:5) || to_char(:6);
end;""", [var, 'test_', 5, '_second_', 3, 7])
self.assertEqual(var.getvalue(), "test_5_second_37")
def test_4310_string_format(self):
"4310 - test string format of cursor"
format_string = "<oracledb.Cursor on <oracledb.Connection to %s@%s>>"
expected_value = format_string % \
(test_env.get_main_user(), test_env.get_connect_string())
self.assertEqual(str(self.cursor), expected_value)
def test_4311_parse_query(self):
"4311 - test parsing query statements"
sql = "select LongIntCol from TestNumbers where IntCol = :val"
self.cursor.parse(sql)
self.assertEqual(self.cursor.statement, sql)
self.assertEqual(self.cursor.description,
[('LONGINTCOL', oracledb.DB_TYPE_NUMBER, 17, None,
16, 0, 0)])
def test_4312_set_output_size(self):
"4312 - test cursor.setoutputsize() does not fail (but does nothing)"
self.cursor.setoutputsize(100, 2)
def test_4313_var_negative(self):
"4313 - test cursor.var() with invalid parameters"
self.assertRaisesRegex(oracledb.ProgrammingError, "^DPY-2007:",
self.cursor.var, 5)
def test_4314_arrayvar_negative(self):
"4314 - test cursor.arrayvar() with invalid parameters"
self.assertRaisesRegex(oracledb.ProgrammingError, "^DPY-2007:",
self.cursor.arrayvar, 5, 1)
def test_4315_boolean_without_plsql(self):
"4315 - test binding boolean data without the use of PL/SQL"
self.cursor.execute("truncate table TestTempTable")
sql = "insert into TestTempTable (IntCol, StringCol1) values (:1, :2)"
self.cursor.execute(sql, (False, "Value should be 0"))
self.cursor.execute(sql, (True, "Value should be 1"))
self.cursor.execute("""
select IntCol, StringCol1
from TestTempTable
order by IntCol""")
expected_value = [(0, "Value should be 0"), (1, "Value should be 1")]
self.assertEqual(self.cursor.fetchall(), expected_value)
def test_4316_as_context_manager(self):
"4316 - test using a cursor as a context manager"
with self.cursor as cursor:
cursor.execute("truncate table TestTempTable")
cursor.execute("select count(*) from TestTempTable")
count, = cursor.fetchone()
self.assertEqual(count, 0)
self.assertRaisesRegex(oracledb.InterfaceError, "^DPY-1006:",
self.cursor.close)
def test_4317_query_row_count(self):
"4317 - test that rowcount attribute is reset to zero on query execute"
sql = "select * from dual where 1 = :s"
self.cursor.execute(sql, [0])
self.cursor.fetchone()
self.assertEqual(self.cursor.rowcount, 0)
self.cursor.execute(sql, [1])
self.cursor.fetchone()
self.assertEqual(self.cursor.rowcount, 1)
self.cursor.execute(sql, [1])
self.cursor.fetchone()
self.assertEqual(self.cursor.rowcount, 1)
self.cursor.execute(sql, [0])
self.cursor.fetchone()
self.assertEqual(self.cursor.rowcount, 0)
def test_4318_var_type_name_none(self):
"4318 - test that the typename attribute can be passed a value of None"
value_to_set = 5
var = self.cursor.var(int, typename=None)
var.setvalue(0, value_to_set)
self.assertEqual(var.getvalue(), value_to_set)
def test_4319_var_type_with_object_type(self):
"4319 - test that an object type can be used as type in cursor.var()"
obj_type = self.connection.gettype("UDT_OBJECT")
var = self.cursor.var(obj_type)
self.cursor.callproc("pkg_TestBindObject.BindObjectOut",
(28, "Bind obj out", var))
obj = var.getvalue()
result = self.cursor.callfunc("pkg_TestBindObject.GetStringRep", str,
(obj,))
exp = "udt_Object(28, 'Bind obj out', null, null, null, null, null)"
self.assertEqual(result, exp)
def test_4320_fetch_xmltype(self):
"4320 - test that fetching an XMLType returns a string"
int_val = 5
label = "IntCol"
expected_result = f"<{label}>{int_val}</{label}>"
self.cursor.execute(f"""
select XMLElement("{label}", IntCol)
from TestStrings
where IntCol = :int_val""",
int_val=int_val)
result, = self.cursor.fetchone()
self.assertEqual(result, expected_result)
def test_4321_lastrowid(self):
"4321 - test last rowid"
# no statement executed: no rowid
self.assertEqual(None, self.cursor.lastrowid)
# DDL statement executed: no rowid
self.cursor.execute("truncate table TestTempTable")
self.assertEqual(None, self.cursor.lastrowid)
# statement prepared: no rowid
self.cursor.prepare("insert into TestTempTable (IntCol) values (:1)")
self.assertEqual(None, self.cursor.lastrowid)
# multiple rows inserted: rowid of last row inserted
rows = [(n,) for n in range(225)]
self.cursor.executemany(None, rows)
rowid = self.cursor.lastrowid
self.cursor.execute("""
select rowid
from TestTempTable
where IntCol = :1""", rows[-1])
self.assertEqual(rowid, self.cursor.fetchone()[0])
# statement executed but no rows updated: no rowid
self.cursor.execute("delete from TestTempTable where 1 = 0")
self.assertEqual(None, self.cursor.lastrowid)
# stetement executed with one row updated: rowid of updated row
self.cursor.execute("""
update TestTempTable set
StringCol1 = 'Modified'
where IntCol = :1""", rows[-2])
rowid = self.cursor.lastrowid
self.cursor.execute("""
select rowid
from TestTempTable
where IntCol = :1""", rows[-2])
self.assertEqual(rowid, self.cursor.fetchone()[0])
# statement executed with many rows updated: rowid of last updated row
self.cursor.execute("""
update TestTempTable set
StringCol1 = 'Row ' || to_char(IntCol)
where IntCol = :1""", rows[-3])
rowid = self.cursor.lastrowid
self.cursor.execute("""
select StringCol1
from TestTempTable
where rowid = :1""", [rowid])
self.assertEqual("Row %s" % rows[-3], self.cursor.fetchone()[0])
def test_4322_prefetchrows(self):
"4322 - test prefetch rows"
self.setup_round_trip_checker()
# perform simple query and verify only one round trip is needed
with self.connection.cursor() as cursor:
cursor.execute("select sysdate from dual").fetchall()
self.assertRoundTrips(1)
# set prefetchrows to 1 and verify that two round trips are now needed
with self.connection.cursor() as cursor:
cursor.prefetchrows = 1
cursor.execute("select sysdate from dual").fetchall()
self.assertRoundTrips(2)
# simple DDL only requires a single round trip
with self.connection.cursor() as cursor:
cursor.execute("truncate table TestTempTable")
self.assertRoundTrips(1)
# array execution only requires a single round trip
num_rows = 590
with self.connection.cursor() as cursor:
sql = "insert into TestTempTable (IntCol) values (:1)"
data = [(n + 1,) for n in range(num_rows)]
cursor.executemany(sql, data)
self.assertRoundTrips(1)
# setting prefetch and array size to 1 requires a round-trip for each
# row
with self.connection.cursor() as cursor:
cursor.prefetchrows = 1
cursor.arraysize = 1
cursor.execute("select IntCol from TestTempTable").fetchall()
self.assertRoundTrips(num_rows + 1)
# setting prefetch and array size to 300 requires 2 round-trips
with self.connection.cursor() as cursor:
cursor.prefetchrows = 300
cursor.arraysize = 300
cursor.execute("select IntCol from TestTempTable").fetchall()
self.assertRoundTrips(2)
def test_4323_existing_cursor_prefetchrows(self):
"4323 - test prefetch rows using existing cursor"
self.setup_round_trip_checker()
# Set prefetch rows on an existing cursor
num_rows = 590
with self.connection.cursor() as cursor:
cursor.execute("truncate table TestTempTable")
sql = "insert into TestTempTable (IntCol) values (:1)"
data = [(n + 1,) for n in range(num_rows)]
cursor.executemany(sql, data)
cursor.prefetchrows = 300
cursor.arraysize = 300
cursor.execute("select IntCol from TestTempTable").fetchall()
self.assertRoundTrips(4)
def test_4324_bind_names_with_single_line_comments(self):
"4324 - test bindnames() with single line comments"
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_4325_bind_names_with_multi_line_comments(self):
"4325 - test bindnames() with multi line comments"
self.cursor.prepare("""/*--select * from :a where :a = 1
select * from table_names where :a = 1*/
select * from :table_name where :value = 1
""")
self.assertEqual(self.cursor.bindnames(), ["TABLE_NAME", "VALUE"])
def test_4326_bind_names_with_strings(self):
"4326 - test bindnames() with strings in the statement"
statement = """
begin
:value := to_date('20021231 12:31:00',
'YYYYMMDD HH24:MI:SS');
end;"""
self.cursor.prepare(statement)
self.assertEqual(self.cursor.bindnames(), ["VALUE"])
def test_4327_parse_plsql(self):
"4327 - test parsing plsql statements"
sql = "begin :value := 5; end;"
self.cursor.parse(sql)
self.assertEqual(self.cursor.statement, sql)
self.assertEqual(self.cursor.description, None)
def test_4328_parse_ddl(self):
"4328 - test parsing ddl statements"
sql = "truncate table TestTempTable"
self.cursor.parse(sql)
self.assertEqual(self.cursor.statement, sql)
self.assertEqual(self.cursor.description, None)
def test_4329_parse_dml(self):
"4329 - test parsing dml statements"
sql = "insert into TestTempTable (IntCol) values (1)"
self.cursor.parse(sql)
self.assertEqual(self.cursor.statement, sql)
self.assertEqual(self.cursor.description, None)
def test_4330_encodingErrors_deprecation(self):
"4330 - test to verify encodingErrors is deprecated"
errors = 'strict'
self.assertRaisesRegex(oracledb.ProgrammingError, "^DPY-2014:",
self.cursor.var, oracledb.NUMBER,
encoding_errors=errors, encodingErrors=errors)
def test_4331_unsupported_arrays_of_arrays(self):
"4331 - test arrays of arrays not supported"
simple_var = self.cursor.arrayvar(oracledb.NUMBER, 3)
self.assertRaisesRegex(oracledb.NotSupportedError, "^DPY-3005:",
simple_var.setvalue, 1, [1, 2, 3])
def test_4332_set_input_sizes_with_invalid_list_parameters(self):
"4332 - test cursor.setinputsizes() with invalid list parameters"
self.assertRaisesRegex(oracledb.ProgrammingError, "^DPY-2011:",
self.cursor.setinputsizes, [int, 2, 10])
def test_4333_unsupported_python_type(self):
"4333 - test unsupported python type on cursor"
self.assertRaisesRegex(oracledb.NotSupportedError, "^DPY-3003:",
self.cursor.var, list)
def test_4334_bind_by_name_with_leading_colon(self):
"4334 - test binding by name with leading colon"
sql = "select :arg1 from dual"
params = {":arg1" : 5}
self.cursor.execute(sql, params)
result, = self.cursor.fetchone()
self.assertEqual(result, params[":arg1"])
def test_4335_bind_out_mixed_null_not_null(self):
"4335 - test binding mixed null and not null values in a PL/SQL block"
sql = """
begin
:1 := null;
:2 := 'Value 1';
:3 := null;
:4 := 'Value 2';
end;"""
out_vars = [self.cursor.var(str) for i in range(4)]
self.cursor.execute(sql, out_vars)
values = [var.getvalue() for var in out_vars]
self.assertEqual(values, [None, 'Value 1', None, 'Value 2'])
def test_4336_bind_names_with_division_operators(self):
"4336 - test bindnames() with multiple division operators"
self.cursor.prepare("""
select :a / :b, :c / :d
from dual""")
self.assertEqual(self.cursor.bindnames(), ["A", "B", "C", "D"])
def test_4337_exclude_from_stmt_cache(self):
"4337 - test excluding statement from statement cache"
num_iters = 10
sql = "select user from dual"
self.setup_parse_count_checker()
# with statement cache enabled, only one parse should take place
for i in range(num_iters):
with self.connection.cursor() as cursor:
cursor.execute(sql)
self.assertParseCount(1)
# with statement cache disabled for the statement, parse count should
# be the same as the number of iterations
for i in range(num_iters):
with self.connection.cursor() as cursor:
cursor.prepare(sql, cache_statement=False)
cursor.execute(None)
self.assertParseCount(num_iters - 1)
def test_4338_bind_names_with_opening_parentheses(self):
"4338 - test bindnames() with opening parentheses in statement"
sql = "(select :a from dual) union (select :b from dual)"
self.cursor.prepare(sql)
self.assertEqual(self.cursor.bindnames(), ["A", "B"])
def test_4339_repeated_ddl(self):
"4339 - test repeated DDL"
self.cursor.execute("truncate table TestTempTable")
self.cursor.execute("insert into TestTempTable (IntCol) values (1)")
self.cursor.execute("truncate table TestTempTable")
self.cursor.execute("insert into TestTempTable (IntCol) values (1)")
def test_4340_sql_with_non_ascii_chars(self):
"4340 - test executing SQL with non-ASCII characters"
self.cursor.execute("select 'FÖÖ' from dual")
result, = self.cursor.fetchone()
self.assertTrue(result in ('FÖÖ', 'F¿¿'))
def test_4341_unquoted_binds_case_sensitivity(self):
"4341 - test case sensitivity of unquoted bind names"
self.cursor.execute("select :test from dual", {"TEST": "a"})
result, = self.cursor.fetchone()
self.assertEqual(result, "a")
def test_4342_quoted_binds_case_sensitivity(self):
"4342 - test case sensitivity of quoted bind names"
sql = 'select :"test" from dual'
params = {'"TEST"': "a"}
self.assertRaisesRegex(oracledb.DatabaseError,
"^ORA-01036:|^DPY-4008:", self.cursor.execute,
sql, params)
def test_4343_reserved_keyword_as_bind_name(self):
"4343 - test using a reserved keywords as a bind name"
sql = 'select :ROWID from dual'
self.assertRaisesRegex(oracledb.DatabaseError,
"^ORA-01745:", self.cursor.parse, sql)
def test_4344_invalid_quoted_bind(self):
"4344 - test using an invalid quoted bind"
sql = 'select ":test" from dual'
self.cursor.prepare(sql)
self.assertEqual(self.cursor.bindnames(), [])
def test_4345_non_ascii_bind_name(self):
"4345 - test using a 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_4346_various_quoted_binds(self):
"4346 - test various quoted bind names"
self.cursor.prepare('select :"percent%" from dual')
self.assertEqual(self.cursor.bindnames(), ["percent%"])
self.cursor.prepare('select :"q?marks" from dual')
self.assertEqual(self.cursor.bindnames(), ["q?marks"])
self.cursor.prepare('select :"percent%(ens)yah" from dual')
self.assertEqual(self.cursor.bindnames(), ["percent%(ens)yah"])
self.cursor.prepare('select :"per % cent" from dual')
self.assertEqual(self.cursor.bindnames(), ["per % cent"])
self.cursor.prepare('select :"per cent" from dual')
self.assertEqual(self.cursor.bindnames(), ["per cent"])
self.cursor.prepare('select :"par(ens)" from dual')
self.assertEqual(self.cursor.bindnames(), ["par(ens)"])
self.cursor.prepare('select :"more/slashes" from dual')
self.assertEqual(self.cursor.bindnames(), ["more/slashes"])
self.cursor.prepare('select :"%percent" from dual')
self.assertEqual(self.cursor.bindnames(), ["%percent"])
self.cursor.prepare('select :"/slashes/" from dual')
self.assertEqual(self.cursor.bindnames(), ["/slashes/"])
self.cursor.prepare('select :"1col:on" from dual')
self.assertEqual(self.cursor.bindnames(), ["1col:on"])
self.cursor.prepare('select :"col:ons" from dual')
self.assertEqual(self.cursor.bindnames(), ["col:ons"])
self.cursor.prepare('select :"more :: %colons%" from dual')
self.assertEqual(self.cursor.bindnames(), ["more :: %colons%"])
self.cursor.prepare('select :"more/slashes" from dual')
self.assertEqual(self.cursor.bindnames(), ["more/slashes"])
self.cursor.prepare('select :"spaces % more spaces" from dual')
self.assertEqual(self.cursor.bindnames(), ["spaces % more spaces"])
self.cursor.prepare('select "col:ons", :"col:ons", :id from dual')
self.assertEqual(self.cursor.bindnames(), ["col:ons", "ID"])
def test_4347_arraysize_lt_prefetchrows(self):
"4347 - test array size less than prefetch rows"
sql = "select 1 from dual union select 2 from dual"
for i in range(2):
with self.connection.cursor() as cursor:
cursor.arraysize = 1
cursor.execute(sql)
rows = cursor.fetchall()
self.assertEqual(rows, [(1,), (2,)])
def test_4348_reexecute_query_with_blob_as_bytes(self):
"4348 - test re-executing a query with blob as bytes"
def type_handler(cursor, name, default_type, size, precision, scale):
if default_type == oracledb.DB_TYPE_BLOB:
return cursor.var(bytes, arraysize=cursor.arraysize)
self.connection.outputtypehandler = type_handler
blob_data = b"An arbitrary set of blob data for test case 4348"
self.cursor.execute("truncate table TestBLOBs")
self.cursor.execute("""
insert into TestBLOBs
(IntCol, BlobCol)
values (1, :data)""",
[blob_data])
self.cursor.execute("select IntCol, BlobCol from TestBLOBs")
self.assertEqual(self.cursor.fetchall(), [(1, blob_data)])
self.cursor.execute("truncate table TestBLOBs")
self.cursor.execute("""
insert into TestBLOBs
(IntCol, BlobCol)
values (1, :data)""",
[blob_data])
self.cursor.execute("select IntCol, BlobCol from TestBLOBs")
self.assertEqual(self.cursor.fetchall(), [(1, blob_data)])
def test_4349_test_sql_with_quoted_identifiers_and_strings(self):
"4349 - test parsing 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_4350_reexecute_after_error(self):
"4350 - test re-executing a statement after raising an error"
sql = "select * from TestFakeTable"
self.assertRaisesRegex(oracledb.DatabaseError, "^ORA-00942:",
self.cursor.execute, sql)
self.assertRaisesRegex(oracledb.DatabaseError, "^ORA-00942:",
self.cursor.execute, sql)
sql = "insert into TestStrings (StringCol) values (NULL)"
self.assertRaisesRegex(oracledb.DatabaseError, "^ORA-01400:",
self.cursor.execute, sql)
self.assertRaisesRegex(oracledb.DatabaseError, "^ORA-01400:",
self.cursor.execute, sql)
def test_4351_variable_not_in_select_list(self):
"4351 - test executing a statement that raises ORA-01007"
with self.connection.cursor() as cursor:
cursor.execute("""
create or replace view ora_1007 as
select
1 as SampleNumber,
'String' as SampleString,
'Another String' as AnotherString
from dual""")
with self.connection.cursor() as cursor:
cursor.execute("select * from ora_1007")
self.assertEqual(cursor.fetchone(),
(1, 'String', 'Another String'))
with self.connection.cursor() as cursor:
cursor.execute("""
create or replace view ora_1007 as
select
1 as SampleNumber,
'Another String' as AnotherString
from dual""")
with self.connection.cursor() as cursor:
cursor.execute("select * from ora_1007")
self.assertEqual(cursor.fetchone(),
(1, 'Another String'))
def test_4352_update_empty_row(self):
"4352 - test updating an empty row"
int_var = self.cursor.var(int)
self.cursor.execute("truncate table TestTempTable")
sql = """
begin
update TestTempTable set
IntCol = :1
where StringCol1 = :2
returning IntCol into :3;
end;"""
self.cursor.execute(sql, [1, "test string 4352", int_var])
self.assertEqual(int_var.values, [None])
def test_4353_single_quoted_strings(self):
"4353 - test bindnames with statement containing strings"
sql = '''select '"string_1"', :bind_1, 'string_2' from dual'''
self.cursor.prepare(sql)
self.assertEqual(self.cursor.bindnames(), ['BIND_1'])
def test_4354_fetch_duplicate_data_twice(self):
"4354 - fetch duplicate data from query in statement cache"
sql = """
select 'A', 'B', 'C' from dual
union all
select 'A', 'B', 'C' from dual
union all
select 'A', 'B', 'C' from dual
"""
expected_data = [('A', 'B', 'C')] * 3
with self.connection.cursor() as cursor:
cursor.prefetchrows = 0
cursor.execute(sql)
self.assertEqual(cursor.fetchall(), expected_data)
with self.connection.cursor() as cursor:
cursor.prefetchrows = 0
cursor.execute(sql)
self.assertEqual(cursor.fetchall(), expected_data)
def test_4355_fetch_duplicate_data_with_out_converter(self):
"4355 - fetch duplicate data with outconverter"
def out_converter(value):
self.assertIs(type(value), str)
return int(value)
def type_handler(cursor, name, default_type, size, precision, scale):
if name == "COL_3":
return cursor.var(str, arraysize=cursor.arraysize,
outconverter=out_converter)
self.cursor.outputtypehandler = type_handler
self.cursor.execute("""
select 'A' as col_1, 2 as col_2, 3 as col_3 from dual
union all
select 'A' as col_1, 2 as col_2, 3 as col_3 from dual
union all
select 'A' as col_1, 2 as col_2, 3 as col_3 from dual""")
expected_data = [('A', 2, 3)] * 3
self.assertEqual(self.cursor.fetchall(), expected_data)
def test_4356_multiple_single_quoted_strings(self):
"4356 - test bindnames with statement containing quoted strings"
sql = "select :bind_4356, 'string_4356', ':string_4356' from dual"
self.cursor.prepare(sql)
self.assertEqual(self.cursor.bindnames(), ['BIND_4356'])
def test_4357_setinputsizes_with_defaults(self):
"4357 - test setinputsizes() with defaults specified"
self.cursor.setinputsizes(None, str)
self.assertIs(self.cursor.bindvars[0], None)
self.assertIsInstance(self.cursor.bindvars[1], oracledb.Var)
self.cursor.setinputsizes(a=None, b=str)
self.assertIs(self.cursor.bindvars.get("a"), None)
self.assertIsInstance(self.cursor.bindvars["b"], oracledb.Var)
def test_4358_kill_conn_with_open_cursor(self):
"4538 - kill connection with open cursor"
admin_conn = test_env.get_admin_connection()
conn = test_env.get_connection()
self.assertEqual(conn.is_healthy(), True)
cursor = conn.cursor()
cursor.execute("""
select
dbms_debug_jdwp.current_session_id,
dbms_debug_jdwp.current_session_serial
from dual""")
sid, serial = cursor.fetchone()
with admin_conn.cursor() as admin_cursor:
sql = f"alter system kill session '{sid},{serial}'"
admin_cursor.execute(sql)
self.assertRaisesRegex(oracledb.DatabaseError, "^DPY-4011:",
cursor.execute, "select user from dual")
self.assertFalse(conn.is_healthy())
def test_4359_kill_conn_in_context_manager(self):
"4359 - kill connection in cursor context manager"
admin_conn = test_env.get_admin_connection()
conn = test_env.get_connection()
self.assertEqual(conn.is_healthy(), True)
with conn.cursor() as cursor:
cursor.execute("""
select
dbms_debug_jdwp.current_session_id,
dbms_debug_jdwp.current_session_serial
from dual""")
sid, serial = cursor.fetchone()
with admin_conn.cursor() as admin_cursor:
sql = f"alter system kill session '{sid},{serial}'"
admin_cursor.execute(sql)
self.assertRaisesRegex(oracledb.DatabaseError, "^DPY-4011:",
cursor.execute, "select user from dual")
self.assertEqual(conn.is_healthy(), False)
def test_4360_fetchmany(self):
"4360 - fetchmany() with and without parameters"
sql_part = "select user from dual"
sql = " union all ".join([sql_part] * 10)
with self.connection.cursor() as cursor:
cursor.arraysize = 6
cursor.execute(sql)
rows = cursor.fetchmany()
self.assertEqual(len(rows), cursor.arraysize)
cursor.execute(sql)
rows = cursor.fetchmany(size=2)
self.assertEqual(len(rows), 2)
cursor.execute(sql)
rows = cursor.fetchmany(numRows=4)
self.assertEqual(len(rows), 4)
cursor.execute(sql)
self.assertRaisesRegex(oracledb.DatabaseError, "^DPY-2014:",
cursor.fetchmany, size=2, numRows=4)
def test_4361_rowcount_after_close(self):
"4361 - access cursor.rowcount after closing cursor"
with self.connection.cursor() as cursor:
cursor.execute("select user from dual")
cursor.fetchall()
self.assertEqual(cursor.rowcount, 1)
self.assertEqual(cursor.rowcount, -1)
def test_4362_change_of_bind_type_with_define(self):
"4362 - changing bind type with define needed"
self.cursor.execute("truncate table TestClobs")
row_for_1 = (1, "Short value 1")
row_for_56 = (56, "Short value 56")
for data in (row_for_1, row_for_56):
self.cursor.execute("""
insert into TestClobs (IntCol, ClobCol)
values (:1, :2)""", data)
sql = "select IntCol, ClobCol from TestClobs where IntCol = :int_col"
with test_env.FetchLobsContextManager(False):
self.cursor.execute(sql, int_col="1")
self.assertEqual(self.cursor.fetchone(), row_for_1)
self.cursor.execute(sql, int_col="56")
self.assertEqual(self.cursor.fetchone(), row_for_56)
self.cursor.execute(sql, int_col=1)
self.assertEqual(self.cursor.fetchone(), row_for_1)
def test_4363_multiple_parse(self):
"4363 - test calling cursor.parse() twice with the same statement"
self.cursor.execute("truncate table TestTempTable")
data = (4363, "Value for test 4363")
self.cursor.execute("""
insert into TestTempTable (IntCol, StringCol1)
values (:1, :2)""", data)
sql = "update TestTempTable set StringCol1 = :v where IntCol = :i"
for i in range(2):
self.cursor.parse(sql)
self.cursor.execute(sql, ("Updated value", data[0]))
def test_4364_binds_between_comment_blocks(self):
"4364 - test bindnames() for bind variables between comment blocks"
self.cursor.prepare("""
select
/* comment 1 */
:a,
/* comment 2 */
:b
/* comment 3 */
from dual""")
self.assertEqual(self.cursor.bindnames(), ["A", "B"])
if __name__ == "__main__":
test_env.run_test_cases()