Fixed "database locked" exception when transaction is rolling back
diff --git a/src/main/java/org/robolectric/shadows/ShadowSQLiteDatabase.java b/src/main/java/org/robolectric/shadows/ShadowSQLiteDatabase.java
index f84076a..65ba450 100644
--- a/src/main/java/org/robolectric/shadows/ShadowSQLiteDatabase.java
+++ b/src/main/java/org/robolectric/shadows/ShadowSQLiteDatabase.java
@@ -126,17 +126,11 @@
             PreparedStatement insert = connection.prepareStatement(sqlInsertString.sql, Statement.RETURN_GENERATED_KEYS);
             Iterator<Object> columns = sqlInsertString.columnValues.iterator();
             int i = 1;
-            long result = -1;
             while (columns.hasNext()) {
                 insert.setObject(i++, columns.next());
             }
             insert.executeUpdate();
-            ResultSet resultSet = insert.getGeneratedKeys();
-            if (resultSet.next()) {
-                result = resultSet.getLong(1);
-            }
-            resultSet.close();
-            return result;
+            return fetchGeneratedKey(insert.getGeneratedKeys());
         } catch (SQLException e) {
             throw new android.database.SQLException(e.getLocalizedMessage());
         }
diff --git a/src/main/java/org/robolectric/shadows/ShadowSQLiteStatement.java b/src/main/java/org/robolectric/shadows/ShadowSQLiteStatement.java
index 8f4206b..d0a1dac 100644
--- a/src/main/java/org/robolectric/shadows/ShadowSQLiteStatement.java
+++ b/src/main/java/org/robolectric/shadows/ShadowSQLiteStatement.java
@@ -5,6 +5,7 @@
 import android.database.sqlite.SQLiteStatement;
 import org.robolectric.internal.Implementation;
 import org.robolectric.internal.Implements;
+import org.robolectric.util.SQLite;
 
 import java.sql.ResultSet;
 import java.sql.SQLException;
@@ -34,13 +35,7 @@
     public long executeInsert() {
         try {
             actualDBstatement.executeUpdate();
-            ResultSet resultSet = actualDBstatement.getGeneratedKeys();
-
-            if (resultSet.next()) {
-                return resultSet.getLong(1);
-            } else {
-                throw new RuntimeException("Could not retrive generatedKeys");
-            }
+            return SQLite.fetchGeneratedKey(actualDBstatement.getGeneratedKeys());
         } catch (SQLException e) {
             throw new RuntimeException(e);
         }
diff --git a/src/main/java/org/robolectric/util/SQLite.java b/src/main/java/org/robolectric/util/SQLite.java
index 19b0298..62bfcc0 100644
--- a/src/main/java/org/robolectric/util/SQLite.java
+++ b/src/main/java/org/robolectric/util/SQLite.java
@@ -3,6 +3,7 @@
 import android.content.ContentValues;
 import android.database.sqlite.SQLiteException;
 
+import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -190,6 +191,21 @@
     }
 
     /**
+     * Fetches generated key from {@link ResultSet resultSet} and immediately closes him.
+     * @param resultSet resultSet returned from {@link java.sql.Statement#getGeneratedKeys()}
+     * @return fetched key, <code>-1</code> otherwise
+     * @throws SQLException if {@link java.sql.ResultSet#next()} or {@link java.sql.ResultSet#close()}
+     *      will throw an exception
+     */
+    public static long fetchGeneratedKey(ResultSet resultSet) throws SQLException {
+        try {
+            return resultSet.next() ? resultSet.getLong(1) : -1;
+        } finally {
+            resultSet.close();
+        }
+    }
+
+    /**
      * Container for a SQL fragment and the objects which are to be
      * bound to the arguments in the fragment.
      */
diff --git a/src/test/java/org/robolectric/shadows/SQLiteStatementTest.java b/src/test/java/org/robolectric/shadows/SQLiteStatementTest.java
index a028f11..022d0e2 100644
--- a/src/test/java/org/robolectric/shadows/SQLiteStatementTest.java
+++ b/src/test/java/org/robolectric/shadows/SQLiteStatementTest.java
@@ -66,6 +66,34 @@
     }
 
     @Test
+    public void testExecuteInsertShouldCloseGeneratedKeysResultSet() throws Exception {
+
+
+        //
+        // NOTE:
+        // As a side-effect we will get "database locked" exception
+        // on rollback when generatedKeys isn't closed
+        //
+        // Don't know how suitable to use Mockito here, but
+        // it will be a little bit simpler to test ShadowSQLiteStatement
+        // if actualDBStatement become mockable
+        //
+
+        database.beginTransaction();
+        try {
+            SQLiteStatement insertStatement = database.compileStatement("INSERT INTO `routine` " +
+                    "(`name` ,`lastUsed`) VALUES ('test',0)");
+            try {
+                insertStatement.executeInsert();
+            } finally {
+                insertStatement.close();
+            }
+        } finally {
+            database.endTransaction();
+        }
+    }
+
+    @Test
     public void testExecuteUpdateDelete() throws Exception {
 
         SQLiteStatement insertStatement = database.compileStatement("INSERT INTO `routine` (`name`) VALUES (?)");