Skip to content

Commit f60ea44

Browse files
Improve handling of metadata.
1 parent 59c52be commit f60ea44

32 files changed

+709
-639
lines changed

doc/src/release_notes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ Common Changes
6464
#) Fixed bug where some :ref:`DbObject <dbobjecttype>` attributes for database
6565
objects defined using ANSI names (including FLOAT and REAL) may have shown
6666
as integers.
67+
#) Internal change: improve handling of metadata.
6768

6869

6970
oracledb 2.5.0 (November 2024)

src/oracledb/base_impl.pxd

Lines changed: 60 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,20 @@ from cpython cimport array
3838
ctypedef unsigned char char_type
3939

4040
cdef enum:
41-
NUM_TYPE_FLOAT = 0
42-
NUM_TYPE_INT = 1
43-
NUM_TYPE_DECIMAL = 2
44-
NUM_TYPE_STR = 3
41+
PY_TYPE_NUM_ARRAY = 13
42+
PY_TYPE_NUM_BOOL = 4
43+
PY_TYPE_NUM_BYTES = 10
44+
PY_TYPE_NUM_DATETIME = 7
45+
PY_TYPE_NUM_DECIMAL = 14
46+
PY_TYPE_NUM_FLOAT = 2
47+
PY_TYPE_NUM_INT = 3
48+
PY_TYPE_NUM_OBJECT = 9
49+
PY_TYPE_NUM_ORACLE_CURSOR = 6
50+
PY_TYPE_NUM_ORACLE_INTERVAL_YM = 12
51+
PY_TYPE_NUM_ORACLE_LOB = 1
52+
PY_TYPE_NUM_ORACLE_OBJECT = 11
53+
PY_TYPE_NUM_STR = 5
54+
PY_TYPE_NUM_TIMEDELTA = 8
4555

4656
cdef enum:
4757
DB_TYPE_NUM_MIN = 2000
@@ -211,6 +221,7 @@ cdef class DbType:
211221
str _ora_name
212222
uint8_t _ora_type_num
213223
uint8_t _csfrm
224+
uint8_t _default_py_type_num
214225

215226
@staticmethod
216227
cdef DbType _from_num(uint32_t num)
@@ -270,7 +281,7 @@ cdef class Buffer:
270281
cdef object parse_interval_ds(self, const uint8_t* ptr)
271282
cdef object parse_interval_ym(self, const uint8_t* ptr)
272283
cdef object parse_oracle_number(self, const uint8_t* ptr,
273-
ssize_t num_bytes, int preferred_num_type)
284+
ssize_t num_bytes, uint8_t py_type_num)
274285
cdef object read_binary_double(self)
275286
cdef object read_binary_float(self)
276287
cdef object read_binary_integer(self)
@@ -280,7 +291,7 @@ cdef class Buffer:
280291
cdef object read_interval_ds(self)
281292
cdef object read_interval_ym(self)
282293
cdef int read_int32be(self, int32_t *value) except -1
283-
cdef object read_oracle_number(self, int preferred_num_type)
294+
cdef object read_oracle_number(self, uint8_t py_type_num)
284295
cdef const char_type* read_raw_bytes(self, ssize_t num_bytes) except NULL
285296
cdef int read_raw_bytes_and_length(self, const char_type **ptr,
286297
ssize_t *num_bytes) except -1
@@ -416,6 +427,34 @@ cdef class VectorEncoder(GrowableBuffer):
416427
cdef int encode(self, array.array value) except -1
417428

418429

