All Projects → nikita-volkov → Hasql

nikita-volkov / Hasql

Licence: mit
Performant PostgreSQL driver with a flexible mapping API

Programming Languages

haskell
3896 projects

Projects that are alternatives of or similar to Hasql

Postgres
Postgres.js - The Fastest full featured PostgreSQL client for Node.js
Stars: ✭ 2,193 (+428.43%)
Mutual labels:  database, postgresql, driver
Psycopg2
PostgreSQL database adapter for the Python programming language
Stars: ✭ 2,425 (+484.34%)
Mutual labels:  database, postgresql, driver
Psycopg3
New generation PostgreSQL database adapter for the Python programming language
Stars: ✭ 278 (-33.01%)
Mutual labels:  database, postgresql, driver
Sqlhooks
Attach hooks to any database/sql driver
Stars: ✭ 397 (-4.34%)
Mutual labels:  database, driver
Cdrs
Cassandra DB native client written in Rust language. Find 1.x versions on https://github.com/AlexPikalov/cdrs/tree/v.1.x Looking for an async version? - Check WIP https://github.com/AlexPikalov/cdrs-async
Stars: ✭ 314 (-24.34%)
Mutual labels:  database, driver
Gokv
Simple key-value store abstraction and implementations for Go (Redis, Consul, etcd, bbolt, BadgerDB, LevelDB, Memcached, DynamoDB, S3, PostgreSQL, MongoDB, CockroachDB and many more)
Stars: ✭ 314 (-24.34%)
Mutual labels:  database, postgresql
Vertica Python
Official native Python client for the Vertica Analytics Database.
Stars: ✭ 301 (-27.47%)
Mutual labels:  database, driver
Postgrest
REST API for any Postgres database
Stars: ✭ 18,166 (+4277.35%)
Mutual labels:  database, postgresql
Rdbc
Rust DataBase Connectivity (RDBC) :: Common Rust API for database drivers
Stars: ✭ 328 (-20.96%)
Mutual labels:  database, driver
Postgresql Monitoring
Queries to monitor postgresql
Stars: ✭ 331 (-20.24%)
Mutual labels:  database, postgresql
Dbeaver
Free universal database tool and SQL client
Stars: ✭ 23,752 (+5623.37%)
Mutual labels:  database, postgresql
Ansible Role Postgresql
Ansible Role - PostgreSQL
Stars: ✭ 310 (-25.3%)
Mutual labels:  database, postgresql
Squeal
Squeal, a deep embedding of SQL in Haskell
Stars: ✭ 308 (-25.78%)
Mutual labels:  database, postgresql
Rel
💎 Modern Database Access Layer for Golang - Testable, Extendable and Crafted Into a Clean and Elegant API
Stars: ✭ 317 (-23.61%)
Mutual labels:  database, postgresql
Sql exporter
Database agnostic SQL exporter for Prometheus
Stars: ✭ 301 (-27.47%)
Mutual labels:  database, postgresql
Pgloader
Migrate to PostgreSQL in a single command!
Stars: ✭ 3,754 (+804.58%)
Mutual labels:  database, postgresql
Jet
Type safe SQL builder with code generation and automatic query result data mapping
Stars: ✭ 373 (-10.12%)
Mutual labels:  database, postgresql
Pg timetable
pg_timetable: Advanced scheduling for PostgreSQL
Stars: ✭ 382 (-7.95%)
Mutual labels:  database, postgresql
Diwata
A user-friendly database interface
Stars: ✭ 386 (-6.99%)
Mutual labels:  database, postgresql
Node Orm2
Object Relational Mapping
Stars: ✭ 3,063 (+638.07%)
Mutual labels:  database, postgresql

What Hasql is

Build Status Hackage

Hasql is a highly efficient PostgreSQL driver and a mapping API. It targets both the users, who need a low level of abstraction, and the users, who face the typical tasks of DB-powered applications, providing them with higher-level APIs.

Ecosystem

Hasql is not just a single library, it is a granular ecosystem of composable libraries, each isolated to perform its own task and stay simple.

  • "hasql" - the root of the ecosystem, which provides the essential abstraction over the PostgreSQL client functionality and mapping of values. Everything else revolves around that library.

  • "hasql-th" - Template Haskell utilities, providing compile-time syntax checking and easy statement declaration.

  • "hasql-transaction" - an STM-inspired composable abstraction over database transactions providing automated conflict resolution.

  • "hasql-dynamic-statements" - a toolkit for generating statements based on the parameters.

  • "hasql-cursor-query" - a declarative abstraction over cursors.

  • "hasql-cursor-transaction" - a lower-level abstraction over cursors, which however allows to fetch from multiple cursors simultaneously. Generally though "hasql-cursor-query" is the recommended alternative.

  • "hasql-pool" - a Hasql-specialized abstraction over the connection pool.

  • "hasql-migration" - A port of postgresql-simple-migration for use with hasql.

  • "hasql-notifications" - Support for PostgreSQL asynchronous notifications.

  • "hasql-optparse-applicative" - "optparse-applicative" parsers for Hasql.

  • "hasql-implicits" - implicit definitions, such as default codecs for standard types.

Benefits of being an ecosystem

  • Simplicity. Each library in isolation provides a simple API, which is hopefully easier to comprehend.

  • Flexibility and composability. The user picks and chooses the features, thus precisely matching the level of abstraction that he needs for his task.

  • Much more stable and more descriptive semantic versioning. E.g., a change in the API of the "hasql-transaction" library won't affect any of the other libraries and it gives the user a more precise information about which part of his application he needs to update to conform.

  • Interchangeability and competition of the ecosystem components. E.g., not everyone will agree with the restrictive design decisions made in the "hasql-transaction" library. However those decisions are not imposed on the user, and instead of having endless debates about how to abstract over transactions, another extension library can simply be released, which will provide a different interpretation of what the abstraction over transactions should be.

  • Horizontal scalability of the ecosystem. Instead of posting feature- or pull-requests, the users are encouraged to release their own small extension-libraries, with themselves becoming the copyright owners and taking on the maintenance responsibilities. Compare this model to the classical one, where some core-team is responsible for everything. One is scalable, the other is not.

Tutorials

Short Example

Following is a complete application, which performs some arithmetic in Postgres using Hasql.

{-# LANGUAGE OverloadedStrings, QuasiQuotes #-}
import Prelude
import Data.Int
import Data.Functor.Contravariant
import Hasql.Session (Session)
import Hasql.Statement (Statement(..))
import qualified Hasql.Session as Session
import qualified Hasql.Decoders as Decoders
import qualified Hasql.Encoders as Encoders
import qualified Hasql.Connection as Connection


main :: IO ()
main = do
  Right connection <- Connection.acquire connectionSettings
  result <- Session.run (sumAndDivModSession 3 8 3) connection
  print result
  where
    connectionSettings = Connection.settings "localhost" 5432 "postgres" "" "postgres"


-- * Sessions
-- 
-- Session is an abstraction over the database connection and all possible errors.
-- It is used to execute statements.
-- It is composable and has a Monad instance.
-- 
-- It's recommended to define sessions in a dedicated 'Sessions'
-- submodule of your project.
-------------------------

sumAndDivModSession :: Int64 -> Int64 -> Int64 -> Session (Int64, Int64)
sumAndDivModSession a b c = do
  -- Get the sum of a and b
  sumOfAAndB <- Session.statement (a, b) sumStatement
  -- Divide the sum by c and get the modulo as well
  Session.statement (sumOfAAndB, c) divModStatement


-- * Statements
-- 
-- Statement is a definition of an individual SQL-statement,
-- accompanied by a specification of how to encode its parameters and
-- decode its result.
-- 
-- It's recommended to define statements in a dedicated 'Statements'
-- submodule of your project.
-------------------------

sumStatement :: Statement (Int64, Int64) Int64
sumStatement = Statement sql encoder decoder True where
  sql = "select $1 + $2"
  encoder =
    (fst >$< Encoders.param (Encoders.nonNullable Encoders.int8)) <>
    (snd >$< Encoders.param (Encoders.nonNullable Encoders.int8))
  decoder = Decoders.singleRow (Decoders.column (Decoders.nonNullable Decoders.int8))

divModStatement :: Statement (Int64, Int64) (Int64, Int64)
divModStatement = Statement sql encoder decoder True where
  sql = "select $1 / $2, $1 % $2"
  encoder =
    (fst >$< Encoders.param (Encoders.nonNullable Encoders.int8)) <>
    (snd >$< Encoders.param (Encoders.nonNullable Encoders.int8))
  decoder = Decoders.singleRow row where
    row =
      (,) <$>
      Decoders.column (Decoders.nonNullable Decoders.int8) <*>
      Decoders.column (Decoders.nonNullable Decoders.int8)

For the general use-case it is advised to prefer declaring statements using the "hasql-th" library, which validates the statements at compile-time and generates codecs automatically. So the above two statements could be implemented the following way:

import qualified Hasql.TH as TH -- from "hasql-th"

sumStatement :: Statement (Int64, Int64) Int64
sumStatement =
  [TH.singletonStatement|
    select ($1 :: int8 + $2 :: int8) :: int8
    |]

divModStatement :: Statement (Int64, Int64) (Int64, Int64)
divModStatement =
  [TH.singletonStatement|
    select
      (($1 :: int8) / ($2 :: int8)) :: int8,
      (($1 :: int8) % ($2 :: int8)) :: int8
    |]
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].