sqlgen

package
v0.6.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 31, 2026 License: MIT Imports: 8 Imported by: 0

README

sqlgen

SQL code generation for Melange authorization functions.

Responsibility

Generates specialized PostgreSQL functions from OpenFGA schemas:

  • Check functions - check_<type>_<relation>() for permission checks
  • List functions - list_<type>_<relation>_objects/subjects() for enumeration
  • Dispatchers - Route calls to specialized functions

This is the core compilation engine that transforms authorization models into executable SQL.

Architecture Role

pkg/schema (types, closure)
       │
       └── internal/sqlgen (analysis, code generation)
               │
               └── pkg/migrator (applies generated SQL)

The package sits between schema analysis and database migration, producing all SQL artifacts.

Code Generation Pipeline

Schema Types
     │
     ▼
┌─────────────┐
│  Analyze    │  Classify relations, detect patterns
└─────────────┘
     │
     ▼
┌─────────────┐
│   Plan      │  Build abstract query plan per relation
└─────────────┘
     │
     ▼
┌─────────────┐
│  Blocks     │  Convert plans to SQL query blocks
└─────────────┘
     │
     ▼
┌─────────────┐
│  Render     │  Emit final PL/pgSQL functions
└─────────────┘

Key Components

Subpackages

The package is organized into focused subpackages:

Package Purpose
sqldsl Generic SQL builders (SelectStmt, Expr, TableExpr, operators)
analysis Relation analysis and strategy selection
tuples Tuple-table specific query builders
plpgsql PL/pgSQL function builder types
inline Inline SQL model data and typed VALUES rows

The root sqlgen package re-exports types for backward compatibility.

SQL DSL (sqldsl/)

Domain-specific types for building SQL:

  • SelectStmt - SELECT query builder
  • Expr - SQL expressions (columns, literals, operators)
  • TableExpr - Table references (base tables, subqueries, VALUES)
Analysis (analysis/)

Classifies relations by their patterns:

  • Direct assignment, implied relations, wildcards
  • Parent inheritance (tuple-to-userset)
  • Exclusions, intersections, usersets
Check Generation (check_plan.go, check_blocks.go, check_render.go)

Three-layer architecture for check functions:

  1. Plan - Abstract representation of permission logic
  2. Blocks - SQL query blocks with comments
  3. Render - Final PL/pgSQL function output
List Generation (list_plan.go, list_blocks.go, list_render.go)

Parallel architecture for list functions with additional complexity for:

  • Recursive object enumeration
  • Subject enumeration with wildcard handling
  • Cursor-based pagination
Inline Data (inline/)

Precomputes closure and userset data as SQL VALUES tables, eliminating runtime table lookups.

Design Principles

  1. Pattern-specific code - Each authorization pattern gets optimized SQL
  2. Compile-time closure - Role hierarchies resolved before runtime
  3. Inline data - No runtime schema lookups, all data embedded in functions
  4. Predictable plans - PostgreSQL can optimize each specialized function independently

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:

  1. Analysis: Parse relation features (direct, implied, userset, TTU, exclusion, intersection)
  2. Planning: Determine which SQL patterns to use based on feature combinations
  3. 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:

  1. Specialized check function: check_{type}_{relation}(subject_type, subject_id, object_id)
  2. No-wildcard variant: check_{type}_{relation}_no_wildcard(...)
  3. List objects function: list_{type}_{relation}_objects(subject_type, subject_id, limit, cursor)
  4. 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:

  1. Call AnalyzeRelations to classify all relations and detect features
  2. Call ComputeCanGenerate to determine generation eligibility and populate metadata
  3. Call GenerateSQL to produce all function definitions
  4. 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

View Source
const (
	ListStrategyDirect         = analysis.ListStrategyDirect
	ListStrategyUserset        = analysis.ListStrategyUserset
	ListStrategyRecursive      = analysis.ListStrategyRecursive
	ListStrategyIntersection   = analysis.ListStrategyIntersection
	ListStrategyDepthExceeded  = analysis.ListStrategyDepthExceeded
	ListStrategySelfRefUserset = analysis.ListStrategySelfRefUserset
	ListStrategyComposed       = analysis.ListStrategyComposed
)

Variables

