module DB
Overview
The DB module is a unified interface to database access. Database dialects is supported by custom database driver shards. Check crystal-lang/crystal-sqlite3 for example.
Drivers implementors check Driver
class.
DB manage a connection pool. The connection pool can be configured by URI
query. See Database
.
Usage
Assuming crystal-sqlite3
is included a sqlite3 database can be opened with #open
.
db = DB.open "sqlite3:./path/to/db/file.db"
db.close
If a block is given to #open
the database is closed automatically
DB.open "sqlite3:./file.db" do |db|
# work with db
end # db is closed
In the code above db
is a Database
. Methods available for querying it are described in QueryMethods
.
Three kind of statements can be performed:
Database#exec
waits no response from the database.Database#scalar
reads a single value of the response.Database#query
returns a ResultSet that allows iteration over the rows in the response and column information.
All of the above methods allows parametrised query. Either positional or named arguments.
Check a full working version:
require "db"
require "sqlite3"
DB.open "sqlite3:./file.db" do |db|
db.exec "create table contacts (name string, age integer)"
db.exec "insert into contacts values (?, ?)", "John Doe", 30
args = [] of DB::Any
args << "Sarah"
args << 33
db.exec "insert into contacts values (?, ?)", args
puts "max age:"
puts db.scalar "select max(age) from contacts" # => 33
puts "contacts:"
db.query "select name, age from contacts order by age desc" do |rs|
puts "#{rs.column_name(0)} (#{rs.column_name(1)})"
# => name (age)
rs.each do
puts "#{rs.read(String)} (#{rs.read(Int32)})"
# => Sarah (33)
# => John Doe (30)
end
end
end
Defined in:
db.crdb/pool.cr
db/string_key_cache.cr
db/query_methods.cr
db/session_methods.cr
db/disposable.cr
db/driver.cr
db/statement.cr
db/begin_transaction.cr
db/connection_context.cr
db/connection.cr
db/transaction.cr
db/pool_statement.cr
db/database.cr
db/pool_prepared_statement.cr
db/pool_unprepared_statement.cr
db/result_set.cr
db/error.cr
db/mapping.cr
db/version.cr
Constant Summary
-
TYPES =
[Nil, String, Bool, Int32, Int64, Float32, Float64, Time, Bytes]
-
Types supported to interface with database driver. These can be used in any
ResultSet#read
or anyDatabase#query
related method to be used as query parameters -
VERSION =
"0.4.0"
Class Method Summary
-
.connect(uri : URI | String)
Opens a connection using the specified uri.
-
.connect(uri : URI | String, &block)
Opens a connection using the specified uri.
-
.open(uri : URI | String)
Opens a database using the specified uri.
-
.open(uri : URI | String, &block)
Same as
#open
but the database is yielded and closed automatically. -
.register_driver(driver_name, driver_class : Driver.class)
Registers a driver class for a given driver_name.
Macro Summary
-
mapping(properties, strict = true)
The
DB.mapping
macro defines how an object is built from a DB::ResultSet. - mapping
Class Method Detail
Opens a connection using the specified uri.
The scheme of the uri determines the driver to use.
Returned connection must be closed by Connection#close
.
If a block is used the connection is yielded and closed automatically.
Opens a connection using the specified uri.
The scheme of the uri determines the driver to use.
Returned connection must be closed by Connection#close
.
If a block is used the connection is yielded and closed automatically.
Opens a database using the specified uri.
The scheme of the uri determines the driver to use.
Returned database must be closed by Database#close
.
If a block is used the database is yielded and closed automatically.
Same as #open
but the database is yielded and closed automatically.
Registers a driver class for a given driver_name. Should be called by drivers implementors only.
Macro Detail
The DB.mapping
macro defines how an object is built from a DB::ResultSet.
It takes hash literal as argument, in which attributes and types are defined.
Once defined, DB::ResultSet#read(t)
populates properties of the class from the
result set.
require "db"
class Employee
DB.mapping({
title: String,
name: String,
})
end
employees = Employee.from_rs(db.query("SELECT title, name FROM employees"))
employees[0].title # => "Manager"
employees[0].name # => "John"
Attributes not mapped with DB.mapping
are not defined as properties.
Also, missing attributes raise a DB::Exception
.
You can also define attributes for each property.
class Employee
DB.mapping({
title: String,
name: {
type: String,
nilable: true,
key: "firstname",
},
})
end
Available attributes:
- type (required) defines its type. In the example above, title: String is a shortcut to title: {type: String}.
- nilable defines if a property can be a
Nil
. - default: value to use if the property is missing in the result set, or if it's
null
andnilable
was not set totrue
. If the default value creates a new instance of an object (for example[1, 2, 3]
orSomeObject.new
), a different instance will be used each time a row is parsed. - key defines which column to read from a reusltset. It defaults to the name of the property.
- converter takes an alternate type for parsing. It requires a
#from_rs
method in that class, and returns an instance of the given type.
The mapping also automatically defines Crystal properties (getters and setters) for each of the keys. It doesn't define a constructor accepting those arguments, but you can provide an overload.
The macro basically defines a constructor accepting a DB::ResultSet
that reads from
it and initializes this type's instance variables.
This macro also declares instance variables of the types given in the mapping.