generated from tpl/purs
Handle Argonaut.Json
This commit is contained in:
parent
71d55170dc
commit
0df63e841d
@ -1,6 +1,8 @@
|
|||||||
# purescript-postgresql-client
|
# purescript-postgresql-client
|
||||||
|
|
||||||
purescript-postgresql-client is a PostgreSQL client library for PureScript.
|
## Type conversions / serialization
|
||||||
|
|
||||||
|
purescript-postgresql-client is a PostgreSQL client library for PureScript based on `node-postgres`.
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ You can edit this file as you like.
|
|||||||
, dependencies =
|
, dependencies =
|
||||||
[ "aff"
|
[ "aff"
|
||||||
, "arrays"
|
, "arrays"
|
||||||
|
, "argonaut"
|
||||||
, "assert"
|
, "assert"
|
||||||
, "bifunctors"
|
, "bifunctors"
|
||||||
, "bytestrings"
|
, "bytestrings"
|
||||||
|
@ -3,6 +3,11 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
// `pg related code/bindings are done here as we want to
|
||||||
|
// allow web related modules to access `PostgreSQL.*` classes.
|
||||||
|
// Putting this import into `PostgreSQL/Value.js` caused problem
|
||||||
|
// with web bundlers.
|
||||||
|
|
||||||
var pg = require('pg');
|
var pg = require('pg');
|
||||||
|
|
||||||
// pg does strange thing converting DATE
|
// pg does strange thing converting DATE
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
module Database.PostgreSQL.Value where
|
module Database.PostgreSQL.Value where
|
||||||
|
|
||||||
|
-- | `node-postgres` is playing guessing game regarding type conversions
|
||||||
|
-- | so we are overriding its defualt behavior for some types - please
|
||||||
|
-- | check PostgreSQL.js
|
||||||
|
|
||||||
import Prelude
|
import Prelude
|
||||||
|
|
||||||
import Control.Monad.Error.Class (throwError)
|
import Control.Monad.Error.Class (throwError)
|
||||||
import Control.Monad.Except (ExceptT, except, runExcept, runExceptT)
|
import Control.Monad.Except (ExceptT, except, runExcept, runExceptT)
|
||||||
|
import Data.Argonaut (Json)
|
||||||
|
import Data.Argonaut (stringify) as Argonaut
|
||||||
import Data.Array (foldl)
|
import Data.Array (foldl)
|
||||||
import Data.Array as Array
|
import Data.Array as Array
|
||||||
import Data.Bifunctor (lmap)
|
import Data.Bifunctor (lmap)
|
||||||
@ -93,7 +99,7 @@ else instance fromSQLValueMaybe :: (FromSQLValue a) => FromSQLValue (Maybe a) wh
|
|||||||
else instance fromSQLValueForeign :: FromSQLValue Foreign where
|
else instance fromSQLValueForeign :: FromSQLValue Foreign where
|
||||||
fromSQLValue = pure
|
fromSQLValue = pure
|
||||||
|
|
||||||
else instance fromSQLValueObject ∷ FromSQLValue a ⇒ FromSQLValue (Object a) where
|
else instance fromSQLValueObject :: FromSQLValue a ⇒ FromSQLValue (Object a) where
|
||||||
fromSQLValue sql = lmap showErr $ unwrap $ runExceptT main
|
fromSQLValue sql = lmap showErr $ unwrap $ runExceptT main
|
||||||
where
|
where
|
||||||
showErr ∷ MultipleErrors → String
|
showErr ∷ MultipleErrors → String
|
||||||
@ -104,11 +110,15 @@ else instance fromSQLValueObject ∷ FromSQLValue a ⇒ FromSQLValue (Object a)
|
|||||||
let eso = sequence $ map fromSQLValue objF
|
let eso = sequence $ map fromSQLValue objF
|
||||||
let emo = lmap (singleton <<< ForeignError) eso
|
let emo = lmap (singleton <<< ForeignError) eso
|
||||||
except emo
|
except emo
|
||||||
|
|
||||||
else instance fromSQLValueDecimal :: FromSQLValue Decimal where
|
else instance fromSQLValueDecimal :: FromSQLValue Decimal where
|
||||||
fromSQLValue v = do
|
fromSQLValue v = do
|
||||||
s <- lmap show $ runExcept (readString v)
|
s <- lmap show $ runExcept (readString v)
|
||||||
note ("Decimal literal parsing failed: " <> s) (Decimal.fromString s)
|
note ("Decimal literal parsing failed: " <> s) (Decimal.fromString s)
|
||||||
|
|
||||||
|
else instance fromSQLValueJson :: FromSQLValue Json where
|
||||||
|
fromSQLValue = Right <<< unsafeFromForeign
|
||||||
|
|
||||||
newtypeFromSQLValue ∷ ∀ a b. Newtype a b ⇒ FromSQLValue b ⇒ Foreign → Either String a
|
newtypeFromSQLValue ∷ ∀ a b. Newtype a b ⇒ FromSQLValue b ⇒ Foreign → Either String a
|
||||||
newtypeFromSQLValue = map wrap <<< fromSQLValue
|
newtypeFromSQLValue = map wrap <<< fromSQLValue
|
||||||
|
|
||||||
@ -164,6 +174,12 @@ else instance toSQLValueObject ∷ ToSQLValue a ⇒ ToSQLValue (Object a) where
|
|||||||
else instance toSQLValueDecimal :: ToSQLValue Decimal where
|
else instance toSQLValueDecimal :: ToSQLValue Decimal where
|
||||||
toSQLValue = Decimal.toString >>> unsafeToForeign
|
toSQLValue = Decimal.toString >>> unsafeToForeign
|
||||||
|
|
||||||
|
else instance toSQLValueJson :: ToSQLValue Json where
|
||||||
|
-- | We are forced to stringify value here to avoid
|
||||||
|
-- | problems with pg auto conversions - please check for example:
|
||||||
|
-- | https://github.com/brianc/node-postgres/issues/1383
|
||||||
|
toSQLValue = Argonaut.stringify >>> unsafeToForeign
|
||||||
|
|
||||||
newtypeToSQLValue ∷ ∀ a b. Newtype a b ⇒ ToSQLValue b ⇒ a → Foreign
|
newtypeToSQLValue ∷ ∀ a b. Newtype a b ⇒ ToSQLValue b ⇒ a → Foreign
|
||||||
newtypeToSQLValue = unwrap >>> toSQLValue
|
newtypeToSQLValue = unwrap >>> toSQLValue
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@ import Prelude
|
|||||||
import Control.Monad.Error.Class (throwError, try)
|
import Control.Monad.Error.Class (throwError, try)
|
||||||
import Control.Monad.Except.Trans (runExceptT)
|
import Control.Monad.Except.Trans (runExceptT)
|
||||||
import Control.Monad.Trans.Class (lift)
|
import Control.Monad.Trans.Class (lift)
|
||||||
|
import Data.Argonaut (Json)
|
||||||
|
import Data.Argonaut (fromArray, fromObject, fromString) as Argonaut
|
||||||
import Data.Array (zip)
|
import Data.Array (zip)
|
||||||
import Data.Date (Date, canonicalDate)
|
import Data.Date (Date, canonicalDate)
|
||||||
import Data.DateTime.Instant (Instant, unInstant)
|
import Data.DateTime.Instant (Instant, unInstant)
|
||||||
@ -25,7 +27,8 @@ import Effect (Effect)
|
|||||||
import Effect.Aff (Aff, error, launchAff)
|
import Effect.Aff (Aff, error, launchAff)
|
||||||
import Effect.Class (liftEffect)
|
import Effect.Class (liftEffect)
|
||||||
import Effect.Exception (message)
|
import Effect.Exception (message)
|
||||||
import Foreign.Object (Object, fromFoldable)
|
import Foreign.Object (fromFoldable) as Object
|
||||||
|
import Foreign.Object (Object)
|
||||||
import Global.Unsafe (unsafeStringify)
|
import Global.Unsafe (unsafeStringify)
|
||||||
import Math ((%))
|
import Math ((%))
|
||||||
import Partial.Unsafe (unsafePartial)
|
import Partial.Unsafe (unsafePartial)
|
||||||
@ -286,9 +289,9 @@ main = do
|
|||||||
pgEqual 3 (length dates)
|
pgEqual 3 (length dates)
|
||||||
liftEffect <<< assert $ all (\(Tuple (Row1 r) e) -> e == r) $ (zip dates [d1, d2, d3])
|
liftEffect <<< assert $ all (\(Tuple (Row1 r) e) -> e == r) $ (zip dates [d1, d2, d3])
|
||||||
|
|
||||||
test conn "handling json and jsonb value" $ do
|
test conn "handling Foreign.Object as json and jsonb" $ do
|
||||||
let jsonIn = fromFoldable [Tuple "a" 1, Tuple "a" 2, Tuple "2" 3]
|
let jsonIn = Object.fromFoldable [Tuple "a" 1, Tuple "a" 2, Tuple "2" 3]
|
||||||
let expected = fromFoldable [Tuple "a" 2, Tuple "2" 3]
|
let expected = Object.fromFoldable [Tuple "a" 2, Tuple "2" 3]
|
||||||
|
|
||||||
execute conn (Query """
|
execute conn (Query """
|
||||||
INSERT INTO jsons (json, jsonb)
|
INSERT INTO jsons (json, jsonb)
|
||||||
@ -298,6 +301,28 @@ main = do
|
|||||||
(js ∷ Array (Row2 (Object Int) (Object Int))) <- query conn (Query """SELECT * FROM JSONS""") Row0
|
(js ∷ Array (Row2 (Object Int) (Object Int))) <- query conn (Query """SELECT * FROM JSONS""") Row0
|
||||||
liftEffect $ assert $ all (\(Row2 j1 j2) → j1 == expected && expected == j2) js
|
liftEffect $ assert $ all (\(Row2 j1 j2) → j1 == expected && expected == j2) js
|
||||||
|
|
||||||
|
test conn "handling Argonaut.Json as json and jsonb for an object" $ do
|
||||||
|
let input = Argonaut.fromObject (Object.fromFoldable [ Tuple "a" (Argonaut.fromString "value") ])
|
||||||
|
|
||||||
|
execute conn (Query """
|
||||||
|
INSERT INTO jsons (json, jsonb)
|
||||||
|
VALUES ($1, $2)
|
||||||
|
""") (Row2 input input)
|
||||||
|
|
||||||
|
(js ∷ Array (Row2 (Json) (Json))) <- query conn (Query """SELECT * FROM JSONS""") Row0
|
||||||
|
liftEffect $ assert $ all (\(Row2 j1 j2) → j1 == input && j2 == input) js
|
||||||
|
|
||||||
|
test conn "handling Argonaut.Json as json and jsonb for an array" $ do
|
||||||
|
let input = Argonaut.fromArray [ Argonaut.fromObject (Object.fromFoldable [ Tuple "a" (Argonaut.fromString "value") ])]
|
||||||
|
|
||||||
|
execute conn (Query """
|
||||||
|
INSERT INTO jsons (json, jsonb)
|
||||||
|
VALUES ($1, $2)
|
||||||
|
""") (Row2 input input)
|
||||||
|
|
||||||
|
(js ∷ Array (Row2 (Json) (Json))) <- query conn (Query """SELECT * FROM JSONS""") Row0
|
||||||
|
liftEffect $ assert $ all (\(Row2 j1 j2) → j1 == input && j2 == input) js
|
||||||
|
|
||||||
test conn "handling jsdate value" $ do
|
test conn "handling jsdate value" $ do
|
||||||
let
|
let
|
||||||
jsd1 = jsdate_ 2010.0 2.0 31.0 6.0 23.0 1.0 123.0
|
jsd1 = jsdate_ 2010.0 2.0 31.0 6.0 23.0 1.0 123.0
|
||||||
|
Loading…
Reference in New Issue
Block a user