[pypy-commit] pypy default: more cleanups for sqlite

bdkearns noreply at buildbot.pypy.org
Fri Apr 5 22:39:28 CEST 2013


Author: Brian Kearns <bdkearns at gmail.com>
Branch: 
Changeset: r63069:f09e57516642
Date: 2013-04-05 16:32 -0400
http://bitbucket.org/pypy/pypy/changeset/f09e57516642/

Log:	more cleanups for sqlite

diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
--- a/lib_pypy/_sqlite3.py
+++ b/lib_pypy/_sqlite3.py
@@ -852,7 +852,7 @@
         self._reset = False
         self.__locked = False
         self.__closed = False
-        self.__description = None
+        self.__lastrowid = None
         self.__rowcount = -1
 
         con._check_thread()
@@ -972,20 +972,24 @@
         try:
             if not isinstance(sql, basestring):
                 raise ValueError("operation parameter must be str or unicode")
-            self.__description = None
+            try:
+                del self.__description
+            except AttributeError:
+                pass
             self.__rowcount = -1
             self.__statement = self.__connection._statement_cache.get(sql)
 
             if self.__connection._isolation_level is not None:
-                if self.__statement._kind == Statement._DDL:
+                if self.__statement._type in ("UPDATE", "DELETE", "INSERT", "REPLACE"):
+                    if not self.__connection._in_transaction:
+                        self.__connection._begin()
+                elif self.__statement._type == "OTHER":
                     if self.__connection._in_transaction:
                         self.__connection.commit()
-                elif self.__statement._kind == Statement._DML:
-                    if not self.__connection._in_transaction:
-                        self.__connection._begin()
-
-            if multiple and self.__statement._kind != Statement._DML:
-                raise ProgrammingError("executemany is only for DML statements")
+                elif self.__statement._type == "SELECT":
+                    if multiple:
+                        raise ProgrammingError("You cannot execute SELECT "
+                                               "statements in executemany().")
 
             for params in many_params:
                 self.__statement._set_params(params)
@@ -996,17 +1000,26 @@
                     self.__statement._reset()
                     raise self.__connection._get_exception(ret)
 
-                if self.__statement._kind == Statement._DML:
+                if ret == _lib.SQLITE_ROW:
+                    if multiple:
+                        raise ProgrammingError("executemany() can only execute DML statements.")
+                    self.__build_row_cast_map()
+                    self.__next_row = self.__fetch_one_row()
+                elif ret == _lib.SQLITE_DONE and not multiple:
                     self.__statement._reset()
 
-                if ret == _lib.SQLITE_ROW:
-                    self.__build_row_cast_map()
-                    self.__next_row = self.__fetch_one_row()
-
-                if self.__statement._kind == Statement._DML:
+                if self.__statement._type in ("UPDATE", "DELETE", "INSERT", "REPLACE"):
                     if self.__rowcount == -1:
                         self.__rowcount = 0
                     self.__rowcount += _lib.sqlite3_changes(self.__connection._db)
+
+                if not multiple and self.__statement._type == "INSERT":
+                    self.__lastrowid = _lib.sqlite3_last_insert_rowid(self.__connection._db)
+                else:
+                    self.__lastrowid = None
+
+                if multiple:
+                    self.__statement._reset()
         finally:
             self.__connection._in_transaction = \
                 not _lib.sqlite3_get_autocommit(self.__connection._db)
@@ -1118,13 +1131,15 @@
     rowcount = property(__get_rowcount)
 
     def __get_description(self):
-        if self.__description is None:
+        try:
+            return self.__description
+        except AttributeError:
             self.__description = self.__statement._get_description()
-        return self.__description
+            return self.__description
     description = property(__get_description)
 
     def __get_lastrowid(self):
-        return _lib.sqlite3_last_insert_rowid(self.__connection._db)
+        return self.__lastrowid
     lastrowid = property(__get_lastrowid)
 
     def setinputsizes(self, *args):
@@ -1135,8 +1150,6 @@
 
 
 class Statement(object):
-    _DML, _DQL, _DDL = range(3)
-
     _statement = None
 
     def __init__(self, connection, sql):
@@ -1147,13 +1160,14 @@
 
         if not isinstance(sql, basestring):
             raise Warning("SQL is of wrong type. Must be string or unicode.")
-        first_word = self._statement_kind = sql.lstrip().split(" ")[0].upper()
-        if first_word in ("INSERT", "UPDATE", "DELETE", "REPLACE"):
-            self._kind = Statement._DML
-        elif first_word in ("SELECT", "PRAGMA"):
-            self._kind = Statement._DQL
+
+        first_word = sql.lstrip().split(" ")[0].upper()
+        if first_word == "":
+            self._type = "INVALID"
+        elif first_word in ("SELECT", "INSERT", "UPDATE", "DELETE", "REPLACE"):
+            self._type = first_word
         else:
-            self._kind = Statement._DDL
+            self._type = "OTHER"
 
         if isinstance(sql, unicode):
             sql = sql.encode('utf-8')
@@ -1166,11 +1180,12 @@
 
         if ret == _lib.SQLITE_OK and not self._statement:
             # an empty statement, work around that, as it's the least trouble
+            self._type = "SELECT"
             c_sql = _ffi.new("char[]", b"select 42")
             ret = _lib.sqlite3_prepare_v2(self.__con._db, c_sql, -1,
                                           statement_star, next_char)
             self._statement = statement_star[0]
-            self._kind = Statement._DQL
+
         if ret != _lib.SQLITE_OK:
             raise self.__con._get_exception(ret)
 
@@ -1281,7 +1296,7 @@
             raise ValueError("parameters are of unsupported type")
 
     def _get_description(self):
-        if self._kind == Statement._DML:
+        if self._type in ("INSERT", "UPDATE", "DELETE", "REPLACE"):
             return None
         desc = []
         for i in xrange(_lib.sqlite3_column_count(self._statement)):
diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py
--- a/pypy/module/test_lib_pypy/test_sqlite3.py
+++ b/pypy/module/test_lib_pypy/test_sqlite3.py
@@ -216,3 +216,10 @@
     cur = con.cursor()
     cur.execute("select 42").fetchall()
     assert cur.description is not None
+
+def test_executemany_lastrowid():
+    con = _sqlite3.connect(':memory:')
+    cur = con.cursor()
+    cur.execute("create table test(a)")
+    cur.executemany("insert into test values (?)", [[1], [2], [3]])
+    assert cur.lastrowid is None


More information about the pypy-commit mailing list