Регистрация SQL-запросов в android

Я использую функции query для создания SQL-запросов для моих таблиц. Есть ли способ увидеть фактический запрос, который запущен? Например, зарегистрируйте его где-нибудь?

Пока что лучшее, что я мог сделать, это посмотреть на элемент mQuery курсора, используя точку останова. Я бы хотел, чтобы вывести запросы автоматически. Этот член, конечно, не является публичным и не имеет геттера.


Только для записи, вот реализация принятого ответа.

 /** * Implement the cursor factory in order to log the queries before returning * the cursor * * @author Vincent @ MarvinLabs */ public class SQLiteCursorFactory implements CursorFactory { private boolean debugQueries = false; public SQLiteCursorFactory() { this.debugQueries = false; } public SQLiteCursorFactory(boolean debugQueries) { this.debugQueries = debugQueries; } @Override public Cursor newCursor(SQLiteDatabase db, SQLiteCursorDriver masterQuery, String editTable, SQLiteQuery query) { if (debugQueries) { Log.d("SQL", query.toString()); } return new SQLiteCursor(db, masterQuery, editTable, query); } } 

Вы можете применить свой собственный SQLiteDatabase.CursorFactory к базе данных. (См. Параметры openDatabase .) Это позволит вам создать собственный подclass Cursor , который сохраняет запрос в легко доступном поле.

edit : На самом деле вам может даже не потребоваться подclass Cursor . Просто используйте метод newCursor() вашего завода для стандартного SQLiteCursor , но прежде чем делать это, SQLiteCursor запрос.

 adb shell setprop log.tag.SQLiteStatements VERBOSE 

Не забудьте перезапустить приложение после установки этого свойства.

Также возможно включить протоколирование времени выполнения. Более подробная информация доступна здесь: http://androidxref.com/4.2.2_r1/xref/frameworks/base/core/java/android/database/sqlite/SQLiteDebug.java

  adb shell setprop log.tag.SQLiteLog V
 adb shell setprop log.tag.SQLiteStatements V
 остановка оболочки adb
 запуск оболочки adb 

Использование SQLiteQueryBuilder очень просто. buildQuery() возвращает необработанную строку sql, которая затем может быть зарегистрирована:

 SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); qb.setTables(ExampleTable.TABLE_NAME); String sql = qb.buildQuery(projection, selection, null, null, sortOrder, null); Log.d("Example", sql); 

Пока что лучшее, что я мог сделать, это посмотреть на элемент mQuery курсора, используя точку останова. Этот член, конечно, не является публичным и не имеет геттера, следовательно, не может его выводить. Любое лучшее предложение?

Если это сценарий отключен, я бы предложил ввести ошибку (например, введите выражение, подобное LIEK, а не LIKE!) И наблюдайте за Eclipse LogCat за любые ошибки! НТН!

Если вы используете SQLiteDatabase со стандартными методами, поскольку вставка, обновление и удаление пользовательского CursorFactory не будут работать.

