{-# LANGUAGE RecordWildCards #-}-------------------------------------------------------------------------------- |-- Module: Database.SQLite.Simple.FromRow-- Copyright: (c) 2011-2012 Leon P Smith-- (c) 2012 Janne Hellsten-- License: BSD3-- Maintainer: Janne Hellsten <jjhellst@gmail.com>-- Stability: experimental-- Portability: portable---- The 'FromRow' typeclass, for converting a row of results-- returned by a SQL query into a more useful Haskell representation.---- Predefined instances are provided for tuples containing up to ten-- elements.------------------------------------------------------------------------------moduleDatabase.SQLite.Simple.FromRow(FromRow(..),RowParser,field,fieldWith,numFieldsRemaining)whereimportControl.Applicative(Applicative(..),(<$>))importControl.Exception(SomeException(..))importControl.Monad(replicateM)importControl.Monad.Trans.State.StrictimportControl.Monad.Trans.ReaderimportControl.Monad.Trans.ClassimportData.ByteString(ByteString)importqualifiedData.ByteString.Char8asBimportDatabase.SQLite.Simple.FromFieldimportDatabase.SQLite.Simple.InternalimportDatabase.SQLite.Simple.OkimportDatabase.SQLite.Simple.TypesimportqualifiedDatabase.SQLite3asBase-- | A collection type that can be converted from a sequence of fields.-- Instances are provided for tuples up to 10 elements and lists of any length.---- Note that instances can defined outside of sqlite-simple, which is-- often useful. For example, here's an instance for a user-defined pair:---- @data User = User { name :: String, fileQuota :: Int }---- instance 'FromRow' User where-- fromRow = User \<$\> 'field' \<*\> 'field'-- @---- The number of calls to 'field' must match the number of fields returned-- in a single row of the query result. Otherwise, a 'ConversionFailed'-- exception will be thrown.---- Note the caveats associated with user-defined implementations of-- 'fromRow'.classFromRowawherefromRow::RowParserafieldWith::FieldParsera->RowParserafieldWithfieldP=RP$doRow{..}<-askcolumn<-liftgetlift(put(column+1))letncols=lengthrowresultif(column>=ncols)thendoletvals=map(\c->(gettypename(rowresult!!c),ellipsis(rowresult!!c)))[0..ncols-1]convertError=ConversionFailed(showncols++" values: "++showvals)("at least "++show(column+1)++" slots in target type")"mismatch between number of columns to \
\convert and number in target type"lift(lift(Errors[SomeExceptionconvertError]))elsedoletr=rowresult!!columnfield=Fieldrcolumnlift(lift(fieldPfield))field::FromFielda=>RowParserafield=fieldWithfromFieldellipsis::Base.SQLData->ByteStringellipsissql|B.lengthbs>15=B.take10bs`B.append`"[...]"|otherwise=bswherebs=B.pack$showsqlnumFieldsRemaining::RowParserIntnumFieldsRemaining=RP$doRow{..}<-askcolumn<-liftgetreturn$!lengthrowresult-columninstance(FromFielda)=>FromRow(Onlya)wherefromRow=Only<$>fieldinstance(FromFielda,FromFieldb)=>FromRow(a,b)wherefromRow=(,)<$>field<*>fieldinstance(FromFielda,FromFieldb,FromFieldc)=>FromRow(a,b,c)wherefromRow=(,,)<$>field<*>field<*>fieldinstance(FromFielda,FromFieldb,FromFieldc,FromFieldd)=>FromRow(a,b,c,d)wherefromRow=(,,,)<$>field<*>field<*>field<*>fieldinstance(FromFielda,FromFieldb,FromFieldc,FromFieldd,FromFielde)=>FromRow(a,b,c,d,e)wherefromRow=(,,,,)<$>field<*>field<*>field<*>field<*>fieldinstance(FromFielda,FromFieldb,FromFieldc,FromFieldd,FromFielde,FromFieldf)=>FromRow(a,b,c,d,e,f)wherefromRow=(,,,,,)<$>field<*>field<*>field<*>field<*>field<*>fieldinstance(FromFielda,FromFieldb,FromFieldc,FromFieldd,FromFielde,FromFieldf,FromFieldg)=>FromRow(a,b,c,d,e,f,g)wherefromRow=(,,,,,,)<$>field<*>field<*>field<*>field<*>field<*>field<*>fieldinstance(FromFielda,FromFieldb,FromFieldc,FromFieldd,FromFielde,FromFieldf,FromFieldg,FromFieldh)=>FromRow(a,b,c,d,e,f,g,h)wherefromRow=(,,,,,,,)<$>field<*>field<*>field<*>field<*>field<*>field<*>field<*>fieldinstance(FromFielda,FromFieldb,FromFieldc,FromFieldd,FromFielde,FromFieldf,FromFieldg,FromFieldh,FromFieldi)=>FromRow(a,b,c,d,e,f,g,h,i)wherefromRow=(,,,,,,,,)<$>field<*>field<*>field<*>field<*>field<*>field<*>field<*>field<*>fieldinstance(FromFielda,FromFieldb,FromFieldc,FromFieldd,FromFielde,FromFieldf,FromFieldg,FromFieldh,FromFieldi,FromFieldj)=>FromRow(a,b,c,d,e,f,g,h,i,j)wherefromRow=(,,,,,,,,,)<$>field<*>field<*>field<*>field<*>field<*>field<*>field<*>field<*>field<*>fieldinstanceFromFielda=>FromRow[a]wherefromRow=don<-numFieldsRemainingreplicateMnfieldinstance(FromRowa,FromRowb)=>FromRow(a:.b)wherefromRow=(:.)<$>fromRow<*>fromRow