feat: int8 support

This commit is contained in:
orion 2023-12-16 15:24:47 -06:00
parent f8e31d1d67
commit 1fe1639265
Signed by: orion
GPG Key ID: 6D4165AE4C928719
3 changed files with 42 additions and 6 deletions

View File

@ -20,6 +20,7 @@ package:
- "foreign-object"
- "identity"
- "integers"
- js-bigints
- "js-date"
- "lists"
- "maybe"

View File

@ -6,11 +6,10 @@ module Database.PostgreSQL.Value where
import Prelude
import Control.Monad.Error.Class (throwError)
import Control.Monad.Error.Class (liftMaybe, throwError)
import Control.Monad.Except (ExceptT, except, runExcept, runExceptT)
import Data.Argonaut (Json)
import Data.Argonaut (stringify) as Argonaut
import Data.Foldable (foldl)
import Data.Array as Array
import Data.Bifunctor (lmap)
import Data.ByteString (ByteString)
@ -20,6 +19,7 @@ import Data.Decimal (Decimal)
import Data.Decimal as Decimal
import Data.Either (Either(..), note)
import Data.Enum (fromEnum, toEnum)
import Data.Foldable (foldl)
import Data.Identity (Identity)
import Data.Int (fromString)
import Data.JSDate (JSDate)
@ -34,6 +34,8 @@ import Data.Traversable (sequence, traverse)
import Foreign (Foreign, ForeignError(..), MultipleErrors, isNull, readArray, readBoolean, readChar, readInt, readNumber, readString, renderForeignError, unsafeFromForeign, unsafeToForeign)
import Foreign.Generic.Internal (readObject)
import Foreign.Object (Object)
import JS.BigInt (BigInt)
import JS.BigInt as BigInt
-- | Convert things to SQL values.
class ToSQLValue a where
@ -49,6 +51,13 @@ instance fromSQLValueBoolean :: FromSQLValue Boolean where
else instance fromSQLValueChar :: FromSQLValue Char where
fromSQLValue = lmap show <<< runExcept <<< readChar
else instance fromSQLValueBigInt :: FromSQLValue BigInt where
fromSQLValue =
lmap show
<<< runExcept
<<< flip bind (\s -> liftMaybe (pure $ ForeignError $ "invalid bigint: " <> s) $ BigInt.fromString s)
<<< readString
else instance fromSQLValueInt :: FromSQLValue Int where
fromSQLValue = lmap show <<< runExcept <<< readInt
@ -130,6 +139,9 @@ instance toSQLValueBoolean :: ToSQLValue Boolean where
else instance toSQLValueChar :: ToSQLValue Char where
toSQLValue = unsafeToForeign
else instance toSQLValueBigInt :: ToSQLValue BigInt where
toSQLValue = unsafeToForeign <<< BigInt.toString
else instance toSQLValueInt :: ToSQLValue Int where
toSQLValue = unsafeToForeign

View File

@ -23,7 +23,7 @@ import Data.Newtype (unwrap)
import Data.Number ((%))
import Data.Tuple (Tuple(..))
import Data.Tuple.Nested ((/\))
import Database.PostgreSQL (Client, Configuration, Connection(..), PGConnectionURI, PGError(..), Pool, Query(Query), Row0(Row0), Row1(Row1), Row2(Row2), Row3(Row3), Row9(Row9), fromClient, fromPool, parseURI)
import Database.PostgreSQL (Client, Configuration, Connection(..), PGConnectionURI, PGError(..), Pool, Query(Query), Row0(Row0), Row1(Row1), Row12(..), Row2(Row2), Row3(Row3), Row9(Row9), fromClient, fromPool, parseURI)
import Database.PostgreSQL.PG (command, execute, onIntegrityError, query, scalar)
import Database.PostgreSQL.PG (withClient, withClientTransaction) as PG
import Database.PostgreSQL.Pool (new) as Pool
@ -34,6 +34,8 @@ import Effect.Class (liftEffect)
import Effect.Exception (message)
import Foreign.Object (Object)
import Foreign.Object (fromFoldable) as Object
import JS.BigInt (BigInt)
import JS.BigInt as BigInt
import JS.Unsafe.Stringify (unsafeStringify)
import Partial.Unsafe (unsafePartial)
import Test.Assert (assert)
@ -45,6 +47,9 @@ import Test.Unit as Test.Unit
import Test.Unit.Assert (equal)
import Test.Unit.Main (runTest)
bigintFromString :: String -> BigInt
bigintFromString = unsafePartial fromJust <<< BigInt.fromString
withClient :: forall a. Pool -> (Client -> AppM a) -> AppM a
withClient = PG.withClient runExceptT
@ -124,6 +129,7 @@ main = do
delicious boolean NOT NULL,
price NUMERIC(4,2) NOT NULL,
added TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
huge_number INT8 NULL,
PRIMARY KEY (name)
);
CREATE TEMPORARY TABLE dates (
@ -263,20 +269,23 @@ main = do
execute handle
( Query
"""
INSERT INTO foods (name, delicious, price)
VALUES ($1, $2, $3), ($4, $5, $6), ($7, $8, $9)
INSERT INTO foods (name, delicious, price, huge_number)
VALUES ($1, $2, $3, $4), ($5, $6, $7, $8), ($9, $10, $11, $12)
"""
)
( Row9
( Row12
"pork"
true
(D.fromString "8.30")
(bigintFromString "123")
"sauerkraut"
false
(D.fromString "3.30")
(bigintFromString "456")
"rookworst"
true
(D.fromString "5.60")
(bigintFromString "789")
)
test handle "select column subset"
$ do
@ -358,6 +367,20 @@ main = do
)
Row0
liftEffect <<< assert $ sauerkrautPrice == [ Row1 (D.fromString "3.30") ]
test handle "handling bigint value"
$ do
insertFood
hugeNumber <-
query handle
( Query
"""
SELECT huge_number
FROM foods
WHERE NOT delicious
"""
)
Row0
liftEffect <<< assert $ hugeNumber == [ Row1 (bigintFromString "456") ]
transactionTest "integrity error handling"
$ do
withRollback client do