summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>2011-06-02 01:16:22 +0100
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>2011-06-02 01:16:22 +0100
commit389f2cf1d01a20dda78f09830e13fd3769ad5bb6 (patch)
tree211e1df26abb459083cfb231285f96451986bbde
parentea03ffbf76c24e7ba36cc6c94ec2b0c748700c20 (diff)
downloadpsycopg2-389f2cf1d01a20dda78f09830e13fd3769ad5bb6.tar.gz
Added autocommit property on connection
-rw-r--r--psycopg/connection.h2
-rw-r--r--psycopg/connection_int.c3
-rw-r--r--psycopg/connection_type.c42
-rw-r--r--psycopg/pqpath.c5
-rwxr-xr-xtests/test_connection.py92
5 files changed, 143 insertions, 1 deletions
diff --git a/psycopg/connection.h b/psycopg/connection.h
index 979b37f..a5aa267 100644
--- a/psycopg/connection.h
+++ b/psycopg/connection.h
@@ -119,6 +119,8 @@ typedef struct {
int equote; /* use E''-style quotes for escaped strings */
PyObject *weakreflist; /* list of weak references */
+ int autocommit;
+
} connectionObject;
/* C-callable functions in connection_int.c and connection_ext.c */
diff --git a/psycopg/connection_int.c b/psycopg/connection_int.c
index b0ed41d..5e2ba02 100644
--- a/psycopg/connection_int.c
+++ b/psycopg/connection_int.c
@@ -989,7 +989,8 @@ conn_set(connectionObject *self, const char *param, const char *value)
int
conn_set_autocommit(connectionObject *self, int value)
{
- return -1;
+ self->autocommit = value;
+ return 0;
}
/* conn_switch_isolation_level - switch isolation level on the connection */
diff --git a/psycopg/connection_type.c b/psycopg/connection_type.c
index 299888a..33a6955 100644
--- a/psycopg/connection_type.c
+++ b/psycopg/connection_type.c
@@ -517,6 +517,42 @@ psyco_conn_set_transaction(connectionObject *self, PyObject *args, PyObject *kwa
}
+#define psyco_conn_autocommit_doc \
+"set or return the autocommit status."
+
+static PyObject *
+psyco_conn_autocommit_get(connectionObject *self)
+{
+ PyObject *ret;
+ ret = self->autocommit ? Py_True : Py_False;
+ Py_INCREF(ret);
+ return ret;
+}
+
+static PyObject *
+_psyco_conn_autocommit_set_checks(connectionObject *self)
+{
+ /* wrapper to use the EXC_IF macros.
+ * return NULL in case of error, else whatever */
+ EXC_IF_CONN_CLOSED(self);
+ EXC_IF_CONN_ASYNC(self, autocommit);
+ EXC_IF_IN_TRANSACTION(self, autocommit);
+ return Py_None; /* borrowed */
+}
+
+static int
+psyco_conn_autocommit_set(connectionObject *self, PyObject *pyvalue)
+{
+ int value;
+
+ if (!_psyco_conn_autocommit_set_checks(self)) { return -1; }
+ if (-1 == (value = PyObject_IsTrue(pyvalue))) { return -1; }
+ if (0 != conn_set_autocommit(self, value)) { return -1; }
+
+ return 0;
+}
+
+
/* set_isolation_level method - switch connection isolation level */
#define psyco_conn_set_isolation_level_doc \
@@ -927,6 +963,12 @@ static struct PyGetSetDef connectionObject_getsets[] = {
EXCEPTION_GETTER(IntegrityError),
EXCEPTION_GETTER(DataError),
EXCEPTION_GETTER(NotSupportedError),
+#ifdef PSYCOPG_EXTENSIONS
+ { "autocommit",
+ (getter)psyco_conn_autocommit_get,
+ (setter)psyco_conn_autocommit_set,
+ psyco_conn_autocommit_doc },
+#endif
{NULL}
};
#undef EXCEPTION_GETTER
diff --git a/psycopg/pqpath.c b/psycopg/pqpath.c
index a614422..f945448 100644
--- a/psycopg/pqpath.c
+++ b/psycopg/pqpath.c
@@ -417,6 +417,11 @@ pq_begin_locked(connectionObject *conn, PGresult **pgres, char **error,
Dprintf("pq_begin_locked: pgconn = %p, isolevel = %ld, status = %d",
conn->pgconn, conn->isolation_level, conn->status);
+ if (conn->autocommit) {
+ Dprintf("pq_begin_locked: autocommit");
+ return 0;
+ }
+
if (conn->isolation_level == ISOLATION_LEVEL_AUTOCOMMIT
|| conn->status != CONN_STATUS_READY) {
Dprintf("pq_begin_locked: transaction in progress");
diff --git a/tests/test_connection.py b/tests/test_connection.py
index 18c9277..9001457 100755
--- a/tests/test_connection.py
+++ b/tests/test_connection.py
@@ -851,6 +851,98 @@ class TransactionControlTests(unittest.TestCase):
self.conn.set_transaction, readonly=True, deferrable=True)
+class AutocommitTests(unittest.TestCase):
+ def setUp(self):
+ self.conn = psycopg2.connect(dsn)
+
+ def tearDown(self):
+ if not self.conn.closed:
+ self.conn.close()
+
+ def test_default_no_autocommit(self):
+ self.assert_(not self.conn.autocommit)
+ self.assertEqual(self.conn.status, psycopg2.extensions.STATUS_READY)
+ self.assertEqual(self.conn.get_transaction_status(),
+ psycopg2.extensions.TRANSACTION_STATUS_IDLE)
+
+ cur = self.conn.cursor()
+ cur.execute('select 1;')
+ self.assertEqual(self.conn.status, psycopg2.extensions.STATUS_BEGIN)
+ self.assertEqual(self.conn.get_transaction_status(),
+ psycopg2.extensions.TRANSACTION_STATUS_INTRANS)
+
+ self.conn.rollback()
+ self.assertEqual(self.conn.status, psycopg2.extensions.STATUS_READY)
+ self.assertEqual(self.conn.get_transaction_status(),
+ psycopg2.extensions.TRANSACTION_STATUS_IDLE)
+
+ def test_set_autocommit(self):
+ self.conn.autocommit = True
+ self.assert_(self.conn.autocommit)
+ self.assertEqual(self.conn.status, psycopg2.extensions.STATUS_READY)
+ self.assertEqual(self.conn.get_transaction_status(),
+ psycopg2.extensions.TRANSACTION_STATUS_IDLE)
+
+ cur = self.conn.cursor()
+ cur.execute('select 1;')
+ self.assertEqual(self.conn.status, psycopg2.extensions.STATUS_READY)
+ self.assertEqual(self.conn.get_transaction_status(),
+ psycopg2.extensions.TRANSACTION_STATUS_IDLE)
+
+ self.conn.autocommit = False
+ self.assert_(not self.conn.autocommit)
+ self.assertEqual(self.conn.status, psycopg2.extensions.STATUS_READY)
+ self.assertEqual(self.conn.get_transaction_status(),
+ psycopg2.extensions.TRANSACTION_STATUS_IDLE)
+
+ cur.execute('select 1;')
+ self.assertEqual(self.conn.status, psycopg2.extensions.STATUS_BEGIN)
+ self.assertEqual(self.conn.get_transaction_status(),
+ psycopg2.extensions.TRANSACTION_STATUS_INTRANS)
+
+ def test_set_intrans_error(self):
+ cur = self.conn.cursor()
+ cur.execute('select 1;')
+ self.assertRaises(psycopg2.ProgrammingError,
+ setattr, self.conn, 'autocommit', True)
+
+ def test_set_transaction_autocommit(self):
+ self.conn.set_transaction(autocommit=True)
+ self.assert_(self.conn.autocommit)
+ self.assertEqual(self.conn.status, psycopg2.extensions.STATUS_READY)
+ self.assertEqual(self.conn.get_transaction_status(),
+ psycopg2.extensions.TRANSACTION_STATUS_IDLE)
+
+ cur = self.conn.cursor()
+ cur.execute('select 1;')
+ self.assertEqual(self.conn.status, psycopg2.extensions.STATUS_READY)
+ self.assertEqual(self.conn.get_transaction_status(),
+ psycopg2.extensions.TRANSACTION_STATUS_IDLE)
+
+ self.conn.set_transaction(autocommit=False)
+ self.assert_(not self.conn.autocommit)
+ self.assertEqual(self.conn.status, psycopg2.extensions.STATUS_READY)
+ self.assertEqual(self.conn.get_transaction_status(),
+ psycopg2.extensions.TRANSACTION_STATUS_IDLE)
+
+ cur.execute('select 1;')
+ self.assertEqual(self.conn.status, psycopg2.extensions.STATUS_BEGIN)
+ self.assertEqual(self.conn.get_transaction_status(),
+ psycopg2.extensions.TRANSACTION_STATUS_INTRANS)
+ self.conn.rollback()
+
+ self.conn.set_transaction('serializable', readonly=True, autocommit=True)
+ self.assert_(self.conn.autocommit)
+ cur.execute('select 1;')
+ self.assertEqual(self.conn.status, psycopg2.extensions.STATUS_READY)
+ self.assertEqual(self.conn.get_transaction_status(),
+ psycopg2.extensions.TRANSACTION_STATUS_IDLE)
+ cur.execute("SHOW default_transaction_isolation;")
+ self.assertEqual(cur.fetchone()[0], 'serializable')
+ cur.execute("SHOW default_transaction_read_only;")
+ self.assertEqual(cur.fetchone()[0], 'on')
+
+
def test_suite():
return unittest.TestLoader().loadTestsFromName(__name__)