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,106 @@
|
|
|
1
|
+
import { PAGE_SIZE_A4 } from "../../model/geometry.js";
|
|
2
|
+
import { displayTextFor } from "../../hsqldb/script.js";
|
|
3
|
+
import { evaluateRptBandOutsideData, runRptReport } from "../formula/evaluate.js";
|
|
4
|
+
import { odbReportGroupChain, rptBandDefinition, rptDefinitionFromReport } from "../formula/definition.js";
|
|
5
|
+
import { CONTENT_FORMAT_VERSION } from "document-schema.js";
|
|
6
|
+
//#region src/odb/report/render.ts
|
|
7
|
+
const MARGIN_PT = 56.69291338582677;
|
|
8
|
+
const CONTENT_WIDTH_PT = PAGE_SIZE_A4.widthPt - 2 * MARGIN_PT;
|
|
9
|
+
const REPORT_HEADER_STYLE = "Report Header";
|
|
10
|
+
const PAGE_HEADER_STYLE = "Page Header";
|
|
11
|
+
const DETAIL_STYLE = "Detail";
|
|
12
|
+
const PAGE_FOOTER_STYLE = "Page Footer";
|
|
13
|
+
const REPORT_FOOTER_STYLE = "Report Footer";
|
|
14
|
+
function groupBandStyle(kind, level) {
|
|
15
|
+
return `${kind === "group-header" ? "Group Header" : "Group Footer"} ${String(level + 1)}`;
|
|
16
|
+
}
|
|
17
|
+
function printedBand(band, styleId, values) {
|
|
18
|
+
if (band === void 0) throw new Error(`rpt report render: a "${styleId}" band instance was emitted for a band this report does not declare`);
|
|
19
|
+
return {
|
|
20
|
+
styleId,
|
|
21
|
+
elements: band.elements,
|
|
22
|
+
values
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function bandOfInstance(report, groups, instance) {
|
|
26
|
+
switch (instance.kind) {
|
|
27
|
+
case "report-header": return printedBand(report.reportHeader, REPORT_HEADER_STYLE, instance.values);
|
|
28
|
+
case "detail": return printedBand(report.detail, DETAIL_STYLE, instance.values);
|
|
29
|
+
case "report-footer": return printedBand(report.reportFooter, REPORT_FOOTER_STYLE, instance.values);
|
|
30
|
+
case "group-header":
|
|
31
|
+
case "group-footer": {
|
|
32
|
+
const level = instance.groupLevel;
|
|
33
|
+
if (level === void 0) throw new Error(`rpt report render: a ${instance.kind} band instance carries no group level`);
|
|
34
|
+
const group = groups[level];
|
|
35
|
+
if (group === void 0) throw new Error(`rpt report render: a ${instance.kind} band instance names group level ${String(level)}, which this report's own chain of ${String(groups.length)} group(s) does not reach`);
|
|
36
|
+
return printedBand(instance.kind === "group-header" ? group.header : group.footer, groupBandStyle(instance.kind, level), instance.values);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function elementText(element, value) {
|
|
41
|
+
if (element.formula === void 0) return element.text ?? "";
|
|
42
|
+
if (value === void 0) throw new Error(`rpt report render: control "${element.formula}" carries a formula but the run produced no value for it`);
|
|
43
|
+
return displayTextFor(value);
|
|
44
|
+
}
|
|
45
|
+
function cellParagraph(element, value, styleId) {
|
|
46
|
+
const text = elementText(element, value);
|
|
47
|
+
return {
|
|
48
|
+
kind: "paragraph",
|
|
49
|
+
styleId,
|
|
50
|
+
runs: text === "" ? [] : [{ text }]
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function bandTable(band) {
|
|
54
|
+
if (band.elements.length === 0) return;
|
|
55
|
+
if (band.values.length !== band.elements.length) throw new Error(`rpt report render: the "${band.styleId}" band printed ${String(band.values.length)} values for ${String(band.elements.length)} control(s)`);
|
|
56
|
+
const columnWidthPt = CONTENT_WIDTH_PT / band.elements.length;
|
|
57
|
+
return {
|
|
58
|
+
kind: "table",
|
|
59
|
+
columnWidthsPt: band.elements.map(() => columnWidthPt),
|
|
60
|
+
rows: [{ cells: band.elements.map((element, index) => ({ blocks: [cellParagraph(element, band.values[index], band.styleId)] })) }]
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function bandBlocks(bands) {
|
|
64
|
+
return bands.flatMap((band) => {
|
|
65
|
+
const table = bandTable(band);
|
|
66
|
+
return table === void 0 ? [] : [table];
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
function pageBands(definition, band, styleId, resultSet) {
|
|
70
|
+
if (band === void 0) return [];
|
|
71
|
+
return [{
|
|
72
|
+
styleId,
|
|
73
|
+
elements: band.elements,
|
|
74
|
+
values: evaluateRptBandOutsideData(definition, rptBandDefinition(band), resultSet)
|
|
75
|
+
}];
|
|
76
|
+
}
|
|
77
|
+
function renderOdbReportContent(report, resultSet) {
|
|
78
|
+
const definition = rptDefinitionFromReport(report);
|
|
79
|
+
const groups = odbReportGroupChain(report);
|
|
80
|
+
const instances = runRptReport(definition, resultSet).bands;
|
|
81
|
+
const printed = (matches) => instances.filter((instance) => matches(instance.kind)).map((instance) => bandOfInstance(report, groups, instance));
|
|
82
|
+
const section = {
|
|
83
|
+
pageSize: PAGE_SIZE_A4,
|
|
84
|
+
margins: {
|
|
85
|
+
topPt: MARGIN_PT,
|
|
86
|
+
rightPt: MARGIN_PT,
|
|
87
|
+
bottomPt: MARGIN_PT,
|
|
88
|
+
leftPt: MARGIN_PT
|
|
89
|
+
},
|
|
90
|
+
blocks: [
|
|
91
|
+
...bandBlocks(printed((kind) => kind === "report-header")),
|
|
92
|
+
...bandBlocks(pageBands(definition, report.pageHeader, PAGE_HEADER_STYLE, resultSet)),
|
|
93
|
+
...bandBlocks(printed((kind) => kind !== "report-header" && kind !== "report-footer")),
|
|
94
|
+
...bandBlocks(pageBands(definition, report.pageFooter, PAGE_FOOTER_STYLE, resultSet)),
|
|
95
|
+
...bandBlocks(printed((kind) => kind === "report-footer"))
|
|
96
|
+
]
|
|
97
|
+
};
|
|
98
|
+
return {
|
|
99
|
+
kind: "wordprocessing",
|
|
100
|
+
formatVersion: CONTENT_FORMAT_VERSION,
|
|
101
|
+
metadata: { title: report.caption ?? report.name },
|
|
102
|
+
sections: [section]
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
//#endregion
|
|
106
|
+
export { renderOdbReportContent };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_odb_read = require("../read.cjs");
|
|
3
|
+
const require_odb_sql_evaluate = require("../sql/evaluate.cjs");
|
|
4
|
+
const require_odb_sql_parser = require("../sql/parser.cjs");
|
|
5
|
+
let odf_js = require("odf.js");
|
|
6
|
+
//#region src/odb/report/source.ts
|
|
7
|
+
var OdbReportDataSourceError = class extends Error {
|
|
8
|
+
reportName;
|
|
9
|
+
command;
|
|
10
|
+
commandType;
|
|
11
|
+
constructor(message, report) {
|
|
12
|
+
super(`Report "${report.name}" data source: ${message}`);
|
|
13
|
+
this.name = "OdbReportDataSourceError";
|
|
14
|
+
this.reportName = report.name;
|
|
15
|
+
this.command = report.command;
|
|
16
|
+
this.commandType = report.commandType;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
function quotedIdentifier(name) {
|
|
20
|
+
return `"${name.replace(/"/g, "\"\"")}"`;
|
|
21
|
+
}
|
|
22
|
+
function savedQueryCommand(report, commandName, queries) {
|
|
23
|
+
const query = queries.find((candidate) => candidate.name === commandName);
|
|
24
|
+
if (query === void 0) throw new OdbReportDataSourceError(`rpt:command-type is "query" and rpt:command names "${commandName}", but this .odb declares no such saved query -- available quer${queries.length === 1 ? "y" : "ies"}: ${queries.length === 0 ? "(none)" : queries.map((candidate) => candidate.name).join(", ")}`, report);
|
|
25
|
+
return query.command;
|
|
26
|
+
}
|
|
27
|
+
function odbReportCommandSql(report, queries) {
|
|
28
|
+
const command = report.command;
|
|
29
|
+
if (command === void 0) throw new OdbReportDataSourceError("the report declares no rpt:command, so there is no table, query, or statement to read its rows from", report);
|
|
30
|
+
switch (report.commandType) {
|
|
31
|
+
case "table": return `SELECT * FROM ${quotedIdentifier(command)}`;
|
|
32
|
+
case "query": return savedQueryCommand(report, command, queries);
|
|
33
|
+
case "command": return command;
|
|
34
|
+
case void 0: throw new OdbReportDataSourceError(`the report declares rpt:command "${command}" but no rpt:command-type, so whether that names a table, a saved query, or a literal statement is undetermined`, report);
|
|
35
|
+
default: throw new OdbReportDataSourceError(`rpt:command-type "${report.commandType}" is not one of the three values this package resolves ("table", "query", "command")`, report);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function resolveOdbReportRows(pkg, report, options) {
|
|
39
|
+
const sql = odbReportCommandSql(report, (0, odf_js.readOdbInventory)(pkg).queries);
|
|
40
|
+
return require_odb_sql_evaluate.evaluateSelect(require_odb_sql_parser.parseSelect(sql), require_odb_read.readOdbTables(pkg, options));
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
exports.OdbReportDataSourceError = OdbReportDataSourceError;
|
|
44
|
+
exports.odbReportCommandSql = odbReportCommandSql;
|
|
45
|
+
exports.resolveOdbReportRows = resolveOdbReportRows;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { n as HsqldbDecodeOptions } from "../../rowformat-Cl2exlEh.cjs";
|
|
2
|
+
import { t as SqlResultSet } from "../../evaluate-BhMXY6DM.cjs";
|
|
3
|
+
import { OdbQueryInfo, OdbReport, Package } from "odf.js";
|
|
4
|
+
//#region src/odb/report/source.d.ts
|
|
5
|
+
declare class OdbReportDataSourceError extends Error {
|
|
6
|
+
readonly reportName: string;
|
|
7
|
+
readonly command: string | undefined;
|
|
8
|
+
readonly commandType: string | undefined;
|
|
9
|
+
constructor(message: string, report: OdbReport);
|
|
10
|
+
}
|
|
11
|
+
declare function odbReportCommandSql(report: OdbReport, queries: readonly OdbQueryInfo[]): string;
|
|
12
|
+
declare function resolveOdbReportRows(pkg: Package, report: OdbReport, options?: HsqldbDecodeOptions): SqlResultSet;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { OdbReportDataSourceError, odbReportCommandSql, resolveOdbReportRows };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { n as HsqldbDecodeOptions } from "../../rowformat-Cl2exlEh.js";
|
|
2
|
+
import { t as SqlResultSet } from "../../evaluate-BU5N1Jk1.js";
|
|
3
|
+
import { OdbQueryInfo, OdbReport, Package } from "odf.js";
|
|
4
|
+
//#region src/odb/report/source.d.ts
|
|
5
|
+
declare class OdbReportDataSourceError extends Error {
|
|
6
|
+
readonly reportName: string;
|
|
7
|
+
readonly command: string | undefined;
|
|
8
|
+
readonly commandType: string | undefined;
|
|
9
|
+
constructor(message: string, report: OdbReport);
|
|
10
|
+
}
|
|
11
|
+
declare function odbReportCommandSql(report: OdbReport, queries: readonly OdbQueryInfo[]): string;
|
|
12
|
+
declare function resolveOdbReportRows(pkg: Package, report: OdbReport, options?: HsqldbDecodeOptions): SqlResultSet;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { OdbReportDataSourceError, odbReportCommandSql, resolveOdbReportRows };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { readOdbTables } from "../read.js";
|
|
2
|
+
import { evaluateSelect } from "../sql/evaluate.js";
|
|
3
|
+
import { parseSelect } from "../sql/parser.js";
|
|
4
|
+
import { readOdbInventory } from "odf.js";
|
|
5
|
+
//#region src/odb/report/source.ts
|
|
6
|
+
var OdbReportDataSourceError = class extends Error {
|
|
7
|
+
reportName;
|
|
8
|
+
command;
|
|
9
|
+
commandType;
|
|
10
|
+
constructor(message, report) {
|
|
11
|
+
super(`Report "${report.name}" data source: ${message}`);
|
|
12
|
+
this.name = "OdbReportDataSourceError";
|
|
13
|
+
this.reportName = report.name;
|
|
14
|
+
this.command = report.command;
|
|
15
|
+
this.commandType = report.commandType;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
function quotedIdentifier(name) {
|
|
19
|
+
return `"${name.replace(/"/g, "\"\"")}"`;
|
|
20
|
+
}
|
|
21
|
+
function savedQueryCommand(report, commandName, queries) {
|
|
22
|
+
const query = queries.find((candidate) => candidate.name === commandName);
|
|
23
|
+
if (query === void 0) throw new OdbReportDataSourceError(`rpt:command-type is "query" and rpt:command names "${commandName}", but this .odb declares no such saved query -- available quer${queries.length === 1 ? "y" : "ies"}: ${queries.length === 0 ? "(none)" : queries.map((candidate) => candidate.name).join(", ")}`, report);
|
|
24
|
+
return query.command;
|
|
25
|
+
}
|
|
26
|
+
function odbReportCommandSql(report, queries) {
|
|
27
|
+
const command = report.command;
|
|
28
|
+
if (command === void 0) throw new OdbReportDataSourceError("the report declares no rpt:command, so there is no table, query, or statement to read its rows from", report);
|
|
29
|
+
switch (report.commandType) {
|
|
30
|
+
case "table": return `SELECT * FROM ${quotedIdentifier(command)}`;
|
|
31
|
+
case "query": return savedQueryCommand(report, command, queries);
|
|
32
|
+
case "command": return command;
|
|
33
|
+
case void 0: throw new OdbReportDataSourceError(`the report declares rpt:command "${command}" but no rpt:command-type, so whether that names a table, a saved query, or a literal statement is undetermined`, report);
|
|
34
|
+
default: throw new OdbReportDataSourceError(`rpt:command-type "${report.commandType}" is not one of the three values this package resolves ("table", "query", "command")`, report);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function resolveOdbReportRows(pkg, report, options) {
|
|
38
|
+
const sql = odbReportCommandSql(report, readOdbInventory(pkg).queries);
|
|
39
|
+
return evaluateSelect(parseSelect(sql), readOdbTables(pkg, options));
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { OdbReportDataSourceError, odbReportCommandSql, resolveOdbReportRows };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HsqldbTable } from "../
|
|
1
|
+
import { r as HsqldbTable } from "../script-DsGGIzGU.cjs";
|
|
2
2
|
import { ContentDocument } from "document-schema.js";
|
|
3
3
|
//#region src/odb/spreadsheet.d.ts
|
|
4
4
|
declare function odbTablesToSpreadsheetDocument(tables: readonly HsqldbTable[]): ContentDocument;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HsqldbTable } from "../
|
|
1
|
+
import { r as HsqldbTable } from "../script-DsGGIzGU.js";
|
|
2
2
|
import { ContentDocument } from "document-schema.js";
|
|
3
3
|
//#region src/odb/spreadsheet.d.ts
|
|
4
4
|
declare function odbTablesToSpreadsheetDocument(tables: readonly HsqldbTable[]): ContentDocument;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/odb/sql/errors.ts
|
|
3
|
+
const MESSAGE_SQL_PREVIEW_LENGTH = 200;
|
|
4
|
+
function truncateForMessage(sql) {
|
|
5
|
+
return sql.length > MESSAGE_SQL_PREVIEW_LENGTH ? `${sql.slice(0, MESSAGE_SQL_PREVIEW_LENGTH)}...` : sql;
|
|
6
|
+
}
|
|
7
|
+
var HsqldbSqlUnsupportedError = class extends Error {
|
|
8
|
+
construct;
|
|
9
|
+
sql;
|
|
10
|
+
constructor(construct, sql) {
|
|
11
|
+
super(`HSQLDB SQL: ${construct} is not supported by this bounded single-table query engine -- in statement: ${truncateForMessage(sql)}`);
|
|
12
|
+
this.name = "HsqldbSqlUnsupportedError";
|
|
13
|
+
this.construct = construct;
|
|
14
|
+
this.sql = sql;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
var HsqldbSqlParseError = class extends Error {
|
|
18
|
+
sql;
|
|
19
|
+
offset;
|
|
20
|
+
constructor(message, sql, offset) {
|
|
21
|
+
super(`HSQLDB SQL parse error at offset ${String(offset)}: ${message} -- in statement: ${truncateForMessage(sql)}`);
|
|
22
|
+
this.name = "HsqldbSqlParseError";
|
|
23
|
+
this.sql = sql;
|
|
24
|
+
this.offset = offset;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
var HsqldbSqlEvaluationError = class extends Error {
|
|
28
|
+
sql;
|
|
29
|
+
constructor(message, sql) {
|
|
30
|
+
super(`HSQLDB SQL evaluation error: ${message} -- in statement: ${truncateForMessage(sql)}`);
|
|
31
|
+
this.name = "HsqldbSqlEvaluationError";
|
|
32
|
+
this.sql = sql;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
//#endregion
|
|
36
|
+
exports.HsqldbSqlEvaluationError = HsqldbSqlEvaluationError;
|
|
37
|
+
exports.HsqldbSqlParseError = HsqldbSqlParseError;
|
|
38
|
+
exports.HsqldbSqlUnsupportedError = HsqldbSqlUnsupportedError;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/odb/sql/errors.d.ts
|
|
2
|
+
declare class HsqldbSqlUnsupportedError extends Error {
|
|
3
|
+
readonly construct: string;
|
|
4
|
+
readonly sql: string;
|
|
5
|
+
constructor(construct: string, sql: string);
|
|
6
|
+
}
|
|
7
|
+
declare class HsqldbSqlParseError extends Error {
|
|
8
|
+
readonly sql: string;
|
|
9
|
+
readonly offset: number;
|
|
10
|
+
constructor(message: string, sql: string, offset: number);
|
|
11
|
+
}
|
|
12
|
+
declare class HsqldbSqlEvaluationError extends Error {
|
|
13
|
+
readonly sql: string;
|
|
14
|
+
constructor(message: string, sql: string);
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { HsqldbSqlEvaluationError, HsqldbSqlParseError, HsqldbSqlUnsupportedError };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/odb/sql/errors.d.ts
|
|
2
|
+
declare class HsqldbSqlUnsupportedError extends Error {
|
|
3
|
+
readonly construct: string;
|
|
4
|
+
readonly sql: string;
|
|
5
|
+
constructor(construct: string, sql: string);
|
|
6
|
+
}
|
|
7
|
+
declare class HsqldbSqlParseError extends Error {
|
|
8
|
+
readonly sql: string;
|
|
9
|
+
readonly offset: number;
|
|
10
|
+
constructor(message: string, sql: string, offset: number);
|
|
11
|
+
}
|
|
12
|
+
declare class HsqldbSqlEvaluationError extends Error {
|
|
13
|
+
readonly sql: string;
|
|
14
|
+
constructor(message: string, sql: string);
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { HsqldbSqlEvaluationError, HsqldbSqlParseError, HsqldbSqlUnsupportedError };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
//#region src/odb/sql/errors.ts
|
|
2
|
+
const MESSAGE_SQL_PREVIEW_LENGTH = 200;
|
|
3
|
+
function truncateForMessage(sql) {
|
|
4
|
+
return sql.length > MESSAGE_SQL_PREVIEW_LENGTH ? `${sql.slice(0, MESSAGE_SQL_PREVIEW_LENGTH)}...` : sql;
|
|
5
|
+
}
|
|
6
|
+
var HsqldbSqlUnsupportedError = class extends Error {
|
|
7
|
+
construct;
|
|
8
|
+
sql;
|
|
9
|
+
constructor(construct, sql) {
|
|
10
|
+
super(`HSQLDB SQL: ${construct} is not supported by this bounded single-table query engine -- in statement: ${truncateForMessage(sql)}`);
|
|
11
|
+
this.name = "HsqldbSqlUnsupportedError";
|
|
12
|
+
this.construct = construct;
|
|
13
|
+
this.sql = sql;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
var HsqldbSqlParseError = class extends Error {
|
|
17
|
+
sql;
|
|
18
|
+
offset;
|
|
19
|
+
constructor(message, sql, offset) {
|
|
20
|
+
super(`HSQLDB SQL parse error at offset ${String(offset)}: ${message} -- in statement: ${truncateForMessage(sql)}`);
|
|
21
|
+
this.name = "HsqldbSqlParseError";
|
|
22
|
+
this.sql = sql;
|
|
23
|
+
this.offset = offset;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
var HsqldbSqlEvaluationError = class extends Error {
|
|
27
|
+
sql;
|
|
28
|
+
constructor(message, sql) {
|
|
29
|
+
super(`HSQLDB SQL evaluation error: ${message} -- in statement: ${truncateForMessage(sql)}`);
|
|
30
|
+
this.name = "HsqldbSqlEvaluationError";
|
|
31
|
+
this.sql = sql;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
//#endregion
|
|
35
|
+
export { HsqldbSqlEvaluationError, HsqldbSqlParseError, HsqldbSqlUnsupportedError };
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_odb_values = require("../values.cjs");
|
|
3
|
+
const require_odb_sql_errors = require("./errors.cjs");
|
|
4
|
+
//#region src/odb/sql/evaluate.ts
|
|
5
|
+
function sqlFailure(sql) {
|
|
6
|
+
return (message) => new require_odb_sql_errors.HsqldbSqlEvaluationError(message, sql);
|
|
7
|
+
}
|
|
8
|
+
function compareValues(left, right, sql) {
|
|
9
|
+
return require_odb_values.compareCellValues(left, right, sqlFailure(sql));
|
|
10
|
+
}
|
|
11
|
+
function truthOfComparison(ordering, operator) {
|
|
12
|
+
switch (operator) {
|
|
13
|
+
case "=": return ordering === 0 ? "true" : "false";
|
|
14
|
+
case "<>": return ordering === 0 ? "false" : "true";
|
|
15
|
+
case "<": return ordering < 0 ? "true" : "false";
|
|
16
|
+
case ">": return ordering > 0 ? "true" : "false";
|
|
17
|
+
case "<=": return ordering <= 0 ? "true" : "false";
|
|
18
|
+
case ">=": return ordering >= 0 ? "true" : "false";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function notTruth(truth) {
|
|
22
|
+
if (truth === "true") return "false";
|
|
23
|
+
return truth === "false" ? "true" : "unknown";
|
|
24
|
+
}
|
|
25
|
+
function andTruth(left, right) {
|
|
26
|
+
if (left === "false" || right === "false") return "false";
|
|
27
|
+
return left === "true" && right === "true" ? "true" : "unknown";
|
|
28
|
+
}
|
|
29
|
+
function orTruth(left, right) {
|
|
30
|
+
if (left === "true" || right === "true") return "true";
|
|
31
|
+
return left === "false" && right === "false" ? "false" : "unknown";
|
|
32
|
+
}
|
|
33
|
+
function literalToValue(literal) {
|
|
34
|
+
switch (literal.kind) {
|
|
35
|
+
case "number": return {
|
|
36
|
+
kind: "number",
|
|
37
|
+
value: literal.value
|
|
38
|
+
};
|
|
39
|
+
case "string": return {
|
|
40
|
+
kind: "string",
|
|
41
|
+
value: literal.value
|
|
42
|
+
};
|
|
43
|
+
case "boolean": return {
|
|
44
|
+
kind: "boolean",
|
|
45
|
+
value: literal.value
|
|
46
|
+
};
|
|
47
|
+
case "null": return require_odb_values.CELL_NULL;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function likePatternToRegExp(pattern) {
|
|
51
|
+
let source = "^";
|
|
52
|
+
for (const character of pattern) if (character === "%") source += "[\\s\\S]*";
|
|
53
|
+
else if (character === "_") source += "[\\s\\S]";
|
|
54
|
+
else source += character.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
55
|
+
return new RegExp(`${source}$`);
|
|
56
|
+
}
|
|
57
|
+
function resolveName(candidates, ref, what, sql) {
|
|
58
|
+
const exact = candidates.find((candidate) => candidate === ref.name);
|
|
59
|
+
if (exact !== void 0) return exact;
|
|
60
|
+
if (!ref.quoted) {
|
|
61
|
+
const folded = candidates.filter((candidate) => candidate.toUpperCase() === ref.name);
|
|
62
|
+
if (folded.length > 1) throw new require_odb_sql_errors.HsqldbSqlEvaluationError(`${what} "${ref.name}" is ambiguous -- it matches ${folded.join(", ")} case-insensitively`, sql);
|
|
63
|
+
const only = folded[0];
|
|
64
|
+
if (only !== void 0) return only;
|
|
65
|
+
}
|
|
66
|
+
throw new require_odb_sql_errors.HsqldbSqlEvaluationError(`${what} "${ref.name}" not found -- available: ${candidates.length === 0 ? "(none)" : candidates.join(", ")}`, sql);
|
|
67
|
+
}
|
|
68
|
+
function resolveTable(tables, ref, sql) {
|
|
69
|
+
const resolvedName = resolveName(tables.map((table) => table.tableName), ref, "table", sql);
|
|
70
|
+
const table = tables.find((candidate) => candidate.tableName === resolvedName);
|
|
71
|
+
if (table === void 0) throw new require_odb_sql_errors.HsqldbSqlEvaluationError(`table "${resolvedName}" not found`, sql);
|
|
72
|
+
return table;
|
|
73
|
+
}
|
|
74
|
+
var ColumnResolver = class {
|
|
75
|
+
table;
|
|
76
|
+
sql;
|
|
77
|
+
cache = /* @__PURE__ */ new Map();
|
|
78
|
+
columnNames;
|
|
79
|
+
constructor(table, sql) {
|
|
80
|
+
this.table = table;
|
|
81
|
+
this.sql = sql;
|
|
82
|
+
this.columnNames = table.columns.map((column) => column.name);
|
|
83
|
+
}
|
|
84
|
+
nameAt(index) {
|
|
85
|
+
const name = this.columnNames[index];
|
|
86
|
+
if (name === void 0) throw new require_odb_sql_errors.HsqldbSqlEvaluationError(`column index ${String(index)} is outside table "${this.table.tableName}"`, this.sql);
|
|
87
|
+
return name;
|
|
88
|
+
}
|
|
89
|
+
indexOf(ref) {
|
|
90
|
+
const cached = this.cache.get(ref);
|
|
91
|
+
if (cached !== void 0) return cached;
|
|
92
|
+
if (ref.qualifier !== void 0) {
|
|
93
|
+
if (resolveName([this.table.tableName], ref.qualifier, "table qualifier", this.sql) !== this.table.tableName) throw new require_odb_sql_errors.HsqldbSqlEvaluationError(`table qualifier "${ref.qualifier.name}" does not name the table in FROM ("${this.table.tableName}")`, this.sql);
|
|
94
|
+
}
|
|
95
|
+
const index = this.columnNames.indexOf(resolveName(this.columnNames, ref.column, "column", this.sql));
|
|
96
|
+
this.cache.set(ref, index);
|
|
97
|
+
return index;
|
|
98
|
+
}
|
|
99
|
+
valueAt(index, row) {
|
|
100
|
+
const value = row[index];
|
|
101
|
+
if (value === void 0) throw new require_odb_sql_errors.HsqldbSqlEvaluationError(`malformed table "${this.table.tableName}": a row carries ${String(row.length)} values but the table declares ${String(this.columnNames.length)} columns`, this.sql);
|
|
102
|
+
return value;
|
|
103
|
+
}
|
|
104
|
+
valueOf(ref, row) {
|
|
105
|
+
return this.valueAt(this.indexOf(ref), row);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
function operandValue(operand, row, resolver) {
|
|
109
|
+
return operand.kind === "literal" ? literalToValue(operand.literal) : resolver.valueOf(operand.column, row);
|
|
110
|
+
}
|
|
111
|
+
function evaluateLike(value, pattern, sql) {
|
|
112
|
+
const key = require_odb_values.cellComparisonKey(value);
|
|
113
|
+
if (key === void 0) return "unknown";
|
|
114
|
+
if (key.valueClass !== "text") throw new require_odb_sql_errors.HsqldbSqlEvaluationError(`LIKE requires a text value, but its left operand is a ${key.valueClass} value`, sql);
|
|
115
|
+
return likePatternToRegExp(pattern).test(key.text) ? "true" : "false";
|
|
116
|
+
}
|
|
117
|
+
function evaluateIn(value, values, sql) {
|
|
118
|
+
if (value.kind === "empty") return "unknown";
|
|
119
|
+
let sawNull = false;
|
|
120
|
+
for (const literal of values) {
|
|
121
|
+
const candidate = literalToValue(literal);
|
|
122
|
+
if (candidate.kind === "empty") {
|
|
123
|
+
sawNull = true;
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (compareValues(value, candidate, sql) === 0) return "true";
|
|
127
|
+
}
|
|
128
|
+
return sawNull ? "unknown" : "false";
|
|
129
|
+
}
|
|
130
|
+
function evaluatePredicate(predicate, row, resolver, sql) {
|
|
131
|
+
switch (predicate.kind) {
|
|
132
|
+
case "comparison": {
|
|
133
|
+
const left = operandValue(predicate.left, row, resolver);
|
|
134
|
+
const right = operandValue(predicate.right, row, resolver);
|
|
135
|
+
if (left.kind === "empty" || right.kind === "empty") return "unknown";
|
|
136
|
+
return truthOfComparison(compareValues(left, right, sql), predicate.operator);
|
|
137
|
+
}
|
|
138
|
+
case "isNull": {
|
|
139
|
+
const isNull = operandValue(predicate.operand, row, resolver).kind === "empty";
|
|
140
|
+
return (predicate.negated ? !isNull : isNull) ? "true" : "false";
|
|
141
|
+
}
|
|
142
|
+
case "like": {
|
|
143
|
+
const truth = evaluateLike(operandValue(predicate.operand, row, resolver), predicate.pattern, sql);
|
|
144
|
+
return predicate.negated ? notTruth(truth) : truth;
|
|
145
|
+
}
|
|
146
|
+
case "in": {
|
|
147
|
+
const truth = evaluateIn(operandValue(predicate.operand, row, resolver), predicate.values, sql);
|
|
148
|
+
return predicate.negated ? notTruth(truth) : truth;
|
|
149
|
+
}
|
|
150
|
+
case "between": {
|
|
151
|
+
const value = operandValue(predicate.operand, row, resolver);
|
|
152
|
+
const lower = operandValue(predicate.lower, row, resolver);
|
|
153
|
+
const upper = operandValue(predicate.upper, row, resolver);
|
|
154
|
+
if (value.kind === "empty" || lower.kind === "empty" || upper.kind === "empty") return "unknown";
|
|
155
|
+
const truth = andTruth(truthOfComparison(compareValues(value, lower, sql), ">="), truthOfComparison(compareValues(value, upper, sql), "<="));
|
|
156
|
+
return predicate.negated ? notTruth(truth) : truth;
|
|
157
|
+
}
|
|
158
|
+
case "not": return notTruth(evaluatePredicate(predicate.predicate, row, resolver, sql));
|
|
159
|
+
case "and": return andTruth(evaluatePredicate(predicate.left, row, resolver, sql), evaluatePredicate(predicate.right, row, resolver, sql));
|
|
160
|
+
case "or": return orTruth(evaluatePredicate(predicate.left, row, resolver, sql), evaluatePredicate(predicate.right, row, resolver, sql));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function aggregateOverValues(aggregate, values, sql) {
|
|
164
|
+
return require_odb_values.aggregateCellValues(aggregate, values, sqlFailure(sql));
|
|
165
|
+
}
|
|
166
|
+
function compareForSort(left, right, sql) {
|
|
167
|
+
const leftNull = left.kind === "empty";
|
|
168
|
+
const rightNull = right.kind === "empty";
|
|
169
|
+
if (leftNull || rightNull) {
|
|
170
|
+
if (leftNull && rightNull) return 0;
|
|
171
|
+
return leftNull ? 1 : -1;
|
|
172
|
+
}
|
|
173
|
+
return compareValues(left, right, sql);
|
|
174
|
+
}
|
|
175
|
+
function sortRows(rows, directions, sql) {
|
|
176
|
+
return [...rows].sort((left, right) => {
|
|
177
|
+
for (const [index, direction] of directions.entries()) {
|
|
178
|
+
const leftKey = left.sortKeys[index];
|
|
179
|
+
const rightKey = right.sortKeys[index];
|
|
180
|
+
if (leftKey === void 0 || rightKey === void 0) throw new require_odb_sql_errors.HsqldbSqlEvaluationError("an ORDER BY term has no sort key on this row", sql);
|
|
181
|
+
const ordering = compareForSort(leftKey, rightKey, sql);
|
|
182
|
+
if (ordering !== 0) return direction === "asc" ? ordering : -ordering;
|
|
183
|
+
}
|
|
184
|
+
return 0;
|
|
185
|
+
}).map((row) => row.output);
|
|
186
|
+
}
|
|
187
|
+
function groupKeyOf(values) {
|
|
188
|
+
return values.map((value) => {
|
|
189
|
+
switch (value.kind) {
|
|
190
|
+
case "empty": return "null";
|
|
191
|
+
case "boolean": return `boolean:${String(value.value)}`;
|
|
192
|
+
case "number":
|
|
193
|
+
case "percentage":
|
|
194
|
+
case "currency": return `numeric:${String(value.value)}`;
|
|
195
|
+
case "date":
|
|
196
|
+
case "time":
|
|
197
|
+
case "dateTime":
|
|
198
|
+
case "string":
|
|
199
|
+
case "error": return `text:${value.value}`;
|
|
200
|
+
}
|
|
201
|
+
}).join("\0");
|
|
202
|
+
}
|
|
203
|
+
function planSelectList(statement, table, resolver) {
|
|
204
|
+
const plan = [];
|
|
205
|
+
for (const item of statement.items) switch (item.kind) {
|
|
206
|
+
case "star":
|
|
207
|
+
for (const [index] of table.columns.entries()) plan.push({
|
|
208
|
+
kind: "column",
|
|
209
|
+
index,
|
|
210
|
+
text: resolver.nameAt(index)
|
|
211
|
+
});
|
|
212
|
+
break;
|
|
213
|
+
case "column":
|
|
214
|
+
plan.push({
|
|
215
|
+
kind: "column",
|
|
216
|
+
index: resolver.indexOf(item.column),
|
|
217
|
+
text: item.column.text
|
|
218
|
+
});
|
|
219
|
+
break;
|
|
220
|
+
case "aggregate": plan.push({
|
|
221
|
+
kind: "aggregate",
|
|
222
|
+
aggregate: item.aggregate,
|
|
223
|
+
argumentIndex: item.argument.kind === "star" ? void 0 : resolver.indexOf(item.argument.column),
|
|
224
|
+
outputName: item.outputName
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
return plan;
|
|
228
|
+
}
|
|
229
|
+
function planColumnNames(plan, resolver) {
|
|
230
|
+
return plan.map((item) => item.kind === "column" ? resolver.nameAt(item.index) : item.outputName);
|
|
231
|
+
}
|
|
232
|
+
function evaluateUngrouped(statement, plan, matching, resolver) {
|
|
233
|
+
const projection = plan.map((item) => {
|
|
234
|
+
if (item.kind !== "column") throw new require_odb_sql_errors.HsqldbSqlEvaluationError(`${item.outputName} is an aggregate, so every other select-list item must be grouped`, statement.sql);
|
|
235
|
+
return item.index;
|
|
236
|
+
});
|
|
237
|
+
const orderIndices = statement.orderBy.map((term) => resolver.indexOf(term.column));
|
|
238
|
+
const sortable = matching.map((row) => ({
|
|
239
|
+
output: projection.map((index) => resolver.valueAt(index, row)),
|
|
240
|
+
sortKeys: orderIndices.map((index) => resolver.valueAt(index, row))
|
|
241
|
+
}));
|
|
242
|
+
return {
|
|
243
|
+
columns: planColumnNames(plan, resolver),
|
|
244
|
+
rows: sortRows(sortable, statement.orderBy.map((term) => term.direction), statement.sql)
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
function partitionIntoGroups(rows, groupIndices, resolver) {
|
|
248
|
+
const groups = /* @__PURE__ */ new Map();
|
|
249
|
+
for (const row of rows) {
|
|
250
|
+
const keyValues = groupIndices.map((index) => resolver.valueAt(index, row));
|
|
251
|
+
const key = groupKeyOf(keyValues);
|
|
252
|
+
const existing = groups.get(key);
|
|
253
|
+
if (existing === void 0) groups.set(key, {
|
|
254
|
+
keyValues,
|
|
255
|
+
rows: [row]
|
|
256
|
+
});
|
|
257
|
+
else existing.rows.push(row);
|
|
258
|
+
}
|
|
259
|
+
return [...groups.values()];
|
|
260
|
+
}
|
|
261
|
+
function evaluateGrouped(statement, plan, matching, resolver) {
|
|
262
|
+
const groupIndices = statement.groupBy.map((ref) => resolver.indexOf(ref));
|
|
263
|
+
for (const item of plan) if (item.kind === "column" && !groupIndices.includes(item.index)) throw new require_odb_sql_errors.HsqldbSqlEvaluationError(`column "${item.text}" is neither grouped nor aggregated -- add it to GROUP BY or wrap it in an aggregate`, statement.sql);
|
|
264
|
+
const groups = groupIndices.length === 0 ? [{
|
|
265
|
+
keyValues: [],
|
|
266
|
+
rows: [...matching]
|
|
267
|
+
}] : partitionIntoGroups(matching, groupIndices, resolver);
|
|
268
|
+
const orderPositions = statement.orderBy.map((term) => {
|
|
269
|
+
const position = groupIndices.indexOf(resolver.indexOf(term.column));
|
|
270
|
+
if (position < 0) throw new require_odb_sql_errors.HsqldbSqlEvaluationError(`ORDER BY column "${term.column.text}" is not a GROUP BY column -- a grouped result has no single value for it`, statement.sql);
|
|
271
|
+
return position;
|
|
272
|
+
});
|
|
273
|
+
const sortable = groups.map((group) => ({
|
|
274
|
+
output: plan.map((item) => {
|
|
275
|
+
if (item.kind === "aggregate") {
|
|
276
|
+
const argumentIndex = item.argumentIndex;
|
|
277
|
+
if (argumentIndex === void 0) return {
|
|
278
|
+
kind: "number",
|
|
279
|
+
value: group.rows.length
|
|
280
|
+
};
|
|
281
|
+
return aggregateOverValues(item.aggregate, group.rows.map((row) => resolver.valueAt(argumentIndex, row)), statement.sql);
|
|
282
|
+
}
|
|
283
|
+
const keyValue = group.keyValues[groupIndices.indexOf(item.index)];
|
|
284
|
+
if (keyValue === void 0) throw new require_odb_sql_errors.HsqldbSqlEvaluationError(`grouped column "${item.text}" has no value on this group`, statement.sql);
|
|
285
|
+
return keyValue;
|
|
286
|
+
}),
|
|
287
|
+
sortKeys: orderPositions.map((position) => {
|
|
288
|
+
const keyValue = group.keyValues[position];
|
|
289
|
+
if (keyValue === void 0) throw new require_odb_sql_errors.HsqldbSqlEvaluationError("an ORDER BY term resolved to a GROUP BY column with no value on this group", statement.sql);
|
|
290
|
+
return keyValue;
|
|
291
|
+
})
|
|
292
|
+
}));
|
|
293
|
+
return {
|
|
294
|
+
columns: planColumnNames(plan, resolver),
|
|
295
|
+
rows: sortRows(sortable, statement.orderBy.map((term) => term.direction), statement.sql)
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
function evaluateSelect(statement, tables) {
|
|
299
|
+
const table = resolveTable(tables, statement.from, statement.sql);
|
|
300
|
+
const resolver = new ColumnResolver(table, statement.sql);
|
|
301
|
+
const plan = planSelectList(statement, table, resolver);
|
|
302
|
+
const where = statement.where;
|
|
303
|
+
const matching = where === void 0 ? table.rows : table.rows.filter((row) => evaluatePredicate(where, row, resolver, statement.sql) === "true");
|
|
304
|
+
const hasAggregate = plan.some((item) => item.kind === "aggregate");
|
|
305
|
+
if (statement.groupBy.length > 0 || hasAggregate) {
|
|
306
|
+
if (statement.groupBy.length > 0 && statement.items.some((item) => item.kind === "star")) throw new require_odb_sql_errors.HsqldbSqlEvaluationError("SELECT * is not valid with GROUP BY -- name the grouped columns and the aggregates explicitly", statement.sql);
|
|
307
|
+
return evaluateGrouped(statement, plan, matching, resolver);
|
|
308
|
+
}
|
|
309
|
+
return evaluateUngrouped(statement, plan, matching, resolver);
|
|
310
|
+
}
|
|
311
|
+
//#endregion
|
|
312
|
+
exports.evaluateSelect = evaluateSelect;
|