赞
踩
类搜索范围:android.database.sqlite:SQLiteDatabase,SQLiteStatement,SQLiteClosable,SQLiteProgram,SQLiteSession,SQLiteConnectionPool,SQLiteConnection&android.database.DatabaseUtils
查询分两步,第一步获取 Cursor,第二步使用 Cursor 获取数据
第一步不会真的去查数据库,第二步才会。
第一步的调用栈:
android.database.sqlite.SQLiteCursorDriver.query::CursorFactory,String: 由子类函数实现:
android.database.sqlite.SQLiteDirectCursorDriver.query::CursorFactory,String:,但这个函数并没有进行查询。
下面是这个子类函数的源码,可以看出来,它除了 new 对象什么也没有干。
public Cursor query(CursorFactory factory, String[] selectionArgs) { final SQLiteQuery query = new SQLiteQuery(mDatabase, mSql, mCancellationSignal); final Cursor cursor; try { query.bindAllArgsAsStrings(selectionArgs); if (factory == null) { cursor = new SQLiteCursor(this, mEditTable, query); } else { cursor = factory.newCursor(mDatabase, this, mEditTable, query); } } catch (RuntimeException ex) { query.close(); throw ex; } mQuery = query; return cursor; }
第二步的调用栈,以SQLiteCursor.getCount()为例:
什么是 CursorWindow 呢?源码文档中的解释:
* A buffer containing multiple cursor rows.
* <p>
* A {@link CursorWindow} is read-write when initially created and used locally.
* When sent to a remote process (by writing it to a {@link Parcel}), the remote process
* receives a read-only view of the cursor window. Typically the cursor window
* will be allocated by the producer, filled with data, and then sent to the
* consumer for reading.
* </p>
下面我们看看你传给的 SQL 语句是如何被消费的:
看看函数 android.database.sqlite.SQLiteConnection.executeForChangedRowCount::String,Object,CancellationSignal: 的注释:
/** * Executes a statement that returns a count of the number of rows * that were changed. Use for UPDATE or DELETE SQL statements. * * @param sql The SQL statement to execute. * @param bindArgs The arguments to bind, or null if none. * @param cancellationSignal A signal to cancel the operation in progress, or null if none. * @return The number of rows that were changed. * * @throws SQLiteException if an error occurs, such as a syntax error * or invalid number of bind arguments. * @throws OperationCanceledException if the operation was canceled. */ public int executeForChangedRowCount(String sql, Object[] bindArgs, CancellationSignal cancellationSignal) { 。。。。。。 } // 这个函数没有注释,但它是与 c++ 层代码的接口函数,因为有 native 修饰,表示它是 c++ 实现 private static native int nativeExecuteForChangedRowCount(long connectionPtr, long statementPtr);
这个函数明确表明自己是用于 UPDATE 或者 DELETE 一类的 SQL 语句,也就是说这个调用栈不适用于创建表与删除表的操作。
下面我们看看你传给的 SQL 语句是如何被消费的:
函数 android.database.sqlite.SQLiteConnection.executeForChangedRowCount::String,Object,CancellationSignal:Parameter1 把你的 SQL 语句传给 android.database.sqlite.SQLiteConnection.acquirePreparedStatement::String:Parameter1,使它从一个字符串变成一个 android.database.sqlite.SQLiteConnection.PreparedStatement 对象,这个对象拥有一个指针指向 c++ 层的一个对象,后面对 PreparedStatement 对象的处理就由 c++ 层完成了。
希望你能看懂下面的图
看看函数 android.database.sqlite.SQLiteStatement.execute::: 的注释:
/** * Execute this SQL statement, if it is not a SELECT / INSERT / DELETE / UPDATE, for example * CREATE / DROP table, view, trigger, index etc. * * @throws android.database.SQLException If the SQL string is invalid for * some reason */ public void execute() { acquireReference(); try { getSession().execute(getSql(), getBindArgs(), getConnectionFlags(), null); } catch (SQLiteDatabaseCorruptException ex) { onCorruption(); throw ex; } finally { releaseReference(); } }
这里明确说明是执行 CREATE / DROP table, view, trigger, index etc. 的SQL 语句。
函数 android.database.sqlite.SQLiteDatabase.execSQL::String,Object: 的注释:
/** * Execute a single SQL statement that is NOT a SELECT/INSERT/UPDATE/DELETE. * <p> * For INSERT statements, use any of the following instead. * <ul> * <li>{@link #insert(String, String, ContentValues)}</li> * <li>{@link #insertOrThrow(String, String, ContentValues)}</li> * <li>{@link #insertWithOnConflict(String, String, ContentValues, int)}</li> * </ul> * <p> * For UPDATE statements, use any of the following instead. * <ul> * <li>{@link #update(String, ContentValues, String, String[])}</li> * <li>{@link #updateWithOnConflict(String, ContentValues, String, String[], int)}</li> * </ul> * <p> * For DELETE statements, use any of the following instead. * <ul> * <li>{@link #delete(String, String, String[])}</li> * </ul> * <p> * For example, the following are good candidates for using this method: * <ul> * <li>ALTER TABLE</li> * <li>CREATE or DROP table / trigger / view / index / virtual table</li> * <li>REINDEX</li> * <li>RELEASE</li> * <li>SAVEPOINT</li> * <li>PRAGMA that returns no data</li> * </ul> * </p> * <p> * When using {@link #enableWriteAheadLogging()}, journal_mode is * automatically managed by this class. So, do not set journal_mode * using "PRAGMA journal_mode'<value>" statement if your app is using * {@link #enableWriteAheadLogging()} * </p> * * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are * not supported. * @param bindArgs only byte[], String, Long and Double are supported in bindArgs. * @throws SQLException if the SQL string is invalid */ public void execSQL(String sql, Object[] bindArgs) throws SQLException { 。。。。。。 }
函数 android.database.DatabaseUtils.stringForQuery::SQLiteDatabase,String,String: 的注释:
/**
* Utility method to run the query on the db and return the value in the
* first column of the first row.
*/
public static String stringForQuery(SQLiteDatabase db, String query, String[] selectionArgs) {
SQLiteStatement prog = db.compileStatement(query);
try {
return stringForQuery(prog, selectionArgs);
} finally {
prog.close();
}
}
它返回查询结果的第一行第一列(first column of the first row)。如果你的表的第一个字段不是字符串类型呢?这个我只能猜它会把其它类型的数据转成字符串类型给你吧。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。