Skip to content

Commit b8a51a4

Browse files
Improve error handling for BFILE LOBs.
1 parent 5f3fc86 commit b8a51a4

File tree

5 files changed

+97
-3
lines changed

5 files changed

+97
-3
lines changed

doc/src/release_notes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ Common Changes
8080
when operations are attempted on BFILE LOBs that are not permitted.
8181
Previously, ``ORA-22275: invalid LOB locator specified`` was raised
8282
instead.
83+
#) Error ``DPY-3026: operation is only supported on BFILE LOBs`` is now raised
84+
when operations are attempted on LOBs that are only supported by BFILE
85+
LOBs. Previously, ``DPI-1002: invalid OCI handle`` was raised instead.
8386
#) Error ``DPY-4005: timed out waiting for the connection pool to return a
8487
connection`` is now raised consistently when using get mode
8588
:data:`oracledb.POOL_GETMODE_TIMEDWAIT` and the timeout expires.

src/oracledb/errors.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ def _raise_not_supported(feature: str) -> None:
285285
ERR_VECTOR_VERSION_NOT_SUPPORTED = 3023
286286
ERR_VECTOR_FORMAT_NOT_SUPPORTED = 3024
287287
ERR_OPERATION_NOT_SUPPORTED_ON_BFILE = 3025
288+
ERR_OPERATION_ONLY_SUPPORTED_ON_BFILE = 3026
288289

289290
# error numbers that result in DatabaseError
290291
ERR_TNS_ENTRY_NOT_FOUND = 4000
@@ -643,6 +644,9 @@ def _raise_not_supported(feature: str) -> None:
643644
ERR_OPERATION_NOT_SUPPORTED_ON_BFILE: (
644645
"operation is not supported on BFILE LOBs"
645646
),
647+
ERR_OPERATION_ONLY_SUPPORTED_ON_BFILE: (
648+
"operation is only supported on BFILE LOBs"
649+
),
646650
ERR_ORACLE_NUMBER_NO_REPR: (
647651
"value cannot be represented as an Oracle number"
648652
),

src/oracledb/lob.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ class BaseLOB:
4141
def __del__(self):
4242
self._impl.free_lob()
4343

44+
def _check_is_bfile(self):
45+
if self._impl.dbtype is not DB_TYPE_BFILE:
46+
errors._raise_err(errors.ERR_OPERATION_ONLY_SUPPORTED_ON_BFILE)
47+
4448
def _check_not_bfile(self):
4549
if self._impl.dbtype is DB_TYPE_BFILE:
4650
errors._raise_err(errors.ERR_OPERATION_NOT_SUPPORTED_ON_BFILE)
@@ -75,12 +79,14 @@ def getfilename(self) -> tuple:
7579
Return a two-tuple consisting of the directory alias and file name for
7680
a BFILE type LOB.
7781
"""
82+
self._check_is_bfile()
7883
return self._impl.get_file_name()
7984

8085
def setfilename(self, dir_alias: str, name: str) -> None:
8186
"""
8287
Set the directory alias and name of a BFILE type LOB.
8388
"""
89+
self._check_is_bfile()
8490
self._impl.set_file_name(dir_alias, name)
8591

8692
@property
@@ -114,6 +120,7 @@ def fileexists(self) -> bool:
114120
Return a boolean indicating if the file referenced by a BFILE type LOB
115121
exists.
116122
"""
123+
self._check_is_bfile()
117124
return self._impl.file_exists()
118125

