aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHector Dearman <hjd@google.com>2023-01-28 16:22:51 +0000
committerHector Dearman <hjd@google.com>2023-01-28 16:22:51 +0000
commitb9395b94af6436f0459e169f06393fa03535cd05 (patch)
treeea37ad34f818821106a0b9e28eb58b02dc03653a
parent07e128e9a2a37507a7db1de743b7b1b3e27cc930 (diff)
downloadperfetto-b9395b94af6436f0459e169f06393fa03535cd05.tar.gz
ui: Add support for BLOB cells in SQL results
Bug: 201664880 Change-Id: Ib9d2b7d96c36341049fd3e14c9f789305a2462c2
-rw-r--r--ui/src/common/query_result.ts52
-rw-r--r--ui/src/controller/aggregation/aggregation_controller.ts2
-rw-r--r--ui/src/frontend/pivot_table_redux.ts2
-rw-r--r--ui/src/frontend/query_table.ts7
4 files changed, 45 insertions, 18 deletions
diff --git a/ui/src/common/query_result.ts b/ui/src/common/query_result.ts
index bae847d17..9d44c9ea7 100644
--- a/ui/src/common/query_result.ts
+++ b/ui/src/common/query_result.ts
@@ -57,8 +57,10 @@ export const NUM = 0;
export const STR = 'str';
export const NUM_NULL: number|null = 1;
export const STR_NULL: string|null = 'str_null';
+export const BLOB: Uint8Array = new Uint8Array();
+export const BLOB_NULL: Uint8Array|null = new Uint8Array();
-export type ColumnType = string|number|null;
+export type ColumnType = string|number|null|Uint8Array;
// Info that could help debug a query error. For example the query
// in question, the stack where the query was issued, the active
@@ -119,11 +121,32 @@ function columnTypeToString(t: ColumnType): string {
return 'STR';
case STR_NULL:
return 'STR_NULL';
+ case BLOB:
+ return 'BLOB';
+ case BLOB_NULL:
+ return 'BLOB_NULL';
default:
return `INVALID(${t})`;
}
}
+function isCompatible(actual: CellType, expected: ColumnType): boolean {
+ switch (actual) {
+ case CellType.CELL_NULL:
+ return expected === NUM_NULL || expected === STR_NULL ||
+ expected === BLOB_NULL;
+ case CellType.CELL_VARINT:
+ case CellType.CELL_FLOAT64:
+ return expected === NUM || expected === NUM_NULL;
+ case CellType.CELL_STRING:
+ return expected === STR || expected === STR_NULL;
+ case CellType.CELL_BLOB:
+ return expected === BLOB || expected === BLOB_NULL;
+ default:
+ throw new Error(`Unknown CellType ${actual}`);
+ }
+}
+
// Disable Long.js support in protobuf. This seems to be enabled only in tests
// but not in production code. In any case, for now we want casting to number
// accepting the 2**53 limitation. This is consistent with passing
@@ -652,8 +675,7 @@ class RowIteratorImpl implements RowIteratorBase {
case CellType.CELL_BLOB:
const blob = this.blobCells[this.nextBlobCell++];
- throw new Error(`TODO implement BLOB support (${blob})`);
- // outRow[colName] = blob;
+ rowData[colName] = blob;
break;
default:
@@ -721,20 +743,16 @@ class RowIteratorImpl implements RowIteratorBase {
if (expType === undefined) continue;
let err = '';
- if (actualType === CellType.CELL_NULL &&
- (expType !== STR_NULL && expType !== NUM_NULL)) {
- err = 'SQL value is NULL but that was not expected' +
- ` (expected type: ${columnTypeToString(expType)}). ` +
- 'Did you intend to use NUM_NULL or STR_NULL?';
- } else if (
- ((actualType === CellType.CELL_VARINT ||
- actualType === CellType.CELL_FLOAT64) &&
- (expType !== NUM && expType !== NUM_NULL)) ||
- ((actualType === CellType.CELL_STRING) &&
- (expType !== STR && expType !== STR_NULL))) {
- err = `Incompatible cell type. Expected: ${
- columnTypeToString(
- expType)} actual: ${CELL_TYPE_NAMES[actualType]}`;
+ if (!isCompatible(actualType, expType)) {
+ if (actualType === CellType.CELL_NULL) {
+ err = 'SQL value is NULL but that was not expected' +
+ ` (expected type: ${columnTypeToString(expType)}). ` +
+ 'Did you intend to use NUM_NULL, STR_NULL or BLOB_NULL?';
+ } else {
+ err = `Incompatible cell type. Expected: ${
+ columnTypeToString(
+ expType)} actual: ${CELL_TYPE_NAMES[actualType]}`;
+ }
}
if (err.length > 0) {
throw new Error(
diff --git a/ui/src/controller/aggregation/aggregation_controller.ts b/ui/src/controller/aggregation/aggregation_controller.ts
index 0510ca0b8..4fa1ecc94 100644
--- a/ui/src/controller/aggregation/aggregation_controller.ts
+++ b/ui/src/controller/aggregation/aggregation_controller.ts
@@ -146,6 +146,8 @@ export abstract class AggregationController extends Controller<'main'> {
column.data[i] = isStringColumn(column) ? internString('NULL') : 0;
} else if (typeof item === 'string') {
column.data[i] = internString(item);
+ } else if (item instanceof Uint8Array) {
+ column.data[i] = internString('<Binary blob>');
} else {
column.data[i] = item;
}
diff --git a/ui/src/frontend/pivot_table_redux.ts b/ui/src/frontend/pivot_table_redux.ts
index e1c880c82..3caaf33e1 100644
--- a/ui/src/frontend/pivot_table_redux.ts
+++ b/ui/src/frontend/pivot_table_redux.ts
@@ -85,6 +85,8 @@ function renderDrillFilter(filter: DrillFilter): string {
return `${column} IS NULL`;
} else if (typeof filter.value === 'number') {
return `${column} = ${filter.value}`;
+ } else if (filter.value instanceof Uint8Array) {
+ throw new Error(`BLOB as DrillFilter not implemented`);
}
return `${column} = ${sqliteString(filter.value)}`;
}
diff --git a/ui/src/frontend/query_table.ts b/ui/src/frontend/query_table.ts
index ff240d9b1..2469b2483 100644
--- a/ui/src/frontend/query_table.ts
+++ b/ui/src/frontend/query_table.ts
@@ -79,7 +79,12 @@ class QueryTableRow implements m.ClassComponent<QueryTableRowAttrs> {
const cells = [];
const {row, columns} = vnode.attrs;
for (const col of columns) {
- cells.push(m('td', row[col]));
+ const value = row[col];
+ if (value instanceof Uint8Array) {
+ cells.push(m('td', `<BLOB sz=${value.length}>`));
+ } else {
+ cells.push(m('td', value));
+ }
}
const containsSliceLocation =
QueryTableRow.columnsContainsSliceLocation(columns);