diff -r fc3eab44765f Lib/sqlite3/test/transactions.py --- a/Lib/sqlite3/test/transactions.py Wed Dec 28 20:03:23 2016 -0800 +++ b/Lib/sqlite3/test/transactions.py Thu Dec 29 16:43:21 2016 +0200 @@ -179,6 +179,15 @@ result = self.con.execute("select * from test").fetchall() self.assertEqual(result, []) + def CheckImmediateTransactionalDDL(self): + # You can achieve transactional DDL by issuing a BEGIN + # statement manually. + self.con.execute("begin immediate") + self.con.execute("create table test(i)") + self.con.rollback() + with self.assertRaises(sqlite.OperationalError): + self.con.execute("select * from test") + def CheckTransactionalDDL(self): # You can achieve transactional DDL by issuing a BEGIN # statement manually. diff -r fc3eab44765f Modules/_sqlite/cursor.c --- a/Modules/_sqlite/cursor.c Wed Dec 28 20:03:23 2016 -0800 +++ b/Modules/_sqlite/cursor.c Thu Dec 29 16:43:21 2016 +0200 @@ -514,7 +514,7 @@ /* For backwards compatibility reasons, do not start a transaction if a DDL statement is encountered. If anybody wants transactional DDL, they can issue a BEGIN statement manually. */ - if (self->connection->begin_statement && !sqlite3_stmt_readonly(self->statement->st) && !self->statement->is_ddl) { + if (self->connection->begin_statement && !sqlite3_stmt_readonly(self->statement->st) && self->statement->is_dml) { if (sqlite3_get_autocommit(self->connection->db)) { result = _pysqlite_connection_begin(self->connection); if (!result) { diff -r fc3eab44765f Modules/_sqlite/statement.c --- a/Modules/_sqlite/statement.c Wed Dec 28 20:03:23 2016 -0800 +++ b/Modules/_sqlite/statement.c Thu Dec 29 16:43:21 2016 +0200 @@ -73,8 +73,8 @@ Py_INCREF(sql); self->sql = sql; - /* determine if the statement is a DDL statement */ - self->is_ddl = 0; + /* determine if the statement is a DML statement */ + self->is_dml = 0; for (p = sql_cstr; *p != 0; p++) { switch (*p) { case ' ': @@ -84,9 +84,11 @@ continue; } - self->is_ddl = (PyOS_strnicmp(p, "create ", 7) == 0) - || (PyOS_strnicmp(p, "drop ", 5) == 0) - || (PyOS_strnicmp(p, "reindex ", 8) == 0); + self->is_dml = (PyOS_strnicmp(p, "insert ", 7) == 0) + || (PyOS_strnicmp(p, "update ", 7) == 0) + || (PyOS_strnicmp(p, "delete ", 7) == 0) + || (PyOS_strnicmp(p, "replace ", 8) == 0) + || (PyOS_strnicmp(p, "select ", 7) == 0); break; } diff -r fc3eab44765f Modules/_sqlite/statement.h --- a/Modules/_sqlite/statement.h Wed Dec 28 20:03:23 2016 -0800 +++ b/Modules/_sqlite/statement.h Thu Dec 29 16:43:21 2016 +0200 @@ -38,7 +38,7 @@ sqlite3_stmt* st; PyObject* sql; int in_use; - int is_ddl; + int is_dml; PyObject* in_weakreflist; /* List of weak references */ } pysqlite_Statement;