Я реализовал свое не очень большое, но рабочее решение, основанное на classе SQLiteDatabase. Он просто повторяет логику методов вставки, обновления и удаления, но без операторов и фактически выполняет ведение журнала SQL-запросов.

 public class SQLiteStatementsLogger { private static final String TAG = SQLiteStatementsLogger.class.getSimpleName(); private static final String[] CONFLICT_VALUES = new String[] {"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "}; public void logInsert(String table, String nullColumnHack, ContentValues values) { logInsertWithOnConflict(table, nullColumnHack, values, 0); } public static void logInsertWithOnConflict(String table, String nullColumnHack, ContentValues initialValues, int conflictAlgorithm) { StringBuilder sql = new StringBuilder(); sql.append("INSERT"); sql.append(CONFLICT_VALUES[conflictAlgorithm]); sql.append(" INTO "); sql.append(table); sql.append('('); Object[] bindArgs = null; int size = (initialValues != null && initialValues.size() > 0) ? initialValues.size() : 0; if (size > 0) { bindArgs = new Object[size]; int i = 0; for (String colName : initialValues.keySet()) { sql.append((i > 0) ? "," : ""); sql.append(colName); bindArgs[i++] = initialValues.get(colName); } sql.append(')'); sql.append(" VALUES ("); for (i = 0; i < size; i++) { sql.append((i > 0) ? ",?" : "?"); } } else { sql.append(nullColumnHack + ") VALUES (NULL"); } sql.append(')'); sql.append(". ("); for (Object arg : bindArgs) { sql.append(String.valueOf(arg)).append(","); } sql.deleteCharAt(sql.length()-1).append(')'); Log.d(TAG, sql.toString()); } public static void logUpdate(String table, ContentValues values, String whereClause, String[] whereArgs) { logUpdateWithOnConflict(table, values, whereClause, whereArgs, 0); } public static void logUpdateWithOnConflict(String table, ContentValues values, String whereClause, String[] whereArgs, int conflictAlgorithm) { StringBuilder sql = new StringBuilder(120); sql.append("UPDATE "); sql.append(CONFLICT_VALUES[conflictAlgorithm]); sql.append(table); sql.append(" SET "); // move all bind args to one array int setValuesSize = values.size(); int bindArgsSize = (whereArgs == null) ? setValuesSize : (setValuesSize + whereArgs.length); Object[] bindArgs = new Object[bindArgsSize]; int i = 0; for (String colName : values.keySet()) { sql.append((i > 0) ? "," : ""); sql.append(colName); bindArgs[i++] = values.get(colName); sql.append("=?"); } if (whereArgs != null) { for (i = setValuesSize; i < bindArgsSize; i++) { bindArgs[i] = whereArgs[i - setValuesSize]; } } if (!TextUtils.isEmpty(whereClause)) { sql.append(" WHERE "); sql.append(whereClause); } sql.append(". ("); for (Object arg : bindArgs) { sql.append(String.valueOf(arg)).append(","); } sql.deleteCharAt(sql.length()-1).append(')'); Log.d(TAG, sql.toString()); } public static void logDelete(String table, String whereClause, String[] whereArgs) { StringBuilder sql = new StringBuilder("DELETE FROM " + table); if (!TextUtils.isEmpty(whereClause)) { sql.append(" WHERE " + whereClause); sql.append(". ("); for (Object arg : whereArgs) { sql.append(String.valueOf(arg)).append(","); } sql.deleteCharAt(sql.length()-1).append(')'); } Log.d(TAG, sql.toString()); } } 

Имейте в виду не использовать регистратор в версиях выпуска. Это может увеличить время выполнения запросов. Вы можете проверить, работает ли assembly в режиме отладки с помощью этой строки кода:

 0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) 

Если вы используете ContentProvider для доступа к БД, вот как я получил его ведение журнала запросов. Не идеальное решение, но оно работает для развития

 @Override public boolean onCreate() { dbHelper = new MySQLiteHelper(getContext()); database=dbHelper.getWritableDatabase(); if(!database.isReadOnly()) database.execSQL("PRAGMA foreign_keys=ON;"); return true; } SQLiteDatabase.CursorFactory cursorFactory = new SQLiteDatabase.CursorFactory() { @Override public Cursor newCursor(SQLiteDatabase db, SQLiteCursorDriver masterQuery, String editTable, SQLiteQuery query) { Log.d(TAG, "Query: "+query); return new SQLiteCursor(db, masterQuery, editTable, query); } }; @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { String table =getTableName(uri); if(Constants.LOG_QUERIES){ database = SQLiteDatabase.openOrCreateDatabase(database.getPath(), cursorFactory); } Cursor cursor =database.query(table, projection, selection, selectionArgs, null, null, sortOrder); cursor.moveToFirst(); return cursor; } 

Он выкинет исключение DatabaseNotClosed, но вы сможете увидеть запрос

Я Log.w("MYAPPNAME", "My text...") регистрирую текст, используя функции java.util.Log и Log.w("MYAPPNAME", "My text...") . Он отображается в представлении журнала Eclipse и может быть отфильтрован для вывода только журналов для «MYAPPNAME».

  • heroku - как просмотреть все журналы
  • Создать учетную запись, Забыли пароль и сменить пароль
  • Настройка ведения журнала для Java-драйвера MongoDB
  • Как читать растущий текстовый файл на C ++?
  • Firebase Cloud Messaging - управление токенами регистрации
  • Давайте будем гением компьютера.