module Test.Expr.Window ( windowTests ) where import qualified Data.ByteString.Char8 as B8 import GHC.Stack (HasCallStack, withFrozenCallStack) import qualified Hedgehog as HH import qualified Orville.PostgreSQL.Expr as Expr import qualified Orville.PostgreSQL.Raw.RawSql as RawSql import qualified Orville.PostgreSQL.Raw.SqlValue as SqlValue import Test.Expr.TestSchema (barColumn) import qualified Test.Property as Property windowTests :: Property.Group windowTests = Property.group "Expr - Window" [ prop_windowClauseSingleDef , prop_windowClauseMultiDef ] prop_windowClauseSingleDef :: Property.NamedProperty prop_windowClauseSingleDef = let windowDef = Expr.windowDefinition Nothing (Just partitionBy) (Just orderBy) (Just frameClause) windowDefName = Expr.fromIdentifier $ Expr.identifier "a" partitionBy = Expr.partitionBy (pure . Expr.valueExpression $ SqlValue.fromInt32 1) orderBy = Expr.orderByClause $ Expr.orderByColumnName barColumn Expr.ascendingOrder frameClause = Expr.frameClause (Just Expr.rowsFrameMode) Expr.unboundedPrecedingFrameStart (Just Expr.unboundedFollowingFrameEnd) (Just Expr.tiesFrameExclusion) in Property.singletonNamedProperty "window clause with single window definition containing a partition by, an order by, and a frame clause generates expected sql." . assertWindowEquals "WINDOW \"a\" AS (PARTITION BY $1 ORDER BY \"bar\" ASC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE TIES)" . Expr.windowClause $ Expr.namedWindowDefinition windowDefName windowDef prop_windowClauseMultiDef :: Property.NamedProperty prop_windowClauseMultiDef = let windowDef1 = Expr.windowDefinition Nothing (Just partitionBy) Nothing Nothing windowDef1Name = Expr.fromIdentifier $ Expr.identifier "a" windowDef2 = Expr.windowDefinition (Just windowDef1Name) Nothing (Just orderBy) (Just frameClause) windowDef2Name = Expr.fromIdentifier $ Expr.identifier "b" partitionBy = Expr.partitionBy (pure . Expr.valueExpression $ SqlValue.fromInt32 1) orderBy = Expr.orderByClause $ Expr.orderByColumnName barColumn Expr.ascendingOrder frameClause = Expr.frameClause (Just Expr.rowsFrameMode) Expr.unboundedPrecedingFrameStart (Just Expr.unboundedFollowingFrameEnd) (Just Expr.tiesFrameExclusion) in Property.singletonNamedProperty "window clause with two window definitions, where the second \"copies\" the first, generates expected sql." . assertWindowEquals "WINDOW \"a\" AS (PARTITION BY $1), \"b\" AS (\"a\" ORDER BY \"bar\" ASC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE TIES)" . Expr.windowClause $ Expr.namedWindowDefinition windowDef1Name windowDef1 <> Expr.namedWindowDefinition windowDef2Name windowDef2 assertWindowEquals :: (HH.MonadTest m, HasCallStack) => String -> Expr.WindowClause -> m () assertWindowEquals windowClauseStr windowClause = withFrozenCallStack $ RawSql.toExampleBytes windowClause HH.=== B8.pack windowClauseStr