packages feed

beam-postgres 0.5.4.3 → 0.5.4.4

raw patch · 4 files changed

+254/−2 lines, 4 filesPVP: minor bump suggested

API additions: PVP suggests at least a minor version bump

API changes (from Hackage documentation)

+ Database.Beam.Postgres: arrayAppend_ :: QGenExpr ctxt Postgres s (Vector a) -> QGenExpr ctxt Postgres s a -> QGenExpr ctxt Postgres s (Vector a)
+ Database.Beam.Postgres: arrayPrepend_ :: QGenExpr ctxt Postgres s a -> QGenExpr ctxt Postgres s (Vector a) -> QGenExpr ctxt Postgres s (Vector a)
+ Database.Beam.Postgres: arrayRemove_ :: QGenExpr ctxt Postgres s (Vector a) -> QGenExpr ctxt Postgres s a -> QGenExpr ctxt Postgres s (Vector a)
+ Database.Beam.Postgres: arrayReplace_ :: QGenExpr ctxt Postgres s (Vector a) -> QGenExpr ctxt Postgres s a -> QGenExpr ctxt Postgres s a -> QGenExpr ctxt Postgres s (Vector a)
+ Database.Beam.Postgres: arraySample_ :: Integral n => QGenExpr ctxt Postgres s (Vector a) -> QGenExpr ctxt Postgres s n -> QGenExpr ctxt Postgres s (Vector a)
+ Database.Beam.Postgres: arrayShuffle_ :: QGenExpr ctxt Postgres s (Vector a) -> QGenExpr ctxt Postgres s (Vector a)
+ Database.Beam.Postgres: arrayToStringWithNull_ :: QGenExpr ctxt Postgres s (Vector a) -> QGenExpr ctxt Postgres s Text -> QGenExpr ctxt Postgres s Text -> QGenExpr ctxt Postgres s Text
+ Database.Beam.Postgres: arrayToString_ :: QGenExpr ctxt Postgres s (Vector a) -> QGenExpr ctxt Postgres s Text -> QGenExpr ctxt Postgres s Text

Files

