Add more db methods, introduce stmt program

Bug: 30355996
Test: no-tests
Change-Id: I5b851b4dc1d5e865bac9bb554be95289f258d085
diff --git a/room/db/src/main/java/com/android/support/db/SupportDb.java b/room/db/src/main/java/com/android/support/db/SupportDb.java
index 3377504..e1bf01d 100644
--- a/room/db/src/main/java/com/android/support/db/SupportDb.java
+++ b/room/db/src/main/java/com/android/support/db/SupportDb.java
@@ -22,7 +22,9 @@
  * A database abstraction which removes the framework dependency and allows swapping underlying
  * sql versions.
  */
+@SuppressWarnings("unused")
 public interface SupportDb {
+    // TODO override all and rename to SupportSqliteDatabase
     /**
      * Runs the query with the given arguments and returns the result Cursor.
      *
@@ -41,4 +43,44 @@
      * @return Compiled statement.
      */
     SupportSqliteStatement compileStatement(String sql);
+
+    /**
+     * Begins a transaction in EXCLUSIVE mode.
+     * <p>
+     * Transactions can be nested.
+     * When the outer transaction is ended all of
+     * the work done in that transaction and all of the nested transactions will be committed or
+     * rolled back. The changes will be rolled back if any transaction is ended without being
+     * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
+     * </p>
+     * <p>Here is the standard idiom for transactions:
+     *
+     * <pre>
+     *   db.beginTransaction();
+     *   try {
+     *     ...
+     *     db.setTransactionSuccessful();
+     *   } finally {
+     *     db.endTransaction();
+     *   }
+     * </pre>
+     */
+    void beginTransaction();
+
+    /**
+     * End a transaction. See beginTransaction for notes about how to use this and when transactions
+     * are committed and rolled back.
+     */
+    void endTransaction();
+
+    /**
+     * Marks the current transaction as successful. Do not do any more database work between
+     * calling this and calling endTransaction. Do as little non-database work as possible in that
+     * situation too. If any errors are encountered between this and endTransaction the transaction
+     * will still be committed.
+     *
+     * @throws IllegalStateException if the current thread is not in a transaction or the
+     * transaction is already marked as successful.
+     */
+    void setTransactionSuccessful();
 }
diff --git a/room/db/src/main/java/com/android/support/db/SupportSqliteProgram.java b/room/db/src/main/java/com/android/support/db/SupportSqliteProgram.java
new file mode 100644
index 0000000..d042551
--- /dev/null
+++ b/room/db/src/main/java/com/android/support/db/SupportSqliteProgram.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.support.db;
+
+/**
+ * An interface to map the behavior of {@link android.database.sqlite.SQLiteProgram}.
+ */
+
+@SuppressWarnings("unused")
+public interface SupportSqliteProgram {
+    /**
+     * Bind a NULL value to this statement. The value remains bound until
+     * {@link #clearBindings} is called.
+     *
+     * @param index The 1-based index to the parameter to bind null to
+     */
+    void bindNull(int index);
+
+    /**
+     * Bind a long value to this statement. The value remains bound until
+     * {@link #clearBindings} is called.
+     *addToBindArgs
+     * @param index The 1-based index to the parameter to bind
+     * @param value The value to bind
+     */
+    void bindLong(int index, long value);
+
+    /**
+     * Bind a double value to this statement. The value remains bound until
+     * {@link #clearBindings} is called.
+     *
+     * @param index The 1-based index to the parameter to bind
+     * @param value The value to bind
+     */
+    void bindDouble(int index, double value);
+
+    /**
+     * Bind a String value to this statement. The value remains bound until
+     * {@link #clearBindings} is called.
+     *
+     * @param index The 1-based index to the parameter to bind
+     * @param value The value to bind, must not be null
+     */
+    void bindString(int index, String value);
+
+    /**
+     * Bind a byte array value to this statement. The value remains bound until
+     * {@link #clearBindings} is called.
+     *
+     * @param index The 1-based index to the parameter to bind
+     * @param value The value to bind, must not be null
+     */
+    void bindBlob(int index, byte[] value);
+
+    /**
+     * Clears all existing bindings. Unset bindings are treated as NULL.
+     */
+    void clearBindings();
+}
diff --git a/room/db/src/main/java/com/android/support/db/SupportSqliteStatement.java b/room/db/src/main/java/com/android/support/db/SupportSqliteStatement.java
index 69c8e5a..ba40227 100644
--- a/room/db/src/main/java/com/android/support/db/SupportSqliteStatement.java
+++ b/room/db/src/main/java/com/android/support/db/SupportSqliteStatement.java
@@ -16,57 +16,69 @@
 
 package com.android.support.db;
 
