@dbsp/nql 1.0.4 → 1.2.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 +38 -5
- package/dist/index.d.ts +50 -33
- package/dist/index.js +589 -157
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -15,16 +15,22 @@ pnpm add @dbsp/nql
|
|
|
15
15
|
|
|
16
16
|
```typescript
|
|
17
17
|
// doctest: skip — exec-only operation; compile from @dbsp/nql is not in doctest preamble and orm.from(intent).all() requires a real PostgreSQL connection
|
|
18
|
+
import { createPgsqlCompileOnlyAdapter } from '@dbsp/adapter-pgsql';
|
|
18
19
|
import { compile } from '@dbsp/nql';
|
|
19
20
|
|
|
20
|
-
// Compile an NQL query to
|
|
21
|
-
const
|
|
21
|
+
// Compile an NQL query to a public intent bundle
|
|
22
|
+
const compiled = compile(
|
|
22
23
|
"users | where active = true | select name, email | order name asc | limit 20",
|
|
23
|
-
|
|
24
|
+
db.model
|
|
24
25
|
);
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
if (!compiled.success || !compiled.ast?.query) {
|
|
28
|
+
throw new Error(compiled.errors.map((e) => e.message).join(', '));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Pass the whole bundle to the adapter; bound params are explicit public IR nodes
|
|
32
|
+
const adapter = createPgsqlCompileOnlyAdapter();
|
|
33
|
+
const query = adapter.compile(compiled.ast, { model: db.model });
|
|
28
34
|
```
|
|
29
35
|
|
|
30
36
|
## Syntax overview
|
|
@@ -51,12 +57,39 @@ orders | group customerId | select customerId, sum(total) as revenue
|
|
|
51
57
|
|
|
52
58
|
- **Pipe syntax** — Readable left-to-right data flow (`table | filter | select | order`)
|
|
53
59
|
- **SQL-style literals** — Single-quoted strings (`'value'`), not double-quoted
|
|
60
|
+
- **Named parameters** — Bind runtime values with `:name` in expression positions
|
|
54
61
|
- **CTE support** — `WITH name AS (subquery)` for named subqueries
|
|
55
62
|
- **Schema-aware** — Validates column names and relation paths against `ModelIR` at parse time
|
|
56
63
|
- **LLM-friendly** — Concise syntax designed for AI-generated queries
|
|
57
64
|
- **Chevrotain-based** — Robust lexer + parser with structured error recovery
|
|
58
65
|
- **Composable** — Output `IntentAST` is the same type used by the TypeScript fluent builders
|
|
59
66
|
|
|
67
|
+
## Named parameters
|
|
68
|
+
|
|
69
|
+
Use `:name` placeholders for runtime values and pass a `params` map to the compiler:
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
// doctest: skip — illustrative direct compiler params example
|
|
73
|
+
import { createPgsqlCompileOnlyAdapter } from '@dbsp/adapter-pgsql';
|
|
74
|
+
import { compile } from '@dbsp/nql';
|
|
75
|
+
|
|
76
|
+
const compiled = compile(
|
|
77
|
+
'users | where id = :id and active = :active | limit :limit',
|
|
78
|
+
db.model,
|
|
79
|
+
undefined,
|
|
80
|
+
{ params: { id: 42, active: true, limit: 10 } },
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
if (!compiled.success || !compiled.ast?.query) {
|
|
84
|
+
throw new Error(compiled.errors.map((e) => e.message).join(', '));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const adapter = createPgsqlCompileOnlyAdapter();
|
|
88
|
+
const query = adapter.compile(compiled.ast, { model: db.model });
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Missing params fail compilation. `null` binds SQL `NULL`; `undefined`, `NaN`, and `Infinity` are rejected. The `@dbsp/core` `orm.nql` template tag builds on the same mechanism for `${value}` interpolation. See [Named Parameters and Template Binding](https://oorabona.github.io/db-semantic-planner/nql/#named-parameters-and-template-binding) for the full contract.
|
|
92
|
+
|
|
60
93
|
## Documentation
|
|
61
94
|
|
|
62
95
|
- [Guides](https://oorabona.github.io/db-semantic-planner/guide/)
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { DeleteIntent, ExpressionIntent, IncludeIntent, InsertIntent, MutationIntent, OrderByIntent, QueryIntent, SelectAllIntent, SelectFieldsIntent, SelectIntent, SelectWithExpressionsIntent, UpdateIntent, UpsertIntent, WhereAndIntent, WhereComparisonIntent, WhereInIntent, WhereIntent, WhereLikeIntent, WhereNotIntent, WhereNullIntent, WhereOrIntent, WhereRangeIntent } from '@dbsp/types';
|
|
1
|
+
import { CompiledNqlQuery } from '@dbsp/types';
|
|
2
|
+
export { CompiledNqlQuery, DeleteIntent, ExpressionIntent, IncludeIntent, InsertIntent, MutationIntent, OrderByIntent, QueryIntent, SelectAllIntent, SelectFieldsIntent, SelectIntent, SelectWithExpressionsIntent, UpdateIntent, UpsertIntent, WhereAndIntent, WhereComparisonIntent, WhereInIntent, WhereIntent, WhereLikeIntent, WhereNotIntent, WhereNullIntent, WhereOrIntent, WhereRangeIntent } from '@dbsp/types';
|
|
3
3
|
import * as chevrotain from 'chevrotain';
|
|
4
4
|
import { Lexer, CstParser, CstNode, IToken } from 'chevrotain';
|
|
5
5
|
|
|
@@ -71,13 +71,14 @@ interface NqlOrderByClause {
|
|
|
71
71
|
}
|
|
72
72
|
interface NqlLimitClause {
|
|
73
73
|
type: 'limit';
|
|
74
|
-
count:
|
|
74
|
+
count: NqlLimitCount;
|
|
75
75
|
relation?: string;
|
|
76
76
|
}
|
|
77
77
|
interface NqlOffsetClause {
|
|
78
78
|
type: 'offset';
|
|
79
|
-
count:
|
|
79
|
+
count: NqlLimitCount;
|
|
80
80
|
}
|
|
81
|
+
type NqlLimitCount = number | NqlNamedParamExpr;
|
|
81
82
|
/**
|
|
82
83
|
* Capture mutation result into a variable (for chained mutations)
|
|
83
84
|
* Used with `bind` keyword: `insert ... | bind result | ...`
|
|
@@ -135,7 +136,7 @@ interface NqlOrderItem {
|
|
|
135
136
|
expression: NqlExpression;
|
|
136
137
|
direction: 'asc' | 'desc';
|
|
137
138
|
}
|
|
138
|
-
type NqlExpression = NqlBinaryExpression | NqlUnaryExpression | NqlComparisonExpression | NqlRangeOpExpression | NqlInExpression | NqlAnyExpression | NqlBetweenExpression | NqlIsNullExpression | NqlExistsExpression | NqlRelationFilterExpression | NqlFunctionCall | NqlWindowExpression | NqlCaseExpression | NqlPathExpression | NqlJsonAccessExpression | NqlJsonComparisonExpression | NqlLiteral | NqlSubquery | NqlVariableRef;
|
|
139
|
+
type NqlExpression = NqlBinaryExpression | NqlUnaryExpression | NqlComparisonExpression | NqlRangeOpExpression | NqlInExpression | NqlAnyExpression | NqlBetweenExpression | NqlIsNullExpression | NqlExistsExpression | NqlRelationFilterExpression | NqlFunctionCall | NqlWindowExpression | NqlCaseExpression | NqlPathExpression | NqlJsonAccessExpression | NqlJsonComparisonExpression | NqlLiteral | NqlSubquery | NqlVariableRef | NqlNamedParamExpr;
|
|
139
140
|
interface NqlBinaryExpression {
|
|
140
141
|
type: 'binary';
|
|
141
142
|
operator: 'and' | 'or' | '+' | '-' | '*' | '/' | '%';
|
|
@@ -162,7 +163,7 @@ interface NqlRangeOpExpression {
|
|
|
162
163
|
operator: 'overlaps' | 'contains' | 'containedBy';
|
|
163
164
|
left: NqlExpression;
|
|
164
165
|
range?: NqlRangeLiteral;
|
|
165
|
-
scalar?: NqlLiteral;
|
|
166
|
+
scalar?: NqlLiteral | NqlNamedParamExpr;
|
|
166
167
|
}
|
|
167
168
|
interface NqlInExpression {
|
|
168
169
|
type: 'in';
|
|
@@ -297,6 +298,15 @@ interface NqlVariableRef {
|
|
|
297
298
|
type: 'variable';
|
|
298
299
|
name: string;
|
|
299
300
|
}
|
|
301
|
+
/**
|
|
302
|
+
* Bound parameter reference (e.g. `:tenantId`).
|
|
303
|
+
* The leading colon is not part of `name`; compiler resolution uses
|
|
304
|
+
* `CompilerContext.params`.
|
|
305
|
+
*/
|
|
306
|
+
interface NqlNamedParamExpr {
|
|
307
|
+
type: 'namedParam';
|
|
308
|
+
name: string;
|
|
309
|
+
}
|
|
300
310
|
type NqlLiteral = NqlStringLiteral | NqlNumberLiteral | NqlBooleanLiteral | NqlNullLiteral | NqlDateRangeLiteral | NqlRangeLiteral;
|
|
301
311
|
interface NqlStringLiteral {
|
|
302
312
|
type: 'string';
|
|
@@ -354,7 +364,7 @@ interface NqlInsertFrom {
|
|
|
354
364
|
/** WHERE clause to filter source rows */
|
|
355
365
|
where?: NqlExpression | undefined;
|
|
356
366
|
/** LIMIT clause to restrict rows */
|
|
357
|
-
limit?:
|
|
367
|
+
limit?: NqlLimitCount | undefined;
|
|
358
368
|
}
|
|
359
369
|
interface NqlUpdate {
|
|
360
370
|
type: 'update';
|
|
@@ -385,31 +395,15 @@ interface NqlUpsertFrom {
|
|
|
385
395
|
source: string;
|
|
386
396
|
columns?: string[] | undefined;
|
|
387
397
|
where?: NqlExpression | undefined;
|
|
388
|
-
limit?:
|
|
398
|
+
limit?: NqlLimitCount | undefined;
|
|
389
399
|
}
|
|
390
400
|
interface NqlAssignment {
|
|
391
401
|
column: string;
|
|
392
402
|
value: NqlExpression;
|
|
393
403
|
}
|
|
394
404
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
/** CTE query (WITH clause): wraps outer QueryIntent in CteQueryIntent */
|
|
398
|
-
readonly cteQuery?: CteQueryIntent;
|
|
399
|
-
readonly mutation?: MutationIntent;
|
|
400
|
-
readonly returning?: readonly string[];
|
|
401
|
-
/** Named bindings from `| bind X` clauses (CTE source queries) */
|
|
402
|
-
readonly bindings?: ReadonlyMap<string, QueryIntent>;
|
|
403
|
-
/**
|
|
404
|
-
* Named mutation bindings from `mutation | select cols | bind X` clauses.
|
|
405
|
-
* When a mutation has RETURNING and is bound, the original MutationIntent is stored here
|
|
406
|
-
* so the adapter can compile it as a CTE: `WITH X AS (INSERT ... RETURNING cols) ...`
|
|
407
|
-
* The corresponding synthetic QueryIntent is also stored in `bindings` for reference resolution.
|
|
408
|
-
*/
|
|
409
|
-
readonly mutationBindings?: ReadonlyMap<string, MutationIntent>;
|
|
410
|
-
/** Set operation (UNION/INTERSECT/EXCEPT) wrapping two queries */
|
|
411
|
-
readonly setOperation?: SetOperationIntent;
|
|
412
|
-
}
|
|
405
|
+
type CompileResult = CompiledNqlQuery;
|
|
406
|
+
|
|
413
407
|
/**
|
|
414
408
|
* Duck-type interface for schema-based column validation.
|
|
415
409
|
* Loose coupling: ModelIR from @dbsp/core satisfies this shape without direct import.
|
|
@@ -440,6 +434,8 @@ interface NqlCompilerOptions {
|
|
|
440
434
|
readonly params?: Readonly<Record<string, unknown>>;
|
|
441
435
|
/** Maximum number of items allowed in an ANY(:param) array. Defaults to MAX_ANY_ITEMS (10000). */
|
|
442
436
|
readonly maxAnyItems?: number;
|
|
437
|
+
/** Permit a where-less update/delete to compile to an unfiltered, all-rows mutation. Default false — a where-less mutation throws unless this is set. */
|
|
438
|
+
readonly allowUnfilteredMutations?: boolean;
|
|
443
439
|
}
|
|
444
440
|
|
|
445
441
|
/**
|
|
@@ -510,6 +506,11 @@ interface NqlWarning {
|
|
|
510
506
|
declare const allTokens: chevrotain.TokenType[];
|
|
511
507
|
declare const NqlLexer: Lexer;
|
|
512
508
|
|
|
509
|
+
/**
|
|
510
|
+
* Tokenize NQL source with the public lexer.
|
|
511
|
+
*/
|
|
512
|
+
declare function tokenize(input: string): ReturnType<typeof NqlLexer.tokenize>;
|
|
513
|
+
|
|
513
514
|
/**
|
|
514
515
|
* NQL Parser using Chevrotain CstParser
|
|
515
516
|
*/
|
|
@@ -578,13 +579,23 @@ declare class NqlParser extends CstParser {
|
|
|
578
579
|
*/
|
|
579
580
|
private orderClause;
|
|
580
581
|
/**
|
|
581
|
-
* limit_clause = "limit" [ident_segment ("." ident_segment)*] NUMBER ;
|
|
582
|
+
* limit_clause = "limit" [ident_segment ("." ident_segment)*] (NUMBER | NAMED_PARAM) ;
|
|
582
583
|
*/
|
|
583
584
|
private limitClause;
|
|
584
585
|
/**
|
|
585
|
-
* offset_clause = "offset" NUMBER ;
|
|
586
|
+
* offset_clause = "offset" (NUMBER | NAMED_PARAM) ;
|
|
586
587
|
*/
|
|
587
588
|
private offsetClause;
|
|
589
|
+
/**
|
|
590
|
+
* numeric_value_atom = NUMBER | NAMED_PARAM ;
|
|
591
|
+
*
|
|
592
|
+
* Structural-position durability rule: value positions that consume scalar
|
|
593
|
+
* values may add `NamedParam` here and validate the resolved value in the
|
|
594
|
+
* compiler. Structural positions such as identifiers, directions, lock modes,
|
|
595
|
+
* and traversal depth hints must not consume this helper; use nqlRaw()/builder
|
|
596
|
+
* APIs for trusted dynamic structure.
|
|
597
|
+
*/
|
|
598
|
+
private numericValueAtom;
|
|
588
599
|
/**
|
|
589
600
|
* lock_clause = lock_strength [ lock_wait_policy ] ;
|
|
590
601
|
* lock_strength = "for update" | "for share" | "for no key update" | "for key share" ;
|
|
@@ -662,7 +673,7 @@ declare class NqlParser extends CstParser {
|
|
|
662
673
|
*/
|
|
663
674
|
private rangeOp;
|
|
664
675
|
/**
|
|
665
|
-
* range_op_suffix = range_op (range_literal | literal) ;
|
|
676
|
+
* range_op_suffix = range_op (range_literal | literal | named_param_expr) ;
|
|
666
677
|
* Example: overlaps [1,10) or contains (0,100) or contains 25
|
|
667
678
|
* Note: contains can take a scalar value (e.g., contains 25 checks if range contains the value)
|
|
668
679
|
*/
|
|
@@ -745,9 +756,13 @@ declare class NqlParser extends CstParser {
|
|
|
745
756
|
*/
|
|
746
757
|
private jsonAccessExpr;
|
|
747
758
|
/**
|
|
748
|
-
* primary_expr = literal | case_expr | path_expr | func_call | "(" expr ")" | "(" scalar_subquery ")" ;
|
|
759
|
+
* primary_expr = named_param_expr | literal | case_expr | path_expr | func_call | "(" expr ")" | "(" scalar_subquery ")" ;
|
|
749
760
|
*/
|
|
750
761
|
private primaryExpr;
|
|
762
|
+
/**
|
|
763
|
+
* named_param_expr = NAMED_PARAM ;
|
|
764
|
+
*/
|
|
765
|
+
private namedParamExpr;
|
|
751
766
|
/**
|
|
752
767
|
* Check if at start of scalar subquery (ident | ...)
|
|
753
768
|
*/
|
|
@@ -864,7 +879,7 @@ declare class NqlParser extends CstParser {
|
|
|
864
879
|
*/
|
|
865
880
|
private insertStmt;
|
|
866
881
|
/**
|
|
867
|
-
* insert_from_stmt = "insert" "into" ident_segment "from" ident_segment [ "where" boolean_expr ] [ "limit"
|
|
882
|
+
* insert_from_stmt = "insert" "into" ident_segment "from" ident_segment [ "where" boolean_expr ] [ "limit" numeric_value_atom ] ;
|
|
868
883
|
* @example insert into archived_users from users where active = false limit 100
|
|
869
884
|
*/
|
|
870
885
|
private insertFromStmt;
|
|
@@ -883,7 +898,7 @@ declare class NqlParser extends CstParser {
|
|
|
883
898
|
*/
|
|
884
899
|
private upsertStmt;
|
|
885
900
|
/**
|
|
886
|
-
* upsert_from_stmt = "upsert" "into" ident_segment "on" ( "(" ident_list ")" | ident_segment ) "from" ident_segment [ "where" boolean_expr ] [ "limit"
|
|
901
|
+
* upsert_from_stmt = "upsert" "into" ident_segment "on" ( "(" ident_list ")" | ident_segment ) "from" ident_segment [ "where" boolean_expr ] [ "limit" numeric_value_atom ] ;
|
|
887
902
|
* @example upsert into authors on id from counts
|
|
888
903
|
* @example upsert into authors on (id, email) from counts where active = true
|
|
889
904
|
*/
|
|
@@ -954,6 +969,7 @@ declare class NqlCstVisitor extends BaseCstVisitor {
|
|
|
954
969
|
orderClause(ctx: CstContext): NqlClause;
|
|
955
970
|
limitClause(ctx: CstContext): NqlClause;
|
|
956
971
|
offsetClause(ctx: CstContext): NqlClause;
|
|
972
|
+
numericValueAtom(ctx: CstContext): NqlLimitCount;
|
|
957
973
|
selectList(ctx: CstContext): NqlSelectItem[];
|
|
958
974
|
selectItem(ctx: CstContext): NqlSelectItem;
|
|
959
975
|
relationStarExpr(ctx: CstContext): NqlSelectItem;
|
|
@@ -980,6 +996,7 @@ declare class NqlCstVisitor extends BaseCstVisitor {
|
|
|
980
996
|
unaryExpr(ctx: CstContext): NqlExpression;
|
|
981
997
|
jsonAccessExpr(ctx: CstContext): NqlExpression;
|
|
982
998
|
primaryExpr(ctx: CstContext): NqlExpression;
|
|
999
|
+
namedParamExpr(ctx: CstContext): NqlNamedParamExpr;
|
|
983
1000
|
caseExpr(ctx: CstContext): NqlCaseExpression;
|
|
984
1001
|
searchedCaseBody(_ctx: CstContext): void;
|
|
985
1002
|
simpleCaseBody(_ctx: CstContext): void;
|
|
@@ -1054,4 +1071,4 @@ declare function parse(input: string, _options?: ParseOptions): ParseResult<NqlP
|
|
|
1054
1071
|
declare function compile(input: string, schema: unknown, // ModelIR from @dbsp/core — satisfies ColumnValidatorSchema
|
|
1055
1072
|
options?: ParseOptions, compilerOptions?: NqlCompilerOptions): ParseResult<CompileResult>;
|
|
1056
1073
|
|
|
1057
|
-
export { type ColumnValidatorSchema, type CompileResult, type NqlAnyExpression, type NqlAssignment, type NqlBetweenExpression, type NqlBinaryExpression, type NqlBindClause, type NqlBooleanLiteral, type NqlCaseExpression, type NqlClause, type NqlComparisonExpression, NqlCompiler, type NqlCompilerOptions, NqlCstVisitor, type NqlCteItem, type NqlDateRangeLiteral, type NqlDelete, type NqlError, type NqlExistsExpression, type NqlExpression, type NqlFlatClause, type NqlFunctionCall, type NqlGroupByClause, type NqlInExpression, type NqlInsert, type NqlInsertFrom, type NqlIsNullExpression, type NqlJoinParam, type NqlJoinSpec, type NqlJsonAccessExpression, type NqlJsonComparisonExpression, NqlLexer, type NqlLimitClause, type NqlLiteral, type NqlLockClause, type NqlMutation, type NqlMutationClause, type NqlMutationPipeline, type NqlNullLiteral, type NqlNumberLiteral, type NqlOffsetClause, type NqlOrderByClause, type NqlOrderItem, type NqlParseError, NqlParser, type NqlPathExpression, type NqlProgram, type NqlQuery, type NqlRangeLiteral, type NqlRangeOpExpression, type NqlRelationFilterExpression, type NqlSelectClause, type NqlSelectExpression, type NqlSelectItem, type NqlSelectRelationStar, type NqlSelectStar, type NqlSemanticError, type NqlSetClause, type NqlStatement, type NqlStringLiteral, type NqlSubquery, type NqlUnaryExpression, type NqlUpdate, type NqlUpsert, type NqlUpsertFrom, type NqlVariableRef, type NqlWarning, type NqlWhereClause, type NqlWindowExpression, type NqlWithQuery, type ParseOptions, type ParseResult, allTokens, compile, createCompiler, cstToAst, nqlVisitor, parse, parseCst };
|
|
1074
|
+
export { type ColumnValidatorSchema, type CompileResult, type NqlAnyExpression, type NqlAssignment, type NqlBetweenExpression, type NqlBinaryExpression, type NqlBindClause, type NqlBooleanLiteral, type NqlCaseExpression, type NqlClause, type NqlComparisonExpression, NqlCompiler, type NqlCompilerOptions, NqlCstVisitor, type NqlCteItem, type NqlDateRangeLiteral, type NqlDelete, type NqlError, type NqlExistsExpression, type NqlExpression, type NqlFlatClause, type NqlFunctionCall, type NqlGroupByClause, type NqlInExpression, type NqlInsert, type NqlInsertFrom, type NqlIsNullExpression, type NqlJoinParam, type NqlJoinSpec, type NqlJsonAccessExpression, type NqlJsonComparisonExpression, NqlLexer, type NqlLimitClause, type NqlLimitCount, type NqlLiteral, type NqlLockClause, type NqlMutation, type NqlMutationClause, type NqlMutationPipeline, type NqlNamedParamExpr, type NqlNullLiteral, type NqlNumberLiteral, type NqlOffsetClause, type NqlOrderByClause, type NqlOrderItem, type NqlParseError, NqlParser, type NqlPathExpression, type NqlProgram, type NqlQuery, type NqlRangeLiteral, type NqlRangeOpExpression, type NqlRelationFilterExpression, type NqlSelectClause, type NqlSelectExpression, type NqlSelectItem, type NqlSelectRelationStar, type NqlSelectStar, type NqlSemanticError, type NqlSetClause, type NqlStatement, type NqlStringLiteral, type NqlSubquery, type NqlUnaryExpression, type NqlUpdate, type NqlUpsert, type NqlUpsertFrom, type NqlVariableRef, type NqlWarning, type NqlWhereClause, type NqlWindowExpression, type NqlWithQuery, type ParseOptions, type ParseResult, allTokens, compile, createCompiler, cstToAst, nqlVisitor, parse, parseCst, tokenize };
|