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(
|
public abstract DatabaseGetTableStructureResponse getTableStructure(
|
||||||
DESCRIPTOR databaseDescriptor, String table);
|
DESCRIPTOR databaseDescriptor, String table);
|
||||||
|
|
||||||
|
public abstract DatabaseGetTableInfoResponse getTableInfo(
|
||||||
|
DESCRIPTOR databaseDescriptor, String table);
|
||||||
|
|
||||||
public abstract DatabaseExecuteSqlResponse executeSQL(
|
public abstract DatabaseExecuteSqlResponse executeSQL(
|
||||||
DESCRIPTOR databaseDescriptor, String query);
|
DESCRIPTOR databaseDescriptor, String query);
|
||||||
|
|
||||||
@@ -76,18 +79,24 @@ public abstract class DatabaseDriver<DESCRIPTOR extends DatabaseDescriptor> {
|
|||||||
public final List<List<Object>> structureValues;
|
public final List<List<Object>> structureValues;
|
||||||
public final List<String> indexesColumns;
|
public final List<String> indexesColumns;
|
||||||
public final List<List<Object>> indexesValues;
|
public final List<List<Object>> indexesValues;
|
||||||
public final String definition;
|
|
||||||
|
|
||||||
public DatabaseGetTableStructureResponse(
|
public DatabaseGetTableStructureResponse(
|
||||||
final List<String> structureColumns,
|
final List<String> structureColumns,
|
||||||
final List<List<Object>> structureValues,
|
final List<List<Object>> structureValues,
|
||||||
final List<String> indexesColumns,
|
final List<String> indexesColumns,
|
||||||
final List<List<Object>> indexesValues,
|
final List<List<Object>> indexesValues) {
|
||||||
String definition) {
|
|
||||||
this.structureColumns = structureColumns;
|
this.structureColumns = structureColumns;
|
||||||
this.structureValues = structureValues;
|
this.structureValues = structureValues;
|
||||||
this.indexesColumns = indexesColumns;
|
this.indexesColumns = indexesColumns;
|
||||||
this.indexesValues = indexesValues;
|
this.indexesValues = indexesValues;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DatabaseGetTableInfoResponse {
|
||||||
|
|
||||||
|
public final String definition;
|
||||||
|
|
||||||
|
public DatabaseGetTableInfoResponse(String definition) {
|
||||||
this.definition = definition;
|
this.definition = definition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import com.facebook.flipper.core.FlipperReceiver;
|
|||||||
import com.facebook.flipper.core.FlipperResponder;
|
import com.facebook.flipper.core.FlipperResponder;
|
||||||
import com.facebook.flipper.plugins.databases.DatabaseDriver.DatabaseExecuteSqlResponse;
|
import com.facebook.flipper.plugins.databases.DatabaseDriver.DatabaseExecuteSqlResponse;
|
||||||
import com.facebook.flipper.plugins.databases.DatabaseDriver.DatabaseGetTableDataResponse;
|
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.DatabaseDriver.DatabaseGetTableStructureResponse;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -26,6 +27,7 @@ public class DatabasesManager {
|
|||||||
private static final String DATABASE_LIST_COMMAND = "databaseList";
|
private static final String DATABASE_LIST_COMMAND = "databaseList";
|
||||||
private static final String GET_TABLE_DATA_COMMAND = "getTableData";
|
private static final String GET_TABLE_DATA_COMMAND = "getTableData";
|
||||||
private static final String GET_TABLE_STRUCTURE_COMMAND = "getTableStructure";
|
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 static final String EXECUTE_COMMAND = "execute";
|
||||||
|
|
||||||
private final List<DatabaseDriver> mDatabaseDriverList;
|
private final List<DatabaseDriver> mDatabaseDriverList;
|
||||||
@@ -152,7 +154,7 @@ public class DatabasesManager {
|
|||||||
databaseDescriptorHolder.databaseDescriptor,
|
databaseDescriptorHolder.databaseDescriptor,
|
||||||
getTableStructureRequest.table);
|
getTableStructureRequest.table);
|
||||||
responder.success(
|
responder.success(
|
||||||
ObjectMapper.databaseGetTableStructureReponseToFlipperObject(
|
ObjectMapper.databaseGetTableStructureResponseToFlipperObject(
|
||||||
databaseGetTableStructureResponse));
|
databaseGetTableStructureResponse));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
responder.error(
|
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(
|
connection.receive(
|
||||||
EXECUTE_COMMAND,
|
EXECUTE_COMMAND,
|
||||||
new FlipperReceiver() {
|
new FlipperReceiver() {
|
||||||
@@ -257,4 +296,15 @@ public class DatabasesManager {
|
|||||||
this.table = table;
|
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.core.FlipperObject;
|
||||||
import com.facebook.flipper.plugins.databases.DatabaseDriver.DatabaseExecuteSqlResponse;
|
import com.facebook.flipper.plugins.databases.DatabaseDriver.DatabaseExecuteSqlResponse;
|
||||||
import com.facebook.flipper.plugins.databases.DatabaseDriver.DatabaseGetTableDataResponse;
|
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.DatabaseDriver.DatabaseGetTableStructureResponse;
|
||||||
import com.facebook.flipper.plugins.databases.DatabasesManager.DatabaseDescriptorHolder;
|
import com.facebook.flipper.plugins.databases.DatabasesManager.DatabaseDescriptorHolder;
|
||||||
import com.facebook.flipper.plugins.databases.DatabasesManager.ExecuteSqlRequest;
|
import com.facebook.flipper.plugins.databases.DatabasesManager.ExecuteSqlRequest;
|
||||||
import com.facebook.flipper.plugins.databases.DatabasesManager.GetTableDataRequest;
|
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 com.facebook.flipper.plugins.databases.DatabasesManager.GetTableStructureRequest;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -76,6 +78,15 @@ public class ObjectMapper {
|
|||||||
return new GetTableStructureRequest(databaseId, table);
|
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) {
|
public static ExecuteSqlRequest flipperObjectToExecuteSqlRequest(FlipperObject params) {
|
||||||
int databaseId = params.getInt("databaseId");
|
int databaseId = params.getInt("databaseId");
|
||||||
String value = params.getString("value");
|
String value = params.getString("value");
|
||||||
@@ -111,7 +122,7 @@ public class ObjectMapper {
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FlipperObject databaseGetTableStructureReponseToFlipperObject(
|
public static FlipperObject databaseGetTableStructureResponseToFlipperObject(
|
||||||
DatabaseGetTableStructureResponse databaseGetTableStructureResponse) {
|
DatabaseGetTableStructureResponse databaseGetTableStructureResponse) {
|
||||||
|
|
||||||
FlipperArray.Builder structureColumnBuilder = new FlipperArray.Builder();
|
FlipperArray.Builder structureColumnBuilder = new FlipperArray.Builder();
|
||||||
@@ -147,7 +158,14 @@ public class ObjectMapper {
|
|||||||
.put("structureValues", structureValuesBuilder.build())
|
.put("structureValues", structureValuesBuilder.build())
|
||||||
.put("indexesColumns", indexesColumnBuilder.build())
|
.put("indexesColumns", indexesColumnBuilder.build())
|
||||||
.put("indexesValues", indexesValuesBuilder.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();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -171,9 +171,7 @@ public class SqliteDatabaseDriver extends DatabaseDriver<SqliteDatabaseDescripto
|
|||||||
Cursor structureCursor = database.rawQuery("PRAGMA table_info(" + table + ")", null);
|
Cursor structureCursor = database.rawQuery("PRAGMA table_info(" + table + ")", null);
|
||||||
Cursor foreignKeysCursor = database.rawQuery("PRAGMA foreign_key_list(" + table + ")", null);
|
Cursor foreignKeysCursor = database.rawQuery("PRAGMA foreign_key_list(" + table + ")", null);
|
||||||
Cursor indexesCursor = database.rawQuery("PRAGMA index_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 {
|
try {
|
||||||
// Structure & foreign keys
|
// 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(
|
return new DatabaseGetTableStructureResponse(
|
||||||
structureColumns, structureValues, indexesColumns, indexesValues, definition);
|
structureColumns, structureValues, indexesColumns, indexesValues);
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
structureCursor.close();
|
structureCursor.close();
|
||||||
foreignKeysCursor.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) {
|
private static List<File> tidyDatabaseList(List<File> databaseFiles) {
|
||||||
Set<File> originalAsSet = new HashSet<>(databaseFiles);
|
Set<File> originalAsSet = new HashSet<>(databaseFiles);
|
||||||
List<File> tidiedList = new ArrayList<>();
|
List<File> tidiedList = new ArrayList<>();
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import static org.junit.Assert.assertThat;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.database.sqlite.SQLiteOpenHelper;
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
|
||||||
import com.facebook.flipper.core.FlipperArray;
|
import com.facebook.flipper.core.FlipperArray;
|
||||||
import com.facebook.flipper.core.FlipperObject;
|
import com.facebook.flipper.core.FlipperObject;
|
||||||
import com.facebook.flipper.plugins.databases.DatabaseDriver.DatabaseExecuteSqlResponse;
|
import com.facebook.flipper.plugins.databases.DatabaseDriver.DatabaseExecuteSqlResponse;
|
||||||
@@ -29,6 +28,7 @@ import org.junit.Ignore;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
import org.robolectric.RuntimeEnvironment;
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
@Ignore
|
@Ignore
|
||||||
@@ -45,28 +45,26 @@ public class DatabasesFlipperPluginTest {
|
|||||||
connectionMock = new FlipperConnectionMock();
|
connectionMock = new FlipperConnectionMock();
|
||||||
responderMock = new FlipperResponderMock();
|
responderMock = new FlipperResponderMock();
|
||||||
|
|
||||||
databaseHelper1 =
|
databaseHelper1 = new DatabaseHelper(RuntimeEnvironment.application, "database1.db");
|
||||||
new DatabaseHelper(ApplicationProvider.getApplicationContext(), "database1.db");
|
|
||||||
databaseHelper1
|
databaseHelper1
|
||||||
.getWritableDatabase()
|
.getWritableDatabase()
|
||||||
.execSQL("INSERT INTO first_table (column1, column2) VALUES('a','b')");
|
.execSQL("INSERT INTO first_table (column1, column2) VALUES('a','b')");
|
||||||
databaseHelper2 =
|
databaseHelper2 = new DatabaseHelper(RuntimeEnvironment.application, "database2.db");
|
||||||
new DatabaseHelper(ApplicationProvider.getApplicationContext(), "database2.db");
|
|
||||||
databaseHelper2
|
databaseHelper2
|
||||||
.getWritableDatabase()
|
.getWritableDatabase()
|
||||||
.execSQL("INSERT INTO first_table (column1, column2) VALUES('a','b')");
|
.execSQL("INSERT INTO first_table (column1, column2) VALUES('a','b')");
|
||||||
plugin =
|
plugin =
|
||||||
new DatabasesFlipperPlugin(
|
new DatabasesFlipperPlugin(
|
||||||
new SqliteDatabaseDriver(
|
new SqliteDatabaseDriver(
|
||||||
ApplicationProvider.getApplicationContext(),
|
RuntimeEnvironment.application,
|
||||||
new SqliteDatabaseProvider() {
|
new SqliteDatabaseProvider() {
|
||||||
@Override
|
@Override
|
||||||
public List<File> getDatabaseFiles() {
|
public List<File> getDatabaseFiles() {
|
||||||
return Arrays.asList(
|
return Arrays.asList(
|
||||||
ApplicationProvider.getApplicationContext()
|
RuntimeEnvironment.application.getDatabasePath(
|
||||||
.getDatabasePath(databaseHelper1.getDatabaseName()),
|
databaseHelper1.getDatabaseName()),
|
||||||
ApplicationProvider.getApplicationContext()
|
RuntimeEnvironment.application.getDatabasePath(
|
||||||
.getDatabasePath(databaseHelper2.getDatabaseName()));
|
databaseHelper2.getDatabaseName()));
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -76,8 +74,8 @@ public class DatabasesFlipperPluginTest {
|
|||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
databaseHelper1.close();
|
databaseHelper1.close();
|
||||||
ApplicationProvider.getApplicationContext().deleteDatabase(databaseHelper1.getDatabaseName());
|
RuntimeEnvironment.application.deleteDatabase(databaseHelper1.getDatabaseName());
|
||||||
ApplicationProvider.getApplicationContext().deleteDatabase(databaseHelper2.getDatabaseName());
|
RuntimeEnvironment.application.deleteDatabase(databaseHelper2.getDatabaseName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -361,6 +359,27 @@ public class DatabasesFlipperPluginTest {
|
|||||||
.put("value", "column1,column2"))
|
.put("value", "column1,column2"))
|
||||||
.build())
|
.build())
|
||||||
.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(
|
.put(
|
||||||
"definition",
|
"definition",
|
||||||
"CREATE TABLE first_table (_id INTEGER PRIMARY KEY AUTOINCREMENT,column1 TEXT,column2 TEXT)")
|
"CREATE TABLE first_table (_id INTEGER PRIMARY KEY AUTOINCREMENT,column1 TEXT,column2 TEXT)")
|
||||||
|
|||||||
Reference in New Issue
Block a user