430+
cdef class OracleMetadata:
431+
cdef:
432+
readonly str name
433+
readonly DbType dbtype
434+
readonly BaseDbObjectTypeImpl objtype
435+
readonly int8_t precision
436+
readonly int8_t scale
437+
readonly uint32_t max_size
438+
readonly uint32_t buffer_size
439+
readonly bint nulls_allowed
440+
readonly bint is_json
441+
readonly bint is_oson
442+
readonly str domain_schema
443+
readonly str domain_name
444+
readonly dict annotations
445+
readonly uint32_t vector_dimensions
446+
readonly uint8_t vector_format
447+
readonly uint8_t vector_flags
448+
uint8_t _py_type_num
449+
450+
cdef int _finalize_init(self) except -1
451+
cdef OracleMetadata copy(self)
452+
@staticmethod
453+
cdef OracleMetadata from_type(object typ)
454+
@staticmethod
455+
cdef OracleMetadata from_value(object value)
456+
457+
419458
cdef class ConnectParamsNode:
420459
cdef:
421460
public bint source_route
@@ -571,8 +610,8 @@ cdef class BaseConnImpl:
571610
ssize_t _oson_max_fname_size
572611
bint _allow_bind_str_to_lob
573612

574-
cdef object _check_value(self, DbType dbtype, BaseDbObjectTypeImpl objtype,
575-
object value, bint* is_ok)
613+
cdef object _check_value(self, OracleMetadata type_info, object value,
614+
bint* is_ok)
576615
cdef BaseCursorImpl _create_cursor_impl(self)
577616

578617

@@ -599,7 +638,7 @@ cdef class BaseCursorImpl:
599638
public object rowfactory
600639
public bint scrollable
601640
public bint set_input_sizes
602-
public list fetch_info_impls
641+
public list fetch_metadata
603642
public list fetch_vars
604643
public list fetch_var_impls
605644
public list bind_vars
@@ -626,8 +665,8 @@ cdef class BaseCursorImpl:
626665
cdef int _close(self, bint in_del) except -1
627666
cdef BaseVarImpl _create_fetch_var(self, object conn, object cursor,
628667
object type_handler, bint
629-
uses_fetch_info, ssize_t pos,
630-
FetchInfoImpl fetch_info)
668+
uses_metadata, ssize_t pos,
669+
OracleMetadata metadata)
631670
cdef object _create_row(self)
632671
cdef BaseVarImpl _create_var_impl(self, object conn)
633672
cdef int _fetch_rows(self, object cursor) except -1
@@ -645,49 +684,21 @@ cdef class BaseCursorImpl:
645684
cdef int bind_one(self, object cursor, object parameters) except -1
646685

647686

648-
cdef class FetchInfoImpl:
649-
cdef:
650-
readonly int16_t precision
651-
readonly int16_t scale
652-
readonly uint32_t buffer_size
653-
readonly uint32_t size
654-
readonly bint nulls_allowed
655-
readonly str name
656-
readonly DbType dbtype
657-
readonly BaseDbObjectTypeImpl objtype
658-
readonly bint is_json
659-
readonly bint is_oson
660-
readonly str domain_schema
661-
readonly str domain_name
662-
readonly dict annotations
663-
readonly uint32_t vector_dimensions
664-
readonly uint8_t vector_format
665-
readonly uint8_t vector_flags
666-
667-
668687
cdef class BaseVarImpl:
669688
cdef:
670-
readonly str name
671-
readonly int16_t precision
672-
readonly int16_t scale
689+
readonly OracleMetadata metadata
673690
readonly uint32_t num_elements
674691
readonly object inconverter
675692
readonly object outconverter
676-
readonly uint32_t size
677-
readonly uint32_t buffer_size
678693
readonly bint bypass_decode
679694
readonly str encoding_errors
680695
readonly bint is_array
681-
readonly bint nulls_allowed
682696
readonly bint convert_nulls
683697
public uint32_t num_elements_in_array
684-
readonly DbType dbtype
685-
readonly BaseDbObjectTypeImpl objtype
686698
bytes _encoding_error_bytes
687699
const char *_encoding_errors
688700
BaseConnImpl _conn_impl
689-
int _preferred_num_type
690-
FetchInfoImpl _fetch_info
701+
OracleMetadata _fetch_metadata
691702
list _values
692703
bint _is_value_set
693704

