documents.js 1.63.0 → 1.65.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +124 -25
- package/dist/convert/convert.cjs +3 -3
- package/dist/convert/convert.d.cts +5 -2
- package/dist/convert/convert.d.ts +4 -1
- package/dist/convert/convert.js +3 -3
- package/dist/edit/docx/content.d.cts +1 -1
- package/dist/edit/docx/content.d.ts +1 -1
- package/dist/edit/docx/paragraph.d.cts +3 -3
- package/dist/edit/docx/paragraph.d.ts +3 -3
- package/dist/edit/ods/address.cjs +42 -24
- package/dist/edit/ods/address.d.cts +12 -2
- package/dist/edit/ods/address.d.ts +12 -2
- package/dist/edit/ods/address.js +39 -25
- package/dist/edit/ods/column-row.cjs +68 -6
- package/dist/edit/ods/column-row.d.cts +5 -1
- package/dist/edit/ods/column-row.d.ts +5 -1
- package/dist/edit/ods/column-row.js +68 -10
- package/dist/edit/ods/content.cjs +10 -2
- package/dist/edit/ods/content.js +10 -2
- package/dist/edit/ods/floating.cjs +90 -0
- package/dist/edit/ods/floating.d.cts +7 -0
- package/dist/edit/ods/floating.d.ts +7 -0
- package/dist/edit/ods/floating.js +88 -0
- package/dist/edit/ods/print-settings.cjs +158 -2
- package/dist/edit/ods/print-settings.js +159 -3
- package/dist/edit/ods/sheet.cjs +13 -0
- package/dist/edit/ods/sheet.d.cts +5 -1
- package/dist/edit/ods/sheet.d.ts +5 -1
- package/dist/edit/ods/sheet.js +14 -1
- package/dist/edit/odt/content.cjs +8 -4
- package/dist/edit/odt/content.js +8 -4
- package/dist/edit/odt/editor.cjs +7 -0
- package/dist/edit/odt/editor.d.cts +3 -0
- package/dist/edit/odt/editor.d.ts +3 -0
- package/dist/edit/odt/editor.js +7 -0
- package/dist/edit/odt/formula.cjs +19 -0
- package/dist/edit/odt/formula.d.cts +8 -0
- package/dist/edit/odt/formula.d.ts +8 -0
- package/dist/edit/odt/formula.js +17 -0
- package/dist/evaluate-BU5N1Jk1.d.ts +11 -0
- package/dist/evaluate-BhMXY6DM.d.cts +11 -0
- package/dist/firebird/backup.d.cts +1 -1
- package/dist/firebird/backup.d.ts +1 -1
- package/dist/firebird/data.cjs +30 -16
- package/dist/firebird/data.d.cts +3 -2
- package/dist/firebird/data.d.ts +3 -2
- package/dist/firebird/data.js +30 -17
- package/dist/fonts/ooxml.d.cts +1 -1
- package/dist/fonts/registry.d.cts +1 -1
- package/dist/formula-CgydMiTt.d.ts +10 -0
- package/dist/formula-CiwPw8nY.d.cts +10 -0
- package/dist/hsqldb/binary-script.d.cts +1 -1
- package/dist/hsqldb/binary-script.d.ts +1 -1
- package/dist/hsqldb/cache.d.cts +1 -1
- package/dist/hsqldb/cache.d.ts +1 -1
- package/dist/hsqldb/rowformat.cjs +22 -13
- package/dist/hsqldb/rowformat.js +22 -13
- package/dist/hsqldb/script.d.cts +1 -18
- package/dist/hsqldb/script.d.ts +1 -18
- package/dist/index.cjs +56 -0
- package/dist/index.d.cts +24 -10
- package/dist/index.d.ts +23 -9
- package/dist/index.js +15 -2
- package/dist/layout/sheets.cjs +30 -24
- package/dist/layout/sheets.js +31 -25
- package/dist/layout/slides.cjs +6 -4
- package/dist/layout/slides.js +7 -5
- package/dist/lexer-DGPWx_f2.d.cts +42 -0
- package/dist/lexer-DGPWx_f2.d.ts +42 -0
- package/dist/mathml/compose.cjs +8 -0
- package/dist/mathml/compose.js +8 -0
- package/dist/mathml/layout-types.d.cts +14 -2
- package/dist/mathml/layout-types.d.ts +14 -2
- package/dist/mathml/layout.cjs +62 -3
- package/dist/mathml/layout.d.cts +1 -1
- package/dist/mathml/layout.d.ts +1 -1
- package/dist/mathml/layout.js +62 -3
- package/dist/mathml/metrics.d.cts +17 -1
- package/dist/mathml/metrics.d.ts +17 -1
- package/dist/mathml/operators.cjs +1 -1
- package/dist/mathml/operators.js +1 -1
- package/dist/mathml/variant.d.cts +1 -6
- package/dist/mathml/variant.d.ts +1 -6
- package/dist/odb/csv.d.cts +1 -1
- package/dist/odb/csv.d.ts +1 -1
- package/dist/odb/formula/definition.cjs +49 -0
- package/dist/odb/formula/definition.d.cts +8 -0
- package/dist/odb/formula/definition.d.ts +8 -0
- package/dist/odb/formula/definition.js +46 -0
- package/dist/odb/formula/errors.cjs +47 -0
- package/dist/odb/formula/errors.d.cts +21 -0
- package/dist/odb/formula/errors.d.ts +21 -0
- package/dist/odb/formula/errors.js +43 -0
- package/dist/odb/formula/evaluate.cjs +283 -0
- package/dist/odb/formula/evaluate.d.cts +43 -0
- package/dist/odb/formula/evaluate.d.ts +43 -0
- package/dist/odb/formula/evaluate.js +281 -0
- package/dist/odb/formula/parser.cjs +198 -0
- package/dist/odb/formula/parser.d.cts +29 -0
- package/dist/odb/formula/parser.d.ts +29 -0
- package/dist/odb/formula/parser.js +197 -0
- package/dist/odb/read.d.cts +1 -1
- package/dist/odb/read.d.ts +1 -1
- package/dist/odb/report/content.cjs +27 -0
- package/dist/odb/report/content.d.cts +14 -0
- package/dist/odb/report/content.d.ts +14 -0
- package/dist/odb/report/content.js +25 -0
- package/dist/odb/report/render.cjs +106 -0
- package/dist/odb/report/render.d.cts +7 -0
- package/dist/odb/report/render.d.ts +7 -0
- package/dist/odb/report/render.js +106 -0
- package/dist/odb/report/source.cjs +45 -0
- package/dist/odb/report/source.d.cts +14 -0
- package/dist/odb/report/source.d.ts +14 -0
- package/dist/odb/report/source.js +42 -0
- package/dist/odb/spreadsheet.d.cts +1 -1
- package/dist/odb/spreadsheet.d.ts +1 -1
- package/dist/odb/sql/errors.cjs +38 -0
- package/dist/odb/sql/errors.d.cts +17 -0
- package/dist/odb/sql/errors.d.ts +17 -0
- package/dist/odb/sql/errors.js +35 -0
- package/dist/odb/sql/evaluate.cjs +312 -0
- package/dist/odb/sql/evaluate.d.cts +2 -0
- package/dist/odb/sql/evaluate.d.ts +2 -0
- package/dist/odb/sql/evaluate.js +311 -0
- package/dist/odb/sql/lexer.cjs +282 -0
- package/dist/odb/sql/lexer.d.cts +2 -0
- package/dist/odb/sql/lexer.d.ts +2 -0
- package/dist/odb/sql/lexer.js +281 -0
- package/dist/odb/sql/parser.cjs +479 -0
- package/dist/odb/sql/parser.d.cts +2 -0
- package/dist/odb/sql/parser.d.ts +2 -0
- package/dist/odb/sql/parser.js +478 -0
- package/dist/odb/values.cjs +75 -0
- package/dist/odb/values.d.cts +2 -0
- package/dist/odb/values.d.ts +2 -0
- package/dist/odb/values.js +69 -0
- package/dist/odf/odt/read.cjs +43 -21
- package/dist/odf/odt/read.js +43 -21
- package/dist/odf-package/formula.cjs +59 -0
- package/dist/odf-package/formula.d.cts +11 -0
- package/dist/odf-package/formula.d.ts +11 -0
- package/dist/odf-package/formula.js +58 -0
- package/dist/odf-package/manifest.cjs +29 -0
- package/dist/odf-package/manifest.d.cts +5 -2
- package/dist/odf-package/manifest.d.ts +5 -2
- package/dist/odf-package/manifest.js +30 -2
- package/dist/odf-package/media.cjs +2 -1
- package/dist/odf-package/media.js +2 -2
- package/dist/omml/read.cjs +265 -0
- package/dist/omml/read.d.cts +12 -0
- package/dist/omml/read.d.ts +12 -0
- package/dist/omml/read.js +263 -0
- package/dist/omml/shared.cjs +67 -0
- package/dist/omml/shared.d.cts +2 -0
- package/dist/omml/shared.d.ts +2 -0
- package/dist/omml/shared.js +64 -0
- package/dist/omml/write.cjs +3 -51
- package/dist/omml/write.d.cts +2 -2
- package/dist/omml/write.d.ts +2 -2
- package/dist/omml/write.js +1 -49
- package/dist/ooxml/docx/extras.cjs +15 -0
- package/dist/ooxml/docx/extras.d.cts +12 -0
- package/dist/ooxml/docx/extras.d.ts +12 -0
- package/dist/ooxml/docx/extras.js +14 -0
- package/dist/ooxml/docx/formula.cjs +109 -0
- package/dist/ooxml/docx/formula.d.cts +2 -0
- package/dist/ooxml/docx/formula.d.ts +2 -0
- package/dist/ooxml/docx/formula.js +108 -0
- package/dist/ooxml/docx/read.cjs +10 -2
- package/dist/ooxml/docx/read.d.cts +6 -2
- package/dist/ooxml/docx/read.d.ts +6 -2
- package/dist/ooxml/docx/read.js +11 -3
- package/dist/parser-B9vC1T6T.d.cts +101 -0
- package/dist/parser-DQSgYJzQ.d.ts +101 -0
- package/dist/{registry-CtPhMD0f.d.cts → registry-lqJej0Jr.d.cts} +1 -1
- package/dist/script-DsGGIzGU.d.cts +19 -0
- package/dist/script-DsGGIzGU.d.ts +19 -0
- package/dist/shared-DLZ3IQUl.d.cts +15 -0
- package/dist/shared-DUOzjwcL.d.ts +15 -0
- package/dist/values-BetetbaH.d.cts +23 -0
- package/dist/values-BetetbaH.d.ts +23 -0
- package/dist/variant-BMrebjMw.d.cts +7 -0
- package/dist/variant-BMrebjMw.d.ts +7 -0
- package/dist/{write-DuyfnbL_.d.cts → write-BQ6SK8r8.d.cts} +2 -6
- package/dist/{write-Zqwx6pka.d.ts → write-THs7ipBq.d.ts} +2 -6
- package/package.json +2 -2
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
import { HsqldbSqlParseError, HsqldbSqlUnsupportedError } from "./errors.js";
|
|
2
|
+
import { tokenizeSql } from "./lexer.js";
|
|
3
|
+
//#region src/odb/sql/parser.ts
|
|
4
|
+
const AGGREGATE_FUNCTIONS = /* @__PURE__ */ new Set([
|
|
5
|
+
"COUNT",
|
|
6
|
+
"SUM",
|
|
7
|
+
"AVG",
|
|
8
|
+
"MIN",
|
|
9
|
+
"MAX"
|
|
10
|
+
]);
|
|
11
|
+
function isAggregateFunction(keyword) {
|
|
12
|
+
return AGGREGATE_FUNCTIONS.has(keyword);
|
|
13
|
+
}
|
|
14
|
+
const OUT_OF_SCOPE_KEYWORDS = /* @__PURE__ */ new Map([
|
|
15
|
+
["JOIN", "a JOIN"],
|
|
16
|
+
["INNER", "a JOIN"],
|
|
17
|
+
["OUTER", "a JOIN"],
|
|
18
|
+
["LEFT", "a JOIN"],
|
|
19
|
+
["RIGHT", "a JOIN"],
|
|
20
|
+
["FULL", "a JOIN"],
|
|
21
|
+
["CROSS", "a JOIN"],
|
|
22
|
+
["NATURAL", "a JOIN"],
|
|
23
|
+
["ON", "a JOIN"],
|
|
24
|
+
["USING", "a JOIN"],
|
|
25
|
+
["UNION", "UNION"],
|
|
26
|
+
["INTERSECT", "INTERSECT"],
|
|
27
|
+
["EXCEPT", "EXCEPT"],
|
|
28
|
+
["MINUS", "EXCEPT (MINUS)"],
|
|
29
|
+
["DISTINCT", "DISTINCT"],
|
|
30
|
+
["ALL", "the ALL quantifier"],
|
|
31
|
+
["HAVING", "HAVING"],
|
|
32
|
+
["LIMIT", "a row-limit clause (LIMIT)"],
|
|
33
|
+
["OFFSET", "a row-limit clause (OFFSET)"],
|
|
34
|
+
["FETCH", "a row-limit clause (FETCH)"],
|
|
35
|
+
["TOP", "a row-limit clause (TOP)"],
|
|
36
|
+
["AS", "a column or table alias (AS)"],
|
|
37
|
+
["CASE", "a CASE expression"],
|
|
38
|
+
["WHEN", "a CASE expression"],
|
|
39
|
+
["THEN", "a CASE expression"],
|
|
40
|
+
["ELSE", "a CASE expression"],
|
|
41
|
+
["END", "a CASE expression"],
|
|
42
|
+
["EXISTS", "an EXISTS subquery"],
|
|
43
|
+
["ANY", "a quantified subquery predicate (ANY)"],
|
|
44
|
+
["SOME", "a quantified subquery predicate (SOME)"],
|
|
45
|
+
["WITH", "a common table expression (WITH)"],
|
|
46
|
+
["INTO", "a SELECT ... INTO clause"],
|
|
47
|
+
["INSERT", "a non-SELECT statement (INSERT)"],
|
|
48
|
+
["UPDATE", "a non-SELECT statement (UPDATE)"],
|
|
49
|
+
["DELETE", "a non-SELECT statement (DELETE)"],
|
|
50
|
+
["CREATE", "a non-SELECT statement (CREATE)"],
|
|
51
|
+
["DROP", "a non-SELECT statement (DROP)"],
|
|
52
|
+
["ALTER", "a non-SELECT statement (ALTER)"],
|
|
53
|
+
["ESCAPE", "a LIKE ... ESCAPE clause"],
|
|
54
|
+
["COLLATE", "a COLLATE clause"],
|
|
55
|
+
["NULLS", "an ORDER BY NULLS FIRST/LAST clause"]
|
|
56
|
+
]);
|
|
57
|
+
function describeToken(token) {
|
|
58
|
+
switch (token.kind) {
|
|
59
|
+
case "keyword": return `keyword "${token.keyword}"`;
|
|
60
|
+
case "identifier": return `identifier "${token.text}"`;
|
|
61
|
+
case "string": return `string literal ${token.text}`;
|
|
62
|
+
case "number": return `numeric literal ${token.text}`;
|
|
63
|
+
case "operator": return `operator "${token.operator}"`;
|
|
64
|
+
case "punctuation": return `"${token.punctuation}"`;
|
|
65
|
+
case "end": return "end of statement";
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function rejectOutOfScopeConstructs(tokens, sql) {
|
|
69
|
+
tokens.forEach((token, index) => {
|
|
70
|
+
if (token.kind === "keyword") {
|
|
71
|
+
const construct = OUT_OF_SCOPE_KEYWORDS.get(token.keyword);
|
|
72
|
+
if (construct !== void 0) throw new HsqldbSqlUnsupportedError(construct, sql);
|
|
73
|
+
if (token.keyword === "SELECT" && index > 0) throw new HsqldbSqlUnsupportedError("a subquery", sql);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (token.kind === "identifier") {
|
|
77
|
+
const next = tokens[index + 1];
|
|
78
|
+
if (next?.kind === "punctuation" && next.punctuation === "(") throw new HsqldbSqlUnsupportedError(`a scalar function (${token.text})`, sql);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
var SqlParser = class {
|
|
83
|
+
tokens;
|
|
84
|
+
sql;
|
|
85
|
+
index = 0;
|
|
86
|
+
constructor(sql) {
|
|
87
|
+
this.sql = sql;
|
|
88
|
+
this.tokens = tokenizeSql(sql);
|
|
89
|
+
rejectOutOfScopeConstructs(this.tokens, sql);
|
|
90
|
+
}
|
|
91
|
+
peek() {
|
|
92
|
+
const token = this.tokens[this.index];
|
|
93
|
+
if (token === void 0) throw new HsqldbSqlParseError("unexpected end of statement", this.sql, this.sql.length);
|
|
94
|
+
return token;
|
|
95
|
+
}
|
|
96
|
+
advance() {
|
|
97
|
+
const token = this.peek();
|
|
98
|
+
if (token.kind !== "end") this.index += 1;
|
|
99
|
+
return token;
|
|
100
|
+
}
|
|
101
|
+
fail(expected) {
|
|
102
|
+
const token = this.peek();
|
|
103
|
+
throw new HsqldbSqlParseError(`expected ${expected}, found ${describeToken(token)}`, this.sql, token.start);
|
|
104
|
+
}
|
|
105
|
+
atKeyword(keyword) {
|
|
106
|
+
const token = this.peek();
|
|
107
|
+
return token.kind === "keyword" && token.keyword === keyword;
|
|
108
|
+
}
|
|
109
|
+
atPunctuation(punctuation) {
|
|
110
|
+
const token = this.peek();
|
|
111
|
+
return token.kind === "punctuation" && token.punctuation === punctuation;
|
|
112
|
+
}
|
|
113
|
+
takeKeyword(keyword) {
|
|
114
|
+
if (!this.atKeyword(keyword)) this.fail(`keyword ${keyword}`);
|
|
115
|
+
this.advance();
|
|
116
|
+
}
|
|
117
|
+
takePunctuation(punctuation) {
|
|
118
|
+
if (!this.atPunctuation(punctuation)) this.fail(`"${punctuation}"`);
|
|
119
|
+
this.advance();
|
|
120
|
+
}
|
|
121
|
+
takeName(what) {
|
|
122
|
+
const token = this.peek();
|
|
123
|
+
if (token.kind !== "identifier") this.fail(what);
|
|
124
|
+
this.advance();
|
|
125
|
+
return {
|
|
126
|
+
name: token.name,
|
|
127
|
+
quoted: token.quoted
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
parseColumnRef() {
|
|
131
|
+
const start = this.peek().start;
|
|
132
|
+
const first = this.takeName("a column name");
|
|
133
|
+
if (this.atPunctuation(".")) {
|
|
134
|
+
this.advance();
|
|
135
|
+
return {
|
|
136
|
+
qualifier: first,
|
|
137
|
+
column: this.takeName("a column name after \".\""),
|
|
138
|
+
text: this.sql.slice(start, this.previousEnd())
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
qualifier: void 0,
|
|
143
|
+
column: first,
|
|
144
|
+
text: this.sql.slice(start, this.previousEnd())
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
previousEnd() {
|
|
148
|
+
const previous = this.tokens[this.index - 1];
|
|
149
|
+
if (previous === void 0) throw new HsqldbSqlParseError("unexpected end of statement", this.sql, this.sql.length);
|
|
150
|
+
return previous.start + previous.text.length;
|
|
151
|
+
}
|
|
152
|
+
parseAggregate(aggregate) {
|
|
153
|
+
this.advance();
|
|
154
|
+
this.takePunctuation("(");
|
|
155
|
+
if (this.atPunctuation("*")) {
|
|
156
|
+
if (aggregate !== "COUNT") this.fail(`a column name -- ${aggregate}(*) is not valid SQL, only COUNT(*) is`);
|
|
157
|
+
this.advance();
|
|
158
|
+
this.takePunctuation(")");
|
|
159
|
+
return {
|
|
160
|
+
kind: "aggregate",
|
|
161
|
+
aggregate,
|
|
162
|
+
argument: { kind: "star" },
|
|
163
|
+
outputName: "COUNT(*)"
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
const column = this.parseColumnRef();
|
|
167
|
+
this.takePunctuation(")");
|
|
168
|
+
return {
|
|
169
|
+
kind: "aggregate",
|
|
170
|
+
aggregate,
|
|
171
|
+
argument: {
|
|
172
|
+
kind: "column",
|
|
173
|
+
column
|
|
174
|
+
},
|
|
175
|
+
outputName: `${aggregate}(${column.column.name})`
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
parseSelectItem() {
|
|
179
|
+
const token = this.peek();
|
|
180
|
+
if (token.kind === "keyword" && isAggregateFunction(token.keyword)) return this.parseAggregate(token.keyword);
|
|
181
|
+
return {
|
|
182
|
+
kind: "column",
|
|
183
|
+
column: this.parseColumnRef()
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
parseSelectList() {
|
|
187
|
+
if (this.atPunctuation("*")) {
|
|
188
|
+
this.advance();
|
|
189
|
+
if (this.atPunctuation(",")) throw new HsqldbSqlUnsupportedError("a select list mixing \"*\" with named columns", this.sql);
|
|
190
|
+
return [{ kind: "star" }];
|
|
191
|
+
}
|
|
192
|
+
const items = [this.parseSelectItem()];
|
|
193
|
+
while (this.atPunctuation(",")) {
|
|
194
|
+
this.advance();
|
|
195
|
+
if (this.atPunctuation("*")) throw new HsqldbSqlUnsupportedError("a select list mixing \"*\" with named columns", this.sql);
|
|
196
|
+
items.push(this.parseSelectItem());
|
|
197
|
+
}
|
|
198
|
+
return items;
|
|
199
|
+
}
|
|
200
|
+
parseLiteral() {
|
|
201
|
+
const token = this.peek();
|
|
202
|
+
if (token.kind === "punctuation" && token.punctuation === "-") {
|
|
203
|
+
this.advance();
|
|
204
|
+
const number = this.peek();
|
|
205
|
+
if (number.kind !== "number") throw new HsqldbSqlUnsupportedError("an arithmetic expression", this.sql);
|
|
206
|
+
this.advance();
|
|
207
|
+
return {
|
|
208
|
+
kind: "number",
|
|
209
|
+
value: -number.value
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
if (token.kind === "number") {
|
|
213
|
+
this.advance();
|
|
214
|
+
return {
|
|
215
|
+
kind: "number",
|
|
216
|
+
value: token.value
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
if (token.kind === "string") {
|
|
220
|
+
this.advance();
|
|
221
|
+
return {
|
|
222
|
+
kind: "string",
|
|
223
|
+
value: token.value
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
if (token.kind === "keyword" && (token.keyword === "TRUE" || token.keyword === "FALSE")) {
|
|
227
|
+
this.advance();
|
|
228
|
+
return {
|
|
229
|
+
kind: "boolean",
|
|
230
|
+
value: token.keyword === "TRUE"
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
if (token.kind === "keyword" && token.keyword === "NULL") {
|
|
234
|
+
this.advance();
|
|
235
|
+
return { kind: "null" };
|
|
236
|
+
}
|
|
237
|
+
this.fail("a literal value");
|
|
238
|
+
}
|
|
239
|
+
parseOperand() {
|
|
240
|
+
const token = this.peek();
|
|
241
|
+
if (token.kind === "identifier") return {
|
|
242
|
+
kind: "column",
|
|
243
|
+
column: this.parseColumnRef()
|
|
244
|
+
};
|
|
245
|
+
if (token.kind === "punctuation" && token.punctuation === "(") throw new HsqldbSqlUnsupportedError("a parenthesised value expression", this.sql);
|
|
246
|
+
return {
|
|
247
|
+
kind: "literal",
|
|
248
|
+
literal: this.parseLiteral()
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
parseInList(operand, negated) {
|
|
252
|
+
this.takePunctuation("(");
|
|
253
|
+
const values = [];
|
|
254
|
+
for (;;) {
|
|
255
|
+
if (this.peek().kind === "identifier") throw new HsqldbSqlUnsupportedError("a column reference inside an IN list", this.sql);
|
|
256
|
+
values.push(this.parseLiteral());
|
|
257
|
+
if (this.atPunctuation(",")) {
|
|
258
|
+
this.advance();
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
this.takePunctuation(")");
|
|
264
|
+
return {
|
|
265
|
+
kind: "in",
|
|
266
|
+
operand,
|
|
267
|
+
values,
|
|
268
|
+
negated
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
parseLike(operand, negated) {
|
|
272
|
+
const token = this.peek();
|
|
273
|
+
if (token.kind !== "string") {
|
|
274
|
+
if (token.kind === "identifier") throw new HsqldbSqlUnsupportedError("a non-literal LIKE pattern", this.sql);
|
|
275
|
+
this.fail("a string literal LIKE pattern");
|
|
276
|
+
}
|
|
277
|
+
this.advance();
|
|
278
|
+
return {
|
|
279
|
+
kind: "like",
|
|
280
|
+
operand,
|
|
281
|
+
pattern: token.value,
|
|
282
|
+
negated
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
parseBetween(operand, negated) {
|
|
286
|
+
const lower = this.parseOperand();
|
|
287
|
+
this.takeKeyword("AND");
|
|
288
|
+
return {
|
|
289
|
+
kind: "between",
|
|
290
|
+
operand,
|
|
291
|
+
lower,
|
|
292
|
+
upper: this.parseOperand(),
|
|
293
|
+
negated
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
parseNegatedPostfix(operand) {
|
|
297
|
+
this.advance();
|
|
298
|
+
if (this.atKeyword("LIKE")) {
|
|
299
|
+
this.advance();
|
|
300
|
+
return this.parseLike(operand, true);
|
|
301
|
+
}
|
|
302
|
+
if (this.atKeyword("IN")) {
|
|
303
|
+
this.advance();
|
|
304
|
+
return this.parseInList(operand, true);
|
|
305
|
+
}
|
|
306
|
+
if (this.atKeyword("BETWEEN")) {
|
|
307
|
+
this.advance();
|
|
308
|
+
return this.parseBetween(operand, true);
|
|
309
|
+
}
|
|
310
|
+
this.fail("keyword LIKE, IN or BETWEEN after NOT");
|
|
311
|
+
}
|
|
312
|
+
parsePostfix(operand) {
|
|
313
|
+
const token = this.peek();
|
|
314
|
+
if (token.kind === "operator") {
|
|
315
|
+
this.advance();
|
|
316
|
+
return {
|
|
317
|
+
kind: "comparison",
|
|
318
|
+
operator: token.operator,
|
|
319
|
+
left: operand,
|
|
320
|
+
right: this.parseOperand()
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
if (token.kind === "punctuation" && (token.punctuation === "*" || token.punctuation === "-")) throw new HsqldbSqlUnsupportedError("an arithmetic expression", this.sql);
|
|
324
|
+
if (token.kind === "keyword") {
|
|
325
|
+
if (token.keyword === "IS") {
|
|
326
|
+
this.advance();
|
|
327
|
+
const negated = this.atKeyword("NOT");
|
|
328
|
+
if (negated) this.advance();
|
|
329
|
+
this.takeKeyword("NULL");
|
|
330
|
+
return {
|
|
331
|
+
kind: "isNull",
|
|
332
|
+
operand,
|
|
333
|
+
negated
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
if (token.keyword === "LIKE") {
|
|
337
|
+
this.advance();
|
|
338
|
+
return this.parseLike(operand, false);
|
|
339
|
+
}
|
|
340
|
+
if (token.keyword === "IN") {
|
|
341
|
+
this.advance();
|
|
342
|
+
return this.parseInList(operand, false);
|
|
343
|
+
}
|
|
344
|
+
if (token.keyword === "BETWEEN") {
|
|
345
|
+
this.advance();
|
|
346
|
+
return this.parseBetween(operand, false);
|
|
347
|
+
}
|
|
348
|
+
if (token.keyword === "NOT") return this.parseNegatedPostfix(operand);
|
|
349
|
+
}
|
|
350
|
+
this.fail("a comparison operator, or keyword IS, LIKE, IN or BETWEEN");
|
|
351
|
+
}
|
|
352
|
+
parsePrimary() {
|
|
353
|
+
if (this.atPunctuation("(")) {
|
|
354
|
+
this.advance();
|
|
355
|
+
const predicate = this.parsePredicate();
|
|
356
|
+
this.takePunctuation(")");
|
|
357
|
+
return predicate;
|
|
358
|
+
}
|
|
359
|
+
return this.parsePostfix(this.parseOperand());
|
|
360
|
+
}
|
|
361
|
+
parseNot() {
|
|
362
|
+
if (this.atKeyword("NOT")) {
|
|
363
|
+
this.advance();
|
|
364
|
+
return {
|
|
365
|
+
kind: "not",
|
|
366
|
+
predicate: this.parseNot()
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
return this.parsePrimary();
|
|
370
|
+
}
|
|
371
|
+
parseAnd() {
|
|
372
|
+
let predicate = this.parseNot();
|
|
373
|
+
while (this.atKeyword("AND")) {
|
|
374
|
+
this.advance();
|
|
375
|
+
predicate = {
|
|
376
|
+
kind: "and",
|
|
377
|
+
left: predicate,
|
|
378
|
+
right: this.parseNot()
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
return predicate;
|
|
382
|
+
}
|
|
383
|
+
parsePredicate() {
|
|
384
|
+
let predicate = this.parseAnd();
|
|
385
|
+
while (this.atKeyword("OR")) {
|
|
386
|
+
this.advance();
|
|
387
|
+
predicate = {
|
|
388
|
+
kind: "or",
|
|
389
|
+
left: predicate,
|
|
390
|
+
right: this.parseAnd()
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
return predicate;
|
|
394
|
+
}
|
|
395
|
+
parseGroupBy() {
|
|
396
|
+
this.takeKeyword("GROUP");
|
|
397
|
+
this.takeKeyword("BY");
|
|
398
|
+
const columns = [this.parseGroupByColumn()];
|
|
399
|
+
while (this.atPunctuation(",")) {
|
|
400
|
+
this.advance();
|
|
401
|
+
columns.push(this.parseGroupByColumn());
|
|
402
|
+
}
|
|
403
|
+
return columns;
|
|
404
|
+
}
|
|
405
|
+
parseGroupByColumn() {
|
|
406
|
+
const token = this.peek();
|
|
407
|
+
if (token.kind === "keyword" && isAggregateFunction(token.keyword)) this.fail("a column name -- an aggregate function is not valid in GROUP BY");
|
|
408
|
+
return this.parseColumnRef();
|
|
409
|
+
}
|
|
410
|
+
parseOrderBy() {
|
|
411
|
+
this.takeKeyword("ORDER");
|
|
412
|
+
this.takeKeyword("BY");
|
|
413
|
+
const terms = [this.parseOrderByTerm()];
|
|
414
|
+
while (this.atPunctuation(",")) {
|
|
415
|
+
this.advance();
|
|
416
|
+
terms.push(this.parseOrderByTerm());
|
|
417
|
+
}
|
|
418
|
+
return terms;
|
|
419
|
+
}
|
|
420
|
+
parseOrderByTerm() {
|
|
421
|
+
const token = this.peek();
|
|
422
|
+
if (token.kind === "keyword" && isAggregateFunction(token.keyword)) throw new HsqldbSqlUnsupportedError("an aggregate function in ORDER BY", this.sql);
|
|
423
|
+
if (token.kind === "number") throw new HsqldbSqlUnsupportedError("an ordinal column reference in ORDER BY (ORDER BY 1)", this.sql);
|
|
424
|
+
const column = this.parseColumnRef();
|
|
425
|
+
if (this.atKeyword("ASC")) {
|
|
426
|
+
this.advance();
|
|
427
|
+
return {
|
|
428
|
+
column,
|
|
429
|
+
direction: "asc"
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
if (this.atKeyword("DESC")) {
|
|
433
|
+
this.advance();
|
|
434
|
+
return {
|
|
435
|
+
column,
|
|
436
|
+
direction: "desc"
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
return {
|
|
440
|
+
column,
|
|
441
|
+
direction: "asc"
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
parseStatement() {
|
|
445
|
+
const first = this.peek();
|
|
446
|
+
if (!(first.kind === "keyword" && first.keyword === "SELECT")) this.fail("keyword SELECT");
|
|
447
|
+
this.advance();
|
|
448
|
+
const items = this.parseSelectList();
|
|
449
|
+
this.takeKeyword("FROM");
|
|
450
|
+
if (this.atPunctuation("(")) throw new HsqldbSqlUnsupportedError("a derived table in FROM", this.sql);
|
|
451
|
+
const from = this.takeName("a table name");
|
|
452
|
+
if (this.atPunctuation(".")) throw new HsqldbSqlUnsupportedError("a schema-qualified table name", this.sql);
|
|
453
|
+
if (this.atPunctuation(",")) throw new HsqldbSqlUnsupportedError("a JOIN", this.sql);
|
|
454
|
+
if (this.peek().kind === "identifier") throw new HsqldbSqlUnsupportedError("a table alias", this.sql);
|
|
455
|
+
let where;
|
|
456
|
+
if (this.atKeyword("WHERE")) {
|
|
457
|
+
this.advance();
|
|
458
|
+
where = this.parsePredicate();
|
|
459
|
+
}
|
|
460
|
+
const groupBy = this.atKeyword("GROUP") ? this.parseGroupBy() : [];
|
|
461
|
+
const orderBy = this.atKeyword("ORDER") ? this.parseOrderBy() : [];
|
|
462
|
+
if (this.atPunctuation(";")) this.advance();
|
|
463
|
+
if (this.peek().kind !== "end") this.fail("end of statement");
|
|
464
|
+
return {
|
|
465
|
+
sql: this.sql,
|
|
466
|
+
items,
|
|
467
|
+
from,
|
|
468
|
+
where,
|
|
469
|
+
groupBy,
|
|
470
|
+
orderBy
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
function parseSelect(sql) {
|
|
475
|
+
return new SqlParser(sql).parseStatement();
|
|
476
|
+
}
|
|
477
|
+
//#endregion
|
|
478
|
+
export { parseSelect };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/odb/values.ts
|
|
3
|
+
const CELL_NULL = { kind: "empty" };
|
|
4
|
+
function cellComparisonKey(value) {
|
|
5
|
+
switch (value.kind) {
|
|
6
|
+
case "number":
|
|
7
|
+
case "percentage":
|
|
8
|
+
case "currency": return {
|
|
9
|
+
valueClass: "numeric",
|
|
10
|
+
numeric: value.value
|
|
11
|
+
};
|
|
12
|
+
case "boolean": return {
|
|
13
|
+
valueClass: "boolean",
|
|
14
|
+
boolean: value.value
|
|
15
|
+
};
|
|
16
|
+
case "date":
|
|
17
|
+
case "time":
|
|
18
|
+
case "dateTime":
|
|
19
|
+
case "string":
|
|
20
|
+
case "error": return {
|
|
21
|
+
valueClass: "text",
|
|
22
|
+
text: value.value
|
|
23
|
+
};
|
|
24
|
+
case "empty": return;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function compareCellKeys(left, right, fail) {
|
|
28
|
+
if (left.valueClass === "numeric" && right.valueClass === "numeric") return left.numeric === right.numeric ? 0 : left.numeric < right.numeric ? -1 : 1;
|
|
29
|
+
if (left.valueClass === "boolean" && right.valueClass === "boolean") return left.boolean === right.boolean ? 0 : left.boolean ? 1 : -1;
|
|
30
|
+
if (left.valueClass === "text" && right.valueClass === "text") return left.text === right.text ? 0 : left.text < right.text ? -1 : 1;
|
|
31
|
+
throw fail(`cannot compare a ${left.valueClass} value with a ${right.valueClass} value`);
|
|
32
|
+
}
|
|
33
|
+
function compareCellValues(left, right, fail) {
|
|
34
|
+
const leftKey = cellComparisonKey(left);
|
|
35
|
+
const rightKey = cellComparisonKey(right);
|
|
36
|
+
if (leftKey === void 0 || rightKey === void 0) throw fail("a NULL value reached a comparison that had already ruled NULL out");
|
|
37
|
+
return compareCellKeys(leftKey, rightKey, fail);
|
|
38
|
+
}
|
|
39
|
+
function cellValuesEqual(left, right) {
|
|
40
|
+
const leftKey = cellComparisonKey(left);
|
|
41
|
+
const rightKey = cellComparisonKey(right);
|
|
42
|
+
if (leftKey === void 0 || rightKey === void 0) return leftKey === rightKey;
|
|
43
|
+
if (leftKey.valueClass === "numeric" && rightKey.valueClass === "numeric") return leftKey.numeric === rightKey.numeric;
|
|
44
|
+
if (leftKey.valueClass === "boolean" && rightKey.valueClass === "boolean") return leftKey.boolean === rightKey.boolean;
|
|
45
|
+
return leftKey.valueClass === "text" && rightKey.valueClass === "text" && leftKey.text === rightKey.text;
|
|
46
|
+
}
|
|
47
|
+
function numericOf(value, aggregate, fail) {
|
|
48
|
+
const key = cellComparisonKey(value);
|
|
49
|
+
if (key?.valueClass !== "numeric") throw fail(`${aggregate} requires numeric values, but found a ${value.kind} value`);
|
|
50
|
+
return key.numeric;
|
|
51
|
+
}
|
|
52
|
+
function aggregateCellValues(aggregate, values, fail) {
|
|
53
|
+
const present = values.filter((value) => value.kind !== "empty");
|
|
54
|
+
if (aggregate === "COUNT") return {
|
|
55
|
+
kind: "number",
|
|
56
|
+
value: present.length
|
|
57
|
+
};
|
|
58
|
+
const first = present[0];
|
|
59
|
+
if (first === void 0) return CELL_NULL;
|
|
60
|
+
if (aggregate === "SUM" || aggregate === "AVG") {
|
|
61
|
+
const total = present.reduce((sum, value) => sum + numericOf(value, aggregate, fail), 0);
|
|
62
|
+
return {
|
|
63
|
+
kind: "number",
|
|
64
|
+
value: aggregate === "SUM" ? total : total / present.length
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return present.reduce((best, value) => (aggregate === "MIN" ? compareCellValues(value, best, fail) < 0 : compareCellValues(value, best, fail) > 0) ? value : best, first);
|
|
68
|
+
}
|
|
69
|
+
//#endregion
|
|
70
|
+
exports.CELL_NULL = CELL_NULL;
|
|
71
|
+
exports.aggregateCellValues = aggregateCellValues;
|
|
72
|
+
exports.cellComparisonKey = cellComparisonKey;
|
|
73
|
+
exports.cellValuesEqual = cellValuesEqual;
|
|
74
|
+
exports.compareCellKeys = compareCellKeys;
|
|
75
|
+
exports.compareCellValues = compareCellValues;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as CellValueFailure, c as cellValuesEqual, i as CellValueClass, l as compareCellKeys, n as CellAggregateFunction, o as aggregateCellValues, r as CellComparisonKey, s as cellComparisonKey, t as CELL_NULL, u as compareCellValues } from "../values-BetetbaH.cjs";
|
|
2
|
+
export { CELL_NULL, CellAggregateFunction, CellComparisonKey, CellValueClass, CellValueFailure, aggregateCellValues, cellComparisonKey, cellValuesEqual, compareCellKeys, compareCellValues };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as CellValueFailure, c as cellValuesEqual, i as CellValueClass, l as compareCellKeys, n as CellAggregateFunction, o as aggregateCellValues, r as CellComparisonKey, s as cellComparisonKey, t as CELL_NULL, u as compareCellValues } from "../values-BetetbaH.js";
|
|
2
|
+
export { CELL_NULL, CellAggregateFunction, CellComparisonKey, CellValueClass, CellValueFailure, aggregateCellValues, cellComparisonKey, cellValuesEqual, compareCellKeys, compareCellValues };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
//#region src/odb/values.ts
|
|
2
|
+
const CELL_NULL = { kind: "empty" };
|
|
3
|
+
function cellComparisonKey(value) {
|
|
4
|
+
switch (value.kind) {
|
|
5
|
+
case "number":
|
|
6
|
+
case "percentage":
|
|
7
|
+
case "currency": return {
|
|
8
|
+
valueClass: "numeric",
|
|
9
|
+
numeric: value.value
|
|
10
|
+
};
|
|
11
|
+
case "boolean": return {
|
|
12
|
+
valueClass: "boolean",
|
|
13
|
+
boolean: value.value
|
|
14
|
+
};
|
|
15
|
+
case "date":
|
|
16
|
+
case "time":
|
|
17
|
+
case "dateTime":
|
|
18
|
+
case "string":
|
|
19
|
+
case "error": return {
|
|
20
|
+
valueClass: "text",
|
|
21
|
+
text: value.value
|
|
22
|
+
};
|
|
23
|
+
case "empty": return;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function compareCellKeys(left, right, fail) {
|
|
27
|
+
if (left.valueClass === "numeric" && right.valueClass === "numeric") return left.numeric === right.numeric ? 0 : left.numeric < right.numeric ? -1 : 1;
|
|
28
|
+
if (left.valueClass === "boolean" && right.valueClass === "boolean") return left.boolean === right.boolean ? 0 : left.boolean ? 1 : -1;
|
|
29
|
+
if (left.valueClass === "text" && right.valueClass === "text") return left.text === right.text ? 0 : left.text < right.text ? -1 : 1;
|
|
30
|
+
throw fail(`cannot compare a ${left.valueClass} value with a ${right.valueClass} value`);
|
|
31
|
+
}
|
|
32
|
+
function compareCellValues(left, right, fail) {
|
|
33
|
+
const leftKey = cellComparisonKey(left);
|
|
34
|
+
const rightKey = cellComparisonKey(right);
|
|
35
|
+
if (leftKey === void 0 || rightKey === void 0) throw fail("a NULL value reached a comparison that had already ruled NULL out");
|
|
36
|
+
return compareCellKeys(leftKey, rightKey, fail);
|
|
37
|
+
}
|
|
38
|
+
function cellValuesEqual(left, right) {
|
|
39
|
+
const leftKey = cellComparisonKey(left);
|
|
40
|
+
const rightKey = cellComparisonKey(right);
|
|
41
|
+
if (leftKey === void 0 || rightKey === void 0) return leftKey === rightKey;
|
|
42
|
+
if (leftKey.valueClass === "numeric" && rightKey.valueClass === "numeric") return leftKey.numeric === rightKey.numeric;
|
|
43
|
+
if (leftKey.valueClass === "boolean" && rightKey.valueClass === "boolean") return leftKey.boolean === rightKey.boolean;
|
|
44
|
+
return leftKey.valueClass === "text" && rightKey.valueClass === "text" && leftKey.text === rightKey.text;
|
|
45
|
+
}
|
|
46
|
+
function numericOf(value, aggregate, fail) {
|
|
47
|
+
const key = cellComparisonKey(value);
|
|
48
|
+
if (key?.valueClass !== "numeric") throw fail(`${aggregate} requires numeric values, but found a ${value.kind} value`);
|
|
49
|
+
return key.numeric;
|
|
50
|
+
}
|
|
51
|
+
function aggregateCellValues(aggregate, values, fail) {
|
|
52
|
+
const present = values.filter((value) => value.kind !== "empty");
|
|
53
|
+
if (aggregate === "COUNT") return {
|
|
54
|
+
kind: "number",
|
|
55
|
+
value: present.length
|
|
56
|
+
};
|
|
57
|
+
const first = present[0];
|
|
58
|
+
if (first === void 0) return CELL_NULL;
|
|
59
|
+
if (aggregate === "SUM" || aggregate === "AVG") {
|
|
60
|
+
const total = present.reduce((sum, value) => sum + numericOf(value, aggregate, fail), 0);
|
|
61
|
+
return {
|
|
62
|
+
kind: "number",
|
|
63
|
+
value: aggregate === "SUM" ? total : total / present.length
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return present.reduce((best, value) => (aggregate === "MIN" ? compareCellValues(value, best, fail) < 0 : compareCellValues(value, best, fail) > 0) ? value : best, first);
|
|
67
|
+
}
|
|
68
|
+
//#endregion
|
|
69
|
+
export { CELL_NULL, aggregateCellValues, cellComparisonKey, cellValuesEqual, compareCellKeys, compareCellValues };
|