Skip to content

Commit 59c52be

Browse files
Added support for precision, scale and max_size on DbObjectAttribute
objects
1 parent b4d3990 commit 59c52be

File tree

11 files changed

+365
-179
lines changed

11 files changed

+365
-179
lines changed

doc/src/api_manual/dbobject_type.rst

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,11 +192,41 @@ DbObjectAttribute Objects
192192
:attr:`DbObjectType.attributes` are instances of this type.
193193

194194

195+
.. attribute:: DbObjectAttribute.max_size
196+
197+
This read-only attribute returns the maximum size (in bytes) of the
198+
attribute when the attribute's type is one of
199+
:data:`oracledb.DB_TYPE_CHAR`, :data:`oracledb.DB_TYPE_NCHAR`,
200+
:data:`oracledb.DB_TYPE_NVARCHAR`, :data:`oracledb.DB_TYPE_RAW`, or
201+
:data:`oracledb.DB_TYPE_VARCHAR`. For all other types the value returned is
202+
`None`.
203+
204+
.. versionadded:: 2.6.0
205+
206+
195207
.. attribute:: DbObjectAttribute.name
196208

197209
This read-only attribute returns the name of the attribute.
198210

199211

212+
.. attribute:: DbObjectAttribute.precision
213+
214+
This read-only attribute returns the precision of the attribute when the
215+
attribute's type is :data:`oracledb.DB_TYPE_NUMBER`. For all other types
216+
the value returned is `None`.
217+
218+
.. versionadded:: 2.6.0
219+
220+
221+
.. attribute:: DbObjectAttribute.scale
222+
223+
This read-only attribute returns the scale of the attribute when the
224+
attribute's type is :data:`oracledb.DB_TYPE_NUMBER`. For all other types
225+
the value returned is `None`.
226+
227+
.. versionadded:: 2.6.0
228+
229+
200230
.. attribute:: DbObjectAttribute.type
201231

202232
This read-only attribute returns the type of the attribute. This will be an

