@dbsp/nql 1.1.0 → 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 +48 -33
- package/dist/index.js +511 -152
- 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.
|
|
@@ -512,6 +506,11 @@ interface NqlWarning {
|
|
|
512
506
|
declare const allTokens: chevrotain.TokenType[];
|
|
513
507
|
declare const NqlLexer: Lexer;
|
|
514
508
|
|
|
509
|
+
/**
|
|
510
|
+
* Tokenize NQL source with the public lexer.
|
|
511
|
+
*/
|
|
512
|
+
declare function tokenize(input: string): ReturnType<typeof NqlLexer.tokenize>;
|
|
513
|
+
|
|
515
514
|
/**
|
|
516
515
|
* NQL Parser using Chevrotain CstParser
|
|
517
516
|
*/
|
|
@@ -580,13 +579,23 @@ declare class NqlParser extends CstParser {
|
|
|
580
579
|
*/
|
|
581
580
|
private orderClause;
|
|
582
581
|
/**
|
|
583
|
-
* limit_clause = "limit" [ident_segment ("." ident_segment)*] NUMBER ;
|
|
582
|
+
* limit_clause = "limit" [ident_segment ("." ident_segment)*] (NUMBER | NAMED_PARAM) ;
|
|
584
583
|
*/
|
|
585
584
|
private limitClause;
|
|
586
585
|
/**
|
|
587
|
-
* offset_clause = "offset" NUMBER ;
|
|
586
|
+
* offset_clause = "offset" (NUMBER | NAMED_PARAM) ;
|
|
588
587
|
*/
|
|
589
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;
|
|
590
599
|
/**
|
|
591
600
|
* lock_clause = lock_strength [ lock_wait_policy ] ;
|
|
592
601
|
* lock_strength = "for update" | "for share" | "for no key update" | "for key share" ;
|
|
@@ -664,7 +673,7 @@ declare class NqlParser extends CstParser {
|
|
|
664
673
|
*/
|
|
665
674
|
private rangeOp;
|
|
666
675
|
/**
|
|
667
|
-
* range_op_suffix = range_op (range_literal | literal) ;
|
|
676
|
+
* range_op_suffix = range_op (range_literal | literal | named_param_expr) ;
|
|
668
677
|
* Example: overlaps [1,10) or contains (0,100) or contains 25
|
|
669
678
|
* Note: contains can take a scalar value (e.g., contains 25 checks if range contains the value)
|
|
670
679
|
*/
|
|
@@ -747,9 +756,13 @@ declare class NqlParser extends CstParser {
|
|
|
747
756
|
*/
|
|
748
757
|
private jsonAccessExpr;
|
|
749
758
|
/**
|
|
750
|
-
* 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 ")" ;
|
|
751
760
|
*/
|
|
752
761
|
private primaryExpr;
|
|
762
|
+
/**
|
|
763
|
+
* named_param_expr = NAMED_PARAM ;
|
|
764
|
+
*/
|
|
765
|
+
private namedParamExpr;
|
|
753
766
|
/**
|
|
754
767
|
* Check if at start of scalar subquery (ident | ...)
|
|
755
768
|
*/
|
|
@@ -866,7 +879,7 @@ declare class NqlParser extends CstParser {
|
|
|
866
879
|
*/
|
|
867
880
|
private insertStmt;
|
|
868
881
|
/**
|
|
869
|
-
* 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 ] ;
|
|
870
883
|
* @example insert into archived_users from users where active = false limit 100
|
|
871
884
|
*/
|
|
872
885
|
private insertFromStmt;
|
|
@@ -885,7 +898,7 @@ declare class NqlParser extends CstParser {
|
|
|
885
898
|
*/
|
|
886
899
|
private upsertStmt;
|
|
887
900
|
/**
|
|
888
|
-
* 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 ] ;
|
|
889
902
|
* @example upsert into authors on id from counts
|
|
890
903
|
* @example upsert into authors on (id, email) from counts where active = true
|
|
891
904
|
*/
|
|
@@ -956,6 +969,7 @@ declare class NqlCstVisitor extends BaseCstVisitor {
|
|
|
956
969
|
orderClause(ctx: CstContext): NqlClause;
|
|
957
970
|
limitClause(ctx: CstContext): NqlClause;
|
|
958
971
|
offsetClause(ctx: CstContext): NqlClause;
|
|
972
|
+
numericValueAtom(ctx: CstContext): NqlLimitCount;
|
|
959
973
|
selectList(ctx: CstContext): NqlSelectItem[];
|
|
960
974
|
selectItem(ctx: CstContext): NqlSelectItem;
|
|
961
975
|
relationStarExpr(ctx: CstContext): NqlSelectItem;
|
|
@@ -982,6 +996,7 @@ declare class NqlCstVisitor extends BaseCstVisitor {
|
|
|
982
996
|
unaryExpr(ctx: CstContext): NqlExpression;
|
|
983
997
|
jsonAccessExpr(ctx: CstContext): NqlExpression;
|
|
984
998
|
primaryExpr(ctx: CstContext): NqlExpression;
|
|
999
|
+
namedParamExpr(ctx: CstContext): NqlNamedParamExpr;
|
|
985
1000
|
caseExpr(ctx: CstContext): NqlCaseExpression;
|
|
986
1001
|
searchedCaseBody(_ctx: CstContext): void;
|
|
987
1002
|
simpleCaseBody(_ctx: CstContext): void;
|
|
@@ -1056,4 +1071,4 @@ declare function parse(input: string, _options?: ParseOptions): ParseResult<NqlP
|
|
|
1056
1071
|
declare function compile(input: string, schema: unknown, // ModelIR from @dbsp/core — satisfies ColumnValidatorSchema
|
|
1057
1072
|
options?: ParseOptions, compilerOptions?: NqlCompilerOptions): ParseResult<CompileResult>;
|
|
1058
1073
|
|
|
1059
|
-
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 };
|