pgdesign v0.26.0 /internal/sqlexpr
On this page

Package sqlexpr is a recursive-descent parser for a subset of PostgreSQL expressions, producing an AST for analysis, validation, and code generation.

#internal/sqlexpr

#internal/sqlexpr

Package sqlexpr is a recursive descent parser for a subset of PostgreSQL SQL expressions. It tokenizes an input string and produces an AST of Node values suitable for static analysis, validation, and code generation.

Operator precedence

Levels from lowest to highest binding:

1. OR 2. AND 3. NOT (unary prefix) 4. Comparison: =, !=, <>, <, >, <=, >=, ~, ~, !~, !~, IS NULL, IS NOT NULL, IS DISTINCT FROM, IN, NOT IN, BETWEEN, LIKE, ILIKE, NOT LIKE, NOT ILIKE 5. Concatenation: || 6. Addition/Subtraction: +, - 7. Multiplication/Division/Modulo: *, /, % 8. Cast: :: 9. Primary: literals, identifiers, function calls, parenthesized expressions, unary minus, EXISTS, CASE

Node types

The AST consists of the following node types, all implementing [Node]:

- [ColumnRef]: column reference, optionally qualified (column, table.column, schema.table.column) - [BoolLiteral]: true or false - [StringLiteral]: single-quoted string - [IntLiteral]: integer - [FloatLiteral]: floating-point number - [NullLiteral]: NULL - [FuncCall]: function call with arguments - [Cast]: PostgreSQL :: cast operator - [BinaryOp]: binary operation (arithmetic, comparison, logical) - [UnaryOp]: unary operation (NOT, IS NULL, IS NOT NULL, unary minus) - [ExistsExpr]: EXISTS (subquery) - [SelectExpr]: simple SELECT inside EXISTS (columns, FROM, optional WHERE) - [ParenExpr]: parenthesized expression - [CaseExpr]: CASE WHEN ... THEN ... ELSE ... END (with [WhenClause])

Keywords

The following keywords are recognized (case-insensitive): OR, AND, NOT, IS, NULL, DISTINCT, FROM, IN, BETWEEN, LIKE, ILIKE, EXISTS, SELECT, WHERE, CASE, WHEN, THEN, ELSE, END, TRUE, FALSE, CAST, AS.

Limitations

- No full SELECT statements; only simple SELECT inside EXISTS with FROM and optional WHERE. - No window functions, CTEs (WITH), or aggregate DISTINCT (e.g., COUNT(DISTINCT x)). - No ORDER BY, GROUP BY, HAVING, or LIMIT. - No subqueries outside EXISTS. - No array subscript notation. - No SIMILAR TO, ANY, or ALL operators. - No type modifiers in casts (e.g., ::varchar(255)).

#Node

Go go
type Node interface

Node is the interface all AST nodes implement.

#ColumnRef

Go go
type ColumnRef struct

ColumnRef is a column reference, optionally qualified. Parts: ["column"], ["table", "column"], or ["schema", "table", "column"].

#BoolLiteral

Go go
type BoolLiteral struct

BoolLiteral is a boolean literal (true/false).

#StringLiteral

Go go
type StringLiteral struct

StringLiteral is a single-quoted string literal.

#IntLiteral

Go go
type IntLiteral struct

IntLiteral is an integer literal.

#FloatLiteral

Go go
type FloatLiteral struct

FloatLiteral is a floating-point literal.

#NullLiteral

Go go
type NullLiteral struct{}

NullLiteral is a NULL literal.

#FuncCall

Go go
type FuncCall struct

FuncCall is a function call with arguments.

#Cast

Go go
type Cast struct

Cast is a type cast expression (expr::type).

#BinaryOp

Go go
type BinaryOp struct

BinaryOp is a binary operation (left op right).

#UnaryOp

Go go
type UnaryOp struct

UnaryOp is a unary operation (e.g., NOT expr).

#ExistsExpr

Go go
type ExistsExpr struct

ExistsExpr is an EXISTS (subquery) expression.

#SelectExpr

Go go
type SelectExpr struct

SelectExpr is a SELECT statement inside EXISTS.

#ParenExpr

Go go
type ParenExpr struct

ParenExpr is a parenthesized expression.

#CaseExpr

Go go
type CaseExpr struct

CaseExpr is a CASE WHEN ... THEN ... [ELSE ...] END expression.

#WhenClause

Go go
type WhenClause struct

WhenClause is a WHEN condition THEN result pair.

#ParseError

Go go
type ParseError struct

ParseError is a structured error with position information from the parser.

#Parse

Go go
func Parse(input string) (Node, error)

Parse parses a SQL expression string into an AST. It handles arithmetic, comparisons, boolean logic, function calls, casts, CASE expressions, and EXISTS subqueries. See the package documentation for the full grammar.

On failure, the returned error is a *[ParseError] (which implements error). ParseError contains Pos (byte offset in the input string), Token (the problematic token text), and Msg (human-readable description) for precise error location reporting.

#Walk

Go go
func Walk(node Node, fn func(Node) bool)

Walk traverses the AST in depth-first order, calling fn for each node. If fn returns false, children of that node are not visited.

#CollectColumnRefs

Go go
func CollectColumnRefs(node Node) []*ColumnRef

CollectColumnRefs walks the AST and returns all ColumnRef nodes found.

#ParseError.Error

Go go
func (e *ParseError) Error() string
Search