doc/src/release_notes.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ Common Changes
5757
#) Added support for :ref:`naming and caching connection pools
5858
<connpoolcache>` during creation, and retrieving them later from the
5959
python-oracledb pool cache with :meth:`oracledb.get_pool()`.
60+
#) Added attributes :attr:`DbObjectAttribute.precision`,
61+
:attr:`DbObjectAttribute.scale`, and :attr:`DbObjectAttribute.max_size` that
62+
provide additional metadata about
63+
:ref:`database object attributes <dbobjectattr>`.
64+
#) Fixed bug where some :ref:`DbObject <dbobjecttype>` attributes for database
65+
objects defined using ANSI names (including FLOAT and REAL) may have shown
66+
as integers.
6067

6168

6269
oracledb 2.5.0 (November 2024)

src/oracledb/dbobject.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,13 +235,39 @@ def _from_impl(cls, impl):
235235
attr._type = None
236236
return attr
237237

238+
@property
239+
def max_size(self) -> Union[int, None]:
240+
"""
241+
Returns the max size of the attribute (in bytes) for attributes of type
242+
DB_TYPE_RAW, DB_TYPE_CHAR, DB_TYPE_NCHAR, DB_TYPE_VARCHAR and
243+
DB_TYPE_NVARCHAR.
244+
"""
245+
if self._impl.max_size:
246+
return self._impl.max_size
247+
238248
@property
239249
def name(self) -> str:
240250
"""
241251
This read-only attribute returns the name of the attribute.
242252
"""
243253
return self._impl.name
244254

255+
@property
256+
def precision(self) -> Union[int, None]:
257+
"""
258+
Returns the precision of the attribute.
259+
"""
260+
if self._impl.precision or self._impl.scale:
261+
return self._impl.precision
262+
263+
@property
264+
def scale(self) -> Union[int, None]:
265+
"""
266+
Returns the scale of the column.
267+
"""
268+
if self._impl.precision or self._impl.scale:
269+
return self._impl.scale
270+
245271
@property
246272
def type(self) -> Union["DbObjectType", DbType]:
247273
"""

src/oracledb/impl/base/cursor.pyx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,9 @@ cdef class BaseCursorImpl:
221221
if db_type_num == DB_TYPE_NUM_NUMBER:
222222
if C_DEFAULTS.fetch_decimals:
223223
var_impl._preferred_num_type = NUM_TYPE_DECIMAL
224-
elif var_impl.scale == 0 \
225-
or (var_impl.scale == -127 and var_impl.precision == 0):
226-
var_impl._preferred_num_type = NUM_TYPE_INT
224+
else:
225+
var_impl._preferred_num_type = \
226+
get_preferred_num_type(var_impl.precision, var_impl.scale)
227227
elif fetch_info.is_oson and db_type_num != DB_TYPE_NUM_JSON:
228228
conn_impl = self._get_conn_impl()
229229
var_impl.dbtype = DB_TYPE_LONG_RAW

src/oracledb/impl/base/types.pyx

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -396,14 +396,9 @@ DB_TYPE_XMLTYPE = DbType(
396396
)
397397

398398
# additional aliases
399-
db_type_by_ora_name["DOUBLE PRECISION"] = DB_TYPE_NUMBER
400-
db_type_by_ora_name["FLOAT"] = DB_TYPE_NUMBER
401-
db_type_by_ora_name["INTEGER"] = DB_TYPE_NUMBER
402399
db_type_by_ora_name["PL/SQL BOOLEAN"] = DB_TYPE_BOOLEAN
403400
db_type_by_ora_name["PL/SQL BINARY INTEGER"] = DB_TYPE_BINARY_INTEGER
404401
db_type_by_ora_name["PL/SQL PLS INTEGER"] = DB_TYPE_BINARY_INTEGER
405-
db_type_by_ora_name["REAL"] = DB_TYPE_NUMBER
406-
db_type_by_ora_name["SMALLINT"] = DB_TYPE_NUMBER
407402
db_type_by_ora_name["TIMESTAMP WITH TZ"] = DB_TYPE_TIMESTAMP_TZ
408403
db_type_by_ora_name["TIMESTAMP WITH LOCAL TZ"] = DB_TYPE_TIMESTAMP_LTZ
409404

src/oracledb/impl/thick/dbobject.pyx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,10 @@ cdef class ThickDbObjectAttrImpl(BaseDbObjectAttrImpl):
289289
impl.precision = info.typeInfo.precision
290290
impl.scale = info.typeInfo.scale
291291
impl.max_size = info.typeInfo.dbSizeInBytes
292-
impl._preferred_num_type = \
293-
get_preferred_num_type(info.typeInfo.precision,
294-
info.typeInfo.scale)
292+
if impl.dbtype.num == DPI_ORACLE_TYPE_NUMBER:
293+
impl._preferred_num_type = \
294+
get_preferred_num_type(info.typeInfo.precision,
295+
info.typeInfo.scale)
295296
if info.typeInfo.objectType:
296297
typ_handle = info.typeInfo.objectType
297298
impl.objtype = ThickDbObjectTypeImpl._from_handle(conn_impl,
@@ -341,9 +342,10 @@ cdef class ThickDbObjectTypeImpl(BaseDbObjectTypeImpl):
341342
impl.element_precision = info.elementTypeInfo.precision
342343
impl.element_scale = info.elementTypeInfo.scale
343344
impl.element_max_size = info.elementTypeInfo.dbSizeInBytes
344-
impl._element_preferred_num_type = \
345-
get_preferred_num_type(info.elementTypeInfo.precision,
346-
info.elementTypeInfo.scale)
345+
if dbtype.num == DPI_ORACLE_TYPE_NUMBER:
346+
impl._element_preferred_num_type = \
347+
get_preferred_num_type(info.elementTypeInfo.precision,
348+
info.elementTypeInfo.scale)
347349
if info.elementTypeInfo.objectType != NULL:
348350
handle = info.elementTypeInfo.objectType
349351
temp = ThickDbObjectTypeImpl._from_handle(conn_impl, handle)

src/oracledb/impl/thin/dbobject_cache.pyx

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,21 @@ cdef str DBO_CACHE_SQL_GET_COLUMNS = """
7878
then data_length
7979
else 0
8080
end,
81-
nvl(data_precision, 0),
82-
nvl(data_scale, 0)
81+
case
82+
when data_precision is null and data_scale is null
83+
then 0
84+
when data_precision is null
85+
then 38
86+
else data_precision
87+
end,
88+
case
89+
when data_precision is null and data_scale is null
90+
and data_type = 'NUMBER'
91+
then -127
92+
when data_scale is null
93+
then 0
94+
else data_scale
95+
end
8396
from all_tab_cols
8497
where owner = :owner
8598
and table_name = substr(:name, 1, length(:name) - 8)
@@ -307,10 +320,13 @@ cdef class BaseThinDbObjectTypeCache:
307320
# process the type code
308321
if attr_type == TNS_OBJ_TDS_TYPE_NUMBER:
309322
ora_type_num = ORA_TYPE_NUM_NUMBER
310-
buf.read_sb1(precision)
311-
buf.read_sb1(scale)
312-
preferred_num_type[0] = \
313-
get_preferred_num_type(precision[0], scale[0])
323+
buf.read_sb1(&temp_precision)
324+
buf.read_sb1(&temp_scale)
325+
if temp_precision != 0 or temp_scale != 0:
326+
precision[0] = temp_precision
327+
scale[0] = temp_scale
328+
preferred_num_type[0] = \
329+
get_preferred_num_type(precision[0], scale[0])
314330
elif attr_type == TNS_OBJ_TDS_TYPE_FLOAT:
315331
ora_type_num = ORA_TYPE_NUM_NUMBER
316332
buf.skip_raw_bytes(1) # precision
@@ -389,13 +405,34 @@ cdef class BaseThinDbObjectTypeCache:
389405
attr_impl.dbtype = DB_TYPE_OBJECT
390406
attr_impl.objtype = attr_typ_impl
391407
else:
392-
attr_impl.dbtype = DbType._from_ora_name(type_name)
393-
attr_impl.max_size = max_size
394-
if precision != 0 or scale != 0:
395-
attr_impl.precision = precision
396-
attr_impl.scale = scale
408+
if type_name in ("INTEGER", "SMALLINT"):
409+
attr_impl.dbtype = DB_TYPE_NUMBER
410+
attr_impl.precision = 38
411+
attr_impl.scale = 0
412+
elif type_name == "REAL":
413+
attr_impl.dbtype = DB_TYPE_NUMBER
414+
attr_impl.precision = 63
415+
attr_impl.scale = -127
416+
elif type_name in ("DOUBLE PRECISION", "FLOAT"):
417+
attr_impl.dbtype = DB_TYPE_NUMBER
418+
# the database sends type name "FLOAT" instead of type name
419+
# "REAL" when looking at table metadata but not when examining
420+
# database object attribute metadata so account for that here
421+
if precision != 0:
422+
attr_impl.precision = precision
423+
else:
424+
attr_impl.precision = 126
425+
attr_impl.scale = -127
426+
else:
427+
attr_impl.dbtype = DbType._from_ora_name(type_name)
428+
attr_impl.max_size = max_size
429+
if attr_impl.dbtype._ora_type_num == ORA_TYPE_NUM_NUMBER:
430+
attr_impl.precision = precision
431+
attr_impl.scale = scale
432+
if attr_impl.dbtype._ora_type_num == ORA_TYPE_NUM_NUMBER:
397433
attr_impl._preferred_num_type = \
398-
get_preferred_num_type(precision, scale)
434+
get_preferred_num_type(attr_impl.precision,
435+
attr_impl.scale)
399436
typ_impl.attrs.append(attr_impl)
400437
typ_impl.attrs_by_name[name] = attr_impl
401438

src/oracledb/thin_impl.pyx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ from .base_impl import (
179179
DB_TYPE_NCLOB,
180180
DB_TYPE_BINARY_INTEGER,
181181
DB_TYPE_CURSOR,
182+
DB_TYPE_NUMBER,
182183
DB_TYPE_OBJECT,
183184
DB_TYPE_XMLTYPE,
184185
)

0 commit comments

Comments
 (0)