diff options
author | Gregory P. Smith <greg@mad-scientist.com> | 2004-06-28 04:06:49 (GMT) |
---|---|---|
committer | Gregory P. Smith <greg@mad-scientist.com> | 2004-06-28 04:06:49 (GMT) |
commit | 19699a93513e5b011170123b0740bd9b7d714a53 (patch) | |
tree | 5df1f7df1da32893c0a7f2e2d3bc49c5bf39779e /Modules | |
parent | 31c50659eaf189e2498558895272053b2f66a25e (diff) | |
download | cpython-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')
-rw-r--r-- | Modules/_bsddb.c | 201 |
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}, |