module Lustra::SQL

Overview

Lustra::SQL

Lustra is made like an onion:

+------------------------------------+
|          THE ORM STACK             +
+------------------------------------+
|  Model | DB Views |  Migrations    | < High Level Tools
+---------------+--------------------+
|  Columns | Validation | Converters | < Mapping system
+---------------+--------------------+
|  Lustra::SQL  | Lustra::Expression | < Low Level SQL Builder
+------------------------------------+
|  Crystal DB   |    Crystal PG      | < Low Level connection
+------------------------------------+

On the bottom stack, Lustra offer SQL query building. Theses features are then used by top level parts of the engine.

The SQL module provide a simple API to generate #delete, #insert, #select and #update methods.

Each requests can be duplicated then modified and executed.

Note: Each request object is mutable. Therefore, to update and store a request, you must use manually the dup method.

Included Modules

Extended Modules

Defined in:

lustra/sql/connection_pool.cr
lustra/sql/errors.cr
lustra/sql/fragment/column.cr
lustra/sql/fragment/fragment.cr
lustra/sql/fragment/from.cr
lustra/sql/fragment/join.cr
lustra/sql/lock.cr
lustra/sql/query/connection.cr
lustra/sql/query/from.cr
lustra/sql/sql.cr
lustra/sql/truncate.cr

Class Method Summary

Instance Method Summary

Instance methods inherited from module Lustra::SQL::Transaction

after_commit(connection : String = "default", &block : DB::Connection -> Nil) after_commit, in_transaction?(connection : String = "default") in_transaction?, rollback(to = nil) rollback, rollback_transaction rollback_transaction, transaction(connection : String = "default", level : Level = Level::Serializable, &) transaction, with_savepoint(sp_name : Symbolic | Nil = nil, connection_name : String = "default", &) with_savepoint

Instance methods inherited from module Lustra::SQL::Logger

log_query(sql, &) log_query

Class methods inherited from module Lustra::SQL::Logger

colorize=(colorize : Bool) colorize=, colorize? : Bool colorize?, colorize_query(qry : String) colorize_query, display_mn_sec(x) : String display_mn_sec, display_time(x) : String display_time

Class Method Detail

def self.lock(table : String | Symbol, mode = "ACCESS EXCLUSIVE", connection = "default", &) #

Lock completetly a table.

Lustra::SQL.lock("my_table") do
end

Optional parameter mode allow you to decide over the lock level Modes are:

  • ACCESS EXCLUSIVE (default)
  • ACCESS SHARE
  • ROW SHARE
  • ROW EXCLUSIVE
  • SHARE UPDATE EXCLUSIVE
  • SHARE
  • SHARE ROW EXCLUSIVE
  • EXCLUSIVE

See Official PG documentation for more informations


[View source]
def self.truncate(tablename : Lustra::Model.class | String | Symbol, restart_sequence : Bool = false, cascade : Bool = false, truncate_inherited : Bool = true, connection_name : String = "default") forall T #

Truncate a table or a model

User.query.count           # => 200
Lustra::SQL.truncate(User) # equivalent to Lustra::SQL.truncate(User.table, connection_name: User.connection)
User.query.count           # => 0

SEE https://www.postgresql.org/docs/current/sql-truncate.html for more information.

  • restart_sequence set to true will append RESTART IDENTITY to the query
  • cascade set to true will append CASCADE to the query
  • truncate_inherited set to false will append ONLY to the query
  • connection_name will be: Model.connection or default unless optionally defined.

[View source]

Instance Method Detail

def add_connection(name : String, url : String) #

[View source]
def delete(table : Symbolic) #

Start a DELETE table query


[View source]
def escape(x : String | Symbol) #

Escape the expression, double quoting it.

It allows use of reserved keywords as table or column name

NOTE Escape is used for escaping postgresql keyword. For example if you have a column named order (which is a reserved word), you want to escape it by double-quoting it.

For escaping STRING value, please use Lustra::SQL.sanitize


[View source]
def execute(connection_name : String, sql) #

Execute a SQL statement on a specific connection.

Usage: Lustra::SQL.execute("seconddatabase", "SELECT 1 FROM users")


[View source]
def execute(sql) #

Execute a SQL statement.

Usage: Lustra::SQL.execute("SELECT 1 FROM users")


[View source]
def init(name : String, url : String) #

[View source]
def init(url : String) #

[View source]
def init(connections : Hash(Symbolic, String)) #

[View source]
def insert(table, args : NamedTuple) #

[View source]
def insert(table, *args) #

Alias of #insert_into, for hurry developers


[View source]
def insert #

Create a new INSERT query


[View source]
def insert_into(table : Symbolic) #

Prepare a new INSERT INTO table query :ditto:


[View source]
def insert_into(table : Symbolic, *args) #

Start an INSERT INTO table query

Lustra::SQL.insert_into("table", {id: 1, name: "hello"}, {id: 2, name: "World"})

[View source]
def raw(x, *params) #

This provide a fast way to create SQL fragment while escaping items, both with ? and :key system:

query = Model.query.select(Lustra::SQL.raw("CASE WHEN x=:x THEN 1 ELSE 0 END AS check", x: "blabla"))
query = Model.query.select(Lustra::SQL.raw("CASE WHEN x=? THEN 1 ELSE 0 END AS check", "blabla"))

[View source]
def raw(__template, **params) #

[View source]
def raw_enum(x, params : Enumerable(T)) forall T #

See self.raw Can pass an array to this version


[View source]
def rollback #

Raise a rollback, in case of transaction


[View source]
def sanitize(x) #

Sanitize string and convert some literals (e.g. Time)


[View source]
def select(*args) #

Start a SELECT FROM table query


[View source]
def unsafe(x) #

[View source]
def update(table) #

Start a UPDATE table query


[View source]
def with_savepoint(connection_name = "default", &) #

Create a transaction, but this one is stackable using savepoints.

Example:

Lustra::SQL.with_savepoint do
  # do something
  Lustra::SQL.with_savepoint do
    rollback # < Rollback only the last `with_savepoint` block
  end
end

[View source]