blob: bd1c271090f6612cdb60d1947034221ef0ccca70 [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
1943 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001944#if (DBVER >= 41)
1945 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1946#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001947 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001948#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001949 MYDB_END_ALLOW_THREADS;
1950 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001951 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001952 self->db = NULL;
1953 return NULL;
1954 }
1955
Guido van Rossum77677112007-11-05 19:43:04 +00001956#if (DBVER >= 42)
1957 self->db->get_flags(self->db, &self->setflags);
1958#endif
1959
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001960 self->flags = flags;
1961 RETURN_NONE();
1962}
1963
1964
1965static PyObject*
1966DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1967{
1968 int flags=0;
1969 PyObject* txnobj = NULL;
1970 int dlen = -1;
1971 int doff = -1;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001972 PyObject *keyobj, *dataobj, *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00001973 Py_buffer *data_buf_view = NULL;
1974 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001975 DBT key, data;
1976 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001977 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001978 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001979
1980 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1981 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1982 return NULL;
1983
1984 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001985 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001986 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001987 if ( !make_dbt(dataobj, &data, &data_buf_view) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001988 !add_partial_dbt(&data, dlen, doff) ||
1989 !checkTxnObj(txnobj, &txn) )
1990 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001991 FREE_DBT_VIEW(key, keyobj, key_buf_view);
1992 free_buf_view(dataobj, data_buf_view);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001993 return NULL;
1994 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001995
1996 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001997 FREE_DBT_VIEW(key, keyobj, key_buf_view);
1998 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001999 return NULL;
2000 }
2001
2002 if (flags & DB_APPEND)
2003 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2004 else {
2005 retval = Py_None;
2006 Py_INCREF(retval);
2007 }
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 retval;
2011}
2012
2013
2014
2015static PyObject*
2016DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2017{
2018 char* filename;
2019 char* database = NULL;
2020 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002021 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002022
2023 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2024 &filename, &database, &flags))
2025 return NULL;
2026 CHECK_DB_NOT_CLOSED(self);
2027
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002028 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002029 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002030 RETURN_IF_ERR();
2031 RETURN_NONE();
2032}
2033
2034
2035
2036static PyObject*
2037DB_rename(DBObject* self, PyObject* args)
2038{
2039 char* filename;
2040 char* database;
2041 char* newname;
2042 int err, flags=0;
2043
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002044 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2045 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002046 return NULL;
2047 CHECK_DB_NOT_CLOSED(self);
2048
2049 MYDB_BEGIN_ALLOW_THREADS;
2050 err = self->db->rename(self->db, filename, database, newname, flags);
2051 MYDB_END_ALLOW_THREADS;
2052 RETURN_IF_ERR();
2053 RETURN_NONE();
2054}
2055
2056
2057static PyObject*
2058DB_set_bt_minkey(DBObject* self, PyObject* args)
2059{
2060 int err, minkey;
2061
2062 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2063 return NULL;
2064 CHECK_DB_NOT_CLOSED(self);
2065
2066 MYDB_BEGIN_ALLOW_THREADS;
2067 err = self->db->set_bt_minkey(self->db, minkey);
2068 MYDB_END_ALLOW_THREADS;
2069 RETURN_IF_ERR();
2070 RETURN_NONE();
2071}
2072
Neal Norwitz84562352005-10-20 04:30:15 +00002073#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002074static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002075_default_cmp(const DBT *leftKey,
2076 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002077{
2078 int res;
2079 int lsize = leftKey->size, rsize = rightKey->size;
2080
Georg Brandlef1701f2006-03-07 14:57:48 +00002081 res = memcmp(leftKey->data, rightKey->data,
2082 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002083
2084 if (res == 0) {
2085 if (lsize < rsize) {
2086 res = -1;
2087 }
2088 else if (lsize > rsize) {
2089 res = 1;
2090 }
2091 }
2092 return res;
2093}
2094
2095static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002096_db_compareCallback(DB* db,
2097 const DBT *leftKey,
2098 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002099{
2100 int res = 0;
2101 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002102 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002103 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002104
2105 if (self == NULL || self->btCompareCallback == NULL) {
2106 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002107 PyErr_SetString(PyExc_TypeError,
2108 (self == 0
2109 ? "DB_bt_compare db is NULL."
2110 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002111 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002112 PyErr_Print();
2113 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002114 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002115 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002116 MYDB_BEGIN_BLOCK_THREADS;
2117
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002118 args = Py_BuildValue("y#y#", leftKey->data, leftKey->size,
Thomas Woutersb3153832006-03-08 01:47:19 +00002119 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002120 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002121 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002122 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002123 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002124 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002125 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002126 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002127 PyErr_Print();
2128 res = _default_cmp(leftKey, rightKey);
2129 } else if (PyInt_Check(result)) {
2130 res = PyInt_AsLong(result);
2131 } else {
2132 PyErr_SetString(PyExc_TypeError,
2133 "DB_bt_compare callback MUST return an int.");
2134 /* we're in a callback within the DB code, we can't raise */
2135 PyErr_Print();
2136 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002137 }
2138
Thomas Woutersb3153832006-03-08 01:47:19 +00002139 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002140 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002141
2142 MYDB_END_BLOCK_THREADS;
2143 }
2144 return res;
2145}
2146
2147static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002148DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002149{
2150 int err;
2151 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002152 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002153
Georg Brandlef1701f2006-03-07 14:57:48 +00002154 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002155 return NULL;
2156
Georg Brandlef1701f2006-03-07 14:57:48 +00002157 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002158
Georg Brandlef1701f2006-03-07 14:57:48 +00002159 if (!PyCallable_Check(comparator)) {
2160 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002161 return NULL;
2162 }
2163
2164 /*
2165 * Perform a test call of the comparator function with two empty
2166 * string objects here. verify that it returns an int (0).
2167 * err if not.
2168 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002169 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002170 result = PyEval_CallObject(comparator, tuple);
2171 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002172 if (result == NULL)
2173 return NULL;
2174 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002175 PyErr_SetString(PyExc_TypeError,
2176 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002177 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002178 } else if (PyInt_AsLong(result) != 0) {
2179 PyErr_SetString(PyExc_TypeError,
2180 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002181 return NULL;
2182 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002183 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002184
2185 /* We don't accept multiple set_bt_compare operations, in order to
2186 * simplify the code. This would have no real use, as one cannot
2187 * change the function once the db is opened anyway */
2188 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002189 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002190 return NULL;
2191 }
2192
Georg Brandlef1701f2006-03-07 14:57:48 +00002193 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002194 self->btCompareCallback = comparator;
2195
2196 /* This is to workaround a problem with un-initialized threads (see
2197 comment in DB_associate) */
2198#ifdef WITH_THREAD
2199 PyEval_InitThreads();
2200#endif
2201
Thomas Woutersb3153832006-03-08 01:47:19 +00002202 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002203
2204 if (err) {
2205 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002206 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002207 self->btCompareCallback = NULL;
2208 }
2209
Georg Brandlef1701f2006-03-07 14:57:48 +00002210 RETURN_IF_ERR();
2211 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002212}
Neal Norwitz84562352005-10-20 04:30:15 +00002213#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002214
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002215
2216static PyObject*
2217DB_set_cachesize(DBObject* self, PyObject* args)
2218{
2219 int err;
2220 int gbytes = 0, bytes = 0, ncache = 0;
2221
2222 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2223 &gbytes,&bytes,&ncache))
2224 return NULL;
2225 CHECK_DB_NOT_CLOSED(self);
2226
2227 MYDB_BEGIN_ALLOW_THREADS;
2228 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2229 MYDB_END_ALLOW_THREADS;
2230 RETURN_IF_ERR();
2231 RETURN_NONE();
2232}
2233
2234
2235static PyObject*
2236DB_set_flags(DBObject* self, PyObject* args)
2237{
2238 int err, flags;
2239
2240 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2241 return NULL;
2242 CHECK_DB_NOT_CLOSED(self);
2243
2244 MYDB_BEGIN_ALLOW_THREADS;
2245 err = self->db->set_flags(self->db, flags);
2246 MYDB_END_ALLOW_THREADS;
2247 RETURN_IF_ERR();
2248
2249 self->setflags |= flags;
2250 RETURN_NONE();
2251}
2252
2253
2254static PyObject*
2255DB_set_h_ffactor(DBObject* self, PyObject* args)
2256{
2257 int err, ffactor;
2258
2259 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2260 return NULL;
2261 CHECK_DB_NOT_CLOSED(self);
2262
2263 MYDB_BEGIN_ALLOW_THREADS;
2264 err = self->db->set_h_ffactor(self->db, ffactor);
2265 MYDB_END_ALLOW_THREADS;
2266 RETURN_IF_ERR();
2267 RETURN_NONE();
2268}
2269
2270
2271static PyObject*
2272DB_set_h_nelem(DBObject* self, PyObject* args)
2273{
2274 int err, nelem;
2275
2276 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2277 return NULL;
2278 CHECK_DB_NOT_CLOSED(self);
2279
2280 MYDB_BEGIN_ALLOW_THREADS;
2281 err = self->db->set_h_nelem(self->db, nelem);
2282 MYDB_END_ALLOW_THREADS;
2283 RETURN_IF_ERR();
2284 RETURN_NONE();
2285}
2286
2287
2288static PyObject*
2289DB_set_lorder(DBObject* self, PyObject* args)
2290{
2291 int err, lorder;
2292
2293 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2294 return NULL;
2295 CHECK_DB_NOT_CLOSED(self);
2296
2297 MYDB_BEGIN_ALLOW_THREADS;
2298 err = self->db->set_lorder(self->db, lorder);
2299 MYDB_END_ALLOW_THREADS;
2300 RETURN_IF_ERR();
2301 RETURN_NONE();
2302}
2303
2304
2305static PyObject*
2306DB_set_pagesize(DBObject* self, PyObject* args)
2307{
2308 int err, pagesize;
2309
2310 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2311 return NULL;
2312 CHECK_DB_NOT_CLOSED(self);
2313
2314 MYDB_BEGIN_ALLOW_THREADS;
2315 err = self->db->set_pagesize(self->db, pagesize);
2316 MYDB_END_ALLOW_THREADS;
2317 RETURN_IF_ERR();
2318 RETURN_NONE();
2319}
2320
2321
2322static PyObject*
2323DB_set_re_delim(DBObject* self, PyObject* args)
2324{
2325 int err;
2326 char delim;
2327
2328 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2329 PyErr_Clear();
2330 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2331 return NULL;
2332 }
2333
2334 CHECK_DB_NOT_CLOSED(self);
2335
2336 MYDB_BEGIN_ALLOW_THREADS;
2337 err = self->db->set_re_delim(self->db, delim);
2338 MYDB_END_ALLOW_THREADS;
2339 RETURN_IF_ERR();
2340 RETURN_NONE();
2341}
2342
2343static PyObject*
2344DB_set_re_len(DBObject* self, PyObject* args)
2345{
2346 int err, len;
2347
2348 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2349 return NULL;
2350 CHECK_DB_NOT_CLOSED(self);
2351
2352 MYDB_BEGIN_ALLOW_THREADS;
2353 err = self->db->set_re_len(self->db, len);
2354 MYDB_END_ALLOW_THREADS;
2355 RETURN_IF_ERR();
2356 RETURN_NONE();
2357}
2358
2359
2360static PyObject*
2361DB_set_re_pad(DBObject* self, PyObject* args)
2362{
2363 int err;
2364 char pad;
2365
2366 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2367 PyErr_Clear();
2368 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2369 return NULL;
2370 }
2371 CHECK_DB_NOT_CLOSED(self);
2372
2373 MYDB_BEGIN_ALLOW_THREADS;
2374 err = self->db->set_re_pad(self->db, pad);
2375 MYDB_END_ALLOW_THREADS;
2376 RETURN_IF_ERR();
2377 RETURN_NONE();
2378}
2379
2380
2381static PyObject*
2382DB_set_re_source(DBObject* self, PyObject* args)
2383{
2384 int err;
2385 char *re_source;
2386
2387 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2388 return NULL;
2389 CHECK_DB_NOT_CLOSED(self);
2390
2391 MYDB_BEGIN_ALLOW_THREADS;
2392 err = self->db->set_re_source(self->db, re_source);
2393 MYDB_END_ALLOW_THREADS;
2394 RETURN_IF_ERR();
2395 RETURN_NONE();
2396}
2397
2398
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002399static PyObject*
2400DB_set_q_extentsize(DBObject* self, PyObject* args)
2401{
2402 int err;
2403 int extentsize;
2404
2405 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2406 return NULL;
2407 CHECK_DB_NOT_CLOSED(self);
2408
2409 MYDB_BEGIN_ALLOW_THREADS;
2410 err = self->db->set_q_extentsize(self->db, extentsize);
2411 MYDB_END_ALLOW_THREADS;
2412 RETURN_IF_ERR();
2413 RETURN_NONE();
2414}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002415
2416static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002417DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002418{
2419 int err, flags = 0, type;
2420 void* sp;
2421 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002422#if (DBVER >= 43)
2423 PyObject* txnobj = NULL;
2424 DB_TXN *txn = NULL;
Thomas Wouters89f507f2006-12-13 04:49:30 +00002425 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002426#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002427 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002428#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002429
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002430#if (DBVER >= 43)
2431 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2432 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002433 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002434 if (!checkTxnObj(txnobj, &txn))
2435 return NULL;
2436#else
2437 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2438 return NULL;
2439#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002440 CHECK_DB_NOT_CLOSED(self);
2441
2442 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002443#if (DBVER >= 43)
2444 err = self->db->stat(self->db, txn, &sp, flags);
2445#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002446 err = self->db->stat(self->db, &sp, flags);
2447#else
2448 err = self->db->stat(self->db, &sp, NULL, flags);
2449#endif
2450 MYDB_END_ALLOW_THREADS;
2451 RETURN_IF_ERR();
2452
2453 self->haveStat = 1;
2454
2455 /* Turn the stat structure into a dictionary */
2456 type = _DB_get_type(self);
2457 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2458 free(sp);
2459 return NULL;
2460 }
2461
2462#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2463#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2464#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2465
2466 switch (type) {
2467 case DB_HASH:
2468 MAKE_HASH_ENTRY(magic);
2469 MAKE_HASH_ENTRY(version);
2470 MAKE_HASH_ENTRY(nkeys);
2471 MAKE_HASH_ENTRY(ndata);
2472 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002473#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002474 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002475#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002476 MAKE_HASH_ENTRY(ffactor);
2477 MAKE_HASH_ENTRY(buckets);
2478 MAKE_HASH_ENTRY(free);
2479 MAKE_HASH_ENTRY(bfree);
2480 MAKE_HASH_ENTRY(bigpages);
2481 MAKE_HASH_ENTRY(big_bfree);
2482 MAKE_HASH_ENTRY(overflows);
2483 MAKE_HASH_ENTRY(ovfl_free);
2484 MAKE_HASH_ENTRY(dup);
2485 MAKE_HASH_ENTRY(dup_free);
2486 break;
2487
2488 case DB_BTREE:
2489 case DB_RECNO:
2490 MAKE_BT_ENTRY(magic);
2491 MAKE_BT_ENTRY(version);
2492 MAKE_BT_ENTRY(nkeys);
2493 MAKE_BT_ENTRY(ndata);
2494 MAKE_BT_ENTRY(pagesize);
2495 MAKE_BT_ENTRY(minkey);
2496 MAKE_BT_ENTRY(re_len);
2497 MAKE_BT_ENTRY(re_pad);
2498 MAKE_BT_ENTRY(levels);
2499 MAKE_BT_ENTRY(int_pg);
2500 MAKE_BT_ENTRY(leaf_pg);
2501 MAKE_BT_ENTRY(dup_pg);
2502 MAKE_BT_ENTRY(over_pg);
2503 MAKE_BT_ENTRY(free);
2504 MAKE_BT_ENTRY(int_pgfree);
2505 MAKE_BT_ENTRY(leaf_pgfree);
2506 MAKE_BT_ENTRY(dup_pgfree);
2507 MAKE_BT_ENTRY(over_pgfree);
2508 break;
2509
2510 case DB_QUEUE:
2511 MAKE_QUEUE_ENTRY(magic);
2512 MAKE_QUEUE_ENTRY(version);
2513 MAKE_QUEUE_ENTRY(nkeys);
2514 MAKE_QUEUE_ENTRY(ndata);
2515 MAKE_QUEUE_ENTRY(pagesize);
2516 MAKE_QUEUE_ENTRY(pages);
2517 MAKE_QUEUE_ENTRY(re_len);
2518 MAKE_QUEUE_ENTRY(re_pad);
2519 MAKE_QUEUE_ENTRY(pgfree);
2520#if (DBVER == 31)
2521 MAKE_QUEUE_ENTRY(start);
2522#endif
2523 MAKE_QUEUE_ENTRY(first_recno);
2524 MAKE_QUEUE_ENTRY(cur_recno);
2525 break;
2526
2527 default:
2528 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2529 Py_DECREF(d);
2530 d = NULL;
2531 }
2532
2533#undef MAKE_HASH_ENTRY
2534#undef MAKE_BT_ENTRY
2535#undef MAKE_QUEUE_ENTRY
2536
2537 free(sp);
2538 return d;
2539}
2540
2541static PyObject*
2542DB_sync(DBObject* self, PyObject* args)
2543{
2544 int err;
2545 int flags = 0;
2546
2547 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2548 return NULL;
2549 CHECK_DB_NOT_CLOSED(self);
2550
2551 MYDB_BEGIN_ALLOW_THREADS;
2552 err = self->db->sync(self->db, flags);
2553 MYDB_END_ALLOW_THREADS;
2554 RETURN_IF_ERR();
2555 RETURN_NONE();
2556}
2557
2558
2559#if (DBVER >= 33)
2560static PyObject*
2561DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2562{
2563 int err, flags=0;
2564 u_int32_t count=0;
2565 PyObject* txnobj = NULL;
2566 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002567 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002568
2569 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2570 &txnobj, &flags))
2571 return NULL;
2572 CHECK_DB_NOT_CLOSED(self);
2573 if (!checkTxnObj(txnobj, &txn))
2574 return NULL;
2575
2576 MYDB_BEGIN_ALLOW_THREADS;
2577 err = self->db->truncate(self->db, txn, &count, flags);
2578 MYDB_END_ALLOW_THREADS;
2579 RETURN_IF_ERR();
2580 return PyInt_FromLong(count);
2581}
2582#endif
2583
2584
2585static PyObject*
2586DB_upgrade(DBObject* self, PyObject* args)
2587{
2588 int err, flags=0;
2589 char *filename;
2590
2591 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2592 return NULL;
2593 CHECK_DB_NOT_CLOSED(self);
2594
2595 MYDB_BEGIN_ALLOW_THREADS;
2596 err = self->db->upgrade(self->db, filename, flags);
2597 MYDB_END_ALLOW_THREADS;
2598 RETURN_IF_ERR();
2599 RETURN_NONE();
2600}
2601
2602
2603static PyObject*
2604DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2605{
2606 int err, flags=0;
2607 char* fileName;
2608 char* dbName=NULL;
2609 char* outFileName=NULL;
2610 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002611 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002612 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002613
2614 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2615 &fileName, &dbName, &outFileName, &flags))
2616 return NULL;
2617
2618 CHECK_DB_NOT_CLOSED(self);
2619 if (outFileName)
2620 outFile = fopen(outFileName, "w");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002621 /* XXX(nnorwitz): it should probably be an exception if outFile
2622 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002623
2624 MYDB_BEGIN_ALLOW_THREADS;
2625 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2626 MYDB_END_ALLOW_THREADS;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002627 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002628 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002629
2630 /* DB.verify acts as a DB handle destructor (like close); this was
2631 * documented in BerkeleyDB 4.2 but had the undocumented effect
2632 * of not being safe in prior versions while still requiring an explicit
2633 * DB.close call afterwards. Lets call close for the user to emulate
2634 * the safe 4.2 behaviour. */
2635#if (DBVER <= 41)
2636 self->db->close(self->db, 0);
2637#endif
2638 self->db = NULL;
2639
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002640 RETURN_IF_ERR();
2641 RETURN_NONE();
2642}
2643
2644
2645static PyObject*
2646DB_set_get_returns_none(DBObject* self, PyObject* args)
2647{
2648 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002649 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002650
2651 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2652 return NULL;
2653 CHECK_DB_NOT_CLOSED(self);
2654
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002655 if (self->moduleFlags.getReturnsNone)
2656 ++oldValue;
2657 if (self->moduleFlags.cursorSetReturnsNone)
2658 ++oldValue;
2659 self->moduleFlags.getReturnsNone = (flags >= 1);
2660 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002661 return PyInt_FromLong(oldValue);
2662}
2663
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002664#if (DBVER >= 41)
2665static PyObject*
2666DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2667{
2668 int err;
2669 u_int32_t flags=0;
2670 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002671 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002672
2673 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2674 &passwd, &flags)) {
2675 return NULL;
2676 }
2677
2678 MYDB_BEGIN_ALLOW_THREADS;
2679 err = self->db->set_encrypt(self->db, passwd, flags);
2680 MYDB_END_ALLOW_THREADS;
2681
2682 RETURN_IF_ERR();
2683 RETURN_NONE();
2684}
2685#endif /* DBVER >= 41 */
2686
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002687
2688/*-------------------------------------------------------------- */
2689/* Mapping and Dictionary-like access routines */
2690
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002691Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002692{
2693 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002694 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002695 int flags = 0;
2696 void* sp;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002697 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002698
2699 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002700 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2701 PyErr_SetObject(DBError, t);
2702 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002703 return -1;
2704 }
2705
2706 if (self->haveStat) { /* Has the stat function been called recently? If
2707 so, we can use the cached value. */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002708 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002709 }
2710
2711 MYDB_BEGIN_ALLOW_THREADS;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002712redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002713#if (DBVER >= 43)
2714 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2715#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002716 err = self->db->stat(self->db, &sp, flags);
2717#else
2718 err = self->db->stat(self->db, &sp, NULL, flags);
2719#endif
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002720
2721 /* All the stat structures have matching fields upto the ndata field,
2722 so we can use any of them for the type cast */
2723 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2724
2725 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2726 * redo a full stat to make sure.
2727 * Fixes SF python bug 1493322, pybsddb bug 1184012
2728 */
2729 if (size == 0 && (flags & DB_FAST_STAT)) {
2730 flags = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002731 if (!err)
2732 free(sp);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002733 goto redo_stat_for_length;
2734 }
2735
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002736 MYDB_END_ALLOW_THREADS;
2737
2738 if (err)
2739 return -1;
2740
2741 self->haveStat = 1;
2742
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002743 free(sp);
2744 return size;
2745}
2746
2747
2748PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2749{
2750 int err;
2751 PyObject* retval;
Thomas Heller39763a12007-09-24 14:43:56 +00002752 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002753 DBT key;
2754 DBT data;
2755
2756 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002757 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002758 return NULL;
2759
2760 CLEAR_DBT(data);
2761 if (CHECK_DBFLAG(self, DB_THREAD)) {
2762 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2763 data.flags = DB_DBT_MALLOC;
2764 }
2765 MYDB_BEGIN_ALLOW_THREADS;
2766 err = self->db->get(self->db, NULL, &key, &data, 0);
2767 MYDB_END_ALLOW_THREADS;
2768 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2769 PyErr_SetObject(PyExc_KeyError, keyobj);
2770 retval = NULL;
2771 }
2772 else if (makeDBError(err)) {
2773 retval = NULL;
2774 }
2775 else {
Martin v. Löwis64ce5052007-08-05 15:39:16 +00002776 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002777 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002778 }
2779
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002780 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002781 return retval;
2782}
2783
2784
2785static int
2786DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2787{
2788 DBT key, data;
2789 int retval;
2790 int flags = 0;
Thomas Heller39763a12007-09-24 14:43:56 +00002791 Py_buffer *data_buf_view = NULL;
2792 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002793
2794 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002795 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2796 PyErr_SetObject(DBError, t);
2797 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002798 return -1;
2799 }
2800
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002801 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002802 return -1;
2803
2804 if (dataobj != NULL) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002805 if (!make_dbt(dataobj, &data, &data_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002806 retval = -1;
2807 else {
2808 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002809 /* dictionaries shouldn't have duplicate keys */
2810 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002811 retval = _DB_put(self, NULL, &key, &data, flags);
2812
2813 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002814 /* try deleting any old record that matches and then PUT it
2815 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002816 _DB_delete(self, NULL, &key, 0);
2817 PyErr_Clear();
2818 retval = _DB_put(self, NULL, &key, &data, flags);
2819 }
2820 }
2821 }
2822 else {
2823 /* dataobj == NULL, so delete the key */
2824 retval = _DB_delete(self, NULL, &key, 0);
2825 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002826 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2827 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002828 return retval;
2829}
2830
2831
2832static PyObject*
2833DB_has_key(DBObject* self, PyObject* args)
2834{
2835 int err;
2836 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00002837 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002838 DBT key, data;
2839 PyObject* txnobj = NULL;
2840 DB_TXN *txn = NULL;
2841
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002842 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002843 return NULL;
2844 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002845 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002846 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002847 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002848 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002849 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002850 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002851
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002852 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002853 it has a record but can't allocate a buffer for the data. This saves
2854 having to deal with data we won't be using.
2855 */
2856 CLEAR_DBT(data);
2857 data.flags = DB_DBT_USERMEM;
2858
2859 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002860 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002861 MYDB_END_ALLOW_THREADS;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002862 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002863
2864 if (err == DB_BUFFER_SMALL || err == 0) {
2865 return PyInt_FromLong(1);
2866 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2867 return PyInt_FromLong(0);
2868 }
2869
2870 makeDBError(err);
2871 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002872}
2873
2874
2875#define _KEYS_LIST 1
2876#define _VALUES_LIST 2
2877#define _ITEMS_LIST 3
2878
2879static PyObject*
2880_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2881{
2882 int err, dbtype;
2883 DBT key;
2884 DBT data;
2885 DBC *cursor;
2886 PyObject* list;
2887 PyObject* item = NULL;
2888
2889 CHECK_DB_NOT_CLOSED(self);
2890 CLEAR_DBT(key);
2891 CLEAR_DBT(data);
2892
2893 dbtype = _DB_get_type(self);
2894 if (dbtype == -1)
2895 return NULL;
2896
2897 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002898 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002899 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002900
2901 /* get a cursor */
2902 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002903 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002904 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002905 if (makeDBError(err)) {
2906 Py_DECREF(list);
2907 return NULL;
2908 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002909
2910 if (CHECK_DBFLAG(self, DB_THREAD)) {
2911 key.flags = DB_DBT_REALLOC;
2912 data.flags = DB_DBT_REALLOC;
2913 }
2914
2915 while (1) { /* use the cursor to traverse the DB, collecting items */
2916 MYDB_BEGIN_ALLOW_THREADS;
2917 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2918 MYDB_END_ALLOW_THREADS;
2919
2920 if (err) {
2921 /* for any error, break out of the loop */
2922 break;
2923 }
2924
2925 switch (type) {
2926 case _KEYS_LIST:
2927 switch(dbtype) {
2928 case DB_BTREE:
2929 case DB_HASH:
2930 default:
Martin v. Löwis64ce5052007-08-05 15:39:16 +00002931 item = PyBytes_FromStringAndSize((char*)key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002932 break;
2933 case DB_RECNO:
2934 case DB_QUEUE:
2935 item = PyInt_FromLong(*((db_recno_t*)key.data));
2936 break;
2937 }
2938 break;
2939
2940 case _VALUES_LIST:
Martin v. Löwis64ce5052007-08-05 15:39:16 +00002941 item = PyBytes_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002942 break;
2943
2944 case _ITEMS_LIST:
2945 switch(dbtype) {
2946 case DB_BTREE:
2947 case DB_HASH:
2948 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002949 item = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002950 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002951 break;
2952 case DB_RECNO:
2953 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002954 item = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002955 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002956 break;
2957 }
2958 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002959 default:
2960 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2961 item = NULL;
2962 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002963 }
2964 if (item == NULL) {
2965 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002966 list = NULL;
2967 goto done;
2968 }
2969 PyList_Append(list, item);
2970 Py_DECREF(item);
2971 }
2972
Gregory P. Smithe9477062005-06-04 06:46:59 +00002973 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2974 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002975 Py_DECREF(list);
2976 list = NULL;
2977 }
2978
2979 done:
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002980 free_dbt(&key);
2981 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002982 MYDB_BEGIN_ALLOW_THREADS;
2983 cursor->c_close(cursor);
2984 MYDB_END_ALLOW_THREADS;
2985 return list;
2986}
2987
2988
2989static PyObject*
2990DB_keys(DBObject* self, PyObject* args)
2991{
2992 PyObject* txnobj = NULL;
2993 DB_TXN *txn = NULL;
2994
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00002995 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002996 return NULL;
2997 if (!checkTxnObj(txnobj, &txn))
2998 return NULL;
2999 return _DB_make_list(self, txn, _KEYS_LIST);
3000}
3001
3002
3003static PyObject*
3004DB_items(DBObject* self, PyObject* args)
3005{
3006 PyObject* txnobj = NULL;
3007 DB_TXN *txn = NULL;
3008
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003009 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003010 return NULL;
3011 if (!checkTxnObj(txnobj, &txn))
3012 return NULL;
3013 return _DB_make_list(self, txn, _ITEMS_LIST);
3014}
3015
3016
3017static PyObject*
3018DB_values(DBObject* self, PyObject* args)
3019{
3020 PyObject* txnobj = NULL;
3021 DB_TXN *txn = NULL;
3022
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003023 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003024 return NULL;
3025 if (!checkTxnObj(txnobj, &txn))
3026 return NULL;
3027 return _DB_make_list(self, txn, _VALUES_LIST);
3028}
3029
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003030/* --------------------------------------------------------------------- */
3031/* DBCursor methods */
3032
3033
3034static PyObject*
3035DBC_close(DBCursorObject* self, PyObject* args)
3036{
3037 int err = 0;
3038
3039 if (!PyArg_ParseTuple(args, ":close"))
3040 return NULL;
3041
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003042 if (self->dbc != NULL) {
3043 MYDB_BEGIN_ALLOW_THREADS;
3044 err = self->dbc->c_close(self->dbc);
3045 self->dbc = NULL;
3046 MYDB_END_ALLOW_THREADS;
3047 }
3048 RETURN_IF_ERR();
3049 RETURN_NONE();
3050}
3051
3052
3053static PyObject*
3054DBC_count(DBCursorObject* self, PyObject* args)
3055{
3056 int err = 0;
3057 db_recno_t count;
3058 int flags = 0;
3059
3060 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3061 return NULL;
3062
3063 CHECK_CURSOR_NOT_CLOSED(self);
3064
3065 MYDB_BEGIN_ALLOW_THREADS;
3066 err = self->dbc->c_count(self->dbc, &count, flags);
3067 MYDB_END_ALLOW_THREADS;
3068 RETURN_IF_ERR();
3069
3070 return PyInt_FromLong(count);
3071}
3072
3073
3074static PyObject*
3075DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3076{
3077 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3078}
3079
3080
3081static PyObject*
3082DBC_delete(DBCursorObject* self, PyObject* args)
3083{
3084 int err, flags=0;
3085
3086 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3087 return NULL;
3088
3089 CHECK_CURSOR_NOT_CLOSED(self);
3090
3091 MYDB_BEGIN_ALLOW_THREADS;
3092 err = self->dbc->c_del(self->dbc, flags);
3093 MYDB_END_ALLOW_THREADS;
3094 RETURN_IF_ERR();
3095
3096 self->mydb->haveStat = 0;
3097 RETURN_NONE();
3098}
3099
3100
3101static PyObject*
3102DBC_dup(DBCursorObject* self, PyObject* args)
3103{
3104 int err, flags =0;
3105 DBC* dbc = NULL;
3106
3107 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3108 return NULL;
3109
3110 CHECK_CURSOR_NOT_CLOSED(self);
3111
3112 MYDB_BEGIN_ALLOW_THREADS;
3113 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3114 MYDB_END_ALLOW_THREADS;
3115 RETURN_IF_ERR();
3116
3117 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3118}
3119
3120static PyObject*
3121DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3122{
3123 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3124}
3125
3126
3127static PyObject*
3128DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3129{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003130 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003131 PyObject* keyobj = NULL;
3132 PyObject* dataobj = NULL;
3133 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00003134 Py_buffer* data_buf_view = NULL;
3135 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003136 int dlen = -1;
3137 int doff = -1;
3138 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003139 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003140 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003141
3142 CLEAR_DBT(key);
3143 CLEAR_DBT(data);
3144 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003145 &flags, &dlen, &doff))
3146 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003147 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003148 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3149 &kwnames[1],
3150 &keyobj, &flags, &dlen, &doff))
3151 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003152 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003153 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3154 kwnames, &keyobj, &dataobj,
3155 &flags, &dlen, &doff))
3156 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003157 return NULL;
3158 }
3159 }
3160 }
3161
3162 CHECK_CURSOR_NOT_CLOSED(self);
3163
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003164 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003165 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003166 if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003167 (!add_partial_dbt(&data, dlen, doff)) )
3168 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003169 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3170 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003171 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003172 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003173
3174 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3175 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003176 if (!(key.flags & DB_DBT_REALLOC)) {
3177 key.flags |= DB_DBT_MALLOC;
3178 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003179 }
3180
3181 MYDB_BEGIN_ALLOW_THREADS;
3182 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3183 MYDB_END_ALLOW_THREADS;
3184
Gregory P. Smithe9477062005-06-04 06:46:59 +00003185 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3186 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003187 Py_INCREF(Py_None);
3188 retval = Py_None;
3189 }
3190 else if (makeDBError(err)) {
3191 retval = NULL;
3192 }
3193 else {
3194 switch (_DB_get_type(self->mydb)) {
3195 case -1:
3196 retval = NULL;
3197 break;
3198 case DB_BTREE:
3199 case DB_HASH:
3200 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003201 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003202 data.data, data.size);
3203 break;
3204 case DB_RECNO:
3205 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003206 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003207 data.data, data.size);
3208 break;
3209 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003210 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003211 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003212 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3213 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003214 return retval;
3215}
3216
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003217#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003218static PyObject*
3219DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3220{
3221 int err, flags=0;
3222 PyObject* keyobj = NULL;
3223 PyObject* dataobj = NULL;
3224 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00003225 Py_buffer* data_buf_view = NULL;
3226 Py_buffer* key_buf_view = NULL;
Gregory P. Smith19699a92004-06-28 04:06:49 +00003227 int dlen = -1;
3228 int doff = -1;
3229 DBT key, pkey, data;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003230 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3231 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003232
3233 CLEAR_DBT(key);
3234 CLEAR_DBT(data);
3235 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3236 &flags, &dlen, &doff))
3237 {
3238 PyErr_Clear();
3239 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003240 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003241 &keyobj, &flags, &dlen, &doff))
3242 {
3243 PyErr_Clear();
3244 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3245 kwnames, &keyobj, &dataobj,
3246 &flags, &dlen, &doff))
3247 {
3248 return NULL;
3249 }
3250 }
3251 }
3252
3253 CHECK_CURSOR_NOT_CLOSED(self);
3254
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003255 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Gregory P. Smith19699a92004-06-28 04:06:49 +00003256 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003257 if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) ||
Gregory P. Smith19699a92004-06-28 04:06:49 +00003258 (!add_partial_dbt(&data, dlen, doff)) ) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003259 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3260 free_buf_view(dataobj, data_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003261 return NULL;
3262 }
3263
3264 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3265 data.flags = DB_DBT_MALLOC;
3266 if (!(key.flags & DB_DBT_REALLOC)) {
3267 key.flags |= DB_DBT_MALLOC;
3268 }
3269 }
3270
3271 CLEAR_DBT(pkey);
3272 pkey.flags = DB_DBT_MALLOC;
3273
3274 MYDB_BEGIN_ALLOW_THREADS;
3275 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3276 MYDB_END_ALLOW_THREADS;
3277
Gregory P. Smithe9477062005-06-04 06:46:59 +00003278 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3279 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003280 Py_INCREF(Py_None);
3281 retval = Py_None;
3282 }
3283 else if (makeDBError(err)) {
3284 retval = NULL;
3285 }
3286 else {
3287 PyObject *pkeyObj;
3288 PyObject *dataObj;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003289 dataObj = PyBytes_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003290
3291 if (self->mydb->primaryDBType == DB_RECNO ||
3292 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003293 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003294 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003295 pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003296
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003297 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003298 {
3299 PyObject *keyObj;
3300 int type = _DB_get_type(self->mydb);
3301 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003302 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003303 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003304 keyObj = PyBytes_FromStringAndSize(key.data, key.size);
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003305 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Thomas Woutersb3153832006-03-08 01:47:19 +00003306 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003307 }
3308 else /* return just the pkey and data */
3309 {
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003310 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003311 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003312 Py_DECREF(dataObj);
3313 Py_DECREF(pkeyObj);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003314 free_dbt(&pkey);
3315 free_dbt(&data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003316 }
3317 /* the only time REALLOC should be set is if we used an integer
3318 * key that make_key_dbt malloc'd for us. always free these. */
3319 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003320 free_dbt(&key);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003321 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003322 free_buf_view(keyobj, key_buf_view);
3323 free_buf_view(dataobj, data_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003324 return retval;
3325}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003326#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003327
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003328
3329static PyObject*
3330DBC_get_recno(DBCursorObject* self, PyObject* args)
3331{
3332 int err;
3333 db_recno_t recno;
3334 DBT key;
3335 DBT data;
3336
3337 if (!PyArg_ParseTuple(args, ":get_recno"))
3338 return NULL;
3339
3340 CHECK_CURSOR_NOT_CLOSED(self);
3341
3342 CLEAR_DBT(key);
3343 CLEAR_DBT(data);
3344 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3345 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3346 data.flags = DB_DBT_MALLOC;
3347 key.flags = DB_DBT_MALLOC;
3348 }
3349
3350 MYDB_BEGIN_ALLOW_THREADS;
3351 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3352 MYDB_END_ALLOW_THREADS;
3353 RETURN_IF_ERR();
3354
3355 recno = *((db_recno_t*)data.data);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003356 free_dbt(&key);
3357 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003358 return PyInt_FromLong(recno);
3359}
3360
3361
3362static PyObject*
3363DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3364{
3365 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3366}
3367
3368
3369static PyObject*
3370DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3371{
3372 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3373}
3374
3375
3376static PyObject*
3377DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3378{
3379 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3380}
3381
3382
3383static PyObject*
3384DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3385{
3386 int err, flags = 0;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003387 PyObject *keyobj, *dataobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003388 Py_buffer *data_buf_view = NULL;
3389 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003390 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003391 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003392 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003393 int dlen = -1;
3394 int doff = -1;
3395
3396 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3397 &keyobj, &dataobj, &flags, &dlen, &doff))
3398 return NULL;
3399
3400 CHECK_CURSOR_NOT_CLOSED(self);
3401
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003402 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003403 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003404 if (!make_dbt(dataobj, &data, &data_buf_view) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003405 !add_partial_dbt(&data, dlen, doff) )
3406 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003407 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3408 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003409 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003410 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003411
3412 MYDB_BEGIN_ALLOW_THREADS;
3413 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3414 MYDB_END_ALLOW_THREADS;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003415 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3416 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003417 RETURN_IF_ERR();
3418 self->mydb->haveStat = 0;
3419 RETURN_NONE();
3420}
3421
3422
3423static PyObject*
3424DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3425{
3426 int err, flags = 0;
3427 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003428 PyObject *retval, *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003429 Py_buffer *key_buf_view = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003430 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003431 int dlen = -1;
3432 int doff = -1;
3433
3434 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3435 &keyobj, &flags, &dlen, &doff))
3436 return NULL;
3437
3438 CHECK_CURSOR_NOT_CLOSED(self);
3439
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003440 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003441 return NULL;
3442
3443 CLEAR_DBT(data);
3444 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3445 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3446 data.flags = DB_DBT_MALLOC;
3447 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003448 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003449 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003450 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003451 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003452
3453 MYDB_BEGIN_ALLOW_THREADS;
3454 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3455 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003456 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3457 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003458 Py_INCREF(Py_None);
3459 retval = Py_None;
3460 }
3461 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003462 retval = NULL;
3463 }
3464 else {
3465 switch (_DB_get_type(self->mydb)) {
3466 case -1:
3467 retval = NULL;
3468 break;
3469 case DB_BTREE:
3470 case DB_HASH:
3471 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003472 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003473 data.data, data.size);
3474 break;
3475 case DB_RECNO:
3476 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003477 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003478 data.data, data.size);
3479 break;
3480 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003481 free_dbt(&data);
3482 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003483 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003484 /* the only time REALLOC should be set is if we used an integer
3485 * key that make_key_dbt malloc'd for us. always free these. */
3486 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003487 free_dbt(&key);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003488 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003489 free_buf_view(keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003490
3491 return retval;
3492}
3493
3494
3495static PyObject*
3496DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3497{
3498 int err, flags = 0;
3499 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003500 PyObject *retval, *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003501 Py_buffer *key_buf_view = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003502 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003503 int dlen = -1;
3504 int doff = -1;
3505
3506 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3507 &keyobj, &flags, &dlen, &doff))
3508 return NULL;
3509
3510 CHECK_CURSOR_NOT_CLOSED(self);
3511
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003512 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003513 return NULL;
3514
3515 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003516 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003517 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003518 return NULL;
3519 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003520 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3521 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003522 data.flags |= DB_DBT_MALLOC;
3523 /* only BTREE databases will return anything in the key */
3524 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3525 key.flags |= DB_DBT_MALLOC;
3526 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003527 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003528 MYDB_BEGIN_ALLOW_THREADS;
3529 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3530 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003531 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3532 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003533 Py_INCREF(Py_None);
3534 retval = Py_None;
3535 }
3536 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003537 retval = NULL;
3538 }
3539 else {
3540 switch (_DB_get_type(self->mydb)) {
3541 case -1:
3542 retval = NULL;
3543 break;
3544 case DB_BTREE:
3545 case DB_HASH:
3546 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003547 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003548 data.data, data.size);
3549 break;
3550 case DB_RECNO:
3551 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003552 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003553 data.data, data.size);
3554 break;
3555 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003556 free_dbt(&key);
3557 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003558 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003559 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003560 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003561 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003562 free_dbt(&key);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003563 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003564 free_buf_view(keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003565
3566 return retval;
3567}
3568
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003569static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003570_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3571 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003572{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003573 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003574 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003575 PyObject *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00003576 Py_buffer *data_buf_view = NULL;
3577 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003578
Gregory P. Smith7441e652003-11-03 21:35:31 +00003579 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003580 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003581 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003582 if (!make_dbt(dataobj, &data, &data_buf_view)) {
3583 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003584 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003585 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003586
3587 MYDB_BEGIN_ALLOW_THREADS;
3588 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3589 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003590 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003591 Py_INCREF(Py_None);
3592 retval = Py_None;
3593 }
3594 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003595 retval = NULL;
3596 }
3597 else {
3598 switch (_DB_get_type(self->mydb)) {
3599 case -1:
3600 retval = NULL;
3601 break;
3602 case DB_BTREE:
3603 case DB_HASH:
3604 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003605 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003606 data.data, data.size);
3607 break;
3608 case DB_RECNO:
3609 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003610 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003611 data.data, data.size);
3612 break;
3613 }
3614 }
3615
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003616 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3617 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003618 return retval;
3619}
3620
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003621static PyObject*
3622DBC_get_both(DBCursorObject* self, PyObject* args)
3623{
3624 int flags=0;
3625 PyObject *keyobj, *dataobj;
3626
3627 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3628 return NULL;
3629
Gregory P. Smith7441e652003-11-03 21:35:31 +00003630 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003631 CHECK_CURSOR_NOT_CLOSED(self);
3632
3633 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3634 self->mydb->moduleFlags.getReturnsNone);
3635}
3636
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003637/* Return size of entry */
3638static PyObject*
3639DBC_get_current_size(DBCursorObject* self, PyObject* args)
3640{
3641 int err, flags=DB_CURRENT;
3642 PyObject* retval = NULL;
3643 DBT key, data;
3644
3645 if (!PyArg_ParseTuple(args, ":get_current_size"))
3646 return NULL;
3647 CHECK_CURSOR_NOT_CLOSED(self);
3648 CLEAR_DBT(key);
3649 CLEAR_DBT(data);
3650
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003651 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003652 getting the record size. */
3653 data.flags = DB_DBT_USERMEM;
3654 data.ulen = 0;
3655 MYDB_BEGIN_ALLOW_THREADS;
3656 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3657 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003658 if (err == DB_BUFFER_SMALL || !err) {
3659 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003660 retval = PyInt_FromLong((long)data.size);
3661 err = 0;
3662 }
3663
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003664 free_dbt(&key);
3665 free_dbt(&data);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003666 RETURN_IF_ERR();
3667 return retval;
3668}
3669
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003670static PyObject*
3671DBC_set_both(DBCursorObject* self, PyObject* args)
3672{
3673 int flags=0;
3674 PyObject *keyobj, *dataobj;
3675
3676 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3677 return NULL;
3678
Gregory P. Smith7441e652003-11-03 21:35:31 +00003679 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003680 CHECK_CURSOR_NOT_CLOSED(self);
3681
3682 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3683 self->mydb->moduleFlags.cursorSetReturnsNone);
3684}
3685
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003686
3687static PyObject*
3688DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3689{
3690 int err, irecno, flags=0;
3691 db_recno_t recno;
3692 DBT key, data;
3693 PyObject* retval;
3694 int dlen = -1;
3695 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003696 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003697
3698 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3699 &irecno, &flags, &dlen, &doff))
3700 return NULL;
3701
3702 CHECK_CURSOR_NOT_CLOSED(self);
3703
3704 CLEAR_DBT(key);
3705 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003706 /* use allocated space so DB will be able to realloc room for the real
3707 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003708 key.data = malloc(sizeof(db_recno_t));
3709 if (key.data == NULL) {
3710 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3711 return NULL;
3712 }
3713 key.size = sizeof(db_recno_t);
3714 key.ulen = key.size;
3715 memcpy(key.data, &recno, sizeof(db_recno_t));
3716 key.flags = DB_DBT_REALLOC;
3717
3718 CLEAR_DBT(data);
3719 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3720 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3721 data.flags = DB_DBT_MALLOC;
3722 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003723 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003724 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003725 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003726 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003727
3728 MYDB_BEGIN_ALLOW_THREADS;
3729 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3730 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003731 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3732 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003733 Py_INCREF(Py_None);
3734 retval = Py_None;
3735 }
3736 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003737 retval = NULL;
3738 }
3739 else { /* Can only be used for BTrees, so no need to return int key */
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003740 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003741 data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003742 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003743 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003744 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003745
3746 return retval;
3747}
3748
3749
3750static PyObject*
3751DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3752{
3753 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3754}
3755
3756
3757static PyObject*
3758DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3759{
3760 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3761}
3762
3763
3764static PyObject*
3765DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3766{
3767 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3768}
3769
3770
3771static PyObject*
3772DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3773{
3774 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3775}
3776
3777
3778static PyObject*
3779DBC_join_item(DBCursorObject* self, PyObject* args)
3780{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003781 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003782 DBT key, data;
3783 PyObject* retval;
3784
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003785 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003786 return NULL;
3787
3788 CHECK_CURSOR_NOT_CLOSED(self);
3789
3790 CLEAR_DBT(key);
3791 CLEAR_DBT(data);
3792 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3793 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3794 key.flags = DB_DBT_MALLOC;
3795 }
3796
3797 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003798 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003799 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003800 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3801 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003802 Py_INCREF(Py_None);
3803 retval = Py_None;
3804 }
3805 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003806 retval = NULL;
3807 }
3808 else {
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003809 retval = Py_BuildValue("y#", key.data, key.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003810 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003811 }
3812
3813 return retval;
3814}
3815
3816
3817
3818/* --------------------------------------------------------------------- */
3819/* DBEnv methods */
3820
3821
3822static PyObject*
3823DBEnv_close(DBEnvObject* self, PyObject* args)
3824{
3825 int err, flags = 0;
3826
3827 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3828 return NULL;
3829 if (!self->closed) { /* Don't close more than once */
3830 MYDB_BEGIN_ALLOW_THREADS;
3831 err = self->db_env->close(self->db_env, flags);
3832 MYDB_END_ALLOW_THREADS;
3833 /* after calling DBEnv->close, regardless of error, this DBEnv
3834 * may not be accessed again (BerkeleyDB docs). */
3835 self->closed = 1;
3836 self->db_env = NULL;
3837 RETURN_IF_ERR();
3838 }
3839 RETURN_NONE();
3840}
3841
3842
3843static PyObject*
3844DBEnv_open(DBEnvObject* self, PyObject* args)
3845{
3846 int err, flags=0, mode=0660;
3847 char *db_home;
3848
3849 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3850 return NULL;
3851
3852 CHECK_ENV_NOT_CLOSED(self);
3853
3854 MYDB_BEGIN_ALLOW_THREADS;
3855 err = self->db_env->open(self->db_env, db_home, flags, mode);
3856 MYDB_END_ALLOW_THREADS;
3857 RETURN_IF_ERR();
3858 self->closed = 0;
3859 self->flags = flags;
3860 RETURN_NONE();
3861}
3862
3863
3864static PyObject*
3865DBEnv_remove(DBEnvObject* self, PyObject* args)
3866{
3867 int err, flags=0;
3868 char *db_home;
3869
3870 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3871 return NULL;
3872 CHECK_ENV_NOT_CLOSED(self);
3873 MYDB_BEGIN_ALLOW_THREADS;
3874 err = self->db_env->remove(self->db_env, db_home, flags);
3875 MYDB_END_ALLOW_THREADS;
3876 RETURN_IF_ERR();
3877 RETURN_NONE();
3878}
3879
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003880#if (DBVER >= 41)
3881static PyObject*
3882DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3883{
3884 int err;
3885 u_int32_t flags=0;
3886 char *file = NULL;
3887 char *database = NULL;
3888 PyObject *txnobj = NULL;
3889 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003890 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003891 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003892
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003893 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003894 &file, &database, &txnobj, &flags)) {
3895 return NULL;
3896 }
3897 if (!checkTxnObj(txnobj, &txn)) {
3898 return NULL;
3899 }
3900 CHECK_ENV_NOT_CLOSED(self);
3901 MYDB_BEGIN_ALLOW_THREADS;
3902 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3903 MYDB_END_ALLOW_THREADS;
3904 RETURN_IF_ERR();
3905 RETURN_NONE();
3906}
3907
3908static PyObject*
3909DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3910{
3911 int err;
3912 u_int32_t flags=0;
3913 char *file = NULL;
3914 char *database = NULL;
3915 char *newname = NULL;
3916 PyObject *txnobj = NULL;
3917 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003918 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003919 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003920
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003921 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003922 &file, &database, &newname, &txnobj, &flags)) {
3923 return NULL;
3924 }
3925 if (!checkTxnObj(txnobj, &txn)) {
3926 return NULL;
3927 }
3928 CHECK_ENV_NOT_CLOSED(self);
3929 MYDB_BEGIN_ALLOW_THREADS;
3930 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3931 flags);
3932 MYDB_END_ALLOW_THREADS;
3933 RETURN_IF_ERR();
3934 RETURN_NONE();
3935}
3936
3937static PyObject*
3938DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3939{
3940 int err;
3941 u_int32_t flags=0;
3942 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003943 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003944
3945 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3946 &passwd, &flags)) {
3947 return NULL;
3948 }
3949
3950 MYDB_BEGIN_ALLOW_THREADS;
3951 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3952 MYDB_END_ALLOW_THREADS;
3953
3954 RETURN_IF_ERR();
3955 RETURN_NONE();
3956}
3957#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003958
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003959#if (DBVER >= 40)
3960static PyObject*
3961DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3962{
3963 int err;
3964 u_int32_t flags=0;
3965 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003966 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003967
3968 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3969 &timeout, &flags)) {
3970 return NULL;
3971 }
3972
3973 MYDB_BEGIN_ALLOW_THREADS;
3974 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3975 MYDB_END_ALLOW_THREADS;
3976
3977 RETURN_IF_ERR();
3978 RETURN_NONE();
3979}
3980#endif /* DBVER >= 40 */
3981
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003982static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003983DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3984{
3985 int err;
3986 long shm_key = 0;
3987
3988 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3989 return NULL;
3990 CHECK_ENV_NOT_CLOSED(self);
3991
3992 err = self->db_env->set_shm_key(self->db_env, shm_key);
3993 RETURN_IF_ERR();
3994 RETURN_NONE();
3995}
3996
3997static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003998DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3999{
4000 int err, gbytes=0, bytes=0, ncache=0;
4001
4002 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4003 &gbytes, &bytes, &ncache))
4004 return NULL;
4005 CHECK_ENV_NOT_CLOSED(self);
4006
4007 MYDB_BEGIN_ALLOW_THREADS;
4008 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4009 MYDB_END_ALLOW_THREADS;
4010 RETURN_IF_ERR();
4011 RETURN_NONE();
4012}
4013
4014
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004015static PyObject*
4016DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4017{
4018 int err, flags=0, onoff=0;
4019
4020 if (!PyArg_ParseTuple(args, "ii:set_flags",
4021 &flags, &onoff))
4022 return NULL;
4023 CHECK_ENV_NOT_CLOSED(self);
4024
4025 MYDB_BEGIN_ALLOW_THREADS;
4026 err = self->db_env->set_flags(self->db_env, flags, onoff);
4027 MYDB_END_ALLOW_THREADS;
4028 RETURN_IF_ERR();
4029 RETURN_NONE();
4030}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004031
4032
4033static PyObject*
4034DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4035{
4036 int err;
4037 char *dir;
4038
4039 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4040 return NULL;
4041 CHECK_ENV_NOT_CLOSED(self);
4042
4043 MYDB_BEGIN_ALLOW_THREADS;
4044 err = self->db_env->set_data_dir(self->db_env, dir);
4045 MYDB_END_ALLOW_THREADS;
4046 RETURN_IF_ERR();
4047 RETURN_NONE();
4048}
4049
4050
4051static PyObject*
4052DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4053{
4054 int err, lg_bsize;
4055
4056 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4057 return NULL;
4058 CHECK_ENV_NOT_CLOSED(self);
4059
4060 MYDB_BEGIN_ALLOW_THREADS;
4061 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4062 MYDB_END_ALLOW_THREADS;
4063 RETURN_IF_ERR();
4064 RETURN_NONE();
4065}
4066
4067
4068static PyObject*
4069DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4070{
4071 int err;
4072 char *dir;
4073
4074 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4075 return NULL;
4076 CHECK_ENV_NOT_CLOSED(self);
4077
4078 MYDB_BEGIN_ALLOW_THREADS;
4079 err = self->db_env->set_lg_dir(self->db_env, dir);
4080 MYDB_END_ALLOW_THREADS;
4081 RETURN_IF_ERR();
4082 RETURN_NONE();
4083}
4084
4085static PyObject*
4086DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4087{
4088 int err, lg_max;
4089
4090 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4091 return NULL;
4092 CHECK_ENV_NOT_CLOSED(self);
4093
4094 MYDB_BEGIN_ALLOW_THREADS;
4095 err = self->db_env->set_lg_max(self->db_env, lg_max);
4096 MYDB_END_ALLOW_THREADS;
4097 RETURN_IF_ERR();
4098 RETURN_NONE();
4099}
4100
4101
Neal Norwitz84562352005-10-20 04:30:15 +00004102#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004103static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004104DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4105{
4106 int err, lg_max;
4107
4108 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4109 return NULL;
4110 CHECK_ENV_NOT_CLOSED(self);
4111
4112 MYDB_BEGIN_ALLOW_THREADS;
4113 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4114 MYDB_END_ALLOW_THREADS;
4115 RETURN_IF_ERR();
4116 RETURN_NONE();
4117}
Neal Norwitz84562352005-10-20 04:30:15 +00004118#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004119
4120
4121static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004122DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4123{
4124 int err, lk_detect;
4125
4126 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4127 return NULL;
4128 CHECK_ENV_NOT_CLOSED(self);
4129
4130 MYDB_BEGIN_ALLOW_THREADS;
4131 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4132 MYDB_END_ALLOW_THREADS;
4133 RETURN_IF_ERR();
4134 RETURN_NONE();
4135}
4136
4137
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004138#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004139static PyObject*
4140DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4141{
4142 int err, max;
4143
4144 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4145 return NULL;
4146 CHECK_ENV_NOT_CLOSED(self);
4147
4148 MYDB_BEGIN_ALLOW_THREADS;
4149 err = self->db_env->set_lk_max(self->db_env, max);
4150 MYDB_END_ALLOW_THREADS;
4151 RETURN_IF_ERR();
4152 RETURN_NONE();
4153}
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004154#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004155
4156
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004157
4158static PyObject*
4159DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4160{
4161 int err, max;
4162
4163 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4164 return NULL;
4165 CHECK_ENV_NOT_CLOSED(self);
4166
4167 MYDB_BEGIN_ALLOW_THREADS;
4168 err = self->db_env->set_lk_max_locks(self->db_env, max);
4169 MYDB_END_ALLOW_THREADS;
4170 RETURN_IF_ERR();
4171 RETURN_NONE();
4172}
4173
4174
4175static PyObject*
4176DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4177{
4178 int err, max;
4179
4180 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4181 return NULL;
4182 CHECK_ENV_NOT_CLOSED(self);
4183
4184 MYDB_BEGIN_ALLOW_THREADS;
4185 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4186 MYDB_END_ALLOW_THREADS;
4187 RETURN_IF_ERR();
4188 RETURN_NONE();
4189}
4190
4191
4192static PyObject*
4193DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4194{
4195 int err, max;
4196
4197 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4198 return NULL;
4199 CHECK_ENV_NOT_CLOSED(self);
4200
4201 MYDB_BEGIN_ALLOW_THREADS;
4202 err = self->db_env->set_lk_max_objects(self->db_env, max);
4203 MYDB_END_ALLOW_THREADS;
4204 RETURN_IF_ERR();
4205 RETURN_NONE();
4206}
4207
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004208
4209static PyObject*
4210DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4211{
4212 int err, mp_mmapsize;
4213
4214 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4215 return NULL;
4216 CHECK_ENV_NOT_CLOSED(self);
4217
4218 MYDB_BEGIN_ALLOW_THREADS;
4219 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4220 MYDB_END_ALLOW_THREADS;
4221 RETURN_IF_ERR();
4222 RETURN_NONE();
4223}
4224
4225
4226static PyObject*
4227DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4228{
4229 int err;
4230 char *dir;
4231
4232 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4233 return NULL;
4234 CHECK_ENV_NOT_CLOSED(self);
4235
4236 MYDB_BEGIN_ALLOW_THREADS;
4237 err = self->db_env->set_tmp_dir(self->db_env, dir);
4238 MYDB_END_ALLOW_THREADS;
4239 RETURN_IF_ERR();
4240 RETURN_NONE();
4241}
4242
4243
4244static PyObject*
4245DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4246{
4247 int flags = 0;
4248 PyObject* txnobj = NULL;
4249 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004250 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004251
4252 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4253 &txnobj, &flags))
4254 return NULL;
4255
4256 if (!checkTxnObj(txnobj, &txn))
4257 return NULL;
4258 CHECK_ENV_NOT_CLOSED(self);
4259
4260 return (PyObject*)newDBTxnObject(self, txn, flags);
4261}
4262
4263
4264static PyObject*
4265DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4266{
4267 int err, kbyte=0, min=0, flags=0;
4268
4269 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4270 return NULL;
4271 CHECK_ENV_NOT_CLOSED(self);
4272
4273 MYDB_BEGIN_ALLOW_THREADS;
4274#if (DBVER >= 40)
4275 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4276#else
4277 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4278#endif
4279 MYDB_END_ALLOW_THREADS;
4280 RETURN_IF_ERR();
4281 RETURN_NONE();
4282}
4283
4284
4285static PyObject*
4286DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4287{
4288 int err, max;
4289
4290 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4291 return NULL;
4292 CHECK_ENV_NOT_CLOSED(self);
4293
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004294 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004295 RETURN_IF_ERR();
4296 RETURN_NONE();
4297}
4298
4299
4300static PyObject*
4301DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4302{
4303 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004304 long stamp;
4305 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004306
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004307 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004308 return NULL;
4309 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004310 timestamp = (time_t)stamp;
4311 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004312 RETURN_IF_ERR();
4313 RETURN_NONE();
4314}
4315
4316
4317static PyObject*
4318DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4319{
4320 int err, atype, flags=0;
4321 int aborted = 0;
4322
4323 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4324 return NULL;
4325 CHECK_ENV_NOT_CLOSED(self);
4326
4327 MYDB_BEGIN_ALLOW_THREADS;
4328#if (DBVER >= 40)
4329 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4330#else
4331 err = lock_detect(self->db_env, flags, atype, &aborted);
4332#endif
4333 MYDB_END_ALLOW_THREADS;
4334 RETURN_IF_ERR();
4335 return PyInt_FromLong(aborted);
4336}
4337
4338
4339static PyObject*
4340DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4341{
4342 int flags=0;
4343 int locker, lock_mode;
4344 DBT obj;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004345 PyObject *objobj, *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00004346 Py_buffer *obj_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004347
4348 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4349 return NULL;
4350
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004351 if (!make_dbt(objobj, &obj, &obj_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004352 return NULL;
4353
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004354 retval = (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4355 free_buf_view(objobj, obj_buf_view);
4356 return retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004357}
4358
4359
4360static PyObject*
4361DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4362{
4363 int err;
4364 u_int32_t theID;
4365
4366 if (!PyArg_ParseTuple(args, ":lock_id"))
4367 return NULL;
4368
4369 CHECK_ENV_NOT_CLOSED(self);
4370 MYDB_BEGIN_ALLOW_THREADS;
4371#if (DBVER >= 40)
4372 err = self->db_env->lock_id(self->db_env, &theID);
4373#else
4374 err = lock_id(self->db_env, &theID);
4375#endif
4376 MYDB_END_ALLOW_THREADS;
4377 RETURN_IF_ERR();
4378
4379 return PyInt_FromLong((long)theID);
4380}
4381
Guido van Rossum77677112007-11-05 19:43:04 +00004382#if (DBVER >= 40)
4383static PyObject*
4384DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
4385{
4386 int err;
4387 u_int32_t theID;
4388
4389 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
4390 return NULL;
4391
4392 CHECK_ENV_NOT_CLOSED(self);
4393 MYDB_BEGIN_ALLOW_THREADS;
4394 err = self->db_env->lock_id_free(self->db_env, theID);
4395 MYDB_END_ALLOW_THREADS;
4396 RETURN_IF_ERR();
4397 RETURN_NONE();
4398}
4399#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004400
4401static PyObject*
4402DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4403{
4404 int err;
4405 DBLockObject* dblockobj;
4406
4407 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4408 return NULL;
4409
4410 CHECK_ENV_NOT_CLOSED(self);
4411 MYDB_BEGIN_ALLOW_THREADS;
4412#if (DBVER >= 40)
4413 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4414#else
4415 err = lock_put(self->db_env, &dblockobj->lock);
4416#endif
4417 MYDB_END_ALLOW_THREADS;
4418 RETURN_IF_ERR();
4419 RETURN_NONE();
4420}
4421
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004422#if (DBVER >= 44)
4423static PyObject*
4424DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4425{
4426 int err;
4427 char *file;
4428 u_int32_t flags = 0;
4429 static char* kwnames[] = { "file", "flags", NULL};
4430
4431 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4432 &file, &flags))
4433 return NULL;
4434 CHECK_ENV_NOT_CLOSED(self);
4435
4436 MYDB_BEGIN_ALLOW_THREADS;
4437 err = self->db_env->lsn_reset(self->db_env, file, flags);
4438 MYDB_END_ALLOW_THREADS;
4439 RETURN_IF_ERR();
4440 RETURN_NONE();
4441}
4442#endif /* DBVER >= 4.4 */
4443
4444#if (DBVER >= 40)
4445static PyObject*
4446DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4447{
4448 int err;
4449 DB_LOG_STAT* statp = NULL;
4450 PyObject* d = NULL;
4451 u_int32_t flags = 0;
4452
4453 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4454 return NULL;
4455 CHECK_ENV_NOT_CLOSED(self);
4456
4457 MYDB_BEGIN_ALLOW_THREADS;
4458 err = self->db_env->log_stat(self->db_env, &statp, flags);
4459 MYDB_END_ALLOW_THREADS;
4460 RETURN_IF_ERR();
4461
4462 /* Turn the stat structure into a dictionary */
4463 d = PyDict_New();
4464 if (d == NULL) {
4465 if (statp)
4466 free(statp);
4467 return NULL;
4468 }
4469
4470#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4471
4472 MAKE_ENTRY(magic);
4473 MAKE_ENTRY(version);
4474 MAKE_ENTRY(mode);
4475 MAKE_ENTRY(lg_bsize);
4476#if (DBVER >= 44)
4477 MAKE_ENTRY(lg_size);
4478 MAKE_ENTRY(record);
4479#endif
4480#if (DBVER <= 40)
4481 MAKE_ENTRY(lg_max);
4482#endif
4483 MAKE_ENTRY(w_mbytes);
4484 MAKE_ENTRY(w_bytes);
4485 MAKE_ENTRY(wc_mbytes);
4486 MAKE_ENTRY(wc_bytes);
4487 MAKE_ENTRY(wcount);
4488 MAKE_ENTRY(wcount_fill);
4489#if (DBVER >= 44)
4490 MAKE_ENTRY(rcount);
4491#endif
4492 MAKE_ENTRY(scount);
4493 MAKE_ENTRY(cur_file);
4494 MAKE_ENTRY(cur_offset);
4495 MAKE_ENTRY(disk_file);
4496 MAKE_ENTRY(disk_offset);
4497 MAKE_ENTRY(maxcommitperflush);
4498 MAKE_ENTRY(mincommitperflush);
4499 MAKE_ENTRY(regsize);
4500 MAKE_ENTRY(region_wait);
4501 MAKE_ENTRY(region_nowait);
4502
4503#undef MAKE_ENTRY
4504 free(statp);
4505 return d;
4506} /* DBEnv_log_stat */
4507#endif /* DBVER >= 4.0 for log_stat method */
4508
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004509
4510static PyObject*
4511DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4512{
4513 int err;
4514 DB_LOCK_STAT* sp;
4515 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004516 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004517
4518 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4519 return NULL;
4520 CHECK_ENV_NOT_CLOSED(self);
4521
4522 MYDB_BEGIN_ALLOW_THREADS;
4523#if (DBVER >= 40)
4524 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4525#else
4526#if (DBVER >= 33)
4527 err = lock_stat(self->db_env, &sp);
4528#else
4529 err = lock_stat(self->db_env, &sp, NULL);
4530#endif
4531#endif
4532 MYDB_END_ALLOW_THREADS;
4533 RETURN_IF_ERR();
4534
4535 /* Turn the stat structure into a dictionary */
4536 d = PyDict_New();
4537 if (d == NULL) {
4538 free(sp);
4539 return NULL;
4540 }
4541
4542#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4543
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004544#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004545 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004546#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004547 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004548 MAKE_ENTRY(maxlocks);
4549 MAKE_ENTRY(maxlockers);
4550 MAKE_ENTRY(maxobjects);
4551 MAKE_ENTRY(nlocks);
4552 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004553 MAKE_ENTRY(nlockers);
4554 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004555 MAKE_ENTRY(nobjects);
4556 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004557 MAKE_ENTRY(nrequests);
4558 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004559#if (DBVER < 44)
4560 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004561 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004562#else
4563 MAKE_ENTRY(lock_nowait);
4564 MAKE_ENTRY(lock_wait);
4565#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004566 MAKE_ENTRY(ndeadlocks);
4567 MAKE_ENTRY(regsize);
4568 MAKE_ENTRY(region_wait);
4569 MAKE_ENTRY(region_nowait);
4570
4571#undef MAKE_ENTRY
4572 free(sp);
4573 return d;
4574}
4575
4576
4577static PyObject*
4578DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4579{
4580 int flags=0;
4581 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004582 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004583 PyObject* list;
4584 PyObject* item = NULL;
4585
4586 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4587 return NULL;
4588
4589 CHECK_ENV_NOT_CLOSED(self);
4590 MYDB_BEGIN_ALLOW_THREADS;
4591#if (DBVER >= 40)
4592 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4593#elif (DBVER == 33)
4594 err = log_archive(self->db_env, &log_list, flags);
4595#else
4596 err = log_archive(self->db_env, &log_list, flags, NULL);
4597#endif
4598 MYDB_END_ALLOW_THREADS;
4599 RETURN_IF_ERR();
4600
4601 list = PyList_New(0);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004602 if (list == NULL) {
4603 if (log_list)
4604 free(log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004605 return NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004606 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004607
4608 if (log_list) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004609 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004610 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
Martin v. Löwis64ce5052007-08-05 15:39:16 +00004611 item = PyUnicode_FromString (*log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004612 if (item == NULL) {
4613 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004614 list = NULL;
4615 break;
4616 }
4617 PyList_Append(list, item);
4618 Py_DECREF(item);
4619 }
4620 free(log_list_start);
4621 }
4622 return list;
4623}
4624
4625
4626static PyObject*
4627DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4628{
4629 int err;
4630 DB_TXN_STAT* sp;
4631 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004632 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004633
4634 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4635 return NULL;
4636 CHECK_ENV_NOT_CLOSED(self);
4637
4638 MYDB_BEGIN_ALLOW_THREADS;
4639#if (DBVER >= 40)
4640 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4641#elif (DBVER == 33)
4642 err = txn_stat(self->db_env, &sp);
4643#else
4644 err = txn_stat(self->db_env, &sp, NULL);
4645#endif
4646 MYDB_END_ALLOW_THREADS;
4647 RETURN_IF_ERR();
4648
4649 /* Turn the stat structure into a dictionary */
4650 d = PyDict_New();
4651 if (d == NULL) {
4652 free(sp);
4653 return NULL;
4654 }
4655
4656#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00004657#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004658
Guido van Rossumd8faa362007-04-27 19:54:29 +00004659 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004660 MAKE_ENTRY(last_txnid);
4661 MAKE_ENTRY(maxtxns);
4662 MAKE_ENTRY(nactive);
4663 MAKE_ENTRY(maxnactive);
4664 MAKE_ENTRY(nbegins);
4665 MAKE_ENTRY(naborts);
4666 MAKE_ENTRY(ncommits);
4667 MAKE_ENTRY(regsize);
4668 MAKE_ENTRY(region_wait);
4669 MAKE_ENTRY(region_nowait);
4670
4671#undef MAKE_ENTRY
Guido van Rossumd8faa362007-04-27 19:54:29 +00004672#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004673 free(sp);
4674 return d;
4675}
4676
4677
4678static PyObject*
4679DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4680{
4681 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004682 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004683
4684 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4685 return NULL;
4686 CHECK_ENV_NOT_CLOSED(self);
4687
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004688 if (self->moduleFlags.getReturnsNone)
4689 ++oldValue;
4690 if (self->moduleFlags.cursorSetReturnsNone)
4691 ++oldValue;
4692 self->moduleFlags.getReturnsNone = (flags >= 1);
4693 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004694 return PyInt_FromLong(oldValue);
4695}
4696
4697
4698/* --------------------------------------------------------------------- */
4699/* DBTxn methods */
4700
4701
4702static PyObject*
4703DBTxn_commit(DBTxnObject* self, PyObject* args)
4704{
4705 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004706 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004707
4708 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4709 return NULL;
4710
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004711 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004712 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4713 "after txn_commit or txn_abort");
4714 PyErr_SetObject(DBError, t);
4715 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004716 return NULL;
4717 }
4718 txn = self->txn;
4719 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004720 MYDB_BEGIN_ALLOW_THREADS;
4721#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004722 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004723#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004724 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004725#endif
4726 MYDB_END_ALLOW_THREADS;
4727 RETURN_IF_ERR();
4728 RETURN_NONE();
4729}
4730
4731static PyObject*
4732DBTxn_prepare(DBTxnObject* self, PyObject* args)
4733{
4734#if (DBVER >= 33)
4735 int err;
4736 char* gid=NULL;
4737 int gid_size=0;
4738
Gregory P. Smith361ed152007-08-23 07:32:27 +00004739 if (!PyArg_ParseTuple(args, "y#:prepare", &gid, &gid_size))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004740 return NULL;
4741
4742 if (gid_size != DB_XIDDATASIZE) {
4743 PyErr_SetString(PyExc_TypeError,
4744 "gid must be DB_XIDDATASIZE bytes long");
4745 return NULL;
4746 }
4747
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004748 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004749 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4750 "after txn_commit or txn_abort");
4751 PyErr_SetObject(DBError, t);
4752 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004753 return NULL;
4754 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004755 MYDB_BEGIN_ALLOW_THREADS;
4756#if (DBVER >= 40)
4757 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4758#else
4759 err = txn_prepare(self->txn, (u_int8_t*)gid);
4760#endif
4761 MYDB_END_ALLOW_THREADS;
4762 RETURN_IF_ERR();
4763 RETURN_NONE();
4764#else
4765 int err;
4766
4767 if (!PyArg_ParseTuple(args, ":prepare"))
4768 return NULL;
4769
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004770 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004771 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4772 "after txn_commit or txn_abort");
4773 PyErr_SetObject(DBError, t);
4774 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004775 return NULL;
4776 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004777 MYDB_BEGIN_ALLOW_THREADS;
4778 err = txn_prepare(self->txn);
4779 MYDB_END_ALLOW_THREADS;
4780 RETURN_IF_ERR();
4781 RETURN_NONE();
4782#endif
4783}
4784
4785
4786static PyObject*
4787DBTxn_abort(DBTxnObject* self, PyObject* args)
4788{
4789 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004790 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004791
4792 if (!PyArg_ParseTuple(args, ":abort"))
4793 return NULL;
4794
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004795 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004796 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4797 "after txn_commit or txn_abort");
4798 PyErr_SetObject(DBError, t);
4799 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004800 return NULL;
4801 }
4802 txn = self->txn;
4803 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004804 MYDB_BEGIN_ALLOW_THREADS;
4805#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004806 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004807#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004808 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004809#endif
4810 MYDB_END_ALLOW_THREADS;
4811 RETURN_IF_ERR();
4812 RETURN_NONE();
4813}
4814
4815
4816static PyObject*
4817DBTxn_id(DBTxnObject* self, PyObject* args)
4818{
4819 int id;
4820
4821 if (!PyArg_ParseTuple(args, ":id"))
4822 return NULL;
4823
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004824 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004825 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4826 "after txn_commit or txn_abort");
4827 PyErr_SetObject(DBError, t);
4828 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004829 return NULL;
4830 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004831 MYDB_BEGIN_ALLOW_THREADS;
4832#if (DBVER >= 40)
4833 id = self->txn->id(self->txn);
4834#else
4835 id = txn_id(self->txn);
4836#endif
4837 MYDB_END_ALLOW_THREADS;
4838 return PyInt_FromLong(id);
4839}
4840
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004841#if (DBVER >= 43)
4842/* --------------------------------------------------------------------- */
4843/* DBSequence methods */
4844
4845
4846static PyObject*
4847DBSequence_close(DBSequenceObject* self, PyObject* args)
4848{
4849 int err, flags=0;
4850 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4851 return NULL;
4852 CHECK_SEQUENCE_NOT_CLOSED(self)
4853
4854 MYDB_BEGIN_ALLOW_THREADS
4855 err = self->sequence->close(self->sequence, flags);
4856 self->sequence = NULL;
4857 MYDB_END_ALLOW_THREADS
4858
4859 RETURN_IF_ERR();
4860
4861 RETURN_NONE();
4862}
4863
4864static PyObject*
4865DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4866{
4867 int err, flags = 0;
4868 int delta = 1;
4869 db_seq_t value;
4870 PyObject *txnobj = NULL;
4871 DB_TXN *txn = NULL;
4872 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4873 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4874 return NULL;
4875 CHECK_SEQUENCE_NOT_CLOSED(self)
4876
4877 if (!checkTxnObj(txnobj, &txn))
4878 return NULL;
4879
4880 MYDB_BEGIN_ALLOW_THREADS
4881 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4882 MYDB_END_ALLOW_THREADS
4883
4884 RETURN_IF_ERR();
4885 return PyLong_FromLongLong(value);
4886
4887}
4888
4889static PyObject*
4890DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4891{
4892 if (!PyArg_ParseTuple(args,":get_dbp"))
4893 return NULL;
4894 CHECK_SEQUENCE_NOT_CLOSED(self)
4895 Py_INCREF(self->mydb);
4896 return (PyObject* )self->mydb;
4897}
4898
4899static PyObject*
4900DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4901{
4902 int err;
4903 DBT key;
Guido van Rossum8ce8a782007-11-01 19:42:39 +00004904 PyObject *retval = NULL;
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004905 key.flags = DB_DBT_MALLOC;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004906 CHECK_SEQUENCE_NOT_CLOSED(self)
4907 MYDB_BEGIN_ALLOW_THREADS
4908 err = self->sequence->get_key(self->sequence, &key);
4909 MYDB_END_ALLOW_THREADS
4910
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004911 if (!err)
4912 retval = PyBytes_FromStringAndSize(key.data, key.size);
4913
4914 free_dbt(&key);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004915 RETURN_IF_ERR();
4916
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004917 return retval;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004918}
4919
4920static PyObject*
4921DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4922{
4923 int err;
4924 db_seq_t value;
4925 if (!PyArg_ParseTuple(args,"L:init_value", &value))
4926 return NULL;
4927 CHECK_SEQUENCE_NOT_CLOSED(self)
4928
4929 MYDB_BEGIN_ALLOW_THREADS
4930 err = self->sequence->initial_value(self->sequence, value);
4931 MYDB_END_ALLOW_THREADS
4932
4933 RETURN_IF_ERR();
4934
4935 RETURN_NONE();
4936}
4937
4938static PyObject*
4939DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4940{
4941 int err, flags = 0;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004942 PyObject *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00004943 Py_buffer *key_buf_view = NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004944 PyObject *txnobj = NULL;
4945 DB_TXN *txn = NULL;
4946 DBT key;
4947
4948 static char* kwnames[] = {"key", "txn", "flags", NULL };
4949 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
4950 return NULL;
4951
4952 if (!checkTxnObj(txnobj, &txn))
4953 return NULL;
4954
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004955 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004956 return NULL;
4957
4958 MYDB_BEGIN_ALLOW_THREADS
4959 err = self->sequence->open(self->sequence, txn, &key, flags);
4960 MYDB_END_ALLOW_THREADS
4961
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004962 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004963 RETURN_IF_ERR();
4964
4965 RETURN_NONE();
4966}
4967
4968static PyObject*
4969DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4970{
4971 int err, flags = 0;
4972 PyObject *txnobj = NULL;
4973 DB_TXN *txn = NULL;
4974
4975 static char* kwnames[] = {"txn", "flags", NULL };
4976 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
4977 return NULL;
4978
4979 if (!checkTxnObj(txnobj, &txn))
4980 return NULL;
4981
4982 CHECK_SEQUENCE_NOT_CLOSED(self)
4983
4984 MYDB_BEGIN_ALLOW_THREADS
4985 err = self->sequence->remove(self->sequence, txn, flags);
4986 MYDB_END_ALLOW_THREADS
4987
4988 RETURN_IF_ERR();
4989 RETURN_NONE();
4990}
4991
4992static PyObject*
4993DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4994{
4995 int err, size;
4996 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
4997 return NULL;
4998 CHECK_SEQUENCE_NOT_CLOSED(self)
4999
5000 MYDB_BEGIN_ALLOW_THREADS
5001 err = self->sequence->set_cachesize(self->sequence, size);
5002 MYDB_END_ALLOW_THREADS
5003
5004 RETURN_IF_ERR();
5005 RETURN_NONE();
5006}
5007
5008static PyObject*
5009DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
5010{
5011 int err, size;
5012 if (!PyArg_ParseTuple(args,":get_cachesize"))
5013 return NULL;
5014 CHECK_SEQUENCE_NOT_CLOSED(self)
5015
5016 MYDB_BEGIN_ALLOW_THREADS
5017 err = self->sequence->get_cachesize(self->sequence, &size);
5018 MYDB_END_ALLOW_THREADS
5019
5020 RETURN_IF_ERR();
5021 return PyInt_FromLong(size);
5022}
5023
5024static PyObject*
5025DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5026{
5027 int err, flags = 0;
5028 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
5029 return NULL;
5030 CHECK_SEQUENCE_NOT_CLOSED(self)
5031
5032 MYDB_BEGIN_ALLOW_THREADS
5033 err = self->sequence->set_flags(self->sequence, flags);
5034 MYDB_END_ALLOW_THREADS
5035
5036 RETURN_IF_ERR();
5037 RETURN_NONE();
5038
5039}
5040
5041static PyObject*
5042DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5043{
5044 unsigned int flags;
5045 int err;
5046 if (!PyArg_ParseTuple(args,":get_flags"))
5047 return NULL;
5048 CHECK_SEQUENCE_NOT_CLOSED(self)
5049
5050 MYDB_BEGIN_ALLOW_THREADS
5051 err = self->sequence->get_flags(self->sequence, &flags);
5052 MYDB_END_ALLOW_THREADS
5053
5054 RETURN_IF_ERR();
5055 return PyInt_FromLong((int)flags);
5056}
5057
5058static PyObject*
5059DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5060{
5061 int err;
5062 db_seq_t min, max;
5063 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
5064 return NULL;
5065 CHECK_SEQUENCE_NOT_CLOSED(self)
5066
5067 MYDB_BEGIN_ALLOW_THREADS
5068 err = self->sequence->set_range(self->sequence, min, max);
5069 MYDB_END_ALLOW_THREADS
5070
5071 RETURN_IF_ERR();
5072 RETURN_NONE();
5073}
5074
5075static PyObject*
5076DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5077{
5078 int err;
5079 db_seq_t min, max;
5080 if (!PyArg_ParseTuple(args,":get_range"))
5081 return NULL;
5082 CHECK_SEQUENCE_NOT_CLOSED(self)
5083
5084 MYDB_BEGIN_ALLOW_THREADS
5085 err = self->sequence->get_range(self->sequence, &min, &max);
5086 MYDB_END_ALLOW_THREADS
5087
5088 RETURN_IF_ERR();
5089 return Py_BuildValue("(LL)", min, max);
5090}
5091
5092static PyObject*
5093DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5094{
5095 int err, flags = 0;
5096 DB_SEQUENCE_STAT* sp = NULL;
5097 PyObject* dict_stat;
5098 static char* kwnames[] = {"flags", NULL };
5099 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5100 return NULL;
5101 CHECK_SEQUENCE_NOT_CLOSED(self);
5102
5103 MYDB_BEGIN_ALLOW_THREADS;
5104 err = self->sequence->stat(self->sequence, &sp, flags);
5105 MYDB_END_ALLOW_THREADS;
5106 RETURN_IF_ERR();
5107
5108 if ((dict_stat = PyDict_New()) == NULL) {
5109 free(sp);
5110 return NULL;
5111 }
5112
5113
5114#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5115#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5116
5117 MAKE_INT_ENTRY(wait);
5118 MAKE_INT_ENTRY(nowait);
5119 MAKE_LONG_LONG_ENTRY(current);
5120 MAKE_LONG_LONG_ENTRY(value);
5121 MAKE_LONG_LONG_ENTRY(last_value);
5122 MAKE_LONG_LONG_ENTRY(min);
5123 MAKE_LONG_LONG_ENTRY(max);
5124 MAKE_INT_ENTRY(cache_size);
5125 MAKE_INT_ENTRY(flags);
5126
5127#undef MAKE_INT_ENTRY
5128#undef MAKE_LONG_LONG_ENTRY
5129
5130 free(sp);
5131 return dict_stat;
5132}
5133#endif
5134
5135
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005136/* --------------------------------------------------------------------- */
5137/* Method definition tables and type objects */
5138
5139static PyMethodDef DB_methods[] = {
5140 {"append", (PyCFunction)DB_append, METH_VARARGS},
5141#if (DBVER >= 33)
5142 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5143#endif
5144 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005145 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5146 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005147 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5148 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5149 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5150 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005151#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005152 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005153#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005154 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5155 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5156 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5157 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5158 {"join", (PyCFunction)DB_join, METH_VARARGS},
5159 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5160 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5161 {"items", (PyCFunction)DB_items, METH_VARARGS},
5162 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5163 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5164 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5165 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5166 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5167 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005168#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005169 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005170#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005171 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005172#if (DBVER >= 41)
5173 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5174#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005175 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5176 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5177 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5178 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5179 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5180 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5181 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5182 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5183 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005184 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005185 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005186 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5187#if (DBVER >= 33)
5188 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5189#endif
5190 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5191 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5192 {"values", (PyCFunction)DB_values, METH_VARARGS},
5193 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5194 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5195 {NULL, NULL} /* sentinel */
5196};
5197
5198
5199static PyMappingMethods DB_mapping = {
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005200 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005201 (binaryfunc)DB_subscript, /*mp_subscript*/
5202 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5203};
5204
5205
5206static PyMethodDef DBCursor_methods[] = {
5207 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5208 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5209 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5210 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5211 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5212 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5213 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005214#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005215 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005216#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005217 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5218 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5219 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5220 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5221 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5222 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5223 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5224 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005225 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005226 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005227 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5228 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5229 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5230 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5231 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5232 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5233 {NULL, NULL} /* sentinel */
5234};
5235
5236
5237static PyMethodDef DBEnv_methods[] = {
5238 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5239 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5240 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005241#if (DBVER >= 41)
5242 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5243 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5244 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5245#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005246#if (DBVER >= 40)
5247 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5248#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005249 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005250 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5251 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005252 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005253 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5254 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5255 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005256#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005257 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005258#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005259 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005260#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005261 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005262#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005263 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5264 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5265 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005266 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5267 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5268 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5269 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5270 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5271 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005272 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005273 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5274 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5275 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
Guido van Rossum77677112007-11-05 19:43:04 +00005276#if (DBVER >= 40)
5277 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
5278#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005279 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5280 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5281 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005282#if (DBVER >= 40)
5283 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5284#endif
5285#if (DBVER >= 44)
5286 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5287#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005288 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5289 {NULL, NULL} /* sentinel */
5290};
5291
5292
5293static PyMethodDef DBTxn_methods[] = {
5294 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5295 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5296 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5297 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5298 {NULL, NULL} /* sentinel */
5299};
5300
5301
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005302#if (DBVER >= 43)
5303static PyMethodDef DBSequence_methods[] = {
5304 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5305 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5306 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5307 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5308 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5309 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5310 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5311 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5312 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5313 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5314 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5315 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5316 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5317 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5318 {NULL, NULL} /* sentinel */
5319};
5320#endif
5321
5322
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005323static PyObject*
5324DB_getattr(DBObject* self, char *name)
5325{
5326 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5327}
5328
5329
5330static PyObject*
5331DBEnv_getattr(DBEnvObject* self, char *name)
5332{
5333 if (!strcmp(name, "db_home")) {
5334 CHECK_ENV_NOT_CLOSED(self);
5335 if (self->db_env->db_home == NULL) {
5336 RETURN_NONE();
5337 }
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005338 return PyUnicode_FromString(self->db_env->db_home);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005339 }
5340
5341 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5342}
5343
5344
5345static PyObject*
5346DBCursor_getattr(DBCursorObject* self, char *name)
5347{
5348 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5349}
5350
5351static PyObject*
5352DBTxn_getattr(DBTxnObject* self, char *name)
5353{
5354 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5355}
5356
5357static PyObject*
5358DBLock_getattr(DBLockObject* self, char *name)
5359{
5360 return NULL;
5361}
5362
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005363#if (DBVER >= 43)
5364static PyObject*
5365DBSequence_getattr(DBSequenceObject* self, char *name)
5366{
5367 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5368}
5369#endif
5370
Neal Norwitz227b5332006-03-22 09:28:35 +00005371static PyTypeObject DB_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005372 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005373 "DB", /*tp_name*/
5374 sizeof(DBObject), /*tp_basicsize*/
5375 0, /*tp_itemsize*/
5376 /* methods */
5377 (destructor)DB_dealloc, /*tp_dealloc*/
5378 0, /*tp_print*/
5379 (getattrfunc)DB_getattr, /*tp_getattr*/
5380 0, /*tp_setattr*/
5381 0, /*tp_compare*/
5382 0, /*tp_repr*/
5383 0, /*tp_as_number*/
5384 0, /*tp_as_sequence*/
5385 &DB_mapping,/*tp_as_mapping*/
5386 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005387 0, /* tp_call */
5388 0, /* tp_str */
5389 0, /* tp_getattro */
5390 0, /* tp_setattro */
5391 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005392 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005393 0, /* tp_doc */
5394 0, /* tp_traverse */
5395 0, /* tp_clear */
5396 0, /* tp_richcompare */
5397 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005398};
5399
5400
Neal Norwitz227b5332006-03-22 09:28:35 +00005401static PyTypeObject DBCursor_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005402 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005403 "DBCursor", /*tp_name*/
5404 sizeof(DBCursorObject), /*tp_basicsize*/
5405 0, /*tp_itemsize*/
5406 /* methods */
5407 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5408 0, /*tp_print*/
5409 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5410 0, /*tp_setattr*/
5411 0, /*tp_compare*/
5412 0, /*tp_repr*/
5413 0, /*tp_as_number*/
5414 0, /*tp_as_sequence*/
5415 0, /*tp_as_mapping*/
5416 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005417 0, /* tp_call */
5418 0, /* tp_str */
5419 0, /* tp_getattro */
5420 0, /* tp_setattro */
5421 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005422 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smitha703a212003-11-03 01:04:41 +00005423 0, /* tp_doc */
5424 0, /* tp_traverse */
5425 0, /* tp_clear */
5426 0, /* tp_richcompare */
5427 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005428};
5429
5430
Neal Norwitz227b5332006-03-22 09:28:35 +00005431static PyTypeObject DBEnv_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005432 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005433 "DBEnv", /*tp_name*/
5434 sizeof(DBEnvObject), /*tp_basicsize*/
5435 0, /*tp_itemsize*/
5436 /* methods */
5437 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5438 0, /*tp_print*/
5439 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5440 0, /*tp_setattr*/
5441 0, /*tp_compare*/
5442 0, /*tp_repr*/
5443 0, /*tp_as_number*/
5444 0, /*tp_as_sequence*/
5445 0, /*tp_as_mapping*/
5446 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005447 0, /* tp_call */
5448 0, /* tp_str */
5449 0, /* tp_getattro */
5450 0, /* tp_setattro */
5451 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005452 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005453 0, /* tp_doc */
5454 0, /* tp_traverse */
5455 0, /* tp_clear */
5456 0, /* tp_richcompare */
5457 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005458};
5459
Neal Norwitz227b5332006-03-22 09:28:35 +00005460static PyTypeObject DBTxn_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005461 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005462 "DBTxn", /*tp_name*/
5463 sizeof(DBTxnObject), /*tp_basicsize*/
5464 0, /*tp_itemsize*/
5465 /* methods */
5466 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5467 0, /*tp_print*/
5468 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5469 0, /*tp_setattr*/
5470 0, /*tp_compare*/
5471 0, /*tp_repr*/
5472 0, /*tp_as_number*/
5473 0, /*tp_as_sequence*/
5474 0, /*tp_as_mapping*/
5475 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005476 0, /* tp_call */
5477 0, /* tp_str */
5478 0, /* tp_getattro */
5479 0, /* tp_setattro */
5480 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005481 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005482 0, /* tp_doc */
5483 0, /* tp_traverse */
5484 0, /* tp_clear */
5485 0, /* tp_richcompare */
5486 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005487};
5488
5489
Neal Norwitz227b5332006-03-22 09:28:35 +00005490static PyTypeObject DBLock_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005491 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005492 "DBLock", /*tp_name*/
5493 sizeof(DBLockObject), /*tp_basicsize*/
5494 0, /*tp_itemsize*/
5495 /* methods */
5496 (destructor)DBLock_dealloc, /*tp_dealloc*/
5497 0, /*tp_print*/
5498 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5499 0, /*tp_setattr*/
5500 0, /*tp_compare*/
5501 0, /*tp_repr*/
5502 0, /*tp_as_number*/
5503 0, /*tp_as_sequence*/
5504 0, /*tp_as_mapping*/
5505 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005506 0, /* tp_call */
5507 0, /* tp_str */
5508 0, /* tp_getattro */
5509 0, /* tp_setattro */
5510 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005511 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005512 0, /* tp_doc */
5513 0, /* tp_traverse */
5514 0, /* tp_clear */
5515 0, /* tp_richcompare */
5516 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005517};
5518
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005519#if (DBVER >= 43)
5520static PyTypeObject DBSequence_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005521 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005522 "DBSequence", /*tp_name*/
5523 sizeof(DBSequenceObject), /*tp_basicsize*/
5524 0, /*tp_itemsize*/
5525 /* methods */
5526 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5527 0, /*tp_print*/
5528 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5529 0, /*tp_setattr*/
5530 0, /*tp_compare*/
5531 0, /*tp_repr*/
5532 0, /*tp_as_number*/
5533 0, /*tp_as_sequence*/
5534 0, /*tp_as_mapping*/
5535 0, /*tp_hash*/
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005536 0, /* tp_call */
5537 0, /* tp_str */
5538 0, /* tp_getattro */
5539 0, /* tp_setattro */
5540 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005541 Py_TPFLAGS_DEFAULT, /* tp_flags */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005542 0, /* tp_doc */
5543 0, /* tp_traverse */
5544 0, /* tp_clear */
5545 0, /* tp_richcompare */
5546 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005547};
5548#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005549
5550/* --------------------------------------------------------------------- */
5551/* Module-level functions */
5552
5553static PyObject*
5554DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5555{
5556 PyObject* dbenvobj = NULL;
5557 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005558 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005559
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005560 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5561 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005562 return NULL;
5563 if (dbenvobj == Py_None)
5564 dbenvobj = NULL;
5565 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5566 makeTypeError("DBEnv", dbenvobj);
5567 return NULL;
5568 }
5569
5570 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5571}
5572
5573
5574static PyObject*
5575DBEnv_construct(PyObject* self, PyObject* args)
5576{
5577 int flags = 0;
5578 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5579 return (PyObject* )newDBEnvObject(flags);
5580}
5581
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005582#if (DBVER >= 43)
5583static PyObject*
5584DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5585{
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005586 PyObject* dbobj;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005587 int flags = 0;
5588 static char* kwnames[] = { "db", "flags", NULL};
5589
5590 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5591 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005592 if (!DBObject_Check(dbobj)) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005593 makeTypeError("DB", dbobj);
5594 return NULL;
5595 }
5596 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5597}
5598#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005599
5600static char bsddb_version_doc[] =
5601"Returns a tuple of major, minor, and patch release numbers of the\n\
5602underlying DB library.";
5603
5604static PyObject*
5605bsddb_version(PyObject* self, PyObject* args)
5606{
5607 int major, minor, patch;
5608
5609 if (!PyArg_ParseTuple(args, ":version"))
5610 return NULL;
5611 db_version(&major, &minor, &patch);
5612 return Py_BuildValue("(iii)", major, minor, patch);
5613}
5614
5615
5616/* List of functions defined in the module */
5617
5618static PyMethodDef bsddb_methods[] = {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005619 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5620 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5621#if (DBVER >= 43)
5622 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5623#endif
5624 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005625 {NULL, NULL} /* sentinel */
5626};
5627
Guido van Rossum8ce8a782007-11-01 19:42:39 +00005628/* API structure */
5629static BSDDB_api bsddb_api;
5630
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005631
5632/* --------------------------------------------------------------------- */
5633/* Module initialization */
5634
5635
5636/* Convenience routine to export an integer value.
5637 * Errors are silently ignored, for better or for worse...
5638 */
5639#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5640
Gregory P. Smith41631e82003-09-21 00:08:14 +00005641#define MODULE_NAME_MAX_LEN 11
5642static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005643
Neal Norwitzf6657e62006-12-28 04:47:50 +00005644PyMODINIT_FUNC init_bsddb(void)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005645{
5646 PyObject* m;
5647 PyObject* d;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005648 PyObject* pybsddb_version_s = PyUnicode_FromString(PY_BSDDB_VERSION);
5649 PyObject* db_version_s = PyUnicode_FromString(DB_VERSION_STRING);
5650 PyObject* svnid_s = PyUnicode_FromString(svn_id);
Guido van Rossum8ce8a782007-11-01 19:42:39 +00005651 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005652
5653 /* Initialize the type of the new type objects here; doing it here
5654 is required for portability to Windows without requiring C++. */
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005655 Py_Type(&DB_Type) = &PyType_Type;
5656 Py_Type(&DBCursor_Type) = &PyType_Type;
5657 Py_Type(&DBEnv_Type) = &PyType_Type;
5658 Py_Type(&DBTxn_Type) = &PyType_Type;
5659 Py_Type(&DBLock_Type) = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005660#if (DBVER >= 43)
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005661 Py_Type(&DBSequence_Type) = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005662#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005663
5664
Mark Hammonda69d4092003-04-22 23:13:27 +00005665#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005666 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005667 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005668#endif
5669
5670 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005671 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005672 if (m == NULL)
5673 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005674
5675 /* Add some symbolic constants to the module */
5676 d = PyModule_GetDict(m);
5677 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005678 PyDict_SetItemString(d, "cvsid", svnid_s);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005679 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5680 Py_DECREF(pybsddb_version_s);
5681 pybsddb_version_s = NULL;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005682 Py_DECREF(svnid_s);
5683 svnid_s = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005684 Py_DECREF(db_version_s);
5685 db_version_s = NULL;
5686
5687 ADD_INT(d, DB_VERSION_MAJOR);
5688 ADD_INT(d, DB_VERSION_MINOR);
5689 ADD_INT(d, DB_VERSION_PATCH);
5690
5691 ADD_INT(d, DB_MAX_PAGES);
5692 ADD_INT(d, DB_MAX_RECORDS);
5693
Gregory P. Smith41631e82003-09-21 00:08:14 +00005694#if (DBVER >= 42)
5695 ADD_INT(d, DB_RPCCLIENT);
5696#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005697 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005698 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5699 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5700#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005701 ADD_INT(d, DB_XA_CREATE);
5702
5703 ADD_INT(d, DB_CREATE);
5704 ADD_INT(d, DB_NOMMAP);
5705 ADD_INT(d, DB_THREAD);
5706
5707 ADD_INT(d, DB_FORCE);
5708 ADD_INT(d, DB_INIT_CDB);
5709 ADD_INT(d, DB_INIT_LOCK);
5710 ADD_INT(d, DB_INIT_LOG);
5711 ADD_INT(d, DB_INIT_MPOOL);
5712 ADD_INT(d, DB_INIT_TXN);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005713 ADD_INT(d, DB_JOINENV);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005714
5715 ADD_INT(d, DB_RECOVER);
5716 ADD_INT(d, DB_RECOVER_FATAL);
5717 ADD_INT(d, DB_TXN_NOSYNC);
5718 ADD_INT(d, DB_USE_ENVIRON);
5719 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5720
5721 ADD_INT(d, DB_LOCKDOWN);
5722 ADD_INT(d, DB_PRIVATE);
5723 ADD_INT(d, DB_SYSTEM_MEM);
5724
5725 ADD_INT(d, DB_TXN_SYNC);
5726 ADD_INT(d, DB_TXN_NOWAIT);
5727
5728 ADD_INT(d, DB_EXCL);
5729 ADD_INT(d, DB_FCNTL_LOCKING);
5730 ADD_INT(d, DB_ODDFILESIZE);
5731 ADD_INT(d, DB_RDWRMASTER);
5732 ADD_INT(d, DB_RDONLY);
5733 ADD_INT(d, DB_TRUNCATE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005734 ADD_INT(d, DB_EXTENT);
5735 ADD_INT(d, DB_CDB_ALLDB);
5736 ADD_INT(d, DB_VERIFY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005737 ADD_INT(d, DB_UPGRADE);
5738
5739 ADD_INT(d, DB_AGGRESSIVE);
5740 ADD_INT(d, DB_NOORDERCHK);
5741 ADD_INT(d, DB_ORDERCHKONLY);
5742 ADD_INT(d, DB_PR_PAGE);
5743#if ! (DBVER >= 33)
5744 ADD_INT(d, DB_VRFY_FLAGMASK);
5745 ADD_INT(d, DB_PR_HEADERS);
5746#endif
5747 ADD_INT(d, DB_PR_RECOVERYTEST);
5748 ADD_INT(d, DB_SALVAGE);
5749
5750 ADD_INT(d, DB_LOCK_NORUN);
5751 ADD_INT(d, DB_LOCK_DEFAULT);
5752 ADD_INT(d, DB_LOCK_OLDEST);
5753 ADD_INT(d, DB_LOCK_RANDOM);
5754 ADD_INT(d, DB_LOCK_YOUNGEST);
5755#if (DBVER >= 33)
5756 ADD_INT(d, DB_LOCK_MAXLOCKS);
5757 ADD_INT(d, DB_LOCK_MINLOCKS);
5758 ADD_INT(d, DB_LOCK_MINWRITE);
5759#endif
5760
5761
5762#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005763 /* docs say to use zero instead */
5764 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005765#else
5766 ADD_INT(d, DB_LOCK_CONFLICT);
5767#endif
5768
5769 ADD_INT(d, DB_LOCK_DUMP);
5770 ADD_INT(d, DB_LOCK_GET);
5771 ADD_INT(d, DB_LOCK_INHERIT);
5772 ADD_INT(d, DB_LOCK_PUT);
5773 ADD_INT(d, DB_LOCK_PUT_ALL);
5774 ADD_INT(d, DB_LOCK_PUT_OBJ);
5775
5776 ADD_INT(d, DB_LOCK_NG);
5777 ADD_INT(d, DB_LOCK_READ);
5778 ADD_INT(d, DB_LOCK_WRITE);
5779 ADD_INT(d, DB_LOCK_NOWAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005780 ADD_INT(d, DB_LOCK_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005781 ADD_INT(d, DB_LOCK_IWRITE);
5782 ADD_INT(d, DB_LOCK_IREAD);
5783 ADD_INT(d, DB_LOCK_IWR);
5784#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005785#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005786 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005787#else
5788 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5789#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005790 ADD_INT(d, DB_LOCK_WWRITE);
5791#endif
5792
5793 ADD_INT(d, DB_LOCK_RECORD);
5794 ADD_INT(d, DB_LOCK_UPGRADE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005795 ADD_INT(d, DB_LOCK_SWITCH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005796#if (DBVER >= 33)
5797 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5798#endif
5799
5800 ADD_INT(d, DB_LOCK_NOWAIT);
5801 ADD_INT(d, DB_LOCK_RECORD);
5802 ADD_INT(d, DB_LOCK_UPGRADE);
5803
5804#if (DBVER >= 33)
5805 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005806#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005807 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005808#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005809 ADD_INT(d, DB_LSTAT_FREE);
5810 ADD_INT(d, DB_LSTAT_HELD);
5811#if (DBVER == 33)
5812 ADD_INT(d, DB_LSTAT_NOGRANT);
5813#endif
5814 ADD_INT(d, DB_LSTAT_PENDING);
5815 ADD_INT(d, DB_LSTAT_WAITING);
5816#endif
5817
5818 ADD_INT(d, DB_ARCH_ABS);
5819 ADD_INT(d, DB_ARCH_DATA);
5820 ADD_INT(d, DB_ARCH_LOG);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005821#if (DBVER >= 42)
5822 ADD_INT(d, DB_ARCH_REMOVE);
5823#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005824
5825 ADD_INT(d, DB_BTREE);
5826 ADD_INT(d, DB_HASH);
5827 ADD_INT(d, DB_RECNO);
5828 ADD_INT(d, DB_QUEUE);
5829 ADD_INT(d, DB_UNKNOWN);
5830
5831 ADD_INT(d, DB_DUP);
5832 ADD_INT(d, DB_DUPSORT);
5833 ADD_INT(d, DB_RECNUM);
5834 ADD_INT(d, DB_RENUMBER);
5835 ADD_INT(d, DB_REVSPLITOFF);
5836 ADD_INT(d, DB_SNAPSHOT);
5837
5838 ADD_INT(d, DB_JOIN_NOSORT);
5839
5840 ADD_INT(d, DB_AFTER);
5841 ADD_INT(d, DB_APPEND);
5842 ADD_INT(d, DB_BEFORE);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005843#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005844 ADD_INT(d, DB_CACHED_COUNTS);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005845#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005846#if (DBVER >= 41)
5847 _addIntToDict(d, "DB_CHECKPOINT", 0);
5848#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005849 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005850 ADD_INT(d, DB_CURLSN);
5851#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005852#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005853 ADD_INT(d, DB_COMMIT);
5854#endif
5855 ADD_INT(d, DB_CONSUME);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005856 ADD_INT(d, DB_CONSUME_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005857 ADD_INT(d, DB_CURRENT);
5858#if (DBVER >= 33)
5859 ADD_INT(d, DB_FAST_STAT);
5860#endif
5861 ADD_INT(d, DB_FIRST);
5862 ADD_INT(d, DB_FLUSH);
5863 ADD_INT(d, DB_GET_BOTH);
5864 ADD_INT(d, DB_GET_RECNO);
5865 ADD_INT(d, DB_JOIN_ITEM);
5866 ADD_INT(d, DB_KEYFIRST);
5867 ADD_INT(d, DB_KEYLAST);
5868 ADD_INT(d, DB_LAST);
5869 ADD_INT(d, DB_NEXT);
5870 ADD_INT(d, DB_NEXT_DUP);
5871 ADD_INT(d, DB_NEXT_NODUP);
5872 ADD_INT(d, DB_NODUPDATA);
5873 ADD_INT(d, DB_NOOVERWRITE);
5874 ADD_INT(d, DB_NOSYNC);
5875 ADD_INT(d, DB_POSITION);
5876 ADD_INT(d, DB_PREV);
5877 ADD_INT(d, DB_PREV_NODUP);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005878#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005879 ADD_INT(d, DB_RECORDCOUNT);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005880#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005881 ADD_INT(d, DB_SET);
5882 ADD_INT(d, DB_SET_RANGE);
5883 ADD_INT(d, DB_SET_RECNO);
5884 ADD_INT(d, DB_WRITECURSOR);
5885
5886 ADD_INT(d, DB_OPFLAGS_MASK);
5887 ADD_INT(d, DB_RMW);
5888#if (DBVER >= 33)
5889 ADD_INT(d, DB_DIRTY_READ);
5890 ADD_INT(d, DB_MULTIPLE);
5891 ADD_INT(d, DB_MULTIPLE_KEY);
5892#endif
5893
Gregory P. Smith29602d22006-01-24 09:46:48 +00005894#if (DBVER >= 44)
5895 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5896 ADD_INT(d, DB_READ_COMMITTED);
5897#endif
5898
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005899#if (DBVER >= 33)
5900 ADD_INT(d, DB_DONOTINDEX);
Gregory P. Smith361ed152007-08-23 07:32:27 +00005901 ADD_INT(d, DB_XIDDATASIZE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005902#endif
5903
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005904#if (DBVER >= 41)
5905 _addIntToDict(d, "DB_INCOMPLETE", 0);
5906#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005907 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005908#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005909 ADD_INT(d, DB_KEYEMPTY);
5910 ADD_INT(d, DB_KEYEXIST);
5911 ADD_INT(d, DB_LOCK_DEADLOCK);
5912 ADD_INT(d, DB_LOCK_NOTGRANTED);
5913 ADD_INT(d, DB_NOSERVER);
5914 ADD_INT(d, DB_NOSERVER_HOME);
5915 ADD_INT(d, DB_NOSERVER_ID);
5916 ADD_INT(d, DB_NOTFOUND);
5917 ADD_INT(d, DB_OLD_VERSION);
5918 ADD_INT(d, DB_RUNRECOVERY);
5919 ADD_INT(d, DB_VERIFY_BAD);
5920#if (DBVER >= 33)
5921 ADD_INT(d, DB_PAGE_NOTFOUND);
5922 ADD_INT(d, DB_SECONDARY_BAD);
5923#endif
5924#if (DBVER >= 40)
5925 ADD_INT(d, DB_STAT_CLEAR);
5926 ADD_INT(d, DB_REGION_INIT);
5927 ADD_INT(d, DB_NOLOCKING);
5928 ADD_INT(d, DB_YIELDCPU);
5929 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5930 ADD_INT(d, DB_NOPANIC);
5931#endif
5932
Guido van Rossum2cc30da2007-11-02 23:46:40 +00005933#ifdef DB_REGISTER
5934 ADD_INT(d, DB_REGISTER);
5935#endif
5936
Gregory P. Smith41631e82003-09-21 00:08:14 +00005937#if (DBVER >= 42)
5938 ADD_INT(d, DB_TIME_NOTGRANTED);
5939 ADD_INT(d, DB_TXN_NOT_DURABLE);
5940 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5941 ADD_INT(d, DB_LOG_AUTOREMOVE);
5942 ADD_INT(d, DB_DIRECT_LOG);
5943 ADD_INT(d, DB_DIRECT_DB);
5944 ADD_INT(d, DB_INIT_REP);
5945 ADD_INT(d, DB_ENCRYPT);
5946 ADD_INT(d, DB_CHKSUM);
5947#endif
5948
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005949#if (DBVER >= 43)
5950 ADD_INT(d, DB_LOG_INMEMORY);
5951 ADD_INT(d, DB_BUFFER_SMALL);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005952 ADD_INT(d, DB_SEQ_DEC);
5953 ADD_INT(d, DB_SEQ_INC);
5954 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005955#endif
5956
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005957#if (DBVER >= 41)
5958 ADD_INT(d, DB_ENCRYPT_AES);
5959 ADD_INT(d, DB_AUTO_COMMIT);
5960#else
5961 /* allow berkeleydb 4.1 aware apps to run on older versions */
5962 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5963#endif
5964
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005965 ADD_INT(d, EINVAL);
5966 ADD_INT(d, EACCES);
5967 ADD_INT(d, ENOSPC);
5968 ADD_INT(d, ENOMEM);
5969 ADD_INT(d, EAGAIN);
5970 ADD_INT(d, EBUSY);
5971 ADD_INT(d, EEXIST);
5972 ADD_INT(d, ENOENT);
5973 ADD_INT(d, EPERM);
5974
Barry Warsaw1baa9822003-03-31 19:51:29 +00005975#if (DBVER >= 40)
5976 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5977 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5978#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005979
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005980 /* The exception name must be correct for pickled exception *
5981 * objects to unpickle properly. */
5982#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5983#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5984#else
5985#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5986#endif
5987
5988 /* All the rest of the exceptions derive only from DBError */
5989#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5990 PyDict_SetItemString(d, #name, name)
5991
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005992 /* The base exception class is DBError */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005993 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5994 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005995
Gregory P. Smithe9477062005-06-04 06:46:59 +00005996 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5997 * from both DBError and KeyError, since the API only supports
5998 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005999 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Guido van Rossum52cc1d82007-03-18 15:41:51 +00006000 {
6001 PyObject *builtin_mod = PyImport_ImportModule("__builtin__");
6002 PyDict_SetItemString(d, "__builtins__", builtin_mod);
6003 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00006004 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
6005 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006006 Py_file_input, d, d);
6007 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00006008 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006009 PyDict_DelItemString(d, "KeyError");
6010
6011
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006012#if !INCOMPLETE_IS_WARNING
6013 MAKE_EX(DBIncompleteError);
6014#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00006015 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006016 MAKE_EX(DBKeyEmptyError);
6017 MAKE_EX(DBKeyExistError);
6018 MAKE_EX(DBLockDeadlockError);
6019 MAKE_EX(DBLockNotGrantedError);
6020 MAKE_EX(DBOldVersionError);
6021 MAKE_EX(DBRunRecoveryError);
6022 MAKE_EX(DBVerifyBadError);
6023 MAKE_EX(DBNoServerError);
6024 MAKE_EX(DBNoServerHomeError);
6025 MAKE_EX(DBNoServerIDError);
6026#if (DBVER >= 33)
6027 MAKE_EX(DBPageNotFoundError);
6028 MAKE_EX(DBSecondaryBadError);
6029#endif
6030
6031 MAKE_EX(DBInvalidArgError);
6032 MAKE_EX(DBAccessError);
6033 MAKE_EX(DBNoSpaceError);
6034 MAKE_EX(DBNoMemoryError);
6035 MAKE_EX(DBAgainError);
6036 MAKE_EX(DBBusyError);
6037 MAKE_EX(DBFileExistsError);
6038 MAKE_EX(DBNoSuchFileError);
6039 MAKE_EX(DBPermissionsError);
6040
6041#undef MAKE_EX
6042
Guido van Rossum8ce8a782007-11-01 19:42:39 +00006043 /* Initiliase the C API structure and add it to the module */
6044 bsddb_api.db_type = &DB_Type;
6045 bsddb_api.dbcursor_type = &DBCursor_Type;
6046 bsddb_api.dbenv_type = &DBEnv_Type;
6047 bsddb_api.dbtxn_type = &DBTxn_Type;
6048 bsddb_api.dblock_type = &DBLock_Type;
6049#if (DBVER >= 43)
6050 bsddb_api.dbsequence_type = &DBSequence_Type;
6051#endif
6052 bsddb_api.makeDBError = makeDBError;
6053
6054 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
6055 PyDict_SetItemString(d, "api", py_api);
6056 Py_DECREF(py_api);
6057
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006058 /* Check for errors */
6059 if (PyErr_Occurred()) {
6060 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006061 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006062 }
6063}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006064
6065/* allow this module to be named _pybsddb so that it can be installed
6066 * and imported on top of python >= 2.3 that includes its own older
6067 * copy of the library named _bsddb without importing the old version. */
Neal Norwitzf6657e62006-12-28 04:47:50 +00006068PyMODINIT_FUNC init_pybsddb(void)
Gregory P. Smith41631e82003-09-21 00:08:14 +00006069{
6070 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6071 init_bsddb();
6072}