@@ -702,11 +713,11 @@ cdef class BaseVarImpl:
702713
cdef object _get_scalar_value(self, uint32_t pos)
703714
cdef int _on_reset_bind(self, uint32_t num_rows) except -1
704715
cdef int _resize(self, uint32_t new_size) except -1
705-
cdef int _set_scalar_value(self, uint32_t pos, object value) except -1
716+
cdef int _set_metadata_from_type(self, object typ) except -1
717+
cdef int _set_metadata_from_value(self, object value,
718+
bint is_plsql) except -1
706719
cdef int _set_num_elements_in_array(self, uint32_t num_elements) except -1
707-
cdef int _set_type_info_from_type(self, object typ) except -1
708-
cdef int _set_type_info_from_value(self, object value,
709-
bint is_plsql) except -1
720+
cdef int _set_scalar_value(self, uint32_t pos, object value) except -1
710721

711722

712723
cdef class BaseLobImpl:
@@ -722,26 +733,14 @@ cdef class BaseDbObjectTypeImpl:
722733
readonly list attrs
723734
readonly bint is_collection
724735
readonly dict attrs_by_name
725-
readonly DbType element_dbtype
726-
readonly BaseDbObjectTypeImpl element_objtype
727-
readonly int8_t element_precision
728-
readonly int8_t element_scale
729-
readonly uint32_t element_max_size
736+
readonly OracleMetadata element_metadata
730737
readonly BaseConnImpl _conn_impl
731-
int _element_preferred_num_type
732738

733739
cpdef str _get_fqn(self)
734740

735741

736-
cdef class BaseDbObjectAttrImpl:
737-
cdef:
738-
readonly str name
739-
readonly DbType dbtype
740-
readonly BaseDbObjectTypeImpl objtype
741-
readonly int8_t precision
742-
readonly int8_t scale
743-
readonly uint32_t max_size
744-
int _preferred_num_type
742+
cdef class BaseDbObjectAttrImpl(OracleMetadata):
743+
pass
745744

746745

747746
cdef class BaseDbObjectImpl:
@@ -875,12 +874,11 @@ cdef class PipelineOpResultImpl:
875874
readonly list rows
876875
readonly object error
877876
readonly object warning
878-
readonly list fetch_info_impls
877+
readonly list fetch_metadata
879878

880879
cdef int _capture_err(self, Exception exc) except -1
881880

882881

883-
cdef int get_preferred_num_type(int16_t precision, int8_t scale)
884882
cdef uint16_t decode_uint16be(const char_type *buf)
885883
cdef uint32_t decode_uint32be(const char_type *buf)
886884
cdef uint16_t decode_uint16le(const char_type *buf)

src/oracledb/base_impl.pyx

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,6 @@ import sys
5959

6060
cydatetime.import_datetime()
6161

62-
include "impl/base/types.pyx"
63-
6462
# Python types used by the driver
6563
cdef type PY_TYPE_ASYNC_CURSOR
6664
cdef type PY_TYPE_ASYNC_LOB
@@ -90,17 +88,14 @@ cdef const char* DRIVER_INSTALLATION_URL = \
9088
cdef const char* ENCODING_UTF8 = "UTF-8"
9189
cdef const char* ENCODING_UTF16 = "UTF-16BE"
9290

93-
cdef int get_preferred_num_type(int16_t precision, int8_t scale):
94-
if scale == 0 or (scale == -127 and precision == 0):
95-
return NUM_TYPE_INT
96-
return NUM_TYPE_FLOAT
97-
9891
# protocols registered with the library
9992
REGISTERED_PROTOCOLS = {}
10093

94+
include "impl/base/types.pyx"
10195
include "impl/base/constants.pxi"
10296
include "impl/base/decoders.pyx"
10397
include "impl/base/encoders.pyx"
98+
include "impl/base/metadata.pyx"
10499
include "impl/base/utils.pyx"
105100
include "impl/base/defaults.pyx"
106101
include "impl/base/pipeline.pyx"