View Source
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
)
View Source
var (
	ComputeRelationClosure = analysis.ComputeRelationClosure
	AnalyzeRelations       = analysis.AnalyzeRelations
	ComputeCanGenerate     = analysis.ComputeCanGenerate
	DetermineListStrategy  = analysis.DetermineListStrategy
	BuildAnalysisLookup    = analysis.BuildAnalysisLookup
)
View Source
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
)
View Source
var (
	BuildInlineSQLData    = inline.BuildInlineSQLData
	BuildClosureTypedRows = inline.BuildClosureTypedRows
	BuildUsersetTypedRows = inline.BuildUsersetTypedRows
)
View Source
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 ListObjectsIntersectionClosureQuery

func ListObjectsIntersectionClosureQuery(functionName string) (string, error)

func ListObjectsIntersectionClosureValidatedQuery

func ListObjectsIntersectionClosureValidatedQuery(objectType, relation, functionName string) (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 ListSubjectsIntersectionClosureQuery

func ListSubjectsIntersectionClosureQuery(functionName string, subjectTypeExpr Expr) (string, error)

func ListSubjectsIntersectionClosureValidatedQuery

func ListSubjectsIntersectionClosureValidatedQuery(objectType, relation, functionName string, functionSubjectTypeExpr, checkSubjectTypeExpr, objectIDExpr Expr) (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

func RenderListObjectsDepthExceededFunction(plan ListPlan) string

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

func RenderListObjectsFunction(plan ListPlan, blocks BlockSet) (string, error)

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

func RenderListSubjectsDepthExceededFunction(plan ListPlan) string

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

func RenderListSubjectsFunction(plan ListPlan, blocks BlockSet) (string, error)

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 Add added in v0.5.0

type Add = sqldsl.Add

sqldsl types

type Alias

type Alias = sqldsl.Alias

sqldsl types

type AnchorPathStep

type AnchorPathStep = analysis.AnchorPathStep

analysis types

type AndExpr

type AndExpr = sqldsl.AndExpr

sqldsl types

type ArrayAppend added in v0.5.0

type ArrayAppend = sqldsl.ArrayAppend

sqldsl types

type ArrayContains added in v0.5.0

type ArrayContains = sqldsl.ArrayContains

sqldsl types

type ArrayLength added in v0.5.0

type ArrayLength = sqldsl.ArrayLength

sqldsl types

type ArrayLiteral added in v0.5.0

type ArrayLiteral = sqldsl.ArrayLiteral

Array types

type Assign added in v0.5.0

type Assign = plpgsql.Assign

plpgsql 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

func BuildListObjectsBlocks(plan ListPlan) (BlockSet, error)

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

func BuildListSubjectsBlocks(plan ListPlan) (BlockSet, error)

BuildListSubjectsBlocks builds all query blocks for a list_subjects function. Returns a BlockSet with Primary and optionally Secondary blocks.

type Bool

type Bool = sqldsl.Bool

sqldsl types

type CTEDef added in v0.5.0

type CTEDef = sqldsl.CTEDef

CTE types

type CaseExpr added in v0.5.0

type CaseExpr = sqldsl.CaseExpr

sqldsl types

type CaseWhen added in v0.5.0

type CaseWhen = sqldsl.CaseWhen

sqldsl types

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

func (p CheckPlan) DetermineCheckFunctionType() string

DetermineCheckFunctionType returns which type of check function to generate. Returns one of: "direct", "intersection", "recursive", "recursive_intersection"

type ClosureRow

type ClosureRow = analysis.ClosureRow

analysis types

type Col

type Col = sqldsl.Col

sqldsl types

type Comment added in v0.5.0

type Comment = plpgsql.Comment

plpgsql types

type CommentedSQL added in v0.5.0

type CommentedSQL = sqldsl.CommentedSQL

sqldsl types

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 Concat

type Concat = sqldsl.Concat

sqldsl types

type Decl added in v0.5.0

type Decl = plpgsql.Decl

plpgsql types

type DispatcherCase

type DispatcherCase struct {
	ObjectType        string
	Relation          string
	CheckFunctionName string
}

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 EmptyArray

type EmptyArray = sqldsl.EmptyArray

sqldsl types

type Eq

type Eq = sqldsl.Eq

Operators

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 Exists

type Exists = sqldsl.Exists

sqldsl types

type Expr

type Expr = sqldsl.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

func SimpleExclusion(objectType, relation string, objectID, subjectType, subjectID Expr) Expr

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 Func

type Func = sqldsl.Func

sqldsl types

type FuncArg added in v0.5.0

type FuncArg = plpgsql.FuncArg

plpgsql types

type FuncCallEq added in v0.5.0

type FuncCallEq = sqldsl.FuncCallEq

Function call types

type FuncCallNe added in v0.5.0

type FuncCallNe = sqldsl.FuncCallNe

sqldsl types

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 Gt

type Gt = sqldsl.Gt

sqldsl types

type Gte

type Gte = sqldsl.Gte

sqldsl types

type HasUserset

type HasUserset = sqldsl.HasUserset

sqldsl types

type If added in v0.5.0

type If = plpgsql.If

plpgsql types

type ImpliedFunctionCheck added in v0.5.0

type ImpliedFunctionCheck struct {
	Relation     string
	FunctionName string
	Check        Expr
}

ImpliedFunctionCheck represents a check that calls another check function.

type In

type In = sqldsl.In

sqldsl types

type InFunctionSelect added in v0.5.0

type InFunctionSelect = sqldsl.InFunctionSelect

sqldsl types

type IndirectAnchorInfo

type IndirectAnchorInfo = analysis.IndirectAnchorInfo

analysis types

type InlineSQLData

type InlineSQLData = inline.InlineSQLData

inline types

type Int

type Int = sqldsl.Int

sqldsl types

type IntersectSubquery added in v0.5.0

type IntersectSubquery = sqldsl.IntersectSubquery

sqldsl types

type IntersectionGroup

type IntersectionGroup = analysis.IntersectionGroup

analysis 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 IntersectionPart

type IntersectionPart = analysis.IntersectionPart

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 IsNotNull

type IsNotNull = sqldsl.IsNotNull

sqldsl types

type IsNull

type IsNull = sqldsl.IsNull

sqldsl types

type IsWildcard

type IsWildcard = sqldsl.IsWildcard

sqldsl types

type JoinClause

type JoinClause = sqldsl.JoinClause

Statements and structures

type LateralFunction

type LateralFunction = sqldsl.LateralFunction

sqldsl types

type Like added in v0.6.0

type Like = sqldsl.Like

sqldsl types

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

type ListDispatcherCase struct {
	ObjectType   string
	Relation     string
	FunctionName string
}

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 ListObjectsSelfCandidateInput

type ListObjectsSelfCandidateInput struct {
	ObjectType    string
	Relation      string
	ClosureValues string      // Deprecated: use ClosureRows
	ClosureRows   []ValuesRow // Typed closure rows (preferred)
}

type ListObjectsUsersetPatternComplexInput

type ListObjectsUsersetPatternComplexInput struct {
	ObjectType       string
	SubjectType      string
	SubjectRelation  string
	SourceRelations  []string
	IsClosurePattern bool
	SourceRelation   string
	Exclusions       ExclusionConfig
}

type ListObjectsUsersetPatternSimpleInput

type ListObjectsUsersetPatternSimpleInput struct {
	ObjectType          string
	SubjectType         string
	SubjectRelation     string
	SourceRelations     []string
	SatisfyingRelations []string
	AllowedSubjectTypes []string
	AllowWildcard       bool
	IsClosurePattern    bool
	SourceRelation      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 (p ListPlan) ExcludeWildcard() bool

func (ListPlan) FeaturesString added in v0.5.0

func (p ListPlan) FeaturesString() string

type ListStrategy added in v0.5.0

type ListStrategy = analysis.ListStrategy

analysis types

type ListSubjectsComplexClosureInput

type ListSubjectsComplexClosureInput struct {
	ObjectType      string
	Relation        string
	ObjectIDExpr    Expr
	SubjectTypeExpr Expr
	ExcludeWildcard bool
	Exclusions      ExclusionConfig
}

type ListSubjectsDirectInput

type ListSubjectsDirectInput struct {
	ObjectType      string
	RelationList    []string
	ObjectIDExpr    Expr
	SubjectTypeExpr Expr
	ExcludeWildcard bool
	Exclusions      ExclusionConfig
}

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 ListSubjectsUsersetPatternComplexInput

type ListSubjectsUsersetPatternComplexInput struct {
	ObjectType       string
	SubjectType      string
	SubjectRelation  string
	SourceRelations  []string
	ObjectIDExpr     Expr
	SubjectTypeExpr  Expr
	IsClosurePattern bool
	SourceRelation   string
	Exclusions       ExclusionConfig
}

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 Lit

type Lit = sqldsl.Lit

sqldsl types

type Lt

type Lt = sqldsl.Lt

sqldsl types

type Lte

type Lte = sqldsl.Lte

sqldsl types

type Ne

type Ne = sqldsl.Ne

sqldsl types

type NoUserset

type NoUserset = sqldsl.NoUserset

sqldsl types

type NotExists

type NotExists = sqldsl.NotExists

sqldsl types

type NotExpr

type NotExpr = sqldsl.NotExpr

sqldsl types

type NotIn added in v0.5.0

type NotIn = sqldsl.NotIn

sqldsl types

type NotLike added in v0.6.0

type NotLike = sqldsl.NotLike

sqldsl types

type Null

type Null = sqldsl.Null

sqldsl types

type ObjectRef

type ObjectRef = sqldsl.ObjectRef

sqldsl types

type OrExpr

type OrExpr = sqldsl.OrExpr

sqldsl types

type Param

type Param = sqldsl.Param

sqldsl types

type Paren

type Paren = sqldsl.Paren

sqldsl types

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 ParentRelationCheck

type ParentRelationCheck = analysis.ParentRelationCheck

analysis types

type ParentRelationInfo

type ParentRelationInfo = analysis.ParentRelationInfo

analysis types

type PlpgsqlFunction added in v0.5.0

type PlpgsqlFunction = plpgsql.PlpgsqlFunction

plpgsql types

type Position added in v0.5.0

type Position = sqldsl.Position

sqldsl types

type QueryBlock added in v0.5.0

type QueryBlock = sqldsl.QueryBlock

sqldsl types

type Raise added in v0.5.0

type Raise = plpgsql.Raise

plpgsql types

type Raw

type Raw = sqldsl.Raw

sqldsl types

type RawStmt added in v0.5.0

type RawStmt = plpgsql.RawStmt

plpgsql types

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 RelationAnalysis

type RelationAnalysis = analysis.RelationAnalysis

analysis types

type RelationDefinition

type RelationDefinition = analysis.RelationDefinition

analysis types

type RelationFeatures

type RelationFeatures = analysis.RelationFeatures

analysis types

type Return added in v0.5.0

type Return = plpgsql.Return

plpgsql types

type ReturnInt added in v0.5.0

type ReturnInt = plpgsql.ReturnInt

plpgsql types

type ReturnQuery added in v0.5.0

type ReturnQuery = plpgsql.ReturnQuery

plpgsql types

type ReturnValue added in v0.5.0

type ReturnValue = plpgsql.ReturnValue

plpgsql types

type SQLer added in v0.5.0

type SQLer = sqldsl.SQLer

sqldsl types

type SelectInto added in v0.5.0

type SelectInto = plpgsql.SelectInto

plpgsql types

type SelectIntoVar added in v0.5.0

type SelectIntoVar = sqldsl.SelectIntoVar

sqldsl types

type SelectStmt

type SelectStmt = sqldsl.SelectStmt

sqldsl types

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 SqlFunction added in v0.5.0

type SqlFunction = plpgsql.SqlFunction

plpgsql types

type Stmt added in v0.5.0

type Stmt = plpgsql.Stmt

plpgsql types

type Sub added in v0.5.0

type Sub = sqldsl.Sub

sqldsl types

type SubjectRef

type SubjectRef = sqldsl.SubjectRef

Ref types

type SubjectTypeRef

type SubjectTypeRef = analysis.SubjectTypeRef

analysis types

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 Substring added in v0.5.0

type Substring = sqldsl.Substring

sqldsl types

type SubstringUsersetRelation

type SubstringUsersetRelation = sqldsl.SubstringUsersetRelation

sqldsl types

type TableExpr

type TableExpr = sqldsl.TableExpr

Table expressions

type TableRef

type TableRef = sqldsl.TableRef

sqldsl types

type TupleQuery

type TupleQuery = tuples.TupleQuery

tuples types

type TypeDefinition

type TypeDefinition = analysis.TypeDefinition

analysis 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 UnionAll added in v0.5.0

type UnionAll = sqldsl.UnionAll

sqldsl types

type UsersetNormalized added in v0.5.0

type UsersetNormalized = sqldsl.UsersetNormalized

sqldsl types

type UsersetObjectID

type UsersetObjectID = sqldsl.UsersetObjectID

Userset types

type UsersetPattern

type UsersetPattern = analysis.UsersetPattern

analysis types

type UsersetRelation

type UsersetRelation = sqldsl.UsersetRelation

sqldsl types

type ValuesRow added in v0.5.0

type ValuesRow = sqldsl.ValuesRow

sqldsl types

type ValuesTable

type ValuesTable = sqldsl.ValuesTable

sqldsl types

type WithCTE added in v0.5.0

type WithCTE = sqldsl.WithCTE

sqldsl types

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL