• Stars
    star
    105
  • Rank 328,322 (Top 7 %)
  • Language
    Haskell
  • License
    MIT License
  • Created almost 9 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Template Haskell utilities for Hasql

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

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

More Repositories

1

hasql

The fastest PostgreSQL libpq-based driver for Haskell
Haskell
489
star
2

record

Anonymous records
Haskell
243
star
3

refined

Refinement types with static checking
Haskell
179
star
4

strelka

A simple, flexible and composable web-router
Haskell
85
star
5

jsonifier

Fast and simple JSON encoding toolkit
Haskell
83
star
6

install-to-project-repo

A script for installing jars to an in-project Maven repository
Python
79
star
7

stm-containers

Containers for STM
Haskell
62
star
8

graph-db

An experimental native Haskell graph database
Haskell
58
star
9

typeclasses

Explicit typeclasses for Elm
Elm
54
star
10

neat-interpolation

A quasiquoter for neat and simple multiline text interpolation
Haskell
53
star
11

domain

Focused domain model declaration toolkit for Haskell
Haskell
47
star
12

sext

A small extensions library for Scala
Scala
37
star
13

compound-types

Sum and Product types and such
Haskell
28
star
14

base-prelude

The most complete prelude formed only from the "base" package
Haskell
27
star
15

rebase

A more progressive alternative to the "base" package
Haskell
26
star
16

slave-thread

A principal solution to ghost threads and silent exceptions
Haskell
23
star
17

hasql-postgres

[Deprecated] A "PostgreSQL" driver for the "hasql" library
Haskell
19
star
18

postgresql-binary

Encoders and decoders for the PostgreSQL's binary format
Haskell
19
star
19

hasql-tutorial1

Tutorial on organisation of Hasql code in a Postgres-integration layer
Haskell
17
star
20

bytestring-tree-builder

A very efficient ByteString builder implementation based on the binary tree
Haskell
17
star
21

rerebase

Reexports from "base" with a bunch of other standard libraries
Haskell
16
star
22

vector-builder

Vector builder
Haskell
15
star
23

postgresql-syntax

PostgreSQL SQL syntax utilities
Yacc
15
star
24

deque

Double-ended queues
Haskell
14
star
25

hasql-pool

A pool of connections for Hasql
Haskell
13
star
26

list-t

ListT done right
Haskell
12
star
27

record-preprocessor

Compiler preprocessor introducing a syntactic extension for anonymous records
Haskell
12
star
28

hasql-transaction

A composable abstraction over retriable transactions for Hasql
Haskell
12
star
29

focus

A general abstraction for manipulating elements of container data structures
Haskell
11
star
30

stm-hamt

STM-specialised Hash Array Mapped Trie
Haskell
9
star
31

hashing-containers

Hashing-based container datastructures for Elm
Elm
9
star
32

bytestring-strict-builder

An efficient strict bytestring builder
Haskell
8
star
33

deferred-folds

Abstractions over deferred folds
Haskell
8
star
34

ptr-poker

Pointer poking action construction and composition toolkit
Haskell
8
star
35

hasql-cursor-query

A declarative abstraction over PostgreSQL Cursor
Haskell
7
star
36

acc

Sequence optimized for monoidal construction and folding
Haskell
7
star
37

ptr

Abstractions for operations on pointers
Haskell
7
star
38

theatre

Minimalistic actor library for Haskell
Haskell
7
star
39

laika

Minimalistic type-checked compile-time template engine
Haskell
7
star
40

conversion

Universal converter between values of different types
Haskell
7
star
41

html-entities

A codec library for HTML-escaped text and HTML-entities
Haskell
7
star
42

binary-parser

A highly-efficient but limited parser API specialised for bytestrings
Haskell
6
star
43

partial-handler

A composable exception handler
Haskell
6
star
44

th-instance-reification

Fixed versions of instances reification functions
Haskell
5
star
45

embrace

A tiny extension library embracing a braceless coding style in Scala
Scala
5
star
46

ez-couch

A CouchDB client library for Haskell
Haskell
5
star
47

messageless

Messageless effects model for Elm
Elm
5
star
48

bit-array

A bit array (aka bitset, bitmap, bit vector) API for numeric types
Haskell
5
star
49

