feat: production polish — recursive CTE, UNION/INTERSECT/EXCEPT, DROP INDEX, JSON path, FTS SQL, covering index, SCRAM auth

- Recursive CTE execution (WITH RECURSIVE + UNION ALL, work-table loop)
- UNION / INTERSECT / EXCEPT parser + executor (nkSetOp)
- DROP INDEX parser + executor
- VIEW DDL persistence via AST-to-SQL serializer
- JSON path operators -> and ->> (lexer, parser, IR, executor)
- FTS SQL wiring WHERE col @@ 'query' (case-insensitive term match)
- Multi-column index range scans (prefix equality + range on last col)
- Covering index optimization (skip LSM read when index covers SELECT)
- SCRAM-SHA-256 authentication (password-based validation)
- 279 tests, 0 failures
This commit is contained in:
2026-05-07 13:00:36 +03:00
parent 7faae09ad3
commit 5deb38feb2
8 changed files with 548 additions and 41 deletions
+20
View File
@@ -72,6 +72,7 @@ type
tkUnion
tkIntersect
tkExcept
tkAll
tkExists
tkBetween
tkLike
@@ -121,6 +122,9 @@ type
tkVector
tkGraph
tkDocument
tkArrowR # ->
tkArrowRR # ->>
tkFtsMatch # @@
tkSimilar
tkNearest
tkTo
@@ -237,6 +241,7 @@ const keywords*: Table[string, TokenKind] = {
"union": tkUnion,
"intersect": tkIntersect,
"except": tkExcept,
"all": tkAll,
"exists": tkExists,
"between": tkBetween,
"like": tkLike,
@@ -433,6 +438,14 @@ proc nextToken*(l: var Lexer): Token =
discard l.advance()
return Token(kind: tkPlus, value: "+", line: startLine, col: startCol)
of '-':
if l.pos + 1 < l.input.len and l.input[l.pos + 1] == '>':
discard l.advance()
if l.pos + 1 < l.input.len and l.input[l.pos + 1] == '>':
discard l.advance()
discard l.advance()
return Token(kind: tkArrowRR, value: "->>", line: startLine, col: startCol)
discard l.advance()
return Token(kind: tkArrowR, value: "->", line: startLine, col: startCol)
discard l.advance()
return Token(kind: tkMinus, value: "-", line: startLine, col: startCol)
of '*':
@@ -499,6 +512,13 @@ proc nextToken*(l: var Lexer): Token =
return Token(kind: tkCoalesce, value: "??", line: startLine, col: startCol)
discard l.advance()
return Token(kind: tkPlaceholder, value: "?", line: startLine, col: startCol)
of '@':
if l.pos + 1 < l.input.len and l.input[l.pos + 1] == '@':
discard l.advance()
discard l.advance()
return Token(kind: tkFtsMatch, value: "@@", line: startLine, col: startCol)
discard l.advance()
return Token(kind: tkInvalid, value: "@", line: startLine, col: startCol)
of '.':
if l.pos + 1 < l.input.len and l.input[l.pos + 1] == '<':
discard l.advance()