src/oracledb/cursor.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,9 +262,7 @@ def description(self) -> tuple:
262262
"""
263263
self._verify_open()
264264
if self._impl.is_query(self):
265-
return [
266-
FetchInfo._from_impl(i) for i in self._impl.fetch_info_impls
267-
]
265+
return [FetchInfo._from_impl(i) for i in self._impl.fetch_metadata]
268266

269267
@property
270268
def fetchvars(self) -> list:

src/oracledb/dbobject.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -347,11 +347,11 @@ def element_type(self) -> Union["DbObjectType", DbType]:
347347
object type; otherwise, it will be one of the database type constants.
348348
"""
349349
if self._element_type is None:
350-
if self._impl.element_objtype is not None:
351-
typ_impl = self._impl.element_objtype
350+
if self._impl.element_metadata.objtype is not None:
351+
typ_impl = self._impl.element_metadata.objtype
352352
self._element_type = DbObjectType._from_impl(typ_impl)
353353
else:
354-
self._element_type = self._impl.element_dbtype
354+
self._element_type = self._impl.element_metadata.dbtype
355355
return self._element_type
356356

357357
def newobject(self, value: Sequence = None) -> DbObject:

src/oracledb/fetch_info.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ def display_size(self) -> Union[int, None]:
114114
"""
115115
Returns the display size of the column.
116116
"""
117-
if self._impl.size > 0:
118-
return self._impl.size
117+
if self._impl.max_size > 0:
118+
return self._impl.max_size
119119
dbtype = self._impl.dbtype
120120
if (
121121
dbtype is DB_TYPE_DATE
@@ -158,7 +158,7 @@ def internal_size(self) -> Union[int, None]:
158158
"""
159159
Returns the size in bytes of the column.
160160
"""
161-
if self._impl.size > 0:
161+
if self._impl.max_size > 0:
162162
return self._impl.buffer_size
163163

164164
@property

src/oracledb/impl/base/bind_var.pyx

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,14 @@ cdef class BindVar:
4747
if isinstance(value, list):
4848
if len(value) != 2:
4949
errors._raise_err(errors.ERR_WRONG_ARRAY_DEFINITION)
50-
var_impl._set_type_info_from_type(value[0])
50+
var_impl._set_metadata_from_type(value[0])
5151
var_impl.num_elements = value[1]
5252
var_impl.is_array = True
5353
elif isinstance(value, int):
54-
var_impl.dbtype = DB_TYPE_VARCHAR
55-
var_impl.size = value
54+
var_impl._set_metadata_from_type(str)
55+
var_impl.metadata.max_size = value
5656
else:
57-
var_impl._set_type_info_from_type(value)
57+
var_impl._set_metadata_from_type(value)
5858
var_impl._finalize_init()
5959
self.var_impl = var_impl
6060
if isinstance(value, PY_TYPE_DB_OBJECT_TYPE):
@@ -68,20 +68,23 @@ cdef class BindVar:
6868
"""
6969
cdef:
7070
bint is_plsql = cursor_impl._is_plsql()
71+
OracleMetadata metadata
7172
BaseVarImpl var_impl
7273
var_impl = cursor_impl._create_var_impl(conn)
7374
if not isinstance(value, list):
7475
var_impl.num_elements = num_elements
75-
var_impl._set_type_info_from_value(value, is_plsql)
76+
var_impl._set_metadata_from_value(value, is_plsql)
7677
else:
7778
var_impl.is_array = True
7879
var_impl.num_elements = max(num_elements, len(value))
7980
for element in value:
8081
if element is not None:
81-
var_impl._set_type_info_from_value(element, is_plsql)
82-
if var_impl.dbtype is None:
83-
var_impl.dbtype = DB_TYPE_VARCHAR
84-
var_impl.size = 1
82+
var_impl._set_metadata_from_value(element, is_plsql)
83+
if var_impl.metadata is None:
84+
metadata = OracleMetadata.__new__(OracleMetadata)
85+
metadata.dbtype = DB_TYPE_VARCHAR
86+
metadata.max_size = 1
87+
var_impl.metadata = metadata
8588
var_impl._finalize_init()
8689
self.var_impl = var_impl
8790

0 commit comments

Comments
 (0)