class
CQL::Schema
- CQL::Schema
- Reference
- Object
Overview
The Schema class represents a database schema.
This class provides methods to build and manage a database schema, including creating tables, executing SQL statements, and generating queries.
Example Creating a new schema
AcmeDB = CQL::Schema.define(:acme_db, adapter: CQL::Adapter::SQLite, uri: "sqlite3://./db/acme.db") do
table :users do
primary :id, Int64, auto_increment: true
column :name, String
column :email, String
end
end
Example Executing a SQL statement
schema.exec("CREATE TABLE products (id INTEGER PRIMARY KEY, name TEXT)")
Example Creating a new query
query = schema.query
Included Modules
Defined in:
schema.crConstant Summary
-
Log =
CQL.config.logger
Constructors
-
.new(name : Symbol, uri : String, adapter : Adapter, version : String = "1.0", quote_identifiers : Bool = false, source : ConnectionSource | Nil = nil)
Initializes a new schema.
Class Method Summary
-
.define(name : Symbol, uri : String, adapter : Adapter, version : String = "1.0", quote_identifiers : Bool = false, source : ConnectionSource | Nil = nil, &)
Builds a new schema.
Macro Summary
Instance Method Summary
-
#adapter : Adapter
- @return [Adapter] the database adapter (default:
Adapter::SQLite)
- @return [Adapter] the database adapter (default:
-
#alter(table_name : Symbol, &)
Alter a table in the schema.
-
#build
Builds the schema.
-
#close : Nil
Closes the connection source (the pool); later statements fail.
-
#ddl_transaction(&)
Runs schema changes atomically where DDL is transactional (a SAVEPOINT inside an open transaction); where DDL commits implicitly, runs them bare and refuses inside an open transaction.
-
#delete
Creates a new delete query for the schema.
- #dialect
-
#exec(sql : String)
Executes a SQL statement.
- #exec_query(& : DB::Connection -> _)
-
#gen : Expression::Generator
Returns a generator for SQL expression building.
DEPRECATED Use new_generator for thread-safe SQL generation
-
#insert
Creates a new insert query for the schema.
-
#migrator(config : MigratorConfig)
Creates a new migrator with custom configuration for schema synchronization.
-
#migrator
Creates a new migrator for the schema.
-
#name : Symbol
- @return [Symbol] the name of the schema
-
#new_generator : Expression::Generator
Creates a new expression generator for thread-safe SQL generation.
-
#pool_stats : PoolStats
Connection pool occupancy, read without checking out a connection.
-
#query
Creates a new query for the schema.
-
#quote_identifiers : Bool
- @return [Bool] whether generated SQL quotes table, column and alias names (opt-in; needed for reserved words such as
orderorgroup).
- @return [Bool] whether generated SQL quotes table, column and alias names (opt-in; needed for reserved words such as
-
#schema_dumper
Creates a schema dumper for this schema.
-
#source : ConnectionSource
- @return [ConnectionSource] where connections and transactions come from: crystal-db's pool by default, or any other source (e.g.
-
#table(name : Symbol, as as_name : Symbol | Nil = nil, &)
Declares a table in the schema;
Table#create!orSchema#buildcreates it in the database. - #table(name : Symbol, as as_name : String | Nil = nil, &)
-
#tables : Hash(Symbol, Table)
- @return [Hash(Symbol, Table)] the tables in the schema
- #transaction(tx : DB::Transaction, &)
-
#transaction(&)
Executes a block within a database transaction.
-
#update
Creates a new update query for the schema.
-
#uri : String
- @return [String] the URI of the database: the string given, or for a schema with a
source:the crystal-db-safe form of it (ConnectionSource#database_uri, e.g.
- @return [String] the URI of the database: the string given, or for a schema with a
-
#version : String
- @return [String] the version of the schema
-
#with_connection(&)
Yields the fiber's transaction connection, or else one pooled connection, to pin statements to it with
using(connection)(e.g.
Instance methods inherited from module CQL::Executor
adapter : Adapter
adapter,
exec_query(& : DB::Connection -> _)
exec_query
Constructor Detail
Initializes a new schema.
- @param name [Symbol] the name of the schema
- @param uri [String] the URI of the database
- @param adapter [Adapter] the database adapter
- @param version [String] the version of the schema (default: "1.0")
Example Initializing a new schema
schema = CQL::Schema.new(:acme_db, "sqlite3://./db/acme.db", CQL::Adapter::SQLite)
Example Running on the native PostgreSQL engine's pool
engine = CQL::Postgres::AsyncEngine.connect("postgres://app@db/app?pool_size=10")
schema = CQL::Schema.new(:app, "postgres://app@db/app", CQL::Adapter::Postgres,
source: CQL::Postgres::EngineSource.new(engine))
Class Method Detail
Builds a new schema.
- @param name [Symbol] the name of the schema
- @param uri [String] the URI of the database
- @param adapter [Adapter] the database adapter
- @param version [String] the version of the schema (default: "1.0")
- @param quote_identifiers [Bool] whether generated SQL quotes identifiers (default: false)
- @param source [ConnectionSource] where connections come from (default: crystal-db's pool opened from the URI)
- @yield the block runs with the schema as its receiver, so
#tabledeclares a table - @return [Schema] the built schema
Example
AcmeDB = CQL::Schema.define(:acme_db, adapter: CQL::Adapter::SQLite, uri: "sqlite3://./db/acme.db") do
table :users do
primary :id, Int64, auto_increment: true
column :name, String
column :email, String
end
end
Macro Detail
Instance Method Detail
- @return [Adapter] the database adapter (default:
Adapter::SQLite)
Alter a table in the schema.
- @param table_name [Symbol] the name of the table
- @yield the block runs with an
AlterTableas its receiver Example
schema.alter :users do
add_column :phone, String
end
Example
schema.alter :users do
drop_column :age
end
Where DDL is transactional, a rollback of the surrounding transaction also restores the table's declaration.
The restore puts back the whole declaration as it was before this #alter, so it also undoes another fiber's
uncommitted #alter of the same table.
Runs schema changes atomically where DDL is transactional (a SAVEPOINT inside an open transaction); where DDL commits implicitly, runs them bare and refuses inside an open transaction.
Creates a new delete query for the schema.
- @return [Delete] the new delete query Example
delete = schema.delete
Executes a SQL statement.
- @param sql [String] the SQL statement to execute
Example
schema.exec("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)")
Returns a generator for SQL expression building.
DEPRECATED: Use #new_generator instead for thread-safe SQL generation.
This method creates a new generator each time to prevent concurrent access issues.
DEPRECATED Use new_generator for thread-safe SQL generation
Creates a new insert query for the schema.
- @return [Insert] the new insert query Example
insert = schema.insert
Creates a new migrator with custom configuration for schema synchronization.
- @param config [MigratorConfig] the configuration for the migrator
- @return [Migrator] the new migrator with custom config Example
config = CQL::MigratorConfig.new(
schema_file_path: "src/schemas/my_app_schema.cr",
schema_name: :MyAppSchema,
schema_symbol: :my_app_schema
)
migrator = schema.migrator(config)
Creates a new migrator for the schema.
- @return [Migrator] the new migrator Example
migrator = schema.migrator
Creates a new expression generator for thread-safe SQL generation. Each call returns a fresh Generator instance to avoid state corruption when multiple fibers generate SQL concurrently.
- @return [Expression::Generator] a new generator instance
Example
gen = schema.new_generator
sql, params = schema.query.from(:users).to_sql(gen)
Connection pool occupancy, read without checking out a connection.
All zeros before the first query when the pool was opened with initial_pool_size=0.
Creates a new query for the schema.
- @return [Query] the new query
Example
query = schema.query
- @return [Bool] whether generated SQL quotes table, column and alias
names (opt-in; needed for reserved words such as
orderorgroup). Applies to queries and DML (SELECT/INSERT/UPDATE/DELETE); DDL emitted by#build, migrations and#alteris not quoted yet, so create such tables with raw SQL or a quoted migration.
Creates a schema dumper for this schema.
- @return [SchemaDump] the new schema dumper Example
dumper = schema.schema_dumper
- @return [ConnectionSource] where connections and transactions come from:
crystal-db's pool by default, or any other source (e.g.
Postgres::EngineSource)
Declares a table in the schema; Table#create! or Schema#build creates it in the database.
- @param name [Symbol] the name of the table
- @param as [Symbol, String, nil] the alias of the table
- @yield the block runs with the table as its receiver
- @return [Table] the declared table Example
schema.table :tags do
primary :id, Int64, auto_increment: true
column :name, String
end
- @return [Hash(Symbol, Table)] the tables in the schema
Executes a block within a database transaction.
- @yield [DB::Transaction] the transaction object
- @return [Nil] the result of the block Example
schema.transaction do |tx|
cnn = tx.connection
cnn.exec("INSERT INTO users (name) VALUES (?)", "John")
cnn.exec("UPDATE accounts SET balance = balance - 100 WHERE user_id = ?", 1)
end
Called inside another transaction on the same fiber, it runs as a SAVEPOINT on that transaction's connection.
Publishes Telemetry::TransactionEvents to Telemetry.subscribe_transactions
subscribers. A manual tx.rollback followed by a normal return still
reports Commit, since CQL cannot see it.
When the transaction rolls back (the block raises, including DB::Rollback,
or the commit fails), table declarations changed by #alter inside it are
restored. A savepoint that commits leaves them to the enclosing transaction.
A manual tx.rollback restores nothing, for the same reason as above.
Creates a new update query for the schema.
- @return [Update] the new update query Example
update = schema.update
- @return [String] the URI of the database: the string given, or for a schema with a
source:the crystal-db-safe form of it (ConnectionSource#database_uri, e.g. without the engine's pool options)
Yields the fiber's transaction connection, or else one pooled connection, to pin statements to it with using(connection)
(e.g. inside a transaction started on that connection).