semanticdb-v2 2.0.0-alpha.1 → 2.0.0-alpha.11
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 +346 -46
- package/dist/cache/index.d.ts +2 -1
- package/dist/cache/manager.d.ts +5 -0
- package/dist/cache/registry.d.ts +14 -0
- package/dist/cache/types.d.ts +17 -0
- package/dist/close.d.ts +1 -0
- package/dist/compatibility/index.d.ts +2 -2
- package/dist/compatibility/logicform.d.ts +1 -7
- package/dist/compiler/compile-cte.d.ts +17 -2
- package/dist/compiler/index.d.ts +2 -1
- package/dist/compiler/shorten-sql.d.ts +1 -1
- package/dist/errors.d.ts +3 -0
- package/dist/executor/compatibility.d.ts +13 -0
- package/dist/executor/components.d.ts +8 -3
- package/dist/executor/connection-registry.d.ts +1 -12
- package/dist/executor/execute-query.d.ts +8 -2
- package/dist/executor/execute.d.ts +1 -1
- package/dist/executor/federated-execution.d.ts +39 -0
- package/dist/executor/fetch-entities.d.ts +7 -1
- package/dist/executor/index.d.ts +1 -1
- package/dist/executor/partition.d.ts +17 -0
- package/dist/executor/result-hydrator/types.d.ts +2 -0
- package/dist/executor/row-identity.d.ts +2 -1
- package/dist/executor/total.d.ts +11 -0
- package/dist/executor/types.d.ts +70 -21
- package/dist/i18n/index.d.ts +4 -0
- package/dist/i18n/locales/en-US.d.ts +2 -0
- package/dist/i18n/locales/zh-CN.d.ts +2 -0
- package/dist/i18n/registry.d.ts +13 -0
- package/dist/i18n/types.d.ts +9 -0
- package/dist/index.d.ts +18 -16
- package/dist/logicform/dimensions.d.ts +16 -0
- package/dist/logicform/index.d.ts +2 -0
- package/dist/logicform-types.d.ts +56 -36
- package/dist/normalizer/core.d.ts +17 -3
- package/dist/normalizer/default-pred-name.d.ts +2 -0
- package/dist/normalizer/index.d.ts +1 -0
- package/dist/normalizer/pred-expression.d.ts +6 -0
- package/dist/normalizer/property-resolve.d.ts +6 -0
- package/dist/operators/builtins/constant.d.ts +2 -0
- package/dist/operators/builtins/period-name.d.ts +2 -1
- package/dist/operators/builtins/period-value.d.ts +2 -0
- package/dist/operators/builtins/query-expression.d.ts +3 -0
- package/dist/operators/builtins/scalar-extremum.d.ts +3 -0
- package/dist/operators/index.d.ts +2 -1
- package/dist/operators/registry.d.ts +5 -3
- package/dist/operators/resolve.d.ts +3 -0
- package/dist/operators/types.d.ts +110 -50
- package/dist/physical/clickhouse-provider.d.ts +29 -2
- package/dist/physical/connection-registry.d.ts +13 -0
- package/dist/physical/connection.d.ts +57 -15
- package/dist/physical/dameng-provider.d.ts +66 -0
- package/dist/physical/databricks-provider.d.ts +88 -0
- package/dist/physical/db-connector.d.ts +23 -0
- package/dist/physical/display-query.d.ts +3 -0
- package/dist/physical/doris-provider.d.ts +7 -1
- package/dist/physical/duckdb-coordinator-provider.d.ts +37 -0
- package/dist/physical/gbase-provider.d.ts +11 -0
- package/dist/physical/index.d.ts +24 -9
- package/dist/physical/load-driver.d.ts +1 -0
- package/dist/physical/maxcompute-provider.d.ts +44 -0
- package/dist/physical/mysql-protocol-provider.d.ts +27 -7
- package/dist/physical/mysql-provider.d.ts +2 -1
- package/dist/physical/oracle-provider.d.ts +21 -4
- package/dist/physical/postgresql-provider.d.ts +25 -4
- package/dist/physical/provider.d.ts +66 -2
- package/dist/physical/snowflake-provider.d.ts +20 -3
- package/dist/physical/sqlserver-provider.d.ts +69 -0
- package/dist/physical/starrocks-provider.d.ts +7 -1
- package/dist/physical/table-description.d.ts +5 -0
- package/dist/physical/table-discovery.d.ts +10 -0
- package/dist/planner/build-lineage.d.ts +1 -1
- package/dist/planner/build-mapping-source-plan.d.ts +6 -0
- package/dist/planner/create-logical-plan.d.ts +11 -0
- package/dist/planner/index.d.ts +4 -2
- package/dist/planner/mapping-granularity.d.ts +7 -0
- package/dist/planner/rewrite-nested-components.d.ts +8 -0
- package/dist/planner/select-schema-mapping.d.ts +19 -2
- package/dist/planner/semantics/index.d.ts +0 -3
- package/dist/planner/semantics/periods.d.ts +13 -0
- package/dist/planner/semantics/registry-defaults.d.ts +2 -1
- package/dist/planner/semantics/registry.d.ts +2 -1
- package/dist/planner/types.d.ts +106 -14
- package/dist/plugins/hierarchy/index.d.ts +1 -1
- package/dist/plugins/hierarchy/mapping-granularity.d.ts +4 -0
- package/dist/plugins/hierarchy/types.d.ts +20 -2
- package/dist/plugins/index.d.ts +10 -1
- package/dist/{planner/semantics → plugins}/observation/classification.d.ts +1 -1
- package/dist/plugins/observation/index.d.ts +17 -0
- package/dist/{planner/semantics → plugins}/observation/operator-policy.d.ts +4 -5
- package/dist/plugins/observation/periods.d.ts +18 -0
- package/dist/{planner/semantics → plugins}/observation/rule.d.ts +1 -1
- package/dist/plugins/observation/types.d.ts +3 -0
- package/dist/plugins/property-hierarchy/index.d.ts +11 -0
- package/dist/plugins/recursive/index.d.ts +26 -0
- package/dist/plugins/temporal/index.d.ts +13 -0
- package/dist/plugins/types.d.ts +165 -1
- package/dist/plugins/validity/classification.d.ts +5 -0
- package/dist/plugins/validity/index.d.ts +15 -0
- package/dist/plugins/validity/periods.d.ts +15 -0
- package/dist/plugins/validity/query-policy.d.ts +3 -0
- package/dist/plugins/validity/rule.d.ts +2 -0
- package/dist/plugins/validity/semantic-types.d.ts +3 -0
- package/dist/schema/dependent-projection.d.ts +8 -0
- package/dist/schema/entity-identity.d.ts +1 -1
- package/dist/schema/index.d.ts +1 -0
- package/dist/schema-mappings/freshness.d.ts +1 -1
- package/dist/schema-mappings/granularity.d.ts +5 -0
- package/dist/schema-mappings/index.d.ts +5 -1
- package/dist/schema-mappings/registry.d.ts +7 -3
- package/dist/schema-mappings/supported-dimensions.d.ts +10 -0
- package/dist/schema-mappings/types.d.ts +59 -9
- package/dist/schema-mappings/yiask.d.ts +27 -0
- package/dist/semantic-types/builtins/tag.d.ts +2 -0
- package/dist/semantic-types/index.d.ts +5 -3
- package/dist/semantic-types/registry.d.ts +2 -0
- package/dist/semantic-types/resolve-schema.d.ts +1 -1
- package/dist/semantic-types/types.d.ts +51 -11
- package/dist/semantic-types/validate-resolved-schema.d.ts +2 -5
- package/dist/semanticdb.esm.js +5 -0
- package/dist/semanticdb.js +5 -0
- package/package.json +49 -17
- package/dist/cache/expiry.js +0 -1
- package/dist/cache/identity.js +0 -1
- package/dist/cache/redis-query-cache.js +0 -1
- package/dist/cache/serialization.js +0 -1
- package/dist/calendar/constants.d.ts +0 -7
- package/dist/calendar/constants.js +0 -1
- package/dist/calendar/index.d.ts +0 -6
- package/dist/calendar/provider-relation-store.d.ts +0 -9
- package/dist/calendar/provider-relation-store.js +0 -1
- package/dist/calendar/resolver.d.ts +0 -10
- package/dist/calendar/resolver.js +0 -1
- package/dist/calendar/system-schemas.d.ts +0 -3
- package/dist/calendar/system-schemas.js +0 -1
- package/dist/calendar/types.d.ts +0 -31
- package/dist/compatibility/logicform.js +0 -1
- package/dist/compiler/compile-cte.js +0 -1
- package/dist/compiler/compile-plan.js +0 -1
- package/dist/compiler/shorten-sql.js +0 -2
- package/dist/custom-functions/custom-functions.d.ts +0 -6
- package/dist/custom-functions/custom-functions.js +0 -1
- package/dist/custom-functions/index.d.ts +0 -3
- package/dist/custom-functions/operator-adapter.d.ts +0 -12
- package/dist/custom-functions/operator-adapter.js +0 -1
- package/dist/custom-functions/types.d.ts +0 -62
- package/dist/errors.js +0 -1
- package/dist/executor/compatibility.js +0 -1
- package/dist/executor/components.js +0 -1
- package/dist/executor/connection-registry.js +0 -1
- package/dist/executor/evaluate.js +0 -1
- package/dist/executor/execute-query.js +0 -1
- package/dist/executor/execute.js +0 -1
- package/dist/executor/fetch-entities.js +0 -1
- package/dist/executor/result-hydrator/entity-loader.js +0 -1
- package/dist/executor/result-hydrator/format-values.js +0 -1
- package/dist/executor/result-hydrator/hydrate-result.js +0 -1
- package/dist/executor/result-hydrator/missing-entity.js +0 -1
- package/dist/executor/result-hydrator/populate-entities.js +0 -1
- package/dist/executor/row-identity.js +0 -1
- package/dist/index.js +0 -1
- package/dist/logicform-types.js +0 -1
- package/dist/normalizer/core.js +0 -1
- package/dist/normalizer/default-pred-name.js +0 -1
- package/dist/normalizer/entity-id.js +0 -1
- package/dist/normalizer/groupby.js +0 -1
- package/dist/normalizer/normalize-logicform.js +0 -1
- package/dist/normalizer/pagination.js +0 -1
- package/dist/normalizer/pred-query-name.js +0 -1
- package/dist/normalizer/preds.js +0 -1
- package/dist/normalizer/query.js +0 -1
- package/dist/normalizer/version.js +0 -1
- package/dist/operators/builtins/abs.js +0 -1
- package/dist/operators/builtins/accumulate.js +0 -1
- package/dist/operators/builtins/add.js +0 -1
- package/dist/operators/builtins/arithmetic.js +0 -1
- package/dist/operators/builtins/average-per-period.js +0 -1
- package/dist/operators/builtins/avg.js +0 -1
- package/dist/operators/builtins/case.js +0 -1
- package/dist/operators/builtins/concat.js +0 -1
- package/dist/operators/builtins/count-distinct.js +0 -1
- package/dist/operators/builtins/count.js +0 -1
- package/dist/operators/builtins/date-bucket.js +0 -1
- package/dist/operators/builtins/divide.js +0 -1
- package/dist/operators/builtins/index.js +0 -1
- package/dist/operators/builtins/max.js +0 -1
- package/dist/operators/builtins/min.js +0 -1
- package/dist/operators/builtins/multiply.js +0 -1
- package/dist/operators/builtins/newly.js +0 -1
- package/dist/operators/builtins/period-boundary.js +0 -1
- package/dist/operators/builtins/period-difference.js +0 -1
- package/dist/operators/builtins/period-growth.js +0 -1
- package/dist/operators/builtins/period-name.js +0 -1
- package/dist/operators/builtins/period-shift.js +0 -1
- package/dist/operators/builtins/rank.js +0 -1
- package/dist/operators/builtins/row-number.js +0 -1
- package/dist/operators/builtins/share-of-total.js +0 -1
- package/dist/operators/builtins/sql.js +0 -1
- package/dist/operators/builtins/substring.js +0 -1
- package/dist/operators/builtins/subtract.js +0 -1
- package/dist/operators/builtins/sum.js +0 -1
- package/dist/operators/builtins/time-range.js +0 -1
- package/dist/operators/groupby.js +0 -1
- package/dist/operators/index.js +0 -1
- package/dist/operators/registry.js +0 -1
- package/dist/operators/sql-expression.js +0 -1
- package/dist/permissions/permissions.js +0 -1
- package/dist/physical/clickhouse-provider.js +0 -1
- package/dist/physical/connection.js +0 -1
- package/dist/physical/display-query.js +0 -1
- package/dist/physical/doris-provider.js +0 -1
- package/dist/physical/mysql-compatible-sql.js +0 -1
- package/dist/physical/mysql-protocol-provider.js +0 -1
- package/dist/physical/mysql-provider.js +0 -1
- package/dist/physical/oracle-provider.js +0 -1
- package/dist/physical/postgresql-provider.js +0 -1
- package/dist/physical/snowflake-provider.js +0 -1
- package/dist/physical/starrocks-provider.js +0 -1
- package/dist/planner/build-lineage.js +0 -1
- package/dist/planner/create-logical-plan.js +0 -1
- package/dist/planner/select-schema-mapping.js +0 -1
- package/dist/planner/semantics/lifecycle/classification.d.ts +0 -7
- package/dist/planner/semantics/lifecycle/classification.js +0 -1
- package/dist/planner/semantics/lifecycle/index.d.ts +0 -3
- package/dist/planner/semantics/lifecycle/query-policy.d.ts +0 -3
- package/dist/planner/semantics/lifecycle/query-policy.js +0 -1
- package/dist/planner/semantics/lifecycle/rule.d.ts +0 -2
- package/dist/planner/semantics/lifecycle/rule.js +0 -1
- package/dist/planner/semantics/observation/classification.js +0 -1
- package/dist/planner/semantics/observation/index.d.ts +0 -4
- package/dist/planner/semantics/observation/operator-policy.js +0 -1
- package/dist/planner/semantics/observation/rule.js +0 -1
- package/dist/planner/semantics/observation/types.d.ts +0 -3
- package/dist/planner/semantics/registry-defaults.js +0 -1
- package/dist/planner/semantics/registry.js +0 -1
- package/dist/planner/types.js +0 -1
- package/dist/plugins/hierarchy/compatibility.js +0 -1
- package/dist/plugins/hierarchy/entity-identity.js +0 -1
- package/dist/plugins/hierarchy/index.js +0 -1
- package/dist/plugins/hierarchy/operator.js +0 -1
- package/dist/plugins/hierarchy/resolve-schema.js +0 -1
- package/dist/plugins/index.js +0 -1
- package/dist/schema/entity-identity.js +0 -1
- package/dist/schema/resolve-property-path.js +0 -1
- package/dist/schema/schema-registry.js +0 -1
- package/dist/schema-mappings/freshness.js +0 -1
- package/dist/schema-mappings/registry.js +0 -1
- package/dist/semantic-types/builtins/boolean.js +0 -1
- package/dist/semantic-types/builtins/category.js +0 -1
- package/dist/semantic-types/builtins/currency.js +0 -1
- package/dist/semantic-types/builtins/date.js +0 -1
- package/dist/semantic-types/builtins/duration.js +0 -1
- package/dist/semantic-types/builtins/end-date.d.ts +0 -2
- package/dist/semantic-types/builtins/end-date.js +0 -1
- package/dist/semantic-types/builtins/entity.js +0 -1
- package/dist/semantic-types/builtins/file.js +0 -1
- package/dist/semantic-types/builtins/human-name.js +0 -1
- package/dist/semantic-types/builtins/id.js +0 -1
- package/dist/semantic-types/builtins/image.js +0 -1
- package/dist/semantic-types/builtins/index.js +0 -1
- package/dist/semantic-types/builtins/int.js +0 -1
- package/dist/semantic-types/builtins/name.js +0 -1
- package/dist/semantic-types/builtins/number.js +0 -1
- package/dist/semantic-types/builtins/object.js +0 -1
- package/dist/semantic-types/builtins/order.js +0 -1
- package/dist/semantic-types/builtins/percentage.js +0 -1
- package/dist/semantic-types/builtins/start-date.d.ts +0 -2
- package/dist/semantic-types/builtins/start-date.js +0 -1
- package/dist/semantic-types/builtins/string.js +0 -1
- package/dist/semantic-types/builtins/timestamp.js +0 -1
- package/dist/semantic-types/index.js +0 -1
- package/dist/semantic-types/primal-types/date.js +0 -1
- package/dist/semantic-types/primal-types/index.js +0 -1
- package/dist/semantic-types/registry.js +0 -1
- package/dist/semantic-types/resolve-schema.js +0 -1
- package/dist/semantic-types/validate-resolved-schema.js +0 -1
- package/dist/utils/clone.js +0 -1
- /package/dist/operators/builtins/{period-boundary.d.ts → period-boundary-expression.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -1,23 +1,37 @@
|
|
|
1
1
|
# SemanticDB
|
|
2
2
|
|
|
3
|
-
SemanticDB translates its own LogicForm into SQL and executes it on
|
|
3
|
+
SemanticDB translates its own LogicForm into SQL and executes it on one or more core compute layers.
|
|
4
4
|
Callers provide schemas, schema mappings, operators, and database connection information.
|
|
5
5
|
SemanticDB creates the matching provider and owns its connection lifecycle.
|
|
6
6
|
|
|
7
|
+
Install SemanticDB together with only the database driver used by the application. Database
|
|
8
|
+
drivers are optional peer dependencies and are loaded on the first execution for that connection;
|
|
9
|
+
Redis cache support is included by the main package.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install semanticdb-v2 mysql2
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Use `@clickhouse/client`, `@databricks/sql`, `dmdb`, `mysql2` (MySQL, Doris, StarRocks, and GBase),
|
|
16
|
+
`mssql`, `pg`, `snowflake-sdk`, or `oracledb` for the corresponding connection kind. MaxCompute
|
|
17
|
+
uses a caller-supplied parameterized execution client. If a configured driver is missing, execution
|
|
18
|
+
fails with an installation command for that driver. SemanticDB caches its internally created
|
|
19
|
+
providers across executions; call `await Logicform.close()` during application shutdown.
|
|
20
|
+
|
|
7
21
|
## Public API
|
|
8
22
|
|
|
9
23
|
```ts
|
|
10
24
|
import { Logicform } from 'semanticdb-v2';
|
|
11
|
-
import { SchemaMappingRegistry } from 'semanticdb-v2';
|
|
12
25
|
|
|
13
|
-
const schemaMappings =
|
|
26
|
+
const schemaMappings = [
|
|
14
27
|
{
|
|
15
28
|
schemaId: 'sales',
|
|
16
29
|
connectionId: 'analytics',
|
|
17
30
|
source: 'analytics.sales_detail',
|
|
31
|
+
mappings: [],
|
|
18
32
|
freshness: { mode: 'ttl', ttlSeconds: 300 },
|
|
19
33
|
},
|
|
20
|
-
]
|
|
34
|
+
];
|
|
21
35
|
|
|
22
36
|
const response = await Logicform.execute(
|
|
23
37
|
{
|
|
@@ -34,8 +48,9 @@ const response = await Logicform.execute(
|
|
|
34
48
|
connections: [{
|
|
35
49
|
id: 'analytics',
|
|
36
50
|
kind: 'clickhouse',
|
|
37
|
-
|
|
38
|
-
|
|
51
|
+
host: 'localhost',
|
|
52
|
+
port: 8123,
|
|
53
|
+
user: 'default',
|
|
39
54
|
password: process.env.CLICKHOUSE_PASSWORD,
|
|
40
55
|
database: 'analytics',
|
|
41
56
|
}],
|
|
@@ -49,27 +64,43 @@ const response = await Logicform.execute(
|
|
|
49
64
|
);
|
|
50
65
|
```
|
|
51
66
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
67
|
+
A successful response always includes `total`, the number of result rows before global
|
|
68
|
+
`limit`/`page` pagination. For grouped LogicForms this is the number of groups after `having` and
|
|
69
|
+
`limitBy`. Paginated physical queries include a separate `sqls` entry with `type: 'total'` for the
|
|
70
|
+
count query; unpaginated and executor-merged results derive the value without another SQL query.
|
|
71
|
+
|
|
72
|
+
The v2 LogicForm contract requires `version` on executable LogicForms, including LogicForm objects
|
|
73
|
+
used as subqueries, and accepts semantic versions greater than or equal to `2.0`. At the public
|
|
74
|
+
`Logicform.execute()` boundary, versionless and 1.x legacy input is converted to 2.0 before v2
|
|
75
|
+
normalization; malformed and other unsupported versions fail with `UNSUPPORTED_LOGICFORM_VERSION`.
|
|
76
|
+
Direct use of the v2 normalizer requires a supported version. A relation query shaped as
|
|
77
|
+
`{ schema, query }` is part of its parent LogicForm and inherits the parent's version.
|
|
56
78
|
|
|
57
79
|
PredItems without an explicit `name` receive a human-readable name during normalization. Generated
|
|
58
80
|
names default to Chinese; pass `locale: 'en-US'` in `ExecuteOptions` for the built-in English
|
|
59
|
-
names.
|
|
81
|
+
names. SemanticDB ships `zh-CN` and `en-US` locale files backed by i18next. Applications can add or
|
|
82
|
+
override locale files through `ExecuteOptions.locales`:
|
|
60
83
|
|
|
61
84
|
```ts
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
:
|
|
67
|
-
|
|
68
|
-
|
|
85
|
+
await Logicform.execute(logicform, {
|
|
86
|
+
locale: 'ja-JP',
|
|
87
|
+
locales: {
|
|
88
|
+
locale: 'ja-JP',
|
|
89
|
+
messages: {
|
|
90
|
+
'operator.$sum': '{operandName}の合計',
|
|
91
|
+
'component.numerator': '{outputName} 分子',
|
|
92
|
+
'component.denominator': '{outputName} 分母',
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
// schemas, schemaMappings, connections, ...
|
|
69
96
|
});
|
|
70
97
|
```
|
|
71
98
|
|
|
72
|
-
|
|
99
|
+
Locale lookup uses the exact locale first, then the matching language, and finally `zh-CN`.
|
|
100
|
+
Multiple locale files can be supplied as an array. A custom operator still owns its fallback name
|
|
101
|
+
through `defaultName()` and can call the context's `t()` helper when it defines translation keys.
|
|
102
|
+
|
|
103
|
+
The same locale applies to `preds`, `groupby`, nested expressions, custom-function subqueries,
|
|
73
104
|
and entity-population queries. A PredItem's normalized `query` is included in its
|
|
74
105
|
generated name, for example `门店为上海的销售额合计`. Operator-specific `args` also participate
|
|
75
106
|
through each operator's `defaultName()`; period operators distinguish同比、环比 and other offsets.
|
|
@@ -78,7 +109,8 @@ An explicitly authored `name` is preserved unchanged.
|
|
|
78
109
|
`entity_id` identifies one entity by `hierarchy.property` on hierarchy Schemas and by the unique
|
|
79
110
|
`type: 'ID'` property on other Schemas. Normalization adds that identity filter unless the query
|
|
80
111
|
already contains one, in which case the explicit query wins. The legacy value `placeholder` is
|
|
81
|
-
preserved as entity context but never becomes a SQL filter.
|
|
112
|
+
preserved as entity context but never becomes a SQL filter. String IDs and safe-integer IDs are
|
|
113
|
+
accepted and retain their original type. This also applies to relation queries
|
|
82
114
|
shaped as `{ schema, query, entity_id }`. `representation` is presentation metadata for frontend
|
|
83
115
|
consumers and does not change normalization, planning, or execution. See
|
|
84
116
|
[Hierarchy plugin](docs/hierarchy-plugin.md) for Schema configuration, `$hierarchyLevel`, legacy
|
|
@@ -89,12 +121,18 @@ Plugins may own Schema metadata, legacy conversion, `entity_id` selection, and O
|
|
|
89
121
|
remaining scoped to one execution. See [Register an external plugin](docs/register-plugin.md).
|
|
90
122
|
|
|
91
123
|
Parent-child Schemas may declare `parentProperty`. `$recursive` filters a property to a root node and
|
|
92
|
-
all descendants; object properties infer the tree Schema from `ref`. MySQL, Doris, StarRocks,
|
|
93
|
-
PostgreSQL compile this as a parameterized recursive CTE.
|
|
124
|
+
all descendants; object properties infer the tree Schema from `ref`. MySQL, Doris, StarRocks,
|
|
125
|
+
PostgreSQL, ClickHouse 24.4+, and Databricks compile this as a parameterized recursive CTE.
|
|
94
126
|
|
|
95
127
|
Top-level projections may set `schema` to read metrics from another registered Schema. SemanticDB
|
|
96
128
|
splits those projections into independent provider queries, aligns shared query/groupby dimensions,
|
|
97
129
|
and merges rows by the group keys before applying `having`, `sort`, `limitBy`, and pagination.
|
|
130
|
+
When the selected Schema mappings use separate physical connections, SemanticDB executes every
|
|
131
|
+
single-connection fragment with its native provider and registers the aggregated fragment results
|
|
132
|
+
in an in-process DuckDB coordinator. DuckDB applies the final full-outer group merge, cross-fragment
|
|
133
|
+
conditions, ordering, totals, and pagination. It is embedded in the Node.js process and does not
|
|
134
|
+
require a service or listening port. `federation.maxMaterializedRows` limits the total number of
|
|
135
|
+
fragment rows admitted to the coordinator and defaults to 100,000.
|
|
98
136
|
|
|
99
137
|
The progress stream emits `started`, `validated`, `normalized`, `planned`, `lineage`,
|
|
100
138
|
`compiled`, `executing`, `hydrating`, `result`, and `completed`. Every event includes a cumulative
|
|
@@ -107,7 +145,11 @@ SQL string for diagnostics:
|
|
|
107
145
|
|
|
108
146
|
```ts
|
|
109
147
|
interface ExecutedSql {
|
|
110
|
-
type: 'semantic-resolution' | 'computation';
|
|
148
|
+
type: 'semantic-resolution' | 'computation' | 'total';
|
|
149
|
+
connectionId?: string;
|
|
150
|
+
provider?: CoreComputeProvider['kind'];
|
|
151
|
+
explain: string;
|
|
152
|
+
logicform: LogicformType;
|
|
111
153
|
sql: string;
|
|
112
154
|
parameters: readonly unknown[];
|
|
113
155
|
displaySql: string;
|
|
@@ -115,14 +157,127 @@ interface ExecutedSql {
|
|
|
115
157
|
```
|
|
116
158
|
|
|
117
159
|
`semantic-resolution` identifies supporting SQL used to resolve semantic input or output, such as
|
|
118
|
-
|
|
160
|
+
time-watermark resolution and object entity population. `computation` identifies SQL that calculates
|
|
119
161
|
the requested LogicForm result. `sqls` includes every physical SQL involved in the execution; an
|
|
120
162
|
entry remains visible when its result is served by the query cache.
|
|
163
|
+
Coordinator SQL uses the reserved connection id `__semanticdb_coordinator__` and provider
|
|
164
|
+
`duckdb`; other entries identify the physical connection that executed them. Successful results
|
|
165
|
+
also expose `providers`, the physical connection/provider pairs that contributed rows. The legacy
|
|
166
|
+
singular `provider` field is `duckdb` for a federated result.
|
|
121
167
|
|
|
122
168
|
Providers execute only parameterized `sql + parameters`; SemanticDB never executes `displaySql`.
|
|
123
169
|
Because `displaySql` contains literal values and may expose sensitive data, use it only in trusted
|
|
124
170
|
debugging and observability channels.
|
|
125
171
|
|
|
172
|
+
### Native SQL and table discovery
|
|
173
|
+
|
|
174
|
+
`DBConnector` provides trusted physical database operations independently of LogicForm execution:
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
import { DBConnector, Logicform } from 'semanticdb-v2';
|
|
178
|
+
import type { DatabaseConnection } from 'semanticdb-v2';
|
|
179
|
+
|
|
180
|
+
const connection = {
|
|
181
|
+
id: 'analytics',
|
|
182
|
+
kind: 'mysql',
|
|
183
|
+
host: 'localhost',
|
|
184
|
+
user: 'analytics',
|
|
185
|
+
password: process.env.MYSQL_PASSWORD ?? '',
|
|
186
|
+
database: 'analytics',
|
|
187
|
+
} satisfies DatabaseConnection;
|
|
188
|
+
|
|
189
|
+
const tables = await DBConnector.getTableList({ connection });
|
|
190
|
+
// [{ name: 'orders', database: 'analytics', type: 'table' }, ...]
|
|
191
|
+
|
|
192
|
+
const description = await DBConnector.describeTable({ connection, table: 'orders' });
|
|
193
|
+
// {
|
|
194
|
+
// columns: [{ name: 'id', type: 'int', comment: 'Order ID', primaryKey: true, exampleValue: 42 }, ...],
|
|
195
|
+
// tableInfo: { name: 'orders', database: 'analytics', type: 'table', comment: 'Orders' },
|
|
196
|
+
// }
|
|
197
|
+
|
|
198
|
+
const { rows } = await DBConnector.runSQL({
|
|
199
|
+
connection,
|
|
200
|
+
sql: 'SELECT * FROM orders WHERE status = ?',
|
|
201
|
+
parameters: ['paid'],
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
const updated = await DBConnector.runSQL({
|
|
205
|
+
connection,
|
|
206
|
+
sql: 'UPDATE orders SET status = ? WHERE id = ?',
|
|
207
|
+
parameters: ['shipped', 42],
|
|
208
|
+
});
|
|
209
|
+
// { rows: [], affectedRows: 1 }
|
|
210
|
+
|
|
211
|
+
// The exact same object belongs in Logicform.execute's connections array:
|
|
212
|
+
// await Logicform.execute(logicform, { connections: [connection], schemas, schemaMappings });
|
|
213
|
+
|
|
214
|
+
await Logicform.close(); // DBConnector.close() is the same shutdown operation.
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Both APIs share providers and connection pools by connection ID and `providerRegistry`. When a
|
|
218
|
+
connection's configuration changes under the same ID, the next operation creates a new provider
|
|
219
|
+
and closes the previous one. Providers and pools are initialized lazily. Either
|
|
220
|
+
`close()` releases **all** SDK-managed connections, including those used by the other API; it does
|
|
221
|
+
not close just the last connector connection.
|
|
222
|
+
|
|
223
|
+
`runSQL` returns `{ rows: DataRow[], affectedRows?: number }`. Commands without a result set return
|
|
224
|
+
an empty array; affected-row counts are included only when the driver reports them. SQL is passed
|
|
225
|
+
through without automatic LIMIT, dialect translation, Schema mapping, hydration, generated `_id`,
|
|
226
|
+
or query caching. It does **not** enforce `ExecuteOptions.permissions`: use trusted callers and
|
|
227
|
+
appropriately restricted database accounts. Supply values through `parameters` using the native
|
|
228
|
+
provider placeholders: `?` for MySQL-compatible databases, Databricks, Dameng, Snowflake and MaxCompute;
|
|
229
|
+
`$1` for PostgreSQL; `@p0` for SQL Server; `:1` for Oracle; typed `{p0:String}`-style
|
|
230
|
+
placeholders for ClickHouse. ClickHouse uses JSONEachRow output; do not override it with another
|
|
231
|
+
FORMAT. Each call is independent, with Oracle/Dameng command execution automatically committed;
|
|
232
|
+
cross-call transactions and multi-statement/multi-result execution are not supported.
|
|
233
|
+
|
|
234
|
+
`getTableList` returns `{ name, database?, schema?, type: 'table' | 'view' }[]` for accessible tables
|
|
235
|
+
and views, retaining namespaces to distinguish same-name tables. Optional `database` and `schema`
|
|
236
|
+
override only this metadata lookup, never the cached connection configuration:
|
|
237
|
+
|
|
238
|
+
- MySQL, Doris, StarRocks, GBase and ClickHouse: `database`; `schema` is rejected.
|
|
239
|
+
- PostgreSQL, Oracle and Dameng: `schema`; cross-database overrides are rejected. Defaults to the
|
|
240
|
+
current schema (or the configured Dameng schema).
|
|
241
|
+
- SQL Server and Snowflake: `database` and `schema`. SQL Server lists all accessible schemas in
|
|
242
|
+
the database by default; Snowflake defaults to the current schema.
|
|
243
|
+
- Databricks: `database` means catalog, and `schema` means schema. Defaults come from the connection's
|
|
244
|
+
`catalog` and `schema` (`connection.database` remains the existing legacy alias for schema).
|
|
245
|
+
- MaxCompute: the existing injected client handles `SHOW TABLES`, returning rows with `table_name`.
|
|
246
|
+
It may implement `getTableList(request)` for project/schema overrides and view metadata, and
|
|
247
|
+
`runSQL(request)` for affected-row counts. Otherwise commands must return `[]` through `execute`.
|
|
248
|
+
|
|
249
|
+
`describeTable({ connection, table, database?, schema?, includeSample? })` inspects one physical
|
|
250
|
+
table or view. `table` is a literal **unqualified** name; provide its namespace separately, using
|
|
251
|
+
the same scope rules as `getTableList`. A dot inside `table` is part of the identifier, not a separator.
|
|
252
|
+
Do not pass a SQL expression or the legacy semantic Schema/`from` object. SQL Server descriptions
|
|
253
|
+
default to the connection's current default schema; pass `schema` explicitly when describing a
|
|
254
|
+
table returned from another schema. Column order follows the database's definition.
|
|
255
|
+
|
|
256
|
+
The result has `columns: { name, type, comment, primaryKey?, exampleValue? }[]` and
|
|
257
|
+
`tableInfo: { name, database?, schema?, type, comment }`. These are physical names/native types,
|
|
258
|
+
not semantic Properties; no `_id` is added. Comments default to an empty string. Primary-key
|
|
259
|
+
membership includes every column of composite keys; unique-only indexes are not primary keys.
|
|
260
|
+
ClickHouse reports its storage primary key, which does not imply relational uniqueness. If the
|
|
261
|
+
adapter cannot determine primary-key membership (Databricks/Snowflake), `primaryKey` is omitted
|
|
262
|
+
rather than guessed. Example values preserve driver types, including `null`.
|
|
263
|
+
|
|
264
|
+
Like the legacy API, descriptions read one example row by default. Set `includeSample: false`
|
|
265
|
+
for metadata-only inspection, avoiding a data read. Empty tables and failed sample queries still
|
|
266
|
+
return metadata without example values; metadata failures, tables not found in the selected namespace, and
|
|
267
|
+
cancellation reject. All SQL uses bound metadata values and quoted identifiers, bypassing
|
|
268
|
+
LogicForm permissions and caching just like `runSQL`.
|
|
269
|
+
|
|
270
|
+
MaxCompute clients may implement `describeTable(request)` to provide project/schema-aware
|
|
271
|
+
metadata. Otherwise the fallback runs `DESC` and expects structured rows with `column_name`,
|
|
272
|
+
`column_type`, optional `column_comment` and `is_primary_key`. Legacy UDBC ASCII `Info` reports
|
|
273
|
+
must be normalized by the client; unparsed reports are rejected rather than producing empty columns.
|
|
274
|
+
|
|
275
|
+
All operations accept `signal` and the same optional `providerRegistry` as `Logicform.execute`.
|
|
276
|
+
Custom providers opt in through `runSQL(request)`, `getTableList(request)` and `describeTable(request)`; missing capabilities
|
|
277
|
+
fail explicitly without changing the existing provider `execute` contract. Unsupported discovery
|
|
278
|
+
scopes are rejected rather than silently ignored. Cancellation does not guarantee rollback of
|
|
279
|
+
commands that have already reached the database.
|
|
280
|
+
|
|
126
281
|
### Permissions
|
|
127
282
|
|
|
128
283
|
Pass table, row, and column permissions together through `ExecuteOptions.permissions`:
|
|
@@ -165,26 +320,44 @@ await Logicform.execute(logicform, {
|
|
|
165
320
|
|
|
166
321
|
When `permissions` is omitted, execution remains unrestricted. When it is present, its Schema keys
|
|
167
322
|
are the table allowlist. `rowPermissions` is always combined with the caller query using `AND`,
|
|
168
|
-
including internal
|
|
323
|
+
including internal time-watermark queries, related-table joins, and object population queries.
|
|
169
324
|
`columnPermissions.whitelist` accepts property names or IDs and restricts caller projections,
|
|
170
325
|
filters, grouping, operator inputs, and relation paths. A row policy may still use a non-whitelisted
|
|
171
326
|
column as an internal filter. If an ID is not whitelisted, SemanticDB generates the executor-owned
|
|
172
327
|
result-row `_id` instead of exposing the physical ID as that identity.
|
|
173
328
|
|
|
174
|
-
###
|
|
329
|
+
### Component operators
|
|
330
|
+
|
|
331
|
+
Composite metrics are regular `OperatorDefinition` values with `kind: 'component'`. Their
|
|
332
|
+
`createComponent` hook can return query components merged through a CTE or JavaScript. Register
|
|
333
|
+
them in the same `OperatorRegistry` as scalar and aggregate operators. Operator names are free-form;
|
|
334
|
+
the `$` prefix is a convention used by built-in operators, not a requirement.
|
|
175
335
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
336
|
+
Every composite component is exposed in result rows by default. Its `name` is its final result-column
|
|
337
|
+
name and may contain Chinese characters or spaces. Built-ins derive child names from the parent output,
|
|
338
|
+
for example `总销售额占比分子` and `总销售额占比分母`. Operators do not return `outputName` or an
|
|
339
|
+
exposure flag; the executor owns the parent output binding. Components are joined on groupby output
|
|
340
|
+
names shared by both sides unless an exceptional custom operator explicitly supplies `joinKeys`.
|
|
341
|
+
|
|
342
|
+
See [Register an operator](docs/register-operator.md) for the component contract.
|
|
182
343
|
|
|
183
344
|
The root entry point accepts a `connections` array of `DatabaseConnection` items. Every item has a unique `id`; set `kind` to `mysql`,
|
|
184
|
-
`doris`, `starrocks`, `
|
|
345
|
+
`doris`, `starrocks`, `gbase`, `maxcompute`, `clickhouse`, `databricks`, `dameng`, `snowflake`,
|
|
346
|
+
`sqlserver`, `oracle`, or `postgresql`, then add that driver's
|
|
185
347
|
native connection fields directly on the item. Each Schema Mapping selects an item through
|
|
186
348
|
`connectionId`. SemanticDB lazily creates and reuses the matching internal provider. Call
|
|
187
349
|
`await Logicform.close()` during application shutdown to close every connection pool and session.
|
|
350
|
+
One LogicForm may reference mappings on multiple connections. This is one logical execution, not
|
|
351
|
+
one cross-database SQL statement: physical fragments run independently and their aggregate results
|
|
352
|
+
are combined by the embedded coordinator. A relation join whose two sides themselves live on
|
|
353
|
+
different connections is not yet materialized automatically. When the related Schema has replicas
|
|
354
|
+
on multiple connections, the Planner selects the mapping colocated with the main mapping and emits
|
|
355
|
+
the `LEFT JOIN` on that connection. It fails explicitly only when no target mapping exists on the
|
|
356
|
+
main connection.
|
|
357
|
+
|
|
358
|
+
MySQL-compatible providers default to 30 connections, at most 10 idle connections, a 60-second
|
|
359
|
+
idle timeout, and TCP keepalive. Native `mysql2` pool options on the connection item override these
|
|
360
|
+
defaults.
|
|
188
361
|
|
|
189
362
|
### PostgreSQL connection
|
|
190
363
|
|
|
@@ -216,6 +389,66 @@ pagination, date, aggregate, string, regex, parameter, and display-SQL behavior
|
|
|
216
389
|
MySQL-compatible SQL helper. Database-specific differences should be implemented by overriding the
|
|
217
390
|
corresponding internal dialect capability.
|
|
218
391
|
|
|
392
|
+
### GBase connection
|
|
393
|
+
|
|
394
|
+
GBase 8a uses its MySQL-compatible protocol through `mysql2`. It defaults to port `5258`; all
|
|
395
|
+
ordinary `mysql2` connection and pool fields remain available:
|
|
396
|
+
|
|
397
|
+
```ts
|
|
398
|
+
const gbase = {
|
|
399
|
+
id: 'gbase-main',
|
|
400
|
+
kind: 'gbase',
|
|
401
|
+
host: process.env.GBASE_HOST,
|
|
402
|
+
user: process.env.GBASE_USER,
|
|
403
|
+
password: process.env.GBASE_PASSWORD,
|
|
404
|
+
database: process.env.GBASE_DATABASE,
|
|
405
|
+
} as const;
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### MaxCompute connection
|
|
409
|
+
|
|
410
|
+
MaxCompute requires a caller-supplied client that preserves the Provider's parameterized execution
|
|
411
|
+
contract. The client receives SQL and parameters separately and owns the actual MaxCompute/JDBC
|
|
412
|
+
transport. SemanticDB calls the client's `close()` when its provider is closed:
|
|
413
|
+
|
|
414
|
+
```ts
|
|
415
|
+
const maxcompute = {
|
|
416
|
+
id: 'maxcompute-main',
|
|
417
|
+
kind: 'maxcompute',
|
|
418
|
+
client: {
|
|
419
|
+
execute: ({ sql, parameters, signal }) => maxComputeGateway.execute({
|
|
420
|
+
sql, parameters, signal,
|
|
421
|
+
}),
|
|
422
|
+
close: () => maxComputeGateway.close(),
|
|
423
|
+
},
|
|
424
|
+
} as const;
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
The legacy UDBC `Statement` endpoint accepts only a complete SQL string, so SemanticDB does not
|
|
428
|
+
use it or interpolate values locally. A gateway implementation must bind `parameters` before this
|
|
429
|
+
connection can execute queries.
|
|
430
|
+
|
|
431
|
+
### SQL Server connection
|
|
432
|
+
|
|
433
|
+
SQL Server uses `mssql`, bracket-quoted identifiers, and named `@p0`, `@p1` parameters:
|
|
434
|
+
|
|
435
|
+
```ts
|
|
436
|
+
const sqlserver = {
|
|
437
|
+
id: 'sqlserver-main',
|
|
438
|
+
kind: 'sqlserver',
|
|
439
|
+
host: process.env.SQLSERVER_HOST,
|
|
440
|
+
port: 1433,
|
|
441
|
+
user: process.env.SQLSERVER_USER,
|
|
442
|
+
password: process.env.SQLSERVER_PASSWORD,
|
|
443
|
+
database: process.env.SQLSERVER_DATABASE,
|
|
444
|
+
options: { encrypt: true },
|
|
445
|
+
} as const;
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
Pagination uses `OFFSET ... FETCH`; SemanticDB supplies a neutral top-level ordering when the
|
|
449
|
+
LogicForm has no sort. JSON array relations use `OPENJSON`. SQL Server has no native regular
|
|
450
|
+
expression predicate, so `$regex` is rejected explicitly.
|
|
451
|
+
|
|
219
452
|
### Snowflake connection
|
|
220
453
|
|
|
221
454
|
Snowflake connection fields are passed to the official `snowflake-sdk`:
|
|
@@ -238,6 +471,52 @@ await Logicform.execute(logicform, {
|
|
|
238
471
|
});
|
|
239
472
|
```
|
|
240
473
|
|
|
474
|
+
### Databricks connection
|
|
475
|
+
|
|
476
|
+
Databricks uses `@databricks/sql` and supports a personal access token or OAuth M2M. `catalog` and
|
|
477
|
+
`schema` select the initial SQL Warehouse session namespace (`database` is accepted as a legacy
|
|
478
|
+
alias for `schema`):
|
|
479
|
+
|
|
480
|
+
```ts
|
|
481
|
+
const databricks = {
|
|
482
|
+
id: 'databricks-main',
|
|
483
|
+
kind: 'databricks',
|
|
484
|
+
host: process.env.DATABRICKS_SERVER_HOSTNAME,
|
|
485
|
+
path: process.env.DATABRICKS_HTTP_PATH,
|
|
486
|
+
authType: 'databricks-oauth',
|
|
487
|
+
oauthClientId: process.env.DATABRICKS_CLIENT_ID,
|
|
488
|
+
oauthClientSecret: process.env.DATABRICKS_CLIENT_SECRET,
|
|
489
|
+
catalog: 'main',
|
|
490
|
+
schema: 'analytics',
|
|
491
|
+
} as const;
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
Use `authType: 'access-token'` with `token` for PAT authentication. Values are sent through the
|
|
495
|
+
driver's ordinal parameter binding and are not interpolated into executable SQL. `authType` is
|
|
496
|
+
required: PAT and OAuth fields are mutually exclusive, and authentication is never inferred from
|
|
497
|
+
the presence of credentials.
|
|
498
|
+
|
|
499
|
+
### Dameng connection
|
|
500
|
+
|
|
501
|
+
Dameng uses the official `dmdb` pool and the `dameng` connection kind:
|
|
502
|
+
|
|
503
|
+
```ts
|
|
504
|
+
const dameng = {
|
|
505
|
+
id: 'dameng-main',
|
|
506
|
+
kind: 'dameng',
|
|
507
|
+
host: process.env.DAMENG_HOST,
|
|
508
|
+
port: 5236,
|
|
509
|
+
user: process.env.DAMENG_USER,
|
|
510
|
+
password: process.env.DAMENG_PASSWORD,
|
|
511
|
+
schema: process.env.DAMENG_SCHEMA,
|
|
512
|
+
} as const;
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
The provider uses positional binds and object-format result rows. Recursive hierarchy queries and
|
|
516
|
+
JSON-array relations are rejected until their behavior can be verified against supported DM server
|
|
517
|
+
versions; scalar queries, grouping, date operations, regex, windows, joins, and pagination compile
|
|
518
|
+
with the DM/Oracle-style dialect.
|
|
519
|
+
|
|
241
520
|
### Oracle connection
|
|
242
521
|
|
|
243
522
|
Oracle uses the official `oracledb` driver in Thin mode and does not require Oracle Client
|
|
@@ -262,7 +541,8 @@ await Logicform.execute(logicform, {
|
|
|
262
541
|
`Schema.properties[].type` is an extensible semantic type. SemanticDB supplies the built-in
|
|
263
542
|
types and derives each property's `primal_type` while resolving the Schema. A supplied
|
|
264
543
|
`primal_type` must match the registered type. `isArray` describes the value container and
|
|
265
|
-
defaults to `false
|
|
544
|
+
defaults to `false`. The built-in `tag` type is a string array and sets `isArray: true`
|
|
545
|
+
automatically; `type: 'category', isArray: true` remains available for other categorical arrays.
|
|
266
546
|
|
|
267
547
|
```ts
|
|
268
548
|
import { createSemanticTypeRegistry, Logicform } from 'semanticdb-v2';
|
|
@@ -306,19 +586,38 @@ comments, or parameter placeholders. Property UDFs do not support the legacy `fu
|
|
|
306
586
|
|
|
307
587
|
### Query cache
|
|
308
588
|
|
|
309
|
-
All compiled provider queries, including the internal
|
|
310
|
-
|
|
311
|
-
includes namespace, provider, SQL, and parameters. Physical
|
|
312
|
-
mapping's `freshness` policy. See
|
|
589
|
+
All compiled provider queries, including the internal time-watermark query, can share one
|
|
590
|
+
internally managed Redis query cache. Pass its JSON connection configuration through `cache`;
|
|
591
|
+
cache identity includes namespace, connection id, provider, SQL, and parameters. Physical
|
|
592
|
+
expiration belongs to each Schema mapping's `freshness` policy. See
|
|
593
|
+
[Query cache and Redis](docs/query-cache.md).
|
|
313
594
|
|
|
314
|
-
|
|
595
|
+
Schema mappings can also expose same-connection entity feature tables as lazy physical
|
|
596
|
+
enrichments. A mapped feature property adds a `LEFT JOIN` only when referenced, and a point-in-time
|
|
597
|
+
feature can be assigned to the containing valid-time entity row. See
|
|
598
|
+
[Schema Mapping feature enrichments](docs/schema-mapping-enrichments.md).
|
|
315
599
|
|
|
316
|
-
|
|
317
|
-
|
|
600
|
+
For aggregate sources, set `granularity` on mapped date or hierarchy Properties.
|
|
601
|
+
Other available dimensions are inferred from their Property mappings, so there is no
|
|
602
|
+
separate Schema Mapping `dimensions` field. The planner selects a source that covers
|
|
603
|
+
the requested properties and physical time or hierarchy grain. See
|
|
604
|
+
[Schema Mapping physical granularity](docs/schema-mapping-granularity.md).
|
|
605
|
+
|
|
606
|
+
When Redis is shared with other applications, pass an application-specific key prefix in the
|
|
607
|
+
execution JSON. SemanticDB reuses the connection by `cache.id`:
|
|
318
608
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
609
|
+
```ts
|
|
610
|
+
await Logicform.execute(logicform, {
|
|
611
|
+
schemas,
|
|
612
|
+
schemaMappings,
|
|
613
|
+
connections,
|
|
614
|
+
cache: {
|
|
615
|
+
id: 'redis-main',
|
|
616
|
+
kind: 'redis',
|
|
617
|
+
url: process.env.REDIS_URL ?? 'redis://localhost:6379/0',
|
|
618
|
+
keyPrefix: process.env.REDIS_KEY_PREFIX,
|
|
619
|
+
namespace: 'tenant-a:mysql-sales',
|
|
620
|
+
},
|
|
322
621
|
});
|
|
323
622
|
```
|
|
324
623
|
|
|
@@ -432,7 +731,8 @@ npm run debug
|
|
|
432
731
|
|
|
433
732
|
## Current scope
|
|
434
733
|
|
|
435
|
-
- ClickHouse, MySQL, Oracle,
|
|
734
|
+
- ClickHouse, Databricks, Dameng, Doris, GBase, MaxCompute, MySQL, Oracle, PostgreSQL, Snowflake,
|
|
735
|
+
SQL Server, and StarRocks core compute providers
|
|
436
736
|
- Projections, conditional aggregates, and `$sum`, `$count`, `$countDistinct`, `$avg`, `$min`, `$max`
|
|
437
737
|
- Structured arithmetic, share-of-total, period comparison, period-boundary, date-bucket,
|
|
438
738
|
cumulative period, trusted SQL expression, string, case, and window operators
|
|
@@ -442,7 +742,7 @@ npm run debug
|
|
|
442
742
|
- `$and` and `$or`, HAVING, sorting, row-count and percentage pagination, and per-group `limitBy`
|
|
443
743
|
- Query-level and output-column lineage
|
|
444
744
|
- Multi-level scalar and array object relation paths, array groupby, and batched entity population
|
|
445
|
-
- Nested `from`
|
|
745
|
+
- Nested `from` LogicForm objects compiled as parameterized derived tables
|
|
446
746
|
|
|
447
747
|
Exports and metadata persistence are intentionally deferred. Directly selected array-object
|
|
448
748
|
properties are populated without expanding the root result rows.
|
package/dist/cache/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { nextDailyExpiration, resolveQueryExpiration, } from './expiry';
|
|
2
2
|
export { queryCacheIdentityHash, sourceCacheIndexHash, } from './identity';
|
|
3
|
-
export type { QueryCache, QueryCacheExecutionOptions, QueryCacheIdentity, QueryCacheWriteOptions, } from './types';
|
|
3
|
+
export type { InvalidateQueryCacheSourceOptions, QueryCache, QueryCacheConfiguration, QueryCacheExecutionOptions, QueryCacheIdentity, QueryCacheWriteOptions, } from './types';
|
|
4
|
+
export { QueryCacheManager } from './manager';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { InvalidateQueryCacheSourceOptions } from './types';
|
|
2
|
+
/** Operations for internally managed query-cache connections. */
|
|
3
|
+
export declare const QueryCacheManager: Readonly<{
|
|
4
|
+
invalidateSource: ({ cache, source }: InvalidateQueryCacheSourceOptions) => Promise<void>;
|
|
5
|
+
}>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { QueryCache, QueryCacheConfiguration, QueryCacheExecutionOptions } from './types';
|
|
2
|
+
type QueryCacheConnection = Omit<QueryCacheConfiguration, 'namespace'>;
|
|
3
|
+
type QueryCacheFactory = (connection: QueryCacheConnection) => Promise<QueryCache>;
|
|
4
|
+
/** Internally owns and reuses cache connections by stable configuration id. */
|
|
5
|
+
export declare class QueryCacheRegistry {
|
|
6
|
+
#private;
|
|
7
|
+
private readonly create;
|
|
8
|
+
constructor(create?: QueryCacheFactory);
|
|
9
|
+
get(configuration: QueryCacheConfiguration): Promise<QueryCacheExecutionOptions>;
|
|
10
|
+
close(): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export declare const resolveQueryCache: (configuration: QueryCacheConfiguration) => Promise<QueryCacheExecutionOptions>;
|
|
13
|
+
export declare const closeQueryCaches: () => Promise<void>;
|
|
14
|
+
export {};
|
package/dist/cache/types.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ import type { CoreComputeProvider, DataRow, SqlParameters } from '../physical/in
|
|
|
2
2
|
export interface QueryCacheIdentity {
|
|
3
3
|
readonly namespace: string;
|
|
4
4
|
readonly provider: CoreComputeProvider['kind'];
|
|
5
|
+
/** Distinguishes separate databases using the same provider dialect. */
|
|
6
|
+
readonly connectionId?: string;
|
|
5
7
|
readonly sql: string;
|
|
6
8
|
readonly parameters: SqlParameters;
|
|
7
9
|
}
|
|
@@ -25,3 +27,18 @@ export interface QueryCacheExecutionOptions {
|
|
|
25
27
|
/** Isolates tenants and physical data sources that can produce identical SQL. */
|
|
26
28
|
readonly namespace: string;
|
|
27
29
|
}
|
|
30
|
+
/** Redis connection and cache namespace supplied as JSON at the public execution boundary. */
|
|
31
|
+
export interface QueryCacheConfiguration {
|
|
32
|
+
/** Stable identity used to reuse one internally managed Redis connection. */
|
|
33
|
+
readonly id: string;
|
|
34
|
+
readonly kind: 'redis';
|
|
35
|
+
readonly url: string;
|
|
36
|
+
readonly keyPrefix?: string;
|
|
37
|
+
/** Isolates tenants and physical data sources that can produce identical SQL. */
|
|
38
|
+
readonly namespace: string;
|
|
39
|
+
}
|
|
40
|
+
export interface InvalidateQueryCacheSourceOptions {
|
|
41
|
+
readonly cache: QueryCacheConfiguration;
|
|
42
|
+
/** Physical Schema Mapping source to invalidate. */
|
|
43
|
+
readonly source: string;
|
|
44
|
+
}
|
package/dist/close.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const closeSemanticDB: () => Promise<void>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { assertNoLegacyLogicformFields, normalizeLegacyLogicform,
|
|
2
|
-
export { normalizeSchemas } from '../executor/compatibility';
|
|
1
|
+
export { assertNoLegacyLogicformFields, normalizeLegacyLogicform, } from './logicform';
|
|
2
|
+
export { isLegacyEmptyMapping, normalizeLegacySchemaMappings, normalizeSchemas, } from '../executor/compatibility';
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import type { LogicformType } from '../logicform-types';
|
|
2
2
|
type SchemaRegistry = Readonly<Record<string, unknown>>;
|
|
3
3
|
/** Converts a legacy LogicForm tree into the v2 wire shape without mutating input. */
|
|
4
|
-
export declare const normalizeLegacyLogicform: (logicform: unknown) => LogicformType;
|
|
5
|
-
/**
|
|
6
|
-
* Converts the legacy `pred.schema` fan-out into v2 composition. The planner
|
|
7
|
-
* intentionally rejects cross-schema PredItems, so this has to happen before
|
|
8
|
-
* the v2 normalizer sees the tree.
|
|
9
|
-
*/
|
|
10
|
-
export declare const splitLegacySchemas: (logicform: LogicformType, schemas?: SchemaRegistry) => LogicformType;
|
|
4
|
+
export declare const normalizeLegacyLogicform: (logicform: unknown, schemas?: SchemaRegistry) => LogicformType;
|
|
11
5
|
/** Rejects legacy wire fields when a caller explicitly declares a v2 LogicForm. */
|
|
12
6
|
export declare const assertNoLegacyLogicformFields: (logicform: unknown) => void;
|
|
13
7
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { OperatorComponentCalculation, OperatorGroupKeyShift } from '../operators/index';
|
|
2
2
|
import type { CoreComputeProvider } from '../physical/index';
|
|
3
3
|
import type { LogicalPlan } from '../planner/index';
|
|
4
4
|
import type { CompiledQuery } from './types';
|
|
@@ -9,4 +9,19 @@ export interface PreparedCteComponent {
|
|
|
9
9
|
readonly groupKeyShifts?: readonly OperatorGroupKeyShift[];
|
|
10
10
|
readonly joinKeys?: readonly string[];
|
|
11
11
|
}
|
|
12
|
-
|
|
12
|
+
/** A compiled top-level execution unit that can be joined into one SQL query. */
|
|
13
|
+
export interface PreparedCteQuery {
|
|
14
|
+
readonly plan: LogicalPlan;
|
|
15
|
+
readonly compiled: CompiledQuery;
|
|
16
|
+
/** Result projection names exposed by this execution unit (excluding groups). */
|
|
17
|
+
readonly outputs: readonly string[];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Combine independent SQL execution units into one statement.
|
|
21
|
+
*
|
|
22
|
+
* Component operators are compiled independently because their input ranges can
|
|
23
|
+
* differ (for example, current and previous periods). Keeping each unit as a
|
|
24
|
+
* CTE preserves those ranges while allowing the provider to execute one query.
|
|
25
|
+
*/
|
|
26
|
+
export declare const compileCteQueries: (units: readonly PreparedCteQuery[], outputPlan: LogicalPlan, provider: CoreComputeProvider, operators?: OperatorRegistry) => CompiledQuery;
|
|
27
|
+
export declare const compileCteCalculation: (calculation: OperatorComponentCalculation, components: readonly PreparedCteComponent[], outputPlan: LogicalPlan, outputName: string, provider: CoreComputeProvider, operators: OperatorRegistry) => CompiledQuery;
|
package/dist/compiler/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { compilePlan } from './compile-plan';
|
|
2
|
-
export { compileCteCalculation } from './compile-cte';
|
|
2
|
+
export { compileCteCalculation, compileCteQueries } from './compile-cte';
|
|
3
|
+
export type { PreparedCteQuery } from './compile-cte';
|
|
3
4
|
export { shortenSQL } from './shorten-sql';
|
|
4
5
|
export type { CompiledQuery } from './types';
|