Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 19699a9

Browse files
committed
Adds support for DB.pget and DBCursor.pget methods.
Based on a patch supplied by Ian Ward <[email protected]> on the pybsddb mailing list 2004-03-26.
1 parent 31c5065 commit 19699a9

3 files changed

Lines changed: 225 additions & 3 deletions

File tree

Lib/bsddb/dbobj.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ def fd(self, *args, **kwargs):
134134
return apply(self._cobj.fd, args, kwargs)
135135
def get(self, *args, **kwargs):
136136
return apply(self._cobj.get, args, kwargs)
137+
def pget(self, *args, **kwargs):
138+
return apply(self._cobj.pget, args, kwargs)
137139
def get_both(self, *args, **kwargs):
138140
return apply(self._cobj.get_both, args, kwargs)
139141
def get_byteswapped(self, *args, **kwargs):

Lib/bsddb/test/test_associate.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
52: ("David Lanz", "Cristofori's Dream", "New Age"),
8484
53: ("David Lanz", "Heartsounds", "New Age"),
8585
54: ("David Lanz", "Leaves on the Seine", "New Age"),
86+
99: ("unknown artist", "Unnamed song", "Unknown"),
8687
}
8788

8889
#----------------------------------------------------------------------
@@ -117,6 +118,7 @@ def addDataToDB(self, d):
117118

118119
def createDB(self):
119120
self.primary = db.DB(self.env)
121+
self.primary.set_get_returns_none(2)
120122
self.primary.open(self.filename, "primary", self.dbtype,
121123
db.DB_CREATE | db.DB_THREAD)
122124

@@ -136,6 +138,7 @@ def test01_associateWithDB(self):
136138

137139
secDB = db.DB(self.env)
138140
secDB.set_flags(db.DB_DUP)
141+
secDB.set_get_returns_none(2)
139142
secDB.open(self.filename, "secondary", db.DB_BTREE,
140143
db.DB_CREATE | db.DB_THREAD)
141144
self.getDB().associate(secDB, self.getGenre)
@@ -166,6 +169,16 @@ def test02_associateAfterDB(self):
166169

167170

168171
def finish_test(self, secDB):
172+
# 'Blues' should not be in the secondary database
173+
vals = secDB.pget('Blues')
174+
assert vals == None, vals
175+
176+
vals = secDB.pget('Unknown')
177+
assert vals[0] == 99 or vals[0] == '99', vals
178+
vals[1].index('Unknown')
179+
vals[1].index('Unnamed')
180+
vals[1].index('unknown')
181+
169182
if verbose:
170183
print "Primary key traversal:"
171184
c = self.getDB().cursor()
@@ -187,6 +200,18 @@ def finish_test(self, secDB):
187200
print "Secondary key traversal:"
188201
c = secDB.cursor()
189202
count = 0
203+
204+
# test cursor pget
205+
vals = c.pget('Unknown', flags=db.DB_LAST)
206+
assert vals[1] == 99 or vals[1] == '99', vals
207+
assert vals[0] == 'Unknown'
208+
vals[2].index('Unknown')
209+
vals[2].index('Unnamed')
210+
vals[2].index('unknown')
211+
212+
vals = c.pget('Unknown', data='wrong value', flags=db.DB_GET_BOTH)
213+
assert vals == None, vals
214+
190215
rec = c.first()
191216
assert rec[0] == "Jazz"
192217
while rec is not None:

Modules/_bsddb.c

Lines changed: 198 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@
9797
#error "eek! DBVER can't handle minor versions > 9"
9898
#endif
9999

100-
#define PY_BSDDB_VERSION "4.2.7"
100+
#define PY_BSDDB_VERSION "4.2.8"
101101
static char *rcs_id = "$Id$";
102102

103103

@@ -1463,6 +1463,94 @@ DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
14631463
return retval;
14641464
}
14651465

