Add getTableInfo API to process incoming TableInfo queries
Summary: Getting the "definition" of the database was originally on the GetTableStructure endpoint. This diff moves it to a new GetTableInfo endpoint Reviewed By: jknoxville Differential Revision: D15902619 fbshipit-source-id: ac136d24ee577711366636801b5d74d83fbc523f
This commit is contained in:
committed by
Facebook Github Bot
parent
a2663ea970
commit
f40ac0617c
@@ -45,6 +45,9 @@ public abstract class DatabaseDriver<DESCRIPTOR extends DatabaseDescriptor> {
|
||||
public abstract DatabaseGetTableStructureResponse getTableStructure(
|
||||
DESCRIPTOR databaseDescriptor, String table);
|
||||
|
||||
public abstract DatabaseGetTableInfoResponse getTableInfo(
|
||||
DESCRIPTOR databaseDescriptor, String table);
|
||||
|
||||
public abstract DatabaseExecuteSqlResponse executeSQL(
|
||||
DESCRIPTOR databaseDescriptor, String query);
|
||||
|
||||
@@ -76,18 +79,24 @@ public abstract class DatabaseDriver<DESCRIPTOR extends DatabaseDescriptor> {
|
||||
public final List<List<Object>> structureValues;
|
||||
public final List<String> indexesColumns;
|
||||
public final List<List<Object>> indexesValues;
|
||||
public final String definition;
|
||||
|
||||
public DatabaseGetTableStructureResponse(
|
||||
final List<String> structureColumns,
|
||||
final List<List<Object>> structureValues,
|
||||
final List<String> indexesColumns,
|
||||
final List<List<Object>> indexesValues,
|
||||
String definition) {
|
||||
final List<List<Object>> indexesValues) {
|
||||
this.structureColumns = structureColumns;
|
||||
this.structureValues = structureValues;
|
||||
this.indexesColumns = indexesColumns;
|
||||
this.indexesValues = indexesValues;
|
||||
}
|
||||
}
|
||||
|
||||
public static class DatabaseGetTableInfoResponse {
|
||||
|
||||
public final String definition;
|
||||
|
||||
public DatabaseGetTableInfoResponse(String definition) {
|
||||
this.definition = definition;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.facebook.flipper.core.FlipperReceiver;
|
||||
import com.facebook.flipper.core.FlipperResponder;
|
||||
import com.facebook.flipper.plugins.databases.DatabaseDriver.DatabaseExecuteSqlResponse;
|
||||
import com.facebook.flipper.plugins.databases.DatabaseDriver.DatabaseGetTableDataResponse;
|
||||
import com.facebook.flipper.plugins.databases.DatabaseDriver.DatabaseGetTableInfoResponse;
|
||||
import com.facebook.flipper.plugins.databases.DatabaseDriver.DatabaseGetTableStructureResponse;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
@@ -26,6 +27,7 @@ public class DatabasesManager {
|
||||
private static final String DATABASE_LIST_COMMAND = "databaseList";
|
||||
private static final String GET_TABLE_DATA_COMMAND = "getTableData";
|
||||
private static final String GET_TABLE_STRUCTURE_COMMAND = "getTableStructure";
|
||||
private static final String GET_TABLE_INFO_COMMAND = "getTableInfo";
|
||||
private static final String EXECUTE_COMMAND = "execute";
|
||||
|
||||
private final List<DatabaseDriver> mDatabaseDriverList;
|
||||
@@ -152,7 +154,7 @@ public class DatabasesManager {
|
||||
databaseDescriptorHolder.databaseDescriptor,
|
||||
getTableStructureRequest.table);
|
||||
responder.success(
|
||||
ObjectMapper.databaseGetTableStructureReponseToFlipperObject(
|
||||
ObjectMapper.databaseGetTableStructureResponseToFlipperObject(
|
||||
databaseGetTableStructureResponse));
|
||||
} catch (Exception e) {
|
||||
responder.error(
|
||||
@@ -163,6 +165,43 @@ public class DatabasesManager {
|
||||
}
|
||||
}
|
||||
});
|
||||
connection.receive(
|
||||
GET_TABLE_INFO_COMMAND,
|
||||
new FlipperReceiver() {
|
||||
@Override
|
||||
public void onReceive(FlipperObject params, FlipperResponder responder) {
|
||||
GetTableInfoRequest getTableInfoRequest =
|
||||
ObjectMapper.flipperObjectToGetTableInfoRequest(params);
|
||||
if (getTableInfoRequest == null) {
|
||||
responder.error(
|
||||
ObjectMapper.toErrorFlipperObject(
|
||||
DatabasesErrorCodes.ERROR_INVALID_REQUEST,
|
||||
DatabasesErrorCodes.ERROR_INVALID_REQUEST_MESSAGE));
|
||||
} else {
|
||||
DatabaseDescriptorHolder databaseDescriptorHolder =
|
||||
mDatabaseDescriptorHolderSparseArray.get(getTableInfoRequest.databaseId);
|
||||
if (databaseDescriptorHolder == null) {
|
||||
responder.error(
|
||||
ObjectMapper.toErrorFlipperObject(
|
||||
DatabasesErrorCodes.ERROR_DATABASE_INVALID,
|
||||
DatabasesErrorCodes.ERROR_DATABASE_INVALID_MESSAGE));
|
||||
} else {
|
||||
try {
|
||||
DatabaseGetTableInfoResponse databaseGetTableInfoResponse =
|
||||
databaseDescriptorHolder.databaseDriver.getTableInfo(
|
||||
databaseDescriptorHolder.databaseDescriptor, getTableInfoRequest.table);
|
||||
responder.success(
|
||||
ObjectMapper.databaseGetTableInfoResponseToFlipperObject(
|
||||
databaseGetTableInfoResponse));
|
||||
} catch (Exception e) {
|
||||
responder.error(
|
||||
ObjectMapper.toErrorFlipperObject(
|
||||
DatabasesErrorCodes.ERROR_SQL_EXECUTION_EXCEPTION, e.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
connection.receive(
|
||||
EXECUTE_COMMAND,
|
||||
new FlipperReceiver() {
|
||||
@@ -257,4 +296,15 @@ public class DatabasesManager {
|
||||
this.table = table;
|
||||
}
|
||||
}
|
||||
|
||||
static class GetTableInfoRequest {
|
||||
|
||||
public final int databaseId;
|
||||
public final String table;
|
||||
|
||||
GetTableInfoRequest(int databaseId, String table) {
|
||||
this.databaseId = databaseId;
|
||||
this.table = table;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,10 +12,12 @@ import com.facebook.flipper.core.FlipperArray.Builder;
|
||||
import com.facebook.flipper.core.FlipperObject;
|
||||
import com.facebook.flipper.plugins.databases.DatabaseDriver.DatabaseExecuteSqlResponse;
|
||||
import com.facebook.flipper.plugins.databases.DatabaseDriver.DatabaseGetTableDataResponse;
|
||||
import com.facebook.flipper.plugins.databases.DatabaseDriver.DatabaseGetTableInfoResponse;
|
||||
import com.facebook.flipper.plugins.databases.DatabaseDriver.DatabaseGetTableStructureResponse;
|
||||
import com.facebook.flipper.plugins.databases.DatabasesManager.DatabaseDescriptorHolder;
|
||||
import com.facebook.flipper.plugins.databases.DatabasesManager.ExecuteSqlRequest;
|
||||
import com.facebook.flipper.plugins.databases.DatabasesManager.GetTableDataRequest;
|
||||
import com.facebook.flipper.plugins.databases.DatabasesManager.GetTableInfoRequest;
|
||||
import com.facebook.flipper.plugins.databases.DatabasesManager.GetTableStructureRequest;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Collection;
|
||||
@@ -76,6 +78,15 @@ public class ObjectMapper {
|
||||
return new GetTableStructureRequest(databaseId, table);
|
||||
}
|
||||
|
||||
public static GetTableInfoRequest flipperObjectToGetTableInfoRequest(FlipperObject params) {
|
||||
int databaseId = params.getInt("databaseId");
|
||||
String table = params.getString("table");
|
||||
if (databaseId <= 0 || TextUtils.isEmpty(table)) {
|
||||
return null;
|
||||
}
|
||||
return new GetTableInfoRequest(databaseId, table);
|
||||
}
|
||||
|
||||
public static ExecuteSqlRequest flipperObjectToExecuteSqlRequest(FlipperObject params) {
|
||||
int databaseId = params.getInt("databaseId");
|
||||
String value = params.getString("value");
|
||||
@@ -111,7 +122,7 @@ public class ObjectMapper {
|
||||
.build();
|
||||
}
|
||||
|
||||
public static FlipperObject databaseGetTableStructureReponseToFlipperObject(
|
||||
public static FlipperObject databaseGetTableStructureResponseToFlipperObject(
|
||||
DatabaseGetTableStructureResponse databaseGetTableStructureResponse) {
|
||||
|
||||
FlipperArray.Builder structureColumnBuilder = new FlipperArray.Builder();
|
||||
@@ -147,7 +158,14 @@ public class ObjectMapper {
|
||||
.put("structureValues", structureValuesBuilder.build())
|
||||
.put("indexesColumns", indexesColumnBuilder.build())
|
||||
.put("indexesValues", indexesValuesBuilder.build())
|
||||
.put("definition", databaseGetTableStructureResponse.definition)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static FlipperObject databaseGetTableInfoResponseToFlipperObject(
|
||||
DatabaseGetTableInfoResponse databaseGetTableInfoResponse) {
|
||||
|
||||
return new FlipperObject.Builder()
|
||||
.put("definition", databaseGetTableInfoResponse.definition)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -171,9 +171,7 @@ public class SqliteDatabaseDriver extends DatabaseDriver<SqliteDatabaseDescripto
|
||||
Cursor structureCursor = database.rawQuery("PRAGMA table_info(" + table + ")", null);
|
||||
Cursor foreignKeysCursor = database.rawQuery("PRAGMA foreign_key_list(" + table + ")", null);
|
||||
Cursor indexesCursor = database.rawQuery("PRAGMA index_list(" + table + ")", null);
|
||||
Cursor definitionCursor =
|
||||
database.rawQuery(
|
||||
"SELECT sql FROM " + SCHEMA_TABLE + " WHERE name=?", new String[] {table});
|
||||
|
||||
try {
|
||||
// Structure & foreign keys
|
||||
|
||||
@@ -234,13 +232,9 @@ public class SqliteDatabaseDriver extends DatabaseDriver<SqliteDatabaseDescripto
|
||||
}
|
||||
}
|
||||
|
||||
// Definition
|
||||
|
||||
definitionCursor.moveToFirst();
|
||||
String definition = definitionCursor.getString(definitionCursor.getColumnIndex("sql"));
|
||||
|
||||
return new DatabaseGetTableStructureResponse(
|
||||
structureColumns, structureValues, indexesColumns, indexesValues, definition);
|
||||
structureColumns, structureValues, indexesColumns, indexesValues);
|
||||
|
||||
} finally {
|
||||
structureCursor.close();
|
||||
foreignKeysCursor.close();
|
||||
@@ -251,6 +245,31 @@ public class SqliteDatabaseDriver extends DatabaseDriver<SqliteDatabaseDescripto
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseGetTableInfoResponse getTableInfo(
|
||||
SqliteDatabaseDescriptor databaseDescriptor, String table) {
|
||||
SQLiteDatabase database =
|
||||
sqliteDatabaseConnectionProvider.openDatabase(databaseDescriptor.file);
|
||||
try {
|
||||
|
||||
Cursor definitionCursor =
|
||||
database.rawQuery(
|
||||
"SELECT sql FROM " + SCHEMA_TABLE + " WHERE name=?", new String[] {table});
|
||||
try {
|
||||
|
||||
// Definition
|
||||
definitionCursor.moveToFirst();
|
||||
String definition = definitionCursor.getString(definitionCursor.getColumnIndex("sql"));
|
||||
|
||||
return new DatabaseGetTableInfoResponse(definition);
|
||||
} finally {
|
||||
definitionCursor.close();
|
||||
}
|
||||
} finally {
|
||||
database.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static List<File> tidyDatabaseList(List<File> databaseFiles) {
|
||||
Set<File> originalAsSet = new HashSet<>(databaseFiles);
|
||||
List<File> tidiedList = new ArrayList<>();
|
||||
|
||||
@@ -12,7 +12,6 @@ import static org.junit.Assert.assertThat;
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import com.facebook.flipper.core.FlipperArray;
|
||||
import com.facebook.flipper.core.FlipperObject;
|
||||
import com.facebook.flipper.plugins.databases.DatabaseDriver.DatabaseExecuteSqlResponse;
|
||||
@@ -29,6 +28,7 @@ import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Ignore
|
||||
@@ -45,28 +45,26 @@ public class DatabasesFlipperPluginTest {
|
||||
connectionMock = new FlipperConnectionMock();
|
||||
responderMock = new FlipperResponderMock();
|
||||
|
||||
databaseHelper1 =
|
||||
new DatabaseHelper(ApplicationProvider.getApplicationContext(), "database1.db");
|
||||
databaseHelper1 = new DatabaseHelper(RuntimeEnvironment.application, "database1.db");
|
||||
databaseHelper1
|
||||
.getWritableDatabase()
|
||||
.execSQL("INSERT INTO first_table (column1, column2) VALUES('a','b')");
|
||||
databaseHelper2 =
|
||||
new DatabaseHelper(ApplicationProvider.getApplicationContext(), "database2.db");
|
||||
databaseHelper2 = new DatabaseHelper(RuntimeEnvironment.application, "database2.db");
|
||||
databaseHelper2
|
||||
.getWritableDatabase()
|
||||
.execSQL("INSERT INTO first_table (column1, column2) VALUES('a','b')");
|
||||
plugin =
|
||||
new DatabasesFlipperPlugin(
|
||||
new SqliteDatabaseDriver(
|
||||
ApplicationProvider.getApplicationContext(),
|
||||
RuntimeEnvironment.application,
|
||||
new SqliteDatabaseProvider() {
|
||||
@Override
|
||||
public List<File> getDatabaseFiles() {
|
||||
return Arrays.asList(
|
||||
ApplicationProvider.getApplicationContext()
|
||||
.getDatabasePath(databaseHelper1.getDatabaseName()),
|
||||
ApplicationProvider.getApplicationContext()
|
||||
.getDatabasePath(databaseHelper2.getDatabaseName()));
|
||||
RuntimeEnvironment.application.getDatabasePath(
|
||||
databaseHelper1.getDatabaseName()),
|
||||
RuntimeEnvironment.application.getDatabasePath(
|
||||
databaseHelper2.getDatabaseName()));
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -76,8 +74,8 @@ public class DatabasesFlipperPluginTest {
|
||||
@After
|
||||
public void tearDown() {
|
||||
databaseHelper1.close();
|
||||
ApplicationProvider.getApplicationContext().deleteDatabase(databaseHelper1.getDatabaseName());
|
||||
ApplicationProvider.getApplicationContext().deleteDatabase(databaseHelper2.getDatabaseName());
|
||||
RuntimeEnvironment.application.deleteDatabase(databaseHelper1.getDatabaseName());
|
||||
RuntimeEnvironment.application.deleteDatabase(databaseHelper2.getDatabaseName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -361,6 +359,27 @@ public class DatabasesFlipperPluginTest {
|
||||
.put("value", "column1,column2"))
|
||||
.build())
|
||||
.build())
|
||||
.build()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCommandGetTableInfo() throws Exception {
|
||||
// Arrange
|
||||
connectionMock.receivers.get("databaseList").onReceive(null, responderMock); // Load data
|
||||
|
||||
// Act
|
||||
connectionMock
|
||||
.receivers
|
||||
.get("getTableInfo")
|
||||
.onReceive(
|
||||
new FlipperObject.Builder().put("databaseId", 1).put("table", "first_table").build(),
|
||||
responderMock);
|
||||
|
||||
// Assert
|
||||
assertThat(
|
||||
responderMock.successes,
|
||||
hasItem(
|
||||
new FlipperObject.Builder()
|
||||
.put(
|
||||
"definition",
|
||||
"CREATE TABLE first_table (_id INTEGER PRIMARY KEY AUTOINCREMENT,column1 TEXT,column2 TEXT)")
|
||||
|
||||
Reference in New Issue
Block a user