Line data Source code
1 : import type * as dashql from '@ankoh/dashql-core';
2 :
3 1 : function terminateStatement(text: string): string {
4 1 : return text.endsWith(';') ? text : `${text};`;
5 1 : }
6 :
7 : /// Split SQL into its statements, keeping SQL that does not parse as a single statement
8 1 : function splitSql(core: dashql.DashQL, catalog: dashql.DashQLCatalog, sql: string, out: string[]) {
9 1 : const trimmed = sql.trim();
10 1 : if (trimmed.length === 0) return;
11 :
12 1 : const bytes = new TextEncoder().encode(sql);
13 1 : const decoder = new TextDecoder();
14 1 : const script = core.createScript(catalog);
15 1 : let parsed: dashql.FlatBufferPtr<dashql.buffers.parser.ParsedScript> | null = null;
16 1 : try {
17 1 : script.replaceText(sql);
18 1 : script.parse();
19 1 : parsed = script.getParsed();
20 1 : const reader = parsed.read();
21 1 : if (reader.scannerErrorsLength() > 0 || reader.parserErrorsLength() > 0 || reader.statementsLength() === 0) {
22 1 : out.push(terminateStatement(trimmed));
23 1 : return;
24 1 : }
25 1 : for (let i = 0; i < reader.statementsLength(); ++i) {
26 1 : const span = reader.statements(i)!.statementSpan();
27 1 : if (!span) continue;
28 1 : const text = decoder.decode(bytes.subarray(span.offset(), span.offset() + span.length())).trim();
29 1 : if (text.length > 0) out.push(terminateStatement(text));
30 1 : }
31 1 : } finally {
32 1 : script.destroy();
33 1 : }
34 1 : }
35 :
36 : /// Split a script into the prompts the shell offers one after another, e.g. a shared script or a snippet.
37 : /// Lines starting with a dot are shell commands, everything between them is SQL.
38 1 : export function splitShellScript(core: dashql.DashQL, catalog: dashql.DashQLCatalog, script: string): string[] {
39 1 : const out: string[] = [];
40 1 : let sql: string[] = [];
41 1 : for (const line of script.split(/\r?\n/)) {
42 1 : const trimmed = line.trim();
43 1 : if (trimmed.startsWith('.')) {
44 1 : splitSql(core, catalog, sql.join('\n'), out);
45 1 : sql = [];
46 1 : out.push(trimmed);
47 1 : } else {
48 1 : sql.push(line);
49 : }
50 1 : }
51 1 : splitSql(core, catalog, sql.join('\n'), out);
52 1 : return out;
53 1 : }
|