119126
def getchunksize(self) -> int:
@@ -217,6 +224,7 @@ async def fileexists(self) -> bool:
217224
Return a boolean indicating if the file referenced by a BFILE type LOB
218225
exists.
219226
"""
227+
self._check_is_bfile()
220228
return await self._impl.file_exists()
221229

222230
async def getchunksize(self) -> int:

tests/test_1900_lob_var.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -535,9 +535,10 @@ def test_1932(self):
535535

536536
def test_1933(self):
537537
"1933 - test creating a lob with an invalid type"
538-
self.assertRaises(
539-
TypeError, self.conn.createlob, oracledb.DB_TYPE_NUMBER
540-
)
538+
with self.assertRaises(TypeError):
539+
self.conn.createlob(oracledb.DB_TYPE_NUMBER)
540+
with self.assertRaises(TypeError):
541+
self.conn.createlob(oracledb.DB_TYPE_BFILE)
541542

542543
def test_1934(self):
543544
"1934 - test creation of temporary LOBs with varying data"
@@ -571,6 +572,36 @@ def test_1935(self):
571572
with self.assertRaisesFullCode("DPY-1001"):
572573
lob.write("x")
573574

575+
def test_1936(self):
576+
"1936 - test reading a non-existent directory"
577+
directory_name = "TEST_1936_MISSING_DIR"
578+
file_name = "test_1936_missing_file.txt"
579+
self.cursor.execute(
580+
"select BFILENAME(:1, :2) from dual", [directory_name, file_name]
581+
)
582+
(bfile,) = self.cursor.fetchone()
583+
self.assertEqual(bfile.getfilename(), (directory_name, file_name))
584+
with self.assertRaisesFullCode("ORA-22285"):
585+
bfile.fileexists()
586+
with self.assertRaisesFullCode("ORA-22285"):
587+
bfile.read()
588+
589+
def test_1937(self):
590+
"1937 - test using BFILE methods on non-BFILE LOBs"
591+
types = [
592+
oracledb.DB_TYPE_BLOB,
593+
oracledb.DB_TYPE_CLOB,
594+
oracledb.DB_TYPE_NCLOB,
595+
]
596+
for typ in types:
597+
lob = self.conn.createlob(typ)
598+
with self.assertRaisesFullCode("DPY-3026"):
599+
lob.getfilename()
600+
with self.assertRaisesFullCode("DPY-3026"):
601+
lob.setfilename("not_relevant", "not_relevant")
602+
with self.assertRaisesFullCode("DPY-3026"):
603+
lob.fileexists()
604+
574605

575606
if __name__ == "__main__":
576607
test_env.run_test_cases()

tests/test_5700_lob_var_async.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,8 @@ async def test_5723(self):
441441
"5723 - test creating a lob with an invalid type"
442442
with self.assertRaises(TypeError):
443443
await self.conn.createlob(oracledb.DB_TYPE_NUMBER)
444+
with self.assertRaises(TypeError):
445+
await self.conn.createlob(oracledb.DB_TYPE_BFILE)
444446

445447
async def test_5724(self):
446448
"5724 - test creation of temporary LOBs with varying data"
@@ -458,6 +460,52 @@ async def test_5724(self):
458460
await lob.write(additional_data, len(initial_data) + 1)
459461
self.assertEqual(await lob.read(), expected_result)
460462

463+
async def test_5725(self):
464+
"5725 - test reading and writing a LOB with a closed connection"
465+
types = [
466+
oracledb.DB_TYPE_BLOB,
467+
oracledb.DB_TYPE_CLOB,
468+
oracledb.DB_TYPE_NCLOB,
469+
]
470+
for typ in types:
471+
conn = await test_env.get_connection(use_async=True)
472+
lob = await conn.createlob(typ, "Temp LOB")
473+
await conn.close()
474+
with self.assertRaisesFullCode("DPY-1001"):
475+
await lob.read()
476+
with self.assertRaisesFullCode("DPY-1001"):
477+
await lob.write("x")
478+
479+
async def test_5726(self):
480+
"5726 - test reading a non-existent directory"
481+
directory_name = "TEST_5726_MISSING_DIR"
482+
file_name = "test_5726_missing_file.txt"
483+
await self.cursor.execute(
484+
"select BFILENAME(:1, :2) from dual", [directory_name, file_name]
485+
)
486+
(bfile,) = await self.cursor.fetchone()
487+
self.assertEqual(bfile.getfilename(), (directory_name, file_name))
488+
with self.assertRaisesFullCode("ORA-22285"):
489+
await bfile.fileexists()
490+
with self.assertRaisesFullCode("ORA-22285"):
491+
await bfile.read()
492+
493+
async def test_5727(self):
494+
"5727 - test using BFILE methods on non-BFILE LOBs"
495+
types = [
496+
oracledb.DB_TYPE_BLOB,
497+
oracledb.DB_TYPE_CLOB,
498+
oracledb.DB_TYPE_NCLOB,
499+
]
500+
for typ in types:
501+
lob = await self.conn.createlob(typ)
502+
with self.assertRaisesFullCode("DPY-3026"):
503+
lob.getfilename()
504+
with self.assertRaisesFullCode("DPY-3026"):
505+
lob.setfilename("not_relevant", "not_relevant")
506+
with self.assertRaisesFullCode("DPY-3026"):
507+
await lob.fileexists()
508+
461509

462510
if __name__ == "__main__":
463511
test_env.run_test_cases()

0 commit comments

Comments
 (0)