Skip to content

Add primitive queries that don't use type classes #64

Description

@JordanMartinez

Copied from here:

  • I see this as an opportunity to simplify how queries are executed (or any SQL statements) - making the whole process more abstract is one thing and simplifying some type classes is the other.
  • type classes like GenericQuery are there for two reasons:
    • to hide complicated constraints from the user, e.q. so that the type of the query consists of one constraint without any intermediate type parameters
    • overloading convenience
  • but the user should not be forced to use them
  • we should provide common query variations that could be used by current type classes and users directly. I've included examples that should illustrate my point
primGenericQuery ∷
  ∀ s a i.
  GetCols i ⇒
  String →  -- query parameter placeholder, e.g. '$' for pg, and '?' for sqlite
  Int →     -- first query parameter index, usually `1`
            -- both of these parameters determine how we generate query
            -- parameter names, e.g. '$1', '$2', ... for pg
  (String → Array Foreign → a) →
  FullQuery s { | i } →
  a
primGenericQuery ph i exec q = do
  -- transform Query AST `q` into a query string and query parameters
  let { strQuery, params } = showM ph i $ showQuery q

  -- execute the query with the parameters
  exec strQuery params

pgPrimGenericQuery ∷
  ∀ s a i m.
  GetCols i ⇒             -- needed by query string generation
  MonadSeldaPG m ⇒        -- PG specific monad constraints
  (Array Foreign → m a) → -- generic decoder, errors are handled by monad `m`
  FullQuery s { | i } →   -- query AST
  m (Array a)             -- result rows of output records, record type `{ | o }` is determined by `i` via the type-function
pgPrimGenericQuery decodeRow = primGenericQuery "$" 1 exec
  where
  exec strQuery params = do
    conn ← ask
    errOrResult ← liftAff $ PostgreSQL.unsafeQuery conn strQuery params
    result ← either throwError pure errOrResult
    traverse decodeRow result.rows

pgGenericQuery ∷
  ∀ s o i m.
  GetCols i ⇒
  MapR UnCol_ i o ⇒             -- type-level function that maps over `{ | i }`
                                -- and removes `Col s` from each record member
                                -- thus `o` is now determined by the input `i`
  MonadSeldaPG m ⇒
  (Array Foreign → m { | o }) →
  FullQuery s { | i } →
  m (Array { | o })             -- the additional constraint forces the
                                -- appropriate result type
pgGenericQuery = pgPrimGenericQuery

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions