All Projects → nikita-volkov → Hasql Th

nikita-volkov / Hasql Th

Licence: mit
Template Haskell utilities for Hasql

Programming Languages

haskell
3896 projects

Projects that are alternatives of or similar to Hasql Th

Pgcenter
Command-line admin tool for observing and troubleshooting Postgres.
Stars: ✭ 1,217 (+1298.85%)
Mutual labels:  postgresql
Open Bank Mark
A bank simulation application using mainly Clojure, which can be used to end-to-end test and show some graphs.
Stars: ✭ 81 (-6.9%)
Mutual labels:  postgresql
Gonymizer
Gonymizer: A Tool to Anonymize Sensitive PostgreSQL Data Tables for Use in QA and Testing
Stars: ✭ 85 (-2.3%)
Mutual labels:  postgresql
Deno crud jwt
🦕 basic jwt implementation with CRUD operations using deno + postgres
Stars: ✭ 80 (-8.05%)
Mutual labels:  postgresql
Bug Tracker Pern Ts
Bug Tracking app with project members support. Made with PERN stack + TypeScript.
Stars: ✭ 79 (-9.2%)
Mutual labels:  postgresql
Twist V2
A book review tool for Leanpub's Markdown Book Format
Stars: ✭ 82 (-5.75%)
Mutual labels:  postgresql
Repmgr
A lightweight replication manager for PostgreSQL (Postgres) - latest version 5.2.1 (2020-12-07)
Stars: ✭ 1,207 (+1287.36%)
Mutual labels:  postgresql
Pgbouncer
lightweight connection pooler for PostgreSQL
Stars: ✭ 1,263 (+1351.72%)
Mutual labels:  postgresql
Pg Anonymizer
Dump anonymized PostgreSQL database with a NodeJS CLI
Stars: ✭ 83 (-4.6%)
Mutual labels:  postgresql
Xeus Sql
xeus-sql is a Jupyter kernel for general SQL implementations.
Stars: ✭ 85 (-2.3%)
Mutual labels:  postgresql
Agent
The best way to backup and restore your database
Stars: ✭ 80 (-8.05%)
Mutual labels:  postgresql
Pg activity
pg_activity is a top like application for PostgreSQL server activity monitoring.
Stars: ✭ 1,232 (+1316.09%)
Mutual labels:  postgresql
Pypi Server
Tornado based server like pypi.python.org. With caching from pypi.
Stars: ✭ 83 (-4.6%)
Mutual labels:  postgresql
Charon
Authorization and authentication service.
Stars: ✭ 79 (-9.2%)
Mutual labels:  postgresql
Testgres
Testing framework for PostgreSQL and its extensions
Stars: ✭ 85 (-2.3%)
Mutual labels:  postgresql
Suricatta
High level sql toolkit for clojure (backed by jooq library)
Stars: ✭ 77 (-11.49%)
Mutual labels:  postgresql
Chloe
A lightweight and high-performance Object/Relational Mapping(ORM) library for .NET --C#
Stars: ✭ 1,248 (+1334.48%)
Mutual labels:  postgresql
Electrocrud
Database CRUD Application Built on Electron | MySQL, Postgres, SQLite
Stars: ✭ 1,267 (+1356.32%)
Mutual labels:  postgresql
Graphjin
GraphJin - Build APIs in 5 minutes with GraphQL. An instant GraphQL to SQL compiler.
Stars: ✭ 1,264 (+1352.87%)
Mutual labels:  postgresql
Gopherus
This tool generates gopher link for exploiting SSRF and gaining RCE in various servers
Stars: ✭ 1,258 (+1345.98%)
Mutual labels:  postgresql

Summary

An extension library for the "hasql" Postgres driver, bringing compile-time syntax checking of queries atop of a great simplification of declaration of statements. All the user needs to do is just specify SQL.

Here's a brief example of how it works:

selectUserDetails :: Statement Int32 (Maybe (Text, Text, Maybe Text))
selectUserDetails =
  [maybeStatement|
    select name :: text, email :: text, phone :: text?
    from "user"
    where id = $1 :: int4
    |]

