Documentation
¶
Overview ¶
Package sqlgen generates specialized SQL functions for OpenFGA authorization checks.
Overview ¶
This package is the SQL code generator for Melange, an OpenFGA-to-PostgreSQL compiler. It analyzes OpenFGA authorization models and generates optimized PostgreSQL functions that evaluate permission checks and list operations without recursive graph traversal.
Architecture ¶
The generator operates in three phases:
- Analysis: Parse relation features (direct, implied, userset, TTU, exclusion, intersection)
- Planning: Determine which SQL patterns to use based on feature combinations
- Rendering: Generate PL/pgSQL functions using the SQL DSL
Subpackages ¶
The package is organized into focused subpackages:
- analysis: Relation analysis and feature detection
- sqldsl: Type-safe SQL DSL for building queries
- plpgsql: PL/pgSQL function builders
- tuples: Tuple table query builders
- inline: Inline data generation for closure and userset tables
SQL DSL ¶
The sqldsl subpackage provides a domain-specific DSL for constructing PostgreSQL queries. Rather than building SQL strings directly, code uses typed DSL elements that compose together and render to SQL.
Example - Direct tuple check:
query := Tuples("t").
ObjectType("document").
Relations("viewer").
WhereSubjectType(SubjectType).
WhereSubjectID(SubjectID, true). // true = allow wildcards
Select("1").
Limit(1)
exists := Exists{Query: query.Build()}
sql := exists.SQL() // Renders to PostgreSQL
Generated Functions ¶
For each relation in the schema, the generator produces:
- Specialized check function: check_{type}_{relation}(subject_type, subject_id, object_id)
- No-wildcard variant: check_{type}_{relation}_no_wildcard(...)
- List objects function: list_{type}_{relation}_objects(subject_type, subject_id, limit, cursor)
- List subjects function: list_{type}_{relation}_subjects(object_id, subject_type, limit, cursor)
The generator also produces dispatcher functions (check_permission, list_accessible_objects, list_accessible_subjects) that route requests to the appropriate specialized function based on object type and relation name.
Relation Patterns ¶
The generator handles all OpenFGA relation patterns:
- Direct: [user] - direct tuple lookup
- Implied: viewer: editor - closure-based lookup
- Wildcard: [user:*] - match any subject_id
- Userset: [group#member] - JOIN to expand group membership
- TTU (Tuple-to-userset): viewer from parent - check permission on linked objects
- Exclusion: but not blocked - anti-join or function call to deny access
- Intersection: writer and editor - INTERSECT of multiple checks
Code Generation Flow ¶
The typical flow for generating SQL:
- Call AnalyzeRelations to classify all relations and detect features
- Call ComputeCanGenerate to determine generation eligibility and populate metadata
- Call GenerateSQL to produce all function definitions
- Apply the generated SQL during migration
Implementation Notes ¶
The DSL uses the builder pattern with method chaining for fluent composition. All DSL types implement either Expr (for expressions) or SQLer (for statements). The SQL() method renders the final PostgreSQL syntax.
Cycle detection for recursive patterns uses a visited array passed through check_permission_internal calls. Depth limits prevent unbounded recursion.
For relations with complex patterns (deep TTU chains, exclusions on excluded relations), the generator delegates to check_permission_internal which handles the full authorization semantics including fallback to the generic implementation.
Index ¶
- Constants
- Variables
- func CollectFunctionNames(analyses []RelationAnalysis) []string
- func ListObjectsComplexClosureQuery(input ListObjectsComplexClosureInput) (string, error)
- func ListObjectsCrossTypeTTUQuery(input ListObjectsCrossTypeTTUInput) (string, error)
- func ListObjectsDirectQuery(input ListObjectsDirectInput) (string, error)
- func ListObjectsIntersectionClosureQuery(functionName string) (string, error)
- func ListObjectsIntersectionClosureValidatedQuery(objectType, relation, functionName string) (string, error)
- func ListObjectsRecursiveTTUQuery(input ListObjectsRecursiveTTUInput) (string, error)
- func ListObjectsSelfCandidateQuery(input ListObjectsSelfCandidateInput) (string, error)
- func ListObjectsUsersetPatternComplexQuery(input ListObjectsUsersetPatternComplexInput) (string, error)
- func ListObjectsUsersetPatternSimpleQuery(input ListObjectsUsersetPatternSimpleInput) (string, error)
- func ListObjectsUsersetSubjectQuery(input ListObjectsUsersetSubjectInput) (string, error)
- func ListSubjectsComplexClosureQuery(input ListSubjectsComplexClosureInput) (string, error)
- func ListSubjectsDirectQuery(input ListSubjectsDirectInput) (string, error)
- func ListSubjectsIntersectionClosureQuery(functionName string, subjectTypeExpr Expr) (string, error)
- func ListSubjectsIntersectionClosureValidatedQuery(objectType, relation, functionName string, ...) (string, error)
- func ListSubjectsSelfCandidateQuery(input ListSubjectsSelfCandidateInput) (string, error)
- func ListSubjectsUsersetFilterQuery(input ListSubjectsUsersetFilterInput) (string, error)
- func ListSubjectsUsersetPatternComplexQuery(input ListSubjectsUsersetPatternComplexInput) (string, error)
- func ListSubjectsUsersetPatternRecursiveComplexQuery(input ListSubjectsUsersetPatternRecursiveComplexInput) (string, error)
- func ListSubjectsUsersetPatternSimpleQuery(input ListSubjectsUsersetPatternSimpleInput) (string, error)
- func RenderCheckFunction(plan CheckPlan, blocks CheckBlocks) (string, error)
- func RenderListObjectsComposedFunction(plan ListPlan, blocks ComposedObjectsBlockSet) (string, error)
- func RenderListObjectsDepthExceededFunction(plan ListPlan) string
- func RenderListObjectsFunction(plan ListPlan, blocks BlockSet) (string, error)
- func RenderListObjectsRecursiveFunction(plan ListPlan, blocks RecursiveBlockSet) (string, error)
- func RenderListObjectsSelfRefUsersetFunction(plan ListPlan, blocks SelfRefUsersetBlockSet) (string, error)
- func RenderListSubjectsComposedFunction(plan ListPlan, blocks ComposedSubjectsBlockSet) (string, error)
- func RenderListSubjectsDepthExceededFunction(plan ListPlan) string
- func RenderListSubjectsFunction(plan ListPlan, blocks BlockSet) (string, error)
- func RenderListSubjectsIntersectionFunction(plan ListPlan, blocks SubjectsIntersectionBlockSet) (string, error)
- func RenderListSubjectsRecursiveFunction(plan ListPlan, blocks SubjectsRecursiveBlockSet) (string, error)
- func RenderListSubjectsSelfRefUsersetFunction(plan ListPlan, blocks SelfRefUsersetSubjectsBlockSet) (string, error)
- type Add
- type Alias
- type AnchorPathStep
- type AndExpr
- type ArrayAppend
- type ArrayContains
- type ArrayLength
- type ArrayLiteral
- type Assign
- type BlockSet
- type Bool
- type CTEDef
- type CaseExpr
- type CaseWhen
- type CheckBlocks
- type CheckPermission
- type CheckPermissionCall
- type CheckPlan
- type ClosureRow
- type Col
- type Comment
- type CommentedSQL
- type ComposedObjectsBlockSet
- type ComposedSubjectsBlockSet
- type Concat
- type Decl
- type DispatcherCase
- type DispatcherData
- type EmptyArray
- type Eq
- type ExcludedIntersectionGroup
- type ExcludedIntersectionPart
- type ExcludedParentRelation
- type ExclusionConfig
- type Exists
- type Expr
- func CheckPermissionExpr(functionName string, subject SubjectRef, relation string, object ObjectRef, ...) Expr
- func CheckPermissionInternalExpr(subject SubjectRef, relation string, object ObjectRef, expect bool) Expr
- func SimpleExclusion(objectType, relation string, objectID, subjectType, subjectID Expr) Expr
- type Func
- type FuncArg
- type FuncCallEq
- type FuncCallNe
- type FunctionCallExpr
- type GeneratedSQL
- type GenerationCapabilities
- type Gt
- type Gte
- type HasUserset
- type If
- type ImpliedFunctionCheck
- type In
- type InFunctionSelect
- type IndirectAnchorInfo
- type InlineSQLData
- type Int
- type IntersectSubquery
- type IntersectionGroup
- type IntersectionGroupCheck
- type IntersectionGroupInfo
- type IntersectionPart
- type IntersectionPartCheck
- type IsNotNull
- type IsNull
- type IsWildcard
- type JoinClause
- type LateralFunction
- type Like
- type ListAnchorPathStepData
- type ListDispatcherCase
- type ListDispatcherData
- type ListGeneratedSQL
- type ListIndirectAnchorData
- type ListObjectsComplexClosureInput
- type ListObjectsCrossTypeTTUInput
- type ListObjectsDirectInput
- type ListObjectsRecursiveTTUInput
- type ListObjectsSelfCandidateInput
- type ListObjectsUsersetPatternComplexInput
- type ListObjectsUsersetPatternSimpleInput
- type ListObjectsUsersetSubjectInput
- type ListParentRelationData
- type ListPlan
- func BuildListObjectsPlan(a RelationAnalysis, inline InlineSQLData) ListPlan
- func BuildListObjectsPlanWithLookup(a RelationAnalysis, inline InlineSQLData, lookup map[string]*RelationAnalysis) ListPlan
- func BuildListSubjectsPlan(a RelationAnalysis, inline InlineSQLData) ListPlan
- func BuildListSubjectsPlanWithLookup(a RelationAnalysis, inline InlineSQLData, lookup map[string]*RelationAnalysis) ListPlan
- type ListStrategy
- type ListSubjectsComplexClosureInput
- type ListSubjectsDirectInput
- type ListSubjectsSelfCandidateInput
- type ListSubjectsUsersetFilterInput
- type ListSubjectsUsersetPatternComplexInput
- type ListSubjectsUsersetPatternRecursiveComplexInput
- type ListSubjectsUsersetPatternSimpleInput
- type ListUsersetPatternData
- 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 ParentRelationBlock
- type ParentRelationCheck
- type ParentRelationInfo
- type PlpgsqlFunction
- type Position
- type QueryBlock
- type Raise
- type Raw
- type RawStmt
- type RecursiveBlockSet
- type RelationAnalysis
- type RelationDefinition
- type RelationFeatures
- type Return
- type ReturnInt
- type ReturnQuery
- type ReturnValue
- type SQLer
- type SelectInto
- type SelectIntoVar
- type SelectStmt
- type SelfRefUsersetBlockSet
- type SelfRefUsersetSubjectsBlockSet
- type SqlFunction
- type Stmt
- type Sub
- type SubjectRef
- type SubjectTypeRef
- type SubjectsIntersectionBlockSet
- type SubjectsRecursiveBlockSet
- type Substring
- type SubstringUsersetRelation
- type TableExpr
- type TableRef
- type TupleQuery
- type TypeDefinition
- type TypedQueryBlock
- type TypedValuesTable
- type UnionAll
- type UsersetNormalized
- type UsersetObjectID
- type UsersetPattern
- type UsersetRelation
- type ValuesRow
- type ValuesTable
- type WithCTE
Constants ¶
const ( ListStrategyDirect = analysis.ListStrategyDirect ListStrategyUserset = analysis.ListStrategyUserset ListStrategyRecursive = analysis.ListStrategyRecursive ListStrategyIntersection = analysis.ListStrategyIntersection ListStrategyDepthExceeded = analysis.ListStrategyDepthExceeded ListStrategySelfRefUserset = analysis.ListStrategySelfRefUserset ListStrategyComposed = analysis.ListStrategyComposed )
Variables ¶
var ( SubjectType = sqldsl.SubjectType SubjectID = sqldsl.SubjectID ObjectType = sqldsl.ObjectType ObjectID = sqldsl.ObjectID Visited = sqldsl.Visited ParamRef = sqldsl.ParamRef LitText = sqldsl.LitText And = sqldsl.And Or = sqldsl.Or Not = sqldsl.Not ExistsExpr = sqldsl.ExistsExpr TableAs = sqldsl.TableAs TypedClosureValuesTable = sqldsl.TypedClosureValuesTable TypedUsersetValuesTable = sqldsl.TypedUsersetValuesTable ClosureTable = sqldsl.ClosureTable UsersetTable = sqldsl.UsersetTable Ident = sqldsl.Ident RenderBlocks = sqldsl.RenderBlocks RenderUnionBlocks = sqldsl.RenderUnionBlocks IndentLines = sqldsl.IndentLines WrapWithPagination = sqldsl.WrapWithPagination WrapWithPaginationWildcardFirst = sqldsl.WrapWithPaginationWildcardFirst SubjectIDMatch = sqldsl.SubjectIDMatch NormalizedUsersetSubject = sqldsl.NormalizedUsersetSubject SelectAs = sqldsl.SelectAs SubjectParams = sqldsl.SubjectParams LiteralObject = sqldsl.LiteralObject Sqlf = sqldsl.Sqlf Optf = sqldsl.Optf InternalPermissionCheckCall = sqldsl.InternalPermissionCheckCall NoWildcardPermissionCheckCall = sqldsl.NoWildcardPermissionCheckCall SpecializedCheckCall = sqldsl.SpecializedCheckCall InternalCheckCall = sqldsl.InternalCheckCall VisitedKey = sqldsl.VisitedKey VisitedWithKey = sqldsl.VisitedWithKey ListObjectsFunctionName = sqldsl.ListObjectsFunctionName ListSubjectsFunctionName = sqldsl.ListSubjectsFunctionName RecursiveCTE = sqldsl.RecursiveCTE SimpleCTE = sqldsl.SimpleCTE MultiCTE = sqldsl.MultiCTE MultiLineComment = sqldsl.MultiLineComment )
var ( ComputeRelationClosure = analysis.ComputeRelationClosure AnalyzeRelations = analysis.AnalyzeRelations ComputeCanGenerate = analysis.ComputeCanGenerate DetermineListStrategy = analysis.DetermineListStrategy BuildAnalysisLookup = analysis.BuildAnalysisLookup )
var ( ListObjectsArgs = plpgsql.ListObjectsArgs ListSubjectsArgs = plpgsql.ListSubjectsArgs ListObjectsReturns = plpgsql.ListObjectsReturns ListSubjectsReturns = plpgsql.ListSubjectsReturns ListObjectsFunctionHeader = plpgsql.ListObjectsFunctionHeader ListSubjectsFunctionHeader = plpgsql.ListSubjectsFunctionHeader ListObjectsDispatcherArgs = plpgsql.ListObjectsDispatcherArgs ListSubjectsDispatcherArgs = plpgsql.ListSubjectsDispatcherArgs )
var ( BuildInlineSQLData = inline.BuildInlineSQLData BuildClosureTypedRows = inline.BuildClosureTypedRows BuildUsersetTypedRows = inline.BuildUsersetTypedRows )
var Tuples = tuples.Tuples
Functions ¶
func CollectFunctionNames ¶
func CollectFunctionNames(analyses []RelationAnalysis) []string
CollectFunctionNames returns all function names that will be generated for the given analyses. This is used for migration tracking and orphan detection to identify stale functions that need to be dropped when the schema changes.
The returned list includes:
- Specialized check functions: check_{type}_{relation}
- No-wildcard check variants: check_{type}_{relation}_no_wildcard
- Specialized list functions: list_{type}_{relation}_objects, list_{type}_{relation}_subjects
- Dispatcher functions (always included): check_permission, list_accessible_objects, etc.
func ListObjectsComplexClosureQuery ¶
func ListObjectsComplexClosureQuery(input ListObjectsComplexClosureInput) (string, error)
func ListObjectsCrossTypeTTUQuery ¶
func ListObjectsCrossTypeTTUQuery(input ListObjectsCrossTypeTTUInput) (string, error)
func ListObjectsDirectQuery ¶
func ListObjectsDirectQuery(input ListObjectsDirectInput) (string, error)
func ListObjectsRecursiveTTUQuery ¶
func ListObjectsRecursiveTTUQuery(input ListObjectsRecursiveTTUInput) (string, error)
func ListObjectsSelfCandidateQuery ¶
func ListObjectsSelfCandidateQuery(input ListObjectsSelfCandidateInput) (string, error)
func ListObjectsUsersetPatternComplexQuery ¶
func ListObjectsUsersetPatternComplexQuery(input ListObjectsUsersetPatternComplexInput) (string, error)
func ListObjectsUsersetPatternSimpleQuery ¶
func ListObjectsUsersetPatternSimpleQuery(input ListObjectsUsersetPatternSimpleInput) (string, error)
func ListObjectsUsersetSubjectQuery ¶
func ListObjectsUsersetSubjectQuery(input ListObjectsUsersetSubjectInput) (string, error)
func ListSubjectsComplexClosureQuery ¶
func ListSubjectsComplexClosureQuery(input ListSubjectsComplexClosureInput) (string, error)
func ListSubjectsDirectQuery ¶
func ListSubjectsDirectQuery(input ListSubjectsDirectInput) (string, error)
func ListSubjectsSelfCandidateQuery ¶
func ListSubjectsSelfCandidateQuery(input ListSubjectsSelfCandidateInput) (string, error)
func ListSubjectsUsersetFilterQuery ¶
func ListSubjectsUsersetFilterQuery(input ListSubjectsUsersetFilterInput) (string, error)
func ListSubjectsUsersetPatternComplexQuery ¶
func ListSubjectsUsersetPatternComplexQuery(input ListSubjectsUsersetPatternComplexInput) (string, error)
func ListSubjectsUsersetPatternRecursiveComplexQuery ¶
func ListSubjectsUsersetPatternRecursiveComplexQuery(input ListSubjectsUsersetPatternRecursiveComplexInput) (string, error)
func ListSubjectsUsersetPatternSimpleQuery ¶
func ListSubjectsUsersetPatternSimpleQuery(input ListSubjectsUsersetPatternSimpleInput) (string, error)
func RenderCheckFunction ¶ added in v0.5.0
func RenderCheckFunction(plan CheckPlan, blocks CheckBlocks) (string, error)
func RenderListObjectsComposedFunction ¶ added in v0.5.0
func RenderListObjectsComposedFunction(plan ListPlan, blocks ComposedObjectsBlockSet) (string, error)
============================================================================= Composed Strategy Render Functions (List Objects) ============================================================================= RenderListObjectsComposedFunction renders a list_objects function for composed access. Composed functions handle indirect anchor patterns (TTU and userset composition).
func RenderListObjectsDepthExceededFunction ¶ added in v0.5.0
RenderListObjectsDepthExceededFunction renders a list_objects function for a relation that exceeds the userset depth limit. The generated function raises M2002 immediately.
func RenderListObjectsFunction ¶ added in v0.5.0
RenderListObjectsFunction renders a complete list_objects function from plan and blocks.
func RenderListObjectsRecursiveFunction ¶ added in v0.5.0
func RenderListObjectsRecursiveFunction(plan ListPlan, blocks RecursiveBlockSet) (string, error)
RenderListObjectsRecursiveFunction renders a recursive list_objects function from plan and blocks. This handles TTU patterns with depth tracking and recursive CTEs.
func RenderListObjectsSelfRefUsersetFunction ¶ added in v0.5.0
func RenderListObjectsSelfRefUsersetFunction(plan ListPlan, blocks SelfRefUsersetBlockSet) (string, error)
RenderListObjectsSelfRefUsersetFunction renders a list_objects function for self-referential userset patterns.
func RenderListSubjectsComposedFunction ¶ added in v0.5.0
func RenderListSubjectsComposedFunction(plan ListPlan, blocks ComposedSubjectsBlockSet) (string, error)
RenderListSubjectsComposedFunction renders a list_subjects function for composed access.
func RenderListSubjectsDepthExceededFunction ¶ added in v0.5.0
RenderListSubjectsDepthExceededFunction renders a list_subjects function for a relation that exceeds the userset depth limit. The generated function raises M2002 immediately.
func RenderListSubjectsFunction ¶ added in v0.5.0
RenderListSubjectsFunction renders a complete list_subjects function from plan and blocks.
func RenderListSubjectsIntersectionFunction ¶ added in v0.5.0
func RenderListSubjectsIntersectionFunction(plan ListPlan, blocks SubjectsIntersectionBlockSet) (string, error)
============================================================================= Intersection List Subjects Render Functions ============================================================================= RenderListSubjectsIntersectionFunction renders an intersection list_subjects function from plan and blocks. Intersection gathers candidates then filters with check_permission at the end.
func RenderListSubjectsRecursiveFunction ¶ added in v0.5.0
func RenderListSubjectsRecursiveFunction(plan ListPlan, blocks SubjectsRecursiveBlockSet) (string, error)
============================================================================= Recursive List Subjects Render Functions ============================================================================= RenderListSubjectsRecursiveFunction renders a recursive list_subjects function from plan and blocks. This handles TTU patterns with subject_pool CTE and check_permission_internal calls.
func RenderListSubjectsSelfRefUsersetFunction ¶ added in v0.5.0
func RenderListSubjectsSelfRefUsersetFunction(plan ListPlan, blocks SelfRefUsersetSubjectsBlockSet) (string, error)
============================================================================= Self-Referential Userset Render Functions (List Subjects) =============================================================================
Types ¶
type BlockSet ¶ added in v0.5.0
type BlockSet struct {
Primary []TypedQueryBlock
Secondary []TypedQueryBlock
SecondarySelf *TypedQueryBlock
}
BlockSet contains query blocks for a list function.
func BuildListObjectsBlocks ¶ added in v0.5.0
BuildListObjectsBlocks builds all query blocks for a list_objects function. Returns a BlockSet with Primary blocks for the main query path.
func BuildListSubjectsBlocks ¶ added in v0.5.0
BuildListSubjectsBlocks builds all query blocks for a list_subjects function. Returns a BlockSet with Primary and optionally Secondary blocks.
type CheckBlocks ¶ added in v0.5.0
type CheckBlocks struct {
DirectCheck Expr // EXISTS check for direct/implied tuple lookup
UsersetCheck Expr // EXISTS check for userset membership
ExclusionCheck Expr // EXISTS check for exclusion (denial)
UsersetSubjectSelfCheck SelectStmt // Validates when subject IS a userset
// UsersetSubjectComputedCheck validates userset subject via tuple join
UsersetSubjectComputedCheck SelectStmt
ParentRelationBlocks []ParentRelationBlock // TTU pattern checks
ImpliedFunctionCalls []ImpliedFunctionCheck // Complex implied relation checks
IntersectionGroups []IntersectionGroupCheck // AND groups for intersection patterns
HasStandaloneAccess bool // Access paths outside intersections exist
}
CheckBlocks contains all the DSL blocks needed to generate a check function.
func BuildCheckBlocks ¶ added in v0.5.0
func BuildCheckBlocks(plan CheckPlan) (CheckBlocks, error)
BuildCheckBlocks builds all DSL blocks for a check function.
type CheckPermission ¶
type CheckPermission struct {
Subject SubjectRef
Relation string
Object ObjectRef
Visited Expr // nil uses empty array
ExpectAllow bool // true compares "= 1", false compares "= 0"
}
CheckPermission represents a call to check_permission_internal.
func CheckAccess ¶
func CheckAccess(relation, objectType string, objectID Expr) CheckPermission
CheckAccess creates a CheckPermission that expects access to be allowed.
func CheckNoAccess ¶
func CheckNoAccess(relation, objectType string, objectID Expr) CheckPermission
CheckNoAccess creates a CheckPermission that expects access to be denied.
func (CheckPermission) SQL ¶
func (c CheckPermission) SQL() string
type CheckPermissionCall ¶
type CheckPermissionCall struct {
FunctionName string
Subject SubjectRef
Relation string
Object ObjectRef
ExpectAllow bool
}
CheckPermissionCall represents a call to a specialized permission check function.
func (CheckPermissionCall) SQL ¶
func (c CheckPermissionCall) SQL() string
type CheckPlan ¶ added in v0.5.0
type CheckPlan struct {
// Input data
Analysis RelationAnalysis
Inline InlineSQLData
// Function identity
FunctionName string
InternalCheckFunctionName string // Dispatcher function for recursive calls
ObjectType string
Relation string
FeaturesString string // Human-readable features for SQL comments
// Feature configuration
AllowWildcard bool // Whether wildcards are allowed
NoWildcard bool // True if this is a no-wildcard variant
Exclusions ExclusionConfig // Exclusion rules configuration
// Feature flags (derived from analysis)
HasDirect bool
HasImplied bool
HasUserset bool
HasExclusion bool
HasIntersection bool
HasRecursive bool
// Derived computation flags
HasStandaloneAccess bool // Has access paths outside of intersections
HasComplexUsersets bool // Has userset patterns requiring function calls
NeedsPLpgSQL bool // Requires PL/pgSQL (not pure SQL)
HasParentRelations bool // Has TTU patterns
HasImpliedFunctionCall bool // Has complex implied relations needing function calls
// Eligibility from unified analysis
Capabilities GenerationCapabilities
// Relation lists for closure lookups
RelationList []string // Relations for tuple lookup (self + simple closure)
ComplexClosure []string // Complex closure relations
AllowedSubjectTypes []string // Subject types allowed for this relation
}
CheckPlan contains all computed data needed to generate a check function. This separates plan computation from block building and rendering. Unlike CheckFunctionData, this contains no pre-rendered SQL fragments.
func BuildCheckPlan ¶ added in v0.5.0
func BuildCheckPlan(a RelationAnalysis, inline InlineSQLData, noWildcard bool) CheckPlan
BuildCheckPlan creates a plan for generating a check function. Set noWildcard to true to generate a no-wildcard variant.
func (CheckPlan) DetermineCheckFunctionType ¶ added in v0.5.0
DetermineCheckFunctionType returns which type of check function to generate. Returns one of: "direct", "intersection", "recursive", "recursive_intersection"
type ComposedObjectsBlockSet ¶ added in v0.5.0
type ComposedObjectsBlockSet struct {
// SelfBlock is the self-candidate check block
SelfBlock *TypedQueryBlock
// MainBlocks are the composed query blocks (TTU and/or userset paths)
MainBlocks []TypedQueryBlock
// AllowedSubjectTypes for the type guard
AllowedSubjectTypes []string
// Anchor metadata for comments
AnchorType string
AnchorRelation string
FirstStepType string
}
ComposedObjectsBlockSet contains blocks for a composed list_objects function. Composed functions handle indirect anchor patterns (TTU and userset composition).
func BuildListObjectsComposedBlocks ¶ added in v0.5.0
func BuildListObjectsComposedBlocks(plan ListPlan) (ComposedObjectsBlockSet, error)
BuildListObjectsComposedBlocks builds block set for composed list_objects function.
type ComposedSubjectsBlockSet ¶ added in v0.5.0
type ComposedSubjectsBlockSet struct {
// SelfBlock is the self-candidate check block (for userset filter)
SelfBlock *TypedQueryBlock
// UsersetFilterBlocks are candidate blocks for userset filter path
UsersetFilterBlocks []TypedQueryBlock
// RegularBlocks are candidate blocks for regular path
RegularBlocks []TypedQueryBlock
// AllowedSubjectTypes for the type guard
AllowedSubjectTypes []string
// HasExclusions indicates if exclusion predicates are needed
HasExclusions bool
// Anchor metadata for comments
AnchorType string
AnchorRelation string
FirstStepType string
}
ComposedSubjectsBlockSet contains blocks for a composed list_subjects function.
func BuildListSubjectsComposedBlocks ¶ added in v0.5.0
func BuildListSubjectsComposedBlocks(plan ListPlan) (ComposedSubjectsBlockSet, error)
BuildListSubjectsComposedBlocks builds block set for composed list_subjects function.
type DispatcherCase ¶
DispatcherCase represents a single CASE WHEN branch in the dispatcher. Each case routes a specific (object_type, relation) pair to its specialized function.
type DispatcherData ¶
type DispatcherData struct {
FunctionName string
HasSpecializedFunctions bool
Cases []DispatcherCase
}
DispatcherData contains data for rendering the dispatcher template.
type ExcludedIntersectionGroup ¶
type ExcludedIntersectionGroup struct {
Parts []ExcludedIntersectionPart
}
ExcludedIntersectionGroup represents a complete intersection exclusion like "but not (A and B)". Access is denied if ALL parts in the group are satisfied.
type ExcludedIntersectionPart ¶
type ExcludedIntersectionPart struct {
Relation string // The relation to check
ExcludedRelation string // Optional nested exclusion (e.g., "editor but not owner")
ParentRelation *ExcludedParentRelation // Optional TTU pattern in the intersection
}
ExcludedIntersectionPart represents one part of an intersection exclusion. For "but not (editor and owner)", there would be two parts: one for editor, one for owner.
type ExcludedParentRelation ¶
type ExcludedParentRelation struct {
Relation string // The relation to check on the parent (e.g., "viewer")
LinkingRelation string // The relation linking to the parent (e.g., "parent")
AllowedLinkingTypes []string // Object types the linking relation can point to
}
ExcludedParentRelation represents a TTU exclusion pattern like "but not viewer from parent". The exclusion is satisfied when a tuple exists linking the object to a parent object that grants the excluded relation.
type ExclusionConfig ¶
type ExclusionConfig struct {
ObjectType string // The object type being checked
ObjectIDExpr Expr // Expression for the object ID (typically a column or parameter)
SubjectTypeExpr Expr // Expression for the subject type
SubjectIDExpr Expr // Expression for the subject ID
// SimpleExcludedRelations can use direct tuple lookups (NOT EXISTS).
SimpleExcludedRelations []string
// ComplexExcludedRelations need check_permission_internal calls.
ComplexExcludedRelations []string
// ExcludedParentRelations represent TTU exclusions (e.g., "but not viewer from parent").
ExcludedParentRelations []ExcludedParentRelation
// ExcludedIntersection represents intersection exclusions (e.g., "but not (A and B)").
ExcludedIntersection []ExcludedIntersectionGroup
}
ExclusionConfig holds all exclusion rules for a query. It classifies exclusions by complexity and generates appropriate SQL predicates.
func (ExclusionConfig) BuildExclusionCTE ¶ added in v0.6.0
func (c ExclusionConfig) BuildExclusionCTE() string
BuildExclusionCTE builds a CTE that materializes all excluded subjects. Used for CTE-based exclusion optimization to precompute exclusions once instead of checking via NOT EXISTS for each result row.
Returns a SELECT statement producing a single column: subject_id
Example for "but not restricted" where restricted: [user]:
SELECT subject_id FROM melange_tuples
WHERE object_type = 'document'
AND relation IN ('restricted')
AND object_id = p_object_id
Result is used in anti-join pattern:
LEFT JOIN excluded_subjects ON excluded_subjects.subject_id = candidate.subject_id
OR excluded_subjects.subject_id = '*'
WHERE excluded_subjects.subject_id IS NULL
func (ExclusionConfig) BuildPredicates ¶
func (c ExclusionConfig) BuildPredicates() []Expr
BuildPredicates converts exclusion rules into SQL predicates.
Simple exclusions become NOT EXISTS subqueries checking for direct tuples. Complex exclusions become check_permission_internal(...) = 0 calls. TTU exclusions check for linking tuples where the parent grants the excluded relation. Intersection exclusions become NOT (part1 AND part2 AND ...) expressions.
All predicates are returned as a slice that should be ANDed into the WHERE clause.
func (ExclusionConfig) CanUseCTEOptimization ¶ added in v0.6.0
func (c ExclusionConfig) CanUseCTEOptimization() bool
CanUseCTEOptimization returns true if exclusions can use CTE-based optimization.
Eligible when:
- Has simple exclusions (direct tuple lookups)
- No complex exclusions (require check_permission calls)
- No TTU exclusions (require parent traversal)
- No intersection exclusions (require AND logic)
The optimization materializes excluded subjects once in a CTE, then uses a single LEFT JOIN...WHERE IS NULL instead of repeated NOT EXISTS predicates.
func (ExclusionConfig) HasExclusions ¶
func (c ExclusionConfig) HasExclusions() bool
HasExclusions returns true if any exclusion rules are configured.
type Expr ¶
Expressions
func CheckPermissionExpr ¶ added in v0.5.0
func CheckPermissionExpr(functionName string, subject SubjectRef, relation string, object ObjectRef, expect bool) Expr
CheckPermissionExpr returns a typed expression for a check_permission call.
func CheckPermissionInternalExpr ¶ added in v0.5.0
func CheckPermissionInternalExpr(subject SubjectRef, relation string, object ObjectRef, expect bool) Expr
CheckPermissionInternalExpr returns a typed expression for check_permission_internal.
func SimpleExclusion ¶
SimpleExclusion creates a NOT EXISTS exclusion for a simple "but not" rule. This checks for the absence of a tuple granting the excluded relation to the subject. Wildcards are handled: if a wildcard tuple exists for the excluded relation, access is denied.
type FunctionCallExpr ¶ added in v0.5.0
type FunctionCallExpr = sqldsl.FunctionCallExpr
sqldsl types
type GeneratedSQL ¶
type GeneratedSQL struct {
// Functions contains CREATE OR REPLACE FUNCTION statements
// for each specialized check function (check_{type}_{relation}).
Functions []string
// NoWildcardFunctions contains CREATE OR REPLACE FUNCTION statements
// for no-wildcard variants (check_{type}_{relation}_no_wildcard).
// These skip wildcard matching for performance-critical paths.
NoWildcardFunctions []string
// Dispatcher contains the check_permission dispatcher function
// that routes requests to specialized functions based on object type and relation.
Dispatcher string
// DispatcherNoWildcard contains the check_permission_no_wildcard dispatcher.
DispatcherNoWildcard string
}
GeneratedSQL contains all SQL generated for a schema. This is applied atomically during migration to ensure consistent state.
func GenerateSQL ¶
func GenerateSQL(analyses []RelationAnalysis, inline InlineSQLData) (GeneratedSQL, error)
GenerateSQL generates specialized SQL functions for all relations in the schema.
For each relation, it generates:
- A specialized check function that evaluates permission checks efficiently
- A no-wildcard variant for scenarios where wildcards are disallowed
- Dispatcher functions that route to the appropriate specialized function
The inline parameter provides precomputed closure and userset data that is inlined into the generated functions as VALUES clauses, eliminating runtime table joins for this metadata.
Returns an error if any function fails to generate, though this is rare as the analysis phase validates generation feasibility.
type GenerationCapabilities ¶ added in v0.5.0
type GenerationCapabilities = analysis.GenerationCapabilities
analysis types
type ImpliedFunctionCheck ¶ added in v0.5.0
ImpliedFunctionCheck represents a check that calls another check function.
type InFunctionSelect ¶ added in v0.5.0
type InFunctionSelect = sqldsl.InFunctionSelect
sqldsl types
type IntersectSubquery ¶ added in v0.5.0
type IntersectSubquery = sqldsl.IntersectSubquery
sqldsl types
type IntersectionGroupCheck ¶ added in v0.5.0
type IntersectionGroupCheck struct {
Parts []IntersectionPartCheck
}
IntersectionGroupCheck represents an AND group where all checks must pass.
type IntersectionGroupInfo ¶
type IntersectionGroupInfo = analysis.IntersectionGroupInfo
analysis types
type IntersectionPartCheck ¶ added in v0.5.0
type IntersectionPartCheck struct {
Relation string
ExcludedRelation string
IsParent bool
ParentRelation string
LinkingRelation string
Check Expr
}
IntersectionPartCheck represents one part of an intersection check.
type ListAnchorPathStepData ¶
type ListAnchorPathStepData struct {
Type string // "ttu" or "userset"
// For TTU steps (e.g., "viewer from parent"):
LinkingRelation string // "parent"
TargetType string // "folder" (first type with direct anchor)
TargetRelation string // "viewer"
AllTargetTypes []string // All types with direct anchor (e.g., ["document", "folder"])
RecursiveTypes []string // Types needing check_permission_internal (same-type recursive TTU)
// For userset steps (e.g., [group#member]):
SubjectType string // "group"
SubjectRelation string // "member"
SatisfyingRelationsList string // SQL-formatted satisfying relations
HasWildcard bool // Whether membership allows wildcards
}
ListAnchorPathStepData contains data for rendering one step in an indirect anchor path.
type ListDispatcherCase ¶
ListDispatcherCase represents a single routing case in the list dispatcher.
type ListDispatcherData ¶
type ListDispatcherData struct {
// HasSpecializedFunctions is true if any specialized list functions were generated.
HasSpecializedFunctions bool
// Cases contains the routing cases for specialized functions.
Cases []ListDispatcherCase
}
ListDispatcherData contains data for rendering list dispatcher templates.
type ListGeneratedSQL ¶
type ListGeneratedSQL struct {
// ListObjectsFunctions contains CREATE OR REPLACE FUNCTION statements
// for each specialized list_objects function (list_{type}_{relation}_objects).
ListObjectsFunctions []string
// ListSubjectsFunctions contains CREATE OR REPLACE FUNCTION statements
// for each specialized list_subjects function (list_{type}_{relation}_subjects).
ListSubjectsFunctions []string
// ListObjectsDispatcher contains the list_accessible_objects dispatcher function
// that routes to specialized functions or falls back to generic.
ListObjectsDispatcher string
// ListSubjectsDispatcher contains the list_accessible_subjects dispatcher function
// that routes to specialized functions or falls back to generic.
ListSubjectsDispatcher string
}
ListGeneratedSQL contains all SQL generated for list functions. This is separate from check function generation to keep concerns isolated. Applied atomically during migration alongside check functions.
func GenerateListSQL ¶
func GenerateListSQL(analyses []RelationAnalysis, inline InlineSQLData) (ListGeneratedSQL, error)
GenerateListSQL generates specialized SQL functions for list operations. The generated SQL includes:
- Per-relation list_objects functions (list_{type}_{relation}_objects)
- Per-relation list_subjects functions (list_{type}_{relation}_subjects)
- Dispatchers that route to specialized functions or fall back to generic
During the migration phase, relations that cannot be generated will use the generic list functions as fallback. As more patterns are supported, the CanGenerateList criteria will be relaxed.
type ListIndirectAnchorData ¶
type ListIndirectAnchorData struct {
// Path steps from this relation to the anchor
Path []ListAnchorPathStepData
// First step's target function (used for composition)
// For multi-hop chains, we compose with the first step's target, not the anchor.
// e.g., for job.can_read -> permission.assignee -> role.assignee, we call
// list_permission_assignee_objects (first step's target), not list_role_assignee_objects (anchor).
FirstStepTargetFunctionName string // e.g., "list_permission_assignee_objects"
// Anchor relation info (end of the chain)
AnchorType string // Type of anchor relation (e.g., "folder")
AnchorRelation string // Anchor relation name (e.g., "viewer")
AnchorFunctionName string // Name of anchor's list function (e.g., "list_folder_viewer_objects")
AnchorSubjectTypes string // SQL-formatted allowed subject types from anchor
AnchorHasWildcard bool // Whether anchor supports wildcards
SatisfyingRelationsList string // SQL-formatted list of relations that satisfy the anchor
}
ListIndirectAnchorData contains data for rendering composed access patterns in list templates. This is used when a relation has no direct/implied access but can reach subjects through TTU or userset patterns to an anchor relation that has direct grants.
type ListObjectsComplexClosureInput ¶
type ListObjectsComplexClosureInput struct {
ObjectType string
Relation string
AllowedSubjectTypes []string
AllowWildcard bool
Exclusions ExclusionConfig
}
type ListObjectsCrossTypeTTUInput ¶
type ListObjectsCrossTypeTTUInput struct {
ObjectType string
LinkingRelation string
Relation string
CrossTypes []string
Exclusions ExclusionConfig
}
type ListObjectsDirectInput ¶
type ListObjectsDirectInput struct {
ObjectType string
Relations []string
AllowedSubjectTypes []string
AllowWildcard bool
Exclusions ExclusionConfig
}
type ListObjectsRecursiveTTUInput ¶
type ListObjectsRecursiveTTUInput struct {
ObjectType string
LinkingRelations []string
Exclusions ExclusionConfig
}
type ListObjectsUsersetSubjectInput ¶
type ListObjectsUsersetSubjectInput struct {
ObjectType string
Relations []string
ClosureValues string // Deprecated: use ClosureRows
ClosureRows []ValuesRow // Typed closure rows (preferred)
Exclusions ExclusionConfig
}
type ListParentRelationData ¶
type ListParentRelationData struct {
Relation string // Relation to check on parent (e.g., "viewer")
LinkingRelation string // Relation that links to parent (e.g., "parent")
AllowedLinkingTypes string // SQL-formatted list of parent types (e.g., "'folder', 'org'")
ParentType string // First allowed linking type (for self-referential check)
IsSelfReferential bool // True if any parent type equals the object type
// AllowedLinkingTypesSlice contains the same types as AllowedLinkingTypes but as a slice.
// Used for typed DSL expressions (In{Expr: ..., Values: AllowedLinkingTypesSlice}).
AllowedLinkingTypesSlice []string
// CrossTypeLinkingTypes is a SQL-formatted list of linking types that are NOT self-referential.
// When a parent relation allows both self-referential and cross-type links (e.g., [folder, document]
// for document.parent), this contains only the cross-type entries (e.g., "'folder'").
// Used to generate check_permission_internal calls for cross-type parents even when
// IsSelfReferential is true for the same linking relation.
CrossTypeLinkingTypes string
HasCrossTypeLinks bool // True if CrossTypeLinkingTypes is non-empty
// IsClosurePattern indicates this TTU pattern was inherited from an implied relation.
// For example, if `can_read: reader` and `reader: repo_admin from owner but not restricted`,
// then can_read's TTU "owner -> repo_admin" is a closure pattern with SourceRelation="reader".
// Closure patterns must verify through the source relation to honor its exclusions/intersections.
IsClosurePattern bool
SourceRelation string // The relation this TTU was inherited from (for closure patterns)
}
ListParentRelationData contains data for rendering TTU pattern expansion in list templates. For a pattern like "viewer from parent", this represents the parent traversal.
type ListPlan ¶ added in v0.5.0
type ListPlan struct {
// Input data
Analysis RelationAnalysis
Inline InlineSQLData
// Function identity
FunctionName string
ObjectType string
Relation string
// Computed relation lists
RelationList []string // Relations for tuple lookup (self + simple closure)
AllSatisfyingRelations []string // All relations that satisfy this one (for list_subjects)
AllowedSubjectTypes []string // Subject types allowed for this relation
ComplexClosure []string // Complex closure relations (excluding intersection)
// Feature configuration
AllowWildcard bool // Whether wildcards are allowed (list_objects)
Exclusions ExclusionConfig // Exclusion rules configuration
// Feature flags (derived from analysis)
HasUserset bool
HasExclusion bool
HasIntersection bool
HasRecursive bool
// Eligibility and strategy from unified analysis
Capabilities GenerationCapabilities
Strategy ListStrategy
// Additional flags for routing
HasUsersetSubject bool // Has userset subject matching capability
HasUsersetPatterns bool // Has userset patterns to expand
HasComplexUsersets bool // Has userset patterns requiring check_permission calls
HasStandaloneAccess bool // Has standalone access paths (not constrained by intersection)
// Optimization flags
UseCTEExclusion bool // Use CTE-based exclusion optimization (precompute + anti-join)
// Analysis lookup for checking parent relation complexity (TTU optimization)
// Maps "objectType.relation" -> *RelationAnalysis
// Used by TTU block generation to determine if parent relations are simple or complex
AnalysisLookup map[string]*RelationAnalysis
}
ListPlan contains all computed data needed to generate a list function.
func BuildListObjectsPlan ¶ added in v0.5.0
func BuildListObjectsPlan(a RelationAnalysis, inline InlineSQLData) ListPlan
BuildListObjectsPlan creates a plan for generating a list_objects function.
func BuildListObjectsPlanWithLookup ¶ added in v0.6.0
func BuildListObjectsPlanWithLookup(a RelationAnalysis, inline InlineSQLData, lookup map[string]*RelationAnalysis) ListPlan
BuildListObjectsPlanWithLookup creates a plan with analysis lookup for TTU optimization.
func BuildListSubjectsPlan ¶ added in v0.5.0
func BuildListSubjectsPlan(a RelationAnalysis, inline InlineSQLData) ListPlan
BuildListSubjectsPlan creates a plan for generating a list_subjects function.
func BuildListSubjectsPlanWithLookup ¶ added in v0.6.0
func BuildListSubjectsPlanWithLookup(a RelationAnalysis, inline InlineSQLData, lookup map[string]*RelationAnalysis) ListPlan
BuildListSubjectsPlanWithLookup creates a plan with analysis lookup for TTU optimization.
func (ListPlan) ExcludeWildcard ¶ added in v0.5.0
func (ListPlan) FeaturesString ¶ added in v0.5.0
type ListSubjectsDirectInput ¶
type ListSubjectsSelfCandidateInput ¶
type ListSubjectsSelfCandidateInput struct {
ObjectType string
Relation string
ObjectIDExpr Expr
FilterTypeExpr Expr
FilterRelationExpr Expr
ClosureValues string // Deprecated: use ClosureRows
ClosureRows []ValuesRow // Typed closure rows (preferred)
ExtraPredicatesSQL []string // Raw SQL predicate strings
}
type ListSubjectsUsersetFilterInput ¶
type ListSubjectsUsersetFilterInput struct {
ObjectType string
RelationList []string
AllowedSubjectTypes []string
ObjectIDExpr Expr
FilterTypeExpr Expr
FilterRelationExpr Expr
ClosureValues string // Deprecated: use ClosureRows
ClosureRows []ValuesRow // Typed closure rows (preferred)
UseTypeGuard bool
ExtraPredicatesSQL []string // Raw SQL predicate strings
}
type ListSubjectsUsersetPatternRecursiveComplexInput ¶
type ListSubjectsUsersetPatternRecursiveComplexInput struct {
ObjectType string
SubjectType string
SubjectRelation string
SourceRelations []string
ObjectIDExpr Expr
SubjectTypeExpr Expr
AllowedSubjectTypes []string
ExcludeWildcard bool
IsClosurePattern bool
SourceRelation string
Exclusions ExclusionConfig
}
type ListSubjectsUsersetPatternSimpleInput ¶
type ListSubjectsUsersetPatternSimpleInput struct {
ObjectType string
SubjectType string
SubjectRelation string
SourceRelations []string
SatisfyingRelations []string
ObjectIDExpr Expr
SubjectTypeExpr Expr
AllowedSubjectTypes []string
ExcludeWildcard bool
IsClosurePattern bool
SourceRelation string
Exclusions ExclusionConfig
}
type ListUsersetPatternData ¶
type ListUsersetPatternData struct {
SubjectType string // e.g., "group"
SubjectRelation string // e.g., "member"
// SatisfyingRelationsList is a SQL-formatted list of relations that satisfy SubjectRelation.
// e.g., "'member', 'admin'" when admin implies member.
SatisfyingRelationsList string
// SourceRelationList is a SQL-formatted list of relations to search for userset grant tuples.
// For direct userset patterns, this is the same as the parent's RelationList.
// For closure userset patterns (inherited from implied relations), this is the source relation.
// e.g., "'viewer'" for a pattern inherited from viewer: [group#member]
SourceRelationList string
// SourceRelation is the relation where this userset pattern is defined (unquoted).
// Used for closure patterns to verify permission via check_permission_internal.
SourceRelation string
// IsClosurePattern is true if this pattern is inherited from an implied relation.
// When true, candidates need to be verified via check_permission_internal on the
// source relation to apply any exclusions or complex features.
IsClosurePattern bool
// HasWildcard is true if any satisfying relation allows wildcards.
// When true, membership check includes subject_id = '*'.
HasWildcard bool
// IsComplex is true if this pattern requires check_permission_internal for membership.
// This happens when any relation in the closure has TTU, exclusion, or intersection.
IsComplex bool
// IsSelfReferential is true if SubjectType == ObjectType and SubjectRelation == Relation.
// Self-referential usersets (e.g., group.member: [group#member]) require recursive CTEs.
// Non-self-referential usersets use JOIN-based expansion.
IsSelfReferential bool
}
ListUsersetPatternData contains data for rendering userset pattern expansion in list templates. For a pattern like [group#member], this generates a UNION block that: - Finds grant tuples where subject is group#member - JOINs with membership tuples to find subjects who are members
type ParentRelationBlock ¶ added in v0.5.0
type ParentRelationBlock struct {
LinkingRelation string
ParentRelation string
AllowedLinkingTypes []string
Query SelectStmt
}
ParentRelationBlock represents a TTU check through a parent relation.
type RecursiveBlockSet ¶ added in v0.5.0
type RecursiveBlockSet struct {
BaseBlocks []TypedQueryBlock
RecursiveBlock *TypedQueryBlock
SelfCandidateBlock *TypedQueryBlock
SelfRefLinkingRelations []string
}
RecursiveBlockSet contains blocks for a recursive list function.
func BuildListObjectsRecursiveBlocks ¶ added in v0.5.0
func BuildListObjectsRecursiveBlocks(plan ListPlan) (RecursiveBlockSet, error)
BuildListObjectsRecursiveBlocks builds blocks for a recursive list_objects function. This handles TTU patterns with depth tracking and recursive CTEs.
func (RecursiveBlockSet) HasRecursive ¶ added in v0.5.0
func (r RecursiveBlockSet) HasRecursive() bool
HasRecursive returns true if there is a recursive block.
type SelfRefUsersetBlockSet ¶ added in v0.5.0
type SelfRefUsersetBlockSet struct {
// BaseBlocks are the base case blocks (depth=0) in the CTE
BaseBlocks []TypedQueryBlock
// RecursiveBlock is the recursive term block that expands self-referential usersets
RecursiveBlock *TypedQueryBlock
// SelfCandidateBlock is added outside the CTE (UNION with CTE result)
SelfCandidateBlock *TypedQueryBlock
}
SelfRefUsersetBlockSet contains blocks for a self-referential userset list function. These blocks are wrapped in a recursive CTE for member expansion.
func BuildListObjectsSelfRefUsersetBlocks ¶ added in v0.5.0
func BuildListObjectsSelfRefUsersetBlocks(plan ListPlan) (SelfRefUsersetBlockSet, error)
BuildListObjectsSelfRefUsersetBlocks builds blocks for a self-referential userset list_objects function.
func (SelfRefUsersetBlockSet) HasRecursive ¶ added in v0.5.0
func (s SelfRefUsersetBlockSet) HasRecursive() bool
HasRecursive returns true if there is a recursive block.
type SelfRefUsersetSubjectsBlockSet ¶ added in v0.5.0
type SelfRefUsersetSubjectsBlockSet struct {
// UsersetFilterBlocks are blocks for the userset filter path (when p_subject_type contains '#')
UsersetFilterBlocks []TypedQueryBlock
// UsersetFilterSelfBlock is the self-candidate block for userset filter path
UsersetFilterSelfBlock *TypedQueryBlock
// UsersetFilterRecursiveBlock is the recursive block for userset filter expansion
UsersetFilterRecursiveBlock *TypedQueryBlock
// RegularBlocks are blocks for the regular path (individual subjects)
RegularBlocks []TypedQueryBlock
// UsersetObjectsBaseBlock is the base block for userset objects CTE
UsersetObjectsBaseBlock *TypedQueryBlock
// UsersetObjectsRecursiveBlock is the recursive block for userset objects CTE
UsersetObjectsRecursiveBlock *TypedQueryBlock
}
SelfRefUsersetSubjectsBlockSet contains blocks for a self-referential userset list_subjects function. This includes separate blocks for userset filter path and regular path.
func BuildListSubjectsSelfRefUsersetBlocks ¶ added in v0.5.0
func BuildListSubjectsSelfRefUsersetBlocks(plan ListPlan) (SelfRefUsersetSubjectsBlockSet, error)
BuildListSubjectsSelfRefUsersetBlocks builds blocks for a self-referential userset list_subjects function.
type SubjectsIntersectionBlockSet ¶ added in v0.5.0
type SubjectsIntersectionBlockSet struct {
RegularCandidateBlocks []TypedQueryBlock
UsersetFilterCandidateBlocks []TypedQueryBlock
UsersetFilterSelfBlock *TypedQueryBlock
}
SubjectsIntersectionBlockSet contains blocks for an intersection list_subjects function. Unlike recursive which uses check_permission_internal within queries, intersection gathers candidates then filters with check_permission at the end.
func BuildListSubjectsIntersectionBlocks ¶ added in v0.5.0
func BuildListSubjectsIntersectionBlocks(plan ListPlan) SubjectsIntersectionBlockSet
type SubjectsRecursiveBlockSet ¶ added in v0.5.0
type SubjectsRecursiveBlockSet struct {
RegularBlocks []TypedQueryBlock
RegularTTUBlocks []TypedQueryBlock
UsersetFilterBlocks []TypedQueryBlock
UsersetFilterSelfBlock *TypedQueryBlock
ParentRelations []ListParentRelationData
}
SubjectsRecursiveBlockSet contains blocks for a recursive list_subjects function.
func BuildListSubjectsRecursiveBlocks ¶ added in v0.5.0
func BuildListSubjectsRecursiveBlocks(plan ListPlan) (SubjectsRecursiveBlockSet, error)
BuildListSubjectsRecursiveBlocks builds blocks for a recursive list_subjects function.
type SubstringUsersetRelation ¶
type SubstringUsersetRelation = sqldsl.SubstringUsersetRelation
sqldsl types
type TypedQueryBlock ¶ added in v0.5.0
type TypedQueryBlock struct {
Comments []string
Query SelectStmt
}
TypedQueryBlock represents a query with optional comments. Uses SelectStmt for type-safe DSL construction.
type TypedValuesTable ¶ added in v0.5.0
type TypedValuesTable = sqldsl.TypedValuesTable
sqldsl types
type UsersetNormalized ¶ added in v0.5.0
type UsersetNormalized = sqldsl.UsersetNormalized
sqldsl types
Source Files
¶
- check_blocks.go
- check_functions.go
- check_plan.go
- check_queries.go
- check_render.go
- compile.go
- doc.go
- exclusion.go
- exports.go
- list_functions.go
- list_helpers.go
- list_objects_blocks.go
- list_objects_blocks_composed.go
- list_objects_blocks_recursive.go
- list_objects_blocks_selfref.go
- list_objects_render.go
- list_objects_render_composed.go
- list_objects_render_depth.go
- list_objects_render_recursive.go
- list_objects_render_selfref.go
- list_plan.go
- list_queries.go
- list_shared_blocks.go
- list_shared_render.go
- list_subjects_blocks.go
- list_subjects_blocks_composed.go
- list_subjects_blocks_intersection.go
- list_subjects_blocks_recursive.go
- list_subjects_blocks_selfref.go
- list_subjects_render.go
- list_subjects_render_composed.go
- list_subjects_render_depth.go
- list_subjects_render_helpers.go
- list_subjects_render_intersection.go
- list_subjects_render_recursive.go
- list_subjects_render_selfref.go
- permission.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package analysis provides relation analysis and strategy selection for SQL code generation.
|
Package analysis provides relation analysis and strategy selection for SQL code generation. |
|
Package inline generates VALUES clauses for inlining metadata into SQL functions.
|
Package inline generates VALUES clauses for inlining metadata into SQL functions. |
|
Package plpgsql provides PL/pgSQL function builder types.
|
Package plpgsql provides PL/pgSQL function builder types. |
|
Package sqldsl provides a type-safe DSL for building PostgreSQL queries.
|
Package sqldsl provides a type-safe DSL for building PostgreSQL queries. |
|
Package tuples provides tuple-table specific builders and helpers.
|
Package tuples provides tuple-table specific builders and helpers. |