Skip to main content

Validation Pipeline

The validation pipeline transforms a parsed AST into a semantically validated schema. This is handled by the parser-database and psl-core crates.

Parser Database

The ParserDatabase is the core container for validated schema information:

Purpose and Scope

The parser database is connector-agnostic - it performs generic validations that apply to all databases:
  • Name resolution and uniqueness
  • Type checking
  • Relationship validation
  • Attribute syntax validation
  • Constraint name generation
Connector-specific validations (like native types, capabilities) happen later in psl-core.
ParserDatabase never fails. It accumulates diagnostics while building as complete a database as possible, even with errors in the schema.

Validation Phases

Validation proceeds in four phases:

1. Name Resolution

First pass: resolve all identifiers to IDs
Resolved items:
  • Models and views
  • Enums
  • Composite types
  • Fields (model fields, composite fields)
  • Datasources
  • Generators
Each item gets a unique ID:

2. Type Resolution

Second pass: resolve type references
For each field:
  • Resolve type identifier to its definition
  • Determine if it’s a scalar, relation, enum, or composite
  • Handle optional/required/list arity
  • Validate type compatibility

3. Attribute Validation

Third pass: validate attributes on models and fields
Validations:
  • Required vs. optional arguments
  • Argument types
  • Attribute compatibility
  • Duplicate attributes

4. Global Validations

Fourth pass: cross-cutting validations
  • Relation completeness and consistency
  • Index name collisions
  • Unique constraint validation
  • Primary key requirements
  • Referential actions compatibility

Database Structure

String Interning

Efficient string storage:
Benefits:
  • Reduced memory usage
  • Fast string comparison (compare IDs)
  • Canonical representation

Type System

Relations

Walker API

The walker API provides type-safe schema traversal:

Walker Types

Walkers provide:
  • Safe access to schema data
  • Navigation between related items
  • Computed properties
  • Database name resolution
Walkers borrow from ParserDatabase, ensuring data consistency. They’re lightweight and can be created on-demand.

Validation Examples

Name Uniqueness

Validation error: DatamodelError::new_duplicate_top_error("User", ...)

Type Resolution

Relation Validation

Attribute Validation

Constraint Names

The database generates default constraint names:
Constraint scopes:
Constraint name generation is connector-specific, handled by the connector trait’s constraint_violation_scopes() method.

Reserved Names

Certain names are reserved and validated:

Index Definitions

Indexes are validated and stored:

Extension Types

Support for custom types via extensions:
Extensions allow adding custom types to the schema without modifying PSL core.

Diagnostic Collection

Diagnostics accumulate throughout validation:

Error Types

Validation Pipeline Entry Points

Single File

Multi-File

Parse Only (Skip Validation)

Testing

PSL uses declarative validation tests:
Test format:
Running tests:
Tests with no error comment at the end expect a valid schema. Tests with error comments expect those exact errors.

Configuration Parsing

Parse only datasource and generator blocks:
This is faster than full validation when you only need configuration.

Common Validations

Primary Key Validation

  • Every model needs an @id or @@id
  • Single-field or compound primary keys
  • Primary key fields cannot be optional

Unique Constraint Validation

  • Single-field @unique or compound @@unique
  • Unique fields can be optional
  • Unique constraints can have names via map:

Relation Validation

  • Both sides of relation must have fields
  • Referencing fields must match referenced fields in type and count
  • Referential actions must be supported by the connector

Default Value Validation

  • Default must match field type
  • Functions like autoincrement(), now(), uuid() validated per connector
  • Constants validated for type compatibility

Next Steps

Connectors

Learn about database-specific validations

Parser

Understand the AST and parsing phase