Add persistent-postgresql-ng package#2
Add persistent-postgresql-ng package#2iand675 wants to merge 1 commit into02-19-add_direct_codec_interface_to_persistent_corefrom
Conversation
A PostgreSQL backend for persistent using the binary wire protocol and libpq pipeline mode. Features: - Binary protocol via postgresql-binary (no text serialization) - Hedis-style automatic pipelining via lazy reply stream (unsafeInterleaveIO + atomicModifyIORef with head/tail) - UNNEST-based bulk inserts (fixed SQL template) - IN-clause collapse to = ANY($1) - Direct decode/encode path (zero PersistValue allocation) - PgDecode/PgEncode value-level codecs for compound types - FetchAll, FetchSingleRow, FetchChunked (PG17+) modes - DirectQueryCap wired into SqlBackend for SqlBackend bridge - Pipelined get, insert, upsert, getBy, count, exists - 24-29x speedup on reads at 1ms network latency Full test suite (363 tests across 3 fetch modes). Benchmarks with TCP delay proxy for latency simulation.
| license-file: LICENSE | ||
| author: Ian Duncan | ||
| maintainer: ian@ianduncan.me | ||
| synopsis: Pipelined PostgreSQL backend for persistent using binary protocol. |
There was a problem hiding this comment.
Restyled by cabal-fmt
| synopsis: Pipelined PostgreSQL backend for persistent using binary protocol. | |
| synopsis: | |
| Pipelined PostgreSQL backend for persistent using binary protocol. | |
| Database.Persist.Postgresql.Internal.PgType | ||
| Database.Persist.Postgresql.Internal.Placeholders | ||
| Database.Persist.Postgresql.JSON | ||
| Database.Persist.Postgresql.CustomType |
There was a problem hiding this comment.
Restyled by cabal-fmt
| Database.Persist.Postgresql.CustomType | |
| Database.Persist.Postgresql.Pipeline | |
| Database.Persist.Postgresql.Pipeline.FFI | |
| Database.Persist.Postgresql.Pipeline.Internal |
| BinaryRoundTripSpec | ||
| DirectDecodeSpec | ||
| DirectEntityPOC | ||
| CustomConstraintTest |
There was a problem hiding this comment.
Restyled by cabal-fmt
| CustomConstraintTest |
| | FetchChunked !Int | ||
| -- ^ Chunked mode (@PQsetChunkedRowsMode@, PG17+ libpq). Each |
There was a problem hiding this comment.
Restyled by fourmolu
| | FetchChunked !Int | |
| -- ^ Chunked mode (@PQsetChunkedRowsMode@, PG17+ libpq). Each | |
| FetchSingleRow | |
| | -- | Chunked mode (@PQsetChunkedRowsMode@, PG17+ libpq). Each |
| scalarCUInt PgBool = 16 | ||
| scalarCUInt PgBytea = 17 | ||
| scalarCUInt PgChar = 18 | ||
| scalarCUInt PgName = 19 | ||
| scalarCUInt PgInt2 = 21 | ||
| scalarCUInt PgInt4 = 23 | ||
| scalarCUInt PgInt8 = 20 | ||
| scalarCUInt PgFloat4 = 700 | ||
| scalarCUInt PgFloat8 = 701 | ||
| scalarCUInt PgText = 25 | ||
| scalarCUInt PgXml = 142 | ||
| scalarCUInt PgMoney = 790 | ||
| scalarCUInt PgBpchar = 1042 | ||
| scalarCUInt PgVarchar = 1043 | ||
| scalarCUInt PgDate = 1082 | ||
| scalarCUInt PgTime = 1083 | ||
| scalarCUInt PgTimestamp = 1114 |
There was a problem hiding this comment.
Restyled by fourmolu
| scalarCUInt PgBool = 16 | |
| scalarCUInt PgBytea = 17 | |
| scalarCUInt PgChar = 18 | |
| scalarCUInt PgName = 19 | |
| scalarCUInt PgInt2 = 21 | |
| scalarCUInt PgInt4 = 23 | |
| scalarCUInt PgInt8 = 20 | |
| scalarCUInt PgFloat4 = 700 | |
| scalarCUInt PgFloat8 = 701 | |
| scalarCUInt PgText = 25 | |
| scalarCUInt PgXml = 142 | |
| scalarCUInt PgMoney = 790 | |
| scalarCUInt PgBpchar = 1042 | |
| scalarCUInt PgVarchar = 1043 | |
| scalarCUInt PgDate = 1082 | |
| scalarCUInt PgTime = 1083 | |
| scalarCUInt PgTimestamp = 1114 | |
| scalarCUInt PgBool = 16 | |
| scalarCUInt PgBytea = 17 | |
| scalarCUInt PgChar = 18 | |
| scalarCUInt PgName = 19 | |
| scalarCUInt PgInt2 = 21 | |
| scalarCUInt PgInt4 = 23 | |
| scalarCUInt PgInt8 = 20 | |
| scalarCUInt PgFloat4 = 700 | |
| scalarCUInt PgFloat8 = 701 | |
| scalarCUInt PgText = 25 | |
| scalarCUInt PgXml = 142 | |
| scalarCUInt PgMoney = 790 | |
| scalarCUInt PgBpchar = 1042 | |
| scalarCUInt PgVarchar = 1043 | |
| scalarCUInt PgDate = 1082 | |
| scalarCUInt PgTime = 1083 | |
| scalarCUInt PgTimestamp = 1114 |
| = QuestionMarkParams | ||
| -- ^ Traditional @?@ placeholders (persistent style). Each @?@ is a | ||
| -- distinct positional parameter. | ||
| | NumberedParams !Int | ||
| -- ^ PostgreSQL-native @$N@ placeholders. The 'Int' is the highest | ||
| -- @$N@ found. A single @$1@ can appear multiple times in the query, | ||
| -- referencing the same parameter value. |
There was a problem hiding this comment.
Restyled by fourmolu
| = QuestionMarkParams | |
| -- ^ Traditional @?@ placeholders (persistent style). Each @?@ is a | |
| -- distinct positional parameter. | |
| | NumberedParams !Int | |
| -- ^ PostgreSQL-native @$N@ placeholders. The 'Int' is the highest | |
| -- @$N@ found. A single @$1@ can appear multiple times in the query, | |
| -- referencing the same parameter value. | |
| = -- | Traditional @?@ placeholders (persistent style). Each @?@ is a | |
| -- distinct positional parameter. | |
| QuestionMarkParams | |
| | -- | PostgreSQL-native @$N@ placeholders. The 'Int' is the highest | |
| -- @$N@ found. A single @$1@ can appear multiple times in the query, | |
| -- referencing the same parameter value. | |
| NumberedParams !Int |
| (T.pack $ "Person " <> show i) | ||
| (20 + i `mod` 60) | ||
| (T.pack $ "person" <> show i <> "@test.com") | ||
| | i <- [1..n] |
There was a problem hiding this comment.
Restyled by fourmolu
| | i <- [1..n] | |
| | i <- [1 .. n] |
| | FetchSingleRow | ||
| -- ^ Single-row mode (@PQsetSingleRowMode@). Each @PGresult@ contains |
There was a problem hiding this comment.
Restyled by fourmolu
| | FetchSingleRow | |
| -- ^ Single-row mode (@PQsetSingleRowMode@). Each @PGresult@ contains | |
| FetchAll | |
| | -- | Single-row mode (@PQsetSingleRowMode@). Each @PGresult@ contains |
| LibPQ.FlushOk -> return () | ||
| LibPQ.FlushFailed -> throwIO $ PipelineExecError "flush failed" |
There was a problem hiding this comment.
Restyled by fourmolu
| LibPQ.FlushOk -> return () | |
| LibPQ.FlushFailed -> throwIO $ PipelineExecError "flush failed" | |
| LibPQ.FlushOk -> return () | |
| LibPQ.FlushFailed -> throwIO $ PipelineExecError "flush failed" |
| Database.Persist.Postgresql.Pipeline.FFI | ||
| Database.Persist.Postgresql.Internal | ||
| Database.Persist.Postgresql.Internal.Decoding | ||
| Database.Persist.Postgresql.Internal.Encoding |
There was a problem hiding this comment.
Restyled by cabal-fmt
| Database.Persist.Postgresql.Internal.Encoding |
| aeson >=1.0 | ||
| , base >=4.9 && <5 | ||
| , bytestring >=0.10 | ||
| , bytestring-strict-builder >=0.4 | ||
| , conduit >=1.2.12 | ||
| , containers >=0.5 | ||
| , file-embed >=0.0.16 | ||
| , monad-logger >=0.3.25 |
There was a problem hiding this comment.
Restyled by cabal-fmt
| aeson >=1.0 | |
| , base >=4.9 && <5 | |
| , bytestring >=0.10 | |
| , bytestring-strict-builder >=0.4 | |
| , conduit >=1.2.12 | |
| , containers >=0.5 | |
| , file-embed >=0.0.16 | |
| , monad-logger >=0.3.25 | |
| aeson >=1.0 | |
| , base >=4.9 && <5 | |
| , bytestring >=0.10 | |
| , bytestring-strict-builder >=0.4 | |
| , conduit >=1.2.12 | |
| , containers >=0.5 | |
| , file-embed >=0.0.16 | |
| , monad-logger >=0.3.25 |
| , bytestring | ||
| , containers | ||
| , fast-logger | ||
| , hspec >=2.4 |
There was a problem hiding this comment.
Restyled by cabal-fmt
| , hspec >=2.4 | |
| , hspec >=2.4 |
| ghc-options: -Wall | ||
| build-depends: | ||
| aeson | ||
| , base >=4.9 && <5 |
There was a problem hiding this comment.
Restyled by cabal-fmt
| , base >=4.9 && <5 | |
| , base >=4.9 && <5 |
| _ -> do | ||
| merr <- LibPQ.errorMessage conn | ||
| LibPQ.finish conn | ||
| let msg = maybe "Unknown connection error" B8.unpack merr |
There was a problem hiding this comment.
Restyled by fourmolu
| let msg = maybe "Unknown connection error" B8.unpack merr | |
| let | |
| msg = maybe "Unknown connection error" B8.unpack merr |
| build-depends: | ||
| base >=4.9 && <5 | ||
| , bytestring | ||
| , criterion >=1.5 |
There was a problem hiding this comment.
Restyled by cabal-fmt
| , criterion >=1.5 | |
| , criterion >=1.5 |
| mapM_ delete delKeys | ||
| forM_ updKeys $ \k -> update k [BenchPersonAge =. 99] | ||
| forM_ (zip repKeys (people 100)) $ \(k, person) -> | ||
| replace k (person { benchPersonAge = 42 }) |
There was a problem hiding this comment.
Restyled by fourmolu
| replace k (person { benchPersonAge = 42 }) | |
| replace k (person{benchPersonAge = 42}) |
| -> ReaderT (PgPipeline.WriteBackend PgPipeline.PostgreSQLBackend) IO a -> IO a | ||
| pl pool action = runSqlPool action pool | ||
|
|
||
|
|
There was a problem hiding this comment.
Restyled by fourmolu
| import Data.Pool (Pool) | ||
| import Data.Text (Text) | ||
| import qualified Data.Text as T | ||
| import Control.Monad.Trans.Reader (ReaderT, withReaderT) |
There was a problem hiding this comment.
Restyled by fourmolu
| import Control.Monad.Trans.Reader (ReaderT, withReaderT) |
| scalarCUInt PgInterval = 1186 | ||
| scalarCUInt PgBit = 1560 | ||
| scalarCUInt PgVarbit = 1562 | ||
| scalarCUInt PgNumeric = 1700 | ||
| scalarCUInt PgVoid = 2278 | ||
| scalarCUInt PgJson = 114 | ||
| scalarCUInt PgJsonb = 3802 | ||
| scalarCUInt PgUnknown = 705 | ||
| scalarCUInt PgUuid = 2950 |
There was a problem hiding this comment.
Restyled by fourmolu
| scalarCUInt PgInterval = 1186 | |
| scalarCUInt PgBit = 1560 | |
| scalarCUInt PgVarbit = 1562 | |
| scalarCUInt PgNumeric = 1700 | |
| scalarCUInt PgVoid = 2278 | |
| scalarCUInt PgJson = 114 | |
| scalarCUInt PgJsonb = 3802 | |
| scalarCUInt PgUnknown = 705 | |
| scalarCUInt PgUuid = 2950 | |
| scalarCUInt PgInterval = 1186 | |
| scalarCUInt PgBit = 1560 | |
| scalarCUInt PgVarbit = 1562 | |
| scalarCUInt PgNumeric = 1700 | |
| scalarCUInt PgVoid = 2278 | |
| scalarCUInt PgJson = 114 | |
| scalarCUInt PgJsonb = 3802 | |
| scalarCUInt PgUnknown = 705 | |
| scalarCUInt PgUuid = 2950 |
| drainToSyncClose conn = do | ||
| mret <- LibPQ.getResult conn | ||
| case mret of | ||
| Nothing -> drainToSyncClose conn -- NULL separator, keep reading |
There was a problem hiding this comment.
Restyled by fourmolu
| Nothing -> drainToSyncClose conn -- NULL separator, keep reading | |
| Nothing -> drainToSyncClose conn -- NULL separator, keep reading |
| | PgUnknown | ||
| -- ^ The PostgreSQL @unknown@ pseudotype (OID 705), used for untyped | ||
| -- string literals. Not to be confused with 'Unrecognized'. |
There was a problem hiding this comment.
Restyled by fourmolu
| | PgUnknown | |
| -- ^ The PostgreSQL @unknown@ pseudotype (OID 705), used for untyped | |
| -- string literals. Not to be confused with 'Unrecognized'. | |
| | -- | The PostgreSQL @unknown@ pseudotype (OID 705), used for untyped | |
| -- string literals. Not to be confused with 'Unrecognized'. | |
| PgUnknown |
| let (_, pt) = pgCols env V.! col | ||
| in case pt of | ||
| Scalar PgText -> onOk (mkRunner col PD.text_strict) | ||
| Scalar PgVarchar -> onOk (mkRunner col PD.text_strict) | ||
| Scalar PgBpchar -> onOk (mkRunner col PD.text_strict) | ||
| Scalar PgChar -> onOk (mkRunner col PD.text_strict) | ||
| Scalar PgName -> onOk (mkRunner col PD.text_strict) | ||
| _ -> mismatch pt "Text" onErr |
There was a problem hiding this comment.
Restyled by fourmolu
| let (_, pt) = pgCols env V.! col | |
| in case pt of | |
| Scalar PgText -> onOk (mkRunner col PD.text_strict) | |
| Scalar PgVarchar -> onOk (mkRunner col PD.text_strict) | |
| Scalar PgBpchar -> onOk (mkRunner col PD.text_strict) | |
| Scalar PgChar -> onOk (mkRunner col PD.text_strict) | |
| Scalar PgName -> onOk (mkRunner col PD.text_strict) | |
| _ -> mismatch pt "Text" onErr | |
| let | |
| (_, pt) = pgCols env V.! col | |
| in | |
| case pt of | |
| Scalar PgText -> onOk (mkRunner col PD.text_strict) | |
| Scalar PgVarchar -> onOk (mkRunner col PD.text_strict) | |
| Scalar PgBpchar -> onOk (mkRunner col PD.text_strict) | |
| Scalar PgChar -> onOk (mkRunner col PD.text_strict) | |
| Scalar PgName -> onOk (mkRunner col PD.text_strict) | |
| _ -> mismatch pt "Text" onErr |
| | otherwise = BS.pack $ concat | ||
| [ hexBytes 0 4, [0x2D] | ||
| , hexBytes 4 2, [0x2D] | ||
| , hexBytes 6 2, [0x2D] | ||
| , hexBytes 8 2, [0x2D] | ||
| , hexBytes 10 6 | ||
| ] |
There was a problem hiding this comment.
Restyled by fourmolu
| | otherwise = BS.pack $ concat | |
| [ hexBytes 0 4, [0x2D] | |
| , hexBytes 4 2, [0x2D] | |
| , hexBytes 6 2, [0x2D] | |
| , hexBytes 8 2, [0x2D] | |
| , hexBytes 10 6 | |
| ] | |
| | otherwise = | |
| BS.pack $ | |
| concat | |
| [ hexBytes 0 4 | |
| , [0x2D] | |
| , hexBytes 4 2 | |
| , [0x2D] | |
| , hexBytes 6 2 | |
| , [0x2D] | |
| , hexBytes 8 2 | |
| , [0x2D] | |
| , hexBytes 10 6 | |
| ] |
| :: PgDecode a | ||
| => PgRowEnv -> FieldNameDB -> Int | ||
| -> (Text -> IO r) -> (FieldRunner PgRowEnv a -> IO r) -> IO r |
There was a problem hiding this comment.
Restyled by fourmolu
| :: PgDecode a | |
| => PgRowEnv -> FieldNameDB -> Int | |
| -> (Text -> IO r) -> (FieldRunner PgRowEnv a -> IO r) -> IO r | |
| :: (PgDecode a) | |
| => PgRowEnv | |
| -> FieldNameDB | |
| -> Int | |
| -> (Text -> IO r) | |
| -> (FieldRunner PgRowEnv a -> IO r) | |
| -> IO r |
| -- Generic array instance via PgDecode | ||
| --------------------------------------------------------------------------- | ||
|
|
||
| instance {-# OVERLAPPABLE #-} PgDecode a => FieldDecode PgRowEnv [a] where |
There was a problem hiding this comment.
Restyled by fourmolu
| instance {-# OVERLAPPABLE #-} PgDecode a => FieldDecode PgRowEnv [a] where | |
| instance {-# OVERLAPPABLE #-} (PgDecode a) => FieldDecode PgRowEnv [a] where |
| pgTypeOid (Scalar s) = scalarOid s | ||
| pgTypeOid (Array s) = maybe (LibPQ.Oid 0) id (arrayOid s) | ||
| pgTypeOid (Composite _ _) = LibPQ.Oid 0 | ||
| pgTypeOid (CompositeArray _) = LibPQ.Oid 0 | ||
| pgTypeOid (Enum _ _) = LibPQ.Oid 0 | ||
| pgTypeOid (EnumArray _) = LibPQ.Oid 0 | ||
| pgTypeOid (Unrecognized n) = LibPQ.Oid (fromIntegral n) |
There was a problem hiding this comment.
Restyled by fourmolu
| pgTypeOid (Scalar s) = scalarOid s | |
| pgTypeOid (Array s) = maybe (LibPQ.Oid 0) id (arrayOid s) | |
| pgTypeOid (Composite _ _) = LibPQ.Oid 0 | |
| pgTypeOid (CompositeArray _) = LibPQ.Oid 0 | |
| pgTypeOid (Enum _ _) = LibPQ.Oid 0 | |
| pgTypeOid (EnumArray _) = LibPQ.Oid 0 | |
| pgTypeOid (Unrecognized n) = LibPQ.Oid (fromIntegral n) | |
| pgTypeOid (Scalar s) = scalarOid s | |
| pgTypeOid (Array s) = maybe (LibPQ.Oid 0) id (arrayOid s) | |
| pgTypeOid (Composite _ _) = LibPQ.Oid 0 | |
| pgTypeOid (CompositeArray _) = LibPQ.Oid 0 | |
| pgTypeOid (Enum _ _) = LibPQ.Oid 0 | |
| pgTypeOid (EnumArray _) = LibPQ.Oid 0 | |
| pgTypeOid (Unrecognized n) = LibPQ.Oid (fromIntegral n) |
| in case pt of | ||
| Array _ -> onOk (mkRunner col decoder) | ||
| Unrecognized _ -> onOk (mkRunner col decoder) | ||
| _ -> mismatch pt "array" onErr |
There was a problem hiding this comment.
Restyled by fourmolu
| in case pt of | |
| Array _ -> onOk (mkRunner col decoder) | |
| Unrecognized _ -> onOk (mkRunner col decoder) | |
| _ -> mismatch pt "array" onErr | |
| in | |
| case pt of | |
| Array _ -> onOk (mkRunner col decoder) | |
| Unrecognized _ -> onOk (mkRunner col decoder) | |
| _ -> mismatch pt "array" onErr |
| let (_, pt) = pgCols env V.! col | ||
| in case pt of | ||
| Scalar PgBytea -> onOk (mkRunner col PD.bytea_strict) | ||
| Scalar PgXml -> onOk (mkRunner col PD.bytea_strict) | ||
| Scalar PgJson -> onOk (mkRunner col PD.bytea_strict) | ||
| Scalar PgJsonb -> onOk (mkRunner col (PD.jsonb_bytes Right)) | ||
| Scalar PgBit -> onOk (mkRunner col PD.bytea_strict) | ||
| Scalar PgVarbit -> onOk (mkRunner col PD.bytea_strict) | ||
| Scalar PgUnknown -> onOk (mkRunner col PD.bytea_strict) | ||
| _ -> mismatch pt "ByteString" onErr |
There was a problem hiding this comment.
Restyled by fourmolu
| let (_, pt) = pgCols env V.! col | |
| in case pt of | |
| Scalar PgBytea -> onOk (mkRunner col PD.bytea_strict) | |
| Scalar PgXml -> onOk (mkRunner col PD.bytea_strict) | |
| Scalar PgJson -> onOk (mkRunner col PD.bytea_strict) | |
| Scalar PgJsonb -> onOk (mkRunner col (PD.jsonb_bytes Right)) | |
| Scalar PgBit -> onOk (mkRunner col PD.bytea_strict) | |
| Scalar PgVarbit -> onOk (mkRunner col PD.bytea_strict) | |
| Scalar PgUnknown -> onOk (mkRunner col PD.bytea_strict) | |
| _ -> mismatch pt "ByteString" onErr | |
| let | |
| (_, pt) = pgCols env V.! col | |
| in | |
| case pt of | |
| Scalar PgBytea -> onOk (mkRunner col PD.bytea_strict) | |
| Scalar PgXml -> onOk (mkRunner col PD.bytea_strict) | |
| Scalar PgJson -> onOk (mkRunner col PD.bytea_strict) | |
| Scalar PgJsonb -> onOk (mkRunner col (PD.jsonb_bytes Right)) | |
| Scalar PgBit -> onOk (mkRunner col PD.bytea_strict) | |
| Scalar PgVarbit -> onOk (mkRunner col PD.bytea_strict) | |
| Scalar PgUnknown -> onOk (mkRunner col PD.bytea_strict) | |
| _ -> mismatch pt "ByteString" onErr |
| decodeByType (Scalar PgInterval) bs = PersistRational . toRational <$> run PD.interval_int bs | ||
| decodeByType (Scalar PgBit) bs = PersistByteString <$> run PD.bytea_strict bs | ||
| decodeByType (Scalar PgVarbit) bs = PersistByteString <$> run PD.bytea_strict bs | ||
| decodeByType (Scalar PgNumeric) bs = decodeNumeric bs | ||
| decodeByType (Scalar PgVoid) _ = Right PersistNull | ||
| decodeByType (Scalar PgJson) bs = PersistByteString <$> run PD.bytea_strict bs | ||
| decodeByType (Scalar PgJsonb) bs = PersistByteString <$> decodeJsonb bs | ||
| decodeByType (Scalar PgUnknown) bs = PersistByteString <$> run PD.bytea_strict bs | ||
| decodeByType (Scalar PgUuid) bs = do |
There was a problem hiding this comment.
Restyled by fourmolu
| decodeByType (Scalar PgInterval) bs = PersistRational . toRational <$> run PD.interval_int bs | |
| decodeByType (Scalar PgBit) bs = PersistByteString <$> run PD.bytea_strict bs | |
| decodeByType (Scalar PgVarbit) bs = PersistByteString <$> run PD.bytea_strict bs | |
| decodeByType (Scalar PgNumeric) bs = decodeNumeric bs | |
| decodeByType (Scalar PgVoid) _ = Right PersistNull | |
| decodeByType (Scalar PgJson) bs = PersistByteString <$> run PD.bytea_strict bs | |
| decodeByType (Scalar PgJsonb) bs = PersistByteString <$> decodeJsonb bs | |
| decodeByType (Scalar PgUnknown) bs = PersistByteString <$> run PD.bytea_strict bs | |
| decodeByType (Scalar PgUuid) bs = do | |
| decodeByType (Scalar PgInterval) bs = PersistRational . toRational <$> run PD.interval_int bs | |
| decodeByType (Scalar PgBit) bs = PersistByteString <$> run PD.bytea_strict bs | |
| decodeByType (Scalar PgVarbit) bs = PersistByteString <$> run PD.bytea_strict bs | |
| decodeByType (Scalar PgNumeric) bs = decodeNumeric bs | |
| decodeByType (Scalar PgVoid) _ = Right PersistNull | |
| decodeByType (Scalar PgJson) bs = PersistByteString <$> run PD.bytea_strict bs | |
| decodeByType (Scalar PgJsonb) bs = PersistByteString <$> decodeJsonb bs | |
| decodeByType (Scalar PgUnknown) bs = PersistByteString <$> run PD.bytea_strict bs | |
| decodeByType (Scalar PgUuid) bs = do |
| import Data.Scientific (Scientific) | ||
| import Data.Text (Text) | ||
| import Data.Time (localTimeToUTC, utc) | ||
| import qualified Database.PostgreSQL.LibPQ as LibPQ |
There was a problem hiding this comment.
Restyled by fourmolu
| import qualified Database.PostgreSQL.LibPQ as LibPQ | |
| import Data.Word (Word8) |
| Unrecognized _ -> onOk (mkRunner col decoder) | ||
| _ -> mismatch pt "array" onErr | ||
|
|
||
| instance {-# OVERLAPPING #-} PgDecode a => FieldDecode PgRowEnv [Maybe a] where |
There was a problem hiding this comment.
Restyled by fourmolu
| instance {-# OVERLAPPING #-} PgDecode a => FieldDecode PgRowEnv [Maybe a] where | |
| instance {-# OVERLAPPING #-} (PgDecode a) => FieldDecode PgRowEnv [Maybe a] where |
| let (_, pt) = pgCols env V.! col | ||
| in case pt of | ||
| Scalar PgNumeric -> onOk (mkRunnerWith col PD.numeric (toRational :: Scientific -> Rational)) | ||
| Scalar PgMoney -> onOk (mkRunnerWith col (PD.int :: PD.Value Int64) fromIntegral) | ||
| _ -> mismatch pt "Rational" onErr |
There was a problem hiding this comment.
Restyled by fourmolu
| let (_, pt) = pgCols env V.! col | |
| in case pt of | |
| Scalar PgNumeric -> onOk (mkRunnerWith col PD.numeric (toRational :: Scientific -> Rational)) | |
| Scalar PgMoney -> onOk (mkRunnerWith col (PD.int :: PD.Value Int64) fromIntegral) | |
| _ -> mismatch pt "Rational" onErr | |
| let | |
| (_, pt) = pgCols env V.! col | |
| in | |
| case pt of | |
| Scalar PgNumeric -> onOk (mkRunnerWith col PD.numeric (toRational :: Scientific -> Rational)) | |
| Scalar PgMoney -> onOk (mkRunnerWith col (PD.int :: PD.Value Int64) fromIntegral) | |
| _ -> mismatch pt "Rational" onErr |
| let (_, pt) = pgCols env V.! col | ||
| in case pt of | ||
| Scalar PgInt8 -> onOk (mkRunner col (PD.int :: PD.Value Int64)) | ||
| Scalar PgInt4 -> onOk (mkRunnerWith col (PD.int :: PD.Value Int32) fromIntegral) | ||
| Scalar PgInt2 -> onOk (mkRunnerWith col (PD.int :: PD.Value Int16) fromIntegral) | ||
| _ -> mismatch pt "Int64" onErr |
There was a problem hiding this comment.
Restyled by fourmolu
| let (_, pt) = pgCols env V.! col | |
| in case pt of | |
| Scalar PgInt8 -> onOk (mkRunner col (PD.int :: PD.Value Int64)) | |
| Scalar PgInt4 -> onOk (mkRunnerWith col (PD.int :: PD.Value Int32) fromIntegral) | |
| Scalar PgInt2 -> onOk (mkRunnerWith col (PD.int :: PD.Value Int16) fromIntegral) | |
| _ -> mismatch pt "Int64" onErr | |
| let | |
| (_, pt) = pgCols env V.! col | |
| in | |
| case pt of | |
| Scalar PgInt8 -> onOk (mkRunner col (PD.int :: PD.Value Int64)) | |
| Scalar PgInt4 -> onOk (mkRunnerWith col (PD.int :: PD.Value Int32) fromIntegral) | |
| Scalar PgInt2 -> onOk (mkRunnerWith col (PD.int :: PD.Value Int16) fromIntegral) | |
| _ -> mismatch pt "Int64" onErr |
| arrayCUInt PgInterval = Just 1187 | ||
| arrayCUInt PgBit = Just 1561 | ||
| arrayCUInt PgVarbit = Just 1563 | ||
| arrayCUInt PgNumeric = Just 1231 | ||
| arrayCUInt PgJson = Just 199 | ||
| arrayCUInt PgJsonb = Just 3807 | ||
| arrayCUInt PgUuid = Just 2951 | ||
| arrayCUInt PgVoid = Nothing | ||
| arrayCUInt PgUnknown = Nothing |
There was a problem hiding this comment.
Restyled by fourmolu
| arrayCUInt PgInterval = Just 1187 | |
| arrayCUInt PgBit = Just 1561 | |
| arrayCUInt PgVarbit = Just 1563 | |
| arrayCUInt PgNumeric = Just 1231 | |
| arrayCUInt PgJson = Just 199 | |
| arrayCUInt PgJsonb = Just 3807 | |
| arrayCUInt PgUuid = Just 2951 | |
| arrayCUInt PgVoid = Nothing | |
| arrayCUInt PgUnknown = Nothing | |
| arrayCUInt PgInterval = Just 1187 | |
| arrayCUInt PgBit = Just 1561 | |
| arrayCUInt PgVarbit = Just 1563 | |
| arrayCUInt PgNumeric = Just 1231 | |
| arrayCUInt PgJson = Just 199 | |
| arrayCUInt PgJsonb = Just 3807 | |
| arrayCUInt PgUuid = Just 2951 | |
| arrayCUInt PgVoid = Nothing | |
| arrayCUInt PgUnknown = Nothing |
| decodeByType (Scalar PgBool) bs = PersistBool <$> run PD.bool bs | ||
| decodeByType (Scalar PgBytea) bs = PersistByteString <$> run PD.bytea_strict bs | ||
| decodeByType (Scalar PgChar) bs = PersistText <$> run PD.text_strict bs | ||
| decodeByType (Scalar PgName) bs = PersistText <$> run PD.text_strict bs | ||
| decodeByType (Scalar PgInt8) bs = PersistInt64 <$> run (PD.int :: PD.Value Int64) bs | ||
| decodeByType (Scalar PgInt2) bs = PersistInt64 . fromIntegral <$> run (PD.int :: PD.Value Int16) bs | ||
| decodeByType (Scalar PgInt4) bs = PersistInt64 . fromIntegral <$> run (PD.int :: PD.Value Int32) bs | ||
| decodeByType (Scalar PgText) bs = PersistText <$> run PD.text_strict bs | ||
| decodeByType (Scalar PgXml) bs = PersistByteString <$> run PD.bytea_strict bs | ||
| decodeByType (Scalar PgFloat4) bs = PersistDouble . realToFrac <$> run PD.float4 bs | ||
| decodeByType (Scalar PgFloat8) bs = PersistDouble <$> run PD.float8 bs | ||
| decodeByType (Scalar PgMoney) bs = PersistRational . fromIntegral <$> run (PD.int :: PD.Value Int64) bs | ||
| decodeByType (Scalar PgBpchar) bs = PersistText <$> run PD.text_strict bs | ||
| decodeByType (Scalar PgVarchar) bs = PersistText <$> run PD.text_strict bs | ||
| decodeByType (Scalar PgDate) bs = PersistDay <$> run PD.date bs | ||
| decodeByType (Scalar PgTime) bs = PersistTimeOfDay <$> run PD.time_int bs | ||
| decodeByType (Scalar PgTimestamp) bs = PersistUTCTime . localTimeToUTC utc <$> run PD.timestamp_int bs |
There was a problem hiding this comment.
Restyled by fourmolu
| decodeByType (Scalar PgBool) bs = PersistBool <$> run PD.bool bs | |
| decodeByType (Scalar PgBytea) bs = PersistByteString <$> run PD.bytea_strict bs | |
| decodeByType (Scalar PgChar) bs = PersistText <$> run PD.text_strict bs | |
| decodeByType (Scalar PgName) bs = PersistText <$> run PD.text_strict bs | |
| decodeByType (Scalar PgInt8) bs = PersistInt64 <$> run (PD.int :: PD.Value Int64) bs | |
| decodeByType (Scalar PgInt2) bs = PersistInt64 . fromIntegral <$> run (PD.int :: PD.Value Int16) bs | |
| decodeByType (Scalar PgInt4) bs = PersistInt64 . fromIntegral <$> run (PD.int :: PD.Value Int32) bs | |
| decodeByType (Scalar PgText) bs = PersistText <$> run PD.text_strict bs | |
| decodeByType (Scalar PgXml) bs = PersistByteString <$> run PD.bytea_strict bs | |
| decodeByType (Scalar PgFloat4) bs = PersistDouble . realToFrac <$> run PD.float4 bs | |
| decodeByType (Scalar PgFloat8) bs = PersistDouble <$> run PD.float8 bs | |
| decodeByType (Scalar PgMoney) bs = PersistRational . fromIntegral <$> run (PD.int :: PD.Value Int64) bs | |
| decodeByType (Scalar PgBpchar) bs = PersistText <$> run PD.text_strict bs | |
| decodeByType (Scalar PgVarchar) bs = PersistText <$> run PD.text_strict bs | |
| decodeByType (Scalar PgDate) bs = PersistDay <$> run PD.date bs | |
| decodeByType (Scalar PgTime) bs = PersistTimeOfDay <$> run PD.time_int bs | |
| decodeByType (Scalar PgTimestamp) bs = PersistUTCTime . localTimeToUTC utc <$> run PD.timestamp_int bs | |
| decodeByType (Scalar PgBool) bs = PersistBool <$> run PD.bool bs | |
| decodeByType (Scalar PgBytea) bs = PersistByteString <$> run PD.bytea_strict bs | |
| decodeByType (Scalar PgChar) bs = PersistText <$> run PD.text_strict bs | |
| decodeByType (Scalar PgName) bs = PersistText <$> run PD.text_strict bs | |
| decodeByType (Scalar PgInt8) bs = PersistInt64 <$> run (PD.int :: PD.Value Int64) bs | |
| decodeByType (Scalar PgInt2) bs = PersistInt64 . fromIntegral <$> run (PD.int :: PD.Value Int16) bs | |
| decodeByType (Scalar PgInt4) bs = PersistInt64 . fromIntegral <$> run (PD.int :: PD.Value Int32) bs | |
| decodeByType (Scalar PgText) bs = PersistText <$> run PD.text_strict bs | |
| decodeByType (Scalar PgXml) bs = PersistByteString <$> run PD.bytea_strict bs | |
| decodeByType (Scalar PgFloat4) bs = PersistDouble . realToFrac <$> run PD.float4 bs | |
| decodeByType (Scalar PgFloat8) bs = PersistDouble <$> run PD.float8 bs | |
| decodeByType (Scalar PgMoney) bs = PersistRational . fromIntegral <$> run (PD.int :: PD.Value Int64) bs | |
| decodeByType (Scalar PgBpchar) bs = PersistText <$> run PD.text_strict bs | |
| decodeByType (Scalar PgVarchar) bs = PersistText <$> run PD.text_strict bs | |
| decodeByType (Scalar PgDate) bs = PersistDay <$> run PD.date bs | |
| decodeByType (Scalar PgTime) bs = PersistTimeOfDay <$> run PD.time_int bs | |
| decodeByType (Scalar PgTimestamp) bs = PersistUTCTime . localTimeToUTC utc <$> run PD.timestamp_int bs |
| fromCUInt 16 = Scalar PgBool | ||
| fromCUInt 17 = Scalar PgBytea | ||
| fromCUInt 18 = Scalar PgChar | ||
| fromCUInt 19 = Scalar PgName | ||
| fromCUInt 20 = Scalar PgInt8 | ||
| fromCUInt 21 = Scalar PgInt2 | ||
| fromCUInt 23 = Scalar PgInt4 | ||
| fromCUInt 25 = Scalar PgText | ||
| fromCUInt 114 = Scalar PgJson | ||
| fromCUInt 142 = Scalar PgXml | ||
| fromCUInt 700 = Scalar PgFloat4 | ||
| fromCUInt 701 = Scalar PgFloat8 | ||
| fromCUInt 705 = Scalar PgUnknown | ||
| fromCUInt 790 = Scalar PgMoney |
There was a problem hiding this comment.
Restyled by fourmolu
| fromCUInt 16 = Scalar PgBool | |
| fromCUInt 17 = Scalar PgBytea | |
| fromCUInt 18 = Scalar PgChar | |
| fromCUInt 19 = Scalar PgName | |
| fromCUInt 20 = Scalar PgInt8 | |
| fromCUInt 21 = Scalar PgInt2 | |
| fromCUInt 23 = Scalar PgInt4 | |
| fromCUInt 25 = Scalar PgText | |
| fromCUInt 114 = Scalar PgJson | |
| fromCUInt 142 = Scalar PgXml | |
| fromCUInt 700 = Scalar PgFloat4 | |
| fromCUInt 701 = Scalar PgFloat8 | |
| fromCUInt 705 = Scalar PgUnknown | |
| fromCUInt 790 = Scalar PgMoney | |
| fromCUInt 16 = Scalar PgBool | |
| fromCUInt 17 = Scalar PgBytea | |
| fromCUInt 18 = Scalar PgChar | |
| fromCUInt 19 = Scalar PgName | |
| fromCUInt 20 = Scalar PgInt8 | |
| fromCUInt 21 = Scalar PgInt2 | |
| fromCUInt 23 = Scalar PgInt4 | |
| fromCUInt 25 = Scalar PgText | |
| fromCUInt 114 = Scalar PgJson | |
| fromCUInt 142 = Scalar PgXml | |
| fromCUInt 700 = Scalar PgFloat4 | |
| fromCUInt 701 = Scalar PgFloat8 | |
| fromCUInt 705 = Scalar PgUnknown | |
| fromCUInt 790 = Scalar PgMoney |
Summary
A PostgreSQL backend for persistent using the binary wire protocol and libpq pipeline mode.
Benchmarks (1ms latency per direction)