mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-18 04:51:35 +03:00
b2b195c0a3
Add support for custom comparison operators in the DC agent API and IR. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/4974 GitOrigin-RevId: 9580160e6171df77fe4979b7c2e87c473aaccbfc
192 lines
8.4 KiB
Haskell
192 lines
8.4 KiB
Haskell
{-# LANGUAGE DeriveAnyClass #-}
|
|
|
|
module Hasura.Backends.DataConnector.IR.Expression
|
|
( Expression (..),
|
|
BinaryComparisonOperator (..),
|
|
BinaryArrayComparisonOperator (..),
|
|
UnaryComparisonOperator (..),
|
|
ComparisonColumn (..),
|
|
ComparisonValue (..),
|
|
)
|
|
where
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
import Autodocodec.Extended (ValueWrapper (..), ValueWrapper2 (..), ValueWrapper3 (..))
|
|
import Data.Aeson (FromJSON, ToJSON)
|
|
import Hasura.Backends.DataConnector.API qualified as API
|
|
import Hasura.Backends.DataConnector.IR.Column qualified as IR.C
|
|
import Hasura.Backends.DataConnector.IR.Relationships qualified as IR.R
|
|
import Hasura.Backends.DataConnector.IR.Scalar.Value qualified as IR.S
|
|
import Hasura.Incremental (Cacheable)
|
|
import Hasura.Prelude
|
|
import Witch qualified
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- | A "concrete" expression type for datasource-agnostic queries (as opposed
|
|
-- to our existing polymorphic intermediate representation).
|
|
--
|
|
-- This type should be seen as an intermediate phase of the processing pipeline
|
|
-- which provides a high-level interface that the GraphQL Engine can use to
|
|
-- inspect, manipulate, optimize, etc. before sending off to an agent that will
|
|
-- be responsible for performing query generation/execution.
|
|
--
|
|
-- This type should ascribe clear semantics to its sub-expressions; when this
|
|
-- is not possible, it should clearly defer to the semantics of some reference
|
|
-- datasource with clearer documentation.
|
|
--
|
|
-- e.g. https://www.postgresql.org/docs/13/sql-expressions.html
|
|
data Expression
|
|
= -- | A logical @AND@ fold.
|
|
--
|
|
-- cf. https://www.postgresql.org/docs/13/functions-logical.html
|
|
And [Expression]
|
|
| -- | A logical @OR@ fold.
|
|
--
|
|
-- cf. https://www.postgresql.org/docs/13/functions-logical.html
|
|
Or [Expression]
|
|
| -- | A logical @NOT@ function.
|
|
--
|
|
-- cf. https://www.postgresql.org/docs/13/functions-logical.html
|
|
Not Expression
|
|
| -- | Apply a 'BinaryComparisonOperator' that compares a column to a 'ComparisonValue';
|
|
-- the result of this application will return "true" or "false" depending on the
|
|
-- 'BinaryComparisonOperator' that's being applied.
|
|
ApplyBinaryComparisonOperator BinaryComparisonOperator ComparisonColumn ComparisonValue
|
|
| -- | Apply a 'BinaryArrayComparisonOperator' that evaluates a column with the
|
|
-- 'BinaryArrayComparisonOperator' against an array of 'ComparisonValue's.
|
|
-- The result of this application will return "true" or "false" depending
|
|
-- on the 'BinaryArrayComparisonOperator' that's being applied.
|
|
ApplyBinaryArrayComparisonOperator BinaryArrayComparisonOperator ComparisonColumn [IR.S.Value]
|
|
| -- | Apply a 'UnaryComparisonOperator' that evaluates a column with the
|
|
-- 'UnaryComparisonOperator'; the result of this application will return "true" or
|
|
-- "false" depending on the 'UnaryComparisonOperator' that's being applied.
|
|
ApplyUnaryComparisonOperator UnaryComparisonOperator ComparisonColumn
|
|
deriving stock (Data, Eq, Generic, Ord, Show)
|
|
deriving anyclass (Cacheable, FromJSON, Hashable, NFData, ToJSON)
|
|
|
|
instance Witch.From Expression API.Expression where
|
|
from = \case
|
|
And exprs -> API.And . ValueWrapper $ Witch.from <$> exprs
|
|
Or exprs -> API.Or . ValueWrapper $ Witch.from <$> exprs
|
|
Not expr -> API.Not . ValueWrapper $ Witch.from expr
|
|
ApplyBinaryComparisonOperator op column value ->
|
|
API.ApplyBinaryComparisonOperator $ ValueWrapper3 (Witch.from op) (Witch.from column) (Witch.from value)
|
|
ApplyUnaryComparisonOperator op column ->
|
|
API.ApplyUnaryComparisonOperator $ ValueWrapper2 (Witch.from op) (Witch.from column)
|
|
ApplyBinaryArrayComparisonOperator op column values ->
|
|
API.ApplyBinaryArrayComparisonOperator $ ValueWrapper3 (Witch.from op) (Witch.from column) (Witch.from <$> values)
|
|
|
|
instance Witch.From API.Expression Expression where
|
|
from = \case
|
|
API.And (ValueWrapper exprs) -> And $ Witch.from <$> exprs
|
|
API.Or (ValueWrapper exprs) -> Or $ Witch.from <$> exprs
|
|
API.Not (ValueWrapper expr) -> Not $ Witch.from expr
|
|
API.ApplyBinaryComparisonOperator (ValueWrapper3 op column value) ->
|
|
ApplyBinaryComparisonOperator (Witch.from op) (Witch.from column) (Witch.from value)
|
|
API.ApplyBinaryArrayComparisonOperator (ValueWrapper3 op column values) ->
|
|
ApplyBinaryArrayComparisonOperator (Witch.from op) (Witch.from column) (Witch.from <$> values)
|
|
API.ApplyUnaryComparisonOperator (ValueWrapper2 op column) ->
|
|
ApplyUnaryComparisonOperator (Witch.from op) (Witch.from column)
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- | Operators which are typically applied to two 'Expression's (via the
|
|
-- 'ApplyOperator' sub-'Expression') to perform a boolean comparison.
|
|
--
|
|
-- cf. https://www.postgresql.org/docs/13/functions-comparison.html
|
|
--
|
|
-- XXX(jkachmar): Comparison operations are tricky business!
|
|
--
|
|
-- We should define the semantics of these comparisons in a way that is clear
|
|
-- and carefully considered.
|
|
data BinaryComparisonOperator
|
|
= LessThan
|
|
| LessThanOrEqual
|
|
| GreaterThan
|
|
| GreaterThanOrEqual
|
|
| Equal
|
|
| CustomBinaryComparisonOperator Text
|
|
deriving stock (Data, Eq, Generic, Ord, Show)
|
|
deriving anyclass (Cacheable, FromJSON, Hashable, NFData, ToJSON)
|
|
|
|
instance Witch.From API.BinaryComparisonOperator BinaryComparisonOperator where
|
|
from API.LessThan = LessThan
|
|
from API.LessThanOrEqual = LessThanOrEqual
|
|
from API.GreaterThan = GreaterThan
|
|
from API.GreaterThanOrEqual = GreaterThanOrEqual
|
|
from API.Equal = Equal
|
|
from (API.CustomBinaryComparisonOperator name) = CustomBinaryComparisonOperator name
|
|
|
|
instance Witch.From BinaryComparisonOperator API.BinaryComparisonOperator where
|
|
from LessThan = API.LessThan
|
|
from LessThanOrEqual = API.LessThanOrEqual
|
|
from GreaterThan = API.GreaterThan
|
|
from GreaterThanOrEqual = API.GreaterThanOrEqual
|
|
from Equal = API.Equal
|
|
from (CustomBinaryComparisonOperator name) = API.CustomBinaryComparisonOperator name
|
|
|
|
data UnaryComparisonOperator
|
|
= IsNull
|
|
| CustomUnaryComparisonOperator Text
|
|
deriving stock (Data, Eq, Generic, Ord, Show)
|
|
deriving anyclass (Cacheable, FromJSON, Hashable, NFData, ToJSON)
|
|
|
|
instance Witch.From API.UnaryComparisonOperator UnaryComparisonOperator where
|
|
from API.IsNull = IsNull
|
|
from (API.CustomUnaryComparisonOperator name) = CustomUnaryComparisonOperator name
|
|
|
|
instance Witch.From UnaryComparisonOperator API.UnaryComparisonOperator where
|
|
from IsNull = API.IsNull
|
|
from (CustomUnaryComparisonOperator name) = API.CustomUnaryComparisonOperator name
|
|
|
|
data BinaryArrayComparisonOperator
|
|
= In
|
|
| CustomBinaryArrayComparisonOperator Text
|
|
deriving stock (Data, Eq, Generic, Ord, Show)
|
|
deriving anyclass (Cacheable, FromJSON, Hashable, NFData, ToJSON)
|
|
|
|
instance Witch.From API.BinaryArrayComparisonOperator BinaryArrayComparisonOperator where
|
|
from API.In = In
|
|
from (API.CustomBinaryArrayComparisonOperator name) = CustomBinaryArrayComparisonOperator name
|
|
|
|
instance Witch.From BinaryArrayComparisonOperator API.BinaryArrayComparisonOperator where
|
|
from In = API.In
|
|
from (CustomBinaryArrayComparisonOperator name) = API.CustomBinaryArrayComparisonOperator name
|
|
|
|
data ComparisonColumn = ComparisonColumn
|
|
{ _ccPath :: [IR.R.RelationshipName],
|
|
_ccName :: IR.C.Name
|
|
}
|
|
deriving stock (Data, Eq, Generic, Ord, Show)
|
|
deriving anyclass (Cacheable, FromJSON, Hashable, NFData, ToJSON)
|
|
|
|
instance Witch.From ComparisonColumn API.ComparisonColumn where
|
|
from ComparisonColumn {..} =
|
|
API.ComparisonColumn
|
|
{ _ccPath = Witch.from <$> _ccPath,
|
|
_ccName = Witch.from _ccName
|
|
}
|
|
|
|
instance Witch.From API.ComparisonColumn ComparisonColumn where
|
|
from API.ComparisonColumn {..} =
|
|
ComparisonColumn
|
|
{ _ccPath = Witch.from <$> _ccPath,
|
|
_ccName = Witch.from _ccName
|
|
}
|
|
|
|
data ComparisonValue
|
|
= AnotherColumn ComparisonColumn
|
|
| ScalarValue IR.S.Value
|
|
deriving stock (Data, Eq, Generic, Ord, Show)
|
|
deriving anyclass (Cacheable, FromJSON, Hashable, NFData, ToJSON)
|
|
|
|
instance Witch.From ComparisonValue API.ComparisonValue where
|
|
from (AnotherColumn column) = API.AnotherColumn $ ValueWrapper (Witch.from column)
|
|
from (ScalarValue value) = API.ScalarValue . ValueWrapper $ Witch.from value
|
|
|
|
instance Witch.From API.ComparisonValue ComparisonValue where
|
|
from (API.AnotherColumn (ValueWrapper column)) = AnotherColumn (Witch.from column)
|
|
from (API.ScalarValue (ValueWrapper value)) = ScalarValue $ Witch.from value
|