f7d4961125
CI / test (push) Has been cancelled
CI / verify (push) Has been cancelled
Clients CI / build-server (push) Has been cancelled
Clients CI / test-python (push) Has been cancelled
Clients CI / test-javascript (push) Has been cancelled
Clients CI / test-nim (push) Has been cancelled
Clients CI / test-rust (push) Has been cancelled
- SET var = value / current_setting('var') for session-scoped variables
- current_user / current_role SQL keywords with auth bridge
- server.nim + httpserver.nim populate ExecutionContext.currentUser/currentRole
- RLS policies can reference current_setting('app.tenant_id') for tenant isolation
- Fixed evalExpr to propagate ctx recursively (fixes current_user in sub-expressions)
- Fixed GROUPING SETS execution (lowerSelect checks selGroupingSetsKind)
- Fixed FTS CREATE INDEX docId mismatch (hash of tableName.$key)
- Fixed all test suites to use isolated temp directories
- Added 5 multi-tenant tests (355 total, all green)
- Updated docs: PLAN_SQL_ADVANCED.md, baraql.md, changelog.md
557 lines
12 KiB
Nim
557 lines
12 KiB
Nim
## BaraQL AST — Abstract Syntax Tree nodes
|
|
import ../core/types
|
|
|
|
type
|
|
NodeKind* = enum
|
|
# Statements
|
|
nkSelect
|
|
nkInsert
|
|
nkUpdate
|
|
nkDelete
|
|
nkMerge
|
|
nkCreateType
|
|
nkDropType
|
|
nkAlterType
|
|
nkCreateTable
|
|
nkDropTable
|
|
nkAlterTable
|
|
nkCreateIndex
|
|
nkDropIndex
|
|
nkBeginTxn
|
|
nkCommitTxn
|
|
nkRollbackTxn
|
|
nkExplainStmt
|
|
nkRecoverToTimestamp
|
|
nkCreateView
|
|
nkDropView
|
|
nkCreateTrigger
|
|
nkDropTrigger
|
|
nkCreateMigration
|
|
nkApplyMigration
|
|
nkMigrationStatus
|
|
nkMigrationUp
|
|
nkMigrationDown
|
|
nkMigrationDryRun
|
|
nkCreateUser
|
|
nkDropUser
|
|
nkCreatePolicy
|
|
nkDropPolicy
|
|
nkEnableRLS
|
|
nkDisableRLS
|
|
nkGrant
|
|
nkRevoke
|
|
nkSetVar
|
|
|
|
# Clauses
|
|
nkFrom
|
|
nkWhere
|
|
nkOrderBy
|
|
nkGroupBy
|
|
nkHaving
|
|
nkLimit
|
|
nkOffset
|
|
nkReturning
|
|
nkWith
|
|
|
|
# Expressions
|
|
nkBinOp
|
|
nkUnaryOp
|
|
nkJsonPath # column->'key' or column->>'key'
|
|
nkFuncCall
|
|
nkTypeCast
|
|
nkPath
|
|
nkIdent
|
|
nkIntLit
|
|
nkFloatLit
|
|
nkStringLit
|
|
nkBoolLit
|
|
nkNullLit
|
|
nkArrayLit
|
|
nkVectorLit
|
|
nkObjectLit
|
|
nkIfElse
|
|
nkCase
|
|
nkSubquery
|
|
nkExists
|
|
nkInExpr
|
|
nkBetweenExpr
|
|
nkLikeExpr
|
|
nkIsExpr
|
|
nkStar
|
|
nkPlaceholder
|
|
nkCurrentUser
|
|
nkCurrentRole
|
|
|
|
# Graph-specific
|
|
nkGraphTraversal
|
|
nkBfsQuery
|
|
nkDfsQuery
|
|
nkShortestPath
|
|
nkPatternMatch
|
|
|
|
# Vector-specific
|
|
nkVectorSimilar
|
|
nkVectorNearest
|
|
|
|
# Pivot
|
|
nkPivot
|
|
nkUnpivot
|
|
|
|
# Set operations
|
|
nkSetOp
|
|
|
|
# Join
|
|
nkJoin
|
|
|
|
# Type definitions / DDL
|
|
nkPropertyDef
|
|
nkLinkDef
|
|
nkIndexDef
|
|
nkColumnDef
|
|
nkConstraintDef
|
|
|
|
# Window functions
|
|
nkWindowExpr
|
|
nkOverClause
|
|
nkFrameSpec
|
|
nkFrameBoundary
|
|
|
|
# Top-level
|
|
nkStatementList
|
|
|
|
BinOpKind* = enum
|
|
bkAdd = "+"
|
|
bkSub = "-"
|
|
bkMul = "*"
|
|
bkDiv = "/"
|
|
bkMod = "%"
|
|
bkPow = "**"
|
|
bkFloorDiv = "//"
|
|
bkEq = "="
|
|
bkNotEq = "!="
|
|
bkLt = "<"
|
|
bkLtEq = "<="
|
|
bkGt = ">"
|
|
bkGtEq = ">="
|
|
bkAnd = "AND"
|
|
bkOr = "OR"
|
|
bkIn = "IN"
|
|
bkNotIn = "NOT IN"
|
|
bkLike = "LIKE"
|
|
bkILike = "ILIKE"
|
|
bkConcat = "++"
|
|
bkCoalesce = "??"
|
|
bkAssign = ":="
|
|
bkArrow = "=>"
|
|
bkJsonPath = "->"
|
|
bkJsonPathText = "->>"
|
|
bkFtsMatch = "@@"
|
|
bkDistance = "<->"
|
|
bkJsonContains = "@>"
|
|
bkJsonContainedBy = "<@"
|
|
bkJsonHasAny = "?|"
|
|
bkJsonHasAll = "?&"
|
|
|
|
UnaryOpKind* = enum
|
|
ukNeg = "-"
|
|
ukNot = "NOT"
|
|
ukIsNull = "IS NULL"
|
|
ukIsNotNull = "IS NOT NULL"
|
|
|
|
JoinKind* = enum
|
|
jkInner
|
|
jkLeft
|
|
jkRight
|
|
jkFull
|
|
jkCross
|
|
|
|
SetOpKind* = enum
|
|
sdkUnion
|
|
sdkIntersect
|
|
sdkExcept
|
|
|
|
GroupingSetsKind* = enum
|
|
gskNone
|
|
gskGroupingSets
|
|
gskRollup
|
|
gskCube
|
|
|
|
SortDir* = enum
|
|
sdAsc
|
|
sdDesc
|
|
|
|
Node* = ref object
|
|
line*: int
|
|
col*: int
|
|
exprAlias*: string
|
|
case kind*: NodeKind
|
|
of nkSelect:
|
|
selDistinct*: bool
|
|
selWith*: seq[(string, Node, bool)]
|
|
selResult*: seq[Node]
|
|
selFrom*: Node
|
|
selJoins*: seq[Node]
|
|
selWhere*: Node
|
|
selGroupBy*: seq[Node]
|
|
selGroupingSetsKind*: GroupingSetsKind
|
|
selGroupingSets*: seq[seq[Node]]
|
|
selHaving*: Node
|
|
selOrderBy*: seq[Node]
|
|
selLimit*: Node
|
|
selOffset*: Node
|
|
of nkInsert:
|
|
insTarget*: string
|
|
insFields*: seq[Node]
|
|
insValues*: seq[Node]
|
|
insReturning*: seq[Node]
|
|
insConflict*: Node
|
|
of nkUpdate:
|
|
updTarget*: string
|
|
updAlias*: string
|
|
updSet*: seq[Node]
|
|
updWhere*: Node
|
|
updReturning*: seq[Node]
|
|
of nkDelete:
|
|
delTarget*: string
|
|
delAlias*: string
|
|
delWhere*: Node
|
|
delReturning*: seq[Node]
|
|
of nkMerge:
|
|
mergeTarget*: string
|
|
mergeTargetAlias*: string
|
|
mergeSource*: Node
|
|
mergeSourceAlias*: string
|
|
mergeOn*: Node
|
|
mergeMatchedUpdate*: seq[Node] # SET assignments, empty if no UPDATE
|
|
mergeNotMatchedInsert*: seq[Node] # column list for INSERT
|
|
mergeNotMatchedValues*: seq[Node] # value expressions for INSERT
|
|
of nkCreateType:
|
|
ctName*: string
|
|
ctBases*: seq[string]
|
|
ctProperties*: seq[Node]
|
|
ctLinks*: seq[Node]
|
|
of nkDropType:
|
|
dtName*: string
|
|
of nkAlterType:
|
|
atName*: string
|
|
atOps*: seq[Node]
|
|
of nkCreateTable:
|
|
crtName*: string
|
|
crtColumns*: seq[Node]
|
|
crtConstraints*: seq[Node]
|
|
crtIfNotExists*: bool
|
|
of nkDropTable:
|
|
drtName*: string
|
|
drtIfExists*: bool
|
|
of nkAlterTable:
|
|
altName*: string
|
|
altOps*: seq[Node]
|
|
of nkColumnDef:
|
|
cdName*: string
|
|
cdType*: string
|
|
cdConstraints*: seq[Node]
|
|
of nkConstraintDef:
|
|
cstName*: string
|
|
cstType*: string
|
|
cstExpr*: Node
|
|
cstColumns*: seq[string]
|
|
cstRefTable*: string
|
|
cstRefColumns*: seq[string]
|
|
cstOnDelete*: string
|
|
cstOnUpdate*: string
|
|
cstCheck*: Node
|
|
cstDefault*: Node
|
|
of nkBeginTxn:
|
|
btxnMode*: string
|
|
of nkCommitTxn:
|
|
ctxnChain*: bool
|
|
of nkRollbackTxn:
|
|
rtxnChain*: bool
|
|
of nkExplainStmt:
|
|
expStmt*: Node
|
|
expAnalyze*: bool
|
|
of nkRecoverToTimestamp:
|
|
recoverTimestamp*: string
|
|
of nkCreateView:
|
|
cvName*: string
|
|
cvQuery*: Node
|
|
cvOrReplace*: bool
|
|
of nkDropView:
|
|
dvName*: string
|
|
dvIfExists*: bool
|
|
of nkCreateTrigger:
|
|
trigName*: string
|
|
trigTable*: string
|
|
trigTiming*: string # BEFORE, AFTER, INSTEAD OF
|
|
trigEvent*: string # INSERT, UPDATE, DELETE
|
|
trigAction*: Node # SQL statement to execute
|
|
of nkDropTrigger:
|
|
trigDropName*: string
|
|
trigDropIfExists*: bool
|
|
of nkCreateMigration:
|
|
cmName*: string
|
|
cmBody*: string # UP migration body (SQL string)
|
|
cmDownBody*: string # DOWN migration body (SQL string)
|
|
cmChecksum*: string # SHA256 of cmBody
|
|
cmAuthor*: string
|
|
cmTimestamp*: int64
|
|
of nkCreateUser:
|
|
cuName*: string
|
|
cuPassword*: string
|
|
cuSuperuser*: bool
|
|
of nkDropUser:
|
|
duName*: string
|
|
duIfExists*: bool
|
|
of nkCreatePolicy:
|
|
cpName*: string
|
|
cpTable*: string
|
|
cpCommand*: string # ALL, SELECT, INSERT, UPDATE, DELETE
|
|
cpUsing*: Node # USING expression
|
|
cpWithCheck*: Node # WITH CHECK expression
|
|
of nkDropPolicy:
|
|
dpName*: string
|
|
dpTable*: string
|
|
dpIfExists*: bool
|
|
of nkEnableRLS:
|
|
erlsTable*: string
|
|
of nkDisableRLS:
|
|
drlsTable*: string
|
|
of nkGrant:
|
|
grPrivilege*: string # SELECT, INSERT, UPDATE, DELETE, ALL
|
|
grTable*: string
|
|
grGrantee*: string # user, role, or PUBLIC
|
|
of nkRevoke:
|
|
rvPrivilege*: string
|
|
rvTable*: string
|
|
rvGrantee*: string
|
|
of nkSetVar:
|
|
svName*: string
|
|
svValue*: string
|
|
of nkApplyMigration:
|
|
amName*: string
|
|
of nkMigrationStatus:
|
|
discard # no fields needed
|
|
of nkMigrationUp:
|
|
muCount*: int # 0 = all, N = apply N pending migrations
|
|
of nkMigrationDown:
|
|
mdCount*: int # 0 = 1, N = rollback N migrations
|
|
of nkMigrationDryRun:
|
|
mdrName*: string # migration name to dry-run
|
|
of nkCreateIndex:
|
|
ciTarget*: string
|
|
ciName*: string
|
|
ciColumns*: seq[string]
|
|
ciExpr*: Node
|
|
ciKind*: IndexKind
|
|
of nkDropIndex:
|
|
diName*: string
|
|
of nkFrom:
|
|
fromTable*: string
|
|
fromAlias*: string
|
|
fromSubquery*: Node
|
|
of nkWhere:
|
|
whereExpr*: Node
|
|
of nkOrderBy:
|
|
orderByExpr*: Node
|
|
orderByDir*: SortDir
|
|
of nkGroupBy:
|
|
groupExprs*: seq[Node]
|
|
of nkHaving:
|
|
havingExpr*: Node
|
|
of nkLimit:
|
|
limitExpr*: Node
|
|
of nkOffset:
|
|
offsetExpr*: Node
|
|
of nkReturning:
|
|
retExprs*: seq[Node]
|
|
of nkWith:
|
|
withBindings*: seq[(string, Node, bool)]
|
|
of nkBinOp:
|
|
binOp*: BinOpKind
|
|
binLeft*: Node
|
|
binRight*: Node
|
|
of nkUnaryOp:
|
|
unOp*: UnaryOpKind
|
|
unOperand*: Node
|
|
of nkJsonPath:
|
|
jpLeft*: Node
|
|
jpKey*: string
|
|
jpAsText*: bool # true for ->>, false for ->
|
|
of nkFuncCall:
|
|
funcName*: string
|
|
funcArgs*: seq[Node]
|
|
funcFilter*: Node
|
|
of nkTypeCast:
|
|
castType*: string
|
|
castExpr*: Node
|
|
of nkPath:
|
|
pathParts*: seq[string]
|
|
of nkIdent:
|
|
identName*: string
|
|
of nkIntLit:
|
|
intVal*: int64
|
|
of nkFloatLit:
|
|
floatVal*: float64
|
|
of nkStringLit:
|
|
strVal*: string
|
|
of nkBoolLit:
|
|
boolVal*: bool
|
|
of nkNullLit:
|
|
discard
|
|
of nkArrayLit:
|
|
arrayElems*: seq[Node]
|
|
of nkVectorLit:
|
|
vecElems*: seq[Node]
|
|
of nkObjectLit:
|
|
objFields*: seq[(string, Node)]
|
|
of nkIfElse:
|
|
ifCond*: Node
|
|
ifThen*: Node
|
|
ifElse*: Node
|
|
of nkCase:
|
|
caseExpr*: Node
|
|
caseWhens*: seq[(Node, Node)]
|
|
caseElse*: Node
|
|
of nkSubquery:
|
|
subQuery*: Node
|
|
of nkExists:
|
|
existsExpr*: Node
|
|
of nkInExpr:
|
|
inLeft*: Node
|
|
inRight*: Node
|
|
of nkBetweenExpr:
|
|
betweenExpr*: Node
|
|
betweenLow*: Node
|
|
betweenHigh*: Node
|
|
of nkLikeExpr:
|
|
likeExpr*: Node
|
|
likePattern*: Node
|
|
likeCaseInsensitive*: bool
|
|
of nkIsExpr:
|
|
isExpr*: Node
|
|
isType*: string
|
|
isNegated*: bool
|
|
of nkGraphTraversal:
|
|
gtGraphName*: string
|
|
gtStart*: Node
|
|
gtEdge*: string
|
|
gtDirection*: string
|
|
gtEnd*: Node
|
|
gtMaxDepth*: int
|
|
gtReturnCols*: seq[string]
|
|
of nkBfsQuery:
|
|
bfsStart*: Node
|
|
bfsTarget*: Node
|
|
bfsEdge*: string
|
|
bfsMaxDepth*: int
|
|
bfsFilter*: Node
|
|
of nkDfsQuery:
|
|
dfsStart*: Node
|
|
dfsTarget*: Node
|
|
dfsEdge*: string
|
|
dfsMaxDepth*: int
|
|
dfsFilter*: Node
|
|
of nkShortestPath:
|
|
spStart*: Node
|
|
spEnd*: Node
|
|
spEdge*: string
|
|
spMaxDepth*: int
|
|
of nkPatternMatch:
|
|
pmPattern*: Node
|
|
pmWhere*: Node
|
|
of nkVectorSimilar:
|
|
vsField*: string
|
|
vsVector*: Node
|
|
vsLimit*: int
|
|
vsMetric*: string
|
|
of nkVectorNearest:
|
|
vnField*: string
|
|
vnVector*: Node
|
|
vnLimit*: int
|
|
vnMetric*: string
|
|
of nkPivot:
|
|
pivotSource*: Node
|
|
pivotAgg*: Node
|
|
pivotForCol*: string
|
|
pivotInValues*: seq[string]
|
|
of nkUnpivot:
|
|
unpivotSource*: Node
|
|
unpivotValueCol*: string
|
|
unpivotForCol*: string
|
|
unpivotInCols*: seq[string]
|
|
of nkJoin:
|
|
joinKind*: JoinKind
|
|
joinTarget*: Node
|
|
joinOn*: Node
|
|
joinAlias*: string
|
|
joinLateral*: bool
|
|
of nkSetOp:
|
|
setOpKind*: SetOpKind
|
|
setOpAll*: bool
|
|
setOpLeft*: Node
|
|
setOpRight*: Node
|
|
of nkStar:
|
|
discard
|
|
of nkPlaceholder:
|
|
discard
|
|
of nkCurrentUser:
|
|
discard
|
|
of nkCurrentRole:
|
|
discard
|
|
of nkPropertyDef:
|
|
pdName*: string
|
|
pdType*: string
|
|
pdRequired*: bool
|
|
pdDefault*: Node
|
|
pdComputed*: bool
|
|
pdExpr*: Node
|
|
of nkLinkDef:
|
|
ldName*: string
|
|
ldTarget*: string
|
|
ldCardinality*: Cardinality
|
|
ldRequired*: bool
|
|
of nkIndexDef:
|
|
idName*: string
|
|
idExpr*: Node
|
|
idKind*: IndexKind
|
|
of nkWindowExpr:
|
|
winFunc*: string
|
|
winArgs*: seq[Node]
|
|
winOver*: Node
|
|
of nkOverClause:
|
|
overPartition*: seq[Node]
|
|
overOrderBy*: seq[Node]
|
|
overFrame*: Node
|
|
of nkFrameSpec:
|
|
frameMode*: string # "ROWS" or "RANGE"
|
|
frameStartType*: string # "UNBOUNDED PRECEDING", "CURRENT ROW", "EXPR PRECEDING", "EXPR FOLLOWING"
|
|
frameStartExpr*: Node
|
|
frameEndType*: string
|
|
frameEndExpr*: Node
|
|
frameExclude*: string # "NO OTHERS", "CURRENT ROW", "GROUP", "TIES"
|
|
of nkFrameBoundary:
|
|
fbType*: string # "UNBOUNDED PRECEDING", "CURRENT ROW", "EXPR PRECEDING", "EXPR FOLLOWING", "UNBOUNDED FOLLOWING"
|
|
fbExpr*: Node
|
|
of nkStatementList:
|
|
stmts*: seq[Node]
|
|
|
|
proc newNode*(kind: NodeKind, line: int = 0, col: int = 0): Node =
|
|
result = Node(kind: kind, line: line, col: col)
|
|
case kind
|
|
of nkSelect: result.selResult = @[]
|
|
of nkInsert: result.insFields = @[]; result.insValues = @[]
|
|
of nkUpdate: result.updSet = @[]
|
|
of nkDelete: discard
|
|
of nkCreateTable: result.crtColumns = @[]; result.crtConstraints = @[]
|
|
of nkAlterTable: result.altOps = @[]
|
|
of nkColumnDef: result.cdConstraints = @[]
|
|
of nkConstraintDef: result.cstColumns = @[]; result.cstRefColumns = @[]
|
|
of nkWindowExpr: result.winArgs = @[]
|
|
of nkOverClause: result.overPartition = @[]; result.overOrderBy = @[]
|
|
of nkMerge:
|
|
result.mergeMatchedUpdate = @[]
|
|
result.mergeNotMatchedInsert = @[]
|
|
result.mergeNotMatchedValues = @[]
|
|
of nkStatementList: result.stmts = @[]
|
|
else: discard
|