úÎŒaˆ<     None CTemplatePG currenly only supports a handful of types. It also doesn't M distinguish between numeric types with different ranges. More types are the 4 most likely feature of future TemplatePG releases. &interval (a time interval), send-only date (day without time) 'timestamptz (timestamp with time zone) text/varchar float integer bool "Convert a type OID from PostgreSQL's catalog to a TemplatePG ) representation. To get a list of types:  SELECT typname, oid FROM pg_type J Note that I have assumed, but not tested, that type OIDs for these basic 5 types are consistent across installations. If not, I'm going to have to ' switch to using the text descriptions This is PostgreSQL's canonical timestamp format. @ Time conversions are complicated a bit because PostgreSQL doesn' t support G timezones with minute parts, and Haskell only supports timezones with  minutes parts. We';ll need to truncate and pad timestamp strings accordingly. - This means with minute parts will not work. KConvert a Haskell value to a string of the given PostgreSQL type. Or, more G accurately, given a PostgreSQL type, create a function for converting 7 compatible Haskell values into a string of that type.  )pgTypeToString :: PGType -> (? -> String) GConvert a string from PostgreSQL of the given type into an appropriate G Haskell value. Or, more accurately, given a PostgreSQL type, create a I function for converting a string of that type into a compatible Haskell  value.  )pgStringToType :: PGType -> (String -> ?) LMake a string safe for interpolation (escape single-quotes). This relies on 7 standard_conforming_strings = on in postgresql.conf. I'm not 100% sure that 1 this makes all strings safe for execution. I don' t know if it's possible to 8 inject SQL with strange (possibly Unicode) characters. PostgreSQL type OID      None +PGException is thrown upon encountering an  with severity of J ERROR, FATAL, or PANIC. It holds the SQLSTATE and message of the error. :PGMessage represents a PostgreSQL protocol message that we'll either send  or receive. See   Phttp://www.postgresql.org/docs/current/interactive/protocol-message-formats.html. ;SimpleQuery takes a simple SQL string. Parameters ($1, $2,  etc.) aren' t allowed. 9A RowDescription contains the name, type, table OID, and < column number of the resulting columns(s) of a query. The 5 column number is useful for inferring nullability. +Parse SQL Destination (prepared statement) !9A ParameterDescription describes the type of a given SQL  query/3statement parameter ($1, $2, etc.). Unfortunately, > PostgreSQL does not give us nullability information for the  parameter. (An ErrorResponse contains the severity, SQLSTATE, and  message of an error. See   Mhttp://www.postgresql.org/docs/current/interactive/protocol-error-fields.html. "Describe a SQL query/&statement. The SQL string can contain  parameters ($1, $2, etc.). #:Each DataRow (result of a query) is a list of ByteStrings = (or just Nothing for null values, to distinguish them from ; emtpy strings). The ByteStrings can then be converted to  the appropriate type by  . $;CommandComplete is bare for now, although it could be made < to contain the number of rows affected by statements in a  later version. %IDetermine whether or not to print debug output based on the value of the ! TPG_DEBUG environment variable.  Connect to a PostgreSQL server. CDisconnect from a PostgreSQL server. Note that this currently doesn't send  a close message. &CConvert a string to a NULL-terminated UTF-8 string. The PostgreSQL 2 protocol transmits most strings in this format.  I haven'?t yet found a function for doing this without requiring manual  memory management. 'LGiven a message, build the over-the-wire representation of it. Note that we & send fewer messages than we receive. (.Get the type and size of an incoming message. )Parse an incoming message. **Send a message to PostgreSQL (low-level). +JReceive the next message from PostgreSQL (low-level). Note that this will  block until it gets a message. ,$Wait for a message of a given type. Describe a SQL statement/0query. A statement description consists of 0 or I more parameter descriptions (a PostgreSQL type) and zero or more result I field descriptions (for queries) (consist of the name of the field, the 2 type of the field, and a nullability indicator). ;A simple query is one which requires sending only a single  M message to the PostgreSQL server. The query is sent as a single string; you J cannot bind parameters. Note that queries can return 0 results (an empty  list). JWhile not strictly necessary, this can make code a little bit clearer. It  executes a  but doesn't look for results. -KAll PostgreSQL messages have a common header: an identifying character and  a 32-bit size field. ' ./0 1!23456"#$789% the host to connect to the port to connect on the database to connect to the username to connect as the password to connect with 6a handle to communicate with the PostgreSQL server on a handle from   &:'()!the type of the message to parse *+,2A list of message identifiers, the first of which 6 found while reading messages from PostgreSQL will be  returned.  SQL string `a list of parameter types, and a list of result field names, types, and nullability indicators.  SQL string A list of result rows,  which themselves are a list  of fields.  SQL string -;    87$#"65432!1 0/.9% &:'()*+,-;None<DGrab a PostgreSQL connection for compile time. We do so through the  environment variables: TPG_DB, TPG_HOST, TPG_PORT, TPG_USER, and  TPG_PASS. Only TPG_DB is required. =)This is where most of the magic happens.  This doesn'At result in a PostgreSQL prepared statement, it just creates one  to do type inference. G This returns a prepared SQL string with all values (as an expression) >weave- 2 lists of equal length into a single list. ?weaveK a list of SQL fragements an Haskell expressions into a single SQL string.  ?queryTuples :: String -> (Handle -> IO [(column1, column2, ...)])FQuery a PostgreSQL server and return the results as a list of tuples. Example (where h is a handle from  ): $(queryTuples "%SELECT usesysid, usename FROM pg_user") h  $=> IO [(Maybe String, Maybe Integer)]  FqueryTuple :: String -> (Handle -> IO (Maybe (column1, column2, ...)))GConvenience function to query a PostgreSQL server and return the first = result as a tuple. If the query produces no results, return @. Example (where h is a handle from  ): let sysid = 10::Integer;   $(queryTuple ">SELECT usesysid, usename FROM pg_user WHERE usesysid = {sysid}") h  ,=> IO (Maybe (Maybe String, Maybe Integer))  &execute :: String -> (Handle -> IO ())FConvenience function to execute a statement on the PostgreSQL server. Example (where h is a handle from  ): let rolename = "BOfH"   $(execute "CREATE ROLE {rolename}") h FRun a sequence of IO actions (presumably SQL statements) wrapped in a  transaction. Unfortunately you'#re restricted to using this in the A ! Monad for now due to the use of B. I'm debating adding a   MonadPeelIO version. Roll back a transaction. 9Ignore duplicate key errors. This is also limited to the A Monad. CGGiven a result description, create a function to convert a result to a  tuple. DCGiven a raw PostgreSQL result and a result field type, convert the ' appropriate field to a Haskell value. ELike  , but deal with possible NULLs. If the boolean  argument is F9, that means that we know that the value is not nullable  and we can use G to keep the code simple. If it's H , then we  don'2t know if the value is nullable and must return a I value in case  it is. JDGiven a SQL string return a list of SQL parts and expression parts.  For example: "ASELECT * FROM table WHERE id = {someID} AND age > {baseAge * 1.5}"  becomes: ([SELECT * FROM table WHERE id = ,  AND age > ],  [someID,  baseAge * 1.5]) KParameters are enclosed in {}- and can be any Haskell expression supported  by haskell-src-meta. <=a SQL string, with .a prepared SQL string and result descriptions >?SQL fragments Haskell expressions LCresult description @A function for converting a row of the given result description D8the name of the variable containing the result list (of I M)  the result field type and index Enullability indicator JNOPK<=>?LCDEJNOPKNone  Q      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIDJKLMNGHODEPGHQDERSTUVWXYZ[\templatepg-0.2.3Database.TemplatePG.TypesDatabase.TemplatePG.ProtocolDatabase.TemplatePG.SQLDatabase.TemplatePGPGType PGIntervalPGDate PGTimestampTZPGTextPGReal PGInteger PGBoolean pgTypeFromOIDpgTypeToStringpgStringToType PGException pgConnect pgDisconnectdescribeStatementexecuteSimpleQueryexecuteSimpleStatement queryTuples queryTupleexecutewithTransactionrollback insertIgnorepgTimestampTZFormat escapeStringShowReal ShowIntegral ErrorResponse PGMessage SimpleQueryRowDescriptionParseParameterDescriptionDescribeDataRowCommandCompletedebugpgStringputMessageBodygetMessageHeadergetMessageBodypgSend pgReceive pgWaitFor$fBinaryPGMessageUnknownMessage ReadyForQuery ParseCompleteParameterStatusNoticeResponseNoDataFlushExecuteEmptyQueryResponseBackendKeyDataAuthenticationprotocolVersion pgMessageID$fExceptionPGException thConnection prepareSQLweave weaveStringbase Data.MaybeNothingghc-prim GHC.TypesIOControl.Exception.Base onException convertRow convertColumnpgStringToType'FalsefromJustTrueMaybeparseSql sqlParameter maybeHeadbytestring-0.10.0.0Data.ByteString.Lazy.Internal ByteStringevery2nd sqlStatementsqlText