All Projects β†’ tizoc β†’ Ppx_pgsql

tizoc / Ppx_pgsql

Licence: bsd-3-clause
Syntax extension for embedded SQL queries using PG'OCaml.

Programming Languages

ocaml
1615 projects

Projects that are alternatives of or similar to Ppx pgsql

Sqlx
🧰 The Rust SQL Toolkit. An async, pure Rust SQL crate featuring compile-time checked queries without a DSL. Supports PostgreSQL, MySQL, SQLite, and MSSQL.
Stars: ✭ 5,039 (+9978%)
Mutual labels:  sql, postgres
Dat
Go Postgres Data Access Toolkit
Stars: ✭ 604 (+1108%)
Mutual labels:  sql, postgres
Gnorm
A database-first code generator for any language
Stars: ✭ 415 (+730%)
Mutual labels:  sql, postgres
Mongo Sql
An extensible SQL generation library for JavaScript with a focus on introspectibility
Stars: ✭ 314 (+528%)
Mutual labels:  sql, postgres
Scala Db Codegen
Scala code/boilerplate generator from a db schema
Stars: ✭ 49 (-2%)
Mutual labels:  sql, postgres
Zombodb
Making Postgres and Elasticsearch work together like it's 2021
Stars: ✭ 3,781 (+7462%)
Mutual labels:  sql, postgres
Citus
Distributed PostgreSQL as an extension
Stars: ✭ 5,580 (+11060%)
Mutual labels:  sql, postgres
Questdb
An open source SQL database designed to process time series data, faster
Stars: ✭ 7,544 (+14988%)
Mutual labels:  sql, postgres
Records
SQL for Humansβ„’
Stars: ✭ 6,761 (+13422%)
Mutual labels:  sql, postgres
Migrate
Database migrations. CLI and Golang library.
Stars: ✭ 7,712 (+15324%)
Mutual labels:  sql, postgres
Ansible Role Postgresql
Ansible Role - PostgreSQL
Stars: ✭ 310 (+520%)
Mutual labels:  sql, postgres
Node Pg Migrate
Node.js database migration management for Postgresql
Stars: ✭ 838 (+1576%)
Mutual labels:  sql, postgres
Loukoum
A simple SQL Query Builder
Stars: ✭ 305 (+510%)
Mutual labels:  sql, postgres
Jet
Type safe SQL builder with code generation and automatic query result data mapping
Stars: ✭ 373 (+646%)
Mutual labels:  sql, postgres
Requery
requery - modern SQL based query & persistence for Java / Kotlin / Android
Stars: ✭ 3,071 (+6042%)
Mutual labels:  sql, postgres
Beam
A type-safe, non-TH Haskell SQL library and ORM
Stars: ✭ 454 (+808%)
Mutual labels:  sql, postgres
Sql Lint
An SQL linter
Stars: ✭ 243 (+386%)
Mutual labels:  sql, postgres
Scenic
Scenic is maintained by Derek Prior, Caleb Hearth, and you, our contributors.
Stars: ✭ 2,856 (+5612%)
Mutual labels:  sql, postgres
Vscode Sqltools
Database management for VSCode
Stars: ✭ 741 (+1382%)
Mutual labels:  sql, postgres
Efcore.pg
Entity Framework Core provider for PostgreSQL
Stars: ✭ 838 (+1576%)
Mutual labels:  sql, postgres

ppx_pgsql

Syntax extension for embedded SQL queries using PG'OCaml.

How it works

Expressions of the form [%sqlf <sql string>] are validated and converted into a function that will execute the query. The generated function will take each named argument (denoted as names starting with the dollar symbol, e.g. $parameter_name) as a keyword argument with the same name, and a database handle as the last argument.

Example:

  let update_account =
    [%sqlf {|
      UPDATE accounts
         SET email = $email, account_type = $account_type
       WHERE account_id = $account_id
   RETURNING account_id, created_at, account_type, email
    |}]

The type of update_account is:

email:string ->
account_type:string ->
account_id:int64 ->
(string, bool) Hashtbl.t Pg_store_helpers.PGOCaml.t ->
(int64 * CalendarLib.Calendar.t * string * string) list
PGOCaml.monad

Named arguments syntax

To install

opam pin add ppx_pgsql -k git https://github.com/tizoc/ppx_pgsql.git

Some tips

Views and NULL-able heuristic

This rewriter tries its best to figure out which columns are NULL-able and which are not, but sometimes it fails to do so.

One case is with columns in views, which will be assumed to always be NULL-able.

To fix this, you can alter the view metadata contained in the pg_attribute table, and set attnotnull to true:

UPDATE pg_attribute SET attnotnull = 't'
 WHERE attrelid IN (
   SELECT oid FROM pg_class
    WHERE relname = 'name_of_view');

Outer joins, and using COALESCE

When performing joins, columns that on the original table are qualified as not NULL-able, may become NULL-able, this will make the heuristic fail.

One workaround is to create a view for such query, and then use the trick described above.

Another option it to use the COALESCE function to force the column to be NULL-able:

-- Given these tables
CREATE TABLE authors (id serial PRIMARY KEY, name varchar(255) NOT NULL);
INSERT INTO authors (id, name) VALUES (1, 'John Doe');
CREATE TABLE books (id serial PRIMARY KEY, title varchar(255) NOT NULL, author int NOT NULL REFERENCES authors(id) ON DELETE CASCADE);

-- This join could result in NULL values for books.title
SELECT
 authors.name,
 coalesce(books.title) -- inferred as NULL-able now
FROM authors
LEFT OUTER JOIN books ON books.author = authors.id

Credit to @NightBlues for coming up with this solution.

IN/NOT IN operator when using a possibly empty dynamic list of values

Using list expressions to build IN/NOT IN query expresions (IN [email protected] or NOT IN [email protected]) is not encouraged when the list of values is dynamic and has the potential of being empty.

The problem with doing so is that the list may be empty, resulting in an invalud query being generated (IN () and NOT IN () are not valid SQL). What is worse, this failure will happen at runtime. Additionaly, by doing so with lists of varying length, a new prepared statement will be created at runtime for each one of the lengths.

An alternative is to use the ANY and ALL operators with arrays:

-- This
SELECT COUNT(*) FROM users
WHERE id IN $@user_ids_list

-- Becomes
SELECT COUNT(*) FROM users
WHERE id = ANY($user_ids_list::int[])

-- And this
SELECT COUNT(*) FROM users
WHERE id NOT IN $@user_ids_list

-- Becomes
SELECT COUNT(*) FROM users
WHERE id <> ALL($user_ids_list::int[])

Another option is to use the unnest array function and an inner SELECT:

SELECT COUNT(*) FROM users
WHERE id IN (SELECT unnest($user_ids_list::int[]))

SELECT COUNT(*) FROM users
WHERE id NOT IN (SELECT unnest($user_ids_list::int[]))
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].