blob: befdd7b6b80f781fa08366f3a6cc94a68c38e084 [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
442 key->data = view->buf;
443 key->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t);
444 *returned_view_p = view;
445 }
446
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000447 else {
448 PyErr_Format(PyExc_TypeError,
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000449 "buffer or int object expected for key, %s found",
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000450 Py_Type(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000451 return 0;
452 }
453
454 return 1;
455}
456
457
458/* Add partial record access to an existing DBT data struct.
459 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
460 and the data storage/retrieval will be done using dlen and doff. */
461static int add_partial_dbt(DBT* d, int dlen, int doff) {
462 /* if neither were set we do nothing (-1 is the default value) */
463 if ((dlen == -1) && (doff == -1)) {
464 return 1;
465 }
466
467 if ((dlen < 0) || (doff < 0)) {
468 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
469 return 0;
470 }
471
472 d->flags = d->flags | DB_DBT_PARTIAL;
473 d->dlen = (unsigned int) dlen;
474 d->doff = (unsigned int) doff;
475 return 1;
476}
477
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000478/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
479/* TODO: make this use the native libc strlcpy() when available (BSD) */
480unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
481{
482 unsigned int srclen, copylen;
483
484 srclen = strlen(src);
485 if (n <= 0)
486 return srclen;
487 copylen = (srclen > n-1) ? n-1 : srclen;
488 /* populate dest[0] thru dest[copylen-1] */
489 memcpy(dest, src, copylen);
490 /* guarantee null termination */
491 dest[copylen] = 0;
492
493 return srclen;
494}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000495
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000496/* Callback used to save away more information about errors from the DB
497 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000498static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000499#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000500static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000501#else
502static void _db_errorCallback(const DB_ENV *db_env,
503 const char* prefix, const char* msg)
504#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000505{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000506 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000507}
508
509
510/* make a nice exception object to raise for errors. */
511static int makeDBError(int err)
512{
513 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000514 PyObject *errObj = NULL;
515 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000516 int exceptionRaised = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000517 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000518
519 switch (err) {
520 case 0: /* successful, no error */ break;
521
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000522#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000523 case DB_INCOMPLETE:
524#if INCOMPLETE_IS_WARNING
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000525 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
526 /* Ensure that bytes_left never goes negative */
527 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
528 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
529 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000530 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000531 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000532 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000533 _db_errmsg[0] = 0;
Skip Montanaro46fc3372007-08-12 11:44:53 +0000534 exceptionRaised = PyErr_WarnEx(PyExc_RuntimeWarning, errTxt, 1);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000535
536#else /* do an exception instead */
537 errObj = DBIncompleteError;
538#endif
539 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000540#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000541
542 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
543 case DB_KEYEXIST: errObj = DBKeyExistError; break;
544 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
545 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
546 case DB_NOTFOUND: errObj = DBNotFoundError; break;
547 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
548 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
549 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
550 case DB_NOSERVER: errObj = DBNoServerError; break;
551 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
552 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
553#if (DBVER >= 33)
554 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
555 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
556#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000557 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000558
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000559#if (DBVER >= 43)
560 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
561 case ENOMEM: errObj = PyExc_MemoryError; break;
562#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000563 case EINVAL: errObj = DBInvalidArgError; break;
564 case EACCES: errObj = DBAccessError; break;
565 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000566 case EAGAIN: errObj = DBAgainError; break;
567 case EBUSY : errObj = DBBusyError; break;
568 case EEXIST: errObj = DBFileExistsError; break;
569 case ENOENT: errObj = DBNoSuchFileError; break;
570 case EPERM : errObj = DBPermissionsError; break;
571
572 default: errObj = DBError; break;
573 }
574
575 if (errObj != NULL) {
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000576 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
577 /* Ensure that bytes_left never goes negative */
578 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
579 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
580 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000581 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000582 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000583 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000584 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000585
586 errTuple = Py_BuildValue("(is)", err, errTxt);
587 PyErr_SetObject(errObj, errTuple);
588 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000589 }
590
591 return ((errObj != NULL) || exceptionRaised);
592}
593
594
595
596/* set a type exception */
597static void makeTypeError(char* expected, PyObject* found)
598{
599 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000600 expected, Py_Type(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000601}
602
603
604/* verify that an obj is either None or a DBTxn, and set the txn pointer */
605static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
606{
607 if (txnobj == Py_None || txnobj == NULL) {
608 *txn = NULL;
609 return 1;
610 }
611 if (DBTxnObject_Check(txnobj)) {
612 *txn = ((DBTxnObject*)txnobj)->txn;
613 return 1;
614 }
615 else
616 makeTypeError("DBTxn", txnobj);
617 return 0;
618}
619
620
621/* Delete a key from a database
622 Returns 0 on success, -1 on an error. */
623static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
624{
625 int err;
626
627 MYDB_BEGIN_ALLOW_THREADS;
628 err = self->db->del(self->db, txn, key, 0);
629 MYDB_END_ALLOW_THREADS;
630 if (makeDBError(err)) {
631 return -1;
632 }
633 self->haveStat = 0;
634 return 0;
635}
636
637
638/* Store a key into a database
639 Returns 0 on success, -1 on an error. */
640static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
641{
642 int err;
643
644 MYDB_BEGIN_ALLOW_THREADS;
645 err = self->db->put(self->db, txn, key, data, flags);
646 MYDB_END_ALLOW_THREADS;
647 if (makeDBError(err)) {
648 return -1;
649 }
650 self->haveStat = 0;
651 return 0;
652}
653
654/* Get a key/data pair from a cursor */
655static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
656 PyObject *args, PyObject *kwargs, char *format)
657{
658 int err;
659 PyObject* retval = NULL;
660 DBT key, data;
661 int dlen = -1;
662 int doff = -1;
663 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000664 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000665
666 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
667 &flags, &dlen, &doff))
668 return NULL;
669
670 CHECK_CURSOR_NOT_CLOSED(self);
671
672 flags |= extra_flags;
673 CLEAR_DBT(key);
674 CLEAR_DBT(data);
675 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
676 /* Tell BerkeleyDB to malloc the return value (thread safe) */
677 data.flags = DB_DBT_MALLOC;
678 key.flags = DB_DBT_MALLOC;
679 }
680 if (!add_partial_dbt(&data, dlen, doff))
681 return NULL;
682
683 MYDB_BEGIN_ALLOW_THREADS;
684 err = self->dbc->c_get(self->dbc, &key, &data, flags);
685 MYDB_END_ALLOW_THREADS;
686
Gregory P. Smithe9477062005-06-04 06:46:59 +0000687 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
688 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000689 Py_INCREF(Py_None);
690 retval = Py_None;
691 }
692 else if (makeDBError(err)) {
693 retval = NULL;
694 }
695 else { /* otherwise, success! */
696
697 /* if Recno or Queue, return the key as an Int */
698 switch (_DB_get_type(self->mydb)) {
699 case -1:
700 retval = NULL;
701 break;
702
703 case DB_RECNO:
704 case DB_QUEUE:
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000705 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000706 data.data, data.size);
707 break;
708 case DB_HASH:
709 case DB_BTREE:
710 default:
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000711 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000712 data.data, data.size);
713 break;
714 }
715 }
716 if (!err) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000717 free_dbt(&key);
718 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000719 }
720 return retval;
721}
722
723
724/* add an integer to a dictionary using the given name as a key */
725static void _addIntToDict(PyObject* dict, char *name, int value)
726{
727 PyObject* v = PyInt_FromLong((long) value);
728 if (!v || PyDict_SetItemString(dict, name, v))
729 PyErr_Clear();
730
731 Py_XDECREF(v);
732}
Guido van Rossumd8faa362007-04-27 19:54:29 +0000733
734/* The same, when the value is a time_t */
735static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
736{
737 PyObject* v;
738 /* if the value fits in regular int, use that. */
739#ifdef HAVE_LONG_LONG
740 if (sizeof(time_t) > sizeof(long))
741 v = PyLong_FromLongLong((PY_LONG_LONG) value);
742 else
743#endif
744 v = PyInt_FromLong((long) value);
745 if (!v || PyDict_SetItemString(dict, name, v))
746 PyErr_Clear();
747
748 Py_XDECREF(v);
749}
750
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000751#if (DBVER >= 43)
752/* add an db_seq_t to a dictionary using the given name as a key */
753static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
754{
755 PyObject* v = PyLong_FromLongLong(value);
756 if (!v || PyDict_SetItemString(dict, name, v))
757 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000758
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000759 Py_XDECREF(v);
760}
761#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000762
763
764
765/* --------------------------------------------------------------------- */
766/* Allocators and deallocators */
767
768static DBObject*
769newDBObject(DBEnvObject* arg, int flags)
770{
771 DBObject* self;
772 DB_ENV* db_env = NULL;
773 int err;
774
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000775 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000776 if (self == NULL)
777 return NULL;
778
779 self->haveStat = 0;
780 self->flags = 0;
781 self->setflags = 0;
782 self->myenvobj = NULL;
783#if (DBVER >= 33)
784 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000785 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000786 self->primaryDBType = 0;
787#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000788 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000789
790 /* keep a reference to our python DBEnv object */
791 if (arg) {
792 Py_INCREF(arg);
793 self->myenvobj = arg;
794 db_env = arg->db_env;
795 }
796
797 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000798 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000799 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000800 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
801 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000802
803 MYDB_BEGIN_ALLOW_THREADS;
804 err = db_create(&self->db, db_env, flags);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000805 if (self->db != NULL) {
806 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000807#if (DBVER >= 33)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000808 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000809#endif
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000810 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000811 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000812 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
813 * list so that a DBEnv can refuse to close without aborting any open
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000814 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000815 if (makeDBError(err)) {
816 if (self->myenvobj) {
817 Py_DECREF(self->myenvobj);
818 self->myenvobj = NULL;
819 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000820 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000821 self = NULL;
822 }
823 return self;
824}
825
826
827static void
828DB_dealloc(DBObject* self)
829{
830 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000831 /* avoid closing a DB when its DBEnv has been closed out from under
832 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000833 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000834 (self->myenvobj && self->myenvobj->db_env))
835 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000836 MYDB_BEGIN_ALLOW_THREADS;
837 self->db->close(self->db, 0);
838 MYDB_END_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000839 } else {
Skip Montanaro46fc3372007-08-12 11:44:53 +0000840 PyErr_WarnEx(PyExc_RuntimeWarning,
841 "DB could not be closed in destructor:"
842 " DBEnv already closed",
843 1);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000844 }
845 self->db = NULL;
846 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000847 if (self->in_weakreflist != NULL) {
848 PyObject_ClearWeakRefs((PyObject *) self);
849 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000850 if (self->myenvobj) {
851 Py_DECREF(self->myenvobj);
852 self->myenvobj = NULL;
853 }
854#if (DBVER >= 33)
855 if (self->associateCallback != NULL) {
856 Py_DECREF(self->associateCallback);
857 self->associateCallback = NULL;
858 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000859 if (self->btCompareCallback != NULL) {
860 Py_DECREF(self->btCompareCallback);
861 self->btCompareCallback = NULL;
862 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000863#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000864 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000865}
866
867
868static DBCursorObject*
869newDBCursorObject(DBC* dbc, DBObject* db)
870{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000871 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000872 if (self == NULL)
873 return NULL;
874
875 self->dbc = dbc;
876 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000877 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000878 Py_INCREF(self->mydb);
879 return self;
880}
881
882
883static void
884DBCursor_dealloc(DBCursorObject* self)
885{
886 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000887
Gregory P. Smitha703a212003-11-03 01:04:41 +0000888 if (self->in_weakreflist != NULL) {
889 PyObject_ClearWeakRefs((PyObject *) self);
890 }
Gregory P. Smitha703a212003-11-03 01:04:41 +0000891
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000892 if (self->dbc != NULL) {
893 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000894 /* If the underlying database has been closed, we don't
895 need to do anything. If the environment has been closed
896 we need to leak, as BerkeleyDB will crash trying to access
897 the environment. There was an exception when the
898 user closed the environment even though there still was
899 a database open. */
900 if (self->mydb->db && self->mydb->myenvobj &&
901 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000902 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000903 self->dbc = NULL;
904 MYDB_END_ALLOW_THREADS;
905 }
906 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000907 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000908}
909
910
911static DBEnvObject*
912newDBEnvObject(int flags)
913{
914 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000915 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000916 if (self == NULL)
917 return NULL;
918
919 self->closed = 1;
920 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000921 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
922 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000923 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000924
925 MYDB_BEGIN_ALLOW_THREADS;
926 err = db_env_create(&self->db_env, flags);
927 MYDB_END_ALLOW_THREADS;
928 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000929 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000930 self = NULL;
931 }
932 else {
933 self->db_env->set_errcall(self->db_env, _db_errorCallback);
934 }
935 return self;
936}
937
938
939static void
940DBEnv_dealloc(DBEnvObject* self)
941{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000942 if (self->in_weakreflist != NULL) {
943 PyObject_ClearWeakRefs((PyObject *) self);
944 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000945
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000946 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000947 MYDB_BEGIN_ALLOW_THREADS;
948 self->db_env->close(self->db_env, 0);
949 MYDB_END_ALLOW_THREADS;
950 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000951 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000952}
953
954
955static DBTxnObject*
956newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
957{
958 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000959 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000960 if (self == NULL)
961 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000962 Py_INCREF(myenv);
963 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000964 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000965
966 MYDB_BEGIN_ALLOW_THREADS;
967#if (DBVER >= 40)
968 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
969#else
970 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
971#endif
972 MYDB_END_ALLOW_THREADS;
973 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +0000974 Py_DECREF(self->env);
975 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000976 self = NULL;
977 }
978 return self;
979}
980
981
982static void
983DBTxn_dealloc(DBTxnObject* self)
984{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000985 if (self->in_weakreflist != NULL) {
986 PyObject_ClearWeakRefs((PyObject *) self);
987 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000988
Gregory P. Smith31c50652004-06-28 01:20:40 +0000989 if (self->txn) {
990 /* it hasn't been finalized, abort it! */
991 MYDB_BEGIN_ALLOW_THREADS;
992#if (DBVER >= 40)
993 self->txn->abort(self->txn);
994#else
995 txn_abort(self->txn);
996#endif
997 MYDB_END_ALLOW_THREADS;
Skip Montanaro46fc3372007-08-12 11:44:53 +0000998 PyErr_WarnEx(PyExc_RuntimeWarning,
999 "DBTxn aborted in destructor. "
1000 " No prior commit() or abort().",
1001 1);
Gregory P. Smith31c50652004-06-28 01:20:40 +00001002 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001003
Neal Norwitz62a21122006-01-25 05:21:55 +00001004 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001005 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001006}
1007
1008
1009static DBLockObject*
1010newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1011 db_lockmode_t lock_mode, int flags)
1012{
1013 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001014 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001015 if (self == NULL)
1016 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001017 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001018
1019 MYDB_BEGIN_ALLOW_THREADS;
1020#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001021 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1022 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001023#else
1024 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1025#endif
1026 MYDB_END_ALLOW_THREADS;
1027 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001028 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001029 self = NULL;
1030 }
1031
1032 return self;
1033}
1034
1035
1036static void
1037DBLock_dealloc(DBLockObject* self)
1038{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001039 if (self->in_weakreflist != NULL) {
1040 PyObject_ClearWeakRefs((PyObject *) self);
1041 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001042 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001043
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001044 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001045}
1046
1047
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001048#if (DBVER >= 43)
1049static DBSequenceObject*
1050newDBSequenceObject(DBObject* mydb, int flags)
1051{
1052 int err;
1053 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1054 if (self == NULL)
1055 return NULL;
1056 Py_INCREF(mydb);
1057 self->mydb = mydb;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001058 self->in_weakreflist = NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001059
1060
1061 MYDB_BEGIN_ALLOW_THREADS;
1062 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1063 MYDB_END_ALLOW_THREADS;
1064 if (makeDBError(err)) {
1065 Py_DECREF(self->mydb);
1066 PyObject_Del(self);
1067 self = NULL;
1068 }
1069
1070 return self;
1071}
1072
1073
1074static void
1075DBSequence_dealloc(DBSequenceObject* self)
1076{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001077 if (self->in_weakreflist != NULL) {
1078 PyObject_ClearWeakRefs((PyObject *) self);
1079 }
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001080
1081 Py_DECREF(self->mydb);
1082 PyObject_Del(self);
1083}
1084#endif
1085
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001086/* --------------------------------------------------------------------- */
1087/* DB methods */
1088
1089static PyObject*
1090DB_append(DBObject* self, PyObject* args)
1091{
1092 PyObject* txnobj = NULL;
1093 PyObject* dataobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001094 Py_buffer* data_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001095 db_recno_t recno;
1096 DBT key, data;
1097 DB_TXN *txn = NULL;
1098
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001099 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001100 return NULL;
1101
1102 CHECK_DB_NOT_CLOSED(self);
1103
1104 /* make a dummy key out of a recno */
1105 recno = 0;
1106 CLEAR_DBT(key);
1107 key.data = &recno;
1108 key.size = sizeof(recno);
1109 key.ulen = key.size;
1110 key.flags = DB_DBT_USERMEM;
1111
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001112 if (!checkTxnObj(txnobj, &txn)) return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001113 if (!make_dbt(dataobj, &data, &data_buf_view)) return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001114
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001115 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND)) {
1116 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001117 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001118 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001119
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001120 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001121 return PyInt_FromLong(recno);
1122}
1123
1124
1125#if (DBVER >= 33)
1126
1127static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001128_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1129 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001130{
1131 int retval = DB_DONOTINDEX;
1132 DBObject* secondaryDB = (DBObject*)db->app_private;
1133 PyObject* callback = secondaryDB->associateCallback;
1134 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001135 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001136 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001137
1138
1139 if (callback != NULL) {
1140 MYDB_BEGIN_BLOCK_THREADS;
1141
Thomas Woutersb3153832006-03-08 01:47:19 +00001142 if (type == DB_RECNO || type == DB_QUEUE)
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001143 args = Py_BuildValue("(ly#)", *((db_recno_t*)priKey->data),
Thomas Woutersb3153832006-03-08 01:47:19 +00001144 priData->data, priData->size);
1145 else
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001146 args = Py_BuildValue("(y#y#)", priKey->data, priKey->size,
Thomas Woutersb3153832006-03-08 01:47:19 +00001147 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001148 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001149 result = PyEval_CallObject(callback, args);
1150 }
1151 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001152 PyErr_Print();
1153 }
1154 else if (result == Py_None) {
1155 retval = DB_DONOTINDEX;
1156 }
1157 else if (PyInt_Check(result)) {
1158 retval = PyInt_AsLong(result);
1159 }
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001160 else if (PyBytes_Check(result)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001161 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001162 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001163
1164 CLEAR_DBT(*secKey);
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001165 size = PyBytes_Size(result);
1166 data = PyBytes_AsString(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001167 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1168 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001169 if (secKey->data) {
1170 memcpy(secKey->data, data, size);
1171 secKey->size = size;
1172 retval = 0;
1173 }
1174 else {
1175 PyErr_SetString(PyExc_MemoryError,
1176 "malloc failed in _db_associateCallback");
1177 PyErr_Print();
1178 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001179 }
1180 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001181 PyErr_SetString(
1182 PyExc_TypeError,
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001183 "DB associate callback should return DB_DONOTINDEX or bytes.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001184 PyErr_Print();
1185 }
1186
Thomas Woutersb3153832006-03-08 01:47:19 +00001187 Py_XDECREF(args);
1188 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001189
1190 MYDB_END_BLOCK_THREADS;
1191 }
1192 return retval;
1193}
1194
1195
1196static PyObject*
1197DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1198{
1199 int err, flags=0;
1200 DBObject* secondaryDB;
1201 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001202#if (DBVER >= 41)
1203 PyObject *txnobj = NULL;
1204 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001205 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001206 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001207#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001208 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001209#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001210
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001211#if (DBVER >= 41)
1212 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1213 &secondaryDB, &callback, &flags,
1214 &txnobj)) {
1215#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001216 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001217 &secondaryDB, &callback, &flags)) {
1218#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001219 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001220 }
1221
1222#if (DBVER >= 41)
1223 if (!checkTxnObj(txnobj, &txn)) return NULL;
1224#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001225
1226 CHECK_DB_NOT_CLOSED(self);
1227 if (!DBObject_Check(secondaryDB)) {
1228 makeTypeError("DB", (PyObject*)secondaryDB);
1229 return NULL;
1230 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001231 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001232 if (callback == Py_None) {
1233 callback = NULL;
1234 }
1235 else if (!PyCallable_Check(callback)) {
1236 makeTypeError("Callable", callback);
1237 return NULL;
1238 }
1239
1240 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001241 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001242 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001243 secondaryDB->associateCallback = callback;
1244 secondaryDB->primaryDBType = _DB_get_type(self);
1245
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001246 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1247 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1248 * The global interepreter lock is not initialized until the first
1249 * thread is created using thread.start_new_thread() or fork() is
1250 * called. that would cause the ALLOW_THREADS here to segfault due
1251 * to a null pointer reference if no threads or child processes
1252 * have been created. This works around that and is a no-op if
1253 * threads have already been initialized.
1254 * (see pybsddb-users mailing list post on 2002-08-07)
1255 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001256#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001257 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001258#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001259 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001260#if (DBVER >= 41)
1261 err = self->db->associate(self->db,
1262 txn,
1263 secondaryDB->db,
1264 _db_associateCallback,
1265 flags);
1266#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001267 err = self->db->associate(self->db,
1268 secondaryDB->db,
1269 _db_associateCallback,
1270 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001271#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001272 MYDB_END_ALLOW_THREADS;
1273
1274 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001275 Py_XDECREF(secondaryDB->associateCallback);
1276 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001277 secondaryDB->primaryDBType = 0;
1278 }
1279
1280 RETURN_IF_ERR();
1281 RETURN_NONE();
1282}
1283
1284
1285#endif
1286
1287
1288static PyObject*
1289DB_close(DBObject* self, PyObject* args)
1290{
1291 int err, flags=0;
1292 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1293 return NULL;
1294 if (self->db != NULL) {
1295 if (self->myenvobj)
1296 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001297 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001298 self->db = NULL;
1299 RETURN_IF_ERR();
1300 }
1301 RETURN_NONE();
1302}
1303
1304
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001305static PyObject*
1306_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1307{
1308 int err, flags=0, type;
1309 PyObject* txnobj = NULL;
1310 PyObject* retval = NULL;
1311 DBT key, data;
1312 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001313 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001314
1315 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1316 &txnobj, &flags))
1317 return NULL;
1318
1319 CHECK_DB_NOT_CLOSED(self);
1320 type = _DB_get_type(self);
1321 if (type == -1)
1322 return NULL;
1323 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001324 PyErr_SetString(PyExc_TypeError,
1325 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001326 return NULL;
1327 }
1328 if (!checkTxnObj(txnobj, &txn))
1329 return NULL;
1330
1331 CLEAR_DBT(key);
1332 CLEAR_DBT(data);
1333 if (CHECK_DBFLAG(self, DB_THREAD)) {
1334 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1335 data.flags = DB_DBT_MALLOC;
1336 key.flags = DB_DBT_MALLOC;
1337 }
1338
1339 MYDB_BEGIN_ALLOW_THREADS;
1340 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1341 MYDB_END_ALLOW_THREADS;
1342
Gregory P. Smithe9477062005-06-04 06:46:59 +00001343 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1344 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001345 err = 0;
1346 Py_INCREF(Py_None);
1347 retval = Py_None;
1348 }
1349 else if (!err) {
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001350 retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001351 data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001352 free_dbt(&key);
1353 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001354 }
1355
1356 RETURN_IF_ERR();
1357 return retval;
1358}
1359
1360static PyObject*
1361DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1362{
1363 return _DB_consume(self, args, kwargs, DB_CONSUME);
1364}
1365
1366static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001367DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1368 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001369{
1370 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1371}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001372
1373
1374static PyObject*
1375DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1376{
1377 int err, flags=0;
1378 DBC* dbc;
1379 PyObject* txnobj = NULL;
1380 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001381 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001382
1383 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1384 &txnobj, &flags))
1385 return NULL;
1386 CHECK_DB_NOT_CLOSED(self);
1387 if (!checkTxnObj(txnobj, &txn))
1388 return NULL;
1389
1390 MYDB_BEGIN_ALLOW_THREADS;
1391 err = self->db->cursor(self->db, txn, &dbc, flags);
1392 MYDB_END_ALLOW_THREADS;
1393 RETURN_IF_ERR();
1394 return (PyObject*) newDBCursorObject(dbc, self);
1395}
1396
1397
1398static PyObject*
1399DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1400{
1401 PyObject* txnobj = NULL;
1402 int flags = 0;
1403 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001404 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001405 DBT key;
1406 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001407 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001408
1409 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1410 &keyobj, &txnobj, &flags))
1411 return NULL;
1412 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001413 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001414 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001415 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001416 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001417 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001418 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001419
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001420 if (-1 == _DB_delete(self, txn, &key, 0)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001421 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001422 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001423 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001424
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001425 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001426 RETURN_NONE();
1427}
1428
1429
1430static PyObject*
1431DB_fd(DBObject* self, PyObject* args)
1432{
1433 int err, the_fd;
1434
1435 if (!PyArg_ParseTuple(args,":fd"))
1436 return NULL;
1437 CHECK_DB_NOT_CLOSED(self);
1438
1439 MYDB_BEGIN_ALLOW_THREADS;
1440 err = self->db->fd(self->db, &the_fd);
1441 MYDB_END_ALLOW_THREADS;
1442 RETURN_IF_ERR();
1443 return PyInt_FromLong(the_fd);
1444}
1445
1446
1447static PyObject*
1448DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1449{
1450 int err, flags=0;
1451 PyObject* txnobj = NULL;
1452 PyObject* keyobj;
1453 PyObject* dfltobj = NULL;
1454 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001455 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001456 int dlen = -1;
1457 int doff = -1;
1458 DBT key, data;
1459 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001460 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001461 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001462
1463 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001464 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1465 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001466 return NULL;
1467
1468 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001469 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001470 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001471 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001472 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001473 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001474 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001475
1476 CLEAR_DBT(data);
1477 if (CHECK_DBFLAG(self, DB_THREAD)) {
1478 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1479 data.flags = DB_DBT_MALLOC;
1480 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001481 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001482 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001483 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001484 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001485
1486 MYDB_BEGIN_ALLOW_THREADS;
1487 err = self->db->get(self->db, txn, &key, &data, flags);
1488 MYDB_END_ALLOW_THREADS;
1489
Gregory P. Smithe9477062005-06-04 06:46:59 +00001490 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001491 err = 0;
1492 Py_INCREF(dfltobj);
1493 retval = dfltobj;
1494 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001495 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1496 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001497 err = 0;
1498 Py_INCREF(Py_None);
1499 retval = Py_None;
1500 }
1501 else if (!err) {
1502 if (flags & DB_SET_RECNO) /* return both key and data */
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001503 retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001504 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001505 else /* return just the data */
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001506 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001507 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001508 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001509 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001510
1511 RETURN_IF_ERR();
1512 return retval;
1513}
1514
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001515#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001516static PyObject*
1517DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1518{
1519 int err, flags=0;
1520 PyObject* txnobj = NULL;
1521 PyObject* keyobj;
1522 PyObject* dfltobj = NULL;
1523 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001524 Py_buffer* key_buf_view = NULL;
Gregory P. Smith19699a92004-06-28 04:06:49 +00001525 int dlen = -1;
1526 int doff = -1;
1527 DBT key, pkey, data;
1528 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001529 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001530 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001531
1532 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1533 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1534 &doff))
1535 return NULL;
1536
1537 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001538 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Gregory P. Smith19699a92004-06-28 04:06:49 +00001539 return NULL;
1540 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001541 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001542 return NULL;
1543 }
1544
1545 CLEAR_DBT(data);
1546 if (CHECK_DBFLAG(self, DB_THREAD)) {
1547 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1548 data.flags = DB_DBT_MALLOC;
1549 }
1550 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001551 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001552 return NULL;
1553 }
1554
1555 CLEAR_DBT(pkey);
1556 pkey.flags = DB_DBT_MALLOC;
1557
1558 MYDB_BEGIN_ALLOW_THREADS;
1559 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1560 MYDB_END_ALLOW_THREADS;
1561
Gregory P. Smithe9477062005-06-04 06:46:59 +00001562 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001563 err = 0;
1564 Py_INCREF(dfltobj);
1565 retval = dfltobj;
1566 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001567 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1568 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001569 err = 0;
1570 Py_INCREF(Py_None);
1571 retval = Py_None;
1572 }
1573 else if (!err) {
1574 PyObject *pkeyObj;
1575 PyObject *dataObj;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001576 dataObj = PyBytes_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001577
1578 if (self->primaryDBType == DB_RECNO ||
1579 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001580 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001581 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001582 pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001583
1584 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1585 {
1586 PyObject *keyObj;
1587 int type = _DB_get_type(self);
1588 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001589 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001590 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001591 keyObj = PyBytes_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001592#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001593 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001594#else
1595 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1596#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001597 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001598 }
1599 else /* return just the pkey and data */
1600 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001601#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001602 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001603#else
1604 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1605#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001606 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001607 Py_DECREF(dataObj);
1608 Py_DECREF(pkeyObj);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001609 free_dbt(&pkey);
1610 free_dbt(&data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001611 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001612 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001613
1614 RETURN_IF_ERR();
1615 return retval;
1616}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001617#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001618
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001619
1620/* Return size of entry */
1621static PyObject*
1622DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1623{
1624 int err, flags=0;
1625 PyObject* txnobj = NULL;
1626 PyObject* keyobj;
1627 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001628 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001629 DBT key, data;
1630 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001631 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001632
1633 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1634 &keyobj, &txnobj))
1635 return NULL;
1636 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001637 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001638 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001639 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001640 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001641 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001642 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001643 CLEAR_DBT(data);
1644
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001645 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1646 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001647 data.flags = DB_DBT_USERMEM;
1648 data.ulen = 0;
1649 MYDB_BEGIN_ALLOW_THREADS;
1650 err = self->db->get(self->db, txn, &key, &data, flags);
1651 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001652 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001653 retval = PyInt_FromLong((long)data.size);
1654 err = 0;
1655 }
1656
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001657 FREE_DBT_VIEW(key, keyobj, key_buf_view);
1658 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001659 RETURN_IF_ERR();
1660 return retval;
1661}
1662
1663
1664static PyObject*
1665DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1666{
1667 int err, flags=0;
1668 PyObject* txnobj = NULL;
1669 PyObject* keyobj;
1670 PyObject* dataobj;
1671 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001672 Py_buffer* data_buf_view = NULL;
1673 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001674 DBT key, data;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001675 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001676 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001677 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001678
1679
1680 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1681 &keyobj, &dataobj, &txnobj, &flags))
1682 return NULL;
1683
1684 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001685 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001686 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001687 if ( !checkTxnObj(txnobj, &txn) ||
1688 !make_dbt(dataobj, &data, &data_buf_view) )
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001689 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001690 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001691 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001692 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001693
1694 flags |= DB_GET_BOTH;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001695 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001696
1697 if (CHECK_DBFLAG(self, DB_THREAD)) {
1698 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001699 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001700 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001701 }
1702
1703 MYDB_BEGIN_ALLOW_THREADS;
1704 err = self->db->get(self->db, txn, &key, &data, flags);
1705 MYDB_END_ALLOW_THREADS;
1706
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001707 free_buf_view(dataobj, data_buf_view);
1708
Gregory P. Smithe9477062005-06-04 06:46:59 +00001709 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1710 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001711 err = 0;
1712 Py_INCREF(Py_None);
1713 retval = Py_None;
1714 }
1715 else if (!err) {
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001716 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001717 /* XXX(gps) I think not: buffer API input vs. bytes object output. */
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001718 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001719
1720 /* Even though the flags require DB_DBT_MALLOC, data is not always
1721 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1722 if (data.data != orig_data)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001723 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001724 }
1725
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001726 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001727 RETURN_IF_ERR();
1728 return retval;
1729}
1730
1731
1732static PyObject*
1733DB_get_byteswapped(DBObject* self, PyObject* args)
1734{
1735#if (DBVER >= 33)
1736 int err = 0;
1737#endif
1738 int retval = -1;
1739
1740 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1741 return NULL;
1742 CHECK_DB_NOT_CLOSED(self);
1743
1744#if (DBVER >= 33)
1745 MYDB_BEGIN_ALLOW_THREADS;
1746 err = self->db->get_byteswapped(self->db, &retval);
1747 MYDB_END_ALLOW_THREADS;
1748 RETURN_IF_ERR();
1749#else
1750 MYDB_BEGIN_ALLOW_THREADS;
1751 retval = self->db->get_byteswapped(self->db);
1752 MYDB_END_ALLOW_THREADS;
1753#endif
1754 return PyInt_FromLong(retval);
1755}
1756
1757
1758static PyObject*
1759DB_get_type(DBObject* self, PyObject* args)
1760{
1761 int type;
1762
1763 if (!PyArg_ParseTuple(args,":get_type"))
1764 return NULL;
1765 CHECK_DB_NOT_CLOSED(self);
1766
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001767 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001768 if (type == -1)
1769 return NULL;
1770 return PyInt_FromLong(type);
1771}
1772
1773
1774static PyObject*
1775DB_join(DBObject* self, PyObject* args)
1776{
1777 int err, flags=0;
1778 int length, x;
1779 PyObject* cursorsObj;
1780 DBC** cursors;
1781 DBC* dbc;
1782
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001783 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1784 return NULL;
1785
1786 CHECK_DB_NOT_CLOSED(self);
1787
1788 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001789 PyErr_SetString(PyExc_TypeError,
1790 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001791 return NULL;
1792 }
1793
1794 length = PyObject_Length(cursorsObj);
1795 cursors = malloc((length+1) * sizeof(DBC*));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001796 if (!cursors) {
1797 PyErr_NoMemory();
1798 return NULL;
1799 }
1800
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001801 cursors[length] = NULL;
1802 for (x=0; x<length; x++) {
1803 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001804 if (item == NULL) {
1805 free(cursors);
1806 return NULL;
1807 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001808 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001809 PyErr_SetString(PyExc_TypeError,
1810 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001811 free(cursors);
1812 return NULL;
1813 }
1814 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001815 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001816 }
1817
1818 MYDB_BEGIN_ALLOW_THREADS;
1819 err = self->db->join(self->db, cursors, &dbc, flags);
1820 MYDB_END_ALLOW_THREADS;
1821 free(cursors);
1822 RETURN_IF_ERR();
1823
Gregory P. Smith7441e652003-11-03 21:35:31 +00001824 /* FIXME: this is a buggy interface. The returned cursor
1825 contains internal references to the passed in cursors
1826 but does not hold python references to them or prevent
1827 them from being closed prematurely. This can cause
1828 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001829 return (PyObject*) newDBCursorObject(dbc, self);
1830}
1831
1832
1833static PyObject*
1834DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1835{
1836 int err, flags=0;
1837 PyObject* txnobj = NULL;
1838 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001839 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001840 DBT key;
1841 DB_TXN *txn = NULL;
1842 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001843 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001844
1845 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1846 &keyobj, &txnobj, &flags))
1847 return NULL;
1848 CHECK_DB_NOT_CLOSED(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001849 if (!checkTxnObj(txnobj, &txn))
1850 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001851 if (!make_dbt(keyobj, &key, &key_buf_view))
1852 /* BTree only, don't need to allow for an int key */
1853 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001854
1855 MYDB_BEGIN_ALLOW_THREADS;
1856 err = self->db->key_range(self->db, txn, &key, &range, flags);
1857 MYDB_END_ALLOW_THREADS;
1858
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001859 free_buf_view(keyobj, key_buf_view);
1860
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001861 RETURN_IF_ERR();
1862 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1863}
1864
1865
1866static PyObject*
1867DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1868{
1869 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1870 char* filename = NULL;
1871 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001872#if (DBVER >= 41)
1873 PyObject *txnobj = NULL;
1874 DB_TXN *txn = NULL;
1875 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001876 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001877 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1878 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001879 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001880 "filename", "dbtype", "flags", "mode", "txn", NULL};
1881#else
1882 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001883 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001884 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1885 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001886 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001887 "filename", "dbtype", "flags", "mode", NULL};
1888#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001889
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001890#if (DBVER >= 41)
1891 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1892 &filename, &dbname, &type, &flags, &mode,
1893 &txnobj))
1894#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001895 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001896 &filename, &dbname, &type, &flags,
1897 &mode))
1898#endif
1899 {
1900 PyErr_Clear();
1901 type = DB_UNKNOWN; flags = 0; mode = 0660;
1902 filename = NULL; dbname = NULL;
1903#if (DBVER >= 41)
1904 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1905 kwnames_basic,
1906 &filename, &type, &flags, &mode,
1907 &txnobj))
1908 return NULL;
1909#else
1910 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1911 kwnames_basic,
1912 &filename, &type, &flags, &mode))
1913 return NULL;
1914#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001915 }
1916
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001917#if (DBVER >= 41)
1918 if (!checkTxnObj(txnobj, &txn)) return NULL;
1919#endif
1920
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001921 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001922 PyObject *t = Py_BuildValue("(is)", 0,
1923 "Cannot call open() twice for DB object");
1924 PyErr_SetObject(DBError, t);
1925 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001926 return NULL;
1927 }
1928
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001929#if 0 && (DBVER >= 41)
1930 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1931 && (self->myenvobj->flags & DB_INIT_TXN))
1932 {
1933 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1934 * explicitly passed) but we are in a transaction ready environment:
1935 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1936 * to work on BerkeleyDB 4.1 without needing to modify their
1937 * DBEnv or DB open calls.
1938 * TODO make this behaviour of the library configurable.
1939 */
1940 flags |= DB_AUTO_COMMIT;
1941 }
1942#endif
1943
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001944 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001945#if (DBVER >= 41)
1946 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1947#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001948 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001949#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001950 MYDB_END_ALLOW_THREADS;
1951 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001952 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001953 self->db = NULL;
1954 return NULL;
1955 }
1956
1957 self->flags = flags;
1958 RETURN_NONE();
1959}
1960
1961
1962static PyObject*
1963DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1964{
1965 int flags=0;
1966 PyObject* txnobj = NULL;
1967 int dlen = -1;
1968 int doff = -1;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001969 PyObject *keyobj, *dataobj, *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00001970 Py_buffer *data_buf_view = NULL;
1971 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001972 DBT key, data;
1973 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001974 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001975 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001976
1977 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1978 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1979 return NULL;
1980
1981 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001982 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001983 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001984 if ( !make_dbt(dataobj, &data, &data_buf_view) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001985 !add_partial_dbt(&data, dlen, doff) ||
1986 !checkTxnObj(txnobj, &txn) )
1987 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001988 FREE_DBT_VIEW(key, keyobj, key_buf_view);
1989 free_buf_view(dataobj, data_buf_view);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001990 return NULL;
1991 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001992
1993 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001994 FREE_DBT_VIEW(key, keyobj, key_buf_view);
1995 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001996 return NULL;
1997 }
1998
1999 if (flags & DB_APPEND)
2000 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2001 else {
2002 retval = Py_None;
2003 Py_INCREF(retval);
2004 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002005 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2006 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002007 return retval;
2008}
2009
2010
2011
2012static PyObject*
2013DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2014{
2015 char* filename;
2016 char* database = NULL;
2017 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002018 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002019
2020 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2021 &filename, &database, &flags))
2022 return NULL;
2023 CHECK_DB_NOT_CLOSED(self);
2024
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002025 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002026 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002027 RETURN_IF_ERR();
2028 RETURN_NONE();
2029}
2030
2031
2032
2033static PyObject*
2034DB_rename(DBObject* self, PyObject* args)
2035{
2036 char* filename;
2037 char* database;
2038 char* newname;
2039 int err, flags=0;
2040
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002041 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2042 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002043 return NULL;
2044 CHECK_DB_NOT_CLOSED(self);
2045
2046 MYDB_BEGIN_ALLOW_THREADS;
2047 err = self->db->rename(self->db, filename, database, newname, flags);
2048 MYDB_END_ALLOW_THREADS;
2049 RETURN_IF_ERR();
2050 RETURN_NONE();
2051}
2052
2053
2054static PyObject*
2055DB_set_bt_minkey(DBObject* self, PyObject* args)
2056{
2057 int err, minkey;
2058
2059 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2060 return NULL;
2061 CHECK_DB_NOT_CLOSED(self);
2062
2063 MYDB_BEGIN_ALLOW_THREADS;
2064 err = self->db->set_bt_minkey(self->db, minkey);
2065 MYDB_END_ALLOW_THREADS;
2066 RETURN_IF_ERR();
2067 RETURN_NONE();
2068}
2069
Neal Norwitz84562352005-10-20 04:30:15 +00002070#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002071static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002072_default_cmp(const DBT *leftKey,
2073 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002074{
2075 int res;
2076 int lsize = leftKey->size, rsize = rightKey->size;
2077
Georg Brandlef1701f2006-03-07 14:57:48 +00002078 res = memcmp(leftKey->data, rightKey->data,
2079 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002080
2081 if (res == 0) {
2082 if (lsize < rsize) {
2083 res = -1;
2084 }
2085 else if (lsize > rsize) {
2086 res = 1;
2087 }
2088 }
2089 return res;
2090}
2091
2092static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002093_db_compareCallback(DB* db,
2094 const DBT *leftKey,
2095 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002096{
2097 int res = 0;
2098 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002099 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002100 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002101
2102 if (self == NULL || self->btCompareCallback == NULL) {
2103 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002104 PyErr_SetString(PyExc_TypeError,
2105 (self == 0
2106 ? "DB_bt_compare db is NULL."
2107 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002108 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002109 PyErr_Print();
2110 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002111 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002112 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002113 MYDB_BEGIN_BLOCK_THREADS;
2114
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002115 args = Py_BuildValue("y#y#", leftKey->data, leftKey->size,
Thomas Woutersb3153832006-03-08 01:47:19 +00002116 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002117 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002118 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002119 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002120 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002121 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002122 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002123 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002124 PyErr_Print();
2125 res = _default_cmp(leftKey, rightKey);
2126 } else if (PyInt_Check(result)) {
2127 res = PyInt_AsLong(result);
2128 } else {
2129 PyErr_SetString(PyExc_TypeError,
2130 "DB_bt_compare callback MUST return an int.");
2131 /* we're in a callback within the DB code, we can't raise */
2132 PyErr_Print();
2133 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002134 }
2135
Thomas Woutersb3153832006-03-08 01:47:19 +00002136 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002137 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002138
2139 MYDB_END_BLOCK_THREADS;
2140 }
2141 return res;
2142}
2143
2144static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002145DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002146{
2147 int err;
2148 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002149 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002150
Georg Brandlef1701f2006-03-07 14:57:48 +00002151 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002152 return NULL;
2153
Georg Brandlef1701f2006-03-07 14:57:48 +00002154 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002155
Georg Brandlef1701f2006-03-07 14:57:48 +00002156 if (!PyCallable_Check(comparator)) {
2157 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002158 return NULL;
2159 }
2160
2161 /*
2162 * Perform a test call of the comparator function with two empty
2163 * string objects here. verify that it returns an int (0).
2164 * err if not.
2165 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002166 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002167 result = PyEval_CallObject(comparator, tuple);
2168 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002169 if (result == NULL)
2170 return NULL;
2171 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002172 PyErr_SetString(PyExc_TypeError,
2173 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002174 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002175 } else if (PyInt_AsLong(result) != 0) {
2176 PyErr_SetString(PyExc_TypeError,
2177 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002178 return NULL;
2179 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002180 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002181
2182 /* We don't accept multiple set_bt_compare operations, in order to
2183 * simplify the code. This would have no real use, as one cannot
2184 * change the function once the db is opened anyway */
2185 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002186 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002187 return NULL;
2188 }
2189
Georg Brandlef1701f2006-03-07 14:57:48 +00002190 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002191 self->btCompareCallback = comparator;
2192
2193 /* This is to workaround a problem with un-initialized threads (see
2194 comment in DB_associate) */
2195#ifdef WITH_THREAD
2196 PyEval_InitThreads();
2197#endif
2198
Thomas Woutersb3153832006-03-08 01:47:19 +00002199 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002200
2201 if (err) {
2202 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002203 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002204 self->btCompareCallback = NULL;
2205 }
2206
Georg Brandlef1701f2006-03-07 14:57:48 +00002207 RETURN_IF_ERR();
2208 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002209}
Neal Norwitz84562352005-10-20 04:30:15 +00002210#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002211
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002212
2213static PyObject*
2214DB_set_cachesize(DBObject* self, PyObject* args)
2215{
2216 int err;
2217 int gbytes = 0, bytes = 0, ncache = 0;
2218
2219 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2220 &gbytes,&bytes,&ncache))
2221 return NULL;
2222 CHECK_DB_NOT_CLOSED(self);
2223
2224 MYDB_BEGIN_ALLOW_THREADS;
2225 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2226 MYDB_END_ALLOW_THREADS;
2227 RETURN_IF_ERR();
2228 RETURN_NONE();
2229}
2230
2231
2232static PyObject*
2233DB_set_flags(DBObject* self, PyObject* args)
2234{
2235 int err, flags;
2236
2237 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2238 return NULL;
2239 CHECK_DB_NOT_CLOSED(self);
2240
2241 MYDB_BEGIN_ALLOW_THREADS;
2242 err = self->db->set_flags(self->db, flags);
2243 MYDB_END_ALLOW_THREADS;
2244 RETURN_IF_ERR();
2245
2246 self->setflags |= flags;
2247 RETURN_NONE();
2248}
2249
2250
2251static PyObject*
2252DB_set_h_ffactor(DBObject* self, PyObject* args)
2253{
2254 int err, ffactor;
2255
2256 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2257 return NULL;
2258 CHECK_DB_NOT_CLOSED(self);
2259
2260 MYDB_BEGIN_ALLOW_THREADS;
2261 err = self->db->set_h_ffactor(self->db, ffactor);
2262 MYDB_END_ALLOW_THREADS;
2263 RETURN_IF_ERR();
2264 RETURN_NONE();
2265}
2266
2267
2268static PyObject*
2269DB_set_h_nelem(DBObject* self, PyObject* args)
2270{
2271 int err, nelem;
2272
2273 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2274 return NULL;
2275 CHECK_DB_NOT_CLOSED(self);
2276
2277 MYDB_BEGIN_ALLOW_THREADS;
2278 err = self->db->set_h_nelem(self->db, nelem);
2279 MYDB_END_ALLOW_THREADS;
2280 RETURN_IF_ERR();
2281 RETURN_NONE();
2282}
2283
2284
2285static PyObject*
2286DB_set_lorder(DBObject* self, PyObject* args)
2287{
2288 int err, lorder;
2289
2290 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2291 return NULL;
2292 CHECK_DB_NOT_CLOSED(self);
2293
2294 MYDB_BEGIN_ALLOW_THREADS;
2295 err = self->db->set_lorder(self->db, lorder);
2296 MYDB_END_ALLOW_THREADS;
2297 RETURN_IF_ERR();
2298 RETURN_NONE();
2299}
2300
2301
2302static PyObject*
2303DB_set_pagesize(DBObject* self, PyObject* args)
2304{
2305 int err, pagesize;
2306
2307 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2308 return NULL;
2309 CHECK_DB_NOT_CLOSED(self);
2310
2311 MYDB_BEGIN_ALLOW_THREADS;
2312 err = self->db->set_pagesize(self->db, pagesize);
2313 MYDB_END_ALLOW_THREADS;
2314 RETURN_IF_ERR();
2315 RETURN_NONE();
2316}
2317
2318
2319static PyObject*
2320DB_set_re_delim(DBObject* self, PyObject* args)
2321{
2322 int err;
2323 char delim;
2324
2325 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2326 PyErr_Clear();
2327 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2328 return NULL;
2329 }
2330
2331 CHECK_DB_NOT_CLOSED(self);
2332
2333 MYDB_BEGIN_ALLOW_THREADS;
2334 err = self->db->set_re_delim(self->db, delim);
2335 MYDB_END_ALLOW_THREADS;
2336 RETURN_IF_ERR();
2337 RETURN_NONE();
2338}
2339
2340static PyObject*
2341DB_set_re_len(DBObject* self, PyObject* args)
2342{
2343 int err, len;
2344
2345 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2346 return NULL;
2347 CHECK_DB_NOT_CLOSED(self);
2348
2349 MYDB_BEGIN_ALLOW_THREADS;
2350 err = self->db->set_re_len(self->db, len);
2351 MYDB_END_ALLOW_THREADS;
2352 RETURN_IF_ERR();
2353 RETURN_NONE();
2354}
2355
2356
2357static PyObject*
2358DB_set_re_pad(DBObject* self, PyObject* args)
2359{
2360 int err;
2361 char pad;
2362
2363 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2364 PyErr_Clear();
2365 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2366 return NULL;
2367 }
2368 CHECK_DB_NOT_CLOSED(self);
2369
2370 MYDB_BEGIN_ALLOW_THREADS;
2371 err = self->db->set_re_pad(self->db, pad);
2372 MYDB_END_ALLOW_THREADS;
2373 RETURN_IF_ERR();
2374 RETURN_NONE();
2375}
2376
2377
2378static PyObject*
2379DB_set_re_source(DBObject* self, PyObject* args)
2380{
2381 int err;
2382 char *re_source;
2383
2384 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2385 return NULL;
2386 CHECK_DB_NOT_CLOSED(self);
2387
2388 MYDB_BEGIN_ALLOW_THREADS;
2389 err = self->db->set_re_source(self->db, re_source);
2390 MYDB_END_ALLOW_THREADS;
2391 RETURN_IF_ERR();
2392 RETURN_NONE();
2393}
2394
2395
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002396static PyObject*
2397DB_set_q_extentsize(DBObject* self, PyObject* args)
2398{
2399 int err;
2400 int extentsize;
2401
2402 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2403 return NULL;
2404 CHECK_DB_NOT_CLOSED(self);
2405
2406 MYDB_BEGIN_ALLOW_THREADS;
2407 err = self->db->set_q_extentsize(self->db, extentsize);
2408 MYDB_END_ALLOW_THREADS;
2409 RETURN_IF_ERR();
2410 RETURN_NONE();
2411}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002412
2413static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002414DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002415{
2416 int err, flags = 0, type;
2417 void* sp;
2418 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002419#if (DBVER >= 43)
2420 PyObject* txnobj = NULL;
2421 DB_TXN *txn = NULL;
Thomas Wouters89f507f2006-12-13 04:49:30 +00002422 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002423#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002424 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002425#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002426
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002427#if (DBVER >= 43)
2428 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2429 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002430 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002431 if (!checkTxnObj(txnobj, &txn))
2432 return NULL;
2433#else
2434 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2435 return NULL;
2436#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002437 CHECK_DB_NOT_CLOSED(self);
2438
2439 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002440#if (DBVER >= 43)
2441 err = self->db->stat(self->db, txn, &sp, flags);
2442#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002443 err = self->db->stat(self->db, &sp, flags);
2444#else
2445 err = self->db->stat(self->db, &sp, NULL, flags);
2446#endif
2447 MYDB_END_ALLOW_THREADS;
2448 RETURN_IF_ERR();
2449
2450 self->haveStat = 1;
2451
2452 /* Turn the stat structure into a dictionary */
2453 type = _DB_get_type(self);
2454 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2455 free(sp);
2456 return NULL;
2457 }
2458
2459#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2460#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2461#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2462
2463 switch (type) {
2464 case DB_HASH:
2465 MAKE_HASH_ENTRY(magic);
2466 MAKE_HASH_ENTRY(version);
2467 MAKE_HASH_ENTRY(nkeys);
2468 MAKE_HASH_ENTRY(ndata);
2469 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002470#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002471 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002472#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002473 MAKE_HASH_ENTRY(ffactor);
2474 MAKE_HASH_ENTRY(buckets);
2475 MAKE_HASH_ENTRY(free);
2476 MAKE_HASH_ENTRY(bfree);
2477 MAKE_HASH_ENTRY(bigpages);
2478 MAKE_HASH_ENTRY(big_bfree);
2479 MAKE_HASH_ENTRY(overflows);
2480 MAKE_HASH_ENTRY(ovfl_free);
2481 MAKE_HASH_ENTRY(dup);
2482 MAKE_HASH_ENTRY(dup_free);
2483 break;
2484
2485 case DB_BTREE:
2486 case DB_RECNO:
2487 MAKE_BT_ENTRY(magic);
2488 MAKE_BT_ENTRY(version);
2489 MAKE_BT_ENTRY(nkeys);
2490 MAKE_BT_ENTRY(ndata);
2491 MAKE_BT_ENTRY(pagesize);
2492 MAKE_BT_ENTRY(minkey);
2493 MAKE_BT_ENTRY(re_len);
2494 MAKE_BT_ENTRY(re_pad);
2495 MAKE_BT_ENTRY(levels);
2496 MAKE_BT_ENTRY(int_pg);
2497 MAKE_BT_ENTRY(leaf_pg);
2498 MAKE_BT_ENTRY(dup_pg);
2499 MAKE_BT_ENTRY(over_pg);
2500 MAKE_BT_ENTRY(free);
2501 MAKE_BT_ENTRY(int_pgfree);
2502 MAKE_BT_ENTRY(leaf_pgfree);
2503 MAKE_BT_ENTRY(dup_pgfree);
2504 MAKE_BT_ENTRY(over_pgfree);
2505 break;
2506
2507 case DB_QUEUE:
2508 MAKE_QUEUE_ENTRY(magic);
2509 MAKE_QUEUE_ENTRY(version);
2510 MAKE_QUEUE_ENTRY(nkeys);
2511 MAKE_QUEUE_ENTRY(ndata);
2512 MAKE_QUEUE_ENTRY(pagesize);
2513 MAKE_QUEUE_ENTRY(pages);
2514 MAKE_QUEUE_ENTRY(re_len);
2515 MAKE_QUEUE_ENTRY(re_pad);
2516 MAKE_QUEUE_ENTRY(pgfree);
2517#if (DBVER == 31)
2518 MAKE_QUEUE_ENTRY(start);
2519#endif
2520 MAKE_QUEUE_ENTRY(first_recno);
2521 MAKE_QUEUE_ENTRY(cur_recno);
2522 break;
2523
2524 default:
2525 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2526 Py_DECREF(d);
2527 d = NULL;
2528 }
2529
2530#undef MAKE_HASH_ENTRY
2531#undef MAKE_BT_ENTRY
2532#undef MAKE_QUEUE_ENTRY
2533
2534 free(sp);
2535 return d;
2536}
2537
2538static PyObject*
2539DB_sync(DBObject* self, PyObject* args)
2540{
2541 int err;
2542 int flags = 0;
2543
2544 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2545 return NULL;
2546 CHECK_DB_NOT_CLOSED(self);
2547
2548 MYDB_BEGIN_ALLOW_THREADS;
2549 err = self->db->sync(self->db, flags);
2550 MYDB_END_ALLOW_THREADS;
2551 RETURN_IF_ERR();
2552 RETURN_NONE();
2553}
2554
2555
2556#if (DBVER >= 33)
2557static PyObject*
2558DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2559{
2560 int err, flags=0;
2561 u_int32_t count=0;
2562 PyObject* txnobj = NULL;
2563 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002564 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002565
2566 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2567 &txnobj, &flags))
2568 return NULL;
2569 CHECK_DB_NOT_CLOSED(self);
2570 if (!checkTxnObj(txnobj, &txn))
2571 return NULL;
2572
2573 MYDB_BEGIN_ALLOW_THREADS;
2574 err = self->db->truncate(self->db, txn, &count, flags);
2575 MYDB_END_ALLOW_THREADS;
2576 RETURN_IF_ERR();
2577 return PyInt_FromLong(count);
2578}
2579#endif
2580
2581
2582static PyObject*
2583DB_upgrade(DBObject* self, PyObject* args)
2584{
2585 int err, flags=0;
2586 char *filename;
2587
2588 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2589 return NULL;
2590 CHECK_DB_NOT_CLOSED(self);
2591
2592 MYDB_BEGIN_ALLOW_THREADS;
2593 err = self->db->upgrade(self->db, filename, flags);
2594 MYDB_END_ALLOW_THREADS;
2595 RETURN_IF_ERR();
2596 RETURN_NONE();
2597}
2598
2599
2600static PyObject*
2601DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2602{
2603 int err, flags=0;
2604 char* fileName;
2605 char* dbName=NULL;
2606 char* outFileName=NULL;
2607 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002608 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002609 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002610
2611 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2612 &fileName, &dbName, &outFileName, &flags))
2613 return NULL;
2614
2615 CHECK_DB_NOT_CLOSED(self);
2616 if (outFileName)
2617 outFile = fopen(outFileName, "w");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002618 /* XXX(nnorwitz): it should probably be an exception if outFile
2619 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002620
2621 MYDB_BEGIN_ALLOW_THREADS;
2622 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2623 MYDB_END_ALLOW_THREADS;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002624 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002625 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002626
2627 /* DB.verify acts as a DB handle destructor (like close); this was
2628 * documented in BerkeleyDB 4.2 but had the undocumented effect
2629 * of not being safe in prior versions while still requiring an explicit
2630 * DB.close call afterwards. Lets call close for the user to emulate
2631 * the safe 4.2 behaviour. */
2632#if (DBVER <= 41)
2633 self->db->close(self->db, 0);
2634#endif
2635 self->db = NULL;
2636
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002637 RETURN_IF_ERR();
2638 RETURN_NONE();
2639}
2640
2641
2642static PyObject*
2643DB_set_get_returns_none(DBObject* self, PyObject* args)
2644{
2645 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002646 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002647
2648 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2649 return NULL;
2650 CHECK_DB_NOT_CLOSED(self);
2651
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002652 if (self->moduleFlags.getReturnsNone)
2653 ++oldValue;
2654 if (self->moduleFlags.cursorSetReturnsNone)
2655 ++oldValue;
2656 self->moduleFlags.getReturnsNone = (flags >= 1);
2657 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002658 return PyInt_FromLong(oldValue);
2659}
2660
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002661#if (DBVER >= 41)
2662static PyObject*
2663DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2664{
2665 int err;
2666 u_int32_t flags=0;
2667 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002668 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002669
2670 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2671 &passwd, &flags)) {
2672 return NULL;
2673 }
2674
2675 MYDB_BEGIN_ALLOW_THREADS;
2676 err = self->db->set_encrypt(self->db, passwd, flags);
2677 MYDB_END_ALLOW_THREADS;
2678
2679 RETURN_IF_ERR();
2680 RETURN_NONE();
2681}
2682#endif /* DBVER >= 41 */
2683
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002684
2685/*-------------------------------------------------------------- */
2686/* Mapping and Dictionary-like access routines */
2687
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002688Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002689{
2690 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002691 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002692 int flags = 0;
2693 void* sp;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002694 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002695
2696 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002697 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2698 PyErr_SetObject(DBError, t);
2699 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002700 return -1;
2701 }
2702
2703 if (self->haveStat) { /* Has the stat function been called recently? If
2704 so, we can use the cached value. */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002705 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002706 }
2707
2708 MYDB_BEGIN_ALLOW_THREADS;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002709redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002710#if (DBVER >= 43)
2711 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2712#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002713 err = self->db->stat(self->db, &sp, flags);
2714#else
2715 err = self->db->stat(self->db, &sp, NULL, flags);
2716#endif
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002717
2718 /* All the stat structures have matching fields upto the ndata field,
2719 so we can use any of them for the type cast */
2720 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2721
2722 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2723 * redo a full stat to make sure.
2724 * Fixes SF python bug 1493322, pybsddb bug 1184012
2725 */
2726 if (size == 0 && (flags & DB_FAST_STAT)) {
2727 flags = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002728 if (!err)
2729 free(sp);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002730 goto redo_stat_for_length;
2731 }
2732
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002733 MYDB_END_ALLOW_THREADS;
2734
2735 if (err)
2736 return -1;
2737
2738 self->haveStat = 1;
2739
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002740 free(sp);
2741 return size;
2742}
2743
2744
2745PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2746{
2747 int err;
2748 PyObject* retval;
Thomas Heller39763a12007-09-24 14:43:56 +00002749 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002750 DBT key;
2751 DBT data;
2752
2753 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002754 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002755 return NULL;
2756
2757 CLEAR_DBT(data);
2758 if (CHECK_DBFLAG(self, DB_THREAD)) {
2759 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2760 data.flags = DB_DBT_MALLOC;
2761 }
2762 MYDB_BEGIN_ALLOW_THREADS;
2763 err = self->db->get(self->db, NULL, &key, &data, 0);
2764 MYDB_END_ALLOW_THREADS;
2765 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2766 PyErr_SetObject(PyExc_KeyError, keyobj);
2767 retval = NULL;
2768 }
2769 else if (makeDBError(err)) {
2770 retval = NULL;
2771 }
2772 else {
Martin v. Löwis64ce5052007-08-05 15:39:16 +00002773 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002774 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002775 }
2776
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002777 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002778 return retval;
2779}
2780
2781
2782static int
2783DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2784{
2785 DBT key, data;
2786 int retval;
2787 int flags = 0;
Thomas Heller39763a12007-09-24 14:43:56 +00002788 Py_buffer *data_buf_view = NULL;
2789 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002790
2791 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002792 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2793 PyErr_SetObject(DBError, t);
2794 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002795 return -1;
2796 }
2797
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002798 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002799 return -1;
2800
2801 if (dataobj != NULL) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002802 if (!make_dbt(dataobj, &data, &data_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002803 retval = -1;
2804 else {
2805 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002806 /* dictionaries shouldn't have duplicate keys */
2807 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002808 retval = _DB_put(self, NULL, &key, &data, flags);
2809
2810 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002811 /* try deleting any old record that matches and then PUT it
2812 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002813 _DB_delete(self, NULL, &key, 0);
2814 PyErr_Clear();
2815 retval = _DB_put(self, NULL, &key, &data, flags);
2816 }
2817 }
2818 }
2819 else {
2820 /* dataobj == NULL, so delete the key */
2821 retval = _DB_delete(self, NULL, &key, 0);
2822 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002823 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2824 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002825 return retval;
2826}
2827
2828
2829static PyObject*
2830DB_has_key(DBObject* self, PyObject* args)
2831{
2832 int err;
2833 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00002834 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002835 DBT key, data;
2836 PyObject* txnobj = NULL;
2837 DB_TXN *txn = NULL;
2838
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002839 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002840 return NULL;
2841 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002842 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002843 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002844 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002845 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002846 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002847 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002848
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002849 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002850 it has a record but can't allocate a buffer for the data. This saves
2851 having to deal with data we won't be using.
2852 */
2853 CLEAR_DBT(data);
2854 data.flags = DB_DBT_USERMEM;
2855
2856 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002857 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002858 MYDB_END_ALLOW_THREADS;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002859 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002860
2861 if (err == DB_BUFFER_SMALL || err == 0) {
2862 return PyInt_FromLong(1);
2863 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2864 return PyInt_FromLong(0);
2865 }
2866
2867 makeDBError(err);
2868 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002869}
2870
2871
2872#define _KEYS_LIST 1
2873#define _VALUES_LIST 2
2874#define _ITEMS_LIST 3
2875
2876static PyObject*
2877_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2878{
2879 int err, dbtype;
2880 DBT key;
2881 DBT data;
2882 DBC *cursor;
2883 PyObject* list;
2884 PyObject* item = NULL;
2885
2886 CHECK_DB_NOT_CLOSED(self);
2887 CLEAR_DBT(key);
2888 CLEAR_DBT(data);
2889
2890 dbtype = _DB_get_type(self);
2891 if (dbtype == -1)
2892 return NULL;
2893
2894 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002895 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002896 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002897
2898 /* get a cursor */
2899 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002900 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002901 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002902 if (makeDBError(err)) {
2903 Py_DECREF(list);
2904 return NULL;
2905 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002906
2907 if (CHECK_DBFLAG(self, DB_THREAD)) {
2908 key.flags = DB_DBT_REALLOC;
2909 data.flags = DB_DBT_REALLOC;
2910 }
2911
2912 while (1) { /* use the cursor to traverse the DB, collecting items */
2913 MYDB_BEGIN_ALLOW_THREADS;
2914 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2915 MYDB_END_ALLOW_THREADS;
2916
2917 if (err) {
2918 /* for any error, break out of the loop */
2919 break;
2920 }
2921
2922 switch (type) {
2923 case _KEYS_LIST:
2924 switch(dbtype) {
2925 case DB_BTREE:
2926 case DB_HASH:
2927 default:
Martin v. Löwis64ce5052007-08-05 15:39:16 +00002928 item = PyBytes_FromStringAndSize((char*)key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002929 break;
2930 case DB_RECNO:
2931 case DB_QUEUE:
2932 item = PyInt_FromLong(*((db_recno_t*)key.data));
2933 break;
2934 }
2935 break;
2936
2937 case _VALUES_LIST:
Martin v. Löwis64ce5052007-08-05 15:39:16 +00002938 item = PyBytes_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002939 break;
2940
2941 case _ITEMS_LIST:
2942 switch(dbtype) {
2943 case DB_BTREE:
2944 case DB_HASH:
2945 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002946 item = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002947 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002948 break;
2949 case DB_RECNO:
2950 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002951 item = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002952 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002953 break;
2954 }
2955 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002956 default:
2957 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2958 item = NULL;
2959 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002960 }
2961 if (item == NULL) {
2962 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002963 list = NULL;
2964 goto done;
2965 }
2966 PyList_Append(list, item);
2967 Py_DECREF(item);
2968 }
2969
Gregory P. Smithe9477062005-06-04 06:46:59 +00002970 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2971 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002972 Py_DECREF(list);
2973 list = NULL;
2974 }
2975
2976 done:
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002977 free_dbt(&key);
2978 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002979 MYDB_BEGIN_ALLOW_THREADS;
2980 cursor->c_close(cursor);
2981 MYDB_END_ALLOW_THREADS;
2982 return list;
2983}
2984
2985
2986static PyObject*
2987DB_keys(DBObject* self, PyObject* args)
2988{
2989 PyObject* txnobj = NULL;
2990 DB_TXN *txn = NULL;
2991
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00002992 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002993 return NULL;
2994 if (!checkTxnObj(txnobj, &txn))
2995 return NULL;
2996 return _DB_make_list(self, txn, _KEYS_LIST);
2997}
2998
2999
3000static PyObject*
3001DB_items(DBObject* self, PyObject* args)
3002{
3003 PyObject* txnobj = NULL;
3004 DB_TXN *txn = NULL;
3005
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003006 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003007 return NULL;
3008 if (!checkTxnObj(txnobj, &txn))
3009 return NULL;
3010 return _DB_make_list(self, txn, _ITEMS_LIST);
3011}
3012
3013
3014static PyObject*
3015DB_values(DBObject* self, PyObject* args)
3016{
3017 PyObject* txnobj = NULL;
3018 DB_TXN *txn = NULL;
3019
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003020 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003021 return NULL;
3022 if (!checkTxnObj(txnobj, &txn))
3023 return NULL;
3024 return _DB_make_list(self, txn, _VALUES_LIST);
3025}
3026
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003027/* --------------------------------------------------------------------- */
3028/* DBCursor methods */
3029
3030
3031static PyObject*
3032DBC_close(DBCursorObject* self, PyObject* args)
3033{
3034 int err = 0;
3035
3036 if (!PyArg_ParseTuple(args, ":close"))
3037 return NULL;
3038
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003039 if (self->dbc != NULL) {
3040 MYDB_BEGIN_ALLOW_THREADS;
3041 err = self->dbc->c_close(self->dbc);
3042 self->dbc = NULL;
3043 MYDB_END_ALLOW_THREADS;
3044 }
3045 RETURN_IF_ERR();
3046 RETURN_NONE();
3047}
3048
3049
3050static PyObject*
3051DBC_count(DBCursorObject* self, PyObject* args)
3052{
3053 int err = 0;
3054 db_recno_t count;
3055 int flags = 0;
3056
3057 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3058 return NULL;
3059
3060 CHECK_CURSOR_NOT_CLOSED(self);
3061
3062 MYDB_BEGIN_ALLOW_THREADS;
3063 err = self->dbc->c_count(self->dbc, &count, flags);
3064 MYDB_END_ALLOW_THREADS;
3065 RETURN_IF_ERR();
3066
3067 return PyInt_FromLong(count);
3068}
3069
3070
3071static PyObject*
3072DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3073{
3074 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3075}
3076
3077
3078static PyObject*
3079DBC_delete(DBCursorObject* self, PyObject* args)
3080{
3081 int err, flags=0;
3082
3083 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3084 return NULL;
3085
3086 CHECK_CURSOR_NOT_CLOSED(self);
3087
3088 MYDB_BEGIN_ALLOW_THREADS;
3089 err = self->dbc->c_del(self->dbc, flags);
3090 MYDB_END_ALLOW_THREADS;
3091 RETURN_IF_ERR();
3092
3093 self->mydb->haveStat = 0;
3094 RETURN_NONE();
3095}
3096
3097
3098static PyObject*
3099DBC_dup(DBCursorObject* self, PyObject* args)
3100{
3101 int err, flags =0;
3102 DBC* dbc = NULL;
3103
3104 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3105 return NULL;
3106
3107 CHECK_CURSOR_NOT_CLOSED(self);
3108
3109 MYDB_BEGIN_ALLOW_THREADS;
3110 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3111 MYDB_END_ALLOW_THREADS;
3112 RETURN_IF_ERR();
3113
3114 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3115}
3116
3117static PyObject*
3118DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3119{
3120 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3121}
3122
3123
3124static PyObject*
3125DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3126{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003127 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003128 PyObject* keyobj = NULL;
3129 PyObject* dataobj = NULL;
3130 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00003131 Py_buffer* data_buf_view = NULL;
3132 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003133 int dlen = -1;
3134 int doff = -1;
3135 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003136 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003137 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003138
3139 CLEAR_DBT(key);
3140 CLEAR_DBT(data);
3141 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003142 &flags, &dlen, &doff))
3143 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003144 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003145 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3146 &kwnames[1],
3147 &keyobj, &flags, &dlen, &doff))
3148 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003149 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003150 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3151 kwnames, &keyobj, &dataobj,
3152 &flags, &dlen, &doff))
3153 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003154 return NULL;
3155 }
3156 }
3157 }
3158
3159 CHECK_CURSOR_NOT_CLOSED(self);
3160
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003161 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003162 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003163 if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003164 (!add_partial_dbt(&data, dlen, doff)) )
3165 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003166 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3167 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003168 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003169 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003170
3171 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3172 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003173 if (!(key.flags & DB_DBT_REALLOC)) {
3174 key.flags |= DB_DBT_MALLOC;
3175 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003176 }
3177
3178 MYDB_BEGIN_ALLOW_THREADS;
3179 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3180 MYDB_END_ALLOW_THREADS;
3181
Gregory P. Smithe9477062005-06-04 06:46:59 +00003182 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3183 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003184 Py_INCREF(Py_None);
3185 retval = Py_None;
3186 }
3187 else if (makeDBError(err)) {
3188 retval = NULL;
3189 }
3190 else {
3191 switch (_DB_get_type(self->mydb)) {
3192 case -1:
3193 retval = NULL;
3194 break;
3195 case DB_BTREE:
3196 case DB_HASH:
3197 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003198 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003199 data.data, data.size);
3200 break;
3201 case DB_RECNO:
3202 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003203 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003204 data.data, data.size);
3205 break;
3206 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003207 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003208 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003209 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3210 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003211 return retval;
3212}
3213
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003214#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003215static PyObject*
3216DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3217{
3218 int err, flags=0;
3219 PyObject* keyobj = NULL;
3220 PyObject* dataobj = NULL;
3221 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00003222 Py_buffer* data_buf_view = NULL;
3223 Py_buffer* key_buf_view = NULL;
Gregory P. Smith19699a92004-06-28 04:06:49 +00003224 int dlen = -1;
3225 int doff = -1;
3226 DBT key, pkey, data;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003227 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3228 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003229
3230 CLEAR_DBT(key);
3231 CLEAR_DBT(data);
3232 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3233 &flags, &dlen, &doff))
3234 {
3235 PyErr_Clear();
3236 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003237 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003238 &keyobj, &flags, &dlen, &doff))
3239 {
3240 PyErr_Clear();
3241 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3242 kwnames, &keyobj, &dataobj,
3243 &flags, &dlen, &doff))
3244 {
3245 return NULL;
3246 }
3247 }
3248 }
3249
3250 CHECK_CURSOR_NOT_CLOSED(self);
3251
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003252 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Gregory P. Smith19699a92004-06-28 04:06:49 +00003253 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003254 if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) ||
Gregory P. Smith19699a92004-06-28 04:06:49 +00003255 (!add_partial_dbt(&data, dlen, doff)) ) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003256 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3257 free_buf_view(dataobj, data_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003258 return NULL;
3259 }
3260
3261 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3262 data.flags = DB_DBT_MALLOC;
3263 if (!(key.flags & DB_DBT_REALLOC)) {
3264 key.flags |= DB_DBT_MALLOC;
3265 }
3266 }
3267
3268 CLEAR_DBT(pkey);
3269 pkey.flags = DB_DBT_MALLOC;
3270
3271 MYDB_BEGIN_ALLOW_THREADS;
3272 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3273 MYDB_END_ALLOW_THREADS;
3274
Gregory P. Smithe9477062005-06-04 06:46:59 +00003275 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3276 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003277 Py_INCREF(Py_None);
3278 retval = Py_None;
3279 }
3280 else if (makeDBError(err)) {
3281 retval = NULL;
3282 }
3283 else {
3284 PyObject *pkeyObj;
3285 PyObject *dataObj;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003286 dataObj = PyBytes_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003287
3288 if (self->mydb->primaryDBType == DB_RECNO ||
3289 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003290 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003291 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003292 pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003293
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003294 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003295 {
3296 PyObject *keyObj;
3297 int type = _DB_get_type(self->mydb);
3298 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003299 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003300 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003301 keyObj = PyBytes_FromStringAndSize(key.data, key.size);
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003302 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Thomas Woutersb3153832006-03-08 01:47:19 +00003303 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003304 }
3305 else /* return just the pkey and data */
3306 {
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003307 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003308 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003309 Py_DECREF(dataObj);
3310 Py_DECREF(pkeyObj);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003311 free_dbt(&pkey);
3312 free_dbt(&data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003313 }
3314 /* the only time REALLOC should be set is if we used an integer
3315 * key that make_key_dbt malloc'd for us. always free these. */
3316 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003317 free_dbt(&key);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003318 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003319 free_buf_view(keyobj, key_buf_view);
3320 free_buf_view(dataobj, data_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003321 return retval;
3322}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003323#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003324
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003325
3326static PyObject*
3327DBC_get_recno(DBCursorObject* self, PyObject* args)
3328{
3329 int err;
3330 db_recno_t recno;
3331 DBT key;
3332 DBT data;
3333
3334 if (!PyArg_ParseTuple(args, ":get_recno"))
3335 return NULL;
3336
3337 CHECK_CURSOR_NOT_CLOSED(self);
3338
3339 CLEAR_DBT(key);
3340 CLEAR_DBT(data);
3341 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3342 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3343 data.flags = DB_DBT_MALLOC;
3344 key.flags = DB_DBT_MALLOC;
3345 }
3346
3347 MYDB_BEGIN_ALLOW_THREADS;
3348 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3349 MYDB_END_ALLOW_THREADS;
3350 RETURN_IF_ERR();
3351
3352 recno = *((db_recno_t*)data.data);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003353 free_dbt(&key);
3354 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003355 return PyInt_FromLong(recno);
3356}
3357
3358
3359static PyObject*
3360DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3361{
3362 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3363}
3364
3365
3366static PyObject*
3367DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3368{
3369 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3370}
3371
3372
3373static PyObject*
3374DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3375{
3376 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3377}
3378
3379
3380static PyObject*
3381DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3382{
3383 int err, flags = 0;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003384 PyObject *keyobj, *dataobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003385 Py_buffer *data_buf_view = NULL;
3386 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003387 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003388 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003389 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003390 int dlen = -1;
3391 int doff = -1;
3392
3393 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3394 &keyobj, &dataobj, &flags, &dlen, &doff))
3395 return NULL;
3396
3397 CHECK_CURSOR_NOT_CLOSED(self);
3398
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003399 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003400 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003401 if (!make_dbt(dataobj, &data, &data_buf_view) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003402 !add_partial_dbt(&data, dlen, doff) )
3403 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003404 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3405 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003406 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003407 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003408
3409 MYDB_BEGIN_ALLOW_THREADS;
3410 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3411 MYDB_END_ALLOW_THREADS;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003412 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3413 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003414 RETURN_IF_ERR();
3415 self->mydb->haveStat = 0;
3416 RETURN_NONE();
3417}
3418
3419
3420static PyObject*
3421DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3422{
3423 int err, flags = 0;
3424 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003425 PyObject *retval, *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003426 Py_buffer *key_buf_view = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003427 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003428 int dlen = -1;
3429 int doff = -1;
3430
3431 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3432 &keyobj, &flags, &dlen, &doff))
3433 return NULL;
3434
3435 CHECK_CURSOR_NOT_CLOSED(self);
3436
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003437 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003438 return NULL;
3439
3440 CLEAR_DBT(data);
3441 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3442 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3443 data.flags = DB_DBT_MALLOC;
3444 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003445 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003446 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003447 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003448 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003449
3450 MYDB_BEGIN_ALLOW_THREADS;
3451 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3452 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003453 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3454 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003455 Py_INCREF(Py_None);
3456 retval = Py_None;
3457 }
3458 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003459 retval = NULL;
3460 }
3461 else {
3462 switch (_DB_get_type(self->mydb)) {
3463 case -1:
3464 retval = NULL;
3465 break;
3466 case DB_BTREE:
3467 case DB_HASH:
3468 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003469 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003470 data.data, data.size);
3471 break;
3472 case DB_RECNO:
3473 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003474 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003475 data.data, data.size);
3476 break;
3477 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003478 free_dbt(&data);
3479 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003480 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003481 /* the only time REALLOC should be set is if we used an integer
3482 * key that make_key_dbt malloc'd for us. always free these. */
3483 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003484 free_dbt(&key);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003485 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003486 free_buf_view(keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003487
3488 return retval;
3489}
3490
3491
3492static PyObject*
3493DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3494{
3495 int err, flags = 0;
3496 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003497 PyObject *retval, *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003498 Py_buffer *key_buf_view = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003499 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003500 int dlen = -1;
3501 int doff = -1;
3502
3503 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3504 &keyobj, &flags, &dlen, &doff))
3505 return NULL;
3506
3507 CHECK_CURSOR_NOT_CLOSED(self);
3508
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003509 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003510 return NULL;
3511
3512 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003513 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003514 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003515 return NULL;
3516 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003517 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3518 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003519 data.flags |= DB_DBT_MALLOC;
3520 /* only BTREE databases will return anything in the key */
3521 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3522 key.flags |= DB_DBT_MALLOC;
3523 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003524 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003525 MYDB_BEGIN_ALLOW_THREADS;
3526 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3527 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003528 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3529 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003530 Py_INCREF(Py_None);
3531 retval = Py_None;
3532 }
3533 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003534 retval = NULL;
3535 }
3536 else {
3537 switch (_DB_get_type(self->mydb)) {
3538 case -1:
3539 retval = NULL;
3540 break;
3541 case DB_BTREE:
3542 case DB_HASH:
3543 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003544 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003545 data.data, data.size);
3546 break;
3547 case DB_RECNO:
3548 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003549 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003550 data.data, data.size);
3551 break;
3552 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003553 free_dbt(&key);
3554 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003555 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003556 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003557 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003558 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003559 free_dbt(&key);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003560 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003561 free_buf_view(keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003562
3563 return retval;
3564}
3565
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003566static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003567_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3568 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003569{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003570 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003571 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003572 PyObject *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00003573 Py_buffer *data_buf_view = NULL;
3574 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003575
Gregory P. Smith7441e652003-11-03 21:35:31 +00003576 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003577 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003578 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003579 if (!make_dbt(dataobj, &data, &data_buf_view)) {
3580 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003581 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003582 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003583
3584 MYDB_BEGIN_ALLOW_THREADS;
3585 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3586 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003587 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003588 Py_INCREF(Py_None);
3589 retval = Py_None;
3590 }
3591 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003592 retval = NULL;
3593 }
3594 else {
3595 switch (_DB_get_type(self->mydb)) {
3596 case -1:
3597 retval = NULL;
3598 break;
3599 case DB_BTREE:
3600 case DB_HASH:
3601 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003602 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003603 data.data, data.size);
3604 break;
3605 case DB_RECNO:
3606 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003607 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003608 data.data, data.size);
3609 break;
3610 }
3611 }
3612
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003613 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3614 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003615 return retval;
3616}
3617
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003618static PyObject*
3619DBC_get_both(DBCursorObject* self, PyObject* args)
3620{
3621 int flags=0;
3622 PyObject *keyobj, *dataobj;
3623
3624 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3625 return NULL;
3626
Gregory P. Smith7441e652003-11-03 21:35:31 +00003627 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003628 CHECK_CURSOR_NOT_CLOSED(self);
3629
3630 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3631 self->mydb->moduleFlags.getReturnsNone);
3632}
3633
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003634/* Return size of entry */
3635static PyObject*
3636DBC_get_current_size(DBCursorObject* self, PyObject* args)
3637{
3638 int err, flags=DB_CURRENT;
3639 PyObject* retval = NULL;
3640 DBT key, data;
3641
3642 if (!PyArg_ParseTuple(args, ":get_current_size"))
3643 return NULL;
3644 CHECK_CURSOR_NOT_CLOSED(self);
3645 CLEAR_DBT(key);
3646 CLEAR_DBT(data);
3647
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003648 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003649 getting the record size. */
3650 data.flags = DB_DBT_USERMEM;
3651 data.ulen = 0;
3652 MYDB_BEGIN_ALLOW_THREADS;
3653 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3654 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003655 if (err == DB_BUFFER_SMALL || !err) {
3656 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003657 retval = PyInt_FromLong((long)data.size);
3658 err = 0;
3659 }
3660
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003661 free_dbt(&key);
3662 free_dbt(&data);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003663 RETURN_IF_ERR();
3664 return retval;
3665}
3666
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003667static PyObject*
3668DBC_set_both(DBCursorObject* self, PyObject* args)
3669{
3670 int flags=0;
3671 PyObject *keyobj, *dataobj;
3672
3673 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3674 return NULL;
3675
Gregory P. Smith7441e652003-11-03 21:35:31 +00003676 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003677 CHECK_CURSOR_NOT_CLOSED(self);
3678
3679 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3680 self->mydb->moduleFlags.cursorSetReturnsNone);
3681}
3682
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003683
3684static PyObject*
3685DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3686{
3687 int err, irecno, flags=0;
3688 db_recno_t recno;
3689 DBT key, data;
3690 PyObject* retval;
3691 int dlen = -1;
3692 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003693 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003694
3695 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3696 &irecno, &flags, &dlen, &doff))
3697 return NULL;
3698
3699 CHECK_CURSOR_NOT_CLOSED(self);
3700
3701 CLEAR_DBT(key);
3702 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003703 /* use allocated space so DB will be able to realloc room for the real
3704 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003705 key.data = malloc(sizeof(db_recno_t));
3706 if (key.data == NULL) {
3707 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3708 return NULL;
3709 }
3710 key.size = sizeof(db_recno_t);
3711 key.ulen = key.size;
3712 memcpy(key.data, &recno, sizeof(db_recno_t));
3713 key.flags = DB_DBT_REALLOC;
3714
3715 CLEAR_DBT(data);
3716 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3717 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3718 data.flags = DB_DBT_MALLOC;
3719 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003720 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003721 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003722 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003723 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003724
3725 MYDB_BEGIN_ALLOW_THREADS;
3726 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3727 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003728 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3729 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003730 Py_INCREF(Py_None);
3731 retval = Py_None;
3732 }
3733 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003734 retval = NULL;
3735 }
3736 else { /* Can only be used for BTrees, so no need to return int key */
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003737 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003738 data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003739 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003740 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003741 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003742
3743 return retval;
3744}
3745
3746
3747static PyObject*
3748DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3749{
3750 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3751}
3752
3753
3754static PyObject*
3755DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3756{
3757 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3758}
3759
3760
3761static PyObject*
3762DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3763{
3764 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3765}
3766
3767
3768static PyObject*
3769DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3770{
3771 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3772}
3773
3774
3775static PyObject*
3776DBC_join_item(DBCursorObject* self, PyObject* args)
3777{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003778 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003779 DBT key, data;
3780 PyObject* retval;
3781
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003782 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003783 return NULL;
3784
3785 CHECK_CURSOR_NOT_CLOSED(self);
3786
3787 CLEAR_DBT(key);
3788 CLEAR_DBT(data);
3789 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3790 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3791 key.flags = DB_DBT_MALLOC;
3792 }
3793
3794 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003795 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003796 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003797 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3798 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003799 Py_INCREF(Py_None);
3800 retval = Py_None;
3801 }
3802 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003803 retval = NULL;
3804 }
3805 else {
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003806 retval = Py_BuildValue("y#", key.data, key.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003807 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003808 }
3809
3810 return retval;
3811}
3812
3813
3814
3815/* --------------------------------------------------------------------- */
3816/* DBEnv methods */
3817
3818
3819static PyObject*
3820DBEnv_close(DBEnvObject* self, PyObject* args)
3821{
3822 int err, flags = 0;
3823
3824 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3825 return NULL;
3826 if (!self->closed) { /* Don't close more than once */
3827 MYDB_BEGIN_ALLOW_THREADS;
3828 err = self->db_env->close(self->db_env, flags);
3829 MYDB_END_ALLOW_THREADS;
3830 /* after calling DBEnv->close, regardless of error, this DBEnv
3831 * may not be accessed again (BerkeleyDB docs). */
3832 self->closed = 1;
3833 self->db_env = NULL;
3834 RETURN_IF_ERR();
3835 }
3836 RETURN_NONE();
3837}
3838
3839
3840static PyObject*
3841DBEnv_open(DBEnvObject* self, PyObject* args)
3842{
3843 int err, flags=0, mode=0660;
3844 char *db_home;
3845
3846 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3847 return NULL;
3848
3849 CHECK_ENV_NOT_CLOSED(self);
3850
3851 MYDB_BEGIN_ALLOW_THREADS;
3852 err = self->db_env->open(self->db_env, db_home, flags, mode);
3853 MYDB_END_ALLOW_THREADS;
3854 RETURN_IF_ERR();
3855 self->closed = 0;
3856 self->flags = flags;
3857 RETURN_NONE();
3858}
3859
3860
3861static PyObject*
3862DBEnv_remove(DBEnvObject* self, PyObject* args)
3863{
3864 int err, flags=0;
3865 char *db_home;
3866
3867 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3868 return NULL;
3869 CHECK_ENV_NOT_CLOSED(self);
3870 MYDB_BEGIN_ALLOW_THREADS;
3871 err = self->db_env->remove(self->db_env, db_home, flags);
3872 MYDB_END_ALLOW_THREADS;
3873 RETURN_IF_ERR();
3874 RETURN_NONE();
3875}
3876
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003877#if (DBVER >= 41)
3878static PyObject*
3879DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3880{
3881 int err;
3882 u_int32_t flags=0;
3883 char *file = NULL;
3884 char *database = NULL;
3885 PyObject *txnobj = NULL;
3886 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003887 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003888 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003889
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003890 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003891 &file, &database, &txnobj, &flags)) {
3892 return NULL;
3893 }
3894 if (!checkTxnObj(txnobj, &txn)) {
3895 return NULL;
3896 }
3897 CHECK_ENV_NOT_CLOSED(self);
3898 MYDB_BEGIN_ALLOW_THREADS;
3899 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3900 MYDB_END_ALLOW_THREADS;
3901 RETURN_IF_ERR();
3902 RETURN_NONE();
3903}
3904
3905static PyObject*
3906DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3907{
3908 int err;
3909 u_int32_t flags=0;
3910 char *file = NULL;
3911 char *database = NULL;
3912 char *newname = NULL;
3913 PyObject *txnobj = NULL;
3914 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003915 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003916 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003917
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003918 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003919 &file, &database, &newname, &txnobj, &flags)) {
3920 return NULL;
3921 }
3922 if (!checkTxnObj(txnobj, &txn)) {
3923 return NULL;
3924 }
3925 CHECK_ENV_NOT_CLOSED(self);
3926 MYDB_BEGIN_ALLOW_THREADS;
3927 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3928 flags);
3929 MYDB_END_ALLOW_THREADS;
3930 RETURN_IF_ERR();
3931 RETURN_NONE();
3932}
3933
3934static PyObject*
3935DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3936{
3937 int err;
3938 u_int32_t flags=0;
3939 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003940 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003941
3942 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3943 &passwd, &flags)) {
3944 return NULL;
3945 }
3946
3947 MYDB_BEGIN_ALLOW_THREADS;
3948 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3949 MYDB_END_ALLOW_THREADS;
3950
3951 RETURN_IF_ERR();
3952 RETURN_NONE();
3953}
3954#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003955
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003956#if (DBVER >= 40)
3957static PyObject*
3958DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3959{
3960 int err;
3961 u_int32_t flags=0;
3962 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003963 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003964
3965 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3966 &timeout, &flags)) {
3967 return NULL;
3968 }
3969
3970 MYDB_BEGIN_ALLOW_THREADS;
3971 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3972 MYDB_END_ALLOW_THREADS;
3973
3974 RETURN_IF_ERR();
3975 RETURN_NONE();
3976}
3977#endif /* DBVER >= 40 */
3978
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003979static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003980DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3981{
3982 int err;
3983 long shm_key = 0;
3984
3985 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3986 return NULL;
3987 CHECK_ENV_NOT_CLOSED(self);
3988
3989 err = self->db_env->set_shm_key(self->db_env, shm_key);
3990 RETURN_IF_ERR();
3991 RETURN_NONE();
3992}
3993
3994static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003995DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3996{
3997 int err, gbytes=0, bytes=0, ncache=0;
3998
3999 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4000 &gbytes, &bytes, &ncache))
4001 return NULL;
4002 CHECK_ENV_NOT_CLOSED(self);
4003
4004 MYDB_BEGIN_ALLOW_THREADS;
4005 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4006 MYDB_END_ALLOW_THREADS;
4007 RETURN_IF_ERR();
4008 RETURN_NONE();
4009}
4010
4011
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004012static PyObject*
4013DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4014{
4015 int err, flags=0, onoff=0;
4016
4017 if (!PyArg_ParseTuple(args, "ii:set_flags",
4018 &flags, &onoff))
4019 return NULL;
4020 CHECK_ENV_NOT_CLOSED(self);
4021
4022 MYDB_BEGIN_ALLOW_THREADS;
4023 err = self->db_env->set_flags(self->db_env, flags, onoff);
4024 MYDB_END_ALLOW_THREADS;
4025 RETURN_IF_ERR();
4026 RETURN_NONE();
4027}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004028
4029
4030static PyObject*
4031DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4032{
4033 int err;
4034 char *dir;
4035
4036 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4037 return NULL;
4038 CHECK_ENV_NOT_CLOSED(self);
4039
4040 MYDB_BEGIN_ALLOW_THREADS;
4041 err = self->db_env->set_data_dir(self->db_env, dir);
4042 MYDB_END_ALLOW_THREADS;
4043 RETURN_IF_ERR();
4044 RETURN_NONE();
4045}
4046
4047
4048static PyObject*
4049DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4050{
4051 int err, lg_bsize;
4052
4053 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4054 return NULL;
4055 CHECK_ENV_NOT_CLOSED(self);
4056
4057 MYDB_BEGIN_ALLOW_THREADS;
4058 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4059 MYDB_END_ALLOW_THREADS;
4060 RETURN_IF_ERR();
4061 RETURN_NONE();
4062}
4063
4064
4065static PyObject*
4066DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4067{
4068 int err;
4069 char *dir;
4070
4071 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4072 return NULL;
4073 CHECK_ENV_NOT_CLOSED(self);
4074
4075 MYDB_BEGIN_ALLOW_THREADS;
4076 err = self->db_env->set_lg_dir(self->db_env, dir);
4077 MYDB_END_ALLOW_THREADS;
4078 RETURN_IF_ERR();
4079 RETURN_NONE();
4080}
4081
4082static PyObject*
4083DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4084{
4085 int err, lg_max;
4086
4087 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4088 return NULL;
4089 CHECK_ENV_NOT_CLOSED(self);
4090
4091 MYDB_BEGIN_ALLOW_THREADS;
4092 err = self->db_env->set_lg_max(self->db_env, lg_max);
4093 MYDB_END_ALLOW_THREADS;
4094 RETURN_IF_ERR();
4095 RETURN_NONE();
4096}
4097
4098
Neal Norwitz84562352005-10-20 04:30:15 +00004099#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004100static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004101DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4102{
4103 int err, lg_max;
4104
4105 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4106 return NULL;
4107 CHECK_ENV_NOT_CLOSED(self);
4108
4109 MYDB_BEGIN_ALLOW_THREADS;
4110 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4111 MYDB_END_ALLOW_THREADS;
4112 RETURN_IF_ERR();
4113 RETURN_NONE();
4114}
Neal Norwitz84562352005-10-20 04:30:15 +00004115#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004116
4117
4118static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004119DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4120{
4121 int err, lk_detect;
4122
4123 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4124 return NULL;
4125 CHECK_ENV_NOT_CLOSED(self);
4126
4127 MYDB_BEGIN_ALLOW_THREADS;
4128 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4129 MYDB_END_ALLOW_THREADS;
4130 RETURN_IF_ERR();
4131 RETURN_NONE();
4132}
4133
4134
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004135#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004136static PyObject*
4137DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4138{
4139 int err, max;
4140
4141 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4142 return NULL;
4143 CHECK_ENV_NOT_CLOSED(self);
4144
4145 MYDB_BEGIN_ALLOW_THREADS;
4146 err = self->db_env->set_lk_max(self->db_env, max);
4147 MYDB_END_ALLOW_THREADS;
4148 RETURN_IF_ERR();
4149 RETURN_NONE();
4150}
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004151#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004152
4153
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004154
4155static PyObject*
4156DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4157{
4158 int err, max;
4159
4160 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4161 return NULL;
4162 CHECK_ENV_NOT_CLOSED(self);
4163
4164 MYDB_BEGIN_ALLOW_THREADS;
4165 err = self->db_env->set_lk_max_locks(self->db_env, max);
4166 MYDB_END_ALLOW_THREADS;
4167 RETURN_IF_ERR();
4168 RETURN_NONE();
4169}
4170
4171
4172static PyObject*
4173DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4174{
4175 int err, max;
4176
4177 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4178 return NULL;
4179 CHECK_ENV_NOT_CLOSED(self);
4180
4181 MYDB_BEGIN_ALLOW_THREADS;
4182 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4183 MYDB_END_ALLOW_THREADS;
4184 RETURN_IF_ERR();
4185 RETURN_NONE();
4186}
4187
4188
4189static PyObject*
4190DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4191{
4192 int err, max;
4193
4194 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4195 return NULL;
4196 CHECK_ENV_NOT_CLOSED(self);
4197
4198 MYDB_BEGIN_ALLOW_THREADS;
4199 err = self->db_env->set_lk_max_objects(self->db_env, max);
4200 MYDB_END_ALLOW_THREADS;
4201 RETURN_IF_ERR();
4202 RETURN_NONE();
4203}
4204
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004205
4206static PyObject*
4207DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4208{
4209 int err, mp_mmapsize;
4210
4211 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4212 return NULL;
4213 CHECK_ENV_NOT_CLOSED(self);
4214
4215 MYDB_BEGIN_ALLOW_THREADS;
4216 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4217 MYDB_END_ALLOW_THREADS;
4218 RETURN_IF_ERR();
4219 RETURN_NONE();
4220}
4221
4222
4223static PyObject*
4224DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4225{
4226 int err;
4227 char *dir;
4228
4229 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4230 return NULL;
4231 CHECK_ENV_NOT_CLOSED(self);
4232
4233 MYDB_BEGIN_ALLOW_THREADS;
4234 err = self->db_env->set_tmp_dir(self->db_env, dir);
4235 MYDB_END_ALLOW_THREADS;
4236 RETURN_IF_ERR();
4237 RETURN_NONE();
4238}
4239
4240
4241static PyObject*
4242DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4243{
4244 int flags = 0;
4245 PyObject* txnobj = NULL;
4246 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004247 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004248
4249 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4250 &txnobj, &flags))
4251 return NULL;
4252
4253 if (!checkTxnObj(txnobj, &txn))
4254 return NULL;
4255 CHECK_ENV_NOT_CLOSED(self);
4256
4257 return (PyObject*)newDBTxnObject(self, txn, flags);
4258}
4259
4260
4261static PyObject*
4262DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4263{
4264 int err, kbyte=0, min=0, flags=0;
4265
4266 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4267 return NULL;
4268 CHECK_ENV_NOT_CLOSED(self);
4269
4270 MYDB_BEGIN_ALLOW_THREADS;
4271#if (DBVER >= 40)
4272 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4273#else
4274 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4275#endif
4276 MYDB_END_ALLOW_THREADS;
4277 RETURN_IF_ERR();
4278 RETURN_NONE();
4279}
4280
4281
4282static PyObject*
4283DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4284{
4285 int err, max;
4286
4287 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4288 return NULL;
4289 CHECK_ENV_NOT_CLOSED(self);
4290
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004291 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004292 RETURN_IF_ERR();
4293 RETURN_NONE();
4294}
4295
4296
4297static PyObject*
4298DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4299{
4300 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004301 long stamp;
4302 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004303
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004304 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004305 return NULL;
4306 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004307 timestamp = (time_t)stamp;
4308 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004309 RETURN_IF_ERR();
4310 RETURN_NONE();
4311}
4312
4313
4314static PyObject*
4315DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4316{
4317 int err, atype, flags=0;
4318 int aborted = 0;
4319
4320 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4321 return NULL;
4322 CHECK_ENV_NOT_CLOSED(self);
4323
4324 MYDB_BEGIN_ALLOW_THREADS;
4325#if (DBVER >= 40)
4326 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4327#else
4328 err = lock_detect(self->db_env, flags, atype, &aborted);
4329#endif
4330 MYDB_END_ALLOW_THREADS;
4331 RETURN_IF_ERR();
4332 return PyInt_FromLong(aborted);
4333}
4334
4335
4336static PyObject*
4337DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4338{
4339 int flags=0;
4340 int locker, lock_mode;
4341 DBT obj;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004342 PyObject *objobj, *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00004343 Py_buffer *obj_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004344
4345 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4346 return NULL;
4347
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004348 if (!make_dbt(objobj, &obj, &obj_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004349 return NULL;
4350
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004351 retval = (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4352 free_buf_view(objobj, obj_buf_view);
4353 return retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004354}
4355
4356
4357static PyObject*
4358DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4359{
4360 int err;
4361 u_int32_t theID;
4362
4363 if (!PyArg_ParseTuple(args, ":lock_id"))
4364 return NULL;
4365
4366 CHECK_ENV_NOT_CLOSED(self);
4367 MYDB_BEGIN_ALLOW_THREADS;
4368#if (DBVER >= 40)
4369 err = self->db_env->lock_id(self->db_env, &theID);
4370#else
4371 err = lock_id(self->db_env, &theID);
4372#endif
4373 MYDB_END_ALLOW_THREADS;
4374 RETURN_IF_ERR();
4375
4376 return PyInt_FromLong((long)theID);
4377}
4378
4379
4380static PyObject*
4381DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4382{
4383 int err;
4384 DBLockObject* dblockobj;
4385
4386 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4387 return NULL;
4388
4389 CHECK_ENV_NOT_CLOSED(self);
4390 MYDB_BEGIN_ALLOW_THREADS;
4391#if (DBVER >= 40)
4392 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4393#else
4394 err = lock_put(self->db_env, &dblockobj->lock);
4395#endif
4396 MYDB_END_ALLOW_THREADS;
4397 RETURN_IF_ERR();
4398 RETURN_NONE();
4399}
4400
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004401#if (DBVER >= 44)
4402static PyObject*
4403DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4404{
4405 int err;
4406 char *file;
4407 u_int32_t flags = 0;
4408 static char* kwnames[] = { "file", "flags", NULL};
4409
4410 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4411 &file, &flags))
4412 return NULL;
4413 CHECK_ENV_NOT_CLOSED(self);
4414
4415 MYDB_BEGIN_ALLOW_THREADS;
4416 err = self->db_env->lsn_reset(self->db_env, file, flags);
4417 MYDB_END_ALLOW_THREADS;
4418 RETURN_IF_ERR();
4419 RETURN_NONE();
4420}
4421#endif /* DBVER >= 4.4 */
4422
4423#if (DBVER >= 40)
4424static PyObject*
4425DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4426{
4427 int err;
4428 DB_LOG_STAT* statp = NULL;
4429 PyObject* d = NULL;
4430 u_int32_t flags = 0;
4431
4432 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4433 return NULL;
4434 CHECK_ENV_NOT_CLOSED(self);
4435
4436 MYDB_BEGIN_ALLOW_THREADS;
4437 err = self->db_env->log_stat(self->db_env, &statp, flags);
4438 MYDB_END_ALLOW_THREADS;
4439 RETURN_IF_ERR();
4440
4441 /* Turn the stat structure into a dictionary */
4442 d = PyDict_New();
4443 if (d == NULL) {
4444 if (statp)
4445 free(statp);
4446 return NULL;
4447 }
4448
4449#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4450
4451 MAKE_ENTRY(magic);
4452 MAKE_ENTRY(version);
4453 MAKE_ENTRY(mode);
4454 MAKE_ENTRY(lg_bsize);
4455#if (DBVER >= 44)
4456 MAKE_ENTRY(lg_size);
4457 MAKE_ENTRY(record);
4458#endif
4459#if (DBVER <= 40)
4460 MAKE_ENTRY(lg_max);
4461#endif
4462 MAKE_ENTRY(w_mbytes);
4463 MAKE_ENTRY(w_bytes);
4464 MAKE_ENTRY(wc_mbytes);
4465 MAKE_ENTRY(wc_bytes);
4466 MAKE_ENTRY(wcount);
4467 MAKE_ENTRY(wcount_fill);
4468#if (DBVER >= 44)
4469 MAKE_ENTRY(rcount);
4470#endif
4471 MAKE_ENTRY(scount);
4472 MAKE_ENTRY(cur_file);
4473 MAKE_ENTRY(cur_offset);
4474 MAKE_ENTRY(disk_file);
4475 MAKE_ENTRY(disk_offset);
4476 MAKE_ENTRY(maxcommitperflush);
4477 MAKE_ENTRY(mincommitperflush);
4478 MAKE_ENTRY(regsize);
4479 MAKE_ENTRY(region_wait);
4480 MAKE_ENTRY(region_nowait);
4481
4482#undef MAKE_ENTRY
4483 free(statp);
4484 return d;
4485} /* DBEnv_log_stat */
4486#endif /* DBVER >= 4.0 for log_stat method */
4487
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004488
4489static PyObject*
4490DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4491{
4492 int err;
4493 DB_LOCK_STAT* sp;
4494 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004495 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004496
4497 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4498 return NULL;
4499 CHECK_ENV_NOT_CLOSED(self);
4500
4501 MYDB_BEGIN_ALLOW_THREADS;
4502#if (DBVER >= 40)
4503 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4504#else
4505#if (DBVER >= 33)
4506 err = lock_stat(self->db_env, &sp);
4507#else
4508 err = lock_stat(self->db_env, &sp, NULL);
4509#endif
4510#endif
4511 MYDB_END_ALLOW_THREADS;
4512 RETURN_IF_ERR();
4513
4514 /* Turn the stat structure into a dictionary */
4515 d = PyDict_New();
4516 if (d == NULL) {
4517 free(sp);
4518 return NULL;
4519 }
4520
4521#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4522
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004523#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004524 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004525#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004526 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004527 MAKE_ENTRY(maxlocks);
4528 MAKE_ENTRY(maxlockers);
4529 MAKE_ENTRY(maxobjects);
4530 MAKE_ENTRY(nlocks);
4531 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004532 MAKE_ENTRY(nlockers);
4533 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004534 MAKE_ENTRY(nobjects);
4535 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004536 MAKE_ENTRY(nrequests);
4537 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004538#if (DBVER < 44)
4539 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004540 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004541#else
4542 MAKE_ENTRY(lock_nowait);
4543 MAKE_ENTRY(lock_wait);
4544#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004545 MAKE_ENTRY(ndeadlocks);
4546 MAKE_ENTRY(regsize);
4547 MAKE_ENTRY(region_wait);
4548 MAKE_ENTRY(region_nowait);
4549
4550#undef MAKE_ENTRY
4551 free(sp);
4552 return d;
4553}
4554
4555
4556static PyObject*
4557DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4558{
4559 int flags=0;
4560 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004561 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004562 PyObject* list;
4563 PyObject* item = NULL;
4564
4565 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4566 return NULL;
4567
4568 CHECK_ENV_NOT_CLOSED(self);
4569 MYDB_BEGIN_ALLOW_THREADS;
4570#if (DBVER >= 40)
4571 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4572#elif (DBVER == 33)
4573 err = log_archive(self->db_env, &log_list, flags);
4574#else
4575 err = log_archive(self->db_env, &log_list, flags, NULL);
4576#endif
4577 MYDB_END_ALLOW_THREADS;
4578 RETURN_IF_ERR();
4579
4580 list = PyList_New(0);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004581 if (list == NULL) {
4582 if (log_list)
4583 free(log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004584 return NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004585 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004586
4587 if (log_list) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004588 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004589 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
Martin v. Löwis64ce5052007-08-05 15:39:16 +00004590 item = PyUnicode_FromString (*log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004591 if (item == NULL) {
4592 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004593 list = NULL;
4594 break;
4595 }
4596 PyList_Append(list, item);
4597 Py_DECREF(item);
4598 }
4599 free(log_list_start);
4600 }
4601 return list;
4602}
4603
4604
4605static PyObject*
4606DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4607{
4608 int err;
4609 DB_TXN_STAT* sp;
4610 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004611 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004612
4613 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4614 return NULL;
4615 CHECK_ENV_NOT_CLOSED(self);
4616
4617 MYDB_BEGIN_ALLOW_THREADS;
4618#if (DBVER >= 40)
4619 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4620#elif (DBVER == 33)
4621 err = txn_stat(self->db_env, &sp);
4622#else
4623 err = txn_stat(self->db_env, &sp, NULL);
4624#endif
4625 MYDB_END_ALLOW_THREADS;
4626 RETURN_IF_ERR();
4627
4628 /* Turn the stat structure into a dictionary */
4629 d = PyDict_New();
4630 if (d == NULL) {
4631 free(sp);
4632 return NULL;
4633 }
4634
4635#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00004636#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004637
Guido van Rossumd8faa362007-04-27 19:54:29 +00004638 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004639 MAKE_ENTRY(last_txnid);
4640 MAKE_ENTRY(maxtxns);
4641 MAKE_ENTRY(nactive);
4642 MAKE_ENTRY(maxnactive);
4643 MAKE_ENTRY(nbegins);
4644 MAKE_ENTRY(naborts);
4645 MAKE_ENTRY(ncommits);
4646 MAKE_ENTRY(regsize);
4647 MAKE_ENTRY(region_wait);
4648 MAKE_ENTRY(region_nowait);
4649
4650#undef MAKE_ENTRY
Guido van Rossumd8faa362007-04-27 19:54:29 +00004651#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004652 free(sp);
4653 return d;
4654}
4655
4656
4657static PyObject*
4658DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4659{
4660 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004661 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004662
4663 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4664 return NULL;
4665 CHECK_ENV_NOT_CLOSED(self);
4666
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004667 if (self->moduleFlags.getReturnsNone)
4668 ++oldValue;
4669 if (self->moduleFlags.cursorSetReturnsNone)
4670 ++oldValue;
4671 self->moduleFlags.getReturnsNone = (flags >= 1);
4672 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004673 return PyInt_FromLong(oldValue);
4674}
4675
4676
4677/* --------------------------------------------------------------------- */
4678/* DBTxn methods */
4679
4680
4681static PyObject*
4682DBTxn_commit(DBTxnObject* self, PyObject* args)
4683{
4684 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004685 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004686
4687 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4688 return NULL;
4689
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004690 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004691 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4692 "after txn_commit or txn_abort");
4693 PyErr_SetObject(DBError, t);
4694 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004695 return NULL;
4696 }
4697 txn = self->txn;
4698 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004699 MYDB_BEGIN_ALLOW_THREADS;
4700#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004701 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004702#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004703 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004704#endif
4705 MYDB_END_ALLOW_THREADS;
4706 RETURN_IF_ERR();
4707 RETURN_NONE();
4708}
4709
4710static PyObject*
4711DBTxn_prepare(DBTxnObject* self, PyObject* args)
4712{
4713#if (DBVER >= 33)
4714 int err;
4715 char* gid=NULL;
4716 int gid_size=0;
4717
Gregory P. Smith361ed152007-08-23 07:32:27 +00004718 if (!PyArg_ParseTuple(args, "y#:prepare", &gid, &gid_size))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004719 return NULL;
4720
4721 if (gid_size != DB_XIDDATASIZE) {
4722 PyErr_SetString(PyExc_TypeError,
4723 "gid must be DB_XIDDATASIZE bytes long");
4724 return NULL;
4725 }
4726
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004727 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004728 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4729 "after txn_commit or txn_abort");
4730 PyErr_SetObject(DBError, t);
4731 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004732 return NULL;
4733 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004734 MYDB_BEGIN_ALLOW_THREADS;
4735#if (DBVER >= 40)
4736 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4737#else
4738 err = txn_prepare(self->txn, (u_int8_t*)gid);
4739#endif
4740 MYDB_END_ALLOW_THREADS;
4741 RETURN_IF_ERR();
4742 RETURN_NONE();
4743#else
4744 int err;
4745
4746 if (!PyArg_ParseTuple(args, ":prepare"))
4747 return NULL;
4748
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004749 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004750 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4751 "after txn_commit or txn_abort");
4752 PyErr_SetObject(DBError, t);
4753 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004754 return NULL;
4755 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004756 MYDB_BEGIN_ALLOW_THREADS;
4757 err = txn_prepare(self->txn);
4758 MYDB_END_ALLOW_THREADS;
4759 RETURN_IF_ERR();
4760 RETURN_NONE();
4761#endif
4762}
4763
4764
4765static PyObject*
4766DBTxn_abort(DBTxnObject* self, PyObject* args)
4767{
4768 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004769 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004770
4771 if (!PyArg_ParseTuple(args, ":abort"))
4772 return NULL;
4773
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004774 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004775 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4776 "after txn_commit or txn_abort");
4777 PyErr_SetObject(DBError, t);
4778 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004779 return NULL;
4780 }
4781 txn = self->txn;
4782 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004783 MYDB_BEGIN_ALLOW_THREADS;
4784#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004785 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004786#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004787 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004788#endif
4789 MYDB_END_ALLOW_THREADS;
4790 RETURN_IF_ERR();
4791 RETURN_NONE();
4792}
4793
4794
4795static PyObject*
4796DBTxn_id(DBTxnObject* self, PyObject* args)
4797{
4798 int id;
4799
4800 if (!PyArg_ParseTuple(args, ":id"))
4801 return NULL;
4802
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004803 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004804 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4805 "after txn_commit or txn_abort");
4806 PyErr_SetObject(DBError, t);
4807 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004808 return NULL;
4809 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004810 MYDB_BEGIN_ALLOW_THREADS;
4811#if (DBVER >= 40)
4812 id = self->txn->id(self->txn);
4813#else
4814 id = txn_id(self->txn);
4815#endif
4816 MYDB_END_ALLOW_THREADS;
4817 return PyInt_FromLong(id);
4818}
4819
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004820#if (DBVER >= 43)
4821/* --------------------------------------------------------------------- */
4822/* DBSequence methods */
4823
4824
4825static PyObject*
4826DBSequence_close(DBSequenceObject* self, PyObject* args)
4827{
4828 int err, flags=0;
4829 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4830 return NULL;
4831 CHECK_SEQUENCE_NOT_CLOSED(self)
4832
4833 MYDB_BEGIN_ALLOW_THREADS
4834 err = self->sequence->close(self->sequence, flags);
4835 self->sequence = NULL;
4836 MYDB_END_ALLOW_THREADS
4837
4838 RETURN_IF_ERR();
4839
4840 RETURN_NONE();
4841}
4842
4843static PyObject*
4844DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4845{
4846 int err, flags = 0;
4847 int delta = 1;
4848 db_seq_t value;
4849 PyObject *txnobj = NULL;
4850 DB_TXN *txn = NULL;
4851 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4852 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4853 return NULL;
4854 CHECK_SEQUENCE_NOT_CLOSED(self)
4855
4856 if (!checkTxnObj(txnobj, &txn))
4857 return NULL;
4858
4859 MYDB_BEGIN_ALLOW_THREADS
4860 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4861 MYDB_END_ALLOW_THREADS
4862
4863 RETURN_IF_ERR();
4864 return PyLong_FromLongLong(value);
4865
4866}
4867
4868static PyObject*
4869DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4870{
4871 if (!PyArg_ParseTuple(args,":get_dbp"))
4872 return NULL;
4873 CHECK_SEQUENCE_NOT_CLOSED(self)
4874 Py_INCREF(self->mydb);
4875 return (PyObject* )self->mydb;
4876}
4877
4878static PyObject*
4879DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4880{
4881 int err;
4882 DBT key;
Guido van Rossum8ce8a782007-11-01 19:42:39 +00004883 PyObject *retval = NULL;
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004884 key.flags = DB_DBT_MALLOC;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004885 CHECK_SEQUENCE_NOT_CLOSED(self)
4886 MYDB_BEGIN_ALLOW_THREADS
4887 err = self->sequence->get_key(self->sequence, &key);
4888 MYDB_END_ALLOW_THREADS
4889
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004890 if (!err)
4891 retval = PyBytes_FromStringAndSize(key.data, key.size);
4892
4893 free_dbt(&key);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004894 RETURN_IF_ERR();
4895
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004896 return retval;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004897}
4898
4899static PyObject*
4900DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4901{
4902 int err;
4903 db_seq_t value;
4904 if (!PyArg_ParseTuple(args,"L:init_value", &value))
4905 return NULL;
4906 CHECK_SEQUENCE_NOT_CLOSED(self)
4907
4908 MYDB_BEGIN_ALLOW_THREADS
4909 err = self->sequence->initial_value(self->sequence, value);
4910 MYDB_END_ALLOW_THREADS
4911
4912 RETURN_IF_ERR();
4913
4914 RETURN_NONE();
4915}
4916
4917static PyObject*
4918DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4919{
4920 int err, flags = 0;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004921 PyObject *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00004922 Py_buffer *key_buf_view = NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004923 PyObject *txnobj = NULL;
4924 DB_TXN *txn = NULL;
4925 DBT key;
4926
4927 static char* kwnames[] = {"key", "txn", "flags", NULL };
4928 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
4929 return NULL;
4930
4931 if (!checkTxnObj(txnobj, &txn))
4932 return NULL;
4933
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004934 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004935 return NULL;
4936
4937 MYDB_BEGIN_ALLOW_THREADS
4938 err = self->sequence->open(self->sequence, txn, &key, flags);
4939 MYDB_END_ALLOW_THREADS
4940
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004941 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004942 RETURN_IF_ERR();
4943
4944 RETURN_NONE();
4945}
4946
4947static PyObject*
4948DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4949{
4950 int err, flags = 0;
4951 PyObject *txnobj = NULL;
4952 DB_TXN *txn = NULL;
4953
4954 static char* kwnames[] = {"txn", "flags", NULL };
4955 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
4956 return NULL;
4957
4958 if (!checkTxnObj(txnobj, &txn))
4959 return NULL;
4960
4961 CHECK_SEQUENCE_NOT_CLOSED(self)
4962
4963 MYDB_BEGIN_ALLOW_THREADS
4964 err = self->sequence->remove(self->sequence, txn, flags);
4965 MYDB_END_ALLOW_THREADS
4966
4967 RETURN_IF_ERR();
4968 RETURN_NONE();
4969}
4970
4971static PyObject*
4972DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4973{
4974 int err, size;
4975 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
4976 return NULL;
4977 CHECK_SEQUENCE_NOT_CLOSED(self)
4978
4979 MYDB_BEGIN_ALLOW_THREADS
4980 err = self->sequence->set_cachesize(self->sequence, size);
4981 MYDB_END_ALLOW_THREADS
4982
4983 RETURN_IF_ERR();
4984 RETURN_NONE();
4985}
4986
4987static PyObject*
4988DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4989{
4990 int err, size;
4991 if (!PyArg_ParseTuple(args,":get_cachesize"))
4992 return NULL;
4993 CHECK_SEQUENCE_NOT_CLOSED(self)
4994
4995 MYDB_BEGIN_ALLOW_THREADS
4996 err = self->sequence->get_cachesize(self->sequence, &size);
4997 MYDB_END_ALLOW_THREADS
4998
4999 RETURN_IF_ERR();
5000 return PyInt_FromLong(size);
5001}
5002
5003static PyObject*
5004DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5005{
5006 int err, flags = 0;
5007 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
5008 return NULL;
5009 CHECK_SEQUENCE_NOT_CLOSED(self)
5010
5011 MYDB_BEGIN_ALLOW_THREADS
5012 err = self->sequence->set_flags(self->sequence, flags);
5013 MYDB_END_ALLOW_THREADS
5014
5015 RETURN_IF_ERR();
5016 RETURN_NONE();
5017
5018}
5019
5020static PyObject*
5021DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5022{
5023 unsigned int flags;
5024 int err;
5025 if (!PyArg_ParseTuple(args,":get_flags"))
5026 return NULL;
5027 CHECK_SEQUENCE_NOT_CLOSED(self)
5028
5029 MYDB_BEGIN_ALLOW_THREADS
5030 err = self->sequence->get_flags(self->sequence, &flags);
5031 MYDB_END_ALLOW_THREADS
5032
5033 RETURN_IF_ERR();
5034 return PyInt_FromLong((int)flags);
5035}
5036
5037static PyObject*
5038DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5039{
5040 int err;
5041 db_seq_t min, max;
5042 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
5043 return NULL;
5044 CHECK_SEQUENCE_NOT_CLOSED(self)
5045
5046 MYDB_BEGIN_ALLOW_THREADS
5047 err = self->sequence->set_range(self->sequence, min, max);
5048 MYDB_END_ALLOW_THREADS
5049
5050 RETURN_IF_ERR();
5051 RETURN_NONE();
5052}
5053
5054static PyObject*
5055DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5056{
5057 int err;
5058 db_seq_t min, max;
5059 if (!PyArg_ParseTuple(args,":get_range"))
5060 return NULL;
5061 CHECK_SEQUENCE_NOT_CLOSED(self)
5062
5063 MYDB_BEGIN_ALLOW_THREADS
5064 err = self->sequence->get_range(self->sequence, &min, &max);
5065 MYDB_END_ALLOW_THREADS
5066
5067 RETURN_IF_ERR();
5068 return Py_BuildValue("(LL)", min, max);
5069}
5070
5071static PyObject*
5072DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5073{
5074 int err, flags = 0;
5075 DB_SEQUENCE_STAT* sp = NULL;
5076 PyObject* dict_stat;
5077 static char* kwnames[] = {"flags", NULL };
5078 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5079 return NULL;
5080 CHECK_SEQUENCE_NOT_CLOSED(self);
5081
5082 MYDB_BEGIN_ALLOW_THREADS;
5083 err = self->sequence->stat(self->sequence, &sp, flags);
5084 MYDB_END_ALLOW_THREADS;
5085 RETURN_IF_ERR();
5086
5087 if ((dict_stat = PyDict_New()) == NULL) {
5088 free(sp);
5089 return NULL;
5090 }
5091
5092
5093#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5094#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5095
5096 MAKE_INT_ENTRY(wait);
5097 MAKE_INT_ENTRY(nowait);
5098 MAKE_LONG_LONG_ENTRY(current);
5099 MAKE_LONG_LONG_ENTRY(value);
5100 MAKE_LONG_LONG_ENTRY(last_value);
5101 MAKE_LONG_LONG_ENTRY(min);
5102 MAKE_LONG_LONG_ENTRY(max);
5103 MAKE_INT_ENTRY(cache_size);
5104 MAKE_INT_ENTRY(flags);
5105
5106#undef MAKE_INT_ENTRY
5107#undef MAKE_LONG_LONG_ENTRY
5108
5109 free(sp);
5110 return dict_stat;
5111}
5112#endif
5113
5114
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005115/* --------------------------------------------------------------------- */
5116/* Method definition tables and type objects */
5117
5118static PyMethodDef DB_methods[] = {
5119 {"append", (PyCFunction)DB_append, METH_VARARGS},
5120#if (DBVER >= 33)
5121 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5122#endif
5123 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005124 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5125 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005126 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5127 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5128 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5129 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005130#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005131 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005132#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005133 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5134 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5135 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5136 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5137 {"join", (PyCFunction)DB_join, METH_VARARGS},
5138 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5139 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5140 {"items", (PyCFunction)DB_items, METH_VARARGS},
5141 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5142 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5143 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5144 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5145 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5146 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005147#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005148 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005149#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005150 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005151#if (DBVER >= 41)
5152 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5153#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005154 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5155 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5156 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5157 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5158 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5159 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5160 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5161 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5162 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005163 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005164 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005165 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5166#if (DBVER >= 33)
5167 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5168#endif
5169 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5170 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5171 {"values", (PyCFunction)DB_values, METH_VARARGS},
5172 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5173 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5174 {NULL, NULL} /* sentinel */
5175};
5176
5177
5178static PyMappingMethods DB_mapping = {
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005179 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005180 (binaryfunc)DB_subscript, /*mp_subscript*/
5181 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5182};
5183
5184
5185static PyMethodDef DBCursor_methods[] = {
5186 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5187 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5188 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5189 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5190 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5191 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5192 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005193#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005194 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005195#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005196 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5197 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5198 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5199 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5200 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5201 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5202 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5203 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005204 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005205 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005206 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5207 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5208 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5209 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5210 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5211 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5212 {NULL, NULL} /* sentinel */
5213};
5214
5215
5216static PyMethodDef DBEnv_methods[] = {
5217 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5218 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5219 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005220#if (DBVER >= 41)
5221 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5222 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5223 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5224#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005225#if (DBVER >= 40)
5226 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5227#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005228 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005229 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5230 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005231 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005232 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5233 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5234 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005235#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005236 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005237#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005238 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005239#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005240 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005241#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005242 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5243 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5244 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005245 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5246 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5247 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5248 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5249 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5250 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005251 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005252 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5253 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5254 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5255 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5256 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5257 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005258#if (DBVER >= 40)
5259 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5260#endif
5261#if (DBVER >= 44)
5262 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5263#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005264 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5265 {NULL, NULL} /* sentinel */
5266};
5267
5268
5269static PyMethodDef DBTxn_methods[] = {
5270 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5271 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5272 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5273 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5274 {NULL, NULL} /* sentinel */
5275};
5276
5277
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005278#if (DBVER >= 43)
5279static PyMethodDef DBSequence_methods[] = {
5280 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5281 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5282 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5283 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5284 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5285 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5286 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5287 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5288 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5289 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5290 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5291 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5292 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5293 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5294 {NULL, NULL} /* sentinel */
5295};
5296#endif
5297
5298
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005299static PyObject*
5300DB_getattr(DBObject* self, char *name)
5301{
5302 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5303}
5304
5305
5306static PyObject*
5307DBEnv_getattr(DBEnvObject* self, char *name)
5308{
5309 if (!strcmp(name, "db_home")) {
5310 CHECK_ENV_NOT_CLOSED(self);
5311 if (self->db_env->db_home == NULL) {
5312 RETURN_NONE();
5313 }
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005314 return PyUnicode_FromString(self->db_env->db_home);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005315 }
5316
5317 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5318}
5319
5320
5321static PyObject*
5322DBCursor_getattr(DBCursorObject* self, char *name)
5323{
5324 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5325}
5326
5327static PyObject*
5328DBTxn_getattr(DBTxnObject* self, char *name)
5329{
5330 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5331}
5332
5333static PyObject*
5334DBLock_getattr(DBLockObject* self, char *name)
5335{
5336 return NULL;
5337}
5338
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005339#if (DBVER >= 43)
5340static PyObject*
5341DBSequence_getattr(DBSequenceObject* self, char *name)
5342{
5343 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5344}
5345#endif
5346
Neal Norwitz227b5332006-03-22 09:28:35 +00005347static PyTypeObject DB_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005348 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005349 "DB", /*tp_name*/
5350 sizeof(DBObject), /*tp_basicsize*/
5351 0, /*tp_itemsize*/
5352 /* methods */
5353 (destructor)DB_dealloc, /*tp_dealloc*/
5354 0, /*tp_print*/
5355 (getattrfunc)DB_getattr, /*tp_getattr*/
5356 0, /*tp_setattr*/
5357 0, /*tp_compare*/
5358 0, /*tp_repr*/
5359 0, /*tp_as_number*/
5360 0, /*tp_as_sequence*/
5361 &DB_mapping,/*tp_as_mapping*/
5362 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005363 0, /* tp_call */
5364 0, /* tp_str */
5365 0, /* tp_getattro */
5366 0, /* tp_setattro */
5367 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005368 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005369 0, /* tp_doc */
5370 0, /* tp_traverse */
5371 0, /* tp_clear */
5372 0, /* tp_richcompare */
5373 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005374};
5375
5376
Neal Norwitz227b5332006-03-22 09:28:35 +00005377static PyTypeObject DBCursor_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005378 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005379 "DBCursor", /*tp_name*/
5380 sizeof(DBCursorObject), /*tp_basicsize*/
5381 0, /*tp_itemsize*/
5382 /* methods */
5383 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5384 0, /*tp_print*/
5385 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5386 0, /*tp_setattr*/
5387 0, /*tp_compare*/
5388 0, /*tp_repr*/
5389 0, /*tp_as_number*/
5390 0, /*tp_as_sequence*/
5391 0, /*tp_as_mapping*/
5392 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005393 0, /* tp_call */
5394 0, /* tp_str */
5395 0, /* tp_getattro */
5396 0, /* tp_setattro */
5397 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005398 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smitha703a212003-11-03 01:04:41 +00005399 0, /* tp_doc */
5400 0, /* tp_traverse */
5401 0, /* tp_clear */
5402 0, /* tp_richcompare */
5403 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005404};
5405
5406
Neal Norwitz227b5332006-03-22 09:28:35 +00005407static PyTypeObject DBEnv_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005408 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005409 "DBEnv", /*tp_name*/
5410 sizeof(DBEnvObject), /*tp_basicsize*/
5411 0, /*tp_itemsize*/
5412 /* methods */
5413 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5414 0, /*tp_print*/
5415 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5416 0, /*tp_setattr*/
5417 0, /*tp_compare*/
5418 0, /*tp_repr*/
5419 0, /*tp_as_number*/
5420 0, /*tp_as_sequence*/
5421 0, /*tp_as_mapping*/
5422 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005423 0, /* tp_call */
5424 0, /* tp_str */
5425 0, /* tp_getattro */
5426 0, /* tp_setattro */
5427 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005428 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005429 0, /* tp_doc */
5430 0, /* tp_traverse */
5431 0, /* tp_clear */
5432 0, /* tp_richcompare */
5433 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005434};
5435
Neal Norwitz227b5332006-03-22 09:28:35 +00005436static PyTypeObject DBTxn_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005437 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005438 "DBTxn", /*tp_name*/
5439 sizeof(DBTxnObject), /*tp_basicsize*/
5440 0, /*tp_itemsize*/
5441 /* methods */
5442 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5443 0, /*tp_print*/
5444 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5445 0, /*tp_setattr*/
5446 0, /*tp_compare*/
5447 0, /*tp_repr*/
5448 0, /*tp_as_number*/
5449 0, /*tp_as_sequence*/
5450 0, /*tp_as_mapping*/
5451 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005452 0, /* tp_call */
5453 0, /* tp_str */
5454 0, /* tp_getattro */
5455 0, /* tp_setattro */
5456 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005457 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005458 0, /* tp_doc */
5459 0, /* tp_traverse */
5460 0, /* tp_clear */
5461 0, /* tp_richcompare */
5462 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005463};
5464
5465
Neal Norwitz227b5332006-03-22 09:28:35 +00005466static PyTypeObject DBLock_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005467 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005468 "DBLock", /*tp_name*/
5469 sizeof(DBLockObject), /*tp_basicsize*/
5470 0, /*tp_itemsize*/
5471 /* methods */
5472 (destructor)DBLock_dealloc, /*tp_dealloc*/
5473 0, /*tp_print*/
5474 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5475 0, /*tp_setattr*/
5476 0, /*tp_compare*/
5477 0, /*tp_repr*/
5478 0, /*tp_as_number*/
5479 0, /*tp_as_sequence*/
5480 0, /*tp_as_mapping*/
5481 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005482 0, /* tp_call */
5483 0, /* tp_str */
5484 0, /* tp_getattro */
5485 0, /* tp_setattro */
5486 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005487 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005488 0, /* tp_doc */
5489 0, /* tp_traverse */
5490 0, /* tp_clear */
5491 0, /* tp_richcompare */
5492 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005493};
5494
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005495#if (DBVER >= 43)
5496static PyTypeObject DBSequence_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005497 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005498 "DBSequence", /*tp_name*/
5499 sizeof(DBSequenceObject), /*tp_basicsize*/
5500 0, /*tp_itemsize*/
5501 /* methods */
5502 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5503 0, /*tp_print*/
5504 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5505 0, /*tp_setattr*/
5506 0, /*tp_compare*/
5507 0, /*tp_repr*/
5508 0, /*tp_as_number*/
5509 0, /*tp_as_sequence*/
5510 0, /*tp_as_mapping*/
5511 0, /*tp_hash*/
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005512 0, /* tp_call */
5513 0, /* tp_str */
5514 0, /* tp_getattro */
5515 0, /* tp_setattro */
5516 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005517 Py_TPFLAGS_DEFAULT, /* tp_flags */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005518 0, /* tp_doc */
5519 0, /* tp_traverse */
5520 0, /* tp_clear */
5521 0, /* tp_richcompare */
5522 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005523};
5524#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005525
5526/* --------------------------------------------------------------------- */
5527/* Module-level functions */
5528
5529static PyObject*
5530DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5531{
5532 PyObject* dbenvobj = NULL;
5533 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005534 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005535
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005536 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5537 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005538 return NULL;
5539 if (dbenvobj == Py_None)
5540 dbenvobj = NULL;
5541 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5542 makeTypeError("DBEnv", dbenvobj);
5543 return NULL;
5544 }
5545
5546 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5547}
5548
5549
5550static PyObject*
5551DBEnv_construct(PyObject* self, PyObject* args)
5552{
5553 int flags = 0;
5554 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5555 return (PyObject* )newDBEnvObject(flags);
5556}
5557
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005558#if (DBVER >= 43)
5559static PyObject*
5560DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5561{
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005562 PyObject* dbobj;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005563 int flags = 0;
5564 static char* kwnames[] = { "db", "flags", NULL};
5565
5566 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5567 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005568 if (!DBObject_Check(dbobj)) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005569 makeTypeError("DB", dbobj);
5570 return NULL;
5571 }
5572 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5573}
5574#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005575
5576static char bsddb_version_doc[] =
5577"Returns a tuple of major, minor, and patch release numbers of the\n\
5578underlying DB library.";
5579
5580static PyObject*
5581bsddb_version(PyObject* self, PyObject* args)
5582{
5583 int major, minor, patch;
5584
5585 if (!PyArg_ParseTuple(args, ":version"))
5586 return NULL;
5587 db_version(&major, &minor, &patch);
5588 return Py_BuildValue("(iii)", major, minor, patch);
5589}
5590
5591
5592/* List of functions defined in the module */
5593
5594static PyMethodDef bsddb_methods[] = {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005595 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5596 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5597#if (DBVER >= 43)
5598 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5599#endif
5600 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005601 {NULL, NULL} /* sentinel */
5602};
5603
Guido van Rossum8ce8a782007-11-01 19:42:39 +00005604/* API structure */
5605static BSDDB_api bsddb_api;
5606
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005607
5608/* --------------------------------------------------------------------- */
5609/* Module initialization */
5610
5611
5612/* Convenience routine to export an integer value.
5613 * Errors are silently ignored, for better or for worse...
5614 */
5615#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5616
Gregory P. Smith41631e82003-09-21 00:08:14 +00005617#define MODULE_NAME_MAX_LEN 11
5618static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005619
Neal Norwitzf6657e62006-12-28 04:47:50 +00005620PyMODINIT_FUNC init_bsddb(void)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005621{
5622 PyObject* m;
5623 PyObject* d;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005624 PyObject* pybsddb_version_s = PyUnicode_FromString(PY_BSDDB_VERSION);
5625 PyObject* db_version_s = PyUnicode_FromString(DB_VERSION_STRING);
5626 PyObject* svnid_s = PyUnicode_FromString(svn_id);
Guido van Rossum8ce8a782007-11-01 19:42:39 +00005627 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005628
5629 /* Initialize the type of the new type objects here; doing it here
5630 is required for portability to Windows without requiring C++. */
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005631 Py_Type(&DB_Type) = &PyType_Type;
5632 Py_Type(&DBCursor_Type) = &PyType_Type;
5633 Py_Type(&DBEnv_Type) = &PyType_Type;
5634 Py_Type(&DBTxn_Type) = &PyType_Type;
5635 Py_Type(&DBLock_Type) = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005636#if (DBVER >= 43)
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005637 Py_Type(&DBSequence_Type) = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005638#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005639
5640
Mark Hammonda69d4092003-04-22 23:13:27 +00005641#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005642 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005643 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005644#endif
5645
5646 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005647 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005648 if (m == NULL)
5649 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005650
5651 /* Add some symbolic constants to the module */
5652 d = PyModule_GetDict(m);
5653 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005654 PyDict_SetItemString(d, "cvsid", svnid_s);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005655 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5656 Py_DECREF(pybsddb_version_s);
5657 pybsddb_version_s = NULL;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005658 Py_DECREF(svnid_s);
5659 svnid_s = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005660 Py_DECREF(db_version_s);
5661 db_version_s = NULL;
5662
5663 ADD_INT(d, DB_VERSION_MAJOR);
5664 ADD_INT(d, DB_VERSION_MINOR);
5665 ADD_INT(d, DB_VERSION_PATCH);
5666
5667 ADD_INT(d, DB_MAX_PAGES);
5668 ADD_INT(d, DB_MAX_RECORDS);
5669
Gregory P. Smith41631e82003-09-21 00:08:14 +00005670#if (DBVER >= 42)
5671 ADD_INT(d, DB_RPCCLIENT);
5672#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005673 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005674 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5675 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5676#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005677 ADD_INT(d, DB_XA_CREATE);
5678
5679 ADD_INT(d, DB_CREATE);
5680 ADD_INT(d, DB_NOMMAP);
5681 ADD_INT(d, DB_THREAD);
5682
5683 ADD_INT(d, DB_FORCE);
5684 ADD_INT(d, DB_INIT_CDB);
5685 ADD_INT(d, DB_INIT_LOCK);
5686 ADD_INT(d, DB_INIT_LOG);
5687 ADD_INT(d, DB_INIT_MPOOL);
5688 ADD_INT(d, DB_INIT_TXN);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005689 ADD_INT(d, DB_JOINENV);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005690
5691 ADD_INT(d, DB_RECOVER);
5692 ADD_INT(d, DB_RECOVER_FATAL);
5693 ADD_INT(d, DB_TXN_NOSYNC);
5694 ADD_INT(d, DB_USE_ENVIRON);
5695 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5696
5697 ADD_INT(d, DB_LOCKDOWN);
5698 ADD_INT(d, DB_PRIVATE);
5699 ADD_INT(d, DB_SYSTEM_MEM);
5700
5701 ADD_INT(d, DB_TXN_SYNC);
5702 ADD_INT(d, DB_TXN_NOWAIT);
5703
5704 ADD_INT(d, DB_EXCL);
5705 ADD_INT(d, DB_FCNTL_LOCKING);
5706 ADD_INT(d, DB_ODDFILESIZE);
5707 ADD_INT(d, DB_RDWRMASTER);
5708 ADD_INT(d, DB_RDONLY);
5709 ADD_INT(d, DB_TRUNCATE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005710 ADD_INT(d, DB_EXTENT);
5711 ADD_INT(d, DB_CDB_ALLDB);
5712 ADD_INT(d, DB_VERIFY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005713 ADD_INT(d, DB_UPGRADE);
5714
5715 ADD_INT(d, DB_AGGRESSIVE);
5716 ADD_INT(d, DB_NOORDERCHK);
5717 ADD_INT(d, DB_ORDERCHKONLY);
5718 ADD_INT(d, DB_PR_PAGE);
5719#if ! (DBVER >= 33)
5720 ADD_INT(d, DB_VRFY_FLAGMASK);
5721 ADD_INT(d, DB_PR_HEADERS);
5722#endif
5723 ADD_INT(d, DB_PR_RECOVERYTEST);
5724 ADD_INT(d, DB_SALVAGE);
5725
5726 ADD_INT(d, DB_LOCK_NORUN);
5727 ADD_INT(d, DB_LOCK_DEFAULT);
5728 ADD_INT(d, DB_LOCK_OLDEST);
5729 ADD_INT(d, DB_LOCK_RANDOM);
5730 ADD_INT(d, DB_LOCK_YOUNGEST);
5731#if (DBVER >= 33)
5732 ADD_INT(d, DB_LOCK_MAXLOCKS);
5733 ADD_INT(d, DB_LOCK_MINLOCKS);
5734 ADD_INT(d, DB_LOCK_MINWRITE);
5735#endif
5736
5737
5738#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005739 /* docs say to use zero instead */
5740 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005741#else
5742 ADD_INT(d, DB_LOCK_CONFLICT);
5743#endif
5744
5745 ADD_INT(d, DB_LOCK_DUMP);
5746 ADD_INT(d, DB_LOCK_GET);
5747 ADD_INT(d, DB_LOCK_INHERIT);
5748 ADD_INT(d, DB_LOCK_PUT);
5749 ADD_INT(d, DB_LOCK_PUT_ALL);
5750 ADD_INT(d, DB_LOCK_PUT_OBJ);
5751
5752 ADD_INT(d, DB_LOCK_NG);
5753 ADD_INT(d, DB_LOCK_READ);
5754 ADD_INT(d, DB_LOCK_WRITE);
5755 ADD_INT(d, DB_LOCK_NOWAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005756 ADD_INT(d, DB_LOCK_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005757 ADD_INT(d, DB_LOCK_IWRITE);
5758 ADD_INT(d, DB_LOCK_IREAD);
5759 ADD_INT(d, DB_LOCK_IWR);
5760#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005761#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005762 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005763#else
5764 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5765#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005766 ADD_INT(d, DB_LOCK_WWRITE);
5767#endif
5768
5769 ADD_INT(d, DB_LOCK_RECORD);
5770 ADD_INT(d, DB_LOCK_UPGRADE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005771 ADD_INT(d, DB_LOCK_SWITCH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005772#if (DBVER >= 33)
5773 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5774#endif
5775
5776 ADD_INT(d, DB_LOCK_NOWAIT);
5777 ADD_INT(d, DB_LOCK_RECORD);
5778 ADD_INT(d, DB_LOCK_UPGRADE);
5779
5780#if (DBVER >= 33)
5781 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005782#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005783 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005784#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005785 ADD_INT(d, DB_LSTAT_FREE);
5786 ADD_INT(d, DB_LSTAT_HELD);
5787#if (DBVER == 33)
5788 ADD_INT(d, DB_LSTAT_NOGRANT);
5789#endif
5790 ADD_INT(d, DB_LSTAT_PENDING);
5791 ADD_INT(d, DB_LSTAT_WAITING);
5792#endif
5793
5794 ADD_INT(d, DB_ARCH_ABS);
5795 ADD_INT(d, DB_ARCH_DATA);
5796 ADD_INT(d, DB_ARCH_LOG);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005797#if (DBVER >= 42)
5798 ADD_INT(d, DB_ARCH_REMOVE);
5799#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005800
5801 ADD_INT(d, DB_BTREE);
5802 ADD_INT(d, DB_HASH);
5803 ADD_INT(d, DB_RECNO);
5804 ADD_INT(d, DB_QUEUE);
5805 ADD_INT(d, DB_UNKNOWN);
5806
5807 ADD_INT(d, DB_DUP);
5808 ADD_INT(d, DB_DUPSORT);
5809 ADD_INT(d, DB_RECNUM);
5810 ADD_INT(d, DB_RENUMBER);
5811 ADD_INT(d, DB_REVSPLITOFF);
5812 ADD_INT(d, DB_SNAPSHOT);
5813
5814 ADD_INT(d, DB_JOIN_NOSORT);
5815
5816 ADD_INT(d, DB_AFTER);
5817 ADD_INT(d, DB_APPEND);
5818 ADD_INT(d, DB_BEFORE);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005819#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005820 ADD_INT(d, DB_CACHED_COUNTS);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005821#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005822#if (DBVER >= 41)
5823 _addIntToDict(d, "DB_CHECKPOINT", 0);
5824#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005825 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005826 ADD_INT(d, DB_CURLSN);
5827#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005828#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005829 ADD_INT(d, DB_COMMIT);
5830#endif
5831 ADD_INT(d, DB_CONSUME);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005832 ADD_INT(d, DB_CONSUME_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005833 ADD_INT(d, DB_CURRENT);
5834#if (DBVER >= 33)
5835 ADD_INT(d, DB_FAST_STAT);
5836#endif
5837 ADD_INT(d, DB_FIRST);
5838 ADD_INT(d, DB_FLUSH);
5839 ADD_INT(d, DB_GET_BOTH);
5840 ADD_INT(d, DB_GET_RECNO);
5841 ADD_INT(d, DB_JOIN_ITEM);
5842 ADD_INT(d, DB_KEYFIRST);
5843 ADD_INT(d, DB_KEYLAST);
5844 ADD_INT(d, DB_LAST);
5845 ADD_INT(d, DB_NEXT);
5846 ADD_INT(d, DB_NEXT_DUP);
5847 ADD_INT(d, DB_NEXT_NODUP);
5848 ADD_INT(d, DB_NODUPDATA);
5849 ADD_INT(d, DB_NOOVERWRITE);
5850 ADD_INT(d, DB_NOSYNC);
5851 ADD_INT(d, DB_POSITION);
5852 ADD_INT(d, DB_PREV);
5853 ADD_INT(d, DB_PREV_NODUP);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005854#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005855 ADD_INT(d, DB_RECORDCOUNT);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005856#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005857 ADD_INT(d, DB_SET);
5858 ADD_INT(d, DB_SET_RANGE);
5859 ADD_INT(d, DB_SET_RECNO);
5860 ADD_INT(d, DB_WRITECURSOR);
5861
5862 ADD_INT(d, DB_OPFLAGS_MASK);
5863 ADD_INT(d, DB_RMW);
5864#if (DBVER >= 33)
5865 ADD_INT(d, DB_DIRTY_READ);
5866 ADD_INT(d, DB_MULTIPLE);
5867 ADD_INT(d, DB_MULTIPLE_KEY);
5868#endif
5869
Gregory P. Smith29602d22006-01-24 09:46:48 +00005870#if (DBVER >= 44)
5871 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5872 ADD_INT(d, DB_READ_COMMITTED);
5873#endif
5874
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005875#if (DBVER >= 33)
5876 ADD_INT(d, DB_DONOTINDEX);
Gregory P. Smith361ed152007-08-23 07:32:27 +00005877 ADD_INT(d, DB_XIDDATASIZE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005878#endif
5879
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005880#if (DBVER >= 41)
5881 _addIntToDict(d, "DB_INCOMPLETE", 0);
5882#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005883 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005884#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005885 ADD_INT(d, DB_KEYEMPTY);
5886 ADD_INT(d, DB_KEYEXIST);
5887 ADD_INT(d, DB_LOCK_DEADLOCK);
5888 ADD_INT(d, DB_LOCK_NOTGRANTED);
5889 ADD_INT(d, DB_NOSERVER);
5890 ADD_INT(d, DB_NOSERVER_HOME);
5891 ADD_INT(d, DB_NOSERVER_ID);
5892 ADD_INT(d, DB_NOTFOUND);
5893 ADD_INT(d, DB_OLD_VERSION);
5894 ADD_INT(d, DB_RUNRECOVERY);
5895 ADD_INT(d, DB_VERIFY_BAD);
5896#if (DBVER >= 33)
5897 ADD_INT(d, DB_PAGE_NOTFOUND);
5898 ADD_INT(d, DB_SECONDARY_BAD);
5899#endif
5900#if (DBVER >= 40)
5901 ADD_INT(d, DB_STAT_CLEAR);
5902 ADD_INT(d, DB_REGION_INIT);
5903 ADD_INT(d, DB_NOLOCKING);
5904 ADD_INT(d, DB_YIELDCPU);
5905 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5906 ADD_INT(d, DB_NOPANIC);
5907#endif
5908
Gregory P. Smith41631e82003-09-21 00:08:14 +00005909#if (DBVER >= 42)
5910 ADD_INT(d, DB_TIME_NOTGRANTED);
5911 ADD_INT(d, DB_TXN_NOT_DURABLE);
5912 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5913 ADD_INT(d, DB_LOG_AUTOREMOVE);
5914 ADD_INT(d, DB_DIRECT_LOG);
5915 ADD_INT(d, DB_DIRECT_DB);
5916 ADD_INT(d, DB_INIT_REP);
5917 ADD_INT(d, DB_ENCRYPT);
5918 ADD_INT(d, DB_CHKSUM);
5919#endif
5920
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005921#if (DBVER >= 43)
5922 ADD_INT(d, DB_LOG_INMEMORY);
5923 ADD_INT(d, DB_BUFFER_SMALL);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005924 ADD_INT(d, DB_SEQ_DEC);
5925 ADD_INT(d, DB_SEQ_INC);
5926 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005927#endif
5928
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005929#if (DBVER >= 41)
5930 ADD_INT(d, DB_ENCRYPT_AES);
5931 ADD_INT(d, DB_AUTO_COMMIT);
5932#else
5933 /* allow berkeleydb 4.1 aware apps to run on older versions */
5934 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5935#endif
5936
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005937 ADD_INT(d, EINVAL);
5938 ADD_INT(d, EACCES);
5939 ADD_INT(d, ENOSPC);
5940 ADD_INT(d, ENOMEM);
5941 ADD_INT(d, EAGAIN);
5942 ADD_INT(d, EBUSY);
5943 ADD_INT(d, EEXIST);
5944 ADD_INT(d, ENOENT);
5945 ADD_INT(d, EPERM);
5946
Barry Warsaw1baa9822003-03-31 19:51:29 +00005947#if (DBVER >= 40)
5948 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5949 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5950#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005951
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005952 /* The exception name must be correct for pickled exception *
5953 * objects to unpickle properly. */
5954#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5955#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5956#else
5957#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5958#endif
5959
5960 /* All the rest of the exceptions derive only from DBError */
5961#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5962 PyDict_SetItemString(d, #name, name)
5963
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005964 /* The base exception class is DBError */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005965 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5966 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005967
Gregory P. Smithe9477062005-06-04 06:46:59 +00005968 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5969 * from both DBError and KeyError, since the API only supports
5970 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005971 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Guido van Rossum52cc1d82007-03-18 15:41:51 +00005972 {
5973 PyObject *builtin_mod = PyImport_ImportModule("__builtin__");
5974 PyDict_SetItemString(d, "__builtins__", builtin_mod);
5975 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00005976 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5977 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005978 Py_file_input, d, d);
5979 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005980 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005981 PyDict_DelItemString(d, "KeyError");
5982
5983
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005984#if !INCOMPLETE_IS_WARNING
5985 MAKE_EX(DBIncompleteError);
5986#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005987 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005988 MAKE_EX(DBKeyEmptyError);
5989 MAKE_EX(DBKeyExistError);
5990 MAKE_EX(DBLockDeadlockError);
5991 MAKE_EX(DBLockNotGrantedError);
5992 MAKE_EX(DBOldVersionError);
5993 MAKE_EX(DBRunRecoveryError);
5994 MAKE_EX(DBVerifyBadError);
5995 MAKE_EX(DBNoServerError);
5996 MAKE_EX(DBNoServerHomeError);
5997 MAKE_EX(DBNoServerIDError);
5998#if (DBVER >= 33)
5999 MAKE_EX(DBPageNotFoundError);
6000 MAKE_EX(DBSecondaryBadError);
6001#endif
6002
6003 MAKE_EX(DBInvalidArgError);
6004 MAKE_EX(DBAccessError);
6005 MAKE_EX(DBNoSpaceError);
6006 MAKE_EX(DBNoMemoryError);
6007 MAKE_EX(DBAgainError);
6008 MAKE_EX(DBBusyError);
6009 MAKE_EX(DBFileExistsError);
6010 MAKE_EX(DBNoSuchFileError);
6011 MAKE_EX(DBPermissionsError);
6012
6013#undef MAKE_EX
6014
Guido van Rossum8ce8a782007-11-01 19:42:39 +00006015 /* Initiliase the C API structure and add it to the module */
6016 bsddb_api.db_type = &DB_Type;
6017 bsddb_api.dbcursor_type = &DBCursor_Type;
6018 bsddb_api.dbenv_type = &DBEnv_Type;
6019 bsddb_api.dbtxn_type = &DBTxn_Type;
6020 bsddb_api.dblock_type = &DBLock_Type;
6021#if (DBVER >= 43)
6022 bsddb_api.dbsequence_type = &DBSequence_Type;
6023#endif
6024 bsddb_api.makeDBError = makeDBError;
6025
6026 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
6027 PyDict_SetItemString(d, "api", py_api);
6028 Py_DECREF(py_api);
6029
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006030 /* Check for errors */
6031 if (PyErr_Occurred()) {
6032 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006033 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006034 }
6035}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006036
6037/* allow this module to be named _pybsddb so that it can be installed
6038 * and imported on top of python >= 2.3 that includes its own older
6039 * copy of the library named _bsddb without importing the old version. */
Neal Norwitzf6657e62006-12-28 04:47:50 +00006040PyMODINIT_FUNC init_pybsddb(void)
Gregory P. Smith41631e82003-09-21 00:08:14 +00006041{
6042 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6043 init_bsddb();
6044}