blob: 874b7f7e7ba253c27a57d1e10b88588ad3b09c1c [file] [log] [blame]
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001/*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
11
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 o Neither the name of Digital Creations nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33------------------------------------------------------------------------*/
34
35
36/*
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
Barry Warsaw9a0d7792002-12-30 20:53:52 +000038 * written to replace a SWIG-generated file. It has since been updated
Gregory P. Smith41631e82003-09-21 00:08:14 +000039 * to compile with BerkeleyDB versions 3.2 through 4.2.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000040 *
41 * This module was started by Andrew Kuchling to remove the dependency
Gregory P. Smithc4119182007-09-09 20:17:22 +000042 * on SWIG in a package by Gregory P. Smith who based his work on a
43 * similar package by Robin Dunn <robin@alldunn.com> which wrapped
44 * Berkeley DB 2.7.x.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000045 *
Barry Warsaw9a0d7792002-12-30 20:53:52 +000046 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
50 *
Gregory P. Smithc4119182007-09-09 20:17:22 +000051 * Gregory P. Smith <greg@krypto.org> is once again the maintainer.
Barry Warsaw9a0d7792002-12-30 20:53:52 +000052 *
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000054 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
56 *
57 * http://pybsddb.sf.net
58 *
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
61 *
62 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000063 *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000064 * This module contains 6 types:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000065 *
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000071 * DBSequence (Sequence)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000072 *
73 */
74
75/* --------------------------------------------------------------------- */
76
77/*
78 * Portions of this module, associated unit tests and build scripts are the
79 * result of a contract with The Written Word (http://thewrittenword.com/)
80 * Many thanks go out to them for causing me to raise the bar on quality and
81 * functionality, resulting in a better bsddb3 package for all of us to use.
82 *
83 * --Robin
84 */
85
86/* --------------------------------------------------------------------- */
87
Gregory P. Smitha703a212003-11-03 01:04:41 +000088#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000089#include <Python.h>
Guido van Rossum8ce8a782007-11-01 19:42:39 +000090
91#define COMPILING_BSDDB_C
92#include "bsddb.h"
93#undef COMPILING_BSDDB_C
94
95static char *svn_id = "$Id$";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000096
97/* --------------------------------------------------------------------- */
98/* Various macro definitions */
99
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000100#if (PY_VERSION_HEX < 0x02050000)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000101typedef int Py_ssize_t;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000102#endif
103
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000104#ifdef WITH_THREAD
105
106/* These are for when calling Python --> C */
107#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
108#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
109
Mark Hammonda69d4092003-04-22 23:13:27 +0000110/* For 2.3, use the PyGILState_ calls */
111#if (PY_VERSION_HEX >= 0x02030000)
112#define MYDB_USE_GILSTATE
113#endif
114
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000115/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000116#if defined(MYDB_USE_GILSTATE)
117#define MYDB_BEGIN_BLOCK_THREADS \
118 PyGILState_STATE __savestate = PyGILState_Ensure();
119#define MYDB_END_BLOCK_THREADS \
120 PyGILState_Release(__savestate);
121#else /* MYDB_USE_GILSTATE */
122/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000123static PyInterpreterState* _db_interpreterState = NULL;
124#define MYDB_BEGIN_BLOCK_THREADS { \
125 PyThreadState* prevState; \
126 PyThreadState* newState; \
127 PyEval_AcquireLock(); \
128 newState = PyThreadState_New(_db_interpreterState); \
129 prevState = PyThreadState_Swap(newState);
130
131#define MYDB_END_BLOCK_THREADS \
132 newState = PyThreadState_Swap(prevState); \
133 PyThreadState_Clear(newState); \
134 PyEval_ReleaseLock(); \
135 PyThreadState_Delete(newState); \
136 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000137#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000138
139#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000140/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000141#define MYDB_BEGIN_ALLOW_THREADS
142#define MYDB_END_ALLOW_THREADS
143#define MYDB_BEGIN_BLOCK_THREADS
144#define MYDB_END_BLOCK_THREADS
145
146#endif
147
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000148/* Should DB_INCOMPLETE be turned into a warning or an exception? */
149#define INCOMPLETE_IS_WARNING 1
150
151/* --------------------------------------------------------------------- */
152/* Exceptions */
153
154static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000155static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000156static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000157static PyObject* DBKeyExistError; /* DB_KEYEXIST */
158static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
159static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
160static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
161static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
162static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
163static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
164static PyObject* DBNoServerError; /* DB_NOSERVER */
165static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
166static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
167#if (DBVER >= 33)
168static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
169static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
170#endif
171
172#if !INCOMPLETE_IS_WARNING
173static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
174#endif
175
176static PyObject* DBInvalidArgError; /* EINVAL */
177static PyObject* DBAccessError; /* EACCES */
178static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000179static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000180static PyObject* DBAgainError; /* EAGAIN */
181static PyObject* DBBusyError; /* EBUSY */
182static PyObject* DBFileExistsError; /* EEXIST */
183static PyObject* DBNoSuchFileError; /* ENOENT */
184static PyObject* DBPermissionsError; /* EPERM */
185
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000186#if (DBVER < 43)
187#define DB_BUFFER_SMALL ENOMEM
188#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000189
190
191/* --------------------------------------------------------------------- */
192/* Structure definitions */
193
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000194#if PYTHON_API_VERSION < 1010
195#error "Python 2.1 or later required"
Gregory P. Smitha703a212003-11-03 01:04:41 +0000196#endif
197
Gregory P. Smith31c50652004-06-28 01:20:40 +0000198
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000199/* Defaults for moduleFlags in DBEnvObject and DBObject. */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000200#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000201#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000202
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000203
Neal Norwitz227b5332006-03-22 09:28:35 +0000204static PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000205
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000206#define DBObject_Check(v) (Py_Type(v) == &DB_Type)
207#define DBCursorObject_Check(v) (Py_Type(v) == &DBCursor_Type)
208#define DBEnvObject_Check(v) (Py_Type(v) == &DBEnv_Type)
209#define DBTxnObject_Check(v) (Py_Type(v) == &DBTxn_Type)
210#define DBLockObject_Check(v) (Py_Type(v) == &DBLock_Type)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000211#if (DBVER >= 43)
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000212#define DBSequenceObject_Check(v) (Py_Type(v) == &DBSequence_Type)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000213#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000214
215
216/* --------------------------------------------------------------------- */
217/* Utility macros and functions */
218
219#define RETURN_IF_ERR() \
220 if (makeDBError(err)) { \
221 return NULL; \
222 }
223
224#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
225
Gregory P. Smithe2767172003-11-02 08:06:29 +0000226#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
227 if ((nonNull) == NULL) { \
228 PyObject *errTuple = NULL; \
229 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
230 PyErr_SetObject((pyErrObj), errTuple); \
231 Py_DECREF(errTuple); \
232 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000233 }
234
Gregory P. Smithe2767172003-11-02 08:06:29 +0000235#define CHECK_DB_NOT_CLOSED(dbobj) \
236 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
237
238#define CHECK_ENV_NOT_CLOSED(env) \
239 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000240
241#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000242 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000243
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000244#if (DBVER >= 43)
245#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
246 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
247#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000248
249#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
250 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
251
252#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
253
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000254
255static int makeDBError(int err);
256
257
258/* Return the access method type of the DBObject */
259static int _DB_get_type(DBObject* self)
260{
261#if (DBVER >= 33)
262 DBTYPE type;
263 int err;
264 err = self->db->get_type(self->db, &type);
265 if (makeDBError(err)) {
266 return -1;
267 }
268 return type;
269#else
270 return self->db->get_type(self->db);
271#endif
272}
273
274
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000275/* Handy function to free a DBT and any self-allocated data within.
276 To be used on self created DBTs. The make_dbt and make_key_dbt
277 functions have their own free routines that do more that this. */
278static void free_dbt(DBT *dbt)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000279{
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000280 if ((dbt->flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && dbt->data != NULL) {
281 free(dbt->data);
282 dbt->data = NULL;
283 }
284}
285
286
287/* Cleanup a Python buffer API view created by make_dbt() */
Thomas Heller39763a12007-09-24 14:43:56 +0000288static void free_buf_view(PyObject *obj, Py_buffer *view)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000289{
290 if (view) {
291 PyObject_ReleaseBuffer(obj, view);
292 PyMem_Free(view);
293 }
294}
295
296
297/* Cleanup a DBT and an associated Python buffer API view
298 created by make_key_dbt() */
299#define FREE_DBT_VIEW(dbt, obj, view) \
300 do { \
301 free_dbt(&(dbt)); \
302 free_buf_view((obj), (view)); \
303 } while(0);
304
305
Thomas Heller39763a12007-09-24 14:43:56 +0000306static Py_buffer * _malloc_view(PyObject *obj)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000307{
Thomas Heller39763a12007-09-24 14:43:56 +0000308 Py_buffer *view;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000309
Thomas Heller39763a12007-09-24 14:43:56 +0000310 if (!(view = PyMem_Malloc(sizeof(Py_buffer)))) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000311 PyErr_SetString(PyExc_MemoryError,
Thomas Heller39763a12007-09-24 14:43:56 +0000312 "Py_buffer malloc failed");
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000313 return NULL;
314 }
315 /* XXX(gps): PyBUF_LOCKDATA is desired to prevent other theads from
316 trashing the data buffer while we release the GIL during the db
317 operation. see http://bugs.python.org/issue1035 */
318 if (PyObject_GetBuffer(obj, view, PyBUF_SIMPLE) == -1) {
319 PyMem_Free(view);
320 return NULL;
321 }
322 if (view->ndim > 1) {
323 PyErr_SetString(PyExc_BufferError,
324 "buffers must be single dimension");
325 PyObject_ReleaseBuffer(obj, view);
326 PyMem_Free(view);
327 return NULL;
328 }
329 return view;
330}
331
332
333/* Create a DBT structure (containing key and data values) from Python
334 strings. Returns >= 1 on success, 0 on an error. The returned_view_p
Thomas Heller39763a12007-09-24 14:43:56 +0000335 may be filled with a newly allocated Py_buffer view on success.
336 The caller MUST call free_buf_view() on any returned Py_buffer. */
337static int make_dbt(PyObject* obj, DBT* dbt, Py_buffer** returned_view_p)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000338{
Thomas Heller39763a12007-09-24 14:43:56 +0000339 Py_buffer *view;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000340
341 /* simple way to ensure the caller can detect if we've returned a
342 new buffer view or not: require their pointer to start out NULL. */
343 assert(*returned_view_p == NULL);
344
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000345 CLEAR_DBT(*dbt);
346 if (obj == Py_None) {
347 /* no need to do anything, the structure has already been zeroed */
Guido van Rossumfc5fafc2007-08-24 05:08:58 +0000348 return 1;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000349 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000350 if (!PyObject_CheckBuffer(obj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000351 PyErr_SetString(PyExc_TypeError,
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000352 "Data values must support the buffer API or be None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000353 return 0;
354 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000355
356 if ( !(view = _malloc_view(obj)) )
357 return 0;
358
359 dbt->data = view->buf;
360 dbt->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t);
361 *returned_view_p = view;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000362 return 1;
363}
364
365
366/* Recno and Queue DBs can have integer keys. This function figures out
367 what's been given, verifies that it's allowed, and then makes the DBT.
368
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000369 Caller MUST call FREE_DBT_VIEW(keydbt, keyobj, key_view) with all
Thomas Heller39763a12007-09-24 14:43:56 +0000370 returned DBT and Py_buffer values when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000371static int
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000372make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags,
Thomas Heller39763a12007-09-24 14:43:56 +0000373 Py_buffer** returned_view_p)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000374{
375 db_recno_t recno;
376 int type;
Thomas Heller39763a12007-09-24 14:43:56 +0000377 Py_buffer *view;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000378
379 /* simple way to ensure the caller can detect if we've returned a
380 new buffer view or not: require their pointer to start out NULL. */
381 assert(*returned_view_p == NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000382
383 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000384 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000385 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000386 if (type == -1)
387 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000388 if (type == DB_RECNO || type == DB_QUEUE) {
389 PyErr_SetString(
390 PyExc_TypeError,
391 "None keys not allowed for Recno and Queue DB's");
392 return 0;
393 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000394 /* no need to do anything, the structure has already been zeroed */
395 }
396
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000397 else if (PyInt_Check(keyobj)) {
398 /* verify access method type */
399 type = _DB_get_type(self);
400 if (type == -1)
401 return 0;
402 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000403 /* if BTREE then an Integer key is allowed with the
404 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000405 *pflags |= DB_SET_RECNO;
406 }
407 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000408 PyErr_SetString(
409 PyExc_TypeError,
410 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000411 return 0;
412 }
413
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000414 /* Make a key out of the requested recno, use allocated space so DB
415 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000416 recno = PyInt_AS_LONG(keyobj);
417 key->data = malloc(sizeof(db_recno_t));
418 if (key->data == NULL) {
419 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
420 return 0;
421 }
422 key->ulen = key->size = sizeof(db_recno_t);
423 memcpy(key->data, &recno, sizeof(db_recno_t));
424 key->flags = DB_DBT_REALLOC;
425 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000426
427 else if (PyObject_CheckBuffer(keyobj)) {
428 /* verify access method type */
429 type = _DB_get_type(self);
430 if (type == -1)
431 return 0;
432 if (type == DB_RECNO || type == DB_QUEUE) {
433 PyErr_SetString(
434 PyExc_TypeError,
435 "Non-integer keys not allowed for Recno and Queue DB's");
436 return 0;
437 }
438
439 if ( !(view = _malloc_view(keyobj)) )
440 return 0;
441
Gregory P. Smith568065e2007-11-01 21:55:08 +0000442 /*
443 * NOTE(gps): I don't like doing a data copy here, it seems
444 * wasteful. But without a clean way to tell FREE_DBT if it
445 * should free key->data or not we have to. Other places in
446 * the code check for DB_THREAD and forceably set DBT_MALLOC
447 * when we otherwise would leave flags 0 to indicate that.
448 */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000449 key->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t);
Gregory P. Smith568065e2007-11-01 21:55:08 +0000450 key->data = malloc(key->size);
451 if (key->data == NULL) {
452 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
453 key->size = 0;
454 return 0;
455 }
456 memcpy(key->data, view->buf, key->size);
457 key->flags = DB_DBT_REALLOC;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000458 *returned_view_p = view;
459 }
460
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000461 else {
462 PyErr_Format(PyExc_TypeError,
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000463 "buffer or int object expected for key, %s found",
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000464 Py_Type(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000465 return 0;
466 }
467
468 return 1;
469}
470
471
472/* Add partial record access to an existing DBT data struct.
473 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
474 and the data storage/retrieval will be done using dlen and doff. */
475static int add_partial_dbt(DBT* d, int dlen, int doff) {
476 /* if neither were set we do nothing (-1 is the default value) */
477 if ((dlen == -1) && (doff == -1)) {
478 return 1;
479 }
480
481 if ((dlen < 0) || (doff < 0)) {
482 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
483 return 0;
484 }
485
486 d->flags = d->flags | DB_DBT_PARTIAL;
487 d->dlen = (unsigned int) dlen;
488 d->doff = (unsigned int) doff;
489 return 1;
490}
491
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000492/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
493/* TODO: make this use the native libc strlcpy() when available (BSD) */
494unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
495{
496 unsigned int srclen, copylen;
497
498 srclen = strlen(src);
499 if (n <= 0)
500 return srclen;
501 copylen = (srclen > n-1) ? n-1 : srclen;
502 /* populate dest[0] thru dest[copylen-1] */
503 memcpy(dest, src, copylen);
504 /* guarantee null termination */
505 dest[copylen] = 0;
506
507 return srclen;
508}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000509
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000510/* Callback used to save away more information about errors from the DB
511 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000512static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000513#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000514static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000515#else
516static void _db_errorCallback(const DB_ENV *db_env,
517 const char* prefix, const char* msg)
518#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000519{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000520 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000521}
522
523
524/* make a nice exception object to raise for errors. */
525static int makeDBError(int err)
526{
527 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000528 PyObject *errObj = NULL;
529 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000530 int exceptionRaised = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000531 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000532
533 switch (err) {
534 case 0: /* successful, no error */ break;
535
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000536#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000537 case DB_INCOMPLETE:
538#if INCOMPLETE_IS_WARNING
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000539 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
540 /* Ensure that bytes_left never goes negative */
541 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
542 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
543 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000544 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000545 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000546 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000547 _db_errmsg[0] = 0;
Skip Montanaro46fc3372007-08-12 11:44:53 +0000548 exceptionRaised = PyErr_WarnEx(PyExc_RuntimeWarning, errTxt, 1);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000549
550#else /* do an exception instead */
551 errObj = DBIncompleteError;
552#endif
553 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000554#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000555
556 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
557 case DB_KEYEXIST: errObj = DBKeyExistError; break;
558 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
559 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
560 case DB_NOTFOUND: errObj = DBNotFoundError; break;
561 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
562 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
563 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
564 case DB_NOSERVER: errObj = DBNoServerError; break;
565 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
566 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
567#if (DBVER >= 33)
568 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
569 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
570#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000571 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000572
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000573#if (DBVER >= 43)
574 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
575 case ENOMEM: errObj = PyExc_MemoryError; break;
576#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000577 case EINVAL: errObj = DBInvalidArgError; break;
578 case EACCES: errObj = DBAccessError; break;
579 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000580 case EAGAIN: errObj = DBAgainError; break;
581 case EBUSY : errObj = DBBusyError; break;
582 case EEXIST: errObj = DBFileExistsError; break;
583 case ENOENT: errObj = DBNoSuchFileError; break;
584 case EPERM : errObj = DBPermissionsError; break;
585
586 default: errObj = DBError; break;
587 }
588
589 if (errObj != NULL) {
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000590 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
591 /* Ensure that bytes_left never goes negative */
592 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
593 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
594 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000595 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000596 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000597 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000598 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000599
600 errTuple = Py_BuildValue("(is)", err, errTxt);
601 PyErr_SetObject(errObj, errTuple);
602 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000603 }
604
605 return ((errObj != NULL) || exceptionRaised);
606}
607
608
609
610/* set a type exception */
611static void makeTypeError(char* expected, PyObject* found)
612{
613 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000614 expected, Py_Type(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000615}
616
617
618/* verify that an obj is either None or a DBTxn, and set the txn pointer */
619static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
620{
621 if (txnobj == Py_None || txnobj == NULL) {
622 *txn = NULL;
623 return 1;
624 }
625 if (DBTxnObject_Check(txnobj)) {
626 *txn = ((DBTxnObject*)txnobj)->txn;
627 return 1;
628 }
629 else
630 makeTypeError("DBTxn", txnobj);
631 return 0;
632}
633
634
635/* Delete a key from a database
636 Returns 0 on success, -1 on an error. */
637static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
638{
639 int err;
640
641 MYDB_BEGIN_ALLOW_THREADS;
642 err = self->db->del(self->db, txn, key, 0);
643 MYDB_END_ALLOW_THREADS;
644 if (makeDBError(err)) {
645 return -1;
646 }
647 self->haveStat = 0;
648 return 0;
649}
650
651
652/* Store a key into a database
653 Returns 0 on success, -1 on an error. */
654static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
655{
656 int err;
657
658 MYDB_BEGIN_ALLOW_THREADS;
659 err = self->db->put(self->db, txn, key, data, flags);
660 MYDB_END_ALLOW_THREADS;
661 if (makeDBError(err)) {
662 return -1;
663 }
664 self->haveStat = 0;
665 return 0;
666}
667
668/* Get a key/data pair from a cursor */
669static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
670 PyObject *args, PyObject *kwargs, char *format)
671{
672 int err;
673 PyObject* retval = NULL;
674 DBT key, data;
675 int dlen = -1;
676 int doff = -1;
677 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000678 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000679
680 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
681 &flags, &dlen, &doff))
682 return NULL;
683
684 CHECK_CURSOR_NOT_CLOSED(self);
685
686 flags |= extra_flags;
687 CLEAR_DBT(key);
688 CLEAR_DBT(data);
689 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
690 /* Tell BerkeleyDB to malloc the return value (thread safe) */
691 data.flags = DB_DBT_MALLOC;
692 key.flags = DB_DBT_MALLOC;
693 }
694 if (!add_partial_dbt(&data, dlen, doff))
695 return NULL;
696
697 MYDB_BEGIN_ALLOW_THREADS;
698 err = self->dbc->c_get(self->dbc, &key, &data, flags);
699 MYDB_END_ALLOW_THREADS;
700
Gregory P. Smithe9477062005-06-04 06:46:59 +0000701 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
702 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000703 Py_INCREF(Py_None);
704 retval = Py_None;
705 }
706 else if (makeDBError(err)) {
707 retval = NULL;
708 }
709 else { /* otherwise, success! */
710
711 /* if Recno or Queue, return the key as an Int */
712 switch (_DB_get_type(self->mydb)) {
713 case -1:
714 retval = NULL;
715 break;
716
717 case DB_RECNO:
718 case DB_QUEUE:
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000719 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000720 data.data, data.size);
721 break;
722 case DB_HASH:
723 case DB_BTREE:
724 default:
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000725 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000726 data.data, data.size);
727 break;
728 }
729 }
730 if (!err) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000731 free_dbt(&key);
732 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000733 }
734 return retval;
735}
736
737
738/* add an integer to a dictionary using the given name as a key */
739static void _addIntToDict(PyObject* dict, char *name, int value)
740{
741 PyObject* v = PyInt_FromLong((long) value);
742 if (!v || PyDict_SetItemString(dict, name, v))
743 PyErr_Clear();
744
745 Py_XDECREF(v);
746}
Guido van Rossumd8faa362007-04-27 19:54:29 +0000747
748/* The same, when the value is a time_t */
749static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
750{
751 PyObject* v;
752 /* if the value fits in regular int, use that. */
753#ifdef HAVE_LONG_LONG
754 if (sizeof(time_t) > sizeof(long))
755 v = PyLong_FromLongLong((PY_LONG_LONG) value);
756 else
757#endif
758 v = PyInt_FromLong((long) value);
759 if (!v || PyDict_SetItemString(dict, name, v))
760 PyErr_Clear();
761
762 Py_XDECREF(v);
763}
764
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000765#if (DBVER >= 43)
766/* add an db_seq_t to a dictionary using the given name as a key */
767static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
768{
769 PyObject* v = PyLong_FromLongLong(value);
770 if (!v || PyDict_SetItemString(dict, name, v))
771 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000772
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000773 Py_XDECREF(v);
774}
775#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000776
777
778
779/* --------------------------------------------------------------------- */
780/* Allocators and deallocators */
781
782static DBObject*
783newDBObject(DBEnvObject* arg, int flags)
784{
785 DBObject* self;
786 DB_ENV* db_env = NULL;
787 int err;
788
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000789 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000790 if (self == NULL)
791 return NULL;
792
793 self->haveStat = 0;
794 self->flags = 0;
795 self->setflags = 0;
796 self->myenvobj = NULL;
797#if (DBVER >= 33)
798 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000799 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000800 self->primaryDBType = 0;
801#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000802 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000803
804 /* keep a reference to our python DBEnv object */
805 if (arg) {
806 Py_INCREF(arg);
807 self->myenvobj = arg;
808 db_env = arg->db_env;
809 }
810
811 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000812 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000813 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000814 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
815 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000816
817 MYDB_BEGIN_ALLOW_THREADS;
818 err = db_create(&self->db, db_env, flags);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000819 if (self->db != NULL) {
820 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000821#if (DBVER >= 33)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000822 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000823#endif
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000824 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000825 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000826 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
827 * list so that a DBEnv can refuse to close without aborting any open
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000828 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000829 if (makeDBError(err)) {
830 if (self->myenvobj) {
831 Py_DECREF(self->myenvobj);
832 self->myenvobj = NULL;
833 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000834 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000835 self = NULL;
836 }
837 return self;
838}
839
840
841static void
842DB_dealloc(DBObject* self)
843{
844 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000845 /* avoid closing a DB when its DBEnv has been closed out from under
846 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000847 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000848 (self->myenvobj && self->myenvobj->db_env))
849 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000850 MYDB_BEGIN_ALLOW_THREADS;
851 self->db->close(self->db, 0);
852 MYDB_END_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000853 } else {
Skip Montanaro46fc3372007-08-12 11:44:53 +0000854 PyErr_WarnEx(PyExc_RuntimeWarning,
855 "DB could not be closed in destructor:"
856 " DBEnv already closed",
857 1);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000858 }
859 self->db = NULL;
860 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000861 if (self->in_weakreflist != NULL) {
862 PyObject_ClearWeakRefs((PyObject *) self);
863 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000864 if (self->myenvobj) {
865 Py_DECREF(self->myenvobj);
866 self->myenvobj = NULL;
867 }
868#if (DBVER >= 33)
869 if (self->associateCallback != NULL) {
870 Py_DECREF(self->associateCallback);
871 self->associateCallback = NULL;
872 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000873 if (self->btCompareCallback != NULL) {
874 Py_DECREF(self->btCompareCallback);
875 self->btCompareCallback = NULL;
876 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000877#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000878 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000879}
880
881
882static DBCursorObject*
883newDBCursorObject(DBC* dbc, DBObject* db)
884{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000885 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000886 if (self == NULL)
887 return NULL;
888
889 self->dbc = dbc;
890 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000891 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000892 Py_INCREF(self->mydb);
893 return self;
894}
895
896
897static void
898DBCursor_dealloc(DBCursorObject* self)
899{
900 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000901
Gregory P. Smitha703a212003-11-03 01:04:41 +0000902 if (self->in_weakreflist != NULL) {
903 PyObject_ClearWeakRefs((PyObject *) self);
904 }
Gregory P. Smitha703a212003-11-03 01:04:41 +0000905
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000906 if (self->dbc != NULL) {
907 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000908 /* If the underlying database has been closed, we don't
909 need to do anything. If the environment has been closed
910 we need to leak, as BerkeleyDB will crash trying to access
911 the environment. There was an exception when the
912 user closed the environment even though there still was
913 a database open. */
914 if (self->mydb->db && self->mydb->myenvobj &&
915 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000916 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000917 self->dbc = NULL;
918 MYDB_END_ALLOW_THREADS;
919 }
920 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000921 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000922}
923
924
925static DBEnvObject*
926newDBEnvObject(int flags)
927{
928 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000929 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000930 if (self == NULL)
931 return NULL;
932
933 self->closed = 1;
934 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000935 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
936 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000937 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000938
939 MYDB_BEGIN_ALLOW_THREADS;
940 err = db_env_create(&self->db_env, flags);
941 MYDB_END_ALLOW_THREADS;
942 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000943 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000944 self = NULL;
945 }
946 else {
947 self->db_env->set_errcall(self->db_env, _db_errorCallback);
948 }
949 return self;
950}
951
952
953static void
954DBEnv_dealloc(DBEnvObject* self)
955{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000956 if (self->in_weakreflist != NULL) {
957 PyObject_ClearWeakRefs((PyObject *) self);
958 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000959
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000960 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000961 MYDB_BEGIN_ALLOW_THREADS;
962 self->db_env->close(self->db_env, 0);
963 MYDB_END_ALLOW_THREADS;
964 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000965 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000966}
967
968
969static DBTxnObject*
970newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
971{
972 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000973 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000974 if (self == NULL)
975 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000976 Py_INCREF(myenv);
977 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000978 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000979
980 MYDB_BEGIN_ALLOW_THREADS;
981#if (DBVER >= 40)
982 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
983#else
984 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
985#endif
986 MYDB_END_ALLOW_THREADS;
987 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +0000988 Py_DECREF(self->env);
989 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000990 self = NULL;
991 }
992 return self;
993}
994
995
996static void
997DBTxn_dealloc(DBTxnObject* self)
998{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000999 if (self->in_weakreflist != NULL) {
1000 PyObject_ClearWeakRefs((PyObject *) self);
1001 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001002
Gregory P. Smith31c50652004-06-28 01:20:40 +00001003 if (self->txn) {
1004 /* it hasn't been finalized, abort it! */
1005 MYDB_BEGIN_ALLOW_THREADS;
1006#if (DBVER >= 40)
1007 self->txn->abort(self->txn);
1008#else
1009 txn_abort(self->txn);
1010#endif
1011 MYDB_END_ALLOW_THREADS;
Skip Montanaro46fc3372007-08-12 11:44:53 +00001012 PyErr_WarnEx(PyExc_RuntimeWarning,
1013 "DBTxn aborted in destructor. "
1014 " No prior commit() or abort().",
1015 1);
Gregory P. Smith31c50652004-06-28 01:20:40 +00001016 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001017
Neal Norwitz62a21122006-01-25 05:21:55 +00001018 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001019 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001020}
1021
1022
1023static DBLockObject*
1024newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1025 db_lockmode_t lock_mode, int flags)
1026{
1027 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001028 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001029 if (self == NULL)
1030 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001031 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001032
1033 MYDB_BEGIN_ALLOW_THREADS;
1034#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001035 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1036 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001037#else
1038 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1039#endif
1040 MYDB_END_ALLOW_THREADS;
1041 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001042 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001043 self = NULL;
1044 }
1045
1046 return self;
1047}
1048
1049
1050static void
1051DBLock_dealloc(DBLockObject* self)
1052{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001053 if (self->in_weakreflist != NULL) {
1054 PyObject_ClearWeakRefs((PyObject *) self);
1055 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001056 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001057
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001058 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001059}
1060
1061
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001062#if (DBVER >= 43)
1063static DBSequenceObject*
1064newDBSequenceObject(DBObject* mydb, int flags)
1065{
1066 int err;
1067 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1068 if (self == NULL)
1069 return NULL;
1070 Py_INCREF(mydb);
1071 self->mydb = mydb;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001072 self->in_weakreflist = NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001073
1074
1075 MYDB_BEGIN_ALLOW_THREADS;
1076 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1077 MYDB_END_ALLOW_THREADS;
1078 if (makeDBError(err)) {
1079 Py_DECREF(self->mydb);
1080 PyObject_Del(self);
1081 self = NULL;
1082 }
1083
1084 return self;
1085}
1086
1087
1088static void
1089DBSequence_dealloc(DBSequenceObject* self)
1090{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001091 if (self->in_weakreflist != NULL) {
1092 PyObject_ClearWeakRefs((PyObject *) self);
1093 }
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001094
1095 Py_DECREF(self->mydb);
1096 PyObject_Del(self);
1097}
1098#endif
1099
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001100/* --------------------------------------------------------------------- */
1101/* DB methods */
1102
1103static PyObject*
1104DB_append(DBObject* self, PyObject* args)
1105{
1106 PyObject* txnobj = NULL;
1107 PyObject* dataobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001108 Py_buffer* data_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001109 db_recno_t recno;
1110 DBT key, data;
1111 DB_TXN *txn = NULL;
1112
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001113 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001114 return NULL;
1115
1116 CHECK_DB_NOT_CLOSED(self);
1117
1118 /* make a dummy key out of a recno */
1119 recno = 0;
1120 CLEAR_DBT(key);
1121 key.data = &recno;
1122 key.size = sizeof(recno);
1123 key.ulen = key.size;
1124 key.flags = DB_DBT_USERMEM;
1125
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001126 if (!checkTxnObj(txnobj, &txn)) return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001127 if (!make_dbt(dataobj, &data, &data_buf_view)) return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001128
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001129 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND)) {
1130 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001131 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001132 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001133
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001134 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001135 return PyInt_FromLong(recno);
1136}
1137
1138
1139#if (DBVER >= 33)
1140
1141static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001142_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1143 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001144{
1145 int retval = DB_DONOTINDEX;
1146 DBObject* secondaryDB = (DBObject*)db->app_private;
1147 PyObject* callback = secondaryDB->associateCallback;
1148 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001149 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001150 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001151
1152
1153 if (callback != NULL) {
1154 MYDB_BEGIN_BLOCK_THREADS;
1155
Thomas Woutersb3153832006-03-08 01:47:19 +00001156 if (type == DB_RECNO || type == DB_QUEUE)
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001157 args = Py_BuildValue("(ly#)", *((db_recno_t*)priKey->data),
Thomas Woutersb3153832006-03-08 01:47:19 +00001158 priData->data, priData->size);
1159 else
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001160 args = Py_BuildValue("(y#y#)", priKey->data, priKey->size,
Thomas Woutersb3153832006-03-08 01:47:19 +00001161 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001162 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001163 result = PyEval_CallObject(callback, args);
1164 }
1165 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001166 PyErr_Print();
1167 }
1168 else if (result == Py_None) {
1169 retval = DB_DONOTINDEX;
1170 }
1171 else if (PyInt_Check(result)) {
1172 retval = PyInt_AsLong(result);
1173 }
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001174 else if (PyBytes_Check(result)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001175 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001176 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001177
1178 CLEAR_DBT(*secKey);
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001179 size = PyBytes_Size(result);
1180 data = PyBytes_AsString(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001181 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1182 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001183 if (secKey->data) {
1184 memcpy(secKey->data, data, size);
1185 secKey->size = size;
1186 retval = 0;
1187 }
1188 else {
1189 PyErr_SetString(PyExc_MemoryError,
1190 "malloc failed in _db_associateCallback");
1191 PyErr_Print();
1192 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001193 }
1194 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001195 PyErr_SetString(
1196 PyExc_TypeError,
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001197 "DB associate callback should return DB_DONOTINDEX or bytes.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001198 PyErr_Print();
1199 }
1200
Thomas Woutersb3153832006-03-08 01:47:19 +00001201 Py_XDECREF(args);
1202 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001203
1204 MYDB_END_BLOCK_THREADS;
1205 }
1206 return retval;
1207}
1208
1209
1210static PyObject*
1211DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1212{
1213 int err, flags=0;
1214 DBObject* secondaryDB;
1215 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001216#if (DBVER >= 41)
1217 PyObject *txnobj = NULL;
1218 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001219 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001220 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001221#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001222 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001223#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001224
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001225#if (DBVER >= 41)
1226 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1227 &secondaryDB, &callback, &flags,
1228 &txnobj)) {
1229#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001230 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001231 &secondaryDB, &callback, &flags)) {
1232#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001233 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001234 }
1235
1236#if (DBVER >= 41)
1237 if (!checkTxnObj(txnobj, &txn)) return NULL;
1238#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001239
1240 CHECK_DB_NOT_CLOSED(self);
1241 if (!DBObject_Check(secondaryDB)) {
1242 makeTypeError("DB", (PyObject*)secondaryDB);
1243 return NULL;
1244 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001245 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001246 if (callback == Py_None) {
1247 callback = NULL;
1248 }
1249 else if (!PyCallable_Check(callback)) {
1250 makeTypeError("Callable", callback);
1251 return NULL;
1252 }
1253
1254 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001255 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001256 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001257 secondaryDB->associateCallback = callback;
1258 secondaryDB->primaryDBType = _DB_get_type(self);
1259
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001260 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1261 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1262 * The global interepreter lock is not initialized until the first
1263 * thread is created using thread.start_new_thread() or fork() is
1264 * called. that would cause the ALLOW_THREADS here to segfault due
1265 * to a null pointer reference if no threads or child processes
1266 * have been created. This works around that and is a no-op if
1267 * threads have already been initialized.
1268 * (see pybsddb-users mailing list post on 2002-08-07)
1269 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001270#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001271 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001272#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001273 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001274#if (DBVER >= 41)
1275 err = self->db->associate(self->db,
1276 txn,
1277 secondaryDB->db,
1278 _db_associateCallback,
1279 flags);
1280#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001281 err = self->db->associate(self->db,
1282 secondaryDB->db,
1283 _db_associateCallback,
1284 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001285#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001286 MYDB_END_ALLOW_THREADS;
1287
1288 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001289 Py_XDECREF(secondaryDB->associateCallback);
1290 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001291 secondaryDB->primaryDBType = 0;
1292 }
1293
1294 RETURN_IF_ERR();
1295 RETURN_NONE();
1296}
1297
1298
1299#endif
1300
1301
1302static PyObject*
1303DB_close(DBObject* self, PyObject* args)
1304{
1305 int err, flags=0;
1306 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1307 return NULL;
1308 if (self->db != NULL) {
1309 if (self->myenvobj)
1310 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001311 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001312 self->db = NULL;
1313 RETURN_IF_ERR();
1314 }
1315 RETURN_NONE();
1316}
1317
1318
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001319static PyObject*
1320_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1321{
1322 int err, flags=0, type;
1323 PyObject* txnobj = NULL;
1324 PyObject* retval = NULL;
1325 DBT key, data;
1326 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001327 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001328
1329 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1330 &txnobj, &flags))
1331 return NULL;
1332
1333 CHECK_DB_NOT_CLOSED(self);
1334 type = _DB_get_type(self);
1335 if (type == -1)
1336 return NULL;
1337 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001338 PyErr_SetString(PyExc_TypeError,
1339 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001340 return NULL;
1341 }
1342 if (!checkTxnObj(txnobj, &txn))
1343 return NULL;
1344
1345 CLEAR_DBT(key);
1346 CLEAR_DBT(data);
1347 if (CHECK_DBFLAG(self, DB_THREAD)) {
1348 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1349 data.flags = DB_DBT_MALLOC;
1350 key.flags = DB_DBT_MALLOC;
1351 }
1352
1353 MYDB_BEGIN_ALLOW_THREADS;
1354 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1355 MYDB_END_ALLOW_THREADS;
1356
Gregory P. Smithe9477062005-06-04 06:46:59 +00001357 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1358 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001359 err = 0;
1360 Py_INCREF(Py_None);
1361 retval = Py_None;
1362 }
1363 else if (!err) {
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001364 retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001365 data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001366 free_dbt(&key);
1367 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001368 }
1369
1370 RETURN_IF_ERR();
1371 return retval;
1372}
1373
1374static PyObject*
1375DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1376{
1377 return _DB_consume(self, args, kwargs, DB_CONSUME);
1378}
1379
1380static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001381DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1382 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001383{
1384 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1385}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001386
1387
1388static PyObject*
1389DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1390{
1391 int err, flags=0;
1392 DBC* dbc;
1393 PyObject* txnobj = NULL;
1394 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001395 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001396
1397 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1398 &txnobj, &flags))
1399 return NULL;
1400 CHECK_DB_NOT_CLOSED(self);
1401 if (!checkTxnObj(txnobj, &txn))
1402 return NULL;
1403
1404 MYDB_BEGIN_ALLOW_THREADS;
1405 err = self->db->cursor(self->db, txn, &dbc, flags);
1406 MYDB_END_ALLOW_THREADS;
1407 RETURN_IF_ERR();
1408 return (PyObject*) newDBCursorObject(dbc, self);
1409}
1410
1411
1412static PyObject*
1413DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1414{
1415 PyObject* txnobj = NULL;
1416 int flags = 0;
1417 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001418 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001419 DBT key;
1420 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001421 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001422
1423 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1424 &keyobj, &txnobj, &flags))
1425 return NULL;
1426 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001427 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001428 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001429 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001430 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001431 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001432 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001433
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001434 if (-1 == _DB_delete(self, txn, &key, 0)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001435 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001436 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001437 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001438
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001439 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001440 RETURN_NONE();
1441}
1442
1443
1444static PyObject*
1445DB_fd(DBObject* self, PyObject* args)
1446{
1447 int err, the_fd;
1448
1449 if (!PyArg_ParseTuple(args,":fd"))
1450 return NULL;
1451 CHECK_DB_NOT_CLOSED(self);
1452
1453 MYDB_BEGIN_ALLOW_THREADS;
1454 err = self->db->fd(self->db, &the_fd);
1455 MYDB_END_ALLOW_THREADS;
1456 RETURN_IF_ERR();
1457 return PyInt_FromLong(the_fd);
1458}
1459
1460
1461static PyObject*
1462DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1463{
1464 int err, flags=0;
1465 PyObject* txnobj = NULL;
1466 PyObject* keyobj;
1467 PyObject* dfltobj = NULL;
1468 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001469 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001470 int dlen = -1;
1471 int doff = -1;
1472 DBT key, data;
1473 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001474 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001475 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001476
1477 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001478 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1479 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001480 return NULL;
1481
1482 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001483 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001484 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001485 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001486 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001487 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001488 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001489
1490 CLEAR_DBT(data);
1491 if (CHECK_DBFLAG(self, DB_THREAD)) {
1492 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1493 data.flags = DB_DBT_MALLOC;
1494 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001495 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001496 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001497 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001498 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001499
1500 MYDB_BEGIN_ALLOW_THREADS;
1501 err = self->db->get(self->db, txn, &key, &data, flags);
1502 MYDB_END_ALLOW_THREADS;
1503
Gregory P. Smithe9477062005-06-04 06:46:59 +00001504 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001505 err = 0;
1506 Py_INCREF(dfltobj);
1507 retval = dfltobj;
1508 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001509 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1510 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001511 err = 0;
1512 Py_INCREF(Py_None);
1513 retval = Py_None;
1514 }
1515 else if (!err) {
1516 if (flags & DB_SET_RECNO) /* return both key and data */
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001517 retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001518 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001519 else /* return just the data */
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001520 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001521 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001522 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001523 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001524
1525 RETURN_IF_ERR();
1526 return retval;
1527}
1528
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001529#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001530static PyObject*
1531DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1532{
1533 int err, flags=0;
1534 PyObject* txnobj = NULL;
1535 PyObject* keyobj;
1536 PyObject* dfltobj = NULL;
1537 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001538 Py_buffer* key_buf_view = NULL;
Gregory P. Smith19699a92004-06-28 04:06:49 +00001539 int dlen = -1;
1540 int doff = -1;
1541 DBT key, pkey, data;
1542 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001543 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001544 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001545
1546 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1547 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1548 &doff))
1549 return NULL;
1550
1551 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001552 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Gregory P. Smith19699a92004-06-28 04:06:49 +00001553 return NULL;
1554 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001555 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001556 return NULL;
1557 }
1558
1559 CLEAR_DBT(data);
1560 if (CHECK_DBFLAG(self, DB_THREAD)) {
1561 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1562 data.flags = DB_DBT_MALLOC;
1563 }
1564 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001565 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001566 return NULL;
1567 }
1568
1569 CLEAR_DBT(pkey);
1570 pkey.flags = DB_DBT_MALLOC;
1571
1572 MYDB_BEGIN_ALLOW_THREADS;
1573 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1574 MYDB_END_ALLOW_THREADS;
1575
Gregory P. Smithe9477062005-06-04 06:46:59 +00001576 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001577 err = 0;
1578 Py_INCREF(dfltobj);
1579 retval = dfltobj;
1580 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001581 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1582 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001583 err = 0;
1584 Py_INCREF(Py_None);
1585 retval = Py_None;
1586 }
1587 else if (!err) {
1588 PyObject *pkeyObj;
1589 PyObject *dataObj;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001590 dataObj = PyBytes_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001591
1592 if (self->primaryDBType == DB_RECNO ||
1593 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001594 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001595 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001596 pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001597
1598 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1599 {
1600 PyObject *keyObj;
1601 int type = _DB_get_type(self);
1602 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001603 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001604 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001605 keyObj = PyBytes_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001606#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001607 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001608#else
1609 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1610#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001611 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001612 }
1613 else /* return just the pkey and data */
1614 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001615#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001616 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001617#else
1618 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1619#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001620 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001621 Py_DECREF(dataObj);
1622 Py_DECREF(pkeyObj);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001623 free_dbt(&pkey);
1624 free_dbt(&data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001625 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001626 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001627
1628 RETURN_IF_ERR();
1629 return retval;
1630}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001631#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001632
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001633
1634/* Return size of entry */
1635static PyObject*
1636DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1637{
1638 int err, flags=0;
1639 PyObject* txnobj = NULL;
1640 PyObject* keyobj;
1641 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001642 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001643 DBT key, data;
1644 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001645 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001646
1647 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1648 &keyobj, &txnobj))
1649 return NULL;
1650 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001651 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001652 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001653 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001654 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001655 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001656 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001657 CLEAR_DBT(data);
1658
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001659 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1660 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001661 data.flags = DB_DBT_USERMEM;
1662 data.ulen = 0;
1663 MYDB_BEGIN_ALLOW_THREADS;
1664 err = self->db->get(self->db, txn, &key, &data, flags);
1665 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001666 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001667 retval = PyInt_FromLong((long)data.size);
1668 err = 0;
1669 }
1670
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001671 FREE_DBT_VIEW(key, keyobj, key_buf_view);
1672 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001673 RETURN_IF_ERR();
1674 return retval;
1675}
1676
1677
1678static PyObject*
1679DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1680{
1681 int err, flags=0;
1682 PyObject* txnobj = NULL;
1683 PyObject* keyobj;
1684 PyObject* dataobj;
1685 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001686 Py_buffer* data_buf_view = NULL;
1687 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001688 DBT key, data;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001689 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001690 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001691 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001692
1693
1694 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1695 &keyobj, &dataobj, &txnobj, &flags))
1696 return NULL;
1697
1698 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001699 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001700 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001701 if ( !checkTxnObj(txnobj, &txn) ||
1702 !make_dbt(dataobj, &data, &data_buf_view) )
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001703 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001704 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001705 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001706 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001707
1708 flags |= DB_GET_BOTH;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001709 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001710
1711 if (CHECK_DBFLAG(self, DB_THREAD)) {
1712 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001713 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001714 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001715 }
1716
1717 MYDB_BEGIN_ALLOW_THREADS;
1718 err = self->db->get(self->db, txn, &key, &data, flags);
1719 MYDB_END_ALLOW_THREADS;
1720
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001721 free_buf_view(dataobj, data_buf_view);
1722
Gregory P. Smithe9477062005-06-04 06:46:59 +00001723 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1724 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001725 err = 0;
1726 Py_INCREF(Py_None);
1727 retval = Py_None;
1728 }
1729 else if (!err) {
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001730 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001731 /* XXX(gps) I think not: buffer API input vs. bytes object output. */
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001732 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001733
1734 /* Even though the flags require DB_DBT_MALLOC, data is not always
1735 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1736 if (data.data != orig_data)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001737 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001738 }
1739
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001740 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001741 RETURN_IF_ERR();
1742 return retval;
1743}
1744
1745
1746static PyObject*
1747DB_get_byteswapped(DBObject* self, PyObject* args)
1748{
1749#if (DBVER >= 33)
1750 int err = 0;
1751#endif
1752 int retval = -1;
1753
1754 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1755 return NULL;
1756 CHECK_DB_NOT_CLOSED(self);
1757
1758#if (DBVER >= 33)
1759 MYDB_BEGIN_ALLOW_THREADS;
1760 err = self->db->get_byteswapped(self->db, &retval);
1761 MYDB_END_ALLOW_THREADS;
1762 RETURN_IF_ERR();
1763#else
1764 MYDB_BEGIN_ALLOW_THREADS;
1765 retval = self->db->get_byteswapped(self->db);
1766 MYDB_END_ALLOW_THREADS;
1767#endif
1768 return PyInt_FromLong(retval);
1769}
1770
1771
1772static PyObject*
1773DB_get_type(DBObject* self, PyObject* args)
1774{
1775 int type;
1776
1777 if (!PyArg_ParseTuple(args,":get_type"))
1778 return NULL;
1779 CHECK_DB_NOT_CLOSED(self);
1780
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001781 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001782 if (type == -1)
1783 return NULL;
1784 return PyInt_FromLong(type);
1785}
1786
1787
1788static PyObject*
1789DB_join(DBObject* self, PyObject* args)
1790{
1791 int err, flags=0;
1792 int length, x;
1793 PyObject* cursorsObj;
1794 DBC** cursors;
1795 DBC* dbc;
1796
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001797 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1798 return NULL;
1799
1800 CHECK_DB_NOT_CLOSED(self);
1801
1802 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001803 PyErr_SetString(PyExc_TypeError,
1804 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001805 return NULL;
1806 }
1807
1808 length = PyObject_Length(cursorsObj);
1809 cursors = malloc((length+1) * sizeof(DBC*));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001810 if (!cursors) {
1811 PyErr_NoMemory();
1812 return NULL;
1813 }
1814
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001815 cursors[length] = NULL;
1816 for (x=0; x<length; x++) {
1817 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001818 if (item == NULL) {
1819 free(cursors);
1820 return NULL;
1821 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001822 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001823 PyErr_SetString(PyExc_TypeError,
1824 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001825 free(cursors);
1826 return NULL;
1827 }
1828 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001829 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001830 }
1831
1832 MYDB_BEGIN_ALLOW_THREADS;
1833 err = self->db->join(self->db, cursors, &dbc, flags);
1834 MYDB_END_ALLOW_THREADS;
1835 free(cursors);
1836 RETURN_IF_ERR();
1837
Gregory P. Smith7441e652003-11-03 21:35:31 +00001838 /* FIXME: this is a buggy interface. The returned cursor
1839 contains internal references to the passed in cursors
1840 but does not hold python references to them or prevent
1841 them from being closed prematurely. This can cause
1842 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001843 return (PyObject*) newDBCursorObject(dbc, self);
1844}
1845
1846
1847static PyObject*
1848DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1849{
1850 int err, flags=0;
1851 PyObject* txnobj = NULL;
1852 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001853 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001854 DBT key;
1855 DB_TXN *txn = NULL;
1856 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001857 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001858
1859 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1860 &keyobj, &txnobj, &flags))
1861 return NULL;
1862 CHECK_DB_NOT_CLOSED(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001863 if (!checkTxnObj(txnobj, &txn))
1864 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001865 if (!make_dbt(keyobj, &key, &key_buf_view))
1866 /* BTree only, don't need to allow for an int key */
1867 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001868
1869 MYDB_BEGIN_ALLOW_THREADS;
1870 err = self->db->key_range(self->db, txn, &key, &range, flags);
1871 MYDB_END_ALLOW_THREADS;
1872
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001873 free_buf_view(keyobj, key_buf_view);
1874
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001875 RETURN_IF_ERR();
1876 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1877}
1878
1879
1880static PyObject*
1881DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1882{
1883 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1884 char* filename = NULL;
1885 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001886#if (DBVER >= 41)
1887 PyObject *txnobj = NULL;
1888 DB_TXN *txn = NULL;
1889 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001890 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001891 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1892 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001893 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001894 "filename", "dbtype", "flags", "mode", "txn", NULL};
1895#else
1896 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001897 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001898 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1899 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001900 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001901 "filename", "dbtype", "flags", "mode", NULL};
1902#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001903
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001904#if (DBVER >= 41)
1905 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1906 &filename, &dbname, &type, &flags, &mode,
1907 &txnobj))
1908#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001909 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001910 &filename, &dbname, &type, &flags,
1911 &mode))
1912#endif
1913 {
1914 PyErr_Clear();
1915 type = DB_UNKNOWN; flags = 0; mode = 0660;
1916 filename = NULL; dbname = NULL;
1917#if (DBVER >= 41)
1918 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1919 kwnames_basic,
1920 &filename, &type, &flags, &mode,
1921 &txnobj))
1922 return NULL;
1923#else
1924 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1925 kwnames_basic,
1926 &filename, &type, &flags, &mode))
1927 return NULL;
1928#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001929 }
1930
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001931#if (DBVER >= 41)
1932 if (!checkTxnObj(txnobj, &txn)) return NULL;
1933#endif
1934
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001935 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001936 PyObject *t = Py_BuildValue("(is)", 0,
1937 "Cannot call open() twice for DB object");
1938 PyErr_SetObject(DBError, t);
1939 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001940 return NULL;
1941 }
1942
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001943#if 0 && (DBVER >= 41)
1944 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1945 && (self->myenvobj->flags & DB_INIT_TXN))
1946 {
1947 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1948 * explicitly passed) but we are in a transaction ready environment:
1949 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1950 * to work on BerkeleyDB 4.1 without needing to modify their
1951 * DBEnv or DB open calls.
1952 * TODO make this behaviour of the library configurable.
1953 */
1954 flags |= DB_AUTO_COMMIT;
1955 }
1956#endif
1957
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001958 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001959#if (DBVER >= 41)
1960 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1961#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001962 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001963#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001964 MYDB_END_ALLOW_THREADS;
1965 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001966 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001967 self->db = NULL;
1968 return NULL;
1969 }
1970
1971 self->flags = flags;
1972 RETURN_NONE();
1973}
1974
1975
1976static PyObject*
1977DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1978{
1979 int flags=0;
1980 PyObject* txnobj = NULL;
1981 int dlen = -1;
1982 int doff = -1;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001983 PyObject *keyobj, *dataobj, *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00001984 Py_buffer *data_buf_view = NULL;
1985 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001986 DBT key, data;
1987 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001988 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001989 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001990
1991 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1992 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1993 return NULL;
1994
1995 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001996 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001997 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001998 if ( !make_dbt(dataobj, &data, &data_buf_view) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001999 !add_partial_dbt(&data, dlen, doff) ||
2000 !checkTxnObj(txnobj, &txn) )
2001 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002002 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2003 free_buf_view(dataobj, data_buf_view);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002004 return NULL;
2005 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002006
2007 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002008 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2009 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002010 return NULL;
2011 }
2012
2013 if (flags & DB_APPEND)
2014 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2015 else {
2016 retval = Py_None;
2017 Py_INCREF(retval);
2018 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002019 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2020 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002021 return retval;
2022}
2023
2024
2025
2026static PyObject*
2027DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2028{
2029 char* filename;
2030 char* database = NULL;
2031 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002032 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002033
2034 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2035 &filename, &database, &flags))
2036 return NULL;
2037 CHECK_DB_NOT_CLOSED(self);
2038
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002039 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002040 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002041 RETURN_IF_ERR();
2042 RETURN_NONE();
2043}
2044
2045
2046
2047static PyObject*
2048DB_rename(DBObject* self, PyObject* args)
2049{
2050 char* filename;
2051 char* database;
2052 char* newname;
2053 int err, flags=0;
2054
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002055 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2056 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002057 return NULL;
2058 CHECK_DB_NOT_CLOSED(self);
2059
2060 MYDB_BEGIN_ALLOW_THREADS;
2061 err = self->db->rename(self->db, filename, database, newname, flags);
2062 MYDB_END_ALLOW_THREADS;
2063 RETURN_IF_ERR();
2064 RETURN_NONE();
2065}
2066
2067
2068static PyObject*
2069DB_set_bt_minkey(DBObject* self, PyObject* args)
2070{
2071 int err, minkey;
2072
2073 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2074 return NULL;
2075 CHECK_DB_NOT_CLOSED(self);
2076
2077 MYDB_BEGIN_ALLOW_THREADS;
2078 err = self->db->set_bt_minkey(self->db, minkey);
2079 MYDB_END_ALLOW_THREADS;
2080 RETURN_IF_ERR();
2081 RETURN_NONE();
2082}
2083
Neal Norwitz84562352005-10-20 04:30:15 +00002084#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002085static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002086_default_cmp(const DBT *leftKey,
2087 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002088{
2089 int res;
2090 int lsize = leftKey->size, rsize = rightKey->size;
2091
Georg Brandlef1701f2006-03-07 14:57:48 +00002092 res = memcmp(leftKey->data, rightKey->data,
2093 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002094
2095 if (res == 0) {
2096 if (lsize < rsize) {
2097 res = -1;
2098 }
2099 else if (lsize > rsize) {
2100 res = 1;
2101 }
2102 }
2103 return res;
2104}
2105
2106static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002107_db_compareCallback(DB* db,
2108 const DBT *leftKey,
2109 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002110{
2111 int res = 0;
2112 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002113 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002114 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002115
2116 if (self == NULL || self->btCompareCallback == NULL) {
2117 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002118 PyErr_SetString(PyExc_TypeError,
2119 (self == 0
2120 ? "DB_bt_compare db is NULL."
2121 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002122 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002123 PyErr_Print();
2124 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002125 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002126 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002127 MYDB_BEGIN_BLOCK_THREADS;
2128
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002129 args = Py_BuildValue("y#y#", leftKey->data, leftKey->size,
Thomas Woutersb3153832006-03-08 01:47:19 +00002130 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002131 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002132 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002133 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002134 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002135 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002136 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002137 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002138 PyErr_Print();
2139 res = _default_cmp(leftKey, rightKey);
2140 } else if (PyInt_Check(result)) {
2141 res = PyInt_AsLong(result);
2142 } else {
2143 PyErr_SetString(PyExc_TypeError,
2144 "DB_bt_compare callback MUST return an int.");
2145 /* we're in a callback within the DB code, we can't raise */
2146 PyErr_Print();
2147 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002148 }
2149
Thomas Woutersb3153832006-03-08 01:47:19 +00002150 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002151 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002152
2153 MYDB_END_BLOCK_THREADS;
2154 }
2155 return res;
2156}
2157
2158static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002159DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002160{
2161 int err;
2162 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002163 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002164
Georg Brandlef1701f2006-03-07 14:57:48 +00002165 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002166 return NULL;
2167
Georg Brandlef1701f2006-03-07 14:57:48 +00002168 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002169
Georg Brandlef1701f2006-03-07 14:57:48 +00002170 if (!PyCallable_Check(comparator)) {
2171 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002172 return NULL;
2173 }
2174
2175 /*
2176 * Perform a test call of the comparator function with two empty
2177 * string objects here. verify that it returns an int (0).
2178 * err if not.
2179 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002180 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002181 result = PyEval_CallObject(comparator, tuple);
2182 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002183 if (result == NULL)
2184 return NULL;
2185 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002186 PyErr_SetString(PyExc_TypeError,
2187 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002188 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002189 } else if (PyInt_AsLong(result) != 0) {
2190 PyErr_SetString(PyExc_TypeError,
2191 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002192 return NULL;
2193 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002194 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002195
2196 /* We don't accept multiple set_bt_compare operations, in order to
2197 * simplify the code. This would have no real use, as one cannot
2198 * change the function once the db is opened anyway */
2199 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002200 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002201 return NULL;
2202 }
2203
Georg Brandlef1701f2006-03-07 14:57:48 +00002204 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002205 self->btCompareCallback = comparator;
2206
2207 /* This is to workaround a problem with un-initialized threads (see
2208 comment in DB_associate) */
2209#ifdef WITH_THREAD
2210 PyEval_InitThreads();
2211#endif
2212
Thomas Woutersb3153832006-03-08 01:47:19 +00002213 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002214
2215 if (err) {
2216 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002217 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002218 self->btCompareCallback = NULL;
2219 }
2220
Georg Brandlef1701f2006-03-07 14:57:48 +00002221 RETURN_IF_ERR();
2222 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002223}
Neal Norwitz84562352005-10-20 04:30:15 +00002224#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002225
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002226
2227static PyObject*
2228DB_set_cachesize(DBObject* self, PyObject* args)
2229{
2230 int err;
2231 int gbytes = 0, bytes = 0, ncache = 0;
2232
2233 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2234 &gbytes,&bytes,&ncache))
2235 return NULL;
2236 CHECK_DB_NOT_CLOSED(self);
2237
2238 MYDB_BEGIN_ALLOW_THREADS;
2239 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2240 MYDB_END_ALLOW_THREADS;
2241 RETURN_IF_ERR();
2242 RETURN_NONE();
2243}
2244
2245
2246static PyObject*
2247DB_set_flags(DBObject* self, PyObject* args)
2248{
2249 int err, flags;
2250
2251 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2252 return NULL;
2253 CHECK_DB_NOT_CLOSED(self);
2254
2255 MYDB_BEGIN_ALLOW_THREADS;
2256 err = self->db->set_flags(self->db, flags);
2257 MYDB_END_ALLOW_THREADS;
2258 RETURN_IF_ERR();
2259
2260 self->setflags |= flags;
2261 RETURN_NONE();
2262}
2263
2264
2265static PyObject*
2266DB_set_h_ffactor(DBObject* self, PyObject* args)
2267{
2268 int err, ffactor;
2269
2270 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2271 return NULL;
2272 CHECK_DB_NOT_CLOSED(self);
2273
2274 MYDB_BEGIN_ALLOW_THREADS;
2275 err = self->db->set_h_ffactor(self->db, ffactor);
2276 MYDB_END_ALLOW_THREADS;
2277 RETURN_IF_ERR();
2278 RETURN_NONE();
2279}
2280
2281
2282static PyObject*
2283DB_set_h_nelem(DBObject* self, PyObject* args)
2284{
2285 int err, nelem;
2286
2287 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2288 return NULL;
2289 CHECK_DB_NOT_CLOSED(self);
2290
2291 MYDB_BEGIN_ALLOW_THREADS;
2292 err = self->db->set_h_nelem(self->db, nelem);
2293 MYDB_END_ALLOW_THREADS;
2294 RETURN_IF_ERR();
2295 RETURN_NONE();
2296}
2297
2298
2299static PyObject*
2300DB_set_lorder(DBObject* self, PyObject* args)
2301{
2302 int err, lorder;
2303
2304 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2305 return NULL;
2306 CHECK_DB_NOT_CLOSED(self);
2307
2308 MYDB_BEGIN_ALLOW_THREADS;
2309 err = self->db->set_lorder(self->db, lorder);
2310 MYDB_END_ALLOW_THREADS;
2311 RETURN_IF_ERR();
2312 RETURN_NONE();
2313}
2314
2315
2316static PyObject*
2317DB_set_pagesize(DBObject* self, PyObject* args)
2318{
2319 int err, pagesize;
2320
2321 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2322 return NULL;
2323 CHECK_DB_NOT_CLOSED(self);
2324
2325 MYDB_BEGIN_ALLOW_THREADS;
2326 err = self->db->set_pagesize(self->db, pagesize);
2327 MYDB_END_ALLOW_THREADS;
2328 RETURN_IF_ERR();
2329 RETURN_NONE();
2330}
2331
2332
2333static PyObject*
2334DB_set_re_delim(DBObject* self, PyObject* args)
2335{
2336 int err;
2337 char delim;
2338
2339 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2340 PyErr_Clear();
2341 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2342 return NULL;
2343 }
2344
2345 CHECK_DB_NOT_CLOSED(self);
2346
2347 MYDB_BEGIN_ALLOW_THREADS;
2348 err = self->db->set_re_delim(self->db, delim);
2349 MYDB_END_ALLOW_THREADS;
2350 RETURN_IF_ERR();
2351 RETURN_NONE();
2352}
2353
2354static PyObject*
2355DB_set_re_len(DBObject* self, PyObject* args)
2356{
2357 int err, len;
2358
2359 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2360 return NULL;
2361 CHECK_DB_NOT_CLOSED(self);
2362
2363 MYDB_BEGIN_ALLOW_THREADS;
2364 err = self->db->set_re_len(self->db, len);
2365 MYDB_END_ALLOW_THREADS;
2366 RETURN_IF_ERR();
2367 RETURN_NONE();
2368}
2369
2370
2371static PyObject*
2372DB_set_re_pad(DBObject* self, PyObject* args)
2373{
2374 int err;
2375 char pad;
2376
2377 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2378 PyErr_Clear();
2379 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2380 return NULL;
2381 }
2382 CHECK_DB_NOT_CLOSED(self);
2383
2384 MYDB_BEGIN_ALLOW_THREADS;
2385 err = self->db->set_re_pad(self->db, pad);
2386 MYDB_END_ALLOW_THREADS;
2387 RETURN_IF_ERR();
2388 RETURN_NONE();
2389}
2390
2391
2392static PyObject*
2393DB_set_re_source(DBObject* self, PyObject* args)
2394{
2395 int err;
2396 char *re_source;
2397
2398 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2399 return NULL;
2400 CHECK_DB_NOT_CLOSED(self);
2401
2402 MYDB_BEGIN_ALLOW_THREADS;
2403 err = self->db->set_re_source(self->db, re_source);
2404 MYDB_END_ALLOW_THREADS;
2405 RETURN_IF_ERR();
2406 RETURN_NONE();
2407}
2408
2409
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002410static PyObject*
2411DB_set_q_extentsize(DBObject* self, PyObject* args)
2412{
2413 int err;
2414 int extentsize;
2415
2416 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2417 return NULL;
2418 CHECK_DB_NOT_CLOSED(self);
2419
2420 MYDB_BEGIN_ALLOW_THREADS;
2421 err = self->db->set_q_extentsize(self->db, extentsize);
2422 MYDB_END_ALLOW_THREADS;
2423 RETURN_IF_ERR();
2424 RETURN_NONE();
2425}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002426
2427static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002428DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002429{
2430 int err, flags = 0, type;
2431 void* sp;
2432 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002433#if (DBVER >= 43)
2434 PyObject* txnobj = NULL;
2435 DB_TXN *txn = NULL;
Thomas Wouters89f507f2006-12-13 04:49:30 +00002436 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002437#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002438 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002439#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002440
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002441#if (DBVER >= 43)
2442 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2443 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002444 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002445 if (!checkTxnObj(txnobj, &txn))
2446 return NULL;
2447#else
2448 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2449 return NULL;
2450#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002451 CHECK_DB_NOT_CLOSED(self);
2452
2453 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002454#if (DBVER >= 43)
2455 err = self->db->stat(self->db, txn, &sp, flags);
2456#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002457 err = self->db->stat(self->db, &sp, flags);
2458#else
2459 err = self->db->stat(self->db, &sp, NULL, flags);
2460#endif
2461 MYDB_END_ALLOW_THREADS;
2462 RETURN_IF_ERR();
2463
2464 self->haveStat = 1;
2465
2466 /* Turn the stat structure into a dictionary */
2467 type = _DB_get_type(self);
2468 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2469 free(sp);
2470 return NULL;
2471 }
2472
2473#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2474#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2475#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2476
2477 switch (type) {
2478 case DB_HASH:
2479 MAKE_HASH_ENTRY(magic);
2480 MAKE_HASH_ENTRY(version);
2481 MAKE_HASH_ENTRY(nkeys);
2482 MAKE_HASH_ENTRY(ndata);
2483 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002484#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002485 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002486#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002487 MAKE_HASH_ENTRY(ffactor);
2488 MAKE_HASH_ENTRY(buckets);
2489 MAKE_HASH_ENTRY(free);
2490 MAKE_HASH_ENTRY(bfree);
2491 MAKE_HASH_ENTRY(bigpages);
2492 MAKE_HASH_ENTRY(big_bfree);
2493 MAKE_HASH_ENTRY(overflows);
2494 MAKE_HASH_ENTRY(ovfl_free);
2495 MAKE_HASH_ENTRY(dup);
2496 MAKE_HASH_ENTRY(dup_free);
2497 break;
2498
2499 case DB_BTREE:
2500 case DB_RECNO:
2501 MAKE_BT_ENTRY(magic);
2502 MAKE_BT_ENTRY(version);
2503 MAKE_BT_ENTRY(nkeys);
2504 MAKE_BT_ENTRY(ndata);
2505 MAKE_BT_ENTRY(pagesize);
2506 MAKE_BT_ENTRY(minkey);
2507 MAKE_BT_ENTRY(re_len);
2508 MAKE_BT_ENTRY(re_pad);
2509 MAKE_BT_ENTRY(levels);
2510 MAKE_BT_ENTRY(int_pg);
2511 MAKE_BT_ENTRY(leaf_pg);
2512 MAKE_BT_ENTRY(dup_pg);
2513 MAKE_BT_ENTRY(over_pg);
2514 MAKE_BT_ENTRY(free);
2515 MAKE_BT_ENTRY(int_pgfree);
2516 MAKE_BT_ENTRY(leaf_pgfree);
2517 MAKE_BT_ENTRY(dup_pgfree);
2518 MAKE_BT_ENTRY(over_pgfree);
2519 break;
2520
2521 case DB_QUEUE:
2522 MAKE_QUEUE_ENTRY(magic);
2523 MAKE_QUEUE_ENTRY(version);
2524 MAKE_QUEUE_ENTRY(nkeys);
2525 MAKE_QUEUE_ENTRY(ndata);
2526 MAKE_QUEUE_ENTRY(pagesize);
2527 MAKE_QUEUE_ENTRY(pages);
2528 MAKE_QUEUE_ENTRY(re_len);
2529 MAKE_QUEUE_ENTRY(re_pad);
2530 MAKE_QUEUE_ENTRY(pgfree);
2531#if (DBVER == 31)
2532 MAKE_QUEUE_ENTRY(start);
2533#endif
2534 MAKE_QUEUE_ENTRY(first_recno);
2535 MAKE_QUEUE_ENTRY(cur_recno);
2536 break;
2537
2538 default:
2539 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2540 Py_DECREF(d);
2541 d = NULL;
2542 }
2543
2544#undef MAKE_HASH_ENTRY
2545#undef MAKE_BT_ENTRY
2546#undef MAKE_QUEUE_ENTRY
2547
2548 free(sp);
2549 return d;
2550}
2551
2552static PyObject*
2553DB_sync(DBObject* self, PyObject* args)
2554{
2555 int err;
2556 int flags = 0;
2557
2558 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2559 return NULL;
2560 CHECK_DB_NOT_CLOSED(self);
2561
2562 MYDB_BEGIN_ALLOW_THREADS;
2563 err = self->db->sync(self->db, flags);
2564 MYDB_END_ALLOW_THREADS;
2565 RETURN_IF_ERR();
2566 RETURN_NONE();
2567}
2568
2569
2570#if (DBVER >= 33)
2571static PyObject*
2572DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2573{
2574 int err, flags=0;
2575 u_int32_t count=0;
2576 PyObject* txnobj = NULL;
2577 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002578 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002579
2580 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2581 &txnobj, &flags))
2582 return NULL;
2583 CHECK_DB_NOT_CLOSED(self);
2584 if (!checkTxnObj(txnobj, &txn))
2585 return NULL;
2586
2587 MYDB_BEGIN_ALLOW_THREADS;
2588 err = self->db->truncate(self->db, txn, &count, flags);
2589 MYDB_END_ALLOW_THREADS;
2590 RETURN_IF_ERR();
2591 return PyInt_FromLong(count);
2592}
2593#endif
2594
2595
2596static PyObject*
2597DB_upgrade(DBObject* self, PyObject* args)
2598{
2599 int err, flags=0;
2600 char *filename;
2601
2602 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2603 return NULL;
2604 CHECK_DB_NOT_CLOSED(self);
2605
2606 MYDB_BEGIN_ALLOW_THREADS;
2607 err = self->db->upgrade(self->db, filename, flags);
2608 MYDB_END_ALLOW_THREADS;
2609 RETURN_IF_ERR();
2610 RETURN_NONE();
2611}
2612
2613
2614static PyObject*
2615DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2616{
2617 int err, flags=0;
2618 char* fileName;
2619 char* dbName=NULL;
2620 char* outFileName=NULL;
2621 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002622 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002623 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002624
2625 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2626 &fileName, &dbName, &outFileName, &flags))
2627 return NULL;
2628
2629 CHECK_DB_NOT_CLOSED(self);
2630 if (outFileName)
2631 outFile = fopen(outFileName, "w");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002632 /* XXX(nnorwitz): it should probably be an exception if outFile
2633 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002634
2635 MYDB_BEGIN_ALLOW_THREADS;
2636 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2637 MYDB_END_ALLOW_THREADS;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002638 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002639 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002640
2641 /* DB.verify acts as a DB handle destructor (like close); this was
2642 * documented in BerkeleyDB 4.2 but had the undocumented effect
2643 * of not being safe in prior versions while still requiring an explicit
2644 * DB.close call afterwards. Lets call close for the user to emulate
2645 * the safe 4.2 behaviour. */
2646#if (DBVER <= 41)
2647 self->db->close(self->db, 0);
2648#endif
2649 self->db = NULL;
2650
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002651 RETURN_IF_ERR();
2652 RETURN_NONE();
2653}
2654
2655
2656static PyObject*
2657DB_set_get_returns_none(DBObject* self, PyObject* args)
2658{
2659 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002660 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002661
2662 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2663 return NULL;
2664 CHECK_DB_NOT_CLOSED(self);
2665
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002666 if (self->moduleFlags.getReturnsNone)
2667 ++oldValue;
2668 if (self->moduleFlags.cursorSetReturnsNone)
2669 ++oldValue;
2670 self->moduleFlags.getReturnsNone = (flags >= 1);
2671 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002672 return PyInt_FromLong(oldValue);
2673}
2674
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002675#if (DBVER >= 41)
2676static PyObject*
2677DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2678{
2679 int err;
2680 u_int32_t flags=0;
2681 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002682 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002683
2684 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2685 &passwd, &flags)) {
2686 return NULL;
2687 }
2688
2689 MYDB_BEGIN_ALLOW_THREADS;
2690 err = self->db->set_encrypt(self->db, passwd, flags);
2691 MYDB_END_ALLOW_THREADS;
2692
2693 RETURN_IF_ERR();
2694 RETURN_NONE();
2695}
2696#endif /* DBVER >= 41 */
2697
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002698
2699/*-------------------------------------------------------------- */
2700/* Mapping and Dictionary-like access routines */
2701
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002702Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002703{
2704 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002705 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002706 int flags = 0;
2707 void* sp;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002708 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002709
2710 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002711 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2712 PyErr_SetObject(DBError, t);
2713 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002714 return -1;
2715 }
2716
2717 if (self->haveStat) { /* Has the stat function been called recently? If
2718 so, we can use the cached value. */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002719 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002720 }
2721
2722 MYDB_BEGIN_ALLOW_THREADS;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002723redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002724#if (DBVER >= 43)
2725 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2726#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002727 err = self->db->stat(self->db, &sp, flags);
2728#else
2729 err = self->db->stat(self->db, &sp, NULL, flags);
2730#endif
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002731
2732 /* All the stat structures have matching fields upto the ndata field,
2733 so we can use any of them for the type cast */
2734 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2735
2736 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2737 * redo a full stat to make sure.
2738 * Fixes SF python bug 1493322, pybsddb bug 1184012
2739 */
2740 if (size == 0 && (flags & DB_FAST_STAT)) {
2741 flags = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002742 if (!err)
2743 free(sp);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002744 goto redo_stat_for_length;
2745 }
2746
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002747 MYDB_END_ALLOW_THREADS;
2748
2749 if (err)
2750 return -1;
2751
2752 self->haveStat = 1;
2753
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002754 free(sp);
2755 return size;
2756}
2757
2758
2759PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2760{
2761 int err;
2762 PyObject* retval;
Thomas Heller39763a12007-09-24 14:43:56 +00002763 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002764 DBT key;
2765 DBT data;
2766
2767 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002768 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002769 return NULL;
2770
2771 CLEAR_DBT(data);
2772 if (CHECK_DBFLAG(self, DB_THREAD)) {
2773 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2774 data.flags = DB_DBT_MALLOC;
2775 }
2776 MYDB_BEGIN_ALLOW_THREADS;
2777 err = self->db->get(self->db, NULL, &key, &data, 0);
2778 MYDB_END_ALLOW_THREADS;
2779 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2780 PyErr_SetObject(PyExc_KeyError, keyobj);
2781 retval = NULL;
2782 }
2783 else if (makeDBError(err)) {
2784 retval = NULL;
2785 }
2786 else {
Martin v. Löwis64ce5052007-08-05 15:39:16 +00002787 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002788 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002789 }
2790
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002791 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002792 return retval;
2793}
2794
2795
2796static int
2797DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2798{
2799 DBT key, data;
2800 int retval;
2801 int flags = 0;
Thomas Heller39763a12007-09-24 14:43:56 +00002802 Py_buffer *data_buf_view = NULL;
2803 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002804
2805 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002806 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2807 PyErr_SetObject(DBError, t);
2808 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002809 return -1;
2810 }
2811
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002812 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002813 return -1;
2814
2815 if (dataobj != NULL) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002816 if (!make_dbt(dataobj, &data, &data_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002817 retval = -1;
2818 else {
2819 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002820 /* dictionaries shouldn't have duplicate keys */
2821 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002822 retval = _DB_put(self, NULL, &key, &data, flags);
2823
2824 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002825 /* try deleting any old record that matches and then PUT it
2826 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002827 _DB_delete(self, NULL, &key, 0);
2828 PyErr_Clear();
2829 retval = _DB_put(self, NULL, &key, &data, flags);
2830 }
2831 }
2832 }
2833 else {
2834 /* dataobj == NULL, so delete the key */
2835 retval = _DB_delete(self, NULL, &key, 0);
2836 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002837 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2838 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002839 return retval;
2840}
2841
2842
2843static PyObject*
2844DB_has_key(DBObject* self, PyObject* args)
2845{
2846 int err;
2847 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00002848 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002849 DBT key, data;
2850 PyObject* txnobj = NULL;
2851 DB_TXN *txn = NULL;
2852
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002853 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002854 return NULL;
2855 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002856 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002857 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002858 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002859 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002860 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002861 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002862
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002863 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002864 it has a record but can't allocate a buffer for the data. This saves
2865 having to deal with data we won't be using.
2866 */
2867 CLEAR_DBT(data);
2868 data.flags = DB_DBT_USERMEM;
2869
2870 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002871 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002872 MYDB_END_ALLOW_THREADS;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002873 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002874
2875 if (err == DB_BUFFER_SMALL || err == 0) {
2876 return PyInt_FromLong(1);
2877 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2878 return PyInt_FromLong(0);
2879 }
2880
2881 makeDBError(err);
2882 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002883}
2884
2885
2886#define _KEYS_LIST 1
2887#define _VALUES_LIST 2
2888#define _ITEMS_LIST 3
2889
2890static PyObject*
2891_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2892{
2893 int err, dbtype;
2894 DBT key;
2895 DBT data;
2896 DBC *cursor;
2897 PyObject* list;
2898 PyObject* item = NULL;
2899
2900 CHECK_DB_NOT_CLOSED(self);
2901 CLEAR_DBT(key);
2902 CLEAR_DBT(data);
2903
2904 dbtype = _DB_get_type(self);
2905 if (dbtype == -1)
2906 return NULL;
2907
2908 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002909 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002910 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002911
2912 /* get a cursor */
2913 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002914 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002915 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002916 if (makeDBError(err)) {
2917 Py_DECREF(list);
2918 return NULL;
2919 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002920
2921 if (CHECK_DBFLAG(self, DB_THREAD)) {
2922 key.flags = DB_DBT_REALLOC;
2923 data.flags = DB_DBT_REALLOC;
2924 }
2925
2926 while (1) { /* use the cursor to traverse the DB, collecting items */
2927 MYDB_BEGIN_ALLOW_THREADS;
2928 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2929 MYDB_END_ALLOW_THREADS;
2930
2931 if (err) {
2932 /* for any error, break out of the loop */
2933 break;
2934 }
2935
2936 switch (type) {
2937 case _KEYS_LIST:
2938 switch(dbtype) {
2939 case DB_BTREE:
2940 case DB_HASH:
2941 default:
Martin v. Löwis64ce5052007-08-05 15:39:16 +00002942 item = PyBytes_FromStringAndSize((char*)key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002943 break;
2944 case DB_RECNO:
2945 case DB_QUEUE:
2946 item = PyInt_FromLong(*((db_recno_t*)key.data));
2947 break;
2948 }
2949 break;
2950
2951 case _VALUES_LIST:
Martin v. Löwis64ce5052007-08-05 15:39:16 +00002952 item = PyBytes_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002953 break;
2954
2955 case _ITEMS_LIST:
2956 switch(dbtype) {
2957 case DB_BTREE:
2958 case DB_HASH:
2959 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002960 item = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002961 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002962 break;
2963 case DB_RECNO:
2964 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002965 item = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002966 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002967 break;
2968 }
2969 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002970 default:
2971 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2972 item = NULL;
2973 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002974 }
2975 if (item == NULL) {
2976 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002977 list = NULL;
2978 goto done;
2979 }
2980 PyList_Append(list, item);
2981 Py_DECREF(item);
2982 }
2983
Gregory P. Smithe9477062005-06-04 06:46:59 +00002984 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2985 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002986 Py_DECREF(list);
2987 list = NULL;
2988 }
2989
2990 done:
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002991 free_dbt(&key);
2992 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002993 MYDB_BEGIN_ALLOW_THREADS;
2994 cursor->c_close(cursor);
2995 MYDB_END_ALLOW_THREADS;
2996 return list;
2997}
2998
2999
3000static PyObject*
3001DB_keys(DBObject* self, PyObject* args)
3002{
3003 PyObject* txnobj = NULL;
3004 DB_TXN *txn = NULL;
3005
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003006 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003007 return NULL;
3008 if (!checkTxnObj(txnobj, &txn))
3009 return NULL;
3010 return _DB_make_list(self, txn, _KEYS_LIST);
3011}
3012
3013
3014static PyObject*
3015DB_items(DBObject* self, PyObject* args)
3016{
3017 PyObject* txnobj = NULL;
3018 DB_TXN *txn = NULL;
3019
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003020 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003021 return NULL;
3022 if (!checkTxnObj(txnobj, &txn))
3023 return NULL;
3024 return _DB_make_list(self, txn, _ITEMS_LIST);
3025}
3026
3027
3028static PyObject*
3029DB_values(DBObject* self, PyObject* args)
3030{
3031 PyObject* txnobj = NULL;
3032 DB_TXN *txn = NULL;
3033
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003034 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003035 return NULL;
3036 if (!checkTxnObj(txnobj, &txn))
3037 return NULL;
3038 return _DB_make_list(self, txn, _VALUES_LIST);
3039}
3040
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003041/* --------------------------------------------------------------------- */
3042/* DBCursor methods */
3043
3044
3045static PyObject*
3046DBC_close(DBCursorObject* self, PyObject* args)
3047{
3048 int err = 0;
3049
3050 if (!PyArg_ParseTuple(args, ":close"))
3051 return NULL;
3052
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003053 if (self->dbc != NULL) {
3054 MYDB_BEGIN_ALLOW_THREADS;
3055 err = self->dbc->c_close(self->dbc);
3056 self->dbc = NULL;
3057 MYDB_END_ALLOW_THREADS;
3058 }
3059 RETURN_IF_ERR();
3060 RETURN_NONE();
3061}
3062
3063
3064static PyObject*
3065DBC_count(DBCursorObject* self, PyObject* args)
3066{
3067 int err = 0;
3068 db_recno_t count;
3069 int flags = 0;
3070
3071 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3072 return NULL;
3073
3074 CHECK_CURSOR_NOT_CLOSED(self);
3075
3076 MYDB_BEGIN_ALLOW_THREADS;
3077 err = self->dbc->c_count(self->dbc, &count, flags);
3078 MYDB_END_ALLOW_THREADS;
3079 RETURN_IF_ERR();
3080
3081 return PyInt_FromLong(count);
3082}
3083
3084
3085static PyObject*
3086DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3087{
3088 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3089}
3090
3091
3092static PyObject*
3093DBC_delete(DBCursorObject* self, PyObject* args)
3094{
3095 int err, flags=0;
3096
3097 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3098 return NULL;
3099
3100 CHECK_CURSOR_NOT_CLOSED(self);
3101
3102 MYDB_BEGIN_ALLOW_THREADS;
3103 err = self->dbc->c_del(self->dbc, flags);
3104 MYDB_END_ALLOW_THREADS;
3105 RETURN_IF_ERR();
3106
3107 self->mydb->haveStat = 0;
3108 RETURN_NONE();
3109}
3110
3111
3112static PyObject*
3113DBC_dup(DBCursorObject* self, PyObject* args)
3114{
3115 int err, flags =0;
3116 DBC* dbc = NULL;
3117
3118 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3119 return NULL;
3120
3121 CHECK_CURSOR_NOT_CLOSED(self);
3122
3123 MYDB_BEGIN_ALLOW_THREADS;
3124 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3125 MYDB_END_ALLOW_THREADS;
3126 RETURN_IF_ERR();
3127
3128 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3129}
3130
3131static PyObject*
3132DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3133{
3134 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3135}
3136
3137
3138static PyObject*
3139DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3140{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003141 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003142 PyObject* keyobj = NULL;
3143 PyObject* dataobj = NULL;
3144 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00003145 Py_buffer* data_buf_view = NULL;
3146 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003147 int dlen = -1;
3148 int doff = -1;
3149 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003150 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003151 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003152
3153 CLEAR_DBT(key);
3154 CLEAR_DBT(data);
3155 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003156 &flags, &dlen, &doff))
3157 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003158 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003159 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3160 &kwnames[1],
3161 &keyobj, &flags, &dlen, &doff))
3162 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003163 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003164 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3165 kwnames, &keyobj, &dataobj,
3166 &flags, &dlen, &doff))
3167 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003168 return NULL;
3169 }
3170 }
3171 }
3172
3173 CHECK_CURSOR_NOT_CLOSED(self);
3174
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003175 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003176 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003177 if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003178 (!add_partial_dbt(&data, dlen, doff)) )
3179 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003180 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3181 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003182 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003183 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003184
3185 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3186 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003187 if (!(key.flags & DB_DBT_REALLOC)) {
3188 key.flags |= DB_DBT_MALLOC;
3189 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003190 }
3191
3192 MYDB_BEGIN_ALLOW_THREADS;
3193 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3194 MYDB_END_ALLOW_THREADS;
3195
Gregory P. Smithe9477062005-06-04 06:46:59 +00003196 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3197 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003198 Py_INCREF(Py_None);
3199 retval = Py_None;
3200 }
3201 else if (makeDBError(err)) {
3202 retval = NULL;
3203 }
3204 else {
3205 switch (_DB_get_type(self->mydb)) {
3206 case -1:
3207 retval = NULL;
3208 break;
3209 case DB_BTREE:
3210 case DB_HASH:
3211 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003212 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003213 data.data, data.size);
3214 break;
3215 case DB_RECNO:
3216 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003217 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003218 data.data, data.size);
3219 break;
3220 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003221 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003222 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003223 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3224 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003225 return retval;
3226}
3227
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003228#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003229static PyObject*
3230DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3231{
3232 int err, flags=0;
3233 PyObject* keyobj = NULL;
3234 PyObject* dataobj = NULL;
3235 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00003236 Py_buffer* data_buf_view = NULL;
3237 Py_buffer* key_buf_view = NULL;
Gregory P. Smith19699a92004-06-28 04:06:49 +00003238 int dlen = -1;
3239 int doff = -1;
3240 DBT key, pkey, data;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003241 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3242 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003243
3244 CLEAR_DBT(key);
3245 CLEAR_DBT(data);
3246 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3247 &flags, &dlen, &doff))
3248 {
3249 PyErr_Clear();
3250 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003251 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003252 &keyobj, &flags, &dlen, &doff))
3253 {
3254 PyErr_Clear();
3255 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3256 kwnames, &keyobj, &dataobj,
3257 &flags, &dlen, &doff))
3258 {
3259 return NULL;
3260 }
3261 }
3262 }
3263
3264 CHECK_CURSOR_NOT_CLOSED(self);
3265
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003266 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Gregory P. Smith19699a92004-06-28 04:06:49 +00003267 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003268 if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) ||
Gregory P. Smith19699a92004-06-28 04:06:49 +00003269 (!add_partial_dbt(&data, dlen, doff)) ) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003270 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3271 free_buf_view(dataobj, data_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003272 return NULL;
3273 }
3274
3275 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3276 data.flags = DB_DBT_MALLOC;
3277 if (!(key.flags & DB_DBT_REALLOC)) {
3278 key.flags |= DB_DBT_MALLOC;
3279 }
3280 }
3281
3282 CLEAR_DBT(pkey);
3283 pkey.flags = DB_DBT_MALLOC;
3284
3285 MYDB_BEGIN_ALLOW_THREADS;
3286 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3287 MYDB_END_ALLOW_THREADS;
3288
Gregory P. Smithe9477062005-06-04 06:46:59 +00003289 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3290 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003291 Py_INCREF(Py_None);
3292 retval = Py_None;
3293 }
3294 else if (makeDBError(err)) {
3295 retval = NULL;
3296 }
3297 else {
3298 PyObject *pkeyObj;
3299 PyObject *dataObj;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003300 dataObj = PyBytes_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003301
3302 if (self->mydb->primaryDBType == DB_RECNO ||
3303 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003304 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003305 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003306 pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003307
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003308 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003309 {
3310 PyObject *keyObj;
3311 int type = _DB_get_type(self->mydb);
3312 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003313 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003314 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003315 keyObj = PyBytes_FromStringAndSize(key.data, key.size);
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003316 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Thomas Woutersb3153832006-03-08 01:47:19 +00003317 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003318 }
3319 else /* return just the pkey and data */
3320 {
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003321 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003322 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003323 Py_DECREF(dataObj);
3324 Py_DECREF(pkeyObj);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003325 free_dbt(&pkey);
3326 free_dbt(&data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003327 }
3328 /* the only time REALLOC should be set is if we used an integer
3329 * key that make_key_dbt malloc'd for us. always free these. */
3330 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003331 free_dbt(&key);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003332 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003333 free_buf_view(keyobj, key_buf_view);
3334 free_buf_view(dataobj, data_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003335 return retval;
3336}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003337#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003338
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003339
3340static PyObject*
3341DBC_get_recno(DBCursorObject* self, PyObject* args)
3342{
3343 int err;
3344 db_recno_t recno;
3345 DBT key;
3346 DBT data;
3347
3348 if (!PyArg_ParseTuple(args, ":get_recno"))
3349 return NULL;
3350
3351 CHECK_CURSOR_NOT_CLOSED(self);
3352
3353 CLEAR_DBT(key);
3354 CLEAR_DBT(data);
3355 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3356 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3357 data.flags = DB_DBT_MALLOC;
3358 key.flags = DB_DBT_MALLOC;
3359 }
3360
3361 MYDB_BEGIN_ALLOW_THREADS;
3362 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3363 MYDB_END_ALLOW_THREADS;
3364 RETURN_IF_ERR();
3365
3366 recno = *((db_recno_t*)data.data);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003367 free_dbt(&key);
3368 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003369 return PyInt_FromLong(recno);
3370}
3371
3372
3373static PyObject*
3374DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3375{
3376 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3377}
3378
3379
3380static PyObject*
3381DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3382{
3383 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3384}
3385
3386
3387static PyObject*
3388DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3389{
3390 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3391}
3392
3393
3394static PyObject*
3395DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3396{
3397 int err, flags = 0;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003398 PyObject *keyobj, *dataobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003399 Py_buffer *data_buf_view = NULL;
3400 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003401 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003402 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003403 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003404 int dlen = -1;
3405 int doff = -1;
3406
3407 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3408 &keyobj, &dataobj, &flags, &dlen, &doff))
3409 return NULL;
3410
3411 CHECK_CURSOR_NOT_CLOSED(self);
3412
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003413 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003414 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003415 if (!make_dbt(dataobj, &data, &data_buf_view) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003416 !add_partial_dbt(&data, dlen, doff) )
3417 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003418 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3419 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003420 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003421 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003422
3423 MYDB_BEGIN_ALLOW_THREADS;
3424 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3425 MYDB_END_ALLOW_THREADS;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003426 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3427 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003428 RETURN_IF_ERR();
3429 self->mydb->haveStat = 0;
3430 RETURN_NONE();
3431}
3432
3433
3434static PyObject*
3435DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3436{
3437 int err, flags = 0;
3438 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003439 PyObject *retval, *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003440 Py_buffer *key_buf_view = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003441 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003442 int dlen = -1;
3443 int doff = -1;
3444
3445 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3446 &keyobj, &flags, &dlen, &doff))
3447 return NULL;
3448
3449 CHECK_CURSOR_NOT_CLOSED(self);
3450
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003451 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003452 return NULL;
3453
3454 CLEAR_DBT(data);
3455 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3456 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3457 data.flags = DB_DBT_MALLOC;
3458 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003459 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003460 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003461 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003462 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003463
3464 MYDB_BEGIN_ALLOW_THREADS;
3465 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3466 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003467 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3468 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003469 Py_INCREF(Py_None);
3470 retval = Py_None;
3471 }
3472 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003473 retval = NULL;
3474 }
3475 else {
3476 switch (_DB_get_type(self->mydb)) {
3477 case -1:
3478 retval = NULL;
3479 break;
3480 case DB_BTREE:
3481 case DB_HASH:
3482 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003483 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003484 data.data, data.size);
3485 break;
3486 case DB_RECNO:
3487 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003488 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003489 data.data, data.size);
3490 break;
3491 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003492 free_dbt(&data);
3493 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003494 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003495 /* the only time REALLOC should be set is if we used an integer
3496 * key that make_key_dbt malloc'd for us. always free these. */
3497 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003498 free_dbt(&key);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003499 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003500 free_buf_view(keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003501
3502 return retval;
3503}
3504
3505
3506static PyObject*
3507DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3508{
3509 int err, flags = 0;
3510 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003511 PyObject *retval, *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003512 Py_buffer *key_buf_view = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003513 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003514 int dlen = -1;
3515 int doff = -1;
3516
3517 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3518 &keyobj, &flags, &dlen, &doff))
3519 return NULL;
3520
3521 CHECK_CURSOR_NOT_CLOSED(self);
3522
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003523 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003524 return NULL;
3525
3526 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003527 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003528 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003529 return NULL;
3530 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003531 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3532 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003533 data.flags |= DB_DBT_MALLOC;
3534 /* only BTREE databases will return anything in the key */
3535 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3536 key.flags |= DB_DBT_MALLOC;
3537 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003538 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003539 MYDB_BEGIN_ALLOW_THREADS;
3540 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3541 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003542 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3543 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003544 Py_INCREF(Py_None);
3545 retval = Py_None;
3546 }
3547 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003548 retval = NULL;
3549 }
3550 else {
3551 switch (_DB_get_type(self->mydb)) {
3552 case -1:
3553 retval = NULL;
3554 break;
3555 case DB_BTREE:
3556 case DB_HASH:
3557 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003558 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003559 data.data, data.size);
3560 break;
3561 case DB_RECNO:
3562 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003563 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003564 data.data, data.size);
3565 break;
3566 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003567 free_dbt(&key);
3568 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003569 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003570 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003571 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003572 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003573 free_dbt(&key);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003574 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003575 free_buf_view(keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003576
3577 return retval;
3578}
3579
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003580static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003581_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3582 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003583{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003584 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003585 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003586 PyObject *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00003587 Py_buffer *data_buf_view = NULL;
3588 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003589
Gregory P. Smith7441e652003-11-03 21:35:31 +00003590 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003591 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003592 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003593 if (!make_dbt(dataobj, &data, &data_buf_view)) {
3594 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003595 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003596 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003597
3598 MYDB_BEGIN_ALLOW_THREADS;
3599 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3600 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003601 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003602 Py_INCREF(Py_None);
3603 retval = Py_None;
3604 }
3605 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003606 retval = NULL;
3607 }
3608 else {
3609 switch (_DB_get_type(self->mydb)) {
3610 case -1:
3611 retval = NULL;
3612 break;
3613 case DB_BTREE:
3614 case DB_HASH:
3615 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003616 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003617 data.data, data.size);
3618 break;
3619 case DB_RECNO:
3620 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003621 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003622 data.data, data.size);
3623 break;
3624 }
3625 }
3626
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003627 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3628 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003629 return retval;
3630}
3631
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003632static PyObject*
3633DBC_get_both(DBCursorObject* self, PyObject* args)
3634{
3635 int flags=0;
3636 PyObject *keyobj, *dataobj;
3637
3638 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3639 return NULL;
3640
Gregory P. Smith7441e652003-11-03 21:35:31 +00003641 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003642 CHECK_CURSOR_NOT_CLOSED(self);
3643
3644 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3645 self->mydb->moduleFlags.getReturnsNone);
3646}
3647
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003648/* Return size of entry */
3649static PyObject*
3650DBC_get_current_size(DBCursorObject* self, PyObject* args)
3651{
3652 int err, flags=DB_CURRENT;
3653 PyObject* retval = NULL;
3654 DBT key, data;
3655
3656 if (!PyArg_ParseTuple(args, ":get_current_size"))
3657 return NULL;
3658 CHECK_CURSOR_NOT_CLOSED(self);
3659 CLEAR_DBT(key);
3660 CLEAR_DBT(data);
3661
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003662 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003663 getting the record size. */
3664 data.flags = DB_DBT_USERMEM;
3665 data.ulen = 0;
3666 MYDB_BEGIN_ALLOW_THREADS;
3667 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3668 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003669 if (err == DB_BUFFER_SMALL || !err) {
3670 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003671 retval = PyInt_FromLong((long)data.size);
3672 err = 0;
3673 }
3674
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003675 free_dbt(&key);
3676 free_dbt(&data);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003677 RETURN_IF_ERR();
3678 return retval;
3679}
3680
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003681static PyObject*
3682DBC_set_both(DBCursorObject* self, PyObject* args)
3683{
3684 int flags=0;
3685 PyObject *keyobj, *dataobj;
3686
3687 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3688 return NULL;
3689
Gregory P. Smith7441e652003-11-03 21:35:31 +00003690 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003691 CHECK_CURSOR_NOT_CLOSED(self);
3692
3693 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3694 self->mydb->moduleFlags.cursorSetReturnsNone);
3695}
3696
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003697
3698static PyObject*
3699DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3700{
3701 int err, irecno, flags=0;
3702 db_recno_t recno;
3703 DBT key, data;
3704 PyObject* retval;
3705 int dlen = -1;
3706 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003707 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003708
3709 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3710 &irecno, &flags, &dlen, &doff))
3711 return NULL;
3712
3713 CHECK_CURSOR_NOT_CLOSED(self);
3714
3715 CLEAR_DBT(key);
3716 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003717 /* use allocated space so DB will be able to realloc room for the real
3718 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003719 key.data = malloc(sizeof(db_recno_t));
3720 if (key.data == NULL) {
3721 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3722 return NULL;
3723 }
3724 key.size = sizeof(db_recno_t);
3725 key.ulen = key.size;
3726 memcpy(key.data, &recno, sizeof(db_recno_t));
3727 key.flags = DB_DBT_REALLOC;
3728
3729 CLEAR_DBT(data);
3730 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3731 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3732 data.flags = DB_DBT_MALLOC;
3733 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003734 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003735 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003736 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003737 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003738
3739 MYDB_BEGIN_ALLOW_THREADS;
3740 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3741 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003742 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3743 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003744 Py_INCREF(Py_None);
3745 retval = Py_None;
3746 }
3747 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003748 retval = NULL;
3749 }
3750 else { /* Can only be used for BTrees, so no need to return int key */
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003751 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003752 data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003753 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003754 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003755 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003756
3757 return retval;
3758}
3759
3760
3761static PyObject*
3762DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3763{
3764 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3765}
3766
3767
3768static PyObject*
3769DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3770{
3771 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3772}
3773
3774
3775static PyObject*
3776DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3777{
3778 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3779}
3780
3781
3782static PyObject*
3783DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3784{
3785 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3786}
3787
3788
3789static PyObject*
3790DBC_join_item(DBCursorObject* self, PyObject* args)
3791{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003792 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003793 DBT key, data;
3794 PyObject* retval;
3795
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003796 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003797 return NULL;
3798
3799 CHECK_CURSOR_NOT_CLOSED(self);
3800
3801 CLEAR_DBT(key);
3802 CLEAR_DBT(data);
3803 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3804 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3805 key.flags = DB_DBT_MALLOC;
3806 }
3807
3808 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003809 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003810 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003811 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3812 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003813 Py_INCREF(Py_None);
3814 retval = Py_None;
3815 }
3816 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003817 retval = NULL;
3818 }
3819 else {
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003820 retval = Py_BuildValue("y#", key.data, key.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003821 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003822 }
3823
3824 return retval;
3825}
3826
3827
3828
3829/* --------------------------------------------------------------------- */
3830/* DBEnv methods */
3831
3832
3833static PyObject*
3834DBEnv_close(DBEnvObject* self, PyObject* args)
3835{
3836 int err, flags = 0;
3837
3838 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3839 return NULL;
3840 if (!self->closed) { /* Don't close more than once */
3841 MYDB_BEGIN_ALLOW_THREADS;
3842 err = self->db_env->close(self->db_env, flags);
3843 MYDB_END_ALLOW_THREADS;
3844 /* after calling DBEnv->close, regardless of error, this DBEnv
3845 * may not be accessed again (BerkeleyDB docs). */
3846 self->closed = 1;
3847 self->db_env = NULL;
3848 RETURN_IF_ERR();
3849 }
3850 RETURN_NONE();
3851}
3852
3853
3854static PyObject*
3855DBEnv_open(DBEnvObject* self, PyObject* args)
3856{
3857 int err, flags=0, mode=0660;
3858 char *db_home;
3859
3860 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3861 return NULL;
3862
3863 CHECK_ENV_NOT_CLOSED(self);
3864
3865 MYDB_BEGIN_ALLOW_THREADS;
3866 err = self->db_env->open(self->db_env, db_home, flags, mode);
3867 MYDB_END_ALLOW_THREADS;
3868 RETURN_IF_ERR();
3869 self->closed = 0;
3870 self->flags = flags;
3871 RETURN_NONE();
3872}
3873
3874
3875static PyObject*
3876DBEnv_remove(DBEnvObject* self, PyObject* args)
3877{
3878 int err, flags=0;
3879 char *db_home;
3880
3881 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3882 return NULL;
3883 CHECK_ENV_NOT_CLOSED(self);
3884 MYDB_BEGIN_ALLOW_THREADS;
3885 err = self->db_env->remove(self->db_env, db_home, flags);
3886 MYDB_END_ALLOW_THREADS;
3887 RETURN_IF_ERR();
3888 RETURN_NONE();
3889}
3890
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003891#if (DBVER >= 41)
3892static PyObject*
3893DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3894{
3895 int err;
3896 u_int32_t flags=0;
3897 char *file = NULL;
3898 char *database = NULL;
3899 PyObject *txnobj = NULL;
3900 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003901 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003902 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003903
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003904 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003905 &file, &database, &txnobj, &flags)) {
3906 return NULL;
3907 }
3908 if (!checkTxnObj(txnobj, &txn)) {
3909 return NULL;
3910 }
3911 CHECK_ENV_NOT_CLOSED(self);
3912 MYDB_BEGIN_ALLOW_THREADS;
3913 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3914 MYDB_END_ALLOW_THREADS;
3915 RETURN_IF_ERR();
3916 RETURN_NONE();
3917}
3918
3919static PyObject*
3920DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3921{
3922 int err;
3923 u_int32_t flags=0;
3924 char *file = NULL;
3925 char *database = NULL;
3926 char *newname = NULL;
3927 PyObject *txnobj = NULL;
3928 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003929 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003930 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003931
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003932 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003933 &file, &database, &newname, &txnobj, &flags)) {
3934 return NULL;
3935 }
3936 if (!checkTxnObj(txnobj, &txn)) {
3937 return NULL;
3938 }
3939 CHECK_ENV_NOT_CLOSED(self);
3940 MYDB_BEGIN_ALLOW_THREADS;
3941 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3942 flags);
3943 MYDB_END_ALLOW_THREADS;
3944 RETURN_IF_ERR();
3945 RETURN_NONE();
3946}
3947
3948static PyObject*
3949DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3950{
3951 int err;
3952 u_int32_t flags=0;
3953 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003954 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003955
3956 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3957 &passwd, &flags)) {
3958 return NULL;
3959 }
3960
3961 MYDB_BEGIN_ALLOW_THREADS;
3962 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3963 MYDB_END_ALLOW_THREADS;
3964
3965 RETURN_IF_ERR();
3966 RETURN_NONE();
3967}
3968#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003969
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003970#if (DBVER >= 40)
3971static PyObject*
3972DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3973{
3974 int err;
3975 u_int32_t flags=0;
3976 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003977 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003978
3979 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3980 &timeout, &flags)) {
3981 return NULL;
3982 }
3983
3984 MYDB_BEGIN_ALLOW_THREADS;
3985 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3986 MYDB_END_ALLOW_THREADS;
3987
3988 RETURN_IF_ERR();
3989 RETURN_NONE();
3990}
3991#endif /* DBVER >= 40 */
3992
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003993static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003994DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3995{
3996 int err;
3997 long shm_key = 0;
3998
3999 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
4000 return NULL;
4001 CHECK_ENV_NOT_CLOSED(self);
4002
4003 err = self->db_env->set_shm_key(self->db_env, shm_key);
4004 RETURN_IF_ERR();
4005 RETURN_NONE();
4006}
4007
4008static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004009DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4010{
4011 int err, gbytes=0, bytes=0, ncache=0;
4012
4013 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4014 &gbytes, &bytes, &ncache))
4015 return NULL;
4016 CHECK_ENV_NOT_CLOSED(self);
4017
4018 MYDB_BEGIN_ALLOW_THREADS;
4019 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4020 MYDB_END_ALLOW_THREADS;
4021 RETURN_IF_ERR();
4022 RETURN_NONE();
4023}
4024
4025
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004026static PyObject*
4027DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4028{
4029 int err, flags=0, onoff=0;
4030
4031 if (!PyArg_ParseTuple(args, "ii:set_flags",
4032 &flags, &onoff))
4033 return NULL;
4034 CHECK_ENV_NOT_CLOSED(self);
4035
4036 MYDB_BEGIN_ALLOW_THREADS;
4037 err = self->db_env->set_flags(self->db_env, flags, onoff);
4038 MYDB_END_ALLOW_THREADS;
4039 RETURN_IF_ERR();
4040 RETURN_NONE();
4041}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004042
4043
4044static PyObject*
4045DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4046{
4047 int err;
4048 char *dir;
4049
4050 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4051 return NULL;
4052 CHECK_ENV_NOT_CLOSED(self);
4053
4054 MYDB_BEGIN_ALLOW_THREADS;
4055 err = self->db_env->set_data_dir(self->db_env, dir);
4056 MYDB_END_ALLOW_THREADS;
4057 RETURN_IF_ERR();
4058 RETURN_NONE();
4059}
4060
4061
4062static PyObject*
4063DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4064{
4065 int err, lg_bsize;
4066
4067 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4068 return NULL;
4069 CHECK_ENV_NOT_CLOSED(self);
4070
4071 MYDB_BEGIN_ALLOW_THREADS;
4072 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4073 MYDB_END_ALLOW_THREADS;
4074 RETURN_IF_ERR();
4075 RETURN_NONE();
4076}
4077
4078
4079static PyObject*
4080DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4081{
4082 int err;
4083 char *dir;
4084
4085 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4086 return NULL;
4087 CHECK_ENV_NOT_CLOSED(self);
4088
4089 MYDB_BEGIN_ALLOW_THREADS;
4090 err = self->db_env->set_lg_dir(self->db_env, dir);
4091 MYDB_END_ALLOW_THREADS;
4092 RETURN_IF_ERR();
4093 RETURN_NONE();
4094}
4095
4096static PyObject*
4097DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4098{
4099 int err, lg_max;
4100
4101 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4102 return NULL;
4103 CHECK_ENV_NOT_CLOSED(self);
4104
4105 MYDB_BEGIN_ALLOW_THREADS;
4106 err = self->db_env->set_lg_max(self->db_env, lg_max);
4107 MYDB_END_ALLOW_THREADS;
4108 RETURN_IF_ERR();
4109 RETURN_NONE();
4110}
4111
4112
Neal Norwitz84562352005-10-20 04:30:15 +00004113#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004114static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004115DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4116{
4117 int err, lg_max;
4118
4119 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4120 return NULL;
4121 CHECK_ENV_NOT_CLOSED(self);
4122
4123 MYDB_BEGIN_ALLOW_THREADS;
4124 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4125 MYDB_END_ALLOW_THREADS;
4126 RETURN_IF_ERR();
4127 RETURN_NONE();
4128}
Neal Norwitz84562352005-10-20 04:30:15 +00004129#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004130
4131
4132static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004133DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4134{
4135 int err, lk_detect;
4136
4137 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4138 return NULL;
4139 CHECK_ENV_NOT_CLOSED(self);
4140
4141 MYDB_BEGIN_ALLOW_THREADS;
4142 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4143 MYDB_END_ALLOW_THREADS;
4144 RETURN_IF_ERR();
4145 RETURN_NONE();
4146}
4147
4148
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004149#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004150static PyObject*
4151DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4152{
4153 int err, max;
4154
4155 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4156 return NULL;
4157 CHECK_ENV_NOT_CLOSED(self);
4158
4159 MYDB_BEGIN_ALLOW_THREADS;
4160 err = self->db_env->set_lk_max(self->db_env, max);
4161 MYDB_END_ALLOW_THREADS;
4162 RETURN_IF_ERR();
4163 RETURN_NONE();
4164}
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004165#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004166
4167
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004168
4169static PyObject*
4170DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4171{
4172 int err, max;
4173
4174 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4175 return NULL;
4176 CHECK_ENV_NOT_CLOSED(self);
4177
4178 MYDB_BEGIN_ALLOW_THREADS;
4179 err = self->db_env->set_lk_max_locks(self->db_env, max);
4180 MYDB_END_ALLOW_THREADS;
4181 RETURN_IF_ERR();
4182 RETURN_NONE();
4183}
4184
4185
4186static PyObject*
4187DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4188{
4189 int err, max;
4190
4191 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4192 return NULL;
4193 CHECK_ENV_NOT_CLOSED(self);
4194
4195 MYDB_BEGIN_ALLOW_THREADS;
4196 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4197 MYDB_END_ALLOW_THREADS;
4198 RETURN_IF_ERR();
4199 RETURN_NONE();
4200}
4201
4202
4203static PyObject*
4204DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4205{
4206 int err, max;
4207
4208 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4209 return NULL;
4210 CHECK_ENV_NOT_CLOSED(self);
4211
4212 MYDB_BEGIN_ALLOW_THREADS;
4213 err = self->db_env->set_lk_max_objects(self->db_env, max);
4214 MYDB_END_ALLOW_THREADS;
4215 RETURN_IF_ERR();
4216 RETURN_NONE();
4217}
4218
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004219
4220static PyObject*
4221DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4222{
4223 int err, mp_mmapsize;
4224
4225 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4226 return NULL;
4227 CHECK_ENV_NOT_CLOSED(self);
4228
4229 MYDB_BEGIN_ALLOW_THREADS;
4230 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4231 MYDB_END_ALLOW_THREADS;
4232 RETURN_IF_ERR();
4233 RETURN_NONE();
4234}
4235
4236
4237static PyObject*
4238DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4239{
4240 int err;
4241 char *dir;
4242
4243 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4244 return NULL;
4245 CHECK_ENV_NOT_CLOSED(self);
4246
4247 MYDB_BEGIN_ALLOW_THREADS;
4248 err = self->db_env->set_tmp_dir(self->db_env, dir);
4249 MYDB_END_ALLOW_THREADS;
4250 RETURN_IF_ERR();
4251 RETURN_NONE();
4252}
4253
4254
4255static PyObject*
4256DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4257{
4258 int flags = 0;
4259 PyObject* txnobj = NULL;
4260 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004261 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004262
4263 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4264 &txnobj, &flags))
4265 return NULL;
4266
4267 if (!checkTxnObj(txnobj, &txn))
4268 return NULL;
4269 CHECK_ENV_NOT_CLOSED(self);
4270
4271 return (PyObject*)newDBTxnObject(self, txn, flags);
4272}
4273
4274
4275static PyObject*
4276DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4277{
4278 int err, kbyte=0, min=0, flags=0;
4279
4280 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4281 return NULL;
4282 CHECK_ENV_NOT_CLOSED(self);
4283
4284 MYDB_BEGIN_ALLOW_THREADS;
4285#if (DBVER >= 40)
4286 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4287#else
4288 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4289#endif
4290 MYDB_END_ALLOW_THREADS;
4291 RETURN_IF_ERR();
4292 RETURN_NONE();
4293}
4294
4295
4296static PyObject*
4297DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4298{
4299 int err, max;
4300
4301 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4302 return NULL;
4303 CHECK_ENV_NOT_CLOSED(self);
4304
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004305 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004306 RETURN_IF_ERR();
4307 RETURN_NONE();
4308}
4309
4310
4311static PyObject*
4312DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4313{
4314 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004315 long stamp;
4316 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004317
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004318 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004319 return NULL;
4320 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004321 timestamp = (time_t)stamp;
4322 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004323 RETURN_IF_ERR();
4324 RETURN_NONE();
4325}
4326
4327
4328static PyObject*
4329DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4330{
4331 int err, atype, flags=0;
4332 int aborted = 0;
4333
4334 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4335 return NULL;
4336 CHECK_ENV_NOT_CLOSED(self);
4337
4338 MYDB_BEGIN_ALLOW_THREADS;
4339#if (DBVER >= 40)
4340 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4341#else
4342 err = lock_detect(self->db_env, flags, atype, &aborted);
4343#endif
4344 MYDB_END_ALLOW_THREADS;
4345 RETURN_IF_ERR();
4346 return PyInt_FromLong(aborted);
4347}
4348
4349
4350static PyObject*
4351DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4352{
4353 int flags=0;
4354 int locker, lock_mode;
4355 DBT obj;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004356 PyObject *objobj, *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00004357 Py_buffer *obj_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004358
4359 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4360 return NULL;
4361
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004362 if (!make_dbt(objobj, &obj, &obj_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004363 return NULL;
4364
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004365 retval = (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4366 free_buf_view(objobj, obj_buf_view);
4367 return retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004368}
4369
4370
4371static PyObject*
4372DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4373{
4374 int err;
4375 u_int32_t theID;
4376
4377 if (!PyArg_ParseTuple(args, ":lock_id"))
4378 return NULL;
4379
4380 CHECK_ENV_NOT_CLOSED(self);
4381 MYDB_BEGIN_ALLOW_THREADS;
4382#if (DBVER >= 40)
4383 err = self->db_env->lock_id(self->db_env, &theID);
4384#else
4385 err = lock_id(self->db_env, &theID);
4386#endif
4387 MYDB_END_ALLOW_THREADS;
4388 RETURN_IF_ERR();
4389
4390 return PyInt_FromLong((long)theID);
4391}
4392
4393
4394static PyObject*
4395DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4396{
4397 int err;
4398 DBLockObject* dblockobj;
4399
4400 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4401 return NULL;
4402
4403 CHECK_ENV_NOT_CLOSED(self);
4404 MYDB_BEGIN_ALLOW_THREADS;
4405#if (DBVER >= 40)
4406 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4407#else
4408 err = lock_put(self->db_env, &dblockobj->lock);
4409#endif
4410 MYDB_END_ALLOW_THREADS;
4411 RETURN_IF_ERR();
4412 RETURN_NONE();
4413}
4414
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004415#if (DBVER >= 44)
4416static PyObject*
4417DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4418{
4419 int err;
4420 char *file;
4421 u_int32_t flags = 0;
4422 static char* kwnames[] = { "file", "flags", NULL};
4423
4424 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4425 &file, &flags))
4426 return NULL;
4427 CHECK_ENV_NOT_CLOSED(self);
4428
4429 MYDB_BEGIN_ALLOW_THREADS;
4430 err = self->db_env->lsn_reset(self->db_env, file, flags);
4431 MYDB_END_ALLOW_THREADS;
4432 RETURN_IF_ERR();
4433 RETURN_NONE();
4434}
4435#endif /* DBVER >= 4.4 */
4436
4437#if (DBVER >= 40)
4438static PyObject*
4439DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4440{
4441 int err;
4442 DB_LOG_STAT* statp = NULL;
4443 PyObject* d = NULL;
4444 u_int32_t flags = 0;
4445
4446 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4447 return NULL;
4448 CHECK_ENV_NOT_CLOSED(self);
4449
4450 MYDB_BEGIN_ALLOW_THREADS;
4451 err = self->db_env->log_stat(self->db_env, &statp, flags);
4452 MYDB_END_ALLOW_THREADS;
4453 RETURN_IF_ERR();
4454
4455 /* Turn the stat structure into a dictionary */
4456 d = PyDict_New();
4457 if (d == NULL) {
4458 if (statp)
4459 free(statp);
4460 return NULL;
4461 }
4462
4463#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4464
4465 MAKE_ENTRY(magic);
4466 MAKE_ENTRY(version);
4467 MAKE_ENTRY(mode);
4468 MAKE_ENTRY(lg_bsize);
4469#if (DBVER >= 44)
4470 MAKE_ENTRY(lg_size);
4471 MAKE_ENTRY(record);
4472#endif
4473#if (DBVER <= 40)
4474 MAKE_ENTRY(lg_max);
4475#endif
4476 MAKE_ENTRY(w_mbytes);
4477 MAKE_ENTRY(w_bytes);
4478 MAKE_ENTRY(wc_mbytes);
4479 MAKE_ENTRY(wc_bytes);
4480 MAKE_ENTRY(wcount);
4481 MAKE_ENTRY(wcount_fill);
4482#if (DBVER >= 44)
4483 MAKE_ENTRY(rcount);
4484#endif
4485 MAKE_ENTRY(scount);
4486 MAKE_ENTRY(cur_file);
4487 MAKE_ENTRY(cur_offset);
4488 MAKE_ENTRY(disk_file);
4489 MAKE_ENTRY(disk_offset);
4490 MAKE_ENTRY(maxcommitperflush);
4491 MAKE_ENTRY(mincommitperflush);
4492 MAKE_ENTRY(regsize);
4493 MAKE_ENTRY(region_wait);
4494 MAKE_ENTRY(region_nowait);
4495
4496#undef MAKE_ENTRY
4497 free(statp);
4498 return d;
4499} /* DBEnv_log_stat */
4500#endif /* DBVER >= 4.0 for log_stat method */
4501
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004502
4503static PyObject*
4504DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4505{
4506 int err;
4507 DB_LOCK_STAT* sp;
4508 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004509 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004510
4511 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4512 return NULL;
4513 CHECK_ENV_NOT_CLOSED(self);
4514
4515 MYDB_BEGIN_ALLOW_THREADS;
4516#if (DBVER >= 40)
4517 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4518#else
4519#if (DBVER >= 33)
4520 err = lock_stat(self->db_env, &sp);
4521#else
4522 err = lock_stat(self->db_env, &sp, NULL);
4523#endif
4524#endif
4525 MYDB_END_ALLOW_THREADS;
4526 RETURN_IF_ERR();
4527
4528 /* Turn the stat structure into a dictionary */
4529 d = PyDict_New();
4530 if (d == NULL) {
4531 free(sp);
4532 return NULL;
4533 }
4534
4535#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4536
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004537#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004538 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004539#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004540 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004541 MAKE_ENTRY(maxlocks);
4542 MAKE_ENTRY(maxlockers);
4543 MAKE_ENTRY(maxobjects);
4544 MAKE_ENTRY(nlocks);
4545 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004546 MAKE_ENTRY(nlockers);
4547 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004548 MAKE_ENTRY(nobjects);
4549 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004550 MAKE_ENTRY(nrequests);
4551 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004552#if (DBVER < 44)
4553 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004554 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004555#else
4556 MAKE_ENTRY(lock_nowait);
4557 MAKE_ENTRY(lock_wait);
4558#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004559 MAKE_ENTRY(ndeadlocks);
4560 MAKE_ENTRY(regsize);
4561 MAKE_ENTRY(region_wait);
4562 MAKE_ENTRY(region_nowait);
4563
4564#undef MAKE_ENTRY
4565 free(sp);
4566 return d;
4567}
4568
4569
4570static PyObject*
4571DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4572{
4573 int flags=0;
4574 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004575 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004576 PyObject* list;
4577 PyObject* item = NULL;
4578
4579 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4580 return NULL;
4581
4582 CHECK_ENV_NOT_CLOSED(self);
4583 MYDB_BEGIN_ALLOW_THREADS;
4584#if (DBVER >= 40)
4585 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4586#elif (DBVER == 33)
4587 err = log_archive(self->db_env, &log_list, flags);
4588#else
4589 err = log_archive(self->db_env, &log_list, flags, NULL);
4590#endif
4591 MYDB_END_ALLOW_THREADS;
4592 RETURN_IF_ERR();
4593
4594 list = PyList_New(0);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004595 if (list == NULL) {
4596 if (log_list)
4597 free(log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004598 return NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004599 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004600
4601 if (log_list) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004602 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004603 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
Martin v. Löwis64ce5052007-08-05 15:39:16 +00004604 item = PyUnicode_FromString (*log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004605 if (item == NULL) {
4606 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004607 list = NULL;
4608 break;
4609 }
4610 PyList_Append(list, item);
4611 Py_DECREF(item);
4612 }
4613 free(log_list_start);
4614 }
4615 return list;
4616}
4617
4618
4619static PyObject*
4620DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4621{
4622 int err;
4623 DB_TXN_STAT* sp;
4624 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004625 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004626
4627 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4628 return NULL;
4629 CHECK_ENV_NOT_CLOSED(self);
4630
4631 MYDB_BEGIN_ALLOW_THREADS;
4632#if (DBVER >= 40)
4633 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4634#elif (DBVER == 33)
4635 err = txn_stat(self->db_env, &sp);
4636#else
4637 err = txn_stat(self->db_env, &sp, NULL);
4638#endif
4639 MYDB_END_ALLOW_THREADS;
4640 RETURN_IF_ERR();
4641
4642 /* Turn the stat structure into a dictionary */
4643 d = PyDict_New();
4644 if (d == NULL) {
4645 free(sp);
4646 return NULL;
4647 }
4648
4649#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00004650#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004651
Guido van Rossumd8faa362007-04-27 19:54:29 +00004652 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004653 MAKE_ENTRY(last_txnid);
4654 MAKE_ENTRY(maxtxns);
4655 MAKE_ENTRY(nactive);
4656 MAKE_ENTRY(maxnactive);
4657 MAKE_ENTRY(nbegins);
4658 MAKE_ENTRY(naborts);
4659 MAKE_ENTRY(ncommits);
4660 MAKE_ENTRY(regsize);
4661 MAKE_ENTRY(region_wait);
4662 MAKE_ENTRY(region_nowait);
4663
4664#undef MAKE_ENTRY
Guido van Rossumd8faa362007-04-27 19:54:29 +00004665#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004666 free(sp);
4667 return d;
4668}
4669
4670
4671static PyObject*
4672DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4673{
4674 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004675 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004676
4677 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4678 return NULL;
4679 CHECK_ENV_NOT_CLOSED(self);
4680
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004681 if (self->moduleFlags.getReturnsNone)
4682 ++oldValue;
4683 if (self->moduleFlags.cursorSetReturnsNone)
4684 ++oldValue;
4685 self->moduleFlags.getReturnsNone = (flags >= 1);
4686 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004687 return PyInt_FromLong(oldValue);
4688}
4689
4690
4691/* --------------------------------------------------------------------- */
4692/* DBTxn methods */
4693
4694
4695static PyObject*
4696DBTxn_commit(DBTxnObject* self, PyObject* args)
4697{
4698 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004699 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004700
4701 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4702 return NULL;
4703
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004704 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004705 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4706 "after txn_commit or txn_abort");
4707 PyErr_SetObject(DBError, t);
4708 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004709 return NULL;
4710 }
4711 txn = self->txn;
4712 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004713 MYDB_BEGIN_ALLOW_THREADS;
4714#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004715 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004716#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004717 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004718#endif
4719 MYDB_END_ALLOW_THREADS;
4720 RETURN_IF_ERR();
4721 RETURN_NONE();
4722}
4723
4724static PyObject*
4725DBTxn_prepare(DBTxnObject* self, PyObject* args)
4726{
4727#if (DBVER >= 33)
4728 int err;
4729 char* gid=NULL;
4730 int gid_size=0;
4731
Gregory P. Smith361ed152007-08-23 07:32:27 +00004732 if (!PyArg_ParseTuple(args, "y#:prepare", &gid, &gid_size))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004733 return NULL;
4734
4735 if (gid_size != DB_XIDDATASIZE) {
4736 PyErr_SetString(PyExc_TypeError,
4737 "gid must be DB_XIDDATASIZE bytes long");
4738 return NULL;
4739 }
4740
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004741 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004742 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4743 "after txn_commit or txn_abort");
4744 PyErr_SetObject(DBError, t);
4745 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004746 return NULL;
4747 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004748 MYDB_BEGIN_ALLOW_THREADS;
4749#if (DBVER >= 40)
4750 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4751#else
4752 err = txn_prepare(self->txn, (u_int8_t*)gid);
4753#endif
4754 MYDB_END_ALLOW_THREADS;
4755 RETURN_IF_ERR();
4756 RETURN_NONE();
4757#else
4758 int err;
4759
4760 if (!PyArg_ParseTuple(args, ":prepare"))
4761 return NULL;
4762
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004763 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004764 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4765 "after txn_commit or txn_abort");
4766 PyErr_SetObject(DBError, t);
4767 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004768 return NULL;
4769 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004770 MYDB_BEGIN_ALLOW_THREADS;
4771 err = txn_prepare(self->txn);
4772 MYDB_END_ALLOW_THREADS;
4773 RETURN_IF_ERR();
4774 RETURN_NONE();
4775#endif
4776}
4777
4778
4779static PyObject*
4780DBTxn_abort(DBTxnObject* self, PyObject* args)
4781{
4782 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004783 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004784
4785 if (!PyArg_ParseTuple(args, ":abort"))
4786 return NULL;
4787
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004788 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004789 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4790 "after txn_commit or txn_abort");
4791 PyErr_SetObject(DBError, t);
4792 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004793 return NULL;
4794 }
4795 txn = self->txn;
4796 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004797 MYDB_BEGIN_ALLOW_THREADS;
4798#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004799 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004800#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004801 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004802#endif
4803 MYDB_END_ALLOW_THREADS;
4804 RETURN_IF_ERR();
4805 RETURN_NONE();
4806}
4807
4808
4809static PyObject*
4810DBTxn_id(DBTxnObject* self, PyObject* args)
4811{
4812 int id;
4813
4814 if (!PyArg_ParseTuple(args, ":id"))
4815 return NULL;
4816
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004817 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004818 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4819 "after txn_commit or txn_abort");
4820 PyErr_SetObject(DBError, t);
4821 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004822 return NULL;
4823 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004824 MYDB_BEGIN_ALLOW_THREADS;
4825#if (DBVER >= 40)
4826 id = self->txn->id(self->txn);
4827#else
4828 id = txn_id(self->txn);
4829#endif
4830 MYDB_END_ALLOW_THREADS;
4831 return PyInt_FromLong(id);
4832}
4833
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004834#if (DBVER >= 43)
4835/* --------------------------------------------------------------------- */
4836/* DBSequence methods */
4837
4838
4839static PyObject*
4840DBSequence_close(DBSequenceObject* self, PyObject* args)
4841{
4842 int err, flags=0;
4843 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4844 return NULL;
4845 CHECK_SEQUENCE_NOT_CLOSED(self)
4846
4847 MYDB_BEGIN_ALLOW_THREADS
4848 err = self->sequence->close(self->sequence, flags);
4849 self->sequence = NULL;
4850 MYDB_END_ALLOW_THREADS
4851
4852 RETURN_IF_ERR();
4853
4854 RETURN_NONE();
4855}
4856
4857static PyObject*
4858DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4859{
4860 int err, flags = 0;
4861 int delta = 1;
4862 db_seq_t value;
4863 PyObject *txnobj = NULL;
4864 DB_TXN *txn = NULL;
4865 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4866 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4867 return NULL;
4868 CHECK_SEQUENCE_NOT_CLOSED(self)
4869
4870 if (!checkTxnObj(txnobj, &txn))
4871 return NULL;
4872
4873 MYDB_BEGIN_ALLOW_THREADS
4874 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4875 MYDB_END_ALLOW_THREADS
4876
4877 RETURN_IF_ERR();
4878 return PyLong_FromLongLong(value);
4879
4880}
4881
4882static PyObject*
4883DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4884{
4885 if (!PyArg_ParseTuple(args,":get_dbp"))
4886 return NULL;
4887 CHECK_SEQUENCE_NOT_CLOSED(self)
4888 Py_INCREF(self->mydb);
4889 return (PyObject* )self->mydb;
4890}
4891
4892static PyObject*
4893DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4894{
4895 int err;
4896 DBT key;
Guido van Rossum8ce8a782007-11-01 19:42:39 +00004897 PyObject *retval = NULL;
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004898 key.flags = DB_DBT_MALLOC;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004899 CHECK_SEQUENCE_NOT_CLOSED(self)
4900 MYDB_BEGIN_ALLOW_THREADS
4901 err = self->sequence->get_key(self->sequence, &key);
4902 MYDB_END_ALLOW_THREADS
4903
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004904 if (!err)
4905 retval = PyBytes_FromStringAndSize(key.data, key.size);
4906
4907 free_dbt(&key);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004908 RETURN_IF_ERR();
4909
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004910 return retval;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004911}
4912
4913static PyObject*
4914DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4915{
4916 int err;
4917 db_seq_t value;
4918 if (!PyArg_ParseTuple(args,"L:init_value", &value))
4919 return NULL;
4920 CHECK_SEQUENCE_NOT_CLOSED(self)
4921
4922 MYDB_BEGIN_ALLOW_THREADS
4923 err = self->sequence->initial_value(self->sequence, value);
4924 MYDB_END_ALLOW_THREADS
4925
4926 RETURN_IF_ERR();
4927
4928 RETURN_NONE();
4929}
4930
4931static PyObject*
4932DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4933{
4934 int err, flags = 0;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004935 PyObject *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00004936 Py_buffer *key_buf_view = NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004937 PyObject *txnobj = NULL;
4938 DB_TXN *txn = NULL;
4939 DBT key;
4940
4941 static char* kwnames[] = {"key", "txn", "flags", NULL };
4942 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
4943 return NULL;
4944
4945 if (!checkTxnObj(txnobj, &txn))
4946 return NULL;
4947
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004948 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004949 return NULL;
4950
4951 MYDB_BEGIN_ALLOW_THREADS
4952 err = self->sequence->open(self->sequence, txn, &key, flags);
4953 MYDB_END_ALLOW_THREADS
4954
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004955 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004956 RETURN_IF_ERR();
4957
4958 RETURN_NONE();
4959}
4960
4961static PyObject*
4962DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4963{
4964 int err, flags = 0;
4965 PyObject *txnobj = NULL;
4966 DB_TXN *txn = NULL;
4967
4968 static char* kwnames[] = {"txn", "flags", NULL };
4969 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
4970 return NULL;
4971
4972 if (!checkTxnObj(txnobj, &txn))
4973 return NULL;
4974
4975 CHECK_SEQUENCE_NOT_CLOSED(self)
4976
4977 MYDB_BEGIN_ALLOW_THREADS
4978 err = self->sequence->remove(self->sequence, txn, flags);
4979 MYDB_END_ALLOW_THREADS
4980
4981 RETURN_IF_ERR();
4982 RETURN_NONE();
4983}
4984
4985static PyObject*
4986DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4987{
4988 int err, size;
4989 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
4990 return NULL;
4991 CHECK_SEQUENCE_NOT_CLOSED(self)
4992
4993 MYDB_BEGIN_ALLOW_THREADS
4994 err = self->sequence->set_cachesize(self->sequence, size);
4995 MYDB_END_ALLOW_THREADS
4996
4997 RETURN_IF_ERR();
4998 RETURN_NONE();
4999}
5000
5001static PyObject*
5002DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
5003{
5004 int err, size;
5005 if (!PyArg_ParseTuple(args,":get_cachesize"))
5006 return NULL;
5007 CHECK_SEQUENCE_NOT_CLOSED(self)
5008
5009 MYDB_BEGIN_ALLOW_THREADS
5010 err = self->sequence->get_cachesize(self->sequence, &size);
5011 MYDB_END_ALLOW_THREADS
5012
5013 RETURN_IF_ERR();
5014 return PyInt_FromLong(size);
5015}
5016
5017static PyObject*
5018DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5019{
5020 int err, flags = 0;
5021 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
5022 return NULL;
5023 CHECK_SEQUENCE_NOT_CLOSED(self)
5024
5025 MYDB_BEGIN_ALLOW_THREADS
5026 err = self->sequence->set_flags(self->sequence, flags);
5027 MYDB_END_ALLOW_THREADS
5028
5029 RETURN_IF_ERR();
5030 RETURN_NONE();
5031
5032}
5033
5034static PyObject*
5035DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5036{
5037 unsigned int flags;
5038 int err;
5039 if (!PyArg_ParseTuple(args,":get_flags"))
5040 return NULL;
5041 CHECK_SEQUENCE_NOT_CLOSED(self)
5042
5043 MYDB_BEGIN_ALLOW_THREADS
5044 err = self->sequence->get_flags(self->sequence, &flags);
5045 MYDB_END_ALLOW_THREADS
5046
5047 RETURN_IF_ERR();
5048 return PyInt_FromLong((int)flags);
5049}
5050
5051static PyObject*
5052DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5053{
5054 int err;
5055 db_seq_t min, max;
5056 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
5057 return NULL;
5058 CHECK_SEQUENCE_NOT_CLOSED(self)
5059
5060 MYDB_BEGIN_ALLOW_THREADS
5061 err = self->sequence->set_range(self->sequence, min, max);
5062 MYDB_END_ALLOW_THREADS
5063
5064 RETURN_IF_ERR();
5065 RETURN_NONE();
5066}
5067
5068static PyObject*
5069DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5070{
5071 int err;
5072 db_seq_t min, max;
5073 if (!PyArg_ParseTuple(args,":get_range"))
5074 return NULL;
5075 CHECK_SEQUENCE_NOT_CLOSED(self)
5076
5077 MYDB_BEGIN_ALLOW_THREADS
5078 err = self->sequence->get_range(self->sequence, &min, &max);
5079 MYDB_END_ALLOW_THREADS
5080
5081 RETURN_IF_ERR();
5082 return Py_BuildValue("(LL)", min, max);
5083}
5084
5085static PyObject*
5086DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5087{
5088 int err, flags = 0;
5089 DB_SEQUENCE_STAT* sp = NULL;
5090 PyObject* dict_stat;
5091 static char* kwnames[] = {"flags", NULL };
5092 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5093 return NULL;
5094 CHECK_SEQUENCE_NOT_CLOSED(self);
5095
5096 MYDB_BEGIN_ALLOW_THREADS;
5097 err = self->sequence->stat(self->sequence, &sp, flags);
5098 MYDB_END_ALLOW_THREADS;
5099 RETURN_IF_ERR();
5100
5101 if ((dict_stat = PyDict_New()) == NULL) {
5102 free(sp);
5103 return NULL;
5104 }
5105
5106
5107#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5108#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5109
5110 MAKE_INT_ENTRY(wait);
5111 MAKE_INT_ENTRY(nowait);
5112 MAKE_LONG_LONG_ENTRY(current);
5113 MAKE_LONG_LONG_ENTRY(value);
5114 MAKE_LONG_LONG_ENTRY(last_value);
5115 MAKE_LONG_LONG_ENTRY(min);
5116 MAKE_LONG_LONG_ENTRY(max);
5117 MAKE_INT_ENTRY(cache_size);
5118 MAKE_INT_ENTRY(flags);
5119
5120#undef MAKE_INT_ENTRY
5121#undef MAKE_LONG_LONG_ENTRY
5122
5123 free(sp);
5124 return dict_stat;
5125}
5126#endif
5127
5128
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005129/* --------------------------------------------------------------------- */
5130/* Method definition tables and type objects */
5131
5132static PyMethodDef DB_methods[] = {
5133 {"append", (PyCFunction)DB_append, METH_VARARGS},
5134#if (DBVER >= 33)
5135 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5136#endif
5137 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005138 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5139 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005140 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5141 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5142 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5143 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005144#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005145 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005146#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005147 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5148 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5149 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5150 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5151 {"join", (PyCFunction)DB_join, METH_VARARGS},
5152 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5153 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5154 {"items", (PyCFunction)DB_items, METH_VARARGS},
5155 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5156 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5157 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5158 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5159 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5160 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005161#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005162 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005163#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005164 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005165#if (DBVER >= 41)
5166 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5167#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005168 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5169 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5170 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5171 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5172 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5173 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5174 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5175 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5176 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005177 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005178 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005179 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5180#if (DBVER >= 33)
5181 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5182#endif
5183 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5184 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5185 {"values", (PyCFunction)DB_values, METH_VARARGS},
5186 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5187 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5188 {NULL, NULL} /* sentinel */
5189};
5190
5191
5192static PyMappingMethods DB_mapping = {
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005193 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005194 (binaryfunc)DB_subscript, /*mp_subscript*/
5195 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5196};
5197
5198
5199static PyMethodDef DBCursor_methods[] = {
5200 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5201 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5202 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5203 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5204 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5205 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5206 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005207#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005208 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005209#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005210 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5211 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5212 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5213 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5214 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5215 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5216 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5217 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005218 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005219 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005220 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5221 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5222 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5223 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5224 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5225 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5226 {NULL, NULL} /* sentinel */
5227};
5228
5229
5230static PyMethodDef DBEnv_methods[] = {
5231 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5232 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5233 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005234#if (DBVER >= 41)
5235 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5236 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5237 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5238#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005239#if (DBVER >= 40)
5240 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5241#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005242 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005243 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5244 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005245 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005246 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5247 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5248 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005249#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005250 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005251#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005252 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005253#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005254 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005255#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005256 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5257 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5258 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005259 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5260 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5261 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5262 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5263 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5264 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005265 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005266 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5267 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5268 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5269 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5270 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5271 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005272#if (DBVER >= 40)
5273 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5274#endif
5275#if (DBVER >= 44)
5276 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5277#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005278 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5279 {NULL, NULL} /* sentinel */
5280};
5281
5282
5283static PyMethodDef DBTxn_methods[] = {
5284 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5285 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5286 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5287 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5288 {NULL, NULL} /* sentinel */
5289};
5290
5291
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005292#if (DBVER >= 43)
5293static PyMethodDef DBSequence_methods[] = {
5294 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5295 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5296 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5297 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5298 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5299 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5300 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5301 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5302 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5303 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5304 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5305 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5306 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5307 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5308 {NULL, NULL} /* sentinel */
5309};
5310#endif
5311
5312
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005313static PyObject*
5314DB_getattr(DBObject* self, char *name)
5315{
5316 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5317}
5318
5319
5320static PyObject*
5321DBEnv_getattr(DBEnvObject* self, char *name)
5322{
5323 if (!strcmp(name, "db_home")) {
5324 CHECK_ENV_NOT_CLOSED(self);
5325 if (self->db_env->db_home == NULL) {
5326 RETURN_NONE();
5327 }
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005328 return PyUnicode_FromString(self->db_env->db_home);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005329 }
5330
5331 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5332}
5333
5334
5335static PyObject*
5336DBCursor_getattr(DBCursorObject* self, char *name)
5337{
5338 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5339}
5340
5341static PyObject*
5342DBTxn_getattr(DBTxnObject* self, char *name)
5343{
5344 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5345}
5346
5347static PyObject*
5348DBLock_getattr(DBLockObject* self, char *name)
5349{
5350 return NULL;
5351}
5352
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005353#if (DBVER >= 43)
5354static PyObject*
5355DBSequence_getattr(DBSequenceObject* self, char *name)
5356{
5357 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5358}
5359#endif
5360
Neal Norwitz227b5332006-03-22 09:28:35 +00005361static PyTypeObject DB_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005362 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005363 "DB", /*tp_name*/
5364 sizeof(DBObject), /*tp_basicsize*/
5365 0, /*tp_itemsize*/
5366 /* methods */
5367 (destructor)DB_dealloc, /*tp_dealloc*/
5368 0, /*tp_print*/
5369 (getattrfunc)DB_getattr, /*tp_getattr*/
5370 0, /*tp_setattr*/
5371 0, /*tp_compare*/
5372 0, /*tp_repr*/
5373 0, /*tp_as_number*/
5374 0, /*tp_as_sequence*/
5375 &DB_mapping,/*tp_as_mapping*/
5376 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005377 0, /* tp_call */
5378 0, /* tp_str */
5379 0, /* tp_getattro */
5380 0, /* tp_setattro */
5381 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005382 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005383 0, /* tp_doc */
5384 0, /* tp_traverse */
5385 0, /* tp_clear */
5386 0, /* tp_richcompare */
5387 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005388};
5389
5390
Neal Norwitz227b5332006-03-22 09:28:35 +00005391static PyTypeObject DBCursor_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005392 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005393 "DBCursor", /*tp_name*/
5394 sizeof(DBCursorObject), /*tp_basicsize*/
5395 0, /*tp_itemsize*/
5396 /* methods */
5397 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5398 0, /*tp_print*/
5399 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5400 0, /*tp_setattr*/
5401 0, /*tp_compare*/
5402 0, /*tp_repr*/
5403 0, /*tp_as_number*/
5404 0, /*tp_as_sequence*/
5405 0, /*tp_as_mapping*/
5406 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005407 0, /* tp_call */
5408 0, /* tp_str */
5409 0, /* tp_getattro */
5410 0, /* tp_setattro */
5411 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005412 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smitha703a212003-11-03 01:04:41 +00005413 0, /* tp_doc */
5414 0, /* tp_traverse */
5415 0, /* tp_clear */
5416 0, /* tp_richcompare */
5417 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005418};
5419
5420
Neal Norwitz227b5332006-03-22 09:28:35 +00005421static PyTypeObject DBEnv_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005422 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005423 "DBEnv", /*tp_name*/
5424 sizeof(DBEnvObject), /*tp_basicsize*/
5425 0, /*tp_itemsize*/
5426 /* methods */
5427 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5428 0, /*tp_print*/
5429 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5430 0, /*tp_setattr*/
5431 0, /*tp_compare*/
5432 0, /*tp_repr*/
5433 0, /*tp_as_number*/
5434 0, /*tp_as_sequence*/
5435 0, /*tp_as_mapping*/
5436 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005437 0, /* tp_call */
5438 0, /* tp_str */
5439 0, /* tp_getattro */
5440 0, /* tp_setattro */
5441 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005442 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005443 0, /* tp_doc */
5444 0, /* tp_traverse */
5445 0, /* tp_clear */
5446 0, /* tp_richcompare */
5447 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005448};
5449
Neal Norwitz227b5332006-03-22 09:28:35 +00005450static PyTypeObject DBTxn_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005451 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005452 "DBTxn", /*tp_name*/
5453 sizeof(DBTxnObject), /*tp_basicsize*/
5454 0, /*tp_itemsize*/
5455 /* methods */
5456 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5457 0, /*tp_print*/
5458 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5459 0, /*tp_setattr*/
5460 0, /*tp_compare*/
5461 0, /*tp_repr*/
5462 0, /*tp_as_number*/
5463 0, /*tp_as_sequence*/
5464 0, /*tp_as_mapping*/
5465 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005466 0, /* tp_call */
5467 0, /* tp_str */
5468 0, /* tp_getattro */
5469 0, /* tp_setattro */
5470 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005471 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005472 0, /* tp_doc */
5473 0, /* tp_traverse */
5474 0, /* tp_clear */
5475 0, /* tp_richcompare */
5476 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005477};
5478
5479
Neal Norwitz227b5332006-03-22 09:28:35 +00005480static PyTypeObject DBLock_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005481 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005482 "DBLock", /*tp_name*/
5483 sizeof(DBLockObject), /*tp_basicsize*/
5484 0, /*tp_itemsize*/
5485 /* methods */
5486 (destructor)DBLock_dealloc, /*tp_dealloc*/
5487 0, /*tp_print*/
5488 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5489 0, /*tp_setattr*/
5490 0, /*tp_compare*/
5491 0, /*tp_repr*/
5492 0, /*tp_as_number*/
5493 0, /*tp_as_sequence*/
5494 0, /*tp_as_mapping*/
5495 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005496 0, /* tp_call */
5497 0, /* tp_str */
5498 0, /* tp_getattro */
5499 0, /* tp_setattro */
5500 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005501 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005502 0, /* tp_doc */
5503 0, /* tp_traverse */
5504 0, /* tp_clear */
5505 0, /* tp_richcompare */
5506 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005507};
5508
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005509#if (DBVER >= 43)
5510static PyTypeObject DBSequence_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005511 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005512 "DBSequence", /*tp_name*/
5513 sizeof(DBSequenceObject), /*tp_basicsize*/
5514 0, /*tp_itemsize*/
5515 /* methods */
5516 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5517 0, /*tp_print*/
5518 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5519 0, /*tp_setattr*/
5520 0, /*tp_compare*/
5521 0, /*tp_repr*/
5522 0, /*tp_as_number*/
5523 0, /*tp_as_sequence*/
5524 0, /*tp_as_mapping*/
5525 0, /*tp_hash*/
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005526 0, /* tp_call */
5527 0, /* tp_str */
5528 0, /* tp_getattro */
5529 0, /* tp_setattro */
5530 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005531 Py_TPFLAGS_DEFAULT, /* tp_flags */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005532 0, /* tp_doc */
5533 0, /* tp_traverse */
5534 0, /* tp_clear */
5535 0, /* tp_richcompare */
5536 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005537};
5538#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005539
5540/* --------------------------------------------------------------------- */
5541/* Module-level functions */
5542
5543static PyObject*
5544DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5545{
5546 PyObject* dbenvobj = NULL;
5547 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005548 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005549
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005550 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5551 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005552 return NULL;
5553 if (dbenvobj == Py_None)
5554 dbenvobj = NULL;
5555 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5556 makeTypeError("DBEnv", dbenvobj);
5557 return NULL;
5558 }
5559
5560 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5561}
5562
5563
5564static PyObject*
5565DBEnv_construct(PyObject* self, PyObject* args)
5566{
5567 int flags = 0;
5568 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5569 return (PyObject* )newDBEnvObject(flags);
5570}
5571
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005572#if (DBVER >= 43)
5573static PyObject*
5574DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5575{
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005576 PyObject* dbobj;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005577 int flags = 0;
5578 static char* kwnames[] = { "db", "flags", NULL};
5579
5580 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5581 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005582 if (!DBObject_Check(dbobj)) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005583 makeTypeError("DB", dbobj);
5584 return NULL;
5585 }
5586 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5587}
5588#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005589
5590static char bsddb_version_doc[] =
5591"Returns a tuple of major, minor, and patch release numbers of the\n\
5592underlying DB library.";
5593
5594static PyObject*
5595bsddb_version(PyObject* self, PyObject* args)
5596{
5597 int major, minor, patch;
5598
5599 if (!PyArg_ParseTuple(args, ":version"))
5600 return NULL;
5601 db_version(&major, &minor, &patch);
5602 return Py_BuildValue("(iii)", major, minor, patch);
5603}
5604
5605
5606/* List of functions defined in the module */
5607
5608static PyMethodDef bsddb_methods[] = {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005609 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5610 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5611#if (DBVER >= 43)
5612 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5613#endif
5614 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005615 {NULL, NULL} /* sentinel */
5616};
5617
Guido van Rossum8ce8a782007-11-01 19:42:39 +00005618/* API structure */
5619static BSDDB_api bsddb_api;
5620
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005621
5622/* --------------------------------------------------------------------- */
5623/* Module initialization */
5624
5625
5626/* Convenience routine to export an integer value.
5627 * Errors are silently ignored, for better or for worse...
5628 */
5629#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5630
Gregory P. Smith41631e82003-09-21 00:08:14 +00005631#define MODULE_NAME_MAX_LEN 11
5632static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005633
Neal Norwitzf6657e62006-12-28 04:47:50 +00005634PyMODINIT_FUNC init_bsddb(void)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005635{
5636 PyObject* m;
5637 PyObject* d;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005638 PyObject* pybsddb_version_s = PyUnicode_FromString(PY_BSDDB_VERSION);
5639 PyObject* db_version_s = PyUnicode_FromString(DB_VERSION_STRING);
5640 PyObject* svnid_s = PyUnicode_FromString(svn_id);
Guido van Rossum8ce8a782007-11-01 19:42:39 +00005641 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005642
5643 /* Initialize the type of the new type objects here; doing it here
5644 is required for portability to Windows without requiring C++. */
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005645 Py_Type(&DB_Type) = &PyType_Type;
5646 Py_Type(&DBCursor_Type) = &PyType_Type;
5647 Py_Type(&DBEnv_Type) = &PyType_Type;
5648 Py_Type(&DBTxn_Type) = &PyType_Type;
5649 Py_Type(&DBLock_Type) = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005650#if (DBVER >= 43)
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005651 Py_Type(&DBSequence_Type) = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005652#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005653
5654
Mark Hammonda69d4092003-04-22 23:13:27 +00005655#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005656 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005657 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005658#endif
5659
5660 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005661 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005662 if (m == NULL)
5663 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005664
5665 /* Add some symbolic constants to the module */
5666 d = PyModule_GetDict(m);
5667 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005668 PyDict_SetItemString(d, "cvsid", svnid_s);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005669 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5670 Py_DECREF(pybsddb_version_s);
5671 pybsddb_version_s = NULL;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005672 Py_DECREF(svnid_s);
5673 svnid_s = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005674 Py_DECREF(db_version_s);
5675 db_version_s = NULL;
5676
5677 ADD_INT(d, DB_VERSION_MAJOR);
5678 ADD_INT(d, DB_VERSION_MINOR);
5679 ADD_INT(d, DB_VERSION_PATCH);
5680
5681 ADD_INT(d, DB_MAX_PAGES);
5682 ADD_INT(d, DB_MAX_RECORDS);
5683
Gregory P. Smith41631e82003-09-21 00:08:14 +00005684#if (DBVER >= 42)
5685 ADD_INT(d, DB_RPCCLIENT);
5686#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005687 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005688 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5689 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5690#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005691 ADD_INT(d, DB_XA_CREATE);
5692
5693 ADD_INT(d, DB_CREATE);
5694 ADD_INT(d, DB_NOMMAP);
5695 ADD_INT(d, DB_THREAD);
5696
5697 ADD_INT(d, DB_FORCE);
5698 ADD_INT(d, DB_INIT_CDB);
5699 ADD_INT(d, DB_INIT_LOCK);
5700 ADD_INT(d, DB_INIT_LOG);
5701 ADD_INT(d, DB_INIT_MPOOL);
5702 ADD_INT(d, DB_INIT_TXN);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005703 ADD_INT(d, DB_JOINENV);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005704
5705 ADD_INT(d, DB_RECOVER);
5706 ADD_INT(d, DB_RECOVER_FATAL);
5707 ADD_INT(d, DB_TXN_NOSYNC);
5708 ADD_INT(d, DB_USE_ENVIRON);
5709 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5710
5711 ADD_INT(d, DB_LOCKDOWN);
5712 ADD_INT(d, DB_PRIVATE);
5713 ADD_INT(d, DB_SYSTEM_MEM);
5714
5715 ADD_INT(d, DB_TXN_SYNC);
5716 ADD_INT(d, DB_TXN_NOWAIT);
5717
5718 ADD_INT(d, DB_EXCL);
5719 ADD_INT(d, DB_FCNTL_LOCKING);
5720 ADD_INT(d, DB_ODDFILESIZE);
5721 ADD_INT(d, DB_RDWRMASTER);
5722 ADD_INT(d, DB_RDONLY);
5723 ADD_INT(d, DB_TRUNCATE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005724 ADD_INT(d, DB_EXTENT);
5725 ADD_INT(d, DB_CDB_ALLDB);
5726 ADD_INT(d, DB_VERIFY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005727 ADD_INT(d, DB_UPGRADE);
5728
5729 ADD_INT(d, DB_AGGRESSIVE);
5730 ADD_INT(d, DB_NOORDERCHK);
5731 ADD_INT(d, DB_ORDERCHKONLY);
5732 ADD_INT(d, DB_PR_PAGE);
5733#if ! (DBVER >= 33)
5734 ADD_INT(d, DB_VRFY_FLAGMASK);
5735 ADD_INT(d, DB_PR_HEADERS);
5736#endif
5737 ADD_INT(d, DB_PR_RECOVERYTEST);
5738 ADD_INT(d, DB_SALVAGE);
5739
5740 ADD_INT(d, DB_LOCK_NORUN);
5741 ADD_INT(d, DB_LOCK_DEFAULT);
5742 ADD_INT(d, DB_LOCK_OLDEST);
5743 ADD_INT(d, DB_LOCK_RANDOM);
5744 ADD_INT(d, DB_LOCK_YOUNGEST);
5745#if (DBVER >= 33)
5746 ADD_INT(d, DB_LOCK_MAXLOCKS);
5747 ADD_INT(d, DB_LOCK_MINLOCKS);
5748 ADD_INT(d, DB_LOCK_MINWRITE);
5749#endif
5750
5751
5752#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005753 /* docs say to use zero instead */
5754 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005755#else
5756 ADD_INT(d, DB_LOCK_CONFLICT);
5757#endif
5758
5759 ADD_INT(d, DB_LOCK_DUMP);
5760 ADD_INT(d, DB_LOCK_GET);
5761 ADD_INT(d, DB_LOCK_INHERIT);
5762 ADD_INT(d, DB_LOCK_PUT);
5763 ADD_INT(d, DB_LOCK_PUT_ALL);
5764 ADD_INT(d, DB_LOCK_PUT_OBJ);
5765
5766 ADD_INT(d, DB_LOCK_NG);
5767 ADD_INT(d, DB_LOCK_READ);
5768 ADD_INT(d, DB_LOCK_WRITE);
5769 ADD_INT(d, DB_LOCK_NOWAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005770 ADD_INT(d, DB_LOCK_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005771 ADD_INT(d, DB_LOCK_IWRITE);
5772 ADD_INT(d, DB_LOCK_IREAD);
5773 ADD_INT(d, DB_LOCK_IWR);
5774#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005775#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005776 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005777#else
5778 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5779#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005780 ADD_INT(d, DB_LOCK_WWRITE);
5781#endif
5782
5783 ADD_INT(d, DB_LOCK_RECORD);
5784 ADD_INT(d, DB_LOCK_UPGRADE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005785 ADD_INT(d, DB_LOCK_SWITCH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005786#if (DBVER >= 33)
5787 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5788#endif
5789
5790 ADD_INT(d, DB_LOCK_NOWAIT);
5791 ADD_INT(d, DB_LOCK_RECORD);
5792 ADD_INT(d, DB_LOCK_UPGRADE);
5793
5794#if (DBVER >= 33)
5795 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005796#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005797 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005798#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005799 ADD_INT(d, DB_LSTAT_FREE);
5800 ADD_INT(d, DB_LSTAT_HELD);
5801#if (DBVER == 33)
5802 ADD_INT(d, DB_LSTAT_NOGRANT);
5803#endif
5804 ADD_INT(d, DB_LSTAT_PENDING);
5805 ADD_INT(d, DB_LSTAT_WAITING);
5806#endif
5807
5808 ADD_INT(d, DB_ARCH_ABS);
5809 ADD_INT(d, DB_ARCH_DATA);
5810 ADD_INT(d, DB_ARCH_LOG);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005811#if (DBVER >= 42)
5812 ADD_INT(d, DB_ARCH_REMOVE);
5813#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005814
5815 ADD_INT(d, DB_BTREE);
5816 ADD_INT(d, DB_HASH);
5817 ADD_INT(d, DB_RECNO);
5818 ADD_INT(d, DB_QUEUE);
5819 ADD_INT(d, DB_UNKNOWN);
5820
5821 ADD_INT(d, DB_DUP);
5822 ADD_INT(d, DB_DUPSORT);
5823 ADD_INT(d, DB_RECNUM);
5824 ADD_INT(d, DB_RENUMBER);
5825 ADD_INT(d, DB_REVSPLITOFF);
5826 ADD_INT(d, DB_SNAPSHOT);
5827
5828 ADD_INT(d, DB_JOIN_NOSORT);
5829
5830 ADD_INT(d, DB_AFTER);
5831 ADD_INT(d, DB_APPEND);
5832 ADD_INT(d, DB_BEFORE);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005833#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005834 ADD_INT(d, DB_CACHED_COUNTS);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005835#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005836#if (DBVER >= 41)
5837 _addIntToDict(d, "DB_CHECKPOINT", 0);
5838#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005839 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005840 ADD_INT(d, DB_CURLSN);
5841#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005842#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005843 ADD_INT(d, DB_COMMIT);
5844#endif
5845 ADD_INT(d, DB_CONSUME);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005846 ADD_INT(d, DB_CONSUME_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005847 ADD_INT(d, DB_CURRENT);
5848#if (DBVER >= 33)
5849 ADD_INT(d, DB_FAST_STAT);
5850#endif
5851 ADD_INT(d, DB_FIRST);
5852 ADD_INT(d, DB_FLUSH);
5853 ADD_INT(d, DB_GET_BOTH);
5854 ADD_INT(d, DB_GET_RECNO);
5855 ADD_INT(d, DB_JOIN_ITEM);
5856 ADD_INT(d, DB_KEYFIRST);
5857 ADD_INT(d, DB_KEYLAST);
5858 ADD_INT(d, DB_LAST);
5859 ADD_INT(d, DB_NEXT);
5860 ADD_INT(d, DB_NEXT_DUP);
5861 ADD_INT(d, DB_NEXT_NODUP);
5862 ADD_INT(d, DB_NODUPDATA);
5863 ADD_INT(d, DB_NOOVERWRITE);
5864 ADD_INT(d, DB_NOSYNC);
5865 ADD_INT(d, DB_POSITION);
5866 ADD_INT(d, DB_PREV);
5867 ADD_INT(d, DB_PREV_NODUP);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005868#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005869 ADD_INT(d, DB_RECORDCOUNT);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005870#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005871 ADD_INT(d, DB_SET);
5872 ADD_INT(d, DB_SET_RANGE);
5873 ADD_INT(d, DB_SET_RECNO);
5874 ADD_INT(d, DB_WRITECURSOR);
5875
5876 ADD_INT(d, DB_OPFLAGS_MASK);
5877 ADD_INT(d, DB_RMW);
5878#if (DBVER >= 33)
5879 ADD_INT(d, DB_DIRTY_READ);
5880 ADD_INT(d, DB_MULTIPLE);
5881 ADD_INT(d, DB_MULTIPLE_KEY);
5882#endif
5883
Gregory P. Smith29602d22006-01-24 09:46:48 +00005884#if (DBVER >= 44)
5885 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5886 ADD_INT(d, DB_READ_COMMITTED);
5887#endif
5888
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005889#if (DBVER >= 33)
5890 ADD_INT(d, DB_DONOTINDEX);
Gregory P. Smith361ed152007-08-23 07:32:27 +00005891 ADD_INT(d, DB_XIDDATASIZE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005892#endif
5893
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005894#if (DBVER >= 41)
5895 _addIntToDict(d, "DB_INCOMPLETE", 0);
5896#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005897 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005898#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005899 ADD_INT(d, DB_KEYEMPTY);
5900 ADD_INT(d, DB_KEYEXIST);
5901 ADD_INT(d, DB_LOCK_DEADLOCK);
5902 ADD_INT(d, DB_LOCK_NOTGRANTED);
5903 ADD_INT(d, DB_NOSERVER);
5904 ADD_INT(d, DB_NOSERVER_HOME);
5905 ADD_INT(d, DB_NOSERVER_ID);
5906 ADD_INT(d, DB_NOTFOUND);
5907 ADD_INT(d, DB_OLD_VERSION);
5908 ADD_INT(d, DB_RUNRECOVERY);
5909 ADD_INT(d, DB_VERIFY_BAD);
5910#if (DBVER >= 33)
5911 ADD_INT(d, DB_PAGE_NOTFOUND);
5912 ADD_INT(d, DB_SECONDARY_BAD);
5913#endif
5914#if (DBVER >= 40)
5915 ADD_INT(d, DB_STAT_CLEAR);
5916 ADD_INT(d, DB_REGION_INIT);
5917 ADD_INT(d, DB_NOLOCKING);
5918 ADD_INT(d, DB_YIELDCPU);
5919 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5920 ADD_INT(d, DB_NOPANIC);
5921#endif
5922
Gregory P. Smith41631e82003-09-21 00:08:14 +00005923#if (DBVER >= 42)
5924 ADD_INT(d, DB_TIME_NOTGRANTED);
5925 ADD_INT(d, DB_TXN_NOT_DURABLE);
5926 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5927 ADD_INT(d, DB_LOG_AUTOREMOVE);
5928 ADD_INT(d, DB_DIRECT_LOG);
5929 ADD_INT(d, DB_DIRECT_DB);
5930 ADD_INT(d, DB_INIT_REP);
5931 ADD_INT(d, DB_ENCRYPT);
5932 ADD_INT(d, DB_CHKSUM);
5933#endif
5934
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005935#if (DBVER >= 43)
5936 ADD_INT(d, DB_LOG_INMEMORY);
5937 ADD_INT(d, DB_BUFFER_SMALL);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005938 ADD_INT(d, DB_SEQ_DEC);
5939 ADD_INT(d, DB_SEQ_INC);
5940 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005941#endif
5942
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005943#if (DBVER >= 41)
5944 ADD_INT(d, DB_ENCRYPT_AES);
5945 ADD_INT(d, DB_AUTO_COMMIT);
5946#else
5947 /* allow berkeleydb 4.1 aware apps to run on older versions */
5948 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5949#endif
5950
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005951 ADD_INT(d, EINVAL);
5952 ADD_INT(d, EACCES);
5953 ADD_INT(d, ENOSPC);
5954 ADD_INT(d, ENOMEM);
5955 ADD_INT(d, EAGAIN);
5956 ADD_INT(d, EBUSY);
5957 ADD_INT(d, EEXIST);
5958 ADD_INT(d, ENOENT);
5959 ADD_INT(d, EPERM);
5960
Barry Warsaw1baa9822003-03-31 19:51:29 +00005961#if (DBVER >= 40)
5962 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5963 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5964#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005965
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005966 /* The exception name must be correct for pickled exception *
5967 * objects to unpickle properly. */
5968#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5969#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5970#else
5971#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5972#endif
5973
5974 /* All the rest of the exceptions derive only from DBError */
5975#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5976 PyDict_SetItemString(d, #name, name)
5977
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005978 /* The base exception class is DBError */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005979 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5980 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005981
Gregory P. Smithe9477062005-06-04 06:46:59 +00005982 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5983 * from both DBError and KeyError, since the API only supports
5984 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005985 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Guido van Rossum52cc1d82007-03-18 15:41:51 +00005986 {
5987 PyObject *builtin_mod = PyImport_ImportModule("__builtin__");
5988 PyDict_SetItemString(d, "__builtins__", builtin_mod);
5989 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00005990 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5991 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005992 Py_file_input, d, d);
5993 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005994 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005995 PyDict_DelItemString(d, "KeyError");
5996
5997
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005998#if !INCOMPLETE_IS_WARNING
5999 MAKE_EX(DBIncompleteError);
6000#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00006001 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006002 MAKE_EX(DBKeyEmptyError);
6003 MAKE_EX(DBKeyExistError);
6004 MAKE_EX(DBLockDeadlockError);
6005 MAKE_EX(DBLockNotGrantedError);
6006 MAKE_EX(DBOldVersionError);
6007 MAKE_EX(DBRunRecoveryError);
6008 MAKE_EX(DBVerifyBadError);
6009 MAKE_EX(DBNoServerError);
6010 MAKE_EX(DBNoServerHomeError);
6011 MAKE_EX(DBNoServerIDError);
6012#if (DBVER >= 33)
6013 MAKE_EX(DBPageNotFoundError);
6014 MAKE_EX(DBSecondaryBadError);
6015#endif
6016
6017 MAKE_EX(DBInvalidArgError);
6018 MAKE_EX(DBAccessError);
6019 MAKE_EX(DBNoSpaceError);
6020 MAKE_EX(DBNoMemoryError);
6021 MAKE_EX(DBAgainError);
6022 MAKE_EX(DBBusyError);
6023 MAKE_EX(DBFileExistsError);
6024 MAKE_EX(DBNoSuchFileError);
6025 MAKE_EX(DBPermissionsError);
6026
6027#undef MAKE_EX
6028
Guido van Rossum8ce8a782007-11-01 19:42:39 +00006029 /* Initiliase the C API structure and add it to the module */
6030 bsddb_api.db_type = &DB_Type;
6031 bsddb_api.dbcursor_type = &DBCursor_Type;
6032 bsddb_api.dbenv_type = &DBEnv_Type;
6033 bsddb_api.dbtxn_type = &DBTxn_Type;
6034 bsddb_api.dblock_type = &DBLock_Type;
6035#if (DBVER >= 43)
6036 bsddb_api.dbsequence_type = &DBSequence_Type;
6037#endif
6038 bsddb_api.makeDBError = makeDBError;
6039
6040 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
6041 PyDict_SetItemString(d, "api", py_api);
6042 Py_DECREF(py_api);
6043
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006044 /* Check for errors */
6045 if (PyErr_Occurred()) {
6046 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006047 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006048 }
6049}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006050
6051/* allow this module to be named _pybsddb so that it can be installed
6052 * and imported on top of python >= 2.3 that includes its own older
6053 * copy of the library named _bsddb without importing the old version. */
Neal Norwitzf6657e62006-12-28 04:47:50 +00006054PyMODINIT_FUNC init_pybsddb(void)
Gregory P. Smith41631e82003-09-21 00:08:14 +00006055{
6056 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6057 init_bsddb();
6058}