-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | YesQL-style SQL database abstraction (legacy compatibility wrapper)
--   
--   Use quasi-quotations or TemplateHaskell to write SQL in SQL, while
--   adding type annotations to turn SQL into well-typed Haskell functions.
@package yeshql
@version 4.1.0.0


-- | License: MIT
--   
--   Unlike existing libraries such as Esqueleto or Persistent, YeshQL does
--   not try to provide full SQL abstraction with added type safety;
--   instead, it gives you some simple tools to write the SQL queries
--   yourself and bind them to (typed) functions.
--   
--   <h1>Usage</h1>
--   
--   The main workhorses are <a>yesh1</a> (to define one query) and
--   <a>yesh</a> (to define multiple queries).
--   
--   Both <a>yesh</a> and <a>yesh1</a> can be used as TemplateHaskell
--   functions directly, or as quasi-quoters, and they can generate
--   declarations or expressions depending on the context in which they are
--   used.
--   
--   <h2>Creating Declarations</h2>
--   
--   When used at the top level, or inside a <tt>where</tt> block, the
--   <a>yesh</a> and <a>yesh1</a> quasi-quoters will declare one or more
--   functions, according to the query names given in the query definition.
--   Example:
--   
--   <pre>
--   [yesh1|
--       -- name:insertUser :: (Integer)
--       -- :name :: String
--       INSERT INTO users (name) VALUES (:name) RETURNING id |]
--   </pre>
--   
--   ...will create a top-level function of type:
--   
--   <pre>
--   insertUser :: IConnection conn =&gt; String -&gt; conn -&gt; IO (Maybe Integer)
--   </pre>
--   
--   Using plain TH, it can also be written as:
--   
--   <pre>
--   yesh1 $ unlines
--       [ "-- name:insertUser :: (Integer)"
--       , "-- :name :: String"
--       , "INSERT INTO users (name) VALUES (:name) RETURNING id"
--       ]
--   </pre>
--   
--   <h2>Syntax</h2>
--   
--   Because SQL itself does not *quite* provide enough information to
--   generate a fully typed Haskell function, we extend SQL syntax a bit.
--   
--   Here's what a typical YeshQL definition looks like:
--   
--   <pre>
--   [yesh|
--       -- name:insertUser :: (Integer)
--       -- :name :: String
--       INSERT INTO users (name) VALUES (:name) RETURNING id
--       ;;;
--       -- name:deleteUser :: rowcount Integer
--       -- :id :: Integer
--       DELETE FROM users WHERE id = :id
--       ;;;
--       -- name:getUser :: (Integer, String)
--       -- :id :: Integer
--       SELECT id, name FROM users WHERE id = :id
--       ;;;
--       -- name:getUserEx :: [(Integer, String)]
--       -- :id :: Integer
--       -- :filename :: String
--       SELECT id, name FROM users WHERE name = :filename OR id = :id
--       |]
--   </pre>
--   
--   Note that queries are separated by _triple_ semicolons; this is done
--   in order to allow semicolons to appear inside queries.
--   
--   On top of standard SQL syntax, YeshQL query definitions are preceded
--   by some extra information in order to generate well-typed HDBC
--   queries. All that information is written in SQL line comments (<tt>--
--   ...</tt>), such that a valid YeshQL definition is also valid SQL by
--   itself (with the exception of parameters, which follow the pattern
--   <tt>:paramName</tt>).
--   
--   Let's break it down:
--   
--   <pre>
--   -- name:insertUser :: (Integer)
--   </pre>
--   
--   This line tells YeshQL to generate an object called
--   <tt>insertUser</tt>, which should be a function of type
--   <tt>IConnection conn =&gt; conn -&gt; {...} -&gt; IO (Maybe
--   Integer)</tt> (where the <tt>{...}</tt> part depends on query
--   parameters, see below).
--   
--   The declared return type can be one of the following:
--   
--   <ul>
--   <li>(); the generated function will ignore any and all results from
--   the query and always return ().</li>
--   <li>The keyword <tt>rowcount</tt>, followed by an integer scalar, e.g.
--   <a>Integer</a> or <a>Int</a>; the generated function will return a row
--   count from <tt>INSERT</tt> <i> <tt>UPDATE</tt> </i> ... statements, or
--   0 from <tt>SELECT</tt> statements.</li>
--   <li>A tuple, where all elements implement <tt>FromSql</tt>; the
--   function will return the result set from a <tt>SELECT</tt> query as a
--   <a>Maybe</a> of such tuples, or always <a>Nothing</a> for other query
--   types. For example, <tt>:: (String, Int)</tt> produces a function
--   whose type ends in <tt>conn -&gt; IO (Maybe (String, Int))</tt>.
--   Null-tuples are marshalled to '()', ignoring result sets; one-tuples
--   (written as <tt>(a)</tt>) are marshalled to scalars.</li>
--   <li>A naked type, i.e., just a type name, without parentheses. The
--   type must implement <a>FromSqlRow</a>; the return type will be a
--   <a>Maybe</a> of that type. E.g., <tt>(:: User)</tt> will produce a
--   function signature ending in <tt>conn -&gt; IO (Maybe User)</tt>.</li>
--   <li>A list of tuples or naked types, written using square brackets
--   (<tt>[</tt> ... <tt>]</tt>), returning a list of mapped rows instead
--   of a <a>Maybe</a>.</li>
--   </ul>
--   
--   Note that, unlike Haskell, YeshQL distinguishes <tt>(Foo)</tt> from
--   <tt>Foo</tt>: the former takes the first column from a result row and
--   maps it using <tt>FromSql</tt>, while the latter takes the entire
--   result row and maps it using <a>FromSqlRow</a>.
--   
--   <pre>
--   -- :paramName :: Type
--   </pre>
--   
--   Declares a Haskell type for a parameter. The parameter
--   <tt>:paramName</tt> can then be referenced zero or more times in the
--   query itself, and will appear in the generated function signature in
--   the order of declaration. So in the above example, the last query
--   definition:
--   
--   <pre>
--   -- name:getUserEx :: (Integer, String)
--   -- :id :: Integer
--   -- :filename :: String
--   SELECT id, name FROM users WHERE name = :filename OR id = :id;
--   </pre>
--   
--   ...will produce the function:
--   
--   <pre>
--   getUserEx :: IConnection conn =&gt; Integer -&gt; String -&gt; conn -&gt; IO [(Integer, String)]
--   getUserEx id filename conn =
--       -- ... generated implementation left out
--   </pre>
--   
--   On top of referencing parameters directly, you can also "drill down"
--   with a projection function, using <tt>.</tt> syntax similar to
--   property access in, say, JavaScript. The intended use case is passing
--   record types as arguments to the query function, and then
--   dereferencing them inside the query, like so:
--   
--   <pre>
--   -- name:updateUser :: rowcount Int
--   -- :user :: User
--   UPDATE users
--   SET username  = :user.name
--   WHERE id = :user.userID
--   </pre>
--   
--   Note that the part after the <tt>.</tt> is a plain Haskell function
--   that must be in scope wherever the query is spliced.
--   
--   Also note that projection functions can be chained, and are not
--   limited to record field accessors.
--   
--   <h2>Loading Queries From External Files</h2>
--   
--   The <a>yeshFile</a> and <a>yesh1File</a> flavors take a file name
--   instead of SQL definition strings. Using these, you can put your SQL
--   in external files rather than clutter your code with long
--   quasi-quotation blocks.
--   
--   <h2>DDL Queries</h2>
--   
--   Normally, you will have one query per function, and that query takes
--   some parameters, and returns a result set or a row count. For DDL
--   queries, however, we aren't interested in the results, and we often
--   want to execute multiple queries with just one function call, e.g. to
--   set up an entire database schema using multiple <tt>CREATE TABLE</tt>
--   statements.
--   
--   By adding the <tt>@ddl</tt> annotation to a query definition, YeshQL
--   will change the following things:
--   
--   <ul>
--   <li>The return type of that query, regardless of what you declare,
--   will be '()'. It is recommended to never declare an explicit return
--   type other than '()' for DDL queries, as future versions may report
--   this as an error.</li>
--   <li>The query cannot accept any parameters.</li>
--   <li>The query may consist of multiple individual SQL queries,
--   semicolon-separated. The combined query is sent to the HDBC backend
--   as-is.</li>
--   <li>Instead of <tt>run</tt>, YeshQL will use <tt>runRaw</tt> in the
--   code it generates.</li>
--   </ul>
--   
--   In practice, this means that the type of a DDL function thus generated
--   will always be <tt><tt>IConnection</tt> conn =&gt; conn -&gt;
--   <a>IO</a> ()</tt>.
--   
--   <h3>Example:</h3>
--   
--   <pre>
--   [yesh1|
--       -- name:makeDatabaseSchema
--       -- @ddl
--       CREATE TABLE users (id INTEGER, username TEXT);
--       CREATE TABLE pages (id INTEGER, title TEXT, slug TEXT, body TEXT);
--       |]
--   </pre>
--   
--   <h2>Other Functions That YeshQL Generates</h2>
--   
--   On top of the obvious query functions, a top-level YeshQL
--   quasiquotation introduces two more definitions per query: a
--   <a>String</a> variable prefixed <tt>describe-</tt>, which contains the
--   SQL query as passed to HDBC (similar to the <tt>DESCRIBE</tt> feature
--   in some RDBMS systems), and another <a>String</a> variable prefixed
--   <tt>doc-</tt>, which contains all the free-form comments that precede
--   the SQL query in the query definition.
--   
--   So for example, this quasiquotation:
--   
--   <pre>
--   [yesh1|
--       -- name:getUser :: User
--       -- :userID :: Integer
--       -- Gets one user by the "id" column.
--       SELECT id, username FROM users WHERE id = :userID LIMIT 1 |]
--   </pre>
--   
--   ...would produce the following three top-level definitions:
--   
--   <pre>
--   getUser :: IConnection conn =&gt; Integer -&gt; conn -&gt; IO (Maybe User)
--   getUser userID conn = ...
--   
--   describeGetUser :: String
--   describeGetUser = "SELECT id, username FROM users WHERE id = ? LIMIT 1"
--   
--   docGetUser :: String
--   docGetUser = "Gets one user by the \"id\" column."
--   </pre>
module Database.YeshQL

-- | We want to be able to call the <tt>yesh</tt> family of functions in
--   both QQ and TH contexts, so unfortunately we need some typeclass
--   polymorphism.
class Yesh a
yeshWith :: Yesh a => YeshBackend -> a
yesh1With :: Yesh a => YeshBackend -> a
class YeshFile a
yeshFileWith :: YeshFile a => YeshBackend -> a
yesh1FileWith :: YeshFile a => YeshBackend -> a
parseQuery :: String -> Either ParseError ParsedQuery
parseQueries :: String -> Either ParseError [ParsedQuery]
data ParsedQuery
ParsedQuery :: String -> String -> [ExtractedParam] -> [String] -> Map String ParsedType -> ParsedReturnType -> String -> Bool -> ParsedQuery
[pqQueryName] :: ParsedQuery -> String
[pqQueryString] :: ParsedQuery -> String
[pqParamsRaw] :: ParsedQuery -> [ExtractedParam]
[pqParamNames] :: ParsedQuery -> [String]
[pqParamTypes] :: ParsedQuery -> Map String ParsedType
[pqReturnType] :: ParsedQuery -> ParsedReturnType
[pqDocComment] :: ParsedQuery -> String
[pqDDL] :: ParsedQuery -> Bool
