summaryrefslogtreecommitdiffstats
path: root/Modules/_bsddb.c
diff options
context:
space:
mode:
authorGregory P. Smith <greg@mad-scientist.com>2004-06-28 04:06:49 (GMT)
committerGregory P. Smith <greg@mad-scientist.com>2004-06-28 04:06:49 (GMT)
commit19699a93513e5b011170123b0740bd9b7d714a53 (patch)
tree5df1f7df1da32893c0a7f2e2d3bc49c5bf39779e /Modules/_bsddb.c
parent31c50659eaf189e2498558895272053b2f66a25e (diff)
downloadcpython-19699a93513e5b011170123b0740bd9b7d714a53.zip
cpython-19699a93513e5b011170123b0740bd9b7d714a53.tar.gz
cpython-19699a93513e5b011170123b0740bd9b7d714a53.tar.bz2
Adds support for DB.pget and DBCursor.pget methods.
Based on a patch supplied by Ian Ward <ian@arevco.ca> on the pybsddb mailing list 2004-03-26.
Diffstat (limited to 'Modules/_bsddb.c')
-rw-r--r--Modules/_bsddb.c201
1 files changed, 198 insertions, 3 deletions
diff --git a/Modules/_bsddb.c b/Modules/_bsddb.c
index e00a64c..b7f6518 100644
--- a/Modules/_bsddb.c
+++ b/Modules/_bsddb.c
@@ -97,7 +97,7 @@
#error "eek! DBVER can't handle minor versions > 9"
#endif
-#define PY_BSDDB_VERSION "4.2.7"
+#define PY_BSDDB_VERSION "4.2.8"
static char *rcs_id = "$Id$";
@@ -1463,6 +1463,94 @@ DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
return retval;
}
+static PyObject*
+DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
+{
+ int err, flags=0;
+ PyObject* txnobj = NULL;
+ PyObject* keyobj;
+ PyObject* dfltobj = NULL;
+ PyObject* retval = NULL;
+ int dlen = -1;
+ int doff = -1;
+ DBT key, pkey, data;
+ DB_TXN *txn = NULL;
+ char* kwnames[] = {"key", "default", "txn", "flags", "dlen", "doff", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
+ &keyobj, &dfltobj, &txnobj, &flags, &dlen,
+ &doff))
+ return NULL;
+
+ CHECK_DB_NOT_CLOSED(self);
+ if (!make_key_dbt(self, keyobj, &key, &flags))
+ return NULL;
+ if (!checkTxnObj(txnobj, &txn)) {
+ FREE_DBT(key);
+ return NULL;
+ }
+
+ CLEAR_DBT(data);
+ if (CHECK_DBFLAG(self, DB_THREAD)) {
+ /* Tell BerkeleyDB to malloc the return value (thread safe) */
+ data.flags = DB_DBT_MALLOC;
+ }
+ if (!add_partial_dbt(&data, dlen, doff)) {
+ FREE_DBT(key);
+ return NULL;
+ }
+
+ CLEAR_DBT(pkey);
+ pkey.flags = DB_DBT_MALLOC;
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
+ MYDB_END_ALLOW_THREADS;
+
+ if ((err == DB_NOTFOUND) && (dfltobj != NULL)) {
+ err = 0;
+ Py_INCREF(dfltobj);
+ retval = dfltobj;
+ }
+ else if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
+ err = 0;
+ Py_INCREF(Py_None);
+ retval = Py_None;
+ }
+ else if (!err) {
+ PyObject *pkeyObj;
+ PyObject *dataObj;
+ dataObj = PyString_FromStringAndSize(data.data, data.size);
+
+ if (self->primaryDBType == DB_RECNO ||
+ self->primaryDBType == DB_QUEUE)
+ pkeyObj = PyInt_FromLong(*(long *)pkey.data);
+ else
+ pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
+
+ if (flags & DB_SET_RECNO) /* return key , pkey and data */
+ {
+ PyObject *keyObj;
+ int type = _DB_get_type(self);
+ if (type == DB_RECNO || type == DB_QUEUE)
+ keyObj = PyInt_FromLong(*(long *)key.data);
+ else
+ keyObj = PyString_FromStringAndSize(key.data, key.size);
+ retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
+ }
+ else /* return just the pkey and data */
+ {
+ retval = Py_BuildValue("OO", pkeyObj, dataObj);
+ }
+ FREE_DBT(pkey);
+ FREE_DBT(data);
+ }
+ FREE_DBT(key);
+
+ RETURN_IF_ERR();
+ return retval;
+}
+
/* Return size of entry */
static PyObject*
@@ -2827,6 +2915,106 @@ DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
return retval;
}
+static PyObject*
+DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
+{
+ int err, flags=0;
+ PyObject* keyobj = NULL;
+ PyObject* dataobj = NULL;
+ PyObject* retval = NULL;
+ int dlen = -1;
+ int doff = -1;
+ DBT key, pkey, data;
+ char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
+
+ CLEAR_DBT(key);
+ CLEAR_DBT(data);
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
+ &flags, &dlen, &doff))
+ {
+ PyErr_Clear();
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
+ &kwnames[1],
+ &keyobj, &flags, &dlen, &doff))
+ {
+ PyErr_Clear();
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
+ kwnames, &keyobj, &dataobj,
+ &flags, &dlen, &doff))
+ {
+ return NULL;
+ }
+ }
+ }
+
+ CHECK_CURSOR_NOT_CLOSED(self);
+
+ if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
+ return NULL;
+ if ( (dataobj && !make_dbt(dataobj, &data)) ||
+ (!add_partial_dbt(&data, dlen, doff)) ) {
+ FREE_DBT(key);
+ return NULL;
+ }
+
+ if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
+ data.flags = DB_DBT_MALLOC;
+ if (!(key.flags & DB_DBT_REALLOC)) {
+ key.flags |= DB_DBT_MALLOC;
+ }
+ }
+
+ CLEAR_DBT(pkey);
+ pkey.flags = DB_DBT_MALLOC;
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
+ MYDB_END_ALLOW_THREADS;
+
+ if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
+ Py_INCREF(Py_None);
+ retval = Py_None;
+ }
+ else if (makeDBError(err)) {
+ retval = NULL;
+ }
+ else {
+ PyObject *pkeyObj;
+ PyObject *dataObj;
+ dataObj = PyString_FromStringAndSize(data.data, data.size);
+
+ if (self->mydb->primaryDBType == DB_RECNO ||
+ self->mydb->primaryDBType == DB_QUEUE)
+ pkeyObj = PyInt_FromLong(*(long *)pkey.data);
+ else
+ pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
+
+ if (flags & DB_SET_RECNO) /* return key, pkey and data */
+ {
+ PyObject *keyObj;
+ int type = _DB_get_type(self->mydb);
+ if (type == DB_RECNO || type == DB_QUEUE)
+ keyObj = PyInt_FromLong(*(long *)key.data);
+ else
+ keyObj = PyString_FromStringAndSize(key.data, key.size);
+ retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
+ FREE_DBT(key);
+ }
+ else /* return just the pkey and data */
+ {
+ retval = Py_BuildValue("OO", pkeyObj, dataObj);
+ }
+ FREE_DBT(pkey);
+ FREE_DBT(data);
+ }
+ /* the only time REALLOC should be set is if we used an integer
+ * key that make_key_dbt malloc'd for us. always free these. */
+ if (key.flags & DB_DBT_REALLOC) {
+ FREE_DBT(key);
+ }
+ return retval;
+}
+
static PyObject*
DBC_get_recno(DBCursorObject* self, PyObject* args)
@@ -2974,8 +3162,13 @@ DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
break;
}
FREE_DBT(data);
+ FREE_DBT(key);
+ }
+ /* the only time REALLOC should be set is if we used an integer
+ * key that make_key_dbt malloc'd for us. always free these. */
+ if (key.flags & DB_DBT_REALLOC) {
+ FREE_DBT(key);
}
- FREE_DBT(key);
return retval;
}
@@ -3044,7 +3237,7 @@ DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
FREE_DBT(data);
}
/* the only time REALLOC should be set is if we used an integer
- * key that make_dbt_key malloc'd for us. always free these. */
+ * key that make_key_dbt malloc'd for us. always free these. */
if (key.flags & DB_DBT_REALLOC) {
FREE_DBT(key);
}
@@ -4183,6 +4376,7 @@ static PyMethodDef DB_methods[] = {
{"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
{"fd", (PyCFunction)DB_fd, METH_VARARGS},
{"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
+ {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
{"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
{"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
{"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
@@ -4242,6 +4436,7 @@ static PyMethodDef DBCursor_methods[] = {
{"dup", (PyCFunction)DBC_dup, METH_VARARGS},
{"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
{"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
+ {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
{"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
{"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
{"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},