Skip to content
This repository has been archived by the owner on May 1, 2023. It is now read-only.

Commit

Permalink
support sending back rows changed
Browse files Browse the repository at this point in the history
Previously we would only return a result for sql commands that were
selct statements. This diff makes `DatabasePeerManager` aware of what
commands are being executed and returns a result set appropriate to that
command.

Note: We are returning a result for all commands (including ones that do
not normally contain results like CREATE TABLE). We do this so that the
inspector interface will not remove the command.

Closes #82
  • Loading branch information
longinoa committed Mar 13, 2015
1 parent 32f6c63 commit d7059d3
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 8 deletions.
5 changes: 4 additions & 1 deletion stetho/src/main/java/com/facebook/stetho/Stetho.java
@@ -1,3 +1,5 @@
// Copyright 2015-present Facebook. All Rights Reserved.

package com.facebook.stetho;

import com.facebook.stetho.inspector.database.DefaultDatabaseFilesProvider;
Expand Down Expand Up @@ -26,6 +28,7 @@
import com.facebook.stetho.inspector.protocol.module.DOM;
import com.facebook.stetho.inspector.protocol.module.DOMStorage;
import com.facebook.stetho.inspector.protocol.module.Database;
import com.facebook.stetho.inspector.protocol.module.DatabaseConstants;
import com.facebook.stetho.inspector.protocol.module.Debugger;
import com.facebook.stetho.inspector.protocol.module.HeapProfiler;
import com.facebook.stetho.inspector.protocol.module.Inspector;
Expand Down Expand Up @@ -115,7 +118,7 @@ public Iterable<ChromeDevtoolsDomain> get() {
modules.add(new Profiler());
modules.add(new Runtime());
modules.add(new Worker());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
if (Build.VERSION.SDK_INT >= DatabaseConstants.MIN_API_LEVEL) {
modules.add(new Database(context, new DefaultDatabaseFilesProvider(context)));
}
return modules;
Expand Down
Expand Up @@ -11,16 +11,19 @@
import java.util.ArrayList;
import java.util.List;

import android.annotation.TargetApi;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteStatement;

import com.facebook.stetho.common.Util;
import com.facebook.stetho.inspector.helper.ChromePeerManager;
import com.facebook.stetho.inspector.helper.PeerRegistrationListener;
import com.facebook.stetho.inspector.jsonrpc.JsonRpcPeer;
import com.facebook.stetho.inspector.protocol.module.Database;
import com.facebook.stetho.inspector.protocol.module.DatabaseConstants;

@ThreadSafe
public class DatabasePeerManager extends ChromePeerManager {
Expand Down Expand Up @@ -129,17 +132,67 @@ public <T> T executeSQL(String databaseName, String query, ExecuteResultHandler<
Util.throwIfNull(handler);
SQLiteDatabase database = openDatabase(databaseName);
try {
Cursor cursor = database.rawQuery(query, null);
try {
return handler.handleResult(cursor);
} finally {
cursor.close();
String firstWord = getFirstWord(query);

if (firstWord.equalsIgnoreCase("UPDATE") || firstWord.equalsIgnoreCase("DELETE")) {
return executeUpdateDelete(database, query, handler);
} else if (firstWord.equalsIgnoreCase("INSERT")) {
return executeInsert(database, query, handler);
} else if (firstWord.equalsIgnoreCase("SELECT")) {
return executeSelect(database, query, handler);
} else {
return executeRawQuery(database, query, handler);
}

} finally {
database.close();
}
}

private static String getFirstWord(String s) {
s.trim();
int firstSpace = s.indexOf(' ');
return firstSpace >= 0 ? s.substring(0, firstSpace) : s;
}

@TargetApi(DatabaseConstants.MIN_API_LEVEL)
private <T> T executeUpdateDelete(
SQLiteDatabase database,
String query,
ExecuteResultHandler<T> handler) {
SQLiteStatement statement = database.compileStatement(query);
int count = statement.executeUpdateDelete();
return handler.handleUpdateDelete(count);
}

private <T> T executeInsert(
SQLiteDatabase database,
String query,
ExecuteResultHandler<T> handler) {
SQLiteStatement statement = database.compileStatement(query);
long count = statement.executeInsert();
return handler.handleInsert(count);
}

private <T> T executeSelect(
SQLiteDatabase database,
String query,
ExecuteResultHandler<T> handler) {
Cursor cursor = database.rawQuery(query, null);
try {
return handler.handleSelect(cursor);
} finally {
cursor.close();
}
}

private <T> T executeRawQuery(
SQLiteDatabase database,
String query,
ExecuteResultHandler<T> handler) {
database.execSQL(query);
return handler.handleRawQuery();
}
private SQLiteDatabase openDatabase(String databaseName) throws SQLiteException {
Util.throwIfNull(databaseName);
File databaseFile = mContext.getDatabasePath(databaseName);
Expand All @@ -151,7 +204,13 @@ private SQLiteDatabase openDatabase(String databaseName) throws SQLiteException
}

public interface ExecuteResultHandler<T> {
public T handleResult(Cursor result) throws SQLiteException;
public T handleRawQuery() throws SQLiteException;

public T handleSelect(Cursor result) throws SQLiteException;

public T handleInsert(long insertedId) throws SQLiteException;

public T handleUpdateDelete(int count) throws SQLiteException;
}

private final PeerRegistrationListener mPeerRegistrationListener =
Expand Down
Expand Up @@ -5,6 +5,7 @@
import com.facebook.stetho.inspector.database.DatabaseFilesProvider;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import android.annotation.TargetApi;
Expand Down Expand Up @@ -85,12 +86,38 @@ public JsonRpcResult executeSQL(JsonRpcPeer peer, JSONObject params) {
return mDatabasePeerManager.executeSQL(request.databaseId, request.query,
new DatabasePeerManager.ExecuteResultHandler<ExecuteSQLResponse>() {
@Override
public ExecuteSQLResponse handleResult(Cursor result) throws SQLiteException {
public ExecuteSQLResponse handleRawQuery() throws SQLiteException {
ExecuteSQLResponse response = new ExecuteSQLResponse();
// This is done because the inspector UI likes to delete rows if you give them no
// name/value list
response.columnNames = Arrays.asList("success");
response.values = Arrays.asList((Object) "true");
return response;
}

@Override
public ExecuteSQLResponse handleSelect(Cursor result) throws SQLiteException {
ExecuteSQLResponse response = new ExecuteSQLResponse();
response.columnNames = Arrays.asList(result.getColumnNames());
response.values = flattenRows(result, MAX_EXECUTE_RESULTS);
return response;
}

@Override
public ExecuteSQLResponse handleInsert(long insertedId) throws SQLiteException {
ExecuteSQLResponse response = new ExecuteSQLResponse();
response.columnNames = Arrays.asList("ID of last inserted row");
response.values = Arrays.asList((Object) insertedId);
return response;
}

@Override
public ExecuteSQLResponse handleUpdateDelete(int count) throws SQLiteException {
ExecuteSQLResponse response = new ExecuteSQLResponse();
response.columnNames = Arrays.asList("Modified rows");
response.values = Arrays.asList((Object) count);
return response;
}
});
} catch (SQLiteException e) {
Error error = new Error();
Expand Down
@@ -0,0 +1,13 @@
// Copyright 2015-present Facebook. All Rights Reserved.

package com.facebook.stetho.inspector.protocol.module;

import android.os.Build;

public interface DatabaseConstants {

/**
* Minimum API version required to use the {@link Database}.
*/
public static final int MIN_API_LEVEL = Build.VERSION_CODES.HONEYCOMB;
}

0 comments on commit d7059d3

Please sign in to comment.