hasql-dynamic-statements

Dynamic statements for Hasql
Haskell
5
star
50

newtype-deriving

Instance derivers for newtype wrappers
Haskell
5
star
51

futures

Haskell
5
star
52

cases

A converter for spinal, snake and camel case
Haskell
5
star
53

text-builder

An efficient strict text builder
Haskell
5
star
54

isomorphism-class

Isomorphism typeclass solving the conversion problem
Haskell
4
star
55

structure-kit

Immutable data structures for all kinds of purposes
Haskell
4
star
56

iri

Haskell
4
star
57

strelka-helloworld

A "Helloworld" application showcasing the "strelka" library
Haskell
4
star
58

optima

Simple and composable options parser
Haskell
4
star
59

success

A version of Either specialised for encoding of success or failure
Haskell
4
star
60

wobsurv

A simple and highly performant HTTP file server
Haskell
4
star
61

strelka-demo

Haskell
4
star
62

strict-list

Strict linked list implementation for Haskell
Haskell
4
star
63

unsequential

An extension removing the sequentiality from monads
Haskell
4
star
64

record-syntax

A library for parsing and processing the Haskell syntax sprinkled with anonymous records
Haskell
4
star
65

transition

Like state-monad but with optional updates
Haskell
3
star
66

supplemented

Early termination for monads
Haskell
3
star
67

fonts

Loading of fonts for Elm
Elm
3
star
68

attoparsec-data

Parsers for the standard Haskell data types
Haskell
3
star
69

remotion

A library for client-server applications based on custom protocols
Haskell
3
star
70

edit-cabal-version.github-action

Haskell
3
star
71

validation

Value validation library for Elm
Elm
3
star
72

json-bytes-builder

Direct-to-bytes JSON Builder
Haskell
3
star
73

kindly

Horizontally composable effects
Haskell
3
star
74

json-incremental-decoder

Incremental JSON parser with early termination and a declarative DSL
Haskell
3
star
75

numeric-qq

Quasi-quoters for numbers of various bases
Haskell
3
star
76

grafika

UI utils for Elm
Elm
3
star
77

hashtables-plus

Extensions for a "hashtables" library
Haskell
3
star
78

conversion-bytestring

"Conversion" instances for the "bytestring" library
Haskell
3
star
79

rebase-generator

A utility for the generation of the "rebase" project
Haskell
3
star
80

html-tokenizer

An "attoparsec"-based HTML tokenizer
Haskell
3
star
81

curly

High level HTTP client based on libcurl
Haskell
3
star
82

contravariant-extras

Extras for the "contravariant" package
Haskell
3
star
83

Fury

A platform independent library of higher order functions for function composing, overloading and asynchronicity in JavaScript and CoffeeScript
CoffeeScript
3
star
84

postgresql-error-codes

PostgreSQL error codes
Haskell
3
star
85

conversion-text

"Conversion" instances for the "text" library
Haskell
3
star
86

lazy

Haskell
3
star
87

mtl-prelude

Reexports of most definitions from "mtl" and "transformers"
Haskell
3
star
88

hasql-cursor-transaction

An abstraction for simultaneous fetching from multiple PostgreSQL cursors
Haskell
3
star
89

json-ast-quickcheck

Compatibility layer for "json-ast" and "QuickCheck"
Haskell
2
star
90

stm-graphs

Experiments with mutable graphs in STM
Haskell
2
star
91

hasql-backend

A backend for Hasql
Haskell
2
star
92

html-compacting

Algorithms for compacting HTML
Haskell
2
star
93

list-t-attoparsec

An "attoparsec" adapter for "list-t"
Haskell
2
star
94

template-haskell-compat-v0208

A backwards compatibility layer for Template Haskell newer than 2.8
Haskell
2
star
95

FuellSys

Fuell library extension of system utilities for node.js
CoffeeScript
2
star
96

markright

Haskell
2
star
97

folding

Elm
2
star
98

url-decoders

Decoders for URL-encoding (aka Percent-encoding)
Haskell
2
star
99

json-ast-json-encoder

Integration of "json-ast" and "json-encoder"
Haskell
2
star
100

bytearray-parsing

Parsing of bytearray-based data
Haskell
2
star