As you can see, it completely eliminates the need to deal with codecs. The quasiquoters directly produce Statement, which you can then dimap over using its Profunctor instance to get to your domain types.

Examples of mapping to custom types
newtype UserId = UserId Int32

data UserDetails = UserDetails {
  _name :: Text,
  _email :: Text,
  _phone :: Maybe Text
}

selectUserDetails :: Statement UserId (Maybe UserDetails)
selectUserDetails =
  dimap
    (\ (UserId a) -> a)
    (\ case
      Just (a, b, c) -> Just (UserDetails a b c)
      Nothing -> Nothing)
    [maybeStatement|
      select name :: text, email :: text, phone :: text?
      from "user"
      where id = $1 :: int4
      |]

Using some Haskell's advanced techniques and the "tuple" library we can reduce the boilerplate in the previous definition:

import Data.Tuple.Curry -- from the "tuple" library

selectUserDetails :: Statement UserId (Maybe UserDetails)
selectUserDetails =
  dimap coerce (fmap (uncurryN UserDetails))
    [maybeStatement|
      select name :: text, email :: text, phone :: text?
      from "user"
      where id = $1 :: int4
      |]

Status

The library supports almost all of Postgresql syntax available for preparable statements. This includes Select, Insert, Update and Delete among others. The only thing that is not supported yet is some of its very rarely used XML-related features.

Quality

Build Status

The parser and renderer get heavily tested using the following property: rendering a random AST then parsing it should produce the same AST. This pretty much covers most possible reasons for bugs in the library.

Implementation

This library internally implements a port of the original Postgres SQL syntax parser. It might sound like an overkill, but there really were no better options.

Unfortunately Postgres doesn't export it's own parser in any of its distributions, so there's no C-library to link to and wrap.

Isolating the original C-code and including it in a Haskell project is also not an option, because it's heavily based on code generators and complex make-file instructions. Maintaining such a codebase also seems like a non-viable option.

Fortunately the original parser is implemented using a declarative notation (the one which the mentioned code generators work with). It being declarative makes the process of porting to Haskell quite straight-forward.

Also for the purposes of this library we need access to the full syntax tree for extracting data on placeholders and statement results. Quick and dirty hacks won't do.

For these reasons it's been decided to port the original parser and AST as close as possible to Haskell using the "megaparsec" library.

Error messages

The parser turns out to be actually better than the one in Postgres in terms of error-reporting. That's because of Haskell's superabilities in the area of parsing compared to C. The library uses the "megaparsec" library and the "headed-megaparsec" extension for it. As the result of that, the error messages produced by this parser are more informative than the ones in Postgres. Following are a few examples.

Error example 1

Consider the following broken statement:

select 1 from a where b >= 3 && b < 4

It is incorrect, because it uses && instead of and. But here's what Postgres' original parser says about it:

ERROR:  syntax error at or near "<"
LINE 1: select 1 from a where b >= 3 && b < 4;
                                          ^

Here's what "hasql-th" says:

  |
2 |     select 1 from a where b >= 3 && b < 4;
  |                                  ^
unexpected '&'

Error example 2

It's not obvious what is wrong in the following statement either:

insert into user (name) values ($1)

The Postgres parser doesn't help much:

ERROR:  syntax error at or near "user"
LINE 1: insert into user (name) values ($1);
                    ^

Here's what "hasql-th" says though:

  |
2 |       insert into user (name) values ($1)
  |                       ^
Reserved keyword "user" used as an identifier. If that's what you intend, you have to wrap it in double quotes.

Error example 3

It turns out that the original Postgres parser never produces any other messages than the opaque "syntax error at or near". "hasql-th" on the other hand is quite descriptive. E.g., here's how it gradually guides to insert the missing expected pieces.

Input:

[resultlessStatement|insert into |]

Error:

  |
1 | insert into 
  |             ^
unexpected end of input
expecting identifier or white space

Input:

[resultlessStatement|insert into a |]

Error:

  |
1 | insert into a 
  |               ^
unexpected end of input
expecting "default", "overriding", "select", "values", '(', white space, or with clause
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].