Documentation
¶
Overview ¶
Package validation provides comprehensive schema validation and safety checking.
This package exposes validation functionality for external tools to validate migration squashing results and ensure schema equivalence.
Basic Usage ¶
Validate squashed migrations against originals:
config := validation.DefaultConfig()
config.DockerApproach = validation.ApproachTwoDatabases
config.PostgreSQLVersion = "17"
validator, err := validation.NewValidator(config)
if err != nil {
log.Fatal(err)
}
result, err := validator.ValidateWithDocker(ctx, originalDir, squashedDir)
if err != nil {
log.Fatal(err)
}
if result.Success {
fmt.Println("✓ Validation passed!")
} else {
for _, err := range result.Errors {
fmt.Printf("Error: %s\n", err.Message)
}
}
Validation Approaches ¶
Three Docker-based strategies:
ApproachTwoContainers - Most accurate, separate containers ApproachTwoDatabases - Balanced, one container two databases (recommended) ApproachSchemaDiff - Fastest, sequential application
Extension Detection ¶
Automatic detection and installation of PostgreSQL extensions:
config := validation.DefaultConfig() config.EnableExtensionDetection = true config.AutoInstallExtensions = true validator, err := validation.NewValidator(config) // Extensions like pgcrypto, uuid-ossp will be auto-detected and installed
Custom Validation ¶
Validate specific aspects:
config := validation.DefaultConfig() config.Level = validation.LevelThorough config.ValidateConstraints = true config.ValidateDependencies = true config.ValidatePerformance = true
Index ¶
- Constants
- func IsReadOnlySQL(sql string) (bool, error)
- func ListRuleCodes() []string
- func ResolveEnabledRules(baseEnabled, enableRules, disableRules []string) ([]string, error)
- type CatalogSnapshot
- type ClassifiedStatement
- type DockerValidationResult
- type ExternalValidationOptions
- type Fix
- type SchemaComparisonResult
- type SchemaDiff
- type SchemaDifference
- type SchemaValidator
- type StatementClass
- type StaticValidator
- type StaticValidatorConfig
- func BuildStaticValidatorConfig(base *StaticValidatorConfig, enableRules, disableRules []string, strict bool) (*StaticValidatorConfig, error)
- func CloneStaticValidatorConfig(conf *StaticValidatorConfig) *StaticValidatorConfig
- func DefaultStaticValidatorConfig() *StaticValidatorConfig
- func MergeStaticValidatorConfig(base, overlay *StaticValidatorConfig) *StaticValidatorConfig
- type ValidationApproach
- type ValidationConfig
- type ValidationError
- type ValidationFix
- type ValidationLevel
- type ValidationResult
- func QuickValidate(ctx context.Context, originalDir, squashedDir string) (*ValidationResult, error)
- func ThoroughValidate(ctx context.Context, originalDir, squashedDir string) (*ValidationResult, error)
- func ValidateSchemaEquivalence(ctx context.Context, originalDir string, squashedDir string, ...) (*ValidationResult, error)
- type ValidationWarning
- type Violation
- type ViolationCategory
Constants ¶
const ( RuleCodeBreakingDropColumn = internal_validation.RuleCodeBreakingDropColumn RuleCodeBreakingDropTable = internal_validation.RuleCodeBreakingDropTable RuleCodeBreakingRenameColumn = internal_validation.RuleCodeBreakingRenameColumn RuleCodeBreakingRenameTable = internal_validation.RuleCodeBreakingRenameTable RuleCodeBreakingTypeChange = internal_validation.RuleCodeBreakingTypeChange RuleCodeSafetyConcurrentIndex = internal_validation.RuleCodeSafetyConcurrentIndex RuleCodeSafetyMissingWhere = internal_validation.RuleCodeSafetyMissingWhere RuleCodeSafetyConstraintNotValid = internal_validation.RuleCodeSafetyConstraintNotValid RuleCodeSafetyConstraintFlow = internal_validation.RuleCodeSafetyConstraintFlow RuleCodeHygienePreferText = internal_validation.RuleCodeHygienePreferText RuleCodeHygienePreferBigInt = internal_validation.RuleCodeHygienePreferBigInt RuleCodeMetaUnusedIgnoreDirective = internal_validation.RuleCodeMetaUnusedIgnoreDirective )
Rule codes (stable cross-surface identifiers)
const CatalogSnapshotContractVersion = internal_validation.CatalogSnapshotContractVersion
Variables ¶
This section is empty.
Functions ¶
func IsReadOnlySQL ¶
IsReadOnlySQL reports whether every statement in the script is read-only. Empty scripts (no statements after comment stripping) report false so that gates never treat unparseable-or-empty input as safe. Parse errors are returned to the caller, which must fail closed.
func ListRuleCodes ¶
func ListRuleCodes() []string
ListRuleCodes returns all registered static validation rule codes.
func ResolveEnabledRules ¶
ResolveEnabledRules resolves a final enabled rule set from base config values plus runtime enable/disable overrides.
Types ¶
type CatalogSnapshot ¶
type CatalogSnapshot = internal_validation.CatalogSnapshot
CatalogSnapshot is a portable schema signature captured from a caller-owned database.
type ClassifiedStatement ¶
type ClassifiedStatement struct {
// SQL is the exact statement text as it appeared in the input.
SQL string `json:"sql"`
// Class is the side-effect classification.
Class StatementClass `json:"class"`
// Reason explains why a non-read-only class was assigned.
Reason string `json:"reason,omitempty"`
}
ClassifiedStatement is one statement extracted from a SQL script together with its classification.
func ClassifyStatements ¶
func ClassifyStatements(sql string) ([]ClassifiedStatement, error)
ClassifyStatements parses a SQL script with the real PostgreSQL parser (pg_query) and classifies every top-level statement. Statement splitting is therefore correct in the presence of dollar-quoted bodies, string literals, and comments. A parse failure returns an error; callers implementing safety gates must fail closed on error.
func (ClassifiedStatement) IsReadOnly ¶
func (c ClassifiedStatement) IsReadOnly() bool
IsReadOnly reports whether the statement is safe on a read-only connection.
type DockerValidationResult ¶
type DockerValidationResult = internal_validation.DockerValidationResult
DockerValidationResult represents the result of Docker-based validation
type ExternalValidationOptions ¶
type ExternalValidationOptions = internal_validation.ExternalValidationOptions
ExternalValidationOptions identifies platform-owned schemas allowed in an otherwise empty database.
type SchemaComparisonResult ¶
type SchemaComparisonResult = internal_validation.SchemaComparisonResult
SchemaComparisonResult represents a comparison between two database schemas
type SchemaDiff ¶
type SchemaDiff = internal_validation.SchemaDiff
SchemaDiff represents differences between two schemas (normalized)
func CompareCatalogSnapshots ¶
func CompareCatalogSnapshots(original, candidate *CatalogSnapshot) (*SchemaDiff, error)
CompareCatalogSnapshots compares portable catalog snapshots without a live database.
func ValidateSchemaDiff ¶
func ValidateSchemaDiff(schema1, schema2 string) (*SchemaDiff, error)
ValidateSchemaDiff performs a direct schema difference comparison between two schema strings. It normalizes both schemas using the default normalizer and returns the differences.
This is useful for pre-flight checks where you have the raw SQL of two schemas (e.g. pg_dump output) and want to see if they are equivalent.
type SchemaDifference ¶
type SchemaDifference = internal_validation.SchemaDifference
SchemaDifference represents a difference between schemas
type SchemaValidator ¶
type SchemaValidator = internal_validation.SchemaValidator
SchemaValidator performs schema validation and safety checking
func NewValidator ¶
func NewValidator(config *ValidationConfig) *SchemaValidator
NewValidator creates a new schema validator with the given configuration
Example:
config := validation.DefaultConfig() config.DockerApproach = validation.ApproachTwoDatabases validator := validation.NewValidator(config)
type StatementClass ¶
type StatementClass string
StatementClass describes the side-effect profile of a single SQL statement.
const ( // StatementReadOnly statements cannot modify data, schema, or server state. StatementReadOnly StatementClass = "read_only" // StatementWrite statements modify data (or may do so, e.g. DO blocks, // procedure calls, and side-effecting functions such as setval/nextval). StatementWrite StatementClass = "write" // StatementDDL statements modify schema objects (CREATE/ALTER/DROP/..., // including SELECT ... INTO which creates a table). StatementDDL StatementClass = "ddl" // StatementMaintenance statements affect server or session state without // directly writing user data (VACUUM, SET, BEGIN/COMMIT, LOCK, ...). // They are NOT read-only. StatementMaintenance StatementClass = "maintenance" )
type StaticValidator ¶
type StaticValidator = internal_validation.StaticValidator
StaticValidator performs AST-based checking of SQL rules
func NewPostFlightValidator ¶
func NewPostFlightValidator() *StaticValidator
NewPostFlightValidator returns a validator optimized for final verification (strict)
func NewPreFlightValidator ¶
func NewPreFlightValidator() *StaticValidator
NewPreFlightValidator returns a validator optimized for initial checks (fast, hygiene focused)
func NewStaticValidator ¶
func NewStaticValidator(config *StaticValidatorConfig) *StaticValidator
NewStaticValidator creates a new static validator with configured rules
type StaticValidatorConfig ¶
type StaticValidatorConfig = config.StaticValidatorConfig
StaticValidatorConfig configures the static validator
func BuildStaticValidatorConfig ¶
func BuildStaticValidatorConfig(base *StaticValidatorConfig, enableRules, disableRules []string, strict bool) (*StaticValidatorConfig, error)
BuildStaticValidatorConfig applies runtime overrides (enable/disable/strict) to a base static-validator config and returns the resolved validator config.
func CloneStaticValidatorConfig ¶
func CloneStaticValidatorConfig(conf *StaticValidatorConfig) *StaticValidatorConfig
CloneStaticValidatorConfig returns a deep copy of the provided static-validator config. If conf is nil, it returns a copy of the engine defaults.
func DefaultStaticValidatorConfig ¶
func DefaultStaticValidatorConfig() *StaticValidatorConfig
DefaultStaticValidatorConfig returns a copy of the engine default static-validator config.
func MergeStaticValidatorConfig ¶
func MergeStaticValidatorConfig(base, overlay *StaticValidatorConfig) *StaticValidatorConfig
MergeStaticValidatorConfig overlays `overlay` onto `base` using engine semantics: - EnabledRules: if overlay has values, they replace base enabled rules. - RuleOptions: deep-merged (base first, then overlay keys overwrite). - TreatWarningsAsErrors: overlay value replaces base value.
If base is nil, engine defaults are used.
type ValidationApproach ¶
type ValidationApproach = internal_validation.ValidationApproach
ValidationApproach defines Docker-based validation strategies
const ( // ApproachTwoContainers uses separate containers for original and squashed migrations (most accurate) ApproachTwoContainers ValidationApproach = internal_validation.ApproachTwoContainers // ApproachTwoDatabases uses one container with two databases (best balance) ApproachTwoDatabases ValidationApproach = internal_validation.ApproachTwoDatabases // ApproachSchemaDiff uses sequential application and schema diff (fastest) ApproachSchemaDiff ValidationApproach = internal_validation.ApproachSchemaDiff )
Validation approaches
type ValidationConfig ¶
type ValidationConfig = internal_validation.ValidationConfig
ValidationConfig configures validation behavior
func DefaultConfig ¶
func DefaultConfig() *ValidationConfig
DefaultConfig returns a recommended configuration for validation
type ValidationError ¶
type ValidationError = internal_validation.ValidationError
ValidationError represents a validation error
type ValidationFix ¶
type ValidationFix = internal_validation.ValidationFix
ValidationFix represents a fix applied during validation
type ValidationLevel ¶
type ValidationLevel = internal_validation.ValidationLevel
ValidationLevel represents the level of validation to perform
const ( // LevelBasic performs basic SQL parsing and syntax validation LevelBasic ValidationLevel = internal_validation.ValidationLevelBasic // LevelStandard includes basic checks plus dependency validation (recommended) LevelStandard ValidationLevel = internal_validation.ValidationLevelStandard // LevelThorough includes standard checks plus performance analysis LevelThorough ValidationLevel = internal_validation.ValidationLevelThorough // LevelComprehensive performs the complete deterministic check suite // (all thorough checks plus full schema comparison) LevelComprehensive ValidationLevel = internal_validation.ValidationLevelComprehensive )
Validation levels
type ValidationResult ¶
type ValidationResult = internal_validation.ValidationResult
ValidationResult represents the result of schema validation
func QuickValidate ¶
func QuickValidate(ctx context.Context, originalDir, squashedDir string) (*ValidationResult, error)
QuickValidate is a convenience function for fast validation with minimal setup. Uses the fastest validation approach (SchemaDiff) for quick feedback.
This is ideal for CI/CD pipelines or rapid development iteration where speed is more important than exhaustive validation.
Example:
result, err := validation.QuickValidate(context.Background(), "./original", "./squashed")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Validation: %v (took %s)\n", result.Success, result.Duration)
func ThoroughValidate ¶
func ThoroughValidate(ctx context.Context, originalDir, squashedDir string) (*ValidationResult, error)
ThoroughValidate performs comprehensive validation with all checks enabled. Uses the most accurate validation approach (TwoContainers) for maximum confidence.
This is recommended for production releases, final validation before deployment, or when schema accuracy is critical.
Example:
result, err := validation.ThoroughValidate(context.Background(), "./original", "./squashed")
if err != nil {
log.Fatal(err)
}
if !result.Success {
log.Printf("Found %d errors and %d warnings\n", len(result.Errors), len(result.Warnings))
}
func ValidateSchemaEquivalence ¶
func ValidateSchemaEquivalence( ctx context.Context, originalDir string, squashedDir string, config *ValidationConfig, ) (*ValidationResult, error)
ValidateSchemaEquivalence is a convenience function that validates whether squashed migrations produce the same schema as the original migrations.
This is a high-level helper that sets up validation with recommended defaults and returns a simple pass/fail result with detailed comparison information.
Parameters:
- ctx: Context for cancellation and timeouts
- originalDir: Directory containing original migration files
- squashedDir: Directory containing squashed migration files
- config: Optional validation configuration (uses defaults if nil)
Returns:
- ValidationResult with Success, Errors, Warnings, and SchemaComparison
- Error if validation infrastructure fails (Docker, parsing, etc.)
Example:
ctx := context.Background()
result, err := validation.ValidateSchemaEquivalence(ctx, "./original", "./squashed", nil)
if err != nil {
log.Fatalf("Validation infrastructure error: %v", err)
}
if result.Success {
fmt.Println("✓ Schemas are equivalent!")
} else {
fmt.Println("✗ Schema differences found:")
for _, diff := range result.SchemaComparison.Differences {
fmt.Printf(" - %s: %s\n", diff.Type, diff.Description)
}
}
type ValidationWarning ¶
type ValidationWarning = internal_validation.ValidationWarning
ValidationWarning represents a validation warning
type Violation ¶
type Violation = internal_validation.Violation
Violation represents a rule violation found during static analysis
type ViolationCategory ¶
type ViolationCategory = internal_validation.ViolationCategory
ViolationCategory represents the severity/type of a violation
const ( CategorySafety ViolationCategory = internal_validation.CategorySafety CategoryBreaking ViolationCategory = internal_validation.CategoryBreaking CategoryHygiene ViolationCategory = internal_validation.CategoryHygiene )
Violation categories