1466+
static PyObject*
1467+
DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1468+
{
1469+
int err, flags=0;
1470+
PyObject* txnobj = NULL;
1471+
PyObject* keyobj;
1472+
PyObject* dfltobj = NULL;
1473+
PyObject* retval = NULL;
1474+
int dlen = -1;
1475+
int doff = -1;
1476+
DBT key, pkey, data;
1477+
DB_TXN *txn = NULL;
1478+
char* kwnames[] = {"key", "default", "txn", "flags", "dlen", "doff", NULL};
1479+
1480+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1481+
&keyobj, &dfltobj, &txnobj, &flags, &dlen,
1482+
&doff))
1483+
return NULL;
1484+
1485+
CHECK_DB_NOT_CLOSED(self);
1486+
if (!make_key_dbt(self, keyobj, &key, &flags))
1487+
return NULL;
1488+
if (!checkTxnObj(txnobj, &txn)) {
1489+
FREE_DBT(key);
1490+
return NULL;
1491+
}
1492+
1493+
CLEAR_DBT(data);
1494+
if (CHECK_DBFLAG(self, DB_THREAD)) {
1495+
/* Tell BerkeleyDB to malloc the return value (thread safe) */
1496+
data.flags = DB_DBT_MALLOC;
1497+
}
1498+
if (!add_partial_dbt(&data, dlen, doff)) {
1499+
FREE_DBT(key);
1500+
return NULL;
1501+
}
1502+
1503+
CLEAR_DBT(pkey);
1504+
pkey.flags = DB_DBT_MALLOC;
1505+
1506+
MYDB_BEGIN_ALLOW_THREADS;
1507+
err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1508+
MYDB_END_ALLOW_THREADS;
1509+
1510+
if ((err == DB_NOTFOUND) && (dfltobj != NULL)) {
1511+
err = 0;
1512+
Py_INCREF(dfltobj);
1513+
retval = dfltobj;
1514+
}
1515+
else if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
1516+
err = 0;
1517+
Py_INCREF(Py_None);
1518+
retval = Py_None;
1519+
}
1520+
else if (!err) {
1521+
PyObject *pkeyObj;
1522+
PyObject *dataObj;
1523+
dataObj = PyString_FromStringAndSize(data.data, data.size);
1524+
1525+
if (self->primaryDBType == DB_RECNO ||
1526+
self->primaryDBType == DB_QUEUE)
1527+
pkeyObj = PyInt_FromLong(*(long *)pkey.data);
1528+
else
1529+
pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1530+
1531+
if (flags & DB_SET_RECNO) /* return key , pkey and data */
1532+
{
1533+
PyObject *keyObj;
1534+
int type = _DB_get_type(self);
1535+
if (type == DB_RECNO || type == DB_QUEUE)
1536+
keyObj = PyInt_FromLong(*(long *)key.data);
1537+
else
1538+
keyObj = PyString_FromStringAndSize(key.data, key.size);
1539+
retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1540+
}
1541+
else /* return just the pkey and data */
1542+
{
1543+
retval = Py_BuildValue("OO", pkeyObj, dataObj);
1544+
}
1545+
FREE_DBT(pkey);
1546+
FREE_DBT(data);
1547+
}
1548+
FREE_DBT(key);
1549+
1550+
RETURN_IF_ERR();
1551+
return retval;
1552+
}
1553+
14661554

14671555
/* Return size of entry */
14681556
static PyObject*
@@ -2827,6 +2915,106 @@ DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
28272915
return retval;
28282916
}
28292917

