[go: nahoru, domu]

Column names moved to QueryResponse object

This allows e.g. to retrieve column names for empty result sets.
It is valid since column names are shared among all result rows.

Bug: 143216096
Test: ./gradlew :sqlite:sqlite-inspection:cC

Change-Id: I6869b5ef26861b0a53e8061029935835f22e3acf
diff --git a/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/QueryTest.kt b/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/QueryTest.kt
index d4a98fb..16508d9 100644
--- a/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/QueryTest.kt
+++ b/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/QueryTest.kt
@@ -111,7 +111,7 @@
     }
 
     @Test
-    fun test_nested_query_with_a_comment() {
+    fun test_valid_query_nested_query_with_a_comment() {
         test_valid_query(
             Database("db", table2),
             values = listOf(
@@ -126,6 +126,45 @@
         )
     }
 
+    @Test
+    fun test_valid_query_empty_result_column_names_present() {
+        test_valid_query(
+            Database("db", table2),
+            values = listOf(
+                table2 to arrayOf("1", "'A'"),
+                table2 to arrayOf("2", "'B'")
+            ),
+            query = "select * from ${table2.name} where 1=0", // impossible condition
+            expectedValues = emptyList(),
+            expectedTypes = emptyList(),
+            expectedColumnNames = table2.columns.map { it.name }
+        )
+    }
+
+    @Test
+    fun test_valid_query_missing_column_values() {
+        test_valid_query(
+            Database("db", table2),
+            values = listOf(
+                table2 to arrayOf("1", "'A'"),
+                table2 to arrayOf("null", "null"),
+                table2 to arrayOf("null", "'C'")
+            ),
+            query = "select * from ${table2.name}",
+            expectedValues = listOf(
+                listOf(1, "A"),
+                listOf(null, null),
+                listOf(null, "C")
+            ),
+            expectedTypes = listOf(
+                listOf("integer", "text"),
+                listOf("null", "null"),
+                listOf("null", "text")
+            ),
+            expectedColumnNames = table2.columns.map { it.name }
+        )
+    }
+
     /** Union of two queries (different column names) resulting in using first query columns. */
     @Test
     fun test_valid_query_two_table_union() {
@@ -183,12 +222,13 @@
         // when
         issueQuery(databaseId, query).let { response ->
             // then
+            assertThat(response.rowsCount).isEqualTo(expectedValues.size)
+            assertThat(response.columnNamesList).isEqualTo(expectedColumnNames)
             response.rowsList.let { actualRows: List<Row> ->
                 actualRows.forEachIndexed { rowIx, row ->
                     row.valuesList.forEachIndexed { colIx, cell ->
                         assertThat(cell.value).isEqualTo(expectedValues[rowIx][colIx])
                         assertThat(cell.type).isEqualTo(expectedTypes[rowIx][colIx])
-                        assertThat(cell.columnName).isEqualTo(expectedColumnNames[colIx])
                     }
                 }
             }
diff --git a/sqlite/sqlite-inspection/src/main/java/androidx/sqlite/inspection/SqliteInspector.java b/sqlite/sqlite-inspection/src/main/java/androidx/sqlite/inspection/SqliteInspector.java
index 1960216..c3101df 100644
--- a/sqlite/sqlite-inspection/src/main/java/androidx/sqlite/inspection/SqliteInspector.java
+++ b/sqlite/sqlite-inspection/src/main/java/androidx/sqlite/inspection/SqliteInspector.java
@@ -47,6 +47,7 @@
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -166,8 +167,12 @@
 
         Cursor cursor = database.rawQuery(command.getQuery(), null);
         try {
+            List<String> columnNames = Arrays.asList(cursor.getColumnNames());
             callback.reply(Response.newBuilder()
-                    .setQuery(QueryResponse.newBuilder().addAllRows(convert(cursor)).build())
+                    .setQuery(QueryResponse.newBuilder()
+                            .addAllRows(convert(cursor))
+                            .addAllColumnNames(columnNames)
+                            .build())
                     .build()
                     .toByteArray()
             );
@@ -209,7 +214,6 @@
     private static CellValue readValue(Cursor cursor, int index) {
         CellValue.Builder builder = CellValue.newBuilder();
 
-        builder.setColumnName(cursor.getColumnName(index));
         switch (cursor.getType(index)) {
             case Cursor.FIELD_TYPE_NULL:
                 // no field to set
diff --git a/sqlite/sqlite-inspection/src/main/proto/live_sql_protocol.proto b/sqlite/sqlite-inspection/src/main/proto/live_sql_protocol.proto
index a98c6e2..94e8661 100644
--- a/sqlite/sqlite-inspection/src/main/proto/live_sql_protocol.proto
+++ b/sqlite/sqlite-inspection/src/main/proto/live_sql_protocol.proto
@@ -98,6 +98,8 @@
 // Object expected as a response to QueryCommand.
 message QueryResponse {
   repeated Row rows = 1;
+  // Names of columns in the result set
+  repeated string column_names = 2;
 }
 
 // Query result row.
@@ -114,8 +116,6 @@
     string string_value = 3;
     bytes blob_value = 4;
   }
-  // Name of the column containing the cell
-  string column_name = 5;
 }
 
 // General Error message.