+import android.os.ParcelFileDescriptor;
+
 /**
  * An interface to map the behavior of {@link android.database.sqlite.SQLiteStatement}.
  */
 @SuppressWarnings("unused")
-public interface SupportSqliteStatement {
+public interface SupportSqliteStatement extends SupportSqliteProgram {
     /**
-     * Bind a NULL value to this statement. The value remains bound until
-     * {@link #clearBindings} is called.
+     * Execute this SQL statement, if it is not a SELECT / INSERT / DELETE / UPDATE, for example
+     * CREATE / DROP table, view, trigger, index etc.
      *
-     * @param index The 1-based index to the parameter to bind null to
+     * @throws android.database.SQLException If the SQL string is invalid for
+     *         some reason
      */
-    void bindNull(int index);
+    void execute();
 
     /**
-     * Bind a long value to this statement. The value remains bound until
-     * {@link #clearBindings} is called.
-     *addToBindArgs
-     * @param index The 1-based index to the parameter to bind
-     * @param value The value to bind
-     */
-    void bindLong(int index, long value);
-
-    /**
-     * Bind a double value to this statement. The value remains bound until
-     * {@link #clearBindings} is called.
+     * Execute this SQL statement, if the the number of rows affected by execution of this SQL
+     * statement is of any importance to the caller - for example, UPDATE / DELETE SQL statements.
      *
-     * @param index The 1-based index to the parameter to bind
-     * @param value The value to bind
+     * @return the number of rows affected by this SQL statement execution.
+     * @throws android.database.SQLException If the SQL string is invalid for
+     *         some reason
      */
-    void bindDouble(int index, double value);
+    int executeUpdateDelete();
 
     /**
-     * Bind a String value to this statement. The value remains bound until
-     * {@link #clearBindings} is called.
+     * Execute this SQL statement and return the ID of the row inserted due to this call.
+     * The SQL statement should be an INSERT for this to be a useful call.
      *
-     * @param index The 1-based index to the parameter to bind
-     * @param value The value to bind, must not be null
-     */
-    void bindString(int index, String value);
-
-    /**
-     * Bind a byte array value to this statement. The value remains bound until
-     * {@link #clearBindings} is called.
+     * @return the row ID of the last row inserted, if this insert is successful. -1 otherwise.
      *
-     * @param index The 1-based index to the parameter to bind
-     * @param value The value to bind, must not be null
+     * @throws android.database.SQLException If the SQL string is invalid for
+     *         some reason
      */
-    void bindBlob(int index, byte[] value);
+    long executeInsert();
 
     /**
-     * Clears all existing bindings. Unset bindings are treated as NULL.
+     * Execute a statement that returns a 1 by 1 table with a numeric value.
+     * For example, SELECT COUNT(*) FROM table;
+     *
+     * @return The result of the query.
+     *
+     * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
      */
-    void clearBindings();
+    long simpleQueryForLong();
+    /**
+     * Execute a statement that returns a 1 by 1 table with a text value.
+     * For example, SELECT COUNT(*) FROM table;
+     *
+     * @return The result of the query.
+     *
+     * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
+     */
+    String simpleQueryForString();
+
+    /**
+     * Executes a statement that returns a 1 by 1 table with a blob value.
+     *
+     * @return A read-only file descriptor for a copy of the blob value, or {@code null}
+     *         if the value is null or could not be read for some reason.
+     *
+     * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
+     */
+    ParcelFileDescriptor simpleQueryForBlobFileDescriptor();
 }