2918+
static PyObject*
2919+
DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2920+
{
2921+
int err, flags=0;
2922+
PyObject* keyobj = NULL;
2923+
PyObject* dataobj = NULL;
2924+
PyObject* retval = NULL;
2925+
int dlen = -1;
2926+
int doff = -1;
2927+
DBT key, pkey, data;
2928+
char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
2929+
2930+
CLEAR_DBT(key);
2931+
CLEAR_DBT(data);
2932+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
2933+
&flags, &dlen, &doff))
2934+
{
2935+
PyErr_Clear();
2936+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
2937+
&kwnames[1],
2938+
&keyobj, &flags, &dlen, &doff))
2939+
{
2940+
PyErr_Clear();
2941+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
2942+
kwnames, &keyobj, &dataobj,
2943+
&flags, &dlen, &doff))
2944+
{
2945+
return NULL;
2946+
}
2947+
}
2948+
}
2949+
2950+
CHECK_CURSOR_NOT_CLOSED(self);
2951+
2952+
if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
2953+
return NULL;
2954+
if ( (dataobj && !make_dbt(dataobj, &data)) ||
2955+
(!add_partial_dbt(&data, dlen, doff)) ) {
2956+
FREE_DBT(key);
2957+
return NULL;
2958+
}
2959+
2960+
if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2961+
data.flags = DB_DBT_MALLOC;
2962+
if (!(key.flags & DB_DBT_REALLOC)) {
2963+
key.flags |= DB_DBT_MALLOC;
2964+
}
2965+
}
2966+
2967+
CLEAR_DBT(pkey);
2968+
pkey.flags = DB_DBT_MALLOC;
2969+
2970+
MYDB_BEGIN_ALLOW_THREADS;
2971+
err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
2972+
MYDB_END_ALLOW_THREADS;
2973+
2974+
if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
2975+
Py_INCREF(Py_None);
2976+
retval = Py_None;
2977+
}
2978+
else if (makeDBError(err)) {
2979+
retval = NULL;
2980+
}
2981+
else {
2982+
PyObject *pkeyObj;
2983+
PyObject *dataObj;
2984+
dataObj = PyString_FromStringAndSize(data.data, data.size);
2985+
2986+
if (self->mydb->primaryDBType == DB_RECNO ||
2987+
self->mydb->primaryDBType == DB_QUEUE)
2988+
pkeyObj = PyInt_FromLong(*(long *)pkey.data);
2989+
else
2990+
pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
2991+
2992+
if (flags & DB_SET_RECNO) /* return key, pkey and data */
2993+
{
2994+
PyObject *keyObj;
2995+
int type = _DB_get_type(self->mydb);
2996+
if (type == DB_RECNO || type == DB_QUEUE)
2997+
keyObj = PyInt_FromLong(*(long *)key.data);
2998+
else
2999+
keyObj = PyString_FromStringAndSize(key.data, key.size);
3000+
retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3001+
FREE_DBT(key);
3002+
}
3003+
else /* return just the pkey and data */
3004+
{
3005+
retval = Py_BuildValue("OO", pkeyObj, dataObj);
3006+
}
3007+
FREE_DBT(pkey);
3008+
FREE_DBT(data);
3009+
}
3010+
/* the only time REALLOC should be set is if we used an integer
3011+
* key that make_key_dbt malloc'd for us. always free these. */
3012+
if (key.flags & DB_DBT_REALLOC) {
3013+
FREE_DBT(key);
3014+
}
3015+
return retval;
3016+
}
3017+
28303018

28313019
static PyObject*
28323020
DBC_get_recno(DBCursorObject* self, PyObject* args)
@@ -2974,8 +3162,13 @@ DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
29743162
break;
29753163
}
29763164
FREE_DBT(data);
3165+
FREE_DBT(key);
3166+
}
3167+
/* the only time REALLOC should be set is if we used an integer
3168+
* key that make_key_dbt malloc'd for us. always free these. */
3169+
if (key.flags & DB_DBT_REALLOC) {
3170+
FREE_DBT(key);
29773171
}
2978-
FREE_DBT(key);
29793172

29803173
return retval;
29813174
}
@@ -3044,7 +3237,7 @@ DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
30443237
FREE_DBT(data);
30453238
}
30463239
/* the only time REALLOC should be set is if we used an integer
3047-
* key that make_dbt_key malloc'd for us. always free these. */
3240+
* key that make_key_dbt malloc'd for us. always free these. */
30483241
if (key.flags & DB_DBT_REALLOC) {
30493242
FREE_DBT(key);
30503243
}
@@ -4183,6 +4376,7 @@ static PyMethodDef DB_methods[] = {
41834376
{"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
41844377
{"fd", (PyCFunction)DB_fd, METH_VARARGS},
41854378
{"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
4379+
{"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
41864380
{"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
41874381
{"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
41884382
{"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
@@ -4242,6 +4436,7 @@ static PyMethodDef DBCursor_methods[] = {
42424436
{"dup", (PyCFunction)DBC_dup, METH_VARARGS},
42434437
{"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
42444438
{"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
4439+
{"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
42454440
{"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
42464441
{"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
42474442
{"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},

0 commit comments

Comments
 (0)