Skip to content

Commit

Permalink
Add EXTRACT function to Rel8.Expr.Time
Browse files Browse the repository at this point in the history
This adds unsafe EXTRACT function to Rel8.Expr.Time, using the low-level
Opaleye functions. Should solve circuithub#236.
  • Loading branch information
guaraqe committed May 12, 2023
1 parent e2a77b7 commit 551eb56
Showing 1 changed file with 23 additions and 1 deletion.
24 changes: 23 additions & 1 deletion src/Rel8/Expr/Time.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module Rel8.Expr.Time
, addTime
, diffTime
, subtractTime
, unsafeExtractFromTime

-- * Working with @CalendarDiffTime@
, scaleInterval
Expand All @@ -22,6 +23,7 @@ module Rel8.Expr.Time
, week, weeks
, month, months
, year, years
, unsafeExtractFromInterval
) where

-- base
Expand All @@ -31,7 +33,9 @@ import Prelude
-- rel8
import Rel8.Expr ( Expr )
import Rel8.Expr.Function ( binaryOperator, nullaryFunction )
import Rel8.Expr.Opaleye ( castExpr, unsafeCastExpr, unsafeLiteral )
import Rel8.Expr.Opaleye ( castExpr, unsafeCastExpr, unsafeLiteral, fromPrimExpr, toPrimExpr )
import Rel8.Type ( DBType )
import qualified Opaleye.Internal.HaskellDB.PrimQuery as Opaleye

-- time
import Data.Time.Calendar ( Day )
Expand Down Expand Up @@ -88,6 +92,14 @@ diffTime = binaryOperator "-"
subtractTime :: Expr CalendarDiffTime -> Expr UTCTime -> Expr UTCTime
subtractTime = flip (binaryOperator "-")

-- | Extract a part of a point in time. See possibilities
-- [here](https://www.postgresqltutorial.com/postgresql-date-functions/postgresql-extract/).
-- This function is unsafe because you must decide yourself the output type.
unsafeExtractFromTime :: DBType a => String -> Expr UTCTime -> Expr a
unsafeExtractFromTime name expr =
castExpr $
fromPrimExpr $
Opaleye.FunExpr "EXTRACT" [Opaleye.FunExpr (name <> " FROM") [toPrimExpr expr]]

scaleInterval :: Expr Double -> Expr CalendarDiffTime -> Expr CalendarDiffTime
scaleInterval = binaryOperator "*"
Expand Down Expand Up @@ -165,3 +177,13 @@ years = (`scaleInterval` year)

singleton :: String -> Expr CalendarDiffTime
singleton unit = castExpr $ unsafeLiteral $ "'1 " ++ unit ++ "'"

-- | Extract a part of an interval. See possibilities
-- [here](https://www.postgresqltutorial.com/postgresql-date-functions/postgresql-extract/).
-- This function is unsafe because you must decide yourself the output type.
unsafeExtractFromInterval :: DBType a => String -> Expr CalendarDiffTime -> Expr a
unsafeExtractFromInterval name expr =
castExpr $
fromPrimExpr $
Opaleye.FunExpr "EXTRACT" [Opaleye.FunExpr (name <> " FROM") [toPrimExpr expr]]

0 comments on commit 551eb56

Please sign in to comment.