What sqlc generate writes, and how the classes, methods and attributes are named.
The real output for every database is in Examples.
| File | Contents |
|---|---|
query_sql.rb |
one per query file: the QuerySql class (one method per query) and the row classes of its queries. The names follow the file: admin_users.sql → AdminUsersSql in admin_users_sql.rb |
models.rb |
one class per table, one module of constants per enum |
connection.rb |
helpers the query classes share |
*.rbs |
signatures for each of the above (unless generateTypes: false) |
Gemfile |
the gems the code needs (only with generateGemfile: true) |
Everything lives in one module: PgCodegen, Mysql2Codegen or Sqlite3Codegen, or the
moduleName you set.
queries = PgCodegen::QuerySql.connect({ dbname: 'app' }, size: 5) # see Connections
queries.get_author(id: 1) # => #<data PgCodegen::GetAuthorRow ...> or nil
queries.get_author!(id: 1) # raises PgCodegen::QuerySql::NotFound instead of returning nil
queries.list_authors # => [#<data PgCodegen::ListAuthorsRow ...>, ...]- One method per query, named after it in snake_case. What it returns depends on the query's annotation: see Queries.
- Arguments are keywords: see Arguments.
- Every
:onequery also gets a bang method (get_author!) that raisesQuerySql::NotFoundwhen there is no row. transaction,connectandneware described in Transactions and Connections.
A query returns <Query>Row objects (GetAuthorRow); sqlc.embed and models.rb use one class per table (Author).
rubyVersion |
Rows are | |
|---|---|---|
| 3.2 and later | Data |
frozen; with and to_h |
| below 3.2 | keyword Struct |
mutable |
Both support pattern matching:
case queries.get_author(id: 1)
in { id:, name: } then puts "#{id}: #{name}"
in nil then puts 'no such author'
endMethods and arguments
- Query names and parameters are snake_cased, with acronyms kept together (
MIN_ID→min_id,HTTPServer→http_server). - A Ruby keyword gets a trailing
_as an argument (end_:). - A parameter used twice is one keyword when it is named with
sqlc.arg; repeated?/$nof one column becomeid:,id_2:. - A query whose name would replace a generated method (
Transaction,Initialize, ...) is a generation error.
Row attributes
- An attribute has the column's name as sqlc reports it: PostgreSQL and SQLite keep
"camelCase"ascamelCase, MySQL reportscamelcase. - A result column without a usable name (
SELECT 1, now()) is named by its position:column_1,column_2, ... - A name that would replace a method of the row gets a trailing
_(class_,hash_,initialize_).Structrows have more methods thanDatarows, so a columncountiscountfromrubyVersion3.2 andcount_below: check the generated.rbswhen you changerubyVersion. - Keywords are fine as attributes: a column
endis the attributeend, but the argumentend_:.
Models
- A table's model is its singular name (
authors→Author). A tableauthorsnext to a tableauthorkeeps the plural (Authors). Change this withrenameorexactTableNames. - A model may have the name of a Ruby or driver constant (tables
exceptions,data,threads,sets, ...). The generated code refers to the originals as::Exception,::Data,::Thread, ..., so the models never shadow them. - SQLite: sqlc before 1.30 reports a quoted table name with its quotes, so
CREATE TABLE "Items"gives the modelItemsthere andItemfrom sqlc 1.30 on. UserenameorexactTableNamesto keep the name when you upgrade sqlc.
Enum constants are described in Types.
Pass a logger (anything with #debug) and every query and transaction is logged at debug level with its name and
duration, for example PgCodegen::QuerySql#get_author (0.4ms):
PgCodegen::QuerySql.connect(params, logger: Rails.logger)
PgCodegen::QuerySql.new(pool, logger: Rails.logger)Parameter values are never logged.
- The SQL of each query is a frozen heredoc constant (
GET_AUTHOR_SQL). - A comment above a query becomes the doc comment of its method. Table, column and enum comments of the schema become doc comments of the models.
- RuboCop: the code is RuboCop-clean. Where a name from your schema breaks a naming rule (
"UserId",naïve), that class or method gets arubocop:disable. Query names such asHasAuthors/IsActivekeep their name (has_authors), withNaming/PredicatePrefixdisabled. - Steep: the
.rbsfiles type-check with Steep. Add the standard libraries the code uses to yourSteepfile:library "monitor"for SQLite, andlibrary "timeout"for arubyVersionbelow 3.3. This repository'sSteepfileshows the full list for all three drivers.