GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — GitHub - DaredevilOSS/sqlc-gen-ruby

BranchesTags
Open more actions menu

Latest commit

 

History

91 Commits
91 Commits

Folders and files

NameName
Last commit message
Last commit date
.github
.github
 
 
docs
docs
 
 
examples
examples
 
 
exe
exe
 
 
lib/sqlc_gen_ruby
lib/sqlc_gen_ruby
 
 
scripts
scripts
 
 
test
test
 
 
tests
tests
 
 
.env
.env
 
 
.gitattributes
.gitattributes
 
 
.gitignore
.gitignore
 
 
.rubocop.yml
.rubocop.yml
 
 
CLAUDE.md
CLAUDE.md
 
 
Dockerfile
Dockerfile
 
 
Gemfile
Gemfile
 
 
Gemfile.e2e
Gemfile.e2e
 
 
Gemfile.lock
Gemfile.lock
 
 
Gemfile.options.e2e
Gemfile.options.e2e
 
 
LICENSE
LICENSE
 
 
README.md
README.md
 
 
Rakefile
Rakefile
 
 
Steepfile
Steepfile
 
 
docker-compose.yml
docker-compose.yml
 
 
sqlc.ci.yaml
sqlc.ci.yaml
 
 
sqlc.local.yaml
sqlc.local.yaml
 
 
steep_expectations.yml
steep_expectations.yml
 
 

Repository files navigation

sqlc-gen-ruby

Write SQL. Get typed, idiomatic Ruby.
A sqlc plugin for PostgreSQL, MySQL and SQLite, with RBS signatures.

Build Tests


sqlc reads your schema and your queries and checks them against each other. This plugin turns the result into plain Ruby files: one method per query, one class per result row, and .rbs signatures for all of it. There is no ORM and no runtime library: the generated code only needs your database gem and connection_pool.

How it works

1. You write SQL

-- schema.sql
CREATE TABLE authors (
  id   BIGSERIAL PRIMARY KEY,
  name text NOT NULL,
  bio  text
);

-- query.sql
-- name: GetAuthor :one
-- Returns the author with the given id, or nil when there is none.
SELECT * FROM authors WHERE id = $1 LIMIT 1;

-- name: CreateAuthor :one
INSERT INTO authors (name, bio) VALUES ($1, $2) RETURNING *;

2. sqlc generate writes Ruby, and RBS to go with it (abridged)

# Returns the author with the given id, or nil when there is none.
def get_author(id:)
  ...
end
class GetAuthorRow
  attr_reader id: ::Integer
  attr_reader name: ::String
  attr_reader bio: ::String?
end

def get_author: (id: ::Integer) -> GetAuthorRow?
def get_author!: (id: ::Integer) -> GetAuthorRow

3. You call it

require_relative 'app/db/query_sql'

queries = PgCodegen::QuerySql.connect({ dbname: 'app', host: 'localhost' }, size: 5)   # a connection pool

author = queries.create_author(name: 'Seuss', bio: nil)   # => #<data PgCodegen::CreateAuthorRow id=1, name="Seuss", bio=nil>
queries.get_author(id: author.id)                          # the row, or nil
queries.get_author!(id: 42)                                # raises QuerySql::NotFound

queries.transaction do |tx|                                # COMMIT at the end, ROLLBACK if it raises
  tx.create_author(name: 'a', bio: nil)
end

The complete, committed output for every database is in examples/.

Install

The plugin is one WebAssembly file, so the only thing to install is sqlc. Add the plugin to sqlc.yaml; the URL and sha256 of every version are in its release notes:

version: "2"
plugins:
- name: ruby
  wasm:
    url: https://github.com/DaredevilOSS/sqlc-gen-ruby/releases/download/${RELEASE_TAG}/sqlc-gen-ruby.wasm
    sha256: ${RELEASE_SHA}
sql:
  - schema: "db/schema.sql"
    queries: "db/query.sql"
    engine: "postgresql"        # or "mysql" / "sqlite"
    codegen:
      - plugin: ruby
        out: app/db
        options:
          driver: pg            # or mysql2 / sqlite3

