//-----------------------------------------------------------------------------
// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// cxoSodaCollection.c
// Defines the routines for handling the SODA collection.
//-----------------------------------------------------------------------------
#include "cxoModule.h"
//-----------------------------------------------------------------------------
// declaration of functions
//-----------------------------------------------------------------------------
static void cxoSodaCollection_free(cxoSodaCollection*);
static PyObject *cxoSodaCollection_repr(cxoSodaCollection*);
static PyObject *cxoSodaCollection_createIndex(cxoSodaCollection*, PyObject*);
static PyObject *cxoSodaCollection_drop(cxoSodaCollection*, PyObject*);
static PyObject *cxoSodaCollection_dropIndex(cxoSodaCollection*, PyObject*,
PyObject*);
static PyObject *cxoSodaCollection_find(cxoSodaCollection*, PyObject*);
static PyObject *cxoSodaCollection_getDataGuide(cxoSodaCollection*, PyObject*);
static PyObject *cxoSodaCollection_insertOne(cxoSodaCollection*, PyObject*);
static PyObject *cxoSodaCollection_insertOneAndGet(cxoSodaCollection*,
PyObject*);
static PyObject *cxoSodaCollection_getMetadata(cxoSodaCollection*, PyObject*);
//-----------------------------------------------------------------------------
// declaration of methods
//-----------------------------------------------------------------------------
static PyMethodDef cxoMethods[] = {
{ "createIndex", (PyCFunction) cxoSodaCollection_createIndex, METH_O },
{ "drop", (PyCFunction) cxoSodaCollection_drop, METH_NOARGS },
{ "dropIndex", (PyCFunction) cxoSodaCollection_dropIndex,
METH_VARARGS | METH_KEYWORDS },
{ "find", (PyCFunction) cxoSodaCollection_find, METH_NOARGS },
{ "getDataGuide", (PyCFunction) cxoSodaCollection_getDataGuide,
METH_NOARGS },
{ "insertOne", (PyCFunction) cxoSodaCollection_insertOne, METH_O },
{ "insertOneAndGet", (PyCFunction) cxoSodaCollection_insertOneAndGet,
METH_O },
{ NULL }
};
//-----------------------------------------------------------------------------
// declaration of members
//-----------------------------------------------------------------------------
static PyMemberDef cxoMembers[] = {
{ "name", T_OBJECT, offsetof(cxoSodaCollection, name), READONLY },
{ NULL }
};
//-----------------------------------------------------------------------------
// declaration of calculated members
//-----------------------------------------------------------------------------
static PyGetSetDef cxoCalcMembers[] = {
{ "metadata", (getter) cxoSodaCollection_getMetadata, 0, 0, 0 },
{ NULL }
};
//-----------------------------------------------------------------------------
// Python type declarations
//-----------------------------------------------------------------------------
PyTypeObject cxoPyTypeSodaCollection = {
PyVarObject_HEAD_INIT(NULL, 0)
"cx_Oracle.SodaCollection", // tp_name
sizeof(cxoSodaCollection), // tp_basicsize
0, // tp_itemsize
(destructor) cxoSodaCollection_free,// tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
(reprfunc) cxoSodaCollection_repr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
0, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0, // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
0, // tp_weaklistoffset
0, // tp_iter
0, // tp_iternext
cxoMethods, // tp_methods
cxoMembers, // tp_members
cxoCalcMembers, // tp_getset
0, // tp_base
0, // tp_dict
0, // tp_descr_get
0, // tp_descr_set
0, // tp_dictoffset
0, // tp_init
0, // tp_alloc
0, // tp_new
0, // tp_free
0, // tp_is_gc
0 // tp_bases
};
//-----------------------------------------------------------------------------
// cxoSodaCollection_initialize()
// Initialize a new collection with its attributes.
//-----------------------------------------------------------------------------
static int cxoSodaCollection_initialize(cxoSodaCollection *coll,
cxoSodaDatabase *db, const char *encoding, dpiSodaColl *handle)
{
uint32_t nameLength;
const char *name;
// get name from ODPI-C
if (dpiSodaColl_getName(handle, &name, &nameLength) < 0)
return cxoError_raiseAndReturnInt();
coll->name = cxoPyString_fromEncodedString(name, nameLength, encoding,
NULL);
if (!coll->name)
return -1;
// set base attributes (handle should not be added until there is no
// possibility of further failure)
coll->handle = handle;
Py_INCREF(db);
coll->db = db;
return 0;
}
//-----------------------------------------------------------------------------
// cxoSodaCollection_new()
// Create a new SODA collection object.
//-----------------------------------------------------------------------------
cxoSodaCollection *cxoSodaCollection_new(cxoSodaDatabase *db,
dpiSodaColl *handle)
{
cxoSodaCollection *coll;
coll = (cxoSodaCollection*)
cxoPyTypeSodaCollection.tp_alloc(&cxoPyTypeSodaCollection, 0);
if (!coll)
return NULL;
if (cxoSodaCollection_initialize(coll, db,
db->connection->encodingInfo.encoding, handle) < 0) {
Py_DECREF(coll);
return NULL;
}
return coll;
}
//-----------------------------------------------------------------------------
// cxoSodaCollection_free()
// Free the memory associated with a SODA collection.
//-----------------------------------------------------------------------------
static void cxoSodaCollection_free(cxoSodaCollection *coll)
{
if (coll->handle) {
dpiSodaColl_release(coll->handle);
coll->handle = NULL;
}
Py_CLEAR(coll->db);
Py_CLEAR(coll->name);
Py_TYPE(coll)->tp_free((PyObject*) coll);
}
//-----------------------------------------------------------------------------
// cxoSodaCollection_repr()
// Return a string representation of a SODA collection.
//-----------------------------------------------------------------------------
static PyObject *cxoSodaCollection_repr(cxoSodaCollection *coll)
{
PyObject *module, *name, *result;
if (cxoUtils_getModuleAndName(Py_TYPE(coll), &module, &name) < 0)
return NULL;
result = cxoUtils_formatString("<%s.%s %s>",
PyTuple_Pack(3, module, name, coll->name));
Py_DECREF(module);
Py_DECREF(name);
return result;
}
//-----------------------------------------------------------------------------
// cxoSodaCollection_createIndex()
// Create an index on a SODA collection.
//-----------------------------------------------------------------------------
static PyObject *cxoSodaCollection_createIndex(cxoSodaCollection *coll,
PyObject *specObj)
{
cxoBuffer specBuffer;
uint32_t flags;
int status;
if (cxoUtils_processJsonArg(specObj, &specBuffer) < 0)
return NULL;
if (cxoConnection_getSodaFlags(coll->db->connection, &flags) < 0)
return NULL;
Py_BEGIN_ALLOW_THREADS
status = dpiSodaColl_createIndex(coll->handle, specBuffer.ptr,
specBuffer.size, flags);
Py_END_ALLOW_THREADS
cxoBuffer_clear(&specBuffer);
if (status < 0)
return cxoError_raiseAndReturnNull();
Py_RETURN_NONE;
}
//-----------------------------------------------------------------------------
// cxoSodaCollection_drop()
// Create a SODA collection and return it.
//-----------------------------------------------------------------------------
static PyObject *cxoSodaCollection_drop(cxoSodaCollection *coll,
PyObject *args)
{
uint32_t flags;
int isDropped;
if (cxoConnection_getSodaFlags(coll->db->connection, &flags) < 0)
return NULL;
if (dpiSodaColl_drop(coll->handle, flags, &isDropped) < 0)
return cxoError_raiseAndReturnNull();
if (isDropped)
Py_RETURN_TRUE;
Py_RETURN_FALSE;
}
//-----------------------------------------------------------------------------
// cxoSodaCollection_dropIndex()
// Drop an index on a SODA collection.
//-----------------------------------------------------------------------------
static PyObject *cxoSodaCollection_dropIndex(cxoSodaCollection *coll,
PyObject *args, PyObject *keywordArgs)
{
static char *keywordList[] = { "name", "force", NULL };
int status, isDropped, force;
PyObject *nameObj, *forceObj;
cxoBuffer nameBuffer;
uint32_t flags;
// parse arguments
forceObj = NULL;
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "O|O", keywordList,
&nameObj, &forceObj))
return NULL;
if (cxoUtils_getBooleanValue(forceObj, 0, &force) < 0)
return NULL;
// drop index
if (cxoConnection_getSodaFlags(coll->db->connection, &flags) < 0)
return NULL;
if (force)
flags |= DPI_SODA_FLAGS_INDEX_DROP_FORCE;
if (cxoBuffer_fromObject(&nameBuffer, nameObj,
coll->db->connection->encodingInfo.encoding) < 0)
return NULL;
Py_BEGIN_ALLOW_THREADS
status = dpiSodaColl_dropIndex(coll->handle, nameBuffer.ptr,
nameBuffer.size, flags, &isDropped);
Py_END_ALLOW_THREADS
cxoBuffer_clear(&nameBuffer);
if (status < 0)
return cxoError_raiseAndReturnNull();
if (isDropped)
Py_RETURN_TRUE;
Py_RETURN_FALSE;
}
//-----------------------------------------------------------------------------
// cxoSodaCollection_find()
// Creates an operation options object which can be used to perform a number
// of operations on the collection using the criteria set on the object.
//-----------------------------------------------------------------------------
static PyObject *cxoSodaCollection_find(cxoSodaCollection *coll,
PyObject *args)
{
return (PyObject*) cxoSodaOperation_new(coll);
}
//-----------------------------------------------------------------------------
// cxoSodaCollection_getDataGuide()
// Return the data guide associated with the collection.
//-----------------------------------------------------------------------------
static PyObject *cxoSodaCollection_getDataGuide(cxoSodaCollection *coll,
PyObject *args)
{
dpiSodaDoc *handle;
cxoSodaDoc *doc;
uint32_t flags;
int status;
if (cxoConnection_getSodaFlags(coll->db->connection, &flags) < 0)
return NULL;
Py_BEGIN_ALLOW_THREADS
status = dpiSodaColl_getDataGuide(coll->handle, flags, &handle);
Py_END_ALLOW_THREADS
if (status < 0)
return cxoError_raiseAndReturnNull();
if (handle) {
doc = cxoSodaDoc_new(coll->db, handle);
if (!doc)
return NULL;
return (PyObject*) doc;
}
Py_RETURN_NONE;
}
//-----------------------------------------------------------------------------
// cxoSodaCollection_insertOne()
// Insert a single document into the collection.
//-----------------------------------------------------------------------------
static PyObject *cxoSodaCollection_insertOne(cxoSodaCollection *coll,
PyObject *arg)
{
cxoSodaDoc *doc;
uint32_t flags;
int status;
if (cxoUtils_processSodaDocArg(coll->db, arg, &doc) < 0)
return NULL;
if (cxoConnection_getSodaFlags(coll->db->connection, &flags) < 0)
return NULL;
Py_BEGIN_ALLOW_THREADS
status = dpiSodaColl_insertOne(coll->handle, doc->handle, flags, NULL);
Py_END_ALLOW_THREADS
if (status < 0) {
cxoError_raiseAndReturnNull();
Py_DECREF(doc);
return NULL;
}
Py_DECREF(doc);
Py_RETURN_NONE;
}
//-----------------------------------------------------------------------------
// cxoSodaCollection_insertOneAndGet()
// Insert a single document into the collection and return a document
// containing all but the content itself.
//-----------------------------------------------------------------------------
static PyObject *cxoSodaCollection_insertOneAndGet(cxoSodaCollection *coll,
PyObject *arg)
{
dpiSodaDoc *returnedDoc;
cxoSodaDoc *doc;
uint32_t flags;
int status;
if (cxoUtils_processSodaDocArg(coll->db, arg, &doc) < 0)
return NULL;
if (cxoConnection_getSodaFlags(coll->db->connection, &flags) < 0)
return NULL;
Py_BEGIN_ALLOW_THREADS
status = dpiSodaColl_insertOne(coll->handle, doc->handle, flags,
&returnedDoc);
Py_END_ALLOW_THREADS
if (status < 0) {
cxoError_raiseAndReturnNull();
Py_DECREF(doc);
return NULL;
}
Py_DECREF(doc);
return (PyObject*) cxoSodaDoc_new(coll->db, returnedDoc);
}
//-----------------------------------------------------------------------------
// cxoSodaCollection_getMetadata()
// Retrieve the metadata for the collection.
//-----------------------------------------------------------------------------
static PyObject *cxoSodaCollection_getMetadata(cxoSodaCollection *coll,
PyObject *unused)
{
PyObject *str, *result;
uint32_t valueLength;
const char *value;
if (dpiSodaColl_getMetadata(coll->handle, &value, &valueLength) < 0)
return cxoError_raiseAndReturnNull();
str = PyUnicode_Decode(value, valueLength,
coll->db->connection->encodingInfo.encoding, NULL);
if (!str)
return NULL;
result = PyObject_CallFunctionObjArgs(cxoJsonLoadFunction, str, NULL);
Py_DECREF(str);
return result;
}