• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2018 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15import {EngineProxy} from './engine';
16import {Row} from './query_result';
17
18const MAX_DISPLAY_ROWS = 10000;
19
20export interface QueryResponse {
21  query: string;
22  error?: string;
23  totalRowCount: number;
24  durationMs: number;
25  columns: string[];
26  rows: Row[];
27  statementCount: number;
28  statementWithOutputCount: number;
29}
30
31export async function runQuery(
32    sqlQuery: string, engine: EngineProxy): Promise<QueryResponse> {
33  const startMs = performance.now();
34  const queryRes = engine.query(sqlQuery);
35
36  // TODO(primiano): once the controller thread is gone we should pass down
37  // the result objects directly to the frontend, iterate over the result
38  // and deal with pagination there. For now we keep the old behavior and
39  // truncate to 10k rows.
40
41  try {
42    await queryRes.waitAllRows();
43  } catch {
44    // In the case of a query error we don't want the exception to bubble up
45    // as a crash. The |queryRes| object will be populated anyways.
46    // queryRes.error() is used to tell if the query errored or not. If it
47    // errored, the frontend will show a graceful message instead.
48  }
49
50  const durationMs = performance.now() - startMs;
51  const rows: Row[] = [];
52  const columns = queryRes.columns();
53  let numRows = 0;
54  for (const iter = queryRes.iter({}); iter.valid(); iter.next()) {
55    const row: Row = {};
56    for (const colName of columns) {
57      const value = iter.get(colName);
58      row[colName] = value === null ? 'NULL' : value;
59    }
60    rows.push(row);
61    if (++numRows >= MAX_DISPLAY_ROWS) break;
62  }
63
64  const result: QueryResponse = {
65    query: sqlQuery,
66    durationMs,
67    error: queryRes.error(),
68    totalRowCount: queryRes.numRows(),
69    columns,
70    rows,
71    statementCount: queryRes.statementCount(),
72    statementWithOutputCount: queryRes.statementWithOutputCount(),
73  };
74  return result;
75}
76