Then:

  1. run sqlc generate;
  2. add connection_pool and your driver gem (pg, mysql2 or sqlite3) to your Gemfile, or set generateGemfile: true and the plugin writes one;
  3. require_relative 'app/db/query_sql'.

What's supported

Ruby 3.1 – 4.0, with PostgreSQL (pg), MySQL (mysql2) and SQLite (sqlite3).

Queries

Every sqlc annotation works on all three databases. Details: Queries.

Annotation The method returns
:one the row or nil; a second method, get_author!, raises instead of returning nil
:many an Array of rows
:exec nil
:execrows the number of affected rows
:execlastid the new id
:execresult an ExecResult (rows_affected, last_insert_id)
:batchexec :batchone :batchmany runs the query once per element of an Array, on one connection
:copyfrom bulk insert, all rows or none: COPY (PostgreSQL), LOAD DATA (MySQL), multi-row INSERT (SQLite)
Macro What it does
sqlc.arg(name) names a parameter
sqlc.narg(name) names a nullable parameter, which defaults to nil
sqlc.slice(ids) IN (...) with an Array (MySQL, SQLite; on PostgreSQL use = ANY($1::bigint[]))
sqlc.embed(table) puts the table's model into the row

Types

Values are what the driver gem returns, so the Ruby type of a column depends on the database. Details and the full list: Types.

SQL PostgreSQL MySQL SQLite
integers Integer Integer Integer
real, double Float Float Float
numeric, decimal BigDecimal BigDecimal Float
text, binary String String String
boolean true / false Integer (0 / 1) Integer (0 / 1)
date Date Date String
timestamp, datetime Time Time String
JSON parsed Ruby objects String (JSON text) String (JSON text)
enums String + constants String + constants
arrays Array[T]
inet, cidr IPAddr

Nullable columns and parameters are T?. The declared type of any column can be changed with overrides.

At runtime

Transactions transaction commits or rolls back, nests with savepoints and takes an isolation level. More
Connections a connection_pool built for you, your own pool, or a connection shared with ActiveRecord / Sequel. More
Concurrency threads, forked workers (Puma, Sidekiq) and the Fiber scheduler (async). More
Failures timeouts, killed threads, lost connections and deadlocks never leave a connection inside a transaction. More
Logging pass logger: to log each query's name and duration; parameter values are never logged. More

Options

Set them under options: of the codegen entry. Details: Options.

Option Default What it does
driver required pg, mysql2 or sqlite3; must match the sqlc engine:
rubyVersion 3.3 the oldest Ruby the code must run on (3.1 – 4.0)
generateTypes true also generate .rbs signatures
generateGemfile false also generate a Gemfile
moduleName <Driver>Codegen the module the code lives in, e.g. MyApp::Db
overrides none change the declared Ruby type of columns and parameters
rename none rename tables and columns, e.g. {authors: Writer, bio: biography}
exactTableNames false name the model Authors instead of the singular Author
preparedStatements true pg only; set false behind pgbouncer in transaction mode

Documentation

Using the plugin

Generated code the files, classes and methods you get, and how they are named
Queries annotations, :copyfrom, macros, arguments
Types the Ruby type of every SQL type, time zones, enums
Connections pools, shared connections, forked workers, fibers
Transactions commit and rollback, savepoints, isolation, what happens on errors
Options every option, overrides
Troubleshooting known errors and surprises per database, with their fixes
Examples schemas, queries and generated output for each database

Working on the plugin

Contributing setup, commands, pull requests
Architecture how the generator works and how it is packed into WebAssembly
Testing test layers, CI, what to run before pushing
Coverage every documented behavior and the test that proves it
Releasing the release workflow and versioning

About

No description, website, or topics provided.

Resources

Readme
MIT license

Contributing

Contributing
Activity
Custom properties

Stars

11 stars

Watchers

2 watching

Forks

1 fork
Report repository

Releases

Packages

Used by

Contributors

Languages

You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.