ChangeLog.md view
@@ -1,3 +1,13 @@+# 0.5.4.4++## Added features++* Added the array functions `arrayAppend_`, `arrayPrepend_`, `arrayRemove_`, `arrayReplace_`, `arrayShuffle_`, `arraySample_`, `arrayToString_`, and `arrayToStringWithNull_` (#770)++## Updated dependencies++* Updated the upper bound on `time` to include `time-1.14`+ # 0.5.4.3  ## Added features
Database/Beam/Postgres/PgSpecific.hs view
@@ -81,6 +81,9 @@   , arrayUpper_, arrayLower_   , arrayUpperUnsafe_, arrayLowerUnsafe_   , arrayLength_, arrayLengthUnsafe_+  , arrayAppend_, arrayPrepend_, arrayRemove_+  , arrayReplace_, arrayShuffle_, arraySample_+  , arrayToString_, arrayToStringWithNull_    , isSupersetOf_, isSubsetOf_ @@ -158,6 +161,7 @@  import           GHC.TypeLits import           GHC.Exts hiding (toList)+import           Data.Text (Text)  -- ** Postgres-specific functions @@ -410,6 +414,165 @@ QExpr a ++. QExpr b =   QExpr (pgBinOp "||" <$> a <*> b) +-- | Postgres array_append(value) function.+--+-- Appends an element to the end of an array. Equivalent to the+-- @anycompatiblearray || anycompatible@ operator.+--+-- Notes:+-- - The array must be empty or one-dimensional (per Postgres rules for+--   concatenating an element with an array).+-- - If the array is NULL, the result is NULL. If the element is NULL,+--   a NULL element is appended.+--+-- @since 0.5.4.4+arrayAppend_+  :: QGenExpr ctxt Postgres s (V.Vector a)+  -> QGenExpr ctxt Postgres s a+  -> QGenExpr ctxt Postgres s (V.Vector a)+arrayAppend_ (QExpr arr) (QExpr el) =+  QExpr (PgExpressionSyntax . mappend (emit "array_append") . pgParens . mconcat <$> sequenceA+    [ fromPgExpression <$> arr+    , pure (emit ", ")+    , fromPgExpression <$> el+    ])++-- | Postgres array_prepend(value) function.+--+-- Prepends an element to the beginning of an array. Equivalent to the+-- @anycompatible || anycompatiblearray@ operator.+--+-- Notes:+-- - The array must be empty or one-dimensional.+-- - If the array is NULL, the result is NULL. If the element is NULL,+--   a NULL element is prepended.+--+-- @since 0.5.4.4+arrayPrepend_+  :: QGenExpr ctxt Postgres s a+  -> QGenExpr ctxt Postgres s (V.Vector a)+  -> QGenExpr ctxt Postgres s (V.Vector a)+arrayPrepend_ (QExpr el) (QExpr arr) =+  QExpr (PgExpressionSyntax . mappend (emit "array_prepend") . pgParens . mconcat <$> sequenceA+    [ fromPgExpression <$> el+    , pure (emit ", ")+    , fromPgExpression <$> arr+    ])++-- | Postgres array_remove(value) function.+--+-- Removes all elements equal to the given value from the array.+-- Comparisons use @IS NOT DISTINCT FROM@ semantics, so this can remove NULLs.+--+-- Notes:+-- - The array must be one-dimensional.+-- - Returns NULL only if the array is NULL; if the value is not present,+--   the original array is returned unchanged.+--+-- @since 0.5.4.4+arrayRemove_+  :: QGenExpr ctxt Postgres s (V.Vector a)+  -> QGenExpr ctxt Postgres s a+  -> QGenExpr ctxt Postgres s (V.Vector a)+arrayRemove_ (QExpr arr) (QExpr el) =+  QExpr (PgExpressionSyntax . mappend (emit "array_remove") . pgParens . mconcat <$> sequenceA+    [ fromPgExpression <$> arr+    , pure (emit ", ")+    , fromPgExpression <$> el+    ])++-- | Postgres array_replace(array, from, to) function.+--+-- Replaces each element equal to the second argument with the third.+--+-- Notes:+-- - Comparisons use IS NOT DISTINCT FROM semantics; can replace NULLs.+-- - The array must be one-dimensional.+--+-- Example:+--+-- @+-- select_ $ pure $ arrayReplace_ (val_ $ V.fromList [1::Int32,2,5,4]) (val_ 5) (val_ 3)+-- -- => {1,2,3,4}+-- @+--+-- @since 0.5.4.4+arrayReplace_+  :: QGenExpr ctxt Postgres s (V.Vector a) -- ^ The array to operate on+  -> QGenExpr ctxt Postgres s a             -- ^ The value to be replaced+  -> QGenExpr ctxt Postgres s a             -- ^ The new value+  -> QGenExpr ctxt Postgres s (V.Vector a)+arrayReplace_ (QExpr arr) (QExpr fromVal) (QExpr toVal) =+  QExpr (PgExpressionSyntax . mappend (emit "array_replace") . pgParens . mconcat <$> sequenceA+    [ fromPgExpression <$> arr+    , pure (emit ", ")+    , fromPgExpression <$> fromVal+    , pure (emit ", ")+    , fromPgExpression <$> toVal+    ])++-- | Postgres array_shuffle(array) function.+-- Randomly shuffles the first dimension.+--+-- @since 0.5.4.4+arrayShuffle_+  :: QGenExpr ctxt Postgres s (V.Vector a)+  -> QGenExpr ctxt Postgres s (V.Vector a)+arrayShuffle_ (QExpr arr) =+  QExpr (PgExpressionSyntax . mappend (emit "array_shuffle") . pgParens . fromPgExpression <$> arr)++-- | Postgres array_sample(array, n) function.+-- Randomly selects @n@ items from the array. For multidimensional arrays,+-- an "item" is a slice with a given first subscript.+--+-- Precondition: @n@ must not exceed the length of the first dimension.+--   If n is negative, it will be treated as 0.+--+-- @since 0.5.4.4+arraySample_+  :: Integral n+  => QGenExpr ctxt Postgres s (V.Vector a)  -- ^ The source array+  -> QGenExpr ctxt Postgres s n             -- ^ Number of elements to sample (negative values treated as 0)+  -> QGenExpr ctxt Postgres s (V.Vector a)+arraySample_ (QExpr arr) (QExpr n) =+  QExpr (PgExpressionSyntax . mappend (emit "array_sample") . pgParens . mconcat <$> sequenceA+    [ fromPgExpression <$> arr+    , pure (emit ", greatest(0, ")+    , fromPgExpression <$> n+    , pure (emit ")")+    ])++-- | Postgres array_to_string(array, delimiter) function.+-- Converts each element to text and joins with the delimiter. NULLs are omitted.+--+-- @since 0.5.4.4+arrayToString_+  :: QGenExpr ctxt Postgres s (V.Vector a)+  -> QGenExpr ctxt Postgres s Text+  -> QGenExpr ctxt Postgres s Text+arrayToString_ (QExpr arr) (QExpr delim) =+  QExpr (PgExpressionSyntax <$> do+    arrExpr <- fromPgExpression <$> arr+    delimExpr <- fromPgExpression <$> delim+    pure $ emit "array_to_string" <> pgParens (arrExpr <> emit ", " <> delimExpr))++-- | Postgres array_to_string(array, delimiter, null_string) function.+-- Converts each element to text and joins with the delimiter. NULLs are+-- represented by the provided @null_string@.+--+-- @since 0.5.4.4+arrayToStringWithNull_+  :: QGenExpr ctxt Postgres s (V.Vector a)+  -> QGenExpr ctxt Postgres s Text+  -> QGenExpr ctxt Postgres s Text+  -> QGenExpr ctxt Postgres s Text+arrayToStringWithNull_ (QExpr arr) (QExpr delim) (QExpr nullStr) =+  QExpr (PgExpressionSyntax <$> do+    arrExpr <- fromPgExpression <$> arr+    delimExpr <- fromPgExpression <$> delim+    nullStrExpr <- fromPgExpression <$> nullStr+    pure $ emit "array_to_string" <>+      pgParens (mconcat [arrExpr, emit ", ", delimExpr, emit ", ", nullStrExpr])) -- ** Array expressions  -- | An expression context that determines which types of expressions can be put
beam-postgres.cabal view
@@ -1,5 +1,5 @@ name:                 beam-postgres-version:              0.5.4.3+version:              0.5.4.4 synopsis:             Connection layer between beam and postgres description:          Beam driver for <https://www.postgresql.org/ PostgreSQL>, an advanced open-source RDBMS homepage:             https://haskell-beam.github.io/beam/user-guide/backends/beam-postgres@@ -46,7 +46,7 @@                       hashable             >=1.1  && <1.6,                       lifted-base          >=0.2  && <0.3,                       free                 >=4.12 && <5.3,-                      time                 >=1.6  && <1.13,+                      time                 >=1.6  && <1.15,                       monad-control        >=1.0  && <1.1,                       mtl                  >=2.1  && <2.4,                       conduit              >=1.2  && <1.4,
test/Database/Beam/Postgres/Test/Select.hs view
@@ -5,6 +5,8 @@ import           Data.Aeson import           Data.ByteString (ByteString) import           Data.Int+import           Data.List (sort)+import qualified Data.Text as T import qualified Data.Vector as V import           Test.Tasty import           Test.Tasty.HUnit@@ -24,6 +26,16 @@   [ testGroup "JSON"       [ testPgArrayToJSON getConn       ]+  , testGroup "ARRAY functions"+      [ testArrayReplace getConn+      , testArrayShuffle getConn+      , testArraySample getConn+      , testArrayToStringBasic getConn+      , testArrayToStringWithNull getConn+      , testArrayAppend getConn+      , testArrayPrepend getConn+      , testArrayRemove getConn+      ]   , testGroup "UUID"       [ testUuidFunction getConn "uuid_nil" $ \ext -> pgUuidNil ext       , testUuidFunction getConn "uuid_ns_dns" $ \ext -> pgUuidNsDns ext@@ -55,6 +67,73 @@     runBeamPostgres conn $ runSelectReturningList $ select $       return $ pgArrayToJson $ val_ $ V.fromList values   assertEqual "JSON list" [PgJSON $ toJSON values] actual++testArrayReplace :: IO ByteString -> TestTree+testArrayReplace getConn = testFunction getConn "array_replace" $ \conn -> do+  let arr = V.fromList [1::Int32,2,5,4]+  res <- runBeamPostgres conn $ runSelectReturningList $ select $ do+    pure $ arrayReplace_ (val_ arr) (val_ (5::Int32)) (val_ (3::Int32))+  assertEqual "array_replace" [V.fromList [1,2,3,4 :: Int32]] res++testArrayShuffle :: IO ByteString -> TestTree+testArrayShuffle getConn = testFunction getConn "array_shuffle" $ \conn -> do+  let arr = V.fromList [1::Int32,2,3,4,5]+  res <- runBeamPostgres conn $ runSelectReturningList $ select $ do+    pure $ arrayShuffle_ (val_ arr)+  -- shuffled result has same length and elements, order may change+  case res of+    [shuf] -> do+      assertEqual "length" (V.length arr) (V.length shuf)+      assertBool "is permutation"+        (sort (V.toList arr) == sort (V.toList shuf))+    _ -> assertFailure "unexpected result"++testArraySample :: IO ByteString -> TestTree+testArraySample getConn = testFunction getConn "array_sample" $ \conn -> do+  let arr = V.fromList [1::Int32,2,3,4,5,6]+  res <- runBeamPostgres conn $ runSelectReturningList $ select $ do+    pure $ arraySample_ (val_ arr) (val_ (3::Int32))+  case res of+    [samp] -> do+      assertEqual "length 3" 3 (V.length samp)+      assertBool "subset" (V.all (`V.elem` arr) samp)+    _ -> assertFailure "unexpected result"++testArrayToStringBasic :: IO ByteString -> TestTree+testArrayToStringBasic getConn = testFunction getConn "array_to_string_basic" $ \conn -> do+  let arr = V.fromList [1::Int32,2,3]+  res <- runBeamPostgres conn $ runSelectReturningList $ select $ do+    pure $ arrayToString_ (val_ arr) (val_ ",")+  assertEqual "join" ["1,2,3" :: T.Text] res++testArrayToStringWithNull :: IO ByteString -> TestTree+testArrayToStringWithNull getConn = testFunction getConn "array_to_string_with_null" $ \conn -> do+  let arr :: V.Vector (Maybe T.Text)+      arr = V.fromList [Just "a", Nothing, Just "b"]+  res <- runBeamPostgres conn $ runSelectReturningList $ select $ do+    pure $ arrayToStringWithNull_ (val_ arr) (val_ "-") (val_ "*")+  assertEqual "join with null" ["a-*-b" :: T.Text] res++testArrayAppend :: IO ByteString -> TestTree+testArrayAppend getConn = testFunction getConn "array_append" $ \conn -> do+  let arr = V.fromList [1::Int32,2]+  res <- runBeamPostgres conn $ runSelectReturningList $ select $ do+    pure $ arrayAppend_ (val_ arr) (val_ (3::Int32))+  assertEqual "append" [V.fromList [1,2,3 :: Int32]] res++testArrayPrepend :: IO ByteString -> TestTree+testArrayPrepend getConn = testFunction getConn "array_prepend" $ \conn -> do+  let arr = V.fromList [2::Int32,3]+  res <- runBeamPostgres conn $ runSelectReturningList $ select $ do+    pure $ arrayPrepend_ (val_ (1::Int32)) (val_ arr)+  assertEqual "prepend" [V.fromList [1,2,3 :: Int32]] res++testArrayRemove :: IO ByteString -> TestTree+testArrayRemove getConn = testFunction getConn "array_remove" $ \conn -> do+  let arr = V.fromList [1::Int32,2,3,2]+  res <- runBeamPostgres conn $ runSelectReturningList $ select $ do+    pure $ arrayRemove_ (val_ arr) (val_ (2::Int32))+  assertEqual "remove" [V.fromList [1,3 :: Int32]] res  data UuidSchema f = UuidSchema   { _uuidOssp :: f (PgExtensionEntity UuidOssp)