Documentation
¶
Overview ¶
Package sqldsl provides a type-safe DSL for building PostgreSQL queries.
Overview ¶
Rather than constructing SQL strings through concatenation or templating, this package provides typed building blocks that compose together to form complete queries. The DSL models authorization query patterns directly, making it easier to construct correct queries and avoiding common SQL injection vulnerabilities.
Core Interfaces ¶
All DSL types implement one of two interfaces:
- Expr: Represents SQL expressions (columns, literals, operators, function calls)
- SQLer: Represents complete SQL statements (SELECT, WITH, etc.)
Both interfaces define a SQL() method that renders the PostgreSQL syntax.
Expression Types ¶
Basic expressions:
Param("p_subject_type") // Function parameter reference
Col{Table: "t", Column: "id"} // Column reference: t.id
Lit("document") // String literal: 'document'
Int(42) // Integer literal: 42
Bool(true) // Boolean literal: TRUE
Null{} // NULL literal
Raw("CURRENT_TIMESTAMP") // Raw SQL (escape hatch)
Operators:
Eq{Left: col, Right: param} // col = param
In{Expr: col, Values: []string} // col IN ('a', 'b')
And(expr1, expr2, expr3) // (expr1 AND expr2 AND expr3)
Or(expr1, expr2) // (expr1 OR expr2)
Not(expr) // NOT (expr)
Exists{Query: subquery} // EXISTS (subquery)
Authorization-specific helpers:
SubjectIDMatch(col, id, wildcard) // Match subject_id with optional wildcard
HasUserset{Source: col} // Check if subject_id contains '#'
UsersetObjectID{Source: col} // Extract object ID from userset (split_part)
Statement Types ¶
SELECT statements:
SelectStmt{
Columns: []string{"object_id", "relation"},
From: "melange_tuples",
Alias: "t",
Where: And(condition1, condition2),
Limit: 100,
}
Common Table Expressions:
WithCTE{
Recursive: true,
CTEs: []CTEDef{
{Name: "accessible", Query: cteQuery},
},
Query: finalSelect,
}
Query Builders ¶
The tuples subpackage provides a fluent builder for common tuple queries:
query := Tuples("t").
ObjectType("document").
Relations("viewer", "editor").
WhereSubjectType(SubjectType).
WhereSubjectID(SubjectID, true).
Select("t.object_id").
Distinct()
sql := query.SQL()
Design Rationale ¶
Type safety: The compiler catches many errors that would otherwise only be found at runtime when executing the generated SQL.
Composition: Complex queries are built from simple parts that can be tested and reasoned about independently.
Authorization semantics: The DSL includes domain-specific helpers like SubjectIDMatch and UsersetObjectID that encode OpenFGA authorization patterns directly, reducing boilerplate and errors.
SQL visibility: Unlike heavy ORMs, the DSL stays close to SQL syntax. Developers familiar with PostgreSQL can easily read and write DSL code.
Package sqldsl provides a domain-specific SQL DSL for generating Melange authorization queries. It models authorization concepts directly rather than generic SQL syntax.
Index ¶
- Variables
- func Ident(name string) string
- func IndentLines(input, indent string) string
- func ListObjectsFunctionName(objectType, relation string) string
- func ListSubjectsFunctionName(objectType, relation string) string
- func Optf(cond bool, format string, args ...any) string
- func RenderBlocks(blocks []QueryBlock) string
- func RenderUnionBlocks(blocks []QueryBlock) string
- func Sqlf(format string, args ...any) string
- func WrapWithExclusionCTEAndPagination(query, exclusionCTE string) string
- func WrapWithPagination(query, idColumn string) string
- func WrapWithPaginationWildcardFirst(query string) string
- type Add
- type Alias
- type AndExpr
- type ArrayAppend
- type ArrayContains
- type ArrayLength
- type ArrayLiteral
- type Bool
- type CTEDef
- type CaseExpr
- type CaseWhen
- type Cast
- type Col
- type CommentedSQL
- type Concat
- type EmptyArray
- type Eq
- type Exists
- type Expr
- type Func
- type FuncCallEq
- func InternalCheckCall(subjectType, subjectID Expr, relation string, ...) FuncCallEq
- func InternalPermissionCheckCall(relation, objectType string, objectID, visited Expr) FuncCallEq
- func NoWildcardPermissionCheckCall(relation, objectType string, subjectID, objectID Expr) FuncCallEq
- func SpecializedCheckCall(funcName string, subjectType, subjectID, objectID, visited Expr) FuncCallEq
- type FuncCallNe
- type FunctionCallExpr
- type Gt
- type Gte
- type HasUserset
- type In
- type InFunctionSelect
- type Int
- type IntersectSubquery
- type IsNotNull
- type IsNull
- type IsWildcard
- type JoinClause
- type LateralFunction
- type Like
- type Lit
- type Lt
- type Lte
- type Ne
- type NoUserset
- type NotExists
- type NotExpr
- type NotIn
- type NotLike
- type Null
- type ObjectRef
- type OrExpr
- type Param
- type Paren
- type Position
- type QueryBlock
- type Raw
- type SQLer
- type SelectIntoVar
- type SelectStmt
- type Sub
- type SubjectRef
- type Substring
- type SubstringUsersetRelation
- type TableExpr
- type TableRef
- type TupleNotIn
- type TypedValuesTable
- type UnionAll
- type UsersetNormalized
- type UsersetObjectID
- type UsersetRelation
- type ValuesRow
- type ValuesTable
- type WithCTE
Constants ¶
This section is empty.
Variables ¶
var ( SubjectType = Param("p_subject_type") SubjectID = Param("p_subject_id") ObjectType = Param("p_object_type") ObjectID = Param("p_object_id") Visited = Param("p_visited") )
Common parameter constants.
Functions ¶
func Ident ¶
Ident sanitizes an identifier for use in SQL. Replaces non-alphanumeric characters with underscores.
func IndentLines ¶
IndentLines adds the given indent prefix to each line of input.
func ListObjectsFunctionName ¶
ListObjectsFunctionName generates a list_TYPE_RELATION_objects function name.
func ListSubjectsFunctionName ¶
ListSubjectsFunctionName generates a list_TYPE_RELATION_subjects function name.
func Optf ¶
Optf returns formatted string if condition is true, empty string otherwise. Useful for optional SQL clauses.
func RenderBlocks ¶
func RenderBlocks(blocks []QueryBlock) string
RenderBlocks renders multiple query blocks sequentially. Each block is indented and comments are rendered as SQL comments.
func RenderUnionBlocks ¶
func RenderUnionBlocks(blocks []QueryBlock) string
RenderUnionBlocks renders query blocks joined with UNION. Each block is indented and comments are rendered as SQL comments.
func Sqlf ¶
Sqlf formats SQL with automatic dedenting and blank line removal. The SQL shape is visible in the format string.
func WrapWithExclusionCTEAndPagination ¶
WrapWithExclusionCTEAndPagination wraps a query with exclusion CTE precomputation and wildcard-first pagination.
Optimization: Materializes excluded subjects once in a CTE, then applies a single LEFT JOIN...WHERE IS NULL anti-pattern instead of repeated NOT EXISTS subqueries.
Structure:
WITH excluded_subjects AS (SELECT subject_id FROM melange_tuples WHERE ...),
candidates AS (...original UNION without exclusion predicates...),
base_results AS (
SELECT DISTINCT s.subject_id FROM candidates s
LEFT JOIN excluded_subjects excl
ON excl.subject_id = s.subject_id OR excl.subject_id = '*'
WHERE excl.subject_id IS NULL
),
...pagination CTEs...
Parameters:
query: UNION of all access paths (without exclusion predicates) exclusionCTE: SQL for exclusion CTE (SELECT subject_id FROM ...)
Returns: Complete paginated query with exclusion anti-join
func WrapWithPagination ¶
WrapWithPagination wraps a query with cursor-based pagination. The idColumn parameter specifies which column to use for ordering and cursoring.
func WrapWithPaginationWildcardFirst ¶
WrapWithPaginationWildcardFirst wraps a query for list_subjects with wildcard-first ordering. Wildcards ('*') are sorted before all other subject IDs to ensure consistent pagination. Uses a compound sort key: (is_not_wildcard, subject_id) where is_not_wildcard is 0 for '*', 1 otherwise.
Types ¶
type Alias ¶
Alias wraps an expression with an alias (expr AS alias).
type AndExpr ¶
type AndExpr struct {
Exprs []Expr
}
AndExpr represents a logical AND of multiple expressions.
type ArrayAppend ¶
type ArrayAppend struct {
Array Expr // The base array expression
Values []Expr // Values to append (rendered as ARRAY[...])
}
ArrayAppend represents array concatenation: arr || ARRAY[values]. Used for building the visited array in recursive check functions.
Example:
ArrayAppend{
Array: Param("p_visited"),
Values: []Expr{Concat{Parts: []Expr{Lit("doc:"), ObjectID, Lit(":viewer")}}},
}
Renders: p_visited || ARRAY['doc:' || p_object_id || ':viewer']
func VisitedWithKey ¶
func VisitedWithKey(objectType, relation string, objectID Expr) ArrayAppend
VisitedWithKey creates the p_visited || ARRAY[key] expression. This is the standard pattern for passing updated visited arrays to recursive calls.
Example:
VisitedWithKey("document", "viewer", ObjectID)
Renders: p_visited || ARRAY['document:' || p_object_id || ':viewer']
type ArrayContains ¶
ArrayContains represents the ANY() check: value = ANY(array).
type ArrayLength ¶
ArrayLength represents array_length(arr, dim).
type ArrayLiteral ¶
type ArrayLiteral struct {
Values []Expr
}
ArrayLiteral represents a SQL array literal: ARRAY[values].
type CTEDef ¶
type CTEDef struct {
Name string // CTE name (e.g., "accessible", "base_results")
Columns []string // Optional column names (e.g., ["object_id", "depth"])
Materialized bool // If true, renders "AS MATERIALIZED" (PostgreSQL 12+)
Query SQLer // The CTE query body
}
CTEDef represents a single Common Table Expression definition. Used within WithCTE to define named subqueries.
type CommentedSQL ¶
type CommentedSQL struct {
Comment string // Comment text (without -- prefix)
Query SQLer // The query to render after the comment
}
CommentedSQL wraps a query with a SQL comment prefix. Useful for adding descriptive comments to parts of a UNION or CTE body.
Example:
CommentedSQL{Comment: "Base case: seed with starting value", Query: baseQuery}
Renders:
-- Base case: seed with starting value <base query>
func MultiLineComment ¶
func MultiLineComment(comments []string, query SQLer) CommentedSQL
MultiLineComment creates a CommentedSQL with multiple comment lines. The query follows after all comment lines.
func (CommentedSQL) SQL ¶
func (c CommentedSQL) SQL() string
SQL renders the comment followed by the query.
type EmptyArray ¶
type EmptyArray struct{}
EmptyArray represents an empty text array (ARRAY[]::TEXT[]).
type Exists ¶
type Exists struct {
Query interface{ SQL() string }
}
Exists represents an EXISTS subquery.
func ExistsExpr ¶
func ExistsExpr(stmt SelectStmt) Exists
ExistsExpr creates an Exists expression from a SelectStmt.
type Expr ¶
type Expr interface {
SQL() string
}
Expr is the interface that all SQL expression types implement.
func NormalizedUsersetSubject ¶
NormalizedUsersetSubject combines the object_id from a userset with a new relation. Example: split_part(subject_id, '#', 1) || '#' || v_filter_relation
func SubjectIDMatch ¶
SubjectIDMatch creates a condition for matching subject IDs. When allowWildcard is true, matches exact ID or wildcard tuples. When allowWildcard is false, matches exact ID and excludes wildcard tuples.
func VisitedKey ¶
VisitedKey creates the standard visited key expression for cycle detection. The key format is: 'objectType:' || objectID || ':relation'
Example:
VisitedKey("document", "viewer", ObjectID)
Renders the expression: 'document:' || p_object_id || ':viewer'
type FuncCallEq ¶
type FuncCallEq struct {
FuncName string
Args []Expr
Value Expr // The value to compare against (typically Int(1) or Int(0))
}
FuncCallEq compares a function call result to a value. Used for authorization check expressions like "check_permission(...) = 1".
Example:
FuncCallEq{
FuncName: "check_doc_viewer",
Args: []Expr{SubjectType, SubjectID, ObjectID, Visited},
Value: Int(1),
}
Renders: check_doc_viewer(p_subject_type, p_subject_id, p_object_id, p_visited) = 1
func InternalCheckCall ¶
func InternalCheckCall(subjectType, subjectID Expr, relation string, parentType, parentID, visited Expr) FuncCallEq
InternalCheckCall creates a check_permission_internal call with explicit subject/object types. Used in parent relation (TTU) checks where the linking tuple provides the parent object.
Example:
InternalCheckCall(SubjectType, SubjectID, "viewer", Col{Table: "link", Column: "subject_type"}, Col{Table: "link", Column: "subject_id"}, visited)
Renders: check_permission_internal(p_subject_type, p_subject_id, 'viewer', link.subject_type, link.subject_id, <visited>) = 1
func InternalPermissionCheckCall ¶
func InternalPermissionCheckCall(relation, objectType string, objectID, visited Expr) FuncCallEq
InternalPermissionCheckCall creates a check_permission_internal function call comparison. This is the most common pattern in the codebase for recursive permission checks.
Example:
InternalPermissionCheckCall("viewer", "document", Col{Table: "t", Column: "object_id"}, Visited)
Renders: check_permission_internal(p_subject_type, p_subject_id, 'viewer', 'document', t.object_id, p_visited) = 1
func NoWildcardPermissionCheckCall ¶
func NoWildcardPermissionCheckCall(relation, objectType string, subjectID, objectID Expr) FuncCallEq
NoWildcardPermissionCheckCall creates a check_permission_no_wildcard function call.
func SpecializedCheckCall ¶
func SpecializedCheckCall(funcName string, subjectType, subjectID, objectID, visited Expr) FuncCallEq
SpecializedCheckCall creates a call to a specialized check function. Used for implied relations and parent relation checks.
Example:
SpecializedCheckCall("check_doc_owner", SubjectType, SubjectID, ObjectID, Visited)
Renders: check_doc_owner(p_subject_type, p_subject_id, p_object_id, p_visited) = 1
type FuncCallNe ¶
FuncCallNe compares a function call result for inequality. Used for negative authorization checks like "check_permission(...) <> 1".
func (FuncCallNe) SQL ¶
func (f FuncCallNe) SQL() string
SQL renders the function call not-equal comparison.
type FunctionCallExpr ¶
type FunctionCallExpr struct {
Name string // Function name
Args []Expr // Function arguments
Alias string // Table alias for the result
}
FunctionCallExpr represents a function call that can be used as a table expression. Used for LATERAL joins with table-returning functions.
func (FunctionCallExpr) TableAlias ¶
func (f FunctionCallExpr) TableAlias() string
TableAlias implements TableExpr.
func (FunctionCallExpr) TableSQL ¶
func (f FunctionCallExpr) TableSQL() string
TableSQL implements TableExpr.
type HasUserset ¶
type HasUserset struct {
Source Expr
}
HasUserset checks if an expression contains a userset marker (#).
func (HasUserset) SQL ¶
func (h HasUserset) SQL() string
type InFunctionSelect ¶
type InFunctionSelect struct {
Expr Expr // The expression to check (left side of IN)
FuncName string // The function to call
Args []Expr // Function arguments
Alias string // Alias for the function result
SelectCol string // Column to select from the function result
}
InFunctionSelect represents "expr IN (SELECT column FROM func(args...) alias)". Used for checking membership against results of a list function.
Example:
InFunctionSelect{
Expr: Col{Table: "t", Column: "subject_id"},
FuncName: "list_doc_viewer_objects",
Args: []Expr{SubjectType, SubjectID, Null{}, Null{}},
Alias: "obj",
SelectCol: "object_id",
}
Renders: t.subject_id IN (SELECT obj.object_id FROM list_doc_viewer_objects(p_subject_type, p_subject_id, NULL, NULL) obj)
func (InFunctionSelect) SQL ¶
func (i InFunctionSelect) SQL() string
SQL renders the IN subquery expression.
type IntersectSubquery ¶
type IntersectSubquery struct {
Queries []SelectStmt
Alias string
}
IntersectSubquery represents an INTERSECT of multiple queries as a subquery. Used for intersection groups where all parts must be satisfied.
Example: IntersectSubquery{Queries: [q1, q2], Alias: "ig"} Renders: (q1 INTERSECT q2) AS ig
func (IntersectSubquery) TableAlias ¶
func (i IntersectSubquery) TableAlias() string
TableAlias implements TableExpr.
func (IntersectSubquery) TableSQL ¶
func (i IntersectSubquery) TableSQL() string
TableSQL renders the INTERSECT subquery as a FROM clause table expression.
type IsWildcard ¶
type IsWildcard struct {
Source Expr
}
IsWildcard checks if an expression equals the wildcard value "*".
func (IsWildcard) SQL ¶
func (w IsWildcard) SQL() string
type JoinClause ¶
type JoinClause struct {
Type string // "INNER", "LEFT", etc.
Table string // Deprecated: use TableExpr instead
TableExpr TableExpr // Preferred: typed table expression
Alias string // Deprecated: use TableExpr's alias instead
On Expr
}
JoinClause represents a SQL JOIN clause.
type LateralFunction ¶
LateralFunction represents a LATERAL function call in a JOIN. Example: LateralFunction{Name: "list_doc_viewer_subjects", Args: []Expr{...}, Alias: "s"} Renders: LATERAL list_doc_viewer_subjects(...) AS s
func (LateralFunction) SQL ¶
func (l LateralFunction) SQL() string
SQL renders the LATERAL function expression.
func (LateralFunction) TableAlias ¶
func (l LateralFunction) TableAlias() string
TableAlias implements TableExpr.
func (LateralFunction) TableSQL ¶
func (l LateralFunction) TableSQL() string
TableSQL implements TableExpr.
type Lit ¶
type Lit string
Lit represents a literal string value (auto-quoted with single quotes).
type NoUserset ¶
type NoUserset struct {
Source Expr
}
NoUserset checks if an expression does NOT contain a userset marker (#).
type NotExists ¶
type NotExists struct {
Query interface{ SQL() string }
}
NotExists represents a NOT EXISTS subquery.
type ObjectRef ¶
ObjectRef represents an object reference (type + id).
func LiteralObject ¶
LiteralObject creates an ObjectRef with literal type and expression ID.
type OrExpr ¶
type OrExpr struct {
Exprs []Expr
}
OrExpr represents a logical OR of multiple expressions.
type Param ¶
type Param string
Param represents a function parameter (e.g., p_subject_type, p_object_id).
type Position ¶
Position represents SQL position(needle in haystack). Returns the position of the first occurrence of needle in haystack.
type QueryBlock ¶
type QueryBlock struct {
Comments []string // Comment lines (without -- prefix)
Query SQLer // The query as typed DSL (SelectStmt, Raw, etc.)
}
QueryBlock represents a query with optional comments. Used to build UNION queries with descriptive comments for each branch.
type SQLer ¶
type SQLer interface {
SQL() string
}
SQLer is an interface for types that can render SQL. SelectStmt, Raw, and other query types implement this interface.
type SelectIntoVar ¶
type SelectIntoVar struct {
Query SQLer // The query (e.g., a CTE)
Variable string // Variable name to select into
}
SelectIntoVar wraps a query for use with PL/pgSQL SELECT INTO. Appends "INTO <variable>" after the query.
Example:
SelectIntoVar{Query: cteQuery, Variable: "v_max_depth"}
Renders:
<query> INTO v_max_depth
func (SelectIntoVar) SQL ¶
func (s SelectIntoVar) SQL() string
SQL renders the query with INTO clause appended.
type SelectStmt ¶
type SelectStmt struct {
Distinct bool
Columns []string // Deprecated: use ColumnExprs instead
ColumnExprs []Expr // Preferred: typed column expressions
From string // Deprecated: use FromExpr instead
FromExpr TableExpr // Preferred: typed table expression
Alias string // Deprecated: use FromExpr's alias instead
Joins []JoinClause
Where Expr
Limit int
}
SelectStmt represents a SELECT query.
func (SelectStmt) NotExists ¶
func (s SelectStmt) NotExists() string
NotExists wraps a query in NOT EXISTS(...).
type SubjectRef ¶
SubjectRef represents a subject reference (type + id).
func SubjectParams ¶
func SubjectParams() SubjectRef
SubjectParams creates a SubjectRef from the standard function parameters.
type Substring ¶
Substring represents SQL substring(source from start [for length]). If For is nil, renders substring(source from start). If For is provided, renders substring(source from start for length).
type SubstringUsersetRelation ¶
type SubstringUsersetRelation struct {
Source Expr
}
SubstringUsersetRelation extracts the relation portion after the '#' marker. Used when the input contains a userset marker and we need just the relation.
func (SubstringUsersetRelation) SQL ¶
func (s SubstringUsersetRelation) SQL() string
type TableExpr ¶
type TableExpr interface {
// TableSQL returns the SQL for use in FROM/JOIN clauses.
TableSQL() string
// TableAlias returns the alias if any (empty string if none).
TableAlias() string
}
TableExpr is the interface for table expressions in FROM and JOIN clauses. Types that can be used as table sources implement this interface.
func ClosureTable ¶
ClosureTable returns a typed closure VALUES table.
func UsersetTable ¶
UsersetTable returns a typed userset VALUES table.
type TableRef ¶
TableRef wraps a raw table name for use as a TableExpr.
type TupleNotIn ¶ added in v0.7.0
type TupleNotIn struct {
Exprs []Expr // Column expressions (e.g., object_type, relation)
Pairs [][]string // Pairs of literal values to exclude
}
TupleNotIn represents a composite NOT IN clause for multiple columns. Renders (expr1, expr2) NOT IN (('a','b'), ('c','d')).
func (TupleNotIn) SQL ¶ added in v0.7.0
func (t TupleNotIn) SQL() string
type TypedValuesTable ¶
type TypedValuesTable struct {
Rows []ValuesRow // Typed expression rows
Alias string // Table alias
Columns []string // Column names
}
TypedValuesTable represents a VALUES clause with typed expression rows. Unlike ValuesTable which uses a pre-formatted string, TypedValuesTable uses structured ValuesRow elements that render via the Expr DSL.
Example:
TypedValuesTable{
Rows: []ValuesRow{{Lit("doc"), Lit("viewer"), Lit("editor")}},
Alias: "c",
Columns: []string{"object_type", "relation", "satisfying_relation"},
}
Renders: (VALUES ('doc', 'viewer', 'editor')) AS c(object_type, relation, satisfying_relation)
func TypedClosureValuesTable ¶
func TypedClosureValuesTable(rows []ValuesRow, alias string) TypedValuesTable
TypedClosureValuesTable creates a typed closure VALUES table. The table has columns: object_type, relation, satisfying_relation
func TypedUsersetValuesTable ¶
func TypedUsersetValuesTable(rows []ValuesRow, alias string) TypedValuesTable
TypedUsersetValuesTable creates a typed userset VALUES table. The table has columns: object_type, relation, subject_type, subject_relation
func (TypedValuesTable) SQL ¶
func (v TypedValuesTable) SQL() string
SQL renders the typed VALUES table expression.
func (TypedValuesTable) TableAlias ¶
func (v TypedValuesTable) TableAlias() string
TableAlias implements TableExpr.
func (TypedValuesTable) TableSQL ¶
func (v TypedValuesTable) TableSQL() string
TableSQL implements TableExpr.
type UnionAll ¶
type UnionAll struct {
Queries []SQLer
Indent string // Optional indent prefix for each query (default: empty)
}
UnionAll represents multiple queries combined with UNION ALL. Each query is rendered and joined with UNION ALL.
Example:
UnionAll{Queries: []SQLer{query1, query2}}
Renders:
query1 UNION ALL query2
type UsersetNormalized ¶
UsersetNormalized replaces the relation in a userset with a new relation. Example: "group:1#admin" with relation "member" -> "group:1#member"
func (UsersetNormalized) SQL ¶
func (u UsersetNormalized) SQL() string
type UsersetObjectID ¶
type UsersetObjectID struct {
Source Expr
}
UsersetObjectID extracts the object ID: "group:1#member" -> "group:1"
func (UsersetObjectID) SQL ¶
func (u UsersetObjectID) SQL() string
type UsersetRelation ¶
type UsersetRelation struct {
Source Expr
}
UsersetRelation extracts the relation: "group:1#member" -> "member"
func (UsersetRelation) SQL ¶
func (u UsersetRelation) SQL() string
type ValuesRow ¶
type ValuesRow []Expr
ValuesRow represents a single row in a VALUES clause as typed expressions. Each element in the slice corresponds to a column value.
type ValuesTable ¶
type ValuesTable struct {
Values string // The VALUES content (e.g., "('a', 'b'), ('c', 'd')")
Alias string // Table alias (e.g., "c")
Columns []string // Column names (e.g., ["object_type", "relation"])
}
ValuesTable represents a VALUES clause as a table expression. Used to inline data like closure values without database tables.
Example: ValuesTable{Values: "('doc', 'viewer', 'editor')", Alias: "c", Columns: []string{"object_type", "relation", "satisfying_relation"}} Renders: (VALUES ('doc', 'viewer', 'editor')) AS c(object_type, relation, satisfying_relation)
func (ValuesTable) TableAlias ¶
func (v ValuesTable) TableAlias() string
TableAlias implements TableExpr.
type WithCTE ¶
type WithCTE struct {
Recursive bool // If true, renders WITH RECURSIVE
CTEs []CTEDef // One or more CTE definitions
Query SQLer // The final SELECT that uses the CTEs
}
WithCTE represents a WITH clause wrapping a final query. Supports both regular and recursive CTEs.
Example:
WithCTE{
Recursive: true,
CTEs: []CTEDef{{Name: "accessible", Columns: []string{"object_id", "depth"}, Query: cteQuery}},
Query: finalSelect,
}
Renders:
WITH RECURSIVE accessible(object_id, depth) AS (
<cte query>
)
<final query>
func MultiCTE ¶
MultiCTE creates a WITH clause with multiple CTEs. Useful for complex queries with subject_pool, base_results, has_wildcard, etc.
func RecursiveCTE ¶
RecursiveCTE is a convenience constructor for a single recursive CTE.