Documentation Index Fetch the complete documentation index at: https://docs.chameleondb.dev/llms.txt
Use this file to discover all available pages before exploring further.
Constraints enforce data integrity rules at the schema level. ChameleonDB validates constraints both at compile time and runtime.
Primary Keys
Every entity must have exactly one primary key:
Designates a field as the entity’s primary key. Syntax: Example: entity User {
id : uuid primary , // Primary key
email : string ,
}
Rules:
Each entity must have exactly one primary field
Primary keys are automatically unique and non-null
Primary keys cannot be modified after creation
SQL Mapping: PRIMARY KEY
Primary Key Best Practices
// ✓ Good - UUID primary key
entity User {
id : uuid primary ,
}
// ✓ Also valid - String primary key
entity Country {
code : string primary , // e.g., "US", "UK"
}
// ✗ Bad - No primary key
entity User {
email : string unique , // Not enough - needs primary key
}
// ✗ Bad - Multiple primary keys
entity User {
id : uuid primary ,
email : string primary , // Error: only one primary key allowed
}
Unique Constraints
Enforce uniqueness across all rows:
Ensures field values are unique across all entities. Syntax: Example: entity User {
id : uuid primary ,
email : string unique , // No two users can have the same email
username : string unique , // No two users can have the same username
}
Rules:
Unique fields cannot have duplicate values
NULL values are considered distinct (multiple NULLs allowed if nullable)
Primary keys are implicitly unique
SQL Mapping: UNIQUE
Unique Constraint Examples
entity Product {
id : uuid primary ,
sku : string unique , // Product SKU must be unique
name : string , // Name can be duplicated
}
entity Email {
id : uuid primary ,
address : string unique , // Email addresses must be unique
user_id : uuid ,
}
Nullable Fields
Allow fields to have NULL values:
Allows a field to be NULL (empty/missing). Syntax: Example: entity User {
id : uuid primary ,
email : string ,
bio : string nullable , // Bio is optional
age : int nullable , // Age is optional
deleted_at : timestamp nullable , // NULL until deleted
}
Rules:
Fields are NOT NULL by default
Primary keys cannot be nullable
Foreign keys can be nullable (optional relations)
SQL Mapping: NULL (default is NOT NULL)
Nullable Best Practices
// ✓ Good - Explicit nullable for optional fields
entity User {
id : uuid primary ,
email : string , // Required
bio : string nullable , // Optional
middle_name : string nullable , // Optional
}
// ✓ Good - Nullable foreign key (optional relation)
entity Post {
id : uuid primary ,
author_id : uuid nullable , // Post can exist without author
author : User nullable ,
}
// ✗ Avoid - Don't make everything nullable
entity User {
id : uuid primary ,
email : string nullable , // Bad: email should be required
name : string nullable , // Bad: name should be required
}
Use nullable sparingly. Non-nullable fields make your domain model clearer and prevent many runtime errors.
Default Values
Specify default values for fields:
Provides a default value when the field is not specified. Syntax: fieldName : type default value
Available defaults:
now() - Current timestamp (for timestamp fields)
Literal values (strings, numbers, booleans)
Example: entity User {
id : uuid primary ,
email : string ,
created_at : timestamp default now (), // Auto-set to current time
active : bool default true , // Default to true (future)
role : string default "user" , // Default role (future)
}
SQL Mapping: DEFAULT value
Current Support (v1.0)
Currently, only default now() is fully supported for timestamp fields. Additional default value types are planned for future releases.
// ✓ Supported now
entity Order {
id : uuid primary ,
created_at : timestamp default now (),
updated_at : timestamp default now (),
}
// 🔮 Coming in future versions
entity User {
active : bool default true ,
role : string default "user" ,
score : int default 0 ,
}
Combining Constraints
Constraints can be combined on a single field:
entity User {
id : uuid primary , // primary only
email : string unique , // unique only
nickname : string unique nullable , // unique + nullable
bio : string nullable , // nullable only
created_at : timestamp default now (), // default only
deleted_at : timestamp nullable , // nullable only
}
Constraint Order
Constraints can appear in any order:
// All equivalent:
email : string unique nullable
email : string nullable unique
email : nullable unique string // ✗ Type must come first
The field type must always come immediately after the colon (:). Constraints follow the type.
Complete Example
Here’s a complete schema demonstrating all constraints:
entity User {
// Primary key (required, unique, non-null)
id : uuid primary ,
// Unique fields
email : string unique ,
username : string unique ,
// Required fields (non-null by default)
name : string ,
// Optional fields
bio : string nullable ,
age : int nullable ,
avatar_url : string nullable ,
// Timestamps with defaults
created_at : timestamp default now (),
updated_at : timestamp default now (),
deleted_at : timestamp nullable ,
// Relations
orders : [ Order ] via user_id ,
}
entity Order {
id : uuid primary ,
total : decimal ,
status : string ,
// Required foreign key
user_id : uuid ,
user : User ,
// Optional foreign key
coupon_id : uuid nullable ,
coupon : Coupon nullable ,
created_at : timestamp default now (),
items : [ OrderItem ] via order_id ,
}
entity Coupon {
// String primary key
code : string primary ,
discount : decimal ,
expires_at : timestamp ,
orders : [ Order ] via coupon_id ,
}
entity OrderItem {
id : uuid primary ,
quantity : int ,
price : decimal ,
order_id : uuid ,
order : Order ,
}
Validation Rules
ChameleonDB enforces these validation rules:
Exactly One Primary Key - Each entity must have exactly one primary field
Primary Keys Non-Nullable - Primary keys cannot be nullable
Primary Keys Are Unique - Primary keys are implicitly unique
Type Compatibility - Default values must match the field type
Constraint Conflicts - Constraints must not conflict (e.g., primary nullable is invalid)
Runtime Enforcement
Constraints are enforced at runtime:
// Unique constraint violation
result , err := db . Insert ( "User" ).
Set ( "email" , "ana@mail.com" ).
Execute ( ctx )
// If email already exists:
// ❌ UniqueConstraintError: Field 'email' must be unique
// Value: ana@mail.com already exists
// NOT NULL constraint violation
result , err := db . Insert ( "User" ).
Set ( "id" , uuid . New ()).
// Missing required 'email' field
Execute ( ctx )
// ❌ NotNullError: Field 'email' cannot be NULL
Best Practices
Use UUIDs for primary keys - UUIDs prevent conflicts and are globally unique
Mark optional fields as nullable - Be explicit about which fields can be empty
Use unique constraints for natural keys - Email addresses, usernames, SKUs, etc.
Use default now() for timestamps - Automatically track creation and update times
Avoid nullable on business-critical fields - Required fields make your domain model clearer and prevent bugs.
Common Patterns
Soft Deletes
entity User {
id : uuid primary ,
email : string unique ,
deleted_at : timestamp nullable , // NULL = not deleted
}
Audit Timestamps
entity Post {
id : uuid primary ,
title : string ,
created_at : timestamp default now (),
updated_at : timestamp default now (),
}
Optional Relations
entity Order {
id : uuid primary ,
user_id : uuid nullable , // Order can exist without user
user : User nullable ,
}
Natural Keys
entity Country {
code : string primary , // "US", "UK" as primary key
name : string ,
}
entity Product {
id : uuid primary ,
sku : string unique , // Business identifier
name : string ,
}
Next Steps
Field Types Learn about available field types
Annotations Optimize with backend annotations