Added support for getting the indexes on a SODA collection.

This commit is contained in:
Anthony Tuininga 2023-08-07 13:35:33 -06:00
parent adc5143ea4
commit b1adaf91d8
7 changed files with 97 additions and 25 deletions

View File

@ -218,6 +218,13 @@ SodaCollection Methods
no documents in the collection, None is returned.
.. method:: SodaCollection.getIndexes()
Returns a list of specifications for the indexes found on the collection.
.. versionadded:: 1.4.0
.. method:: SodaCollection.insertMany(docs)
Inserts a list of documents into the collection at one time. Each of the

View File

@ -53,6 +53,8 @@ Thin Mode Changes
Thick Mode Changes
++++++++++++++++++
#) Added function :meth:`SodaCollection.getIndexes()` for geting the indexes
on a SODA collection.
#) Fixed bug when using external authentication with an Easy Connect
connection string.
#) Relaxed restriction for end-to-end string connection attributes. These

View File

@ -430,11 +430,6 @@ cdef extern from "impl/thick/odpi/embed/dpi.c":
uint32_t nativeTypeNum
dpiDataBuffer value
ctypedef struct dpiSodaCollNames:
uint32_t numNames
const char **names
uint32_t *nameLengths
ctypedef struct dpiSodaOperOptions:
uint32_t numKeys
const char **keys
@ -459,6 +454,11 @@ cdef extern from "impl/thick/odpi/embed/dpi.c":
uint16_t statementType
bint isReturning
ctypedef struct dpiStringList:
uint32_t numStrings
const char **strings
uint32_t *stringLengths
ctypedef struct dpiSubscrCreateParams:
uint32_t subscrNamespace
uint32_t protocol
@ -684,6 +684,9 @@ cdef extern from "impl/thick/odpi/embed/dpi.c":
unsigned int minorVersion, dpiContextCreateParams *params,
dpiContext **context, dpiErrorInfo *errorInfo) nogil
int dpiContext_freeStringList(dpiContext *context,
dpiStringList *stringList) nogil
int dpiContext_getClientVersion(const dpiContext *context,
dpiVersionInfo *versionInfo) nogil
@ -1037,6 +1040,9 @@ cdef extern from "impl/thick/odpi/embed/dpi.c":
const dpiSodaOperOptions *options, uint32_t flags,
uint64_t *count) nogil
int dpiSodaColl_getIndexes(dpiSodaColl *coll, uint32_t flags,
dpiStringList *lst) nogil
int dpiSodaColl_getMetadata(dpiSodaColl *coll, const char **value,
uint32_t *valueLength) nogil
@ -1076,12 +1082,9 @@ cdef extern from "impl/thick/odpi/embed/dpi.c":
const char *mediaType, uint32_t mediaTypeLength, uint32_t flags,
dpiSodaDoc **doc) nogil
int dpiSodaDb_freeCollectionNames(dpiSodaDb *db,
dpiSodaCollNames *names) nogil
int dpiSodaDb_getCollectionNames(dpiSodaDb *db,
const char *startName, uint32_t startNameLength, uint32_t limit,
uint32_t flags, dpiSodaCollNames *names) nogil
uint32_t flags, dpiStringList *names) nogil
int dpiSodaDb_openCollection(dpiSodaDb *db, const char *name,
uint32_t nameLength, uint32_t flags, dpiSodaColl **coll) nogil

View File

@ -1,5 +1,5 @@
#------------------------------------------------------------------------------
# Copyright (c) 2020, 2022, Oracle and/or its affiliates.
# Copyright (c) 2020, 2023, 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
@ -99,30 +99,19 @@ cdef class ThickSodaDbImpl(BaseSodaDbImpl):
"""
cdef:
StringBuffer start_name_buf = StringBuffer()
dpiSodaCollNames coll_names
uint32_t flags, i
list result
dpiStringList names
uint32_t flags
int status
str temp
start_name_buf.set_value(start_name)
self._get_flags(&flags)
with nogil:
status = dpiSodaDb_getCollectionNames(self._handle,
start_name_buf.ptr,
start_name_buf.length,
limit, flags, &coll_names)
limit, flags, &names)
if status < 0:
_raise_from_odpi()
try:
result = cpython.PyList_New(coll_names.numNames)
for i in range(coll_names.numNames):
temp = coll_names.names[i][:coll_names.nameLengths[i]].decode()
cpython.Py_INCREF(temp)
cpython.PyList_SET_ITEM(result, i, temp)
return result
finally:
if dpiSodaDb_freeCollectionNames(self._handle, &coll_names) < 0:
_raise_from_odpi()
return _string_list_to_python(&names)
def open_collection(self, str name):
"""
@ -283,6 +272,21 @@ cdef class ThickSodaCollImpl(BaseSodaCollImpl):
if doc_impl._handle != NULL:
return doc_impl
def get_indexes(self):
"""
Internal method for getting the list of indexes on a collection.
"""
cdef:
dpiStringList indexes
uint32_t flags
int status
self._db_impl._get_flags(&flags)
with nogil:
status = dpiSodaColl_getIndexes(self._handle, flags, &indexes)
if status < 0:
_raise_from_odpi()
return _string_list_to_python(&indexes)
def get_metadata(self):
"""
Internal method for getting the metadata for a collection.

View File

@ -374,6 +374,24 @@ cdef uint32_t _get_native_type_num(DbType dbtype):
return DPI_NATIVE_TYPE_JSON
return DPI_NATIVE_TYPE_BYTES
cdef list _string_list_to_python(dpiStringList *str_list):
"""
Converts the contents of dpiStringList to a Python list of strings.
"""
cdef:
list result
uint32_t i
str temp
try:
result = cpython.PyList_New(str_list.numStrings)
for i in range(str_list.numStrings):
temp = str_list.strings[i][:str_list.stringLengths[i]].decode()
cpython.Py_INCREF(temp)
cpython.PyList_SET_ITEM(result, i, temp)
return result
finally:
if dpiContext_freeStringList(driver_context, str_list) < 0:
_raise_from_odpi()
cdef object _create_new_from_info(dpiErrorInfo *error_info):
"""

View File

@ -214,6 +214,12 @@ class SodaCollection:
if doc_impl is not None:
return SodaDocument._from_impl(doc_impl)
def getIndexes(self) -> list:
"""
Return a list of indexes associated with the collection.
"""
return [json.loads(s) for s in self._impl.get_indexes()]
def insertMany(self, docs: list) -> None:
"""
Inserts a list of documents into the collection at one time. Each of

View File

@ -611,5 +611,37 @@ class TestCase(test_env.BaseTestCase):
self.assertRaises(TypeError, coll.find().fetchArraySize, -1)
coll.drop()
def test_3429_getting_indexes(self):
"3429 - test getting indexes on a collection"
soda_db = self.get_soda_database()
coll = soda_db.createCollection("TestSodaGetIndexes")
index_1 = {
'name': 'ix_3428-1',
'fields': [
{
'path': 'address.city',
'datatype': 'string',
'order': 'asc'
}
]
}
index_2 = {
'name': 'ix_3428-2',
'fields': [
{
'path': 'address.postal_code',
'datatype': 'string',
'order': 'asc'
}
]
}
self.assertEqual(coll.getIndexes(), [])
coll.createIndex(index_1)
coll.createIndex(index_2)
indexes = coll.getIndexes()
indexes.sort(key=lambda x: x["name"])
self.assertEqual(indexes[0]["fields"][0]["path"], "address.city")
self.assertEqual(indexes[1]["fields"][0]["path"], "address.postal_code")
if __name__ == "__main__":
test_env.run_test_cases()