module Hasura.Backends.BigQuery.DDL.BoolExp
  ( parseBoolExpOperations,
  )
where

import Data.Aeson qualified as J
import Data.Aeson.Key qualified as K
import Data.Aeson.KeyMap qualified as KM
import Data.Text.Extended
import Hasura.Base.Error
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp
import Hasura.RQL.Types.BackendType
import Hasura.RQL.Types.Column
import Hasura.RQL.Types.SchemaCache
import Hasura.SQL.Types

parseBoolExpOperations ::
  forall m v.
  (MonadError QErr m) =>
  ValueParser 'BigQuery m v ->
  FieldInfoMap (FieldInfo 'BigQuery) ->
  FieldInfoMap (FieldInfo 'BigQuery) ->
  ColumnReference 'BigQuery ->
  J.Value ->
  m [OpExpG 'BigQuery v]
parseBoolExpOperations :: forall (m :: * -> *) v.
MonadError QErr m =>
ValueParser 'BigQuery m v
-> FieldInfoMap (FieldInfo 'BigQuery)
-> FieldInfoMap (FieldInfo 'BigQuery)
-> ColumnReference 'BigQuery
-> Value
-> m [OpExpG 'BigQuery v]
parseBoolExpOperations ValueParser 'BigQuery m v
rhsParser FieldInfoMap (FieldInfo 'BigQuery)
_rootTableFieldInfoMap FieldInfoMap (FieldInfo 'BigQuery)
_fields ColumnReference 'BigQuery
columnRef Value
value =
  Text -> m [OpExpG 'BigQuery v] -> m [OpExpG 'BigQuery v]
forall (m :: * -> *) a. QErrM m => Text -> m a -> m a
withPathK (ColumnReference 'BigQuery -> Text
forall a. ToTxt a => a -> Text
toTxt ColumnReference 'BigQuery
columnRef) (m [OpExpG 'BigQuery v] -> m [OpExpG 'BigQuery v])
-> m [OpExpG 'BigQuery v] -> m [OpExpG 'BigQuery v]
forall a b. (a -> b) -> a -> b
$ ColumnType 'BigQuery -> Value -> m [OpExpG 'BigQuery v]
parseOperations (ColumnReference 'BigQuery -> ColumnType 'BigQuery
forall (backend :: BackendType).
ColumnReference backend -> ColumnType backend
columnReferenceType ColumnReference 'BigQuery
columnRef) Value
value
  where
    parseWithTy :: ColumnType 'BigQuery -> Value -> m v
parseWithTy ColumnType 'BigQuery
ty = ValueParser 'BigQuery m v
rhsParser (ColumnType 'BigQuery -> CollectableType (ColumnType 'BigQuery)
forall a. a -> CollectableType a
CollectableTypeScalar ColumnType 'BigQuery
ty)

    parseOperations :: ColumnType 'BigQuery -> J.Value -> m [OpExpG 'BigQuery v]
    parseOperations :: ColumnType 'BigQuery -> Value -> m [OpExpG 'BigQuery v]
parseOperations ColumnType 'BigQuery
columnType = \case
      J.Object Object
o -> ((Key, Value) -> m (OpExpG 'BigQuery v))
-> [(Key, Value)] -> m [OpExpG 'BigQuery v]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (ColumnType 'BigQuery -> (Text, Value) -> m (OpExpG 'BigQuery v)
parseOperation ColumnType 'BigQuery
columnType ((Text, Value) -> m (OpExpG 'BigQuery v))
-> ((Key, Value) -> (Text, Value))
-> (Key, Value)
-> m (OpExpG 'BigQuery v)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Key -> Text) -> (Key, Value) -> (Text, Value)
forall b c d. (b -> c) -> (b, d) -> (c, d)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first Key -> Text
K.toText) ([(Key, Value)] -> m [OpExpG 'BigQuery v])
-> [(Key, Value)] -> m [OpExpG 'BigQuery v]
forall a b. (a -> b) -> a -> b
$ Object -> [(Key, Value)]
forall v. KeyMap v -> [(Key, v)]
KM.toList Object
o
      Value
v -> OpExpG 'BigQuery v -> [OpExpG 'BigQuery v]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (OpExpG 'BigQuery v -> [OpExpG 'BigQuery v])
-> (v -> OpExpG 'BigQuery v) -> v -> [OpExpG 'BigQuery v]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ComparisonNullability -> v -> OpExpG 'BigQuery v
forall (backend :: BackendType) field.
ComparisonNullability -> field -> OpExpG backend field
AEQ ComparisonNullability
NullableComparison (v -> [OpExpG 'BigQuery v]) -> m v -> m [OpExpG 'BigQuery v]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ColumnType 'BigQuery -> Value -> m v
parseWithTy ColumnType 'BigQuery
columnType Value
v

    parseOperation :: ColumnType 'BigQuery -> (Text, J.Value) -> m (OpExpG 'BigQuery v)
    parseOperation :: ColumnType 'BigQuery -> (Text, Value) -> m (OpExpG 'BigQuery v)
parseOperation ColumnType 'BigQuery
columnType (Text
opStr, Value
val) = Text -> m (OpExpG 'BigQuery v) -> m (OpExpG 'BigQuery v)
forall (m :: * -> *) a. QErrM m => Text -> m a -> m a
withPathK Text
opStr
      (m (OpExpG 'BigQuery v) -> m (OpExpG 'BigQuery v))
-> m (OpExpG 'BigQuery v) -> m (OpExpG 'BigQuery v)
forall a b. (a -> b) -> a -> b
$ case Text
opStr of
        Text
"_eq" -> m (OpExpG 'BigQuery v)
parseEq
        Text
"$eq" -> m (OpExpG 'BigQuery v)
parseEq
        Text
"_neq" -> m (OpExpG 'BigQuery v)
parseNeq
        Text
"$neq" -> m (OpExpG 'BigQuery v)
parseNeq
        Text
"$in" -> m (OpExpG 'BigQuery v)
parseIn
        Text
"_in" -> m (OpExpG 'BigQuery v)
parseIn
        Text
"$nin" -> m (OpExpG 'BigQuery v)
parseNin
        Text
"_nin" -> m (OpExpG 'BigQuery v)
parseNin
        Text
"_gt" -> m (OpExpG 'BigQuery v)
parseGt
        Text
"$gt" -> m (OpExpG 'BigQuery v)
parseGt
        Text
"_lt" -> m (OpExpG 'BigQuery v)
parseLt
        Text
"$lt" -> m (OpExpG 'BigQuery v)
parseLt
        Text
"_gte" -> m (OpExpG 'BigQuery v)
parseGte
        Text
"$gte" -> m (OpExpG 'BigQuery v)
parseGte
        Text
"_lte" -> m (OpExpG 'BigQuery v)
parseLte
        Text
"$lte" -> m (OpExpG 'BigQuery v)
parseLte
        -- TODO: support column operators

        Text
x -> Code -> Text -> m (OpExpG 'BigQuery v)
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
UnexpectedPayload (Text -> m (OpExpG 'BigQuery v)) -> Text -> m (OpExpG 'BigQuery v)
forall a b. (a -> b) -> a -> b
$ Text
"Unknown operator: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
x
      where
        colTy :: ColumnType 'BigQuery
colTy = ColumnReference 'BigQuery -> ColumnType 'BigQuery
forall (backend :: BackendType).
ColumnReference backend -> ColumnType backend
columnReferenceType ColumnReference 'BigQuery
columnRef
        parseOne :: m v
parseOne = ColumnType 'BigQuery -> Value -> m v
parseWithTy ColumnType 'BigQuery
columnType Value
val
        parseManyWithType :: ColumnType 'BigQuery -> m v
parseManyWithType ColumnType 'BigQuery
ty = ValueParser 'BigQuery m v
rhsParser (ColumnType 'BigQuery -> CollectableType (ColumnType 'BigQuery)
forall a. a -> CollectableType a
CollectableTypeArray ColumnType 'BigQuery
ty) Value
val

        parseEq :: m (OpExpG 'BigQuery v)
parseEq = ComparisonNullability -> v -> OpExpG 'BigQuery v
forall (backend :: BackendType) field.
ComparisonNullability -> field -> OpExpG backend field
AEQ ComparisonNullability
NullableComparison (v -> OpExpG 'BigQuery v) -> m v -> m (OpExpG 'BigQuery v)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m v
parseOne
        parseNeq :: m (OpExpG 'BigQuery v)
parseNeq = ComparisonNullability -> v -> OpExpG 'BigQuery v
forall (backend :: BackendType) field.
ComparisonNullability -> field -> OpExpG backend field
ANE ComparisonNullability
NullableComparison (v -> OpExpG 'BigQuery v) -> m v -> m (OpExpG 'BigQuery v)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m v
parseOne
        parseIn :: m (OpExpG 'BigQuery v)
parseIn = v -> OpExpG 'BigQuery v
forall (backend :: BackendType) field.
field -> OpExpG backend field
AIN (v -> OpExpG 'BigQuery v) -> m v -> m (OpExpG 'BigQuery v)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ColumnType 'BigQuery -> m v
parseManyWithType ColumnType 'BigQuery
colTy
        parseNin :: m (OpExpG 'BigQuery v)
parseNin = v -> OpExpG 'BigQuery v
forall (backend :: BackendType) field.
field -> OpExpG backend field
ANIN (v -> OpExpG 'BigQuery v) -> m v -> m (OpExpG 'BigQuery v)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ColumnType 'BigQuery -> m v
parseManyWithType ColumnType 'BigQuery
colTy
        parseGt :: m (OpExpG 'BigQuery v)
parseGt = v -> OpExpG 'BigQuery v
forall (backend :: BackendType) field.
field -> OpExpG backend field
AGT (v -> OpExpG 'BigQuery v) -> m v -> m (OpExpG 'BigQuery v)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m v
parseOne
        parseLt :: m (OpExpG 'BigQuery v)
parseLt = v -> OpExpG 'BigQuery v
forall (backend :: BackendType) field.
field -> OpExpG backend field
ALT (v -> OpExpG 'BigQuery v) -> m v -> m (OpExpG 'BigQuery v)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m v
parseOne
        parseGte :: m (OpExpG 'BigQuery v)
parseGte = v -> OpExpG 'BigQuery v
forall (backend :: BackendType) field.
field -> OpExpG backend field
AGTE (v -> OpExpG 'BigQuery v) -> m v -> m (OpExpG 'BigQuery v)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m v
parseOne
        parseLte :: m (OpExpG 'BigQuery v)
parseLte = v -> OpExpG 'BigQuery v
forall (backend :: BackendType) field.
field -> OpExpG backend field
ALTE (v -> OpExpG 'BigQuery v) -> m v -> m (OpExpG 'BigQuery v)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m v
parseOne