Skip to content

Commit 6e86db9

Browse files
Avoid segfault when fetching sparse vectors with flexible dimensions.
1 parent 4bbc320 commit 6e86db9

File tree

4 files changed

+49
-11
lines changed

4 files changed

+49
-11
lines changed

doc/src/user_guide/dataframes.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,8 @@ When converting Oracle Database VECTORs:
174174
``indices`` and ``values`` similar to :ref:`SparseVector objects
175175
<sparsevectorsobj>`.
176176

177-
- VECTOR columns with flexible dimensions are supported.
177+
- Fixed and flexible dimensions are supported for dense VECTOR columns. For
178+
sparse VECTOR columns, the dimension of each vector must be the same.
178179

179180
- VECTOR columns with flexible formats are not supported. Each vector value
180181
must have the same storage format data type.

src/oracledb/errors.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ def _raise_not_supported(feature: str) -> None:
288288
ERR_PAYLOAD_CANNOT_BE_ENQUEUED = 2062
289289
ERR_SCROLL_OUT_OF_RESULT_SET = 2063
290290
ERR_POOL_MAX_LESS_THAN_MIN = 2064
291+
ERR_ARROW_SPARSE_VECTOR_NOT_ALLOWED = 2065
291292

292293
# error numbers that result in NotSupportedError
293294
ERR_TIME_NOT_SUPPORTED = 3000
@@ -893,6 +894,10 @@ def _raise_not_supported(feature: str) -> None:
893894
ERR_INVALID_NETWORK_NAME: (
894895
'"{name}" includes characters that are not allowed'
895896
),
897+
ERR_ARROW_SPARSE_VECTOR_NOT_ALLOWED: (
898+
"Apache Arrow format does not support sparse vectors with flexible "
899+
"dimensions"
900+
),
896901
ERR_ARROW_UNSUPPORTED_DATA_TYPE: (
897902
"conversion from Oracle Database type {db_type_name} to Apache "
898903
"Arrow format is not supported"

src/oracledb/interchange/nanoarrow_bridge.pyx

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -604,26 +604,30 @@ cdef class OracleArrowArray:
604604
"""
605605
Append a sparse vector to the array.
606606
"""
607-
cdef:
608-
ArrowArray *num_dims_array = self.arrow_array.children[0]
609-
ArrowArray *indices_array = self.arrow_array.children[1]
610-
ArrowArray *values_array = self.arrow_array.children[2]
607+
cdef ArrowArray *array
608+
609+
# validate that the array supports sparse vectors
610+
if self.arrow_type != NANOARROW_TYPE_STRUCT:
611+
errors._raise_err(errors.ERR_ARROW_SPARSE_VECTOR_NOT_ALLOWED)
611612

612613
# append number of dimensions
613-
_check_nanoarrow(ArrowArrayAppendInt(num_dims_array, num_dims))
614+
array = self.arrow_array.children[0]
615+
_check_nanoarrow(ArrowArrayAppendInt(array, num_dims))
614616

615617
# append indices array
616-
append_uint32_array(indices_array, indices)
618+
array = self.arrow_array.children[1]
619+
append_uint32_array(array, indices)
617620

618621
# append values array
622+
array = self.arrow_array.children[2]
619623
if self.child_arrow_type == NANOARROW_TYPE_FLOAT:
620-
append_float_array(values_array, values)
624+
append_float_array(array, values)
621625
elif self.child_arrow_type == NANOARROW_TYPE_DOUBLE:
622-
append_double_array(values_array, values)
626+
append_double_array(array, values)
623627
elif self.child_arrow_type == NANOARROW_TYPE_INT8:
624-
append_int8_array(values_array, values)
628+
append_int8_array(array, values)
625629
elif self.child_arrow_type == NANOARROW_TYPE_UINT8:
626-
append_uint8_array(values_array, values)
630+
append_uint8_array(array, values)
627631

628632
# indicate structure is completed
629633
_check_nanoarrow(ArrowArrayFinishElement(self.arrow_array))

tests/test_8000_dataframe.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,6 +1119,34 @@ def test_8038(self):
11191119
"""
11201120
)
11211121

1122+
@unittest.skipUnless(
1123+
test_env.has_client_version(23, 7), "unsupported client"
1124+
)
1125+
@unittest.skipUnless(
1126+
test_env.has_server_version(23, 7), "unsupported server"
1127+
)
1128+
def test_8039(self):
1129+
"8039 - DPY-4007 -fetch sparse vectors with flexible dimensions"
1130+
self.__check_interop()
1131+
with self.assertRaisesFullCode("DPY-2065"):
1132+
self.conn.fetch_df_all(
1133+
"""
1134+
SELECT TO_VECTOR(
1135+
TO_VECTOR('[34.6, 0, 0, 0, 0, 0, 77.8]', 7, FLOAT64),
1136+
7,
1137+
FLOAT64,
1138+
SPARSE
1139+
)
1140+
union all
1141+
SELECT TO_VECTOR(
1142+
TO_VECTOR('[34.6, 0, 0, 0, 0, 0, 0, 9.1]', 8, FLOAT64),
1143+
8,
1144+
FLOAT64,
1145+
SPARSE
1146+
)
1147+
"""
1148+
)
1149+
11221150

11231151
if __name__ == "__main__":
11241152
test_env.run_test_cases()

0 commit comments

Comments
 (0)