úÎ4#/£     Safe7  !"#$% & '()*+,-./0123456789:;< % & &   !"#$% & '()*+,-./0123456789:;<*Turn SQL queries into type-safe functions.(c) 2015 Tobias Dammers#Tobias Dammers <tdammers@gmail.com> experimentalNone=fMonad in which we can perform IO and tag dependencies. Mostly needed because we cannot easily make a MonadIO instance for >i, and also because we want to avoid a dependency on mtl or transformers. For convenience, we also pull ? into this typeclass. ¶Generate a top-level declaration or an expression for a single SQL query. If used at the top level (i.e., generating a declaration), the query definition must specify a query name. ¶Generate top-level declarations or expressions for several SQL queries. If used at the top level (i.e., generating declarations), all queries in the definitions must be named, and  ¬ will generate a separate set of functions for each. If used in an expression context, the current behavior is somewhat undesirable, namely sequencing the queries using @.…Future versions will most likely change this to create a tuple of query expressions instead, such that you can write something like: ÿJlet (createUser, getUser, updateUser, deleteUser) = [yesh| -- name:createUser :: (Integer) -- :username :: String INSERT INTO users (username) VALUES (:username) RETURNING id; -- name:getUser :: (Integer, String) -- :userID :: Integer SELECT id, username FROM users WHERE id = :userID; -- name:updateUser :: Integer -- :userID :: Integer -- :username :: String UPDATE users SET username = :username WHERE id = :userID; -- name:deleteUser :: Integer -- :userID :: Integer DELETE FROM users WHERE id = :userID LIMIT 1; |] äGenerate one query definition or expression from an external file. In a declaration context, the query name will be derived from the filename unless the query contains an explicit name. Query name derivation works as follows:DTake only the basename (stripping off the directories and extension)CRemove all non-alphabetic characters from the beginning of the name4Remove all non-alphanumeric characters from the nameLower-case the first character.éNote that since there is always a filename to derive the query name from, explicitly defining a query name is only necessary when you want it to differ from the filename; however, making it explicit anyway is probably a good idea.xGenerate multiple query definitions or expressions from an external file. Query name derivation works exactly like for p, except that an underscore and a 0-based query index are appended to disambiguate queries from the same file.8In an expression context, the same caveats apply as for  A, i.e., to generate expressions, you will almost certainly want , not .=A?B CDEFGHIJKLMNOPQRSTUVW    =A?B CDEFGHIJKLMNOPQRSTUVWX      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^yeshq_11xzrIxPYP813LsGiLz6KDDatabase.YeshQLDatabase.YeshQL.Parser ParsedQuery pqQueryName pqQueryString pqParamsRaw pqParamNames pqParamTypes pqReturnType pqDocCommentpqDDL parseQuery parseQueriesyesh1yesh yesh1FileyeshFile mkQueryDecs mkQueryExp Annotation DDLAnnotation ParsedItem ParsedLiteral ParsedParam ParsedCommentParsedAnnotation ParsedType PlainType MaybeTypeAutoType pqTypeFor parsedQueryextractParamNamesextractParamTypeMapextractParsedQueryextractParsedParamsextractDocComment extractIsDDL parseQueryN parseQueriesNmainPmultiPqueryP nameDeclP namelessDeclP identifierP returnTypePreturnTypeSinglePreturnTypeMultiPtypePitemP semicolonP annotationPddlAnnotationP paramDeclPcommentPparamPquotedPliteralP whitespacePignorenewlinePMonadPerformIOtemplate-haskellLanguage.Haskell.TH.SyntaxQaddDependentFilebaseGHC.Base>> performIOnthIdent queryNamequeryIdentifierucfirstlcfirstwithParsedQuerywithParsedQuerieswithParsedQueryFilewithParsedQueriesFile nameQuery nameQueriesmakeValidIdentifier withParsedwithParsedFile pgQueryTypemkTypemkQueryDecsMultimkQueryExpMultipqNames mkQueryBody$fMonadPerformIOQ$fMonadPerformIOIO