summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.hgignore1
-rw-r--r--build_posix/Make.base6
-rw-r--r--build_posix/configure.ac6
-rwxr-xr-xexamples/python/ex_access.py44
-rw-r--r--lang/python/wiredtiger.i206
-rw-r--r--src/include/wiredtiger.in66
6 files changed, 291 insertions, 38 deletions
diff --git a/.hgignore b/.hgignore
index 4c2acd1f6e7..862f32c8f54 100644
--- a/.hgignore
+++ b/.hgignore
@@ -16,3 +16,4 @@
^src/server
^test/bt/(CONFIG|__rand|__wt.bdb|__wt.run|__wt.wt|db|t|vgout\..*)
/tags$
+~$
diff --git a/build_posix/Make.base b/build_posix/Make.base
index a25e63a2a10..925c9dd772c 100644
--- a/build_posix/Make.base
+++ b/build_posix/Make.base
@@ -26,7 +26,11 @@ prototype.chk: $(libwiredtiger_a_SOURCES)
@(cd ../dist && sh s_prototypes) && touch $@
if PYTHON
+if DEBUG
+PY_SETUP_DEBUG = -g
+wiredtiger_wrap_o_CFLAGS = -g
+endif
all-local: ../lang/python/_wiredtiger.so
endif
../lang/python/_wiredtiger.so: libwiredtiger.a ../lang/python/wiredtiger.i
- @(cd ../lang/python ; python setup.py build_ext -f -i)
+ @(cd ../lang/python ; python setup.py build_ext -f -i $(PY_SETUP_DEBUG))
diff --git a/build_posix/configure.ac b/build_posix/configure.ac
index ab13e625e3f..c1dc0c41324 100644
--- a/build_posix/configure.ac
+++ b/build_posix/configure.ac
@@ -32,7 +32,10 @@ if test "$GCC" = "yes"; then
#
# If we're using gcc, change the optimization to -O3, unless we're
# doing a small build, in which case we use -Os.
- if test "$db_cv_enable_smallbuild" = "yes"; then
+ if test "$db_cv_enable_debug" = "yes"; then
+ # don't touch for debugging
+ :
+ elif test "$db_cv_enable_smallbuild" = "yes"; then
CFLAGS=`echo "$CFLAGS" | sed 's/-O./-Os /g'`
else
CFLAGS=`echo "$CFLAGS" | sed 's/-O./-O3 /g'`
@@ -61,6 +64,7 @@ if test "$db_cv_enable_debug" = "yes"; then
CFLAGS=`echo "$CFLAGS" | sed 's/-g//g'`
CFLAGS="$CFLAGS -g"
fi
+AM_CONDITIONAL(DEBUG, test "$db_cv_enable_debug" = "yes")
# Python API
if test "$db_cv_enable_python" = "yes"; then
diff --git a/examples/python/ex_access.py b/examples/python/ex_access.py
new file mode 100755
index 00000000000..5fb0abdbc9e
--- /dev/null
+++ b/examples/python/ex_access.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env PYTHONPATH=../../lang/python:../../lang/python/src python
+#
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2008-2011 WiredTiger, Inc.
+# All rights reserved.
+#
+# ex_access.py
+# demonstrates how to create and access a simple table.
+#
+
+import wiredtiger
+import sys
+
+home = 'WT_TEST'
+
+try:
+ conn = wiredtiger.wiredtiger_open(home, None, 'create')
+ print('connected: ' + `conn`);
+ session = conn.open_session(None, None)
+except BaseException as e:
+ print('Error connecting to', (home + ':'), e);
+ sys.exit(1)
+
+# Note: further error checking omitted for clarity.
+
+session.create_table('access', 'key_format=S,value_format=S')
+cursor = session.open_cursor('table:access', None, None)
+
+# Insert a record.
+cursor.set_key('key1')
+cursor.set_value('value1')
+
+# TODO: remove try block when cursor.insert works
+try:
+ cursor.insert()
+except BaseException as tuple:
+ print('Error cursor insert: ', tuple);
+
+for key, value in cursor:
+ print('Got record: ' + key + ' : ' + value)
+
+conn.close(None)
+sys.exit(0)
diff --git a/lang/python/wiredtiger.i b/lang/python/wiredtiger.i
index b4723c8bca9..8e6570aa01d 100644
--- a/lang/python/wiredtiger.i
+++ b/lang/python/wiredtiger.i
@@ -1,13 +1,213 @@
%module wiredtiger
/* Set the input argument to point to a temporary variable */
-%typemap(in, numinputs=0) WT_CONNECTION ** (WT_CONNECTION *temp) {
+%typemap(in, numinputs=0) WT_CONNECTION ** (WT_CONNECTION *temp = NULL) {
$1 = &temp;
}
-/* Append connection to returned list */
+%typemap(in, numinputs=0) WT_SESSION ** (WT_SESSION *temp = NULL) {
+ $1 = &temp;
+}
+%typemap(in, numinputs=0) WT_CURSOR ** (WT_CURSOR *temp = NULL) {
+ $1 = &temp;
+}
+
+/* Set the return value to the returned connection, session, or cursor */
%typemap(argout) WT_CONNECTION ** {
- $result = SWIG_NewPointerObj(SWIG_as_voidptr($1),
+ $result = SWIG_NewPointerObj(SWIG_as_voidptr(*$1),
SWIGTYPE_p_wt_connection, 0);
}
+%typemap(argout) WT_SESSION ** {
+ $result = SWIG_NewPointerObj(SWIG_as_voidptr(*$1),
+ SWIGTYPE_p_wt_session, 0);
+}
+
+%typemap(argout) WT_CURSOR ** {
+ $result = SWIG_NewPointerObj(SWIG_as_voidptr(*$1),
+ SWIGTYPE_p_wt_cursor, 0);
+}
+
+
+/* Checking for error returns - any error is an exception.
+ * TODO: need to create a wiredtiger exception, probably language specific
+ */
+%typemap(out) int {
+ $result = SWIG_From_int((int)(result));
+ if ($1 != 0 && $1 != WT_NOTFOUND) {
+ SWIG_exception_fail(SWIG_RuntimeError, wiredtiger_strerror($1));
+ return NULL;
+ }
+}
+
+/*
+ * Extra 'self' elimination.
+ * The methods we're wrapping look like this:
+ * struct wt_xxx {
+ * int method(WT_XXX *, ...otherargs...);
+ * };
+ * as expected SWIG creates:
+ * wt_xxx.method(WT_XXX *, ...otherargs...);
+ * so we'd like to eliminate the WT_XXX * and set its value to
+ * the wt_xxx var. To make life difficult, a typemap with numinputs=0
+ * (which we want to use for WT_XXX *) seems to be emitted before
+ * all other typemaps. SWIG doc claims that adjacent args can be
+ * typemapped as a single unit, that doesn't work here, I guess these two
+ * args are apparently not considered adjacent. Furthermore,
+ * there's no way to create an extra stack variable for them
+ * to communicate.
+ *
+ * Our solution is to use argp1 (a var that will be used used by
+ * wt_xxx *) as a holder. The holder keeps the address where we want
+ * stored the computed self value. The 'in' typemap for WT_XXX * sets
+ * that, and the 'in' typemape for wt_xxx * uses it to store the
+ * value. prepare_copy_self() and copy_self() encapsulate this
+ * communication between the two typemaps.
+ */
+%{
+ static void prepare_copy_self(void ***holderp, void **myargp)
+ {
+ if (*holderp == NULL) {
+ *holderp = myargp;
+ }
+ }
+
+ static void copy_self(void **holder, void *self)
+ {
+ if (holder != NULL) {
+ *holder = self;
+ }
+ }
+%}
+
+// Can't do: $1 = self; , when this typemap is used, we don't always have
+// self?? TODO: look at this more, it would clean things up some.
+%typemap(in, numinputs=0) WT_CONNECTION *thisconnection, WT_SESSION *thissession, WT_CURSOR *thiscursor %{
+ prepare_copy_self((void ***)&argp1, (void **)&$1);
+%}
+
+// For some reason the following three cannot be combined in a single typemap
+%typemap(in) struct wt_connection *self (void *argp = 0, int res = 0, void **copy) {
+ // struct wt_connection *
+ copy = (void **)argp;
+ res = SWIG_ConvertPtr($input, &argp,$descriptor, $disown | 0);
+ if (!SWIG_IsOK(res)) {
+ SWIG_exception_fail(SWIG_ArgError(res), "in method '" "$symname" "', argument " "$argnum" " of type '" "$type" "'");
+ }
+ $1 = ($ltype)(argp);
+ copy_self(copy, $1);
+}
+
+%typemap(in) struct wt_session *self (void *argp = 0, int res = 0, void **copy) {
+ // struct wt_session *
+ copy = (void **)argp;
+ res = SWIG_ConvertPtr($input, &argp,$descriptor, $disown | 0);
+ if (!SWIG_IsOK(res)) {
+ SWIG_exception_fail(SWIG_ArgError(res), "in method '" "$symname" "', argument " "$argnum" " of type '" "$type" "'");
+ }
+ $1 = ($ltype)(argp);
+ copy_self(copy, $1);
+}
+
+%typemap(in) struct wt_cursor *self (void *argp = 0, int res = 0, void **copy) {
+ // struct wt_cursor *
+ copy = (void **)argp;
+ res = SWIG_ConvertPtr($input, &argp,$descriptor, $disown | 0);
+ if (!SWIG_IsOK(res)) {
+ SWIG_exception_fail(SWIG_ArgError(res), "in method '" "$symname" "', argument " "$argnum" " of type '" "$type" "'");
+ }
+ $1 = ($ltype)(argp);
+ copy_self(copy, $1);
+}
+
+/* WT_CURSOR customization.
+ * We want our own 'next' function for wt_cursor, so we can
+ * implement iterable. Since nobody but use will use
+ * the 'real' version, we'll remove it to avoid confusion.
+ */
+%ignore next(WT_CURSOR *);
+
+/* We create an artificial return type for next, and use the typemap to
+ * convert it to its final value (a python tuple). That consolidates
+ * the return code.
+ * TODO: no need to do this anymore?
+ */
+%{
+typedef struct IterNextValue {
+ PyObject *pyobj;
+ int ret;
+} IterNextValue;
+%}
+
+%typemap(out) IterNextValue {
+ if ($1.ret != 0) {
+ if ($1.ret == WT_NOTFOUND) {
+ PyErr_SetString(PyExc_StopIteration, "No more data for cursor");
+ }
+ else {
+ PyErr_SetString(PyExc_RuntimeError, wiredtiger_strerror($1.ret));
+ }
+ $1.pyobj = NULL;
+ }
+ $result = $1.pyobj;
+}
+
+/* Implement the iterable contract for wt_cursor */
+%extend wt_cursor {
+ struct wt_cursor *__iter__() {
+ return $self;
+ }
+
+ IterNextValue next() {
+ // TODO: handle arbitrary types, not just strings!
+ char *keyptr = 0;
+ char *valptr = 0;
+ IterNextValue result;
+ int ret;
+
+ result.pyobj = NULL;
+ ret = self->next(self);
+#if 0
+ //TODO: for testing until real insertion works
+ {
+ // fake some values to test the caller...
+ static int count = 2;
+
+ if (count-- > 0) {
+ result.pyobj = Py_BuildValue("(ss)", "foo", "bar");
+ result.ret = 0;
+ return result;
+ }
+ else {
+ ret = EIO; /* TODO!! */
+ }
+ }
+#endif
+
+ if (ret == 0) {
+ ret = self->get_key(self, &keyptr);
+ }
+ if (ret == 0) {
+ ret = self->get_value(self, &valptr);
+ }
+ if (ret == 0) {
+ result.pyobj = Py_BuildValue("(ss)", keyptr, valptr);
+ }
+ result.ret = ret;
+ return result;
+ }
+};
+
+/* TODO:
+// This typemap handles set_key, set_value.
+// Unfortunately, the only way to distinguish between these two
+// calls is to look at $symname.
+%typemap(in) (WT_CURSOR *, ...) {
+ int symlen = strlen($symname);
+ int iskey = (symname == 7);
+}
+*?
+
+/*TODO: %varargs(void *arg) wt_cursor.set_key;*/
+%varargs(char *arg) set_key;
+%varargs(char *arg) set_value;
%include "wiredtiger.h"
diff --git a/src/include/wiredtiger.in b/src/include/wiredtiger.in
index 3e37ce66667..1976c2d890b 100644
--- a/src/include/wiredtiger.in
+++ b/src/include/wiredtiger.in
@@ -181,7 +181,7 @@ struct wt_cursor {
* @param cursor the cursor handle
* @errors
*/
- int __F(get_key)(WT_CURSOR *cursor, ...);
+ int __F(get_key)(WT_CURSOR *thiscursor, ...);
/*! Get the value for the current record.
*
@@ -191,7 +191,7 @@ struct wt_cursor {
* @param cursor the cursor handle
* @errors
*/
- int __F(get_value)(WT_CURSOR *cursor, ...);
+ int __F(get_value)(WT_CURSOR *thiscursor, ...);
/*! Set the key for the next operation.
*
@@ -205,7 +205,7 @@ struct wt_cursor {
* cursor, and the next operation to access the key will fail. This
* simplifies error handling in applications.
*/
- void __F(set_key)(WT_CURSOR *cursor, ...);
+ void __F(set_key)(WT_CURSOR *thiscursor, ...);
/*! Set the data for the next operation.
*
@@ -219,7 +219,7 @@ struct wt_cursor {
* cursor, and the next operation to access the value will fail. This
* simplifies error handling in applications.
*/
- void __F(set_value)(WT_CURSOR *cursor, ...);
+ void __F(set_value)(WT_CURSOR *thiscursor, ...);
/*! @} */
/*! @name Cursor positioning
@@ -233,7 +233,7 @@ struct wt_cursor {
* @param cursor the cursor handle
* @errors
*/
- int __F(first)(WT_CURSOR *cursor);
+ int __F(first)(WT_CURSOR *thiscursor);
/*! Move to the last record.
*
@@ -243,7 +243,7 @@ struct wt_cursor {
* @param cursor the cursor handle
* @errors
*/
- int __F(last)(WT_CURSOR *cursor);
+ int __F(last)(WT_CURSOR *thiscursor);
/*! Move to the next record.
*
@@ -253,7 +253,7 @@ struct wt_cursor {
* @param cursor the cursor handle
* @errors
*/
- int __F(next)(WT_CURSOR *cursor);
+ int __F(next)(WT_CURSOR *thiscursor);
/*! Move to the previous record.
*
@@ -263,7 +263,7 @@ struct wt_cursor {
* @param cursor the cursor handle
* @errors
*/
- int __F(prev)(WT_CURSOR *cursor);
+ int __F(prev)(WT_CURSOR *thiscursor);
/*! Search for a record.
*
@@ -275,7 +275,7 @@ struct wt_cursor {
* @param cursor the cursor handle
* @errors
*/
- int __F(search)(WT_CURSOR *cursor);
+ int __F(search)(WT_CURSOR *thiscursor);
/*! Search for a record.
*
@@ -289,7 +289,7 @@ struct wt_cursor {
* found, -1 if a smaller key is found, +1 if a larger key is found
* @errors
*/
- int __F(search_near)(WT_CURSOR *cursor, int *exactp);
+ int __F(search_near)(WT_CURSOR *thiscursor, int *exactp);
/*! @} */
/*! @name Data modification
@@ -308,7 +308,7 @@ struct wt_cursor {
* @param cursor the cursor handle
* @errors
*/
- int __F(insert)(WT_CURSOR *cursor);
+ int __F(insert)(WT_CURSOR *thiscursor);
/*! Update the current record. The cursor must be positioned on a
* record and the value of the record will be updated. If the record
@@ -323,7 +323,7 @@ struct wt_cursor {
* @param cursor the cursor handle
* @errors
*/
- int __F(update)(WT_CURSOR *cursor);
+ int __F(update)(WT_CURSOR *thiscursor);
/*! Remove the current record.
*
@@ -333,7 +333,7 @@ struct wt_cursor {
* @param cursor the cursor handle
* @errors
*/
- int __F(remove)(WT_CURSOR *cursor);
+ int __F(remove)(WT_CURSOR *thiscursor);
/*! @} */
/*! Close the cursor.
@@ -350,7 +350,7 @@ struct wt_cursor {
* @configend
* @errors
*/
- int __F(close)(WT_CURSOR *cursor, const char *config);
+ int __F(close)(WT_CURSOR *thiscursor, const char *config);
/*
* Protected fields, only to be used by cursor implementations.
@@ -407,7 +407,7 @@ struct wt_session {
* @configend
* @errors
*/
- int __F(close)(WT_SESSION *session, const char *config);
+ int __F(close)(WT_SESSION *thissession, const char *config);
/*! @name Cursor handles
* @{
@@ -468,7 +468,7 @@ struct wt_session {
* @param cursorp a pointer to the newly opened cursor
* @errors
*/
- int __F(open_cursor)(WT_SESSION *session,
+ int __F(open_cursor)(WT_SESSION *thissession,
const char *uri, WT_CURSOR *to_dup,
const char *config, WT_CURSOR **cursorp);
/*! @} */
@@ -522,7 +522,7 @@ struct wt_session {
* @configend
* @errors
*/
- int __F(create_table)(WT_SESSION *session, const char *name,
+ int __F(create_table)(WT_SESSION *thissession, const char *name,
const char *config);
/*! Rename a table.
@@ -537,7 +537,7 @@ struct wt_session {
* @configend
* @errors
*/
- int __F(rename_table)(WT_SESSION *session,
+ int __F(rename_table)(WT_SESSION *thissession,
const char *oldname, const char *newname, const char *config);
/*! Drop (delete) a table.
@@ -551,7 +551,7 @@ struct wt_session {
* @configend
* @errors
*/
- int __F(drop_table)(WT_SESSION *session,
+ int __F(drop_table)(WT_SESSION *thissession,
const char *name, const char *config);
/*! Truncate a table.
@@ -572,7 +572,7 @@ struct wt_session {
* @configend
* @errors
*/
- int __F(truncate_table)(WT_SESSION *session, const char *name,
+ int __F(truncate_table)(WT_SESSION *thissession, const char *name,
WT_CURSOR *start, WT_CURSOR *end, const char *config);
/*! Verify a table.
@@ -588,7 +588,7 @@ struct wt_session {
* @configend
* @errors
*/
- int __F(verify_table)(WT_SESSION *session, const char *name,
+ int __F(verify_table)(WT_SESSION *thissession, const char *name,
const char *config);
/*! @} */
@@ -623,7 +623,7 @@ struct wt_session {
* @configend
* @errors
*/
- int __F(begin_transaction)(WT_SESSION *session, const char *config);
+ int __F(begin_transaction)(WT_SESSION *thissession, const char *config);
/*! Commit the current transaction.
*
@@ -640,7 +640,7 @@ struct wt_session {
* @configend
* @errors
*/
- int __F(commit_transaction)(WT_SESSION *session, const char *config);
+ int __F(commit_transaction)(WT_SESSION *thissession, const char *config);
/*! Roll back the current transaction.
*
@@ -657,7 +657,7 @@ struct wt_session {
* @configend
* @errors
*/
- int __F(rollback_transaction)(WT_SESSION *session, const char *config);
+ int __F(rollback_transaction)(WT_SESSION *thissession, const char *config);
/*! Flush the cache and/or the log and optionally archive log files.
*
@@ -708,7 +708,7 @@ struct wt_connection {
* @configend
* @errors
*/
- int __F(load_extension)(WT_CONNECTION *connection,
+ int __F(load_extension)(WT_CONNECTION *thisconnection,
const char *path, const char *config);
/*! Add a new type of cursor.
@@ -733,7 +733,7 @@ struct wt_connection {
* @configend
* @errors
*/
- int __F(add_cursor_type)(WT_CONNECTION *connection,
+ int __F(add_cursor_type)(WT_CONNECTION *thisconnection,
const char *prefix, WT_CURSOR_TYPE *ctype, const char *config);
/*! Add a custom collation function.
@@ -757,7 +757,7 @@ struct wt_connection {
* @configend
* @errors
*/
- int __F(add_collator)(WT_CONNECTION *connection,
+ int __F(add_collator)(WT_CONNECTION *thisconnection,
const char *name, WT_COLLATOR *collator, const char *config);
/*! Add a custom extractor for index keys or column groups.
@@ -781,7 +781,7 @@ struct wt_connection {
* @configend
* @errors
*/
- int __F(add_extractor)(WT_CONNECTION *connection, const char *name,
+ int __F(add_extractor)(WT_CONNECTION *thisconnection, const char *name,
WT_EXTRACTOR *extractor, const char *config);
/*! Close a connection.
@@ -796,7 +796,7 @@ struct wt_connection {
* @configend
* @errors
*/
- int __F(close)(WT_CONNECTION *connection, const char *config);
+ int __F(close)(WT_CONNECTION *thisconnection, const char *config);
/*! The home directory of the connection.
*
@@ -806,7 +806,7 @@ struct wt_connection {
* @param connection the connection handle
* @returns a pointer to a string naming the home directory
*/
- const char *__F(get_home)(WT_CONNECTION *connection);
+ const char *__F(get_home)(WT_CONNECTION *thisconnection);
/*! Did opening this handle create the database?
*
@@ -819,7 +819,7 @@ struct wt_connection {
* ::wiredtiger_open, true (non-zero) if it was created by opening
* this handle.
*/
- int __F(is_new)(WT_CONNECTION *connection);
+ int __F(is_new)(WT_CONNECTION *thisconnection);
/*! Open a session.
*
@@ -834,8 +834,8 @@ struct wt_connection {
* @param sessionp the new session handle
* @errors
*/
- int __F(open_session)(WT_CONNECTION *connection,
- WT_EVENT_HANDLER *errhandler, const char *config,
+ int __F(open_session)(WT_CONNECTION *thisconnection,
+ WT_ERROR_HANDLER *errhandler, const char *config,
WT_SESSION **sessionp);
};