README
A high-performance, type-safe ORM for Crystal applications.
Build fast, reliable database applications with compile-time safety and exceptional performance.
What Makes CQL Special?
CQL brings compile-time safety and performance optimization to Crystal applications. Unlike traditional ORMs that check for errors at runtime, CQL validates your queries, relationships, and data access patterns before your code executes.
# Type-safe queries that catch errors at compile time
users = User.where(active: true) # Type checked
.order(created_at: :desc) # Validates column exists
.limit(10) # Validates parameter type
.all
# This would fail at COMPILE TIME, not runtime:
# User.where(nonexistent: true) # Compile error!
# User.where(age: "invalid") # Type mismatch caught early!Key Features & Benefits
Performance Optimized
Zero-allocation queries through Crystal's compile-time optimizations
Connection pooling built-in for high-concurrency applications
Query caching with multiple cache backends (Memory, Redis)
N+1 query detection and performance monitoring tools
Type Safety at Compile Time
Catch bugs early - invalid queries fail at compile time
Full IDE support with autocompletion and refactoring
Relationship safety - no more runtime association errors
Query validation - SQL structure validated before deployment
Developer Experience
ActiveRecord-style API - familiar patterns for Rails developers
Automatic schema management - migrations with rollback support
Rich query DSL - expressive and readable database queries
Built-in validations - data integrity without boilerplate
Production Ready
PostgreSQL, MySQL, SQLite support through Crystal DB drivers
Transaction management with rollback safety
Performance monitoring and query analysis tools
Multiple design patterns - Active Record, Repository, Data Mapper support
Quick Start
Get up and running in under 5 minutes:
Try CQL Interactively
Explore CQL features with our interactive examples runner:
# Clone the repository
git clone https://github.com/azutoolkit/cql
cd cql
# Run the interactive examples
crystal examples/run_examples.crChoose from organized categories:
Basic Examples - Simple caching and core concepts
Advanced Caching - Enterprise-grade caching patterns
Configuration - Environment setup and best practices
Migrations - Database schema evolution
Performance - Monitoring and optimization
Framework Integration - Web framework examples
Complete Blog App - Full-featured application demo
1. Add to Your Project
# shard.yml
dependencies:
cql:
github: azutoolkit/cql
version: ~> 0.0.435
pg: # PostgreSQL driver
github: will/crystal-pg
version: ~> 0.26.02. Define Your Schema
# Set up your database schema
BlogDB = CQL::Schema.define(
:blog_schema,
adapter: CQL::Adapter::Postgres,
uri: ENV["DATABASE_URL"]
) do
table :users do
primary :id, Int64
text :name
text :email
boolean :active, default: "1"
timestamps
end
table :posts do
primary :id, Int64
text :title
text :content
bigint :user_id
boolean :published, default: "0"
timestamps
foreign_key [:user_id], references: :users, references_columns: [:id]
end
end3. Create Your First Model
struct User
include CQL::ActiveRecord::Model(Int64)
db_context BlogDB, :users
getter id : Int64?
getter name : String
getter email : String
getter active : Bool = true
getter created_at : Time?
getter updated_at : Time?
# Type-safe relationships
has_many :posts, foreign_key: :user_id
# Built-in validations
validate :name, presence: true, size: 2..50
validate :email, presence: true, match: /@/
def initialize(@name : String, @email : String, @active : Bool = true)
end
end4. Start Building
# Create records with validation
user = User.create!(name: "Alice", email: "alice@example.com")
# Type-safe queries
active_users = User.where(active: true)
.order(created_at: :desc)
.limit(50)
.all
# Work with relationships
user = User.find!(1)
posts = user.posts.all
puts "User #{user.name} has #{posts.size} posts"Database Support
Supported databases with their Crystal DB drivers:
PostgreSQL
pg
postgres://user:pass@localhost/mydb
MySQL
mysql
mysql://user:pass@localhost/mydb
SQLite
sqlite3
sqlite3://./database.db
Advanced Features
Relationships Made Simple
# Define relationships with type safety
struct Post
include CQL::ActiveRecord::Model(Int64)
db_context BlogDB, :posts
getter id : Int64?
getter title : String
getter content : String
getter user_id : Int64
getter published : Bool = false
belongs_to :user, User, foreign_key: :user_id
has_many :comments, Comment, foreign_key: :post_id
def initialize(@title : String, @content : String, @user_id : Int64)
end
end
# Work with relationships efficiently
post = Post.find!(1)
author = post.user # Type: User
comments = post.comments.all # Type: Array(Comment)Powerful Query DSL
# Complex queries with full type safety
recent_posts = Post.where(published: true)
.where { users.created_at >= 1.month.ago }
.order(created_at: :desc)
.limit(100)
.all
# Use the CQL Query builder for complex joins
posts_with_authors = BlogDB.query
.from(:posts)
.join(:users) { |j| j.posts.user_id.eq(j.users.id) }
.where{ posts.published: true }
.select(posts: [:title, :content], users: [:name])
.all({title: String, content: String, name: String})Automatic Schema Management
# Migrations with full rollback support
class CreateUsers < CQL::Migration(1)
def up
schema.create :users do
primary :id, Int64, auto_increment: true
text :name, null: false
text :email, null: false
boolean :active, default: true
timestamps
end
schema.alter :users do
create_index :idx_users_email, [:email], unique: true
end
schema.users.create!
end
def down
schema.users.drop!
end
endBuilt-in Validations
struct User
include CQL::ActiveRecord::Model(Int64)
db_context BlogDB, :users
# ... properties ...
# Comprehensive validation support
validate :name, presence: true, size: 2..50
validate :email, required: true, match: /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validate :age, gt: 0, lt: 120
validate :password_confirmation, confirmation: :password
validate :terms, accept: true
def initialize(@name : String, @email : String)
end
end
# Validate before saving
user = User.new(name: "Alice", email: "alice@example.com")
if user.valid?
user.save!
else
puts user.errors.messages
endWhy Choose CQL?
For High-Performance Applications
APIs serving high request volumes
Real-time applications requiring low latency
Data-intensive processing applications
Microservices architecture
For Enterprise Development
Large team collaboration with type safety
Long-term maintenance requirements
Complex business logic with data integrity
Compliance and audit requirements
For Modern Development
Type-safe development practices
DevOps and CI/CD pipeline integration
Container-based deployment strategies
Cloud-native architecture patterns
Complete Documentation
Getting Started
New to CQL?
Migrating?
Interactive Examples (crystal examples/run_examples.cr)
Core Features
Foundation
Active Record
Advanced
Quick Reference
I want to...
Go to...
Set up a new project
Build complex queries
Handle database changes
Deploy to production
Ready to Get Started?
# Try the interactive examples first
crystal examples/run_examples.cr
# Or install CQL and start building
shards installTry Interactive Examples → • Start with Installation →
Built with Crystal's performance and safety in mind.
All examples are tested with the latest CQL version.
Documentation • Examples • FAQ • Issues
Last updated
Was this helpful?