server/bigquery: generate graphql schema for table computed fields

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/4460
GitOrigin-RevId: 7b772cd9fba6b612ad05eb1aca1fa13e6ae8556d
This commit is contained in:
Rakesh Emmadi 2022-05-25 15:54:41 +05:30 committed by hasura-bot
parent 8a05ff207b
commit acde210fdc
65 changed files with 1212 additions and 605 deletions

View File

@ -429,6 +429,7 @@ library
, Hasura.Backends.BigQuery.DDL.BoolExp
, Hasura.Backends.BigQuery.DDL.RunSQL
, Hasura.Backends.BigQuery.DDL.Source
, Hasura.Backends.BigQuery.DDL.ComputedField
, Hasura.Backends.BigQuery.FromIr
, Hasura.Backends.BigQuery.Instances.API
, Hasura.Backends.BigQuery.Instances.Execute
@ -532,7 +533,8 @@ library
, Hasura.Backends.Postgres.Translate.Update
, Hasura.Backends.Postgres.Types.BoolExp
, Hasura.Backends.Postgres.Types.CitusExtraTableMetadata
, Hasura.Backends.Postgres.Types.ComputedFieldDefinition
, Hasura.Backends.Postgres.Types.ComputedField
, Hasura.Backends.Postgres.Types.Function
, Hasura.Backends.Postgres.Types.Column
, Hasura.Backends.Postgres.Types.Insert
, Hasura.Backends.Postgres.Types.Table
@ -648,6 +650,7 @@ library
, Hasura.RQL.Types.GraphqlSchemaIntrospection
, Hasura.RQL.Types.Function
, Hasura.RQL.Types.Instances
, Hasura.RQL.Types.BoolExp
, Hasura.RQL.Types.Metadata
, Hasura.RQL.Types.Metadata.Backend
, Hasura.RQL.Types.Metadata.Instances

View File

@ -1,6 +1,5 @@
module Hasura.Backends.BigQuery.DDL
( buildComputedFieldInfo,
fetchAndValidateEnumValues,
( fetchAndValidateEnumValues,
buildFunctionInfo,
updateColumnInEventTrigger,
parseBoolExpOperations,
@ -11,6 +10,7 @@ where
import Data.Aeson
import Hasura.Backends.BigQuery.DDL.BoolExp
import Hasura.Backends.BigQuery.DDL.ComputedField as M
import Hasura.Backends.BigQuery.DDL.Source as M
import Hasura.Backends.BigQuery.Types qualified as BigQuery
import Hasura.Base.Error
@ -19,7 +19,6 @@ import Hasura.RQL.IR.BoolExp
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.Column
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.ComputedField
import Hasura.RQL.Types.EventTrigger
import Hasura.RQL.Types.Function
import Hasura.RQL.Types.SchemaCache
@ -29,18 +28,6 @@ import Hasura.SQL.Types
import Hasura.Server.Utils
import Hasura.Session
buildComputedFieldInfo ::
(MonadError QErr m) =>
HashSet (TableName 'BigQuery) ->
TableName 'BigQuery ->
ComputedFieldName ->
ComputedFieldDefinition 'BigQuery ->
RawFunctionInfo 'BigQuery ->
Comment ->
m (ComputedFieldInfo 'BigQuery)
buildComputedFieldInfo _ _ _ _ _ _ =
throw400 NotSupported "Computed fields aren't supported for BigQuery sources"
fetchAndValidateEnumValues ::
(Monad m) =>
SourceConfig 'BigQuery ->

View File

@ -0,0 +1,158 @@
-- | BigQuery DDL ComputedField
--
-- Implementation to build 'ComputedFieldInfo' for a BigQuery table from metadata
module Hasura.Backends.BigQuery.DDL.ComputedField
( buildComputedFieldInfo,
)
where
import Control.Monad.Validate qualified as MV
import Data.HashMap.Strict qualified as HM
import Data.HashSet qualified as HS
import Data.Sequence qualified as Seq
import Data.Text.Extended
import Hasura.Backends.BigQuery.DDL.Source
import Hasura.Backends.BigQuery.Instances.Types ()
import Hasura.Backends.BigQuery.Meta
import Hasura.Backends.BigQuery.Types
import Hasura.Base.Error
import Hasura.Prelude
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.ComputedField
import Hasura.RQL.Types.Function
import Hasura.SQL.Backend
import Hasura.Server.Utils
import Language.GraphQL.Draft.Syntax qualified as G
-- | Errors that occur when validating and building computed fields.
data ComputedFieldError
= CFENoArgumentType FunctionArgName
| CFENotTableValuedFunction
| CFENoInputArguments
| CFENoArgumentName
| CFEInvalidArgumentName FunctionArgName
| CFEInvalidColumnName TableName ColumnName
| CFEReturnTableNotTracked TableName
| CFENeedReturnTableName
| CFENotRelevantReturnTable TableName
| CFEReturnTableSchemaError ReturnTableSchemaError
-- | Errors that occur when validating returning table schema fields
data ReturnTableSchemaError
= RTSENoFieldName
| RTSENoType Text
| RTSENotValidGraphQLName Text
-- | Generate read-able error message
showError :: FunctionName -> ComputedFieldError -> Text
showError functionName = \case
CFENoArgumentType argName ->
"argument " <> argName <<> " has no data type defined in the function " <>> functionName
CFENotTableValuedFunction ->
prefixFunction <> " is not a TABLE_VALUED_FUNCTION"
CFENoInputArguments ->
prefixFunction <> " has no input arguments defined"
CFENoArgumentName ->
prefixFunction <> " has at least one argument without name"
CFEInvalidArgumentName argName ->
"the argument " <> argName <<> " is not one of function " <> functionName <<> " input arguments"
CFEInvalidColumnName tableName columnName ->
"the column " <> columnName <<> " does not exist in table " <>> tableName
CFEReturnTableNotTracked tableName ->
prefixFunction <> " returning set of table " <> tableName <<> " is not tracked"
CFENeedReturnTableName ->
prefixFunction <> " is not defined with 'RETURNS TABLE'. Expecting return table name."
CFENotRelevantReturnTable tableName ->
"return table " <> tableName <<> " is not required as the function " <> functionName <<> " returns arbitrary column fields"
CFEReturnTableSchemaError returnFieldsError -> showReturnFieldsError returnFieldsError
where
showReturnFieldsError :: ReturnTableSchemaError -> Text
showReturnFieldsError = \case
RTSENoFieldName -> "at least one field name is absent"
RTSENoType fieldName -> "fieldName " <> fieldName <<> " has not type information"
RTSENotValidGraphQLName fieldName -> "fieldName " <> fieldName <<> " is not a valid GraphQL name"
prefixFunction :: Text
prefixFunction = "function " <>> functionName
-- | Validate computed field metadata and build field information
buildComputedFieldInfo ::
forall m.
(MonadError QErr m) =>
HashSet TableName ->
TableName ->
HashSet ColumnName ->
ComputedFieldName ->
ComputedFieldDefinition ->
RestRoutine ->
Comment ->
m (ComputedFieldInfo 'BigQuery)
buildComputedFieldInfo trackedTables table tableColumns computedField ComputedFieldDefinition {..} restRoutine comment = do
either (throw400 NotSupported . showErrors) pure =<< MV.runValidateT mkComputedFieldInfo
where
mkComputedFieldInfo ::
forall n.
MV.MonadValidate [ComputedFieldError] n =>
n (ComputedFieldInfo 'BigQuery)
mkComputedFieldInfo = do
-- Currently, we only support functions returning set of rows in computed field.
-- Support for scalar computed fields is being tracked at https://github.com/hasura/graphql-engine/issues/8521.
unless (routineType restRoutine == TABLE_VALUED_FUNCTION) $ MV.dispute $ pure CFENotTableValuedFunction
restArguments <- onNothing (arguments restRoutine) $ MV.refute (pure CFENoInputArguments)
inputArguments <- Seq.fromList <$> for restArguments resolveInputArgument
for_ (HM.toList _bqcfdArgumentMapping) (validateArgumentMapping inputArguments)
let fieldFunction = ComputedFieldFunction _bqcfdFunction inputArguments _bqcfdArgumentMapping Nothing
fieldReturn <- resolveFunctionReturning (returnTableType restRoutine) _bqcfdReturnTable
pure $ ComputedFieldInfo @'BigQuery () computedField fieldFunction fieldReturn $ commentToMaybeText comment
where
resolveInputArgument :: RestArgument -> n FunctionArgument
resolveInputArgument RestArgument {..} = do
case _raName of
Nothing -> MV.refute $ pure CFENoArgumentName
Just name -> do
let argName = FunctionArgName name
restType <- onNothing _raDataType $ MV.refute $ pure $ CFENoArgumentType argName
pure $ FunctionArgument argName (restTypeToScalarType restType)
validateArgumentMapping :: Seq FunctionArgument -> (FunctionArgName, ColumnName) -> n ()
validateArgumentMapping args (functionArgName, columnName) = do
-- Check if argument is one of function input arguments
unless (functionArgName `elem` (_faName <$> args)) $ MV.dispute $ pure $ CFEInvalidArgumentName functionArgName
-- Check if column name exist in list of table columns
unless (columnName `HS.member` tableColumns) $ MV.dispute $ pure $ CFEInvalidColumnName table columnName
resolveReturnSqlFields :: [RestStandardSqlField] -> n [(ColumnName, G.Name, ScalarType)]
resolveReturnSqlFields fields =
forM fields $ \RestStandardSqlField {..} -> do
fieldName <- onNothing _rssfName $ MV.refute $ pure $ CFEReturnTableSchemaError RTSENoFieldName
fieldGraphQLName <- onNothing (G.mkName fieldName) $ MV.refute $ pure $ CFEReturnTableSchemaError $ RTSENotValidGraphQLName fieldName
type' <- onNothing _rssType $ MV.refute $ pure $ CFEReturnTableSchemaError $ RTSENoType fieldName
pure (ColumnName fieldName, fieldGraphQLName, restTypeToScalarType type')
resolveFunctionReturning ::
Maybe RestStandardSqlTableType ->
Maybe TableName ->
n ComputedFieldReturn
resolveFunctionReturning Nothing Nothing =
MV.refute $ pure CFENeedReturnTableName
resolveFunctionReturning Nothing (Just returnTable) =
-- Function does not return schema of a table. The return table type should be inferred
-- from function definition. The user provides returning table name through metadata.
-- Check if returning table is tracked.
if returnTable `HS.member` trackedTables
then pure (ReturnExistingTable returnTable)
else MV.refute $ pure $ CFEReturnTableNotTracked returnTable
resolveFunctionReturning (Just returnFields) Nothing =
-- Return table is not specified and the function returns a schema of a table,
-- specified as a list of column names and their type.
ReturnTableSchema <$> resolveReturnSqlFields (_rrttColumns returnFields)
resolveFunctionReturning (Just _) (Just returnTable) =
MV.refute $ pure $ CFENotRelevantReturnTable returnTable
showErrors :: [ComputedFieldError] -> Text
showErrors allErrors =
"the computed field " <> computedField <<> " cannot be added to table "
<> table <<> " "
<> reasonMessage
where
reasonMessage = makeReasonMessage allErrors (showError _bqcfdFunction)

View File

@ -4,6 +4,7 @@ module Hasura.Backends.BigQuery.DDL.Source
( resolveSource,
postDropSourceHook,
resolveSourceConfig,
restTypeToScalarType,
)
where

View File

@ -29,6 +29,7 @@ import Hasura.Prelude
import Hasura.RQL.IR qualified as Ir
import Hasura.RQL.Types.Column qualified as Rql
import Hasura.RQL.Types.Common qualified as Rql
import Hasura.RQL.Types.Function qualified as Rql
import Hasura.RQL.Types.Relationships.Local qualified as Rql
import Hasura.SQL.Backend
@ -52,6 +53,9 @@ data Error
| InvalidIntegerishSql Expression
| ConnectionsNotSupported
| ActionsNotSupported
| -- | TODO: SQL generation for computed fields is not being added now.
-- See https://github.com/hasura/graphql-engine-mono/issues/4369
ComputedFieldsNotSupported
instance Show Error where
show =
@ -71,6 +75,7 @@ instance Show Error where
InvalidIntegerishSql {} -> "InvalidIntegerishSql"
ConnectionsNotSupported {} -> "ConnectionsNotSupported"
ActionsNotSupported {} -> "ActionsNotSupported"
ComputedFieldsNotSupported {} -> "ComputedFieldsNotSupported"
-- | The base monad used throughout this module for all conversion
-- functions.
@ -186,7 +191,7 @@ fromSelectRows annSelectG = do
selectFrom <-
case from of
Ir.FromTable qualifiedObject -> fromQualifiedTable qualifiedObject
Ir.FromFunction nm (Ir.FunctionArgsExp [Ir.AEInput json] _) (Just columns)
Ir.FromFunction nm (Rql.FunctionArgsExp [BigQuery.AEInput json] _) (Just columns)
| functionName nm == "unnest" -> fromUnnestedJSON json columns (map fst fields)
_ -> refute (pure (FromTypeUnsupported from))
Args
@ -663,6 +668,7 @@ unfurlAnnotatedOrderByElement =
{ fieldNameEntity = entityAliasText joinAlias,
fieldName = alias
}
Ir.AOCComputedField {} -> refute $ pure ComputedFieldsNotSupported
--------------------------------------------------------------------------------
-- Conversion functions
@ -726,6 +732,7 @@ fromAnnBoolExpFld =
selectOffset = Nothing
}
)
Ir.AVComputedField {} -> refute $ pure ComputedFieldsNotSupported
fromColumnInfo :: Rql.ColumnInfo 'BigQuery -> ReaderT EntityAlias FromIr FieldName
fromColumnInfo Rql.ColumnInfo {ciColumn = ColumnName column} = do
@ -932,6 +939,7 @@ fromAnnFieldsG existingJoins stringifyNumbers (Rql.FieldName name, field) =
JoinFieldSource (Aliased {aliasedThing, aliasedAlias = name})
)
(fromArraySelectG arraySelectG)
Ir.AFComputedField {} -> refute $ pure ComputedFieldsNotSupported
-- | Here is where we project a field as a column expression. If
-- number stringification is on, then we wrap it in a

View File

@ -31,6 +31,7 @@ import Hasura.RQL.IR.Select qualified as IR
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.Column
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.Function
import Hasura.SQL.AnyBackend qualified as AB
import Hasura.SQL.Backend
import Hasura.Session
@ -217,8 +218,8 @@ bqDBRemoteRelationshipPlan userInfo sourceName sourceConfig lhs lhsSchema argume
jsonToRecordSet =
IR.FromFunction
(BigQuery.FunctionName "unnest" Nothing)
( IR.FunctionArgsExp
[IR.AEInput rowsArgument]
( FunctionArgsExp
[BigQuery.AEInput rowsArgument]
mempty
)
(Just recordSetDefinitionList)

View File

@ -3,6 +3,7 @@
module Hasura.Backends.BigQuery.Instances.Metadata () where
import Hasura.Backends.BigQuery.DDL qualified as BigQuery
import Hasura.Base.Error (Code (UnexpectedPayload), throw400)
import Hasura.Prelude
import Hasura.RQL.Types.EventTrigger (RecreateEventTriggers (RETDoNothing))
import Hasura.RQL.Types.Metadata.Backend
@ -19,3 +20,5 @@ instance BackendMetadata 'BigQuery where
updateColumnInEventTrigger = BigQuery.updateColumnInEventTrigger
parseCollectableType = BigQuery.parseCollectableType
postDropSourceHook = BigQuery.postDropSourceHook
buildComputedFieldBooleanExp _ _ _ _ _ _ =
throw400 UnexpectedPayload "Computed fields are not supported in boolean expressions"

View File

@ -16,11 +16,13 @@ import Hasura.GraphQL.Parser hiding (EnumValueInfo, field)
import Hasura.GraphQL.Parser qualified as P
import Hasura.GraphQL.Parser.Constants qualified as G
import Hasura.GraphQL.Parser.Internal.Parser hiding (field)
import Hasura.GraphQL.Parser.Internal.Parser qualified as P
import Hasura.GraphQL.Schema.Backend
import Hasura.GraphQL.Schema.BoolExp
import Hasura.GraphQL.Schema.Build qualified as GSB
import Hasura.GraphQL.Schema.Common
import Hasura.GraphQL.Schema.Select
import Hasura.GraphQL.Schema.Table
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp
import Hasura.RQL.IR.Select qualified as IR
@ -29,7 +31,7 @@ import Hasura.RQL.Types.Column
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.ComputedField
import Hasura.RQL.Types.Function
import Hasura.RQL.Types.SchemaCache
import Hasura.RQL.Types.SchemaCache hiding (askTableInfo)
import Hasura.RQL.Types.Table
import Hasura.SQL.Backend
import Language.GraphQL.Draft.Syntax qualified as G
@ -373,15 +375,108 @@ geographyWithinDistanceInput = do
<*> (mkParameter <$> P.fieldWithDefault G._use_spheroid Nothing (G.VBoolean False) booleanParser)
-- | Computed field parser.
-- Currently unsupported: returns Nothing for now.
bqComputedField ::
forall r m n.
MonadBuildSchema 'BigQuery r m n =>
SourceName ->
ComputedFieldInfo 'BigQuery ->
TableName 'BigQuery ->
TableInfo 'BigQuery ->
m (Maybe (FieldParser n (AnnotatedField 'BigQuery)))
bqComputedField _sourceName _fieldInfo _table _tableInfo = pure Nothing
bqComputedField sourceName ComputedFieldInfo {..} tableName _tableInfo = runMaybeT do
stringifyNum <- asks $ qcStringifyNum . getter
fieldName <- lift $ textToName $ computedFieldNameToText _cfiName
functionArgsParser <- lift $ computedFieldFunctionArgs _cfiFunction
case _cfiReturnType of
BigQuery.ReturnExistingTable returnTable -> do
returnTableInfo <- lift $ askTableInfo sourceName returnTable
returnTablePermissions <- MaybeT $ tableSelectPermissions returnTableInfo
selectionSetParser <- MaybeT (fmap (P.multiple . P.nonNullableParser) <$> tableSelectionSet sourceName returnTableInfo)
selectArgsParser <- lift $ tableArguments sourceName returnTableInfo
let fieldArgsParser = liftA2 (,) functionArgsParser selectArgsParser
pure $
P.subselection fieldName fieldDescription fieldArgsParser selectionSetParser
<&> \((functionArgs', args), fields) ->
IR.AFComputedField _cfiXComputedFieldInfo _cfiName $
IR.CFSTable JASMultipleRows $
IR.AnnSelectG
{ IR._asnFields = fields,
IR._asnFrom = IR.FromFunction (_cffName _cfiFunction) functionArgs' Nothing,
IR._asnPerm = tablePermissionsInfo returnTablePermissions,
IR._asnArgs = args,
IR._asnStrfyNum = stringifyNum
}
BigQuery.ReturnTableSchema returnFields -> do
objectTypeName <-
P.mkTypename =<< do
computedFieldGQLName <- textToName $ computedFieldNameToText _cfiName
pure $ computedFieldGQLName <> G.__ <> G.__fields
selectionSetParser <- do
fieldParsers <- lift $ for returnFields selectArbitraryField
let description = G.Description $ "column fields returning by " <>> _cfiName
pure $
P.selectionSetObject objectTypeName (Just description) fieldParsers []
<&> parsedSelectionsToFields IR.AFExpression
pure $
P.subselection fieldName fieldDescription functionArgsParser selectionSetParser
<&> \(functionArgs', fields) ->
IR.AFComputedField _cfiXComputedFieldInfo _cfiName $
IR.CFSTable JASMultipleRows $
IR.AnnSelectG
{ IR._asnFields = fields,
IR._asnFrom = IR.FromFunction (_cffName _cfiFunction) functionArgs' Nothing,
IR._asnPerm = IR.noTablePermissions,
IR._asnArgs = IR.noSelectArgs,
IR._asnStrfyNum = stringifyNum
}
where
fieldDescription :: Maybe G.Description
fieldDescription = G.Description <$> _cfiDescription
selectArbitraryField ::
(BigQuery.ColumnName, G.Name, BigQuery.ScalarType) ->
m (FieldParser n (AnnotatedField 'BigQuery))
selectArbitraryField (columnName, graphQLName, columnType) = do
field <- columnParser @'BigQuery (ColumnScalar columnType) (G.Nullability True)
pure $
P.selection_ graphQLName Nothing field
$> IR.mkAnnColumnField columnName (ColumnScalar columnType) Nothing Nothing
computedFieldFunctionArgs ::
ComputedFieldFunction 'BigQuery ->
m (InputFieldsParser n (FunctionArgsExp 'BigQuery (UnpreparedValue 'BigQuery)))
computedFieldFunctionArgs ComputedFieldFunction {..} = do
let fieldName = G._args
fieldDesc =
G.Description $
"input parameters for computed field "
<> _cfiName <<> " defined on table " <>> tableName
objectName <-
P.mkTypename =<< do
tableInfo <- askTableInfo sourceName tableName
computedFieldGQLName <- textToName $ computedFieldNameToText _cfiName
tableGQLName <- getTableGQLName @'BigQuery tableInfo
pure $ computedFieldGQLName <> G.__ <> tableGQLName <> G.__args
let userInputArgs = filter (not . flip Map.member _cffComputedFieldImplicitArgs . BigQuery._faName) (toList _cffInputArgs)
argumentParsers <- sequenceA <$> forM userInputArgs parseArgument
let objectParser =
P.object objectName Nothing argumentParsers `P.bind` \inputArguments -> do
let tableColumnInputs = Map.map BigQuery.AETableColumn $ Map.mapKeys getFuncArgNameTxt _cffComputedFieldImplicitArgs
pure $ FunctionArgsExp mempty $ Map.fromList inputArguments <> tableColumnInputs
pure $ P.field fieldName (Just fieldDesc) objectParser
parseArgument :: BigQuery.FunctionArgument -> m (InputFieldsParser n (Text, BigQuery.ArgumentExp (UnpreparedValue 'BigQuery)))
parseArgument arg = do
typedParser <- columnParser (ColumnScalar $ BigQuery._faType arg) (G.Nullability False)
let argumentName = getFuncArgNameTxt $ BigQuery._faName arg
fieldName <- textToName argumentName
let argParser = P.field fieldName Nothing typedParser
pure $ argParser `P.bindFields` \inputValue -> pure ((argumentName, BigQuery.AEInput $ mkParameter inputValue))
{-
NOTE: Unused. Should we remove?

View File

@ -20,7 +20,7 @@ instance Backend 'BigQuery where
type TableName 'BigQuery = BigQuery.TableName
type FunctionName 'BigQuery = BigQuery.FunctionName
type RawFunctionInfo 'BigQuery = BigQuery.RestRoutine
type FunctionArgType 'BigQuery = Void
type FunctionArgument 'BigQuery = BigQuery.FunctionArgument
type ConstraintName 'BigQuery = Void
type BasicOrderType 'BigQuery = BigQuery.Order
type NullsOrderType 'BigQuery = BigQuery.NullsOrder
@ -32,9 +32,12 @@ instance Backend 'BigQuery where
type ScalarSelectionArguments 'BigQuery = Void
type BooleanOperators 'BigQuery = BigQuery.BooleanOperators
type ComputedFieldDefinition 'BigQuery = BigQuery.ComputedFieldDefinition
type XStreamingSubscription 'BigQuery = XDisable
type FunctionArgumentExp 'BigQuery = BigQuery.ArgumentExp
type ComputedFieldImplicitArguments 'BigQuery = BigQuery.ComputedFieldImplicitArguments
type ComputedFieldReturn 'BigQuery = BigQuery.ComputedFieldReturn
type XComputedField 'BigQuery = XDisable
type XStreamingSubscription 'BigQuery = XDisable
type XComputedField 'BigQuery = XEnable
type XRelay 'BigQuery = XDisable
type XNodesAgg 'BigQuery = XEnable
type XNestedInserts 'BigQuery = XDisable
@ -42,9 +45,6 @@ instance Backend 'BigQuery where
type ExtraTableMetadata 'BigQuery = ()
functionArgScalarType :: FunctionArgType 'BigQuery -> ScalarType 'BigQuery
functionArgScalarType = absurd
isComparableType :: ScalarType 'BigQuery -> Bool
isComparableType = BigQuery.isComparableType
@ -85,3 +85,14 @@ instance Backend 'BigQuery where
computedFieldFunction :: ComputedFieldDefinition 'BigQuery -> FunctionName 'BigQuery
computedFieldFunction = BigQuery._bqcfdFunction
computedFieldReturnType :: ComputedFieldReturn 'BigQuery -> ComputedFieldReturnType 'BigQuery
computedFieldReturnType = \case
BigQuery.ReturnExistingTable tableName -> ReturnsTable tableName
BigQuery.ReturnTableSchema _ -> ReturnsOthers
fromComputedFieldImplicitArguments :: v -> ComputedFieldImplicitArguments 'BigQuery -> [FunctionArgumentExp 'BigQuery v]
fromComputedFieldImplicitArguments _ _ =
-- As of now, computed fields are not supported in boolean and order by expressions.
-- We don't have to generate arguments expression from implicit arguments.
[]

View File

@ -28,16 +28,14 @@ import Data.Aeson qualified as Aeson
import Data.Foldable
import Data.Maybe
import Data.Sequence qualified as Seq
import Data.Text (Text)
import Data.Text qualified as T
import GHC.Generics
import Hasura.Backends.BigQuery.Connection
import Hasura.Backends.BigQuery.Source
import Hasura.Backends.BigQuery.Types
import Hasura.Prelude (hasuraJSON)
import Hasura.Prelude
import Network.HTTP.Simple
import Network.HTTP.Types
import Prelude
--------------------------------------------------------------------------------
-- Types
@ -298,7 +296,7 @@ data RestRoutineType
| SCALAR_FUNCTION
| PROCEDURE
| TABLE_VALUED_FUNCTION
deriving (Show, Generic)
deriving (Show, Eq, Generic)
instance FromJSON RestRoutineType
@ -306,23 +304,41 @@ instance FromJSON RestRoutineType
-- Ref: https://cloud.google.com/bigquery/docs/reference/rest/v2/routines#Argument
data RestArgument = RestArgument
{ -- | The name of this argument. Can be absent for function return argument.
_raName :: Maybe Text
_raName :: Maybe Text,
_raDataType :: Maybe RestType
}
deriving (Show, Generic)
instance FromJSON RestArgument where
parseJSON = genericParseJSON hasuraJSON
parseJSON =
withObject
"RestArgument"
( \o -> do
name <- o .:? "name"
typeObject <- o .:? "dataType"
type' <- mapM (.: "typeKind") typeObject
pure $ RestArgument name type'
)
-- | A field or a column.
-- Ref: https://cloud.google.com/bigquery/docs/reference/rest/v2/StandardSqlField
data RestStandardSqlField = RestStandardSqlField
{ -- | The field name is optional and is absent for fields with STRUCT type.
_rssfName :: Maybe Text
_rssfName :: Maybe Text,
_rssType :: Maybe RestType
}
deriving (Show, Generic)
instance FromJSON RestStandardSqlField where
parseJSON = genericParseJSON hasuraJSON
parseJSON =
withObject
"RestStandardSqlField"
( \o -> do
name <- o .:? "name"
typeObject <- o .:? "type"
type' <- mapM (.: "typeKind") typeObject
pure $ RestStandardSqlField name type'
)
-- | A table type, which has only list of columns with names and types.
-- Ref: https://cloud.google.com/bigquery/docs/reference/rest/v2/routines#StandardSqlTableType
@ -422,9 +438,10 @@ getRoutinesForDataSet conn dataSet = do
<> T.unpack dataSet
<> "/routines?alt=json&"
<> T.unpack (encodeParams extraParameters)
extraParameters = pageTokenParam
extraParameters = pageTokenParam <> readMaskParam
where
pageTokenParam =
case pageToken of
Nothing -> []
Just token -> [("pageToken", token)]
readMaskParam = [("readMask", "routineType,arguments,returnTableType")]

View File

@ -59,13 +59,17 @@ module Hasura.Backends.BigQuery.Types
scalarTypeGraphQLName,
scientificToText,
FunctionName (..),
ArgumentName (..),
ComputedFieldDefinition (..),
ArgumentExp (..),
ComputedFieldImplicitArguments,
ComputedFieldReturn (..),
FunctionArgument (..),
)
where
import Data.Aeson (FromJSON, FromJSONKey, ToJSON, ToJSONKey)
import Data.Aeson qualified as J
import Data.Aeson.Casing qualified as J
import Data.Aeson.Extended qualified as J
import Data.Aeson.Types qualified as J
import Data.ByteString (ByteString)
@ -87,6 +91,7 @@ import Hasura.Incremental.Internal.Dependency
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp
import Hasura.RQL.Types.Common qualified as RQL
import Hasura.RQL.Types.Function (FunctionArgName)
import Language.GraphQL.Draft.Syntax qualified as G
import Language.Haskell.TH.Syntax
import Text.ParserCombinators.ReadP (eof, readP_to_S)
@ -893,7 +898,11 @@ instance FromJSON FunctionName where
instance ToJSON FunctionName where
toJSON FunctionName {..} = J.object ["name" J..= functionName, "dataset" J..= functionNameSchema]
instance ToTxt FunctionName where toTxt = tshow
instance ToTxt FunctionName where
toTxt FunctionName {..} =
case functionNameSchema of
Nothing -> functionName
Just schemaName -> schemaName <> "." <> functionName
instance Hashable FunctionName
@ -903,18 +912,15 @@ instance ToJSONKey FunctionName
instance NFData FunctionName
newtype ArgumentName = ArgumentName {getArgumentName :: Text}
deriving (Eq, Show, Generic, Data, Lift, Ord, NFData, Hashable, Cacheable, ToJSON, ToJSONKey, FromJSON, FromJSONKey)
-- | The metadata required to define a computed field for a BigQuery table
data ComputedFieldDefinition = ComputedFieldDefinition
{ -- | Name of the user defined routine
_bqcfdFunction :: FunctionName,
-- | Name of the table which the function returns. If not provided
-- the return table is inferred from the routine API metadata.
-- the return table schema is inferred from the routine API metadata.
_bqcfdReturnTable :: Maybe TableName,
-- | A mapping context to determine argument value from table column
_bqcfdArgumentMapping :: HashMap ArgumentName ColumnName
_bqcfdArgumentMapping :: HashMap FunctionArgName ColumnName
}
deriving (Eq, Show, Generic, Data, Lift, Ord)
@ -930,6 +936,59 @@ instance ToJSON ComputedFieldDefinition where
instance FromJSON ComputedFieldDefinition where
parseJSON = J.genericParseJSON hasuraJSON
-- | A argument expression for SQL functions
data ArgumentExp v
= -- | Value coming from user's input through GraphQL query
AEInput v
| -- | For computed fields, value of column from the table
AETableColumn ColumnName
deriving stock (Eq, Show, Functor, Foldable, Traversable, Generic)
instance (Hashable v) => Hashable (ArgumentExp v)
type ComputedFieldImplicitArguments = HashMap FunctionArgName ColumnName
-- | Returning type of the function underlying a computed field
data ComputedFieldReturn
= -- | Returns existing table, needs to be present in the metadata
ReturnExistingTable TableName
| -- | An arbitrary table schema specified by column name and type pairs
ReturnTableSchema [(ColumnName, G.Name, ScalarType)]
deriving (Show, Eq, Generic)
instance Cacheable ComputedFieldReturn
instance NFData ComputedFieldReturn
instance Hashable ComputedFieldReturn
instance ToJSON ComputedFieldReturn where
toJSON =
J.genericToJSON $
J.defaultOptions
{ J.constructorTagModifier = J.snakeCase,
J.sumEncoding = J.TaggedObject "type" "info"
}
-- | Function input argument specification
data FunctionArgument = FunctionArgument
{ -- | Argument name of a table valued function is required
-- Ref: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_function_statement
_faName :: FunctionArgName,
-- | The data type of the argument
_faType :: ScalarType
}
deriving (Show, Eq, Generic)
instance Cacheable FunctionArgument
instance NFData FunctionArgument
instance Hashable FunctionArgument
instance ToJSON FunctionArgument where
toJSON = J.genericToJSON hasuraJSON
--------------------------------------------------------------------------------
-- Backend-related stuff
--

View File

@ -16,7 +16,7 @@ import Hasura.Backends.DataConnector.IR.Scalar.Value qualified as IR.S.V
import Hasura.Backends.DataConnector.IR.Table as IR.T
import Hasura.Base.Error (Code (ValidationFailed), QErr, throw400)
import Hasura.Prelude
import Hasura.RQL.Types.Backend (Backend (..), XDisable)
import Hasura.RQL.Types.Backend (Backend (..), ComputedFieldReturnType, XDisable)
import Hasura.RQL.Types.Common as RQL (boolScalar, floatScalar, stringScalar)
import Hasura.SQL.Backend (BackendType (DataConnector))
import Language.GraphQL.Draft.Syntax qualified as G
@ -41,7 +41,7 @@ instance Backend 'DataConnector where
type TableName 'DataConnector = IR.T.Name
type FunctionName 'DataConnector = IR.F.Name
type RawFunctionInfo 'DataConnector = XDisable
type FunctionArgType 'DataConnector = XDisable
type FunctionArgument 'DataConnector = XDisable
type ConstraintName 'DataConnector = Unimplemented
type BasicOrderType 'DataConnector = IR.O.OrderType
type NullsOrderType 'DataConnector = Unimplemented
@ -54,6 +54,9 @@ instance Backend 'DataConnector where
type BooleanOperators 'DataConnector = Const XDisable
type ExtraTableMetadata 'DataConnector = Unimplemented
type ComputedFieldDefinition 'DataConnector = Unimplemented
type FunctionArgumentExp 'DataConnector = Const Unimplemented
type ComputedFieldImplicitArguments 'DataConnector = Unimplemented
type ComputedFieldReturn 'DataConnector = Unimplemented
type XComputedField 'DataConnector = XDisable
type XRelay 'DataConnector = XDisable
@ -61,9 +64,6 @@ instance Backend 'DataConnector where
type XNestedInserts 'DataConnector = XDisable
type XStreamingSubscription 'DataConnector = XDisable
functionArgScalarType :: FunctionArgType 'DataConnector -> ScalarType 'DataConnector
functionArgScalarType = error "functionArgScalarType: not implemented for the Data Connector backend."
isComparableType :: ScalarType 'DataConnector -> Bool
isComparableType = isNumType @'DataConnector
@ -86,6 +86,12 @@ instance Backend 'DataConnector where
computedFieldFunction :: ComputedFieldDefinition 'DataConnector -> FunctionName 'DataConnector
computedFieldFunction = error "computedFieldFunction: not implemented for the Data Connector backend"
computedFieldReturnType :: ComputedFieldReturn 'DataConnector -> ComputedFieldReturnType 'DataConnector
computedFieldReturnType = error "computedFieldReturnType: not implemented for the Data Connector backend"
fromComputedFieldImplicitArguments :: v -> ComputedFieldImplicitArguments 'DataConnector -> [FunctionArgumentExp 'DataConnector v]
fromComputedFieldImplicitArguments = error "fromComputedFieldImplicitArguments: not implemented for the Data Connector backend"
-- phil said this was cursed
tableToFunction :: TableName 'DataConnector -> FunctionName 'DataConnector
tableToFunction = coerce

View File

@ -49,6 +49,8 @@ instance BackendMetadata 'DataConnector where
buildFunctionInfo = error "buildFunctionInfo: not implemented for the Data Connector backend."
updateColumnInEventTrigger = error "updateColumnInEventTrigger: not implemented for the Data Connector backend."
postDropSourceHook _sourceConfig = pure ()
buildComputedFieldBooleanExp _ _ _ _ _ _ =
error "buildComputedFieldBooleanExp: not implemented for the Data Connector backend."
resolveSourceConfig' ::
MonadIO m =>

View File

@ -40,12 +40,13 @@ buildComputedFieldInfo ::
(MonadError QErr m) =>
HashSet (TableName 'MSSQL) ->
TableName 'MSSQL ->
HashSet (Column 'MSSQL) ->
ComputedFieldName ->
ComputedFieldDefinition 'MSSQL ->
RawFunctionInfo 'MSSQL ->
Comment ->
m (ComputedFieldInfo 'MSSQL)
buildComputedFieldInfo _ _ _ _ _ _ =
buildComputedFieldInfo _ _ _ _ _ _ _ =
throw400 NotSupported "Computed fields aren't supported for MSSQL sources"
fetchAndValidateEnumValues ::

View File

@ -7,6 +7,7 @@
module Hasura.Backends.MSSQL.Instances.Metadata () where
import Hasura.Backends.MSSQL.DDL qualified as MSSQL
import Hasura.Base.Error (throw500)
import Hasura.RQL.Types.Metadata.Backend
import Hasura.SQL.Backend
@ -21,3 +22,5 @@ instance BackendMetadata 'MSSQL where
updateColumnInEventTrigger = MSSQL.updateColumnInEventTrigger
parseCollectableType = MSSQL.parseCollectableType
postDropSourceHook = MSSQL.postDropSourceHook
buildComputedFieldBooleanExp _ _ _ _ _ _ =
throw500 "Computed fields are not yet defined for MSSQL backends"

View File

@ -28,7 +28,7 @@ instance Backend 'MSSQL where
-- It's something of a wart that we have to
-- specify this here, as we don't support functions for MSSQL.
type FunctionName 'MSSQL = Text
type FunctionArgType 'MSSQL = Void
type FunctionArgument 'MSSQL = Void
type ConstraintName 'MSSQL = Text
type BasicOrderType 'MSSQL = MSSQL.Order
type NullsOrderType 'MSSQL = MSSQL.NullsOrder
@ -43,6 +43,9 @@ instance Backend 'MSSQL where
type BackendUpdate 'MSSQL = MSSQL.BackendUpdate
type ComputedFieldDefinition 'MSSQL = Void
type FunctionArgumentExp 'MSSQL = Const Void
type ComputedFieldImplicitArguments 'MSSQL = Void
type ComputedFieldReturn 'MSSQL = Void
type ExtraTableMetadata 'MSSQL = [MSSQL.ColumnName] -- List of identity columns
type BackendInsert 'MSSQL = MSSQL.BackendInsert
@ -53,9 +56,6 @@ instance Backend 'MSSQL where
type XNestedInserts 'MSSQL = XDisable
type XStreamingSubscription 'MSSQL = XDisable
functionArgScalarType :: FunctionArgType 'MSSQL -> ScalarType 'MSSQL
functionArgScalarType = absurd
isComparableType :: ScalarType 'MSSQL -> Bool
isComparableType = MSSQL.isComparableType
@ -92,3 +92,9 @@ instance Backend 'MSSQL where
computedFieldFunction :: ComputedFieldDefinition 'MSSQL -> FunctionName 'MSSQL
computedFieldFunction = absurd
computedFieldReturnType :: ComputedFieldReturn 'MSSQL -> ComputedFieldReturnType 'MSSQL
computedFieldReturnType = absurd
fromComputedFieldImplicitArguments :: v -> ComputedFieldImplicitArguments 'MSSQL -> [FunctionArgumentExp 'MSSQL v]
fromComputedFieldImplicitArguments _ = absurd

View File

@ -19,3 +19,5 @@ instance BackendMetadata 'MySQL where
updateColumnInEventTrigger = error "updateColumnInEventTrigger: MySQL backend does not support this operation yet."
parseCollectableType = error "parseCollectableType: MySQL backend does not support this operation yet."
postDropSourceHook = MySQL.postDropSourceHook
buildComputedFieldBooleanExp _ _ _ _ _ _ =
error "buildComputedFieldBooleanExp: MySQL backend does not support this operation yet."

View File

@ -19,7 +19,7 @@ instance Backend 'MySQL where
type TableName 'MySQL = MySQL.TableName
type FunctionName 'MySQL = MySQL.FunctionName
type RawFunctionInfo 'MySQL = Void -- MySQL.FunctionName
type FunctionArgType 'MySQL = Void
type FunctionArgument 'MySQL = Void
type ConstraintName 'MySQL = MySQL.ConstraintName
type BasicOrderType 'MySQL = MySQL.Order
type NullsOrderType 'MySQL = MySQL.NullsOrder
@ -31,6 +31,9 @@ instance Backend 'MySQL where
type ScalarSelectionArguments 'MySQL = Void
type BooleanOperators 'MySQL = Const Void
type ComputedFieldDefinition 'MySQL = Void
type FunctionArgumentExp 'MySQL = Const Void
type ComputedFieldImplicitArguments 'MySQL = Void
type ComputedFieldReturn 'MySQL = Void
type XComputedField 'MySQL = Void
type XRelay 'MySQL = Void
type XNodesAgg 'MySQL = XEnable
@ -38,9 +41,6 @@ instance Backend 'MySQL where
type XNestedInserts 'MySQL = XDisable
type XStreamingSubscription 'MySQL = XDisable
functionArgScalarType :: FunctionArgType 'MySQL -> ScalarType 'MySQL
functionArgScalarType = error "functionArgScalarType: not implemented yet"
isComparableType :: ScalarType 'MySQL -> Bool
isComparableType = isNumType @'MySQL -- TODO: For now we only allow comparisons for numeric types
@ -108,3 +108,9 @@ instance Backend 'MySQL where
computedFieldFunction :: ComputedFieldDefinition 'MySQL -> FunctionName 'MySQL
computedFieldFunction = error "computedFieldFunction: MySQL backend does not support this operation yet"
computedFieldReturnType :: ComputedFieldReturn 'MySQL -> ComputedFieldReturnType 'MySQL
computedFieldReturnType = error "computedFieldReturnType: MySQL backend does not support this operation yet"
fromComputedFieldImplicitArguments :: v -> ComputedFieldImplicitArguments 'MySQL -> [FunctionArgumentExp 'MySQL v]
fromComputedFieldImplicitArguments = error "fromComputedFieldImplicitArguments: MySQL backend does not support this operation yet"

View File

@ -5,6 +5,7 @@
-- See 'Hasura.RQL.DDL.Schema.Cache' and 'Hasura.RQL.Types.Eventing.Backend'.
module Hasura.Backends.Postgres.DDL.BoolExp
( parseBoolExpOperations,
buildComputedFieldBooleanExp,
)
where
@ -12,13 +13,17 @@ import Data.Aeson
import Data.HashMap.Strict qualified as Map
import Data.Text qualified as T
import Data.Text.Extended
import Hasura.Backends.Postgres.SQL.Types
import Hasura.Backends.Postgres.SQL.Types hiding (TableName)
import Hasura.Backends.Postgres.Types.BoolExp
import Hasura.Backends.Postgres.Types.ComputedField as PG
import Hasura.Base.Error
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.BoolExp
import Hasura.RQL.Types.Column
import Hasura.RQL.Types.ComputedField
import Hasura.RQL.Types.Function
import Hasura.RQL.Types.SchemaCache
import Hasura.RQL.Types.Table
import Hasura.SQL.Backend
@ -288,3 +293,37 @@ parseBoolExpOperations rhsParser rootTable fim columnRef value = do
parseVal :: (FromJSON a) => m a
parseVal = decodeValue val
buildComputedFieldBooleanExp ::
forall pgKind m v.
( MonadError QErr m,
Backend ('Postgres pgKind),
TableCoreInfoRM ('Postgres pgKind) m
) =>
BoolExpResolver ('Postgres pgKind) m v ->
BoolExpRHSParser ('Postgres pgKind) m v ->
TableName ('Postgres pgKind) ->
FieldInfoMap (FieldInfo ('Postgres pgKind)) ->
ComputedFieldInfo ('Postgres pgKind) ->
Value ->
m (AnnComputedFieldBoolExp ('Postgres pgKind) v)
buildComputedFieldBooleanExp boolExpResolver rhsParser rootTable colInfoMap ComputedFieldInfo {..} colVal = do
let ComputedFieldFunction {..} = _cfiFunction
case toList _cffInputArgs of
[] -> do
let hasuraSession = _berpSessionValue rhsParser
computedFieldFunctionArgs = flip FunctionArgsExp mempty $ PG.fromComputedFieldImplicitArguments hasuraSession _cffComputedFieldImplicitArgs
AnnComputedFieldBoolExp _cfiXComputedFieldInfo _cfiName _cffName computedFieldFunctionArgs
<$> case _cfiReturnType of
CFRScalar scalarType ->
CFBEScalar
<$> parseBoolExpOperations (_berpValueParser rhsParser) rootTable colInfoMap (ColumnReferenceComputedField _cfiName scalarType) colVal
CFRSetofTable table -> do
tableBoolExp <- decodeValue colVal
tableFieldInfoMap <- askFieldInfoMapSource table
annTableBoolExp <- (getBoolExpResolver boolExpResolver) rhsParser table tableFieldInfoMap $ unBoolExp tableBoolExp
pure $ CFBETable table annTableBoolExp
_ ->
throw400
UnexpectedPayload
"Computed columns with input arguments can not be part of the where clause"

View File

@ -14,7 +14,8 @@ import Data.Sequence qualified as Seq
import Data.Text.Extended
import Hasura.Backends.Postgres.DDL.Function
import Hasura.Backends.Postgres.SQL.Types
import Hasura.Backends.Postgres.Types.ComputedFieldDefinition qualified as PG
import Hasura.Backends.Postgres.Types.ComputedField qualified as PG
import Hasura.Backends.Postgres.Types.Function qualified as PG
import Hasura.Base.Error
import Hasura.Prelude
import Hasura.RQL.Types.Common (Comment (..))
@ -36,13 +37,13 @@ data ComputedFieldValidateError
data InvalidTableArgument
= ITANotFound !FunctionArgName
| ITANotComposite !FunctionTableArgument
| ITANotTable !QualifiedTable !FunctionTableArgument
| ITANotComposite !PG.FunctionTableArgument
| ITANotTable !QualifiedTable !PG.FunctionTableArgument
deriving (Show, Eq)
data InvalidSessionArgument
= ISANotFound !FunctionArgName
| ISANotJSON !FunctionSessionArgument
| ISANotJSON !PG.FunctionSessionArgument
deriving (Show, Eq)
showError :: QualifiedFunction -> ComputedFieldValidateError -> Text
@ -72,10 +73,10 @@ showError qf = \case
"the function " <> qf <<> " is of type VOLATILE; cannot be added as a computed field"
where
showFunctionTableArgument = \case
FTAFirst -> "first argument of the function " <>> qf
FTANamed argName _ -> argName <<> " argument of the function " <>> qf
PG.FTAFirst -> "first argument of the function " <>> qf
PG.FTANamed argName _ -> argName <<> " argument of the function " <>> qf
showFunctionSessionArgument = \case
FunctionSessionArgument argName _ -> argName <<> " argument of the function " <>> qf
PG.FunctionSessionArgument argName _ -> argName <<> " argument of the function " <>> qf
buildComputedFieldInfo ::
forall pgKind m.
@ -83,12 +84,13 @@ buildComputedFieldInfo ::
-- | the set of all tracked tables
S.HashSet QualifiedTable ->
QualifiedTable ->
S.HashSet PGCol ->
ComputedFieldName ->
PG.ComputedFieldDefinition ->
PGRawFunctionInfo ->
Comment ->
m (ComputedFieldInfo ('Postgres pgKind))
buildComputedFieldInfo trackedTables table computedField definition rawFunctionInfo comment =
buildComputedFieldInfo trackedTables table _tableColumns computedField definition rawFunctionInfo comment =
either (throw400 NotSupported . showErrors) pure =<< MV.runValidateT mkComputedFieldInfo
where
inputArgNames = rfiInputArgNames rawFunctionInfo
@ -122,14 +124,14 @@ buildComputedFieldInfo trackedTables table computedField definition rawFunctionI
MV.dispute $
pure $
CFVEReturnTableNotFound returnTable
pure $ CFRSetofTable returnTable
pure $ PG.CFRSetofTable returnTable
else do
let scalarType = _qptName functionReturnType
unless (isBaseType functionReturnType) $
MV.dispute $
pure $
CFVENotBaseReturnType scalarType
pure $ CFRScalar scalarType
pure $ PG.CFRScalar scalarType
-- Validate and resolve table argument
let inputArgs =
@ -139,10 +141,10 @@ buildComputedFieldInfo trackedTables table computedField definition rawFunctionI
inputArgNames
tableArgument <- case maybeTableArg of
Just argName ->
case findWithIndex ((Just argName ==) . faName) inputArgs of
case findWithIndex ((Just argName ==) . PG.faName) inputArgs of
Just (tableArg, index) -> do
let functionTableArg = FTANamed argName index
validateTableArgumentType functionTableArg $ faType tableArg
let functionTableArg = PG.FTANamed argName index
validateTableArgumentType functionTableArg $ PG.faType tableArg
pure functionTableArg
Nothing ->
MV.refute $ pure $ CFVEInvalidTableArgument $ ITANotFound argName
@ -150,15 +152,15 @@ buildComputedFieldInfo trackedTables table computedField definition rawFunctionI
case inputArgs of
[] -> MV.dispute $ pure CFVENoInputArguments
(firstArg : _) ->
validateTableArgumentType FTAFirst $ faType firstArg
pure FTAFirst
validateTableArgumentType PG.FTAFirst $ PG.faType firstArg
pure PG.FTAFirst
maybePGSessionArg <- sequence $ do
argName <- maybeSessionArg
return $ case findWithIndex ((Just argName ==) . faName) inputArgs of
return $ case findWithIndex ((Just argName ==) . PG.faName) inputArgs of
Just (sessionArg, index) -> do
let functionSessionArg = FunctionSessionArgument argName index
validateSessionArgumentType functionSessionArg $ faType sessionArg
let functionSessionArg = PG.FunctionSessionArgument argName index
validateSessionArgumentType functionSessionArg $ PG.faType sessionArg
pure functionSessionArg
Nothing ->
MV.refute $ pure $ CFVEInvalidSessionArgument $ ISANotFound argName
@ -166,15 +168,15 @@ buildComputedFieldInfo trackedTables table computedField definition rawFunctionI
let inputArgSeq =
Seq.fromList $
dropTableAndSessionArgument tableArgument maybePGSessionArg inputArgs
computedFieldArgs = PG.ComputedFieldImplicitArguments tableArgument maybePGSessionArg
computedFieldFunction =
ComputedFieldFunction function inputArgSeq tableArgument maybePGSessionArg $
rfiDescription rawFunctionInfo
ComputedFieldFunction function inputArgSeq computedFieldArgs $ rfiDescription rawFunctionInfo
pure $ ComputedFieldInfo @('Postgres pgKind) () computedField computedFieldFunction returnType description
validateTableArgumentType ::
(MV.MonadValidate [ComputedFieldValidateError] n) =>
FunctionTableArgument ->
PG.FunctionTableArgument ->
QualifiedPGType ->
n ()
validateTableArgumentType tableArg qpt = do
@ -186,7 +188,7 @@ buildComputedFieldInfo trackedTables table computedField definition rawFunctionI
validateSessionArgumentType ::
(MV.MonadValidate [ComputedFieldValidateError] n) =>
FunctionSessionArgument ->
PG.FunctionSessionArgument ->
QualifiedPGType ->
n ()
validateSessionArgumentType sessionArg qpt = do
@ -202,19 +204,19 @@ buildComputedFieldInfo trackedTables table computedField definition rawFunctionI
reasonMessage = makeReasonMessage allErrors (showError function)
dropTableAndSessionArgument ::
FunctionTableArgument ->
Maybe FunctionSessionArgument ->
[FunctionArg ('Postgres pgKind)] ->
[FunctionArg ('Postgres pgKind)]
PG.FunctionTableArgument ->
Maybe PG.FunctionSessionArgument ->
[PG.FunctionArg] ->
[PG.FunctionArg]
dropTableAndSessionArgument tableArg sessionArg inputArgs =
let withoutTable = case tableArg of
FTAFirst -> tail inputArgs
FTANamed argName _ ->
filter ((/=) (Just argName) . faName) inputArgs
PG.FTAFirst -> tail inputArgs
PG.FTANamed argName _ ->
filter ((/=) (Just argName) . PG.faName) inputArgs
alsoWithoutSession = case sessionArg of
Nothing -> withoutTable
Just (FunctionSessionArgument name _) ->
filter ((/=) (Just name) . faName) withoutTable
Just (PG.FunctionSessionArgument name _) ->
filter ((/=) (Just name) . PG.faName) withoutTable
in alsoWithoutSession
description :: Maybe Text

View File

@ -16,6 +16,7 @@ import Data.Sequence qualified as Seq
import Data.Text qualified as T
import Data.Text.Extended
import Hasura.Backends.Postgres.SQL.Types hiding (FunctionName)
import Hasura.Backends.Postgres.Types.Function
import Hasura.Base.Error
import Hasura.Prelude
import Hasura.RQL.Types.Backend
@ -28,7 +29,7 @@ import Hasura.SQL.Backend
import Hasura.Server.Utils
import Language.GraphQL.Draft.Syntax qualified as G
mkFunctionArgs :: Int -> [QualifiedPGType] -> [FunctionArgName] -> [FunctionArg ('Postgres pgKind)]
mkFunctionArgs :: Int -> [QualifiedPGType] -> [FunctionArgName] -> [FunctionArg]
mkFunctionArgs defArgsNo tys argNames =
bool withNames withNoNames $ null argNames
where

View File

@ -38,7 +38,7 @@ import Database.PG.Query qualified as Q
import Hasura.Backends.Postgres.Connection
import Hasura.Backends.Postgres.DDL.Source.Version
import Hasura.Backends.Postgres.SQL.Types hiding (FunctionName)
import Hasura.Backends.Postgres.Types.ComputedFieldDefinition
import Hasura.Backends.Postgres.Types.ComputedField
import Hasura.Base.Error
import Hasura.Logging
import Hasura.Prelude

View File

@ -39,6 +39,7 @@ import Hasura.Backends.Postgres.SQL.Types qualified as PG
import Hasura.Backends.Postgres.SQL.Value qualified as PG
import Hasura.Backends.Postgres.Translate.Select (PostgresAnnotatedFieldJSON)
import Hasura.Backends.Postgres.Translate.Select qualified as DS
import Hasura.Backends.Postgres.Types.Function qualified as PG
import Hasura.Backends.Postgres.Types.Update
import Hasura.Base.Error (QErr)
import Hasura.EncJSON (EncJSON, encJFromBS, encJFromJValue)
@ -86,6 +87,7 @@ import Hasura.RQL.Types.Common
SourceName,
StringifyNumbers,
)
import Hasura.RQL.Types.Function
import Hasura.SQL.AnyBackend qualified as AB
import Hasura.SQL.Backend
import Hasura.Session (UserInfo (..))
@ -488,7 +490,7 @@ pgDBRemoteRelationshipPlan userInfo sourceName sourceConfig lhs lhsSchema argume
jsonToRecordSet =
IR.FromFunction
(PG.QualifiedObject "pg_catalog" $ PG.FunctionName "jsonb_to_recordset")
(IR.FunctionArgsExp [IR.AEInput rowsArgument] mempty)
(FunctionArgsExp [PG.AEInput rowsArgument] mempty)
(Just recordSetDefinitionList)
rootSelection =

View File

@ -130,3 +130,4 @@ instance
parseCollectableType = PG.parseCollectableType
postDropSourceHook = PG.postDropSourceHook
validateRelationship = validateRel @pgKind
buildComputedFieldBooleanExp = PG.buildComputedFieldBooleanExp

View File

@ -139,9 +139,9 @@ instance
buildTableInsertMutationFields = GSB.buildTableInsertMutationFields backendInsertParser
buildTableUpdateMutationFields = pgkBuildTableUpdateMutationFields
buildTableDeleteMutationFields = GSB.buildTableDeleteMutationFields
buildFunctionQueryFields = GSB.buildFunctionQueryFields
buildFunctionQueryFields = GSB.buildFunctionQueryFieldsPG
buildFunctionRelayQueryFields = pgkBuildFunctionRelayQueryFields
buildFunctionMutationFields = GSB.buildFunctionMutationFields
buildFunctionMutationFields = GSB.buildFunctionMutationFieldsPG
-- table components
tableArguments = defaultTableArgs

View File

@ -19,7 +19,8 @@ import Hasura.Backends.Postgres.SQL.Types qualified as PG
import Hasura.Backends.Postgres.SQL.Value qualified as PG
import Hasura.Backends.Postgres.Types.BoolExp qualified as PG
import Hasura.Backends.Postgres.Types.CitusExtraTableMetadata qualified as Citus
import Hasura.Backends.Postgres.Types.ComputedFieldDefinition qualified as PG
import Hasura.Backends.Postgres.Types.ComputedField qualified as PG
import Hasura.Backends.Postgres.Types.Function qualified as PG
import Hasura.Backends.Postgres.Types.Insert qualified as PG (BackendInsert)
import Hasura.Backends.Postgres.Types.Update qualified as PG
import Hasura.Base.Error
@ -69,7 +70,7 @@ instance
type SourceConnConfiguration ('Postgres pgKind) = PG.PostgresConnConfiguration
type TableName ('Postgres pgKind) = PG.QualifiedTable
type FunctionName ('Postgres pgKind) = PG.QualifiedFunction
type FunctionArgType ('Postgres pgKind) = PG.QualifiedPGType
type FunctionArgument ('Postgres pgKind) = PG.FunctionArg
type RawFunctionInfo ('Postgres pgKind) = PG.PGRawFunctionInfo
type ConstraintName ('Postgres pgKind) = PG.ConstraintName
type BasicOrderType ('Postgres pgKind) = PG.OrderType
@ -83,6 +84,10 @@ instance
type ComputedFieldDefinition ('Postgres pgKind) = PG.ComputedFieldDefinition
type ScalarSelectionArguments ('Postgres pgKind) = PG.ColumnOp
type FunctionArgumentExp ('Postgres pgKind) = PG.ArgumentExp
type ComputedFieldImplicitArguments ('Postgres pgKind) = PG.ComputedFieldImplicitArguments
type ComputedFieldReturn ('Postgres pgKind) = PG.ComputedFieldReturn
type BackendUpdate ('Postgres pgKind) = PG.BackendUpdate
type ExtraTableMetadata ('Postgres pgKind) = PgExtraTableMetadata pgKind
@ -94,7 +99,6 @@ instance
type XNestedInserts ('Postgres pgKind) = XEnable
type XStreamingSubscription ('Postgres pgKind) = XEnable
functionArgScalarType = PG.mkFunctionArgScalarType
isComparableType = PG.isComparableType
isNumType = PG.isNumType
textToScalarValue = PG.textToScalarValue
@ -103,6 +107,10 @@ instance
functionToTable = fmap (PG.TableName . PG.getFunctionTxt)
tableToFunction = fmap (PG.FunctionName . PG.getTableTxt)
computedFieldFunction = PG._cfdFunction
computedFieldReturnType = \case
PG.CFRScalar scalarType -> ReturnsScalar scalarType
PG.CFRSetofTable table -> ReturnsTable table
fromComputedFieldImplicitArguments = PG.fromComputedFieldImplicitArguments
tableGraphQLName = PG.qualifiedObjectToName
functionGraphQLName = PG.qualifiedObjectToName

View File

@ -6,22 +6,23 @@
module Hasura.Backends.Postgres.Translate.BoolExp
( toSQLBoolExp,
annBoolExp,
BoolExpRHSParser (..),
)
where
import Data.HashMap.Strict qualified as M
import Data.Text.Extended (ToTxt, (<<>))
import Data.Text.Extended (ToTxt)
import Hasura.Backends.Postgres.SQL.DML qualified as S
import Hasura.Backends.Postgres.SQL.Types hiding (TableName)
import Hasura.Backends.Postgres.Types.BoolExp
import Hasura.Backends.Postgres.Types.Function (onArgumentExp)
import Hasura.Base.Error
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.BoolExp
import Hasura.RQL.Types.Column
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.ComputedField
import Hasura.RQL.Types.Function
import Hasura.RQL.Types.Metadata.Backend
import Hasura.RQL.Types.Relationships.Local
import Hasura.RQL.Types.SchemaCache
@ -29,14 +30,6 @@ import Hasura.RQL.Types.Table
import Hasura.SQL.Backend
import Hasura.SQL.Types
-- | Context to parse a RHS value in a boolean expression
data BoolExpRHSParser (b :: BackendType) m v = BoolExpRHSParser
{ -- | Parse a JSON value with enforcing a column type
_berpValueParser :: !(ValueParser b m v),
-- | Required for a computed field SQL function with session argument
_berpSessionValue :: !v
}
-- This convoluted expression instead of col = val
-- to handle the case of col : null
equalsBoolExpBuilder :: SQLExpression ('Postgres pgKind) -> SQLExpression ('Postgres pgKind) -> S.BoolExp
@ -98,28 +91,9 @@ annColExp rhsParser rootTable colInfoMap (ColExp fieldName colVal) = do
relFieldInfoMap <- askFieldInfoMapSource $ riRTable relInfo
annRelBoolExp <- annBoolExp rhsParser rootTable relFieldInfoMap $ unBoolExp relBoolExp
return $ AVRelationship relInfo annRelBoolExp
FIComputedField ComputedFieldInfo {..} -> do
let ComputedFieldFunction {..} = _cfiFunction
case toList _cffInputArgs of
[] -> do
let hasuraSession = _berpSessionValue rhsParser
sessionArgPresence = mkSessionArgumentPresence hasuraSession _cffSessionArgument _cffTableArgument
AVComputedField . AnnComputedFieldBoolExp _cfiXComputedFieldInfo _cfiName _cffName sessionArgPresence
<$> case _cfiReturnType of
CFRScalar scalarType ->
CFBEScalar
<$> parseBoolExpOperations (_berpValueParser rhsParser) rootTable colInfoMap (ColumnReferenceComputedField _cfiName scalarType) colVal
CFRSetofTable table -> do
tableBoolExp <- decodeValue colVal
tableFieldInfoMap <- askFieldInfoMapSource table
annTableBoolExp <- annBoolExp rhsParser table tableFieldInfoMap $ unBoolExp tableBoolExp
pure $ CFBETable table annTableBoolExp
_ ->
throw400
UnexpectedPayload
"Computed columns with input arguments can not be part of the where clause"
-- TODO Rakesh (from master)
FIComputedField computedFieldInfo ->
AVComputedField <$> buildComputedFieldBooleanExp (BoolExpResolver annBoolExp) rhsParser rootTable colInfoMap computedFieldInfo colVal
-- Using remote fields in the boolean expression is not supported.
FIRemoteRelationship {} ->
throw400 UnexpectedPayload "remote field unsupported"
@ -239,22 +213,21 @@ translateBoolExp = \case
data LHSField b
= LColumn !FieldName
| LComputedField !QualifiedFunction !(SessionArgumentPresence (SQLExpression b))
| LComputedField !QualifiedFunction !(FunctionArgsExp b (SQLExpression b))
mkComputedFieldFunctionExp ::
S.Qual ->
QualifiedFunction ->
SessionArgumentPresence (SQLExpression ('Postgres pgKind)) ->
FunctionArgsExp ('Postgres pgKind) (SQLExpression ('Postgres pgKind)) ->
Maybe S.Alias ->
S.FunctionExp
mkComputedFieldFunctionExp qual function sessionArgPresence alias =
mkComputedFieldFunctionExp qual function functionArgs alias =
-- "function_schema"."function_name"("qual".*)
let tableRowInput = S.SEStar $ Just qual
functionArgs = flip S.FunctionArgs mempty $ case sessionArgPresence of
SAPNotPresent -> [tableRowInput] -- No session argument
SAPFirst sessArg -> [sessArg, tableRowInput]
SAPSecond sessArg -> [tableRowInput, sessArg]
in S.FunctionExp function functionArgs $ flip S.FunctionAlias Nothing <$> alias
resolvedFunctionArgs =
let FunctionArgsExp {..} = fmap (onArgumentExp tableRowInput (S.SEIdentifier . Identifier)) functionArgs
in S.FunctionArgs _faePositional _faeNamed
in S.FunctionExp function resolvedFunctionArgs $ flip S.FunctionAlias Nothing <$> alias
mkFieldCompExp ::
S.Qual -> S.Qual -> LHSField ('Postgres pgKind) -> OpExpG ('Postgres pgKind) S.SQLExp -> S.BoolExp
@ -345,16 +318,3 @@ mkFieldCompExp rootReference currTableReference lhsField = mkCompExp qLhsField
in sqlAll $ map (mkCompExp (S.SETyAnn lhs targetAnn)) operations
sqlAll = foldr (S.BEBin S.AndOp) (S.BELit True)
-------------------------------------------------------------------------------
-- | Asking for a table's fields info without explicit @'SourceName' argument.
-- The source name is implicitly inferred from @'SourceM' via @'TableCoreInfoRM'.
askFieldInfoMapSource ::
(QErrM m, Backend b, TableCoreInfoRM b m) =>
TableName b ->
m (FieldInfoMap (FieldInfo b))
askFieldInfoMapSource tableName = do
fmap _tciFieldInfoMap $
onNothingM (lookupTableCoreInfo tableName) $
throw400 NotExists $ "table " <> tableName <<> " does not exist"

View File

@ -21,9 +21,11 @@ where
import Hasura.Backends.Postgres.SQL.DML qualified as S
import Hasura.Backends.Postgres.SQL.Types (Identifier (..), QualifiedFunction, qualifiedObjectToText, toIdentifier)
import Hasura.Backends.Postgres.Translate.Select.Internal.Aliases
import Hasura.Backends.Postgres.Types.Function
import Hasura.Prelude
import Hasura.RQL.IR
import Hasura.RQL.Types.Common (FieldName)
import Hasura.RQL.Types.Function
import Hasura.SQL.Backend
-- | First element extractor expression from given record set
@ -76,7 +78,7 @@ encodeBase64 =
S.SEFnApp "regexp_replace" [e, S.SELit "\\n", S.SELit "", S.SELit "g"] Nothing
fromTableRowArgs ::
Identifier -> FunctionArgsExpTableRow S.SQLExp -> S.FunctionArgs
Identifier -> FunctionArgsExpG (ArgumentExp S.SQLExp) -> S.FunctionArgs
fromTableRowArgs prefix = toFunctionArgs . fmap toSQLExp
where
toFunctionArgs (FunctionArgsExp positional named) =

View File

@ -0,0 +1,127 @@
{-# LANGUAGE TemplateHaskell #-}
-- | Postgres types related to computed fields
module Hasura.Backends.Postgres.Types.ComputedField
( ComputedFieldDefinition (..),
FunctionTableArgument (..),
FunctionSessionArgument (..),
ComputedFieldImplicitArguments (..),
fromComputedFieldImplicitArguments,
ComputedFieldReturn (..),
_CFRScalar,
_CFRSetofTable,
)
where
import Control.Lens.TH (makePrisms)
import Data.Aeson.Casing
import Data.Aeson.Extended
import Hasura.Backends.Postgres.SQL.Types
import Hasura.Backends.Postgres.Types.Function
import Hasura.Incremental (Cacheable)
import Hasura.Prelude
import Hasura.RQL.Types.Function
data ComputedFieldDefinition = ComputedFieldDefinition
{ _cfdFunction :: !QualifiedFunction,
_cfdTableArgument :: !(Maybe FunctionArgName),
_cfdSessionArgument :: !(Maybe FunctionArgName)
}
deriving (Show, Eq, Generic)
instance NFData ComputedFieldDefinition
instance Hashable ComputedFieldDefinition
instance Cacheable ComputedFieldDefinition
instance ToJSON ComputedFieldDefinition where
toJSON = genericToJSON hasuraJSON {omitNothingFields = True}
instance FromJSON ComputedFieldDefinition where
parseJSON = genericParseJSON hasuraJSON {omitNothingFields = True}
-- | The function table argument is either the very first argument or the named
-- argument with an index. The index is 0 if the named argument is the first.
data FunctionTableArgument
= FTAFirst
| FTANamed
!FunctionArgName
-- ^ argument name
!Int
-- ^ argument index
deriving (Show, Eq, Generic)
instance Cacheable FunctionTableArgument
instance NFData FunctionTableArgument
instance Hashable FunctionTableArgument
instance ToJSON FunctionTableArgument where
toJSON FTAFirst = String "first_argument"
toJSON (FTANamed argName _) = object ["name" .= argName]
-- | The session argument, which passes Hasura session variables to a
-- SQL function as a JSON object.
data FunctionSessionArgument
= FunctionSessionArgument
!FunctionArgName
-- ^ The argument name
!Int
-- ^ The ordinal position in the function input parameters
deriving (Show, Eq, Generic)
instance Cacheable FunctionSessionArgument
instance NFData FunctionSessionArgument
instance Hashable FunctionSessionArgument
instance ToJSON FunctionSessionArgument where
toJSON (FunctionSessionArgument argName _) = toJSON argName
data ComputedFieldImplicitArguments = ComputedFieldImplicitArguments
{ _cffaTableArgument :: FunctionTableArgument,
_cffaSessionArgument :: Maybe FunctionSessionArgument
}
deriving stock (Show, Eq, Generic)
instance NFData ComputedFieldImplicitArguments
instance Hashable ComputedFieldImplicitArguments
instance Cacheable ComputedFieldImplicitArguments
instance ToJSON ComputedFieldImplicitArguments where
toJSON = genericToJSON hasuraJSON
fromComputedFieldImplicitArguments ::
v ->
ComputedFieldImplicitArguments ->
[ArgumentExp v]
fromComputedFieldImplicitArguments _ (ComputedFieldImplicitArguments _ Nothing) = [AETableRow] -- No session argument
fromComputedFieldImplicitArguments sess (ComputedFieldImplicitArguments FTAFirst _) = [AETableRow, AESession sess]
fromComputedFieldImplicitArguments sess (ComputedFieldImplicitArguments (FTANamed _ 0) _) = [AETableRow, AESession sess] -- Index is 0 implies table argument is first
fromComputedFieldImplicitArguments sess _ = [AESession sess, AETableRow]
data ComputedFieldReturn
= CFRScalar PGScalarType
| CFRSetofTable QualifiedTable
deriving (Show, Eq, Generic)
instance Cacheable ComputedFieldReturn
instance NFData ComputedFieldReturn
instance Hashable ComputedFieldReturn
instance ToJSON ComputedFieldReturn where
toJSON =
genericToJSON $
defaultOptions
{ constructorTagModifier = snakeCase . drop 3,
sumEncoding = TaggedObject "type" "info"
}
$(makePrisms ''ComputedFieldReturn)

View File

@ -1,32 +0,0 @@
-- | Postgres types ComputedFieldDefinition
--
-- Computed field metadata definition for a Postgres backend
module Hasura.Backends.Postgres.Types.ComputedFieldDefinition
( ComputedFieldDefinition (..),
)
where
import Data.Aeson.Extended
import Hasura.Backends.Postgres.SQL.Types
import Hasura.Incremental (Cacheable)
import Hasura.Prelude
import Hasura.RQL.Types.Function
data ComputedFieldDefinition = ComputedFieldDefinition
{ _cfdFunction :: !QualifiedFunction,
_cfdTableArgument :: !(Maybe FunctionArgName),
_cfdSessionArgument :: !(Maybe FunctionArgName)
}
deriving (Show, Eq, Generic)
instance NFData ComputedFieldDefinition
instance Hashable ComputedFieldDefinition
instance Cacheable ComputedFieldDefinition
instance ToJSON ComputedFieldDefinition where
toJSON = genericToJSON hasuraJSON {omitNothingFields = True}
instance FromJSON ComputedFieldDefinition where
parseJSON = genericParseJSON hasuraJSON {omitNothingFields = True}

View File

@ -0,0 +1,72 @@
-- | Postgres Types Functions
--
-- Postgres specific types related to SQL functions
module Hasura.Backends.Postgres.Types.Function
( ArgumentExp (..),
onArgumentExp,
actionResponsePayloadColumn,
FunctionArg (..),
HasDefault (..),
)
where
import Data.Aeson
import Hasura.Backends.Postgres.SQL.Types
import Hasura.Incremental (Cacheable)
import Hasura.Prelude
import Hasura.RQL.Types.Function
newtype HasDefault = HasDefault {unHasDefault :: Bool}
deriving (Show, Eq, Generic, ToJSON, Cacheable, NFData, Hashable)
data FunctionArg = FunctionArg
{ faName :: Maybe FunctionArgName,
faType :: QualifiedPGType,
faHasDefault :: HasDefault
}
deriving (Show, Eq, Generic)
instance Cacheable FunctionArg
instance NFData FunctionArg
instance Hashable FunctionArg
instance ToJSON FunctionArg where
toJSON = genericToJSON hasuraJSON
-- Function arguments
data ArgumentExp a
= -- | Table row accessor
AETableRow
| -- | Hardcoded reference to @hdb_catalog.hdb_action_log.response_payload@
AEActionResponsePayload
| -- | JSON/JSONB hasura session variable object
AESession a
| AEInput a
deriving stock (Eq, Show, Functor, Foldable, Traversable, Generic)
instance (Hashable a) => Hashable (ArgumentExp a)
-- | Eliminate 'ArgumentExp'
--
-- Used to ensure that the right column is used for 'AEActionResponsePayload'.
onArgumentExp ::
-- | Value to return for 'AETableRow'
a ->
-- | Create value to return for 'AEResponsePayload' given column text
(Text -> a) ->
-- | 'ArgumentExp' to eliminate
ArgumentExp a ->
a
onArgumentExp tableRow fromColumn = \case
AETableRow -> tableRow
AEActionResponsePayload -> fromColumn actionResponsePayloadColumn
AESession a -> a
AEInput a -> a
-- | Hardcoded @hdb_catalog.hdb_action_log.response_payload@ column name
actionResponsePayloadColumn :: Text
actionResponsePayloadColumn = "response_payload"
{-# INLINE actionResponsePayloadColumn #-}

View File

@ -43,6 +43,7 @@ import Hasura.Backends.Postgres.SQL.DML qualified as S
import Hasura.Backends.Postgres.SQL.Types
import Hasura.Backends.Postgres.SQL.Value (PGScalarValue (..))
import Hasura.Backends.Postgres.Translate.Select qualified as RS
import Hasura.Backends.Postgres.Types.Function qualified as TF
import Hasura.Base.Error
import Hasura.EncJSON
import Hasura.Eventing.Common
@ -66,6 +67,7 @@ import Hasura.RQL.Types.Common
import Hasura.RQL.Types.ComputedField
import Hasura.RQL.Types.CustomTypes
import Hasura.RQL.Types.Eventing
import Hasura.RQL.Types.Function
import Hasura.RQL.Types.SchemaCache
import Hasura.SQL.Backend
import Hasura.SQL.Types
@ -273,7 +275,7 @@ resolveAsyncActionQuery userInfo annAction =
IR.AsyncOutput annFields ->
RS.AFComputedField () (ComputedFieldName [nonEmptyTextQQ|__action_computed_field|]) $
RS.CFSTable jsonAggSelect $
processOutputSelectionSet RS.AEActionResponsePayload outputType definitionList annFields stringifyNumerics
processOutputSelectionSet TF.AEActionResponsePayload outputType definitionList annFields stringifyNumerics
IR.AsyncId -> mkAnnFldFromPGCol idColumn
IR.AsyncCreatedAt -> mkAnnFldFromPGCol createdAtColumn
IR.AsyncErrors -> mkAnnFldFromPGCol errorsColumn
@ -285,7 +287,7 @@ resolveAsyncActionQuery userInfo annAction =
PGValJSONB $
Q.JSONB $
J.toJSON [actionLogResponse]
functionArgs = RS.FunctionArgsExp [RS.AEInput actionLogInput] mempty
functionArgs = FunctionArgsExp [TF.AEInput actionLogInput] mempty
tableFromExp =
RS.FromFunction jsonbToRecordSet functionArgs $
Just
@ -300,7 +302,7 @@ resolveAsyncActionQuery userInfo annAction =
IR.AnnActionAsyncQuery _ actionId outputType asyncFields definitionList stringifyNumerics _ actionSource = annAction
idColumn = (unsafePGCol "id", PGUUID)
responsePayloadColumn = (unsafePGCol RS.actionResponsePayloadColumn, PGJSONB)
responsePayloadColumn = (unsafePGCol TF.actionResponsePayloadColumn, PGJSONB)
createdAtColumn = (unsafePGCol "created_at", PGTimeStampTZ)
errorsColumn = (unsafePGCol "errors", PGJSONB)
sessionVarsColumn = (unsafePGCol "session_variables", PGJSONB)
@ -631,7 +633,7 @@ callWebhook
| otherwise = False
processOutputSelectionSet ::
RS.ArgumentExp v ->
TF.ArgumentExp v ->
GraphQLType ->
[(PGCol, PGScalarType)] ->
IR.ActionFields ->
@ -647,7 +649,7 @@ processOutputSelectionSet tableRowInput actionOutputType definitionList actionFi
if isListType actionOutputType
then "jsonb_to_recordset" -- Multirow array response
else "jsonb_to_record" -- Single object response
functionArgs = RS.FunctionArgsExp [tableRowInput] mempty
functionArgs = FunctionArgsExp [tableRowInput] mempty
selectFrom = RS.FromFunction jsonbToPostgresRecordFunction functionArgs $ Just definitionList
actionFieldToAnnField :: IR.ActionFieldG Void -> RS.AnnFieldG ('Postgres 'Vanilla) Void v

View File

@ -22,6 +22,7 @@ import Hasura.RQL.IR
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.ComputedField
import Hasura.RQL.Types.Function
import Hasura.RQL.Types.Relationships.Remote
import Hasura.SQL.AnyBackend qualified as AB
import Language.GraphQL.Draft.Syntax qualified as G
@ -395,12 +396,13 @@ transformAnnFields fields = do
in (fmap snd annotatedJoinColumns, phantomFields_)
mkScalarComputedFieldSelect ::
forall b.
(Backend b) =>
ScalarComputedField b ->
AnnFieldG b Void (UnpreparedValue b)
mkScalarComputedFieldSelect ScalarComputedField {..} =
let functionArgs =
flip FunctionArgsExp mempty $
functionArgsWithTableRowAndSession UVSession _scfTableArgument _scfSessionArgument
flip FunctionArgsExp mempty $ fromComputedFieldImplicitArguments @b UVSession _scfComputedFieldImplicitArgs
fieldSelect =
flip CFSScalar Nothing $
ComputedFieldScalarSelect _scfFunction functionArgs _scfType Nothing

View File

@ -215,14 +215,16 @@ deriving instance
( Backend b,
Show (ScalarValue b),
Show (SourceConfig b),
Show (BooleanOperators b (P.UnpreparedValue b))
Show (BooleanOperators b (P.UnpreparedValue b)),
Show (FunctionArgumentExp b (P.UnpreparedValue b))
) =>
Show (RemoteSourceJoin b)
deriving instance
( Backend b,
Eq (ScalarValue b),
Eq (BooleanOperators b (P.UnpreparedValue b))
Eq (BooleanOperators b (P.UnpreparedValue b)),
Eq (FunctionArgumentExp b (P.UnpreparedValue b))
) =>
Eq (RemoteSourceJoin b)

View File

@ -88,7 +88,8 @@ type MonadBuildSchema b r m n =
-- See <#modelling Note BackendSchema modelling principles>.
class
( Backend b,
Eq (BooleanOperators b (UnpreparedValue b))
Eq (BooleanOperators b (UnpreparedValue b)),
Eq (FunctionArgumentExp b (UnpreparedValue b))
) =>
BackendSchema (b :: BackendType)
where

View File

@ -24,9 +24,11 @@ import Hasura.GraphQL.Schema.Common (askTableInfo, partialSQLExpToUnpreparedValu
import Hasura.GraphQL.Schema.Table
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.Column
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.ComputedField
import Hasura.RQL.Types.Function
import Hasura.RQL.Types.Relationships.Local
import Hasura.RQL.Types.SchemaCache hiding (askTableInfo)
import Hasura.RQL.Types.Table
@ -96,14 +98,17 @@ boolExp sourceName tableInfo = memoizeOn 'boolExp (sourceName, tableName) $ do
-- For a computed field to qualify in boolean expression it shouldn't have any input arguments
case toList _cffInputArgs of
[] -> do
let sessionArgPresence =
mkSessionArgumentPresence P.UVSession _cffSessionArgument _cffTableArgument
fmap (AVComputedField . AnnComputedFieldBoolExp _cfiXComputedFieldInfo _cfiName _cffName sessionArgPresence)
<$> case _cfiReturnType of
CFRScalar scalarType -> lift $ fmap CFBEScalar <$> comparisonExps @b (ColumnScalar scalarType)
CFRSetofTable table -> do
info <- askTableInfo sourceName table
let functionArgs =
flip FunctionArgsExp mempty $
fromComputedFieldImplicitArguments @b P.UVSession _cffComputedFieldImplicitArgs
fmap (AVComputedField . AnnComputedFieldBoolExp _cfiXComputedFieldInfo _cfiName _cffName functionArgs)
<$> case computedFieldReturnType @b _cfiReturnType of
ReturnsScalar scalarType -> lift $ fmap CFBEScalar <$> comparisonExps @b (ColumnScalar scalarType)
ReturnsTable table -> do
info <- askTableInfo @b sourceName table
lift $ fmap (CFBETable table) <$> boolExp sourceName info
ReturnsOthers -> hoistMaybe Nothing
_ -> hoistMaybe Nothing
-- Using remote relationship fields in boolean expressions is not supported.

View File

@ -44,8 +44,8 @@
-- they have the sizes and shapes that result in the most elegant uses of them
-- that we can manage.
module Hasura.GraphQL.Schema.Build
( buildFunctionMutationFields,
buildFunctionQueryFields,
( buildFunctionMutationFieldsPG,
buildFunctionQueryFieldsPG,
buildTableDeleteMutationFields,
buildTableInsertMutationFields,
buildTableQueryFields,
@ -71,6 +71,7 @@ import Hasura.RQL.Types.Function
import Hasura.RQL.Types.SchemaCache
import Hasura.RQL.Types.SourceCustomization
import Hasura.RQL.Types.Table
import Hasura.SQL.Backend
import Language.GraphQL.Draft.Syntax qualified as G
buildTableQueryFields ::
@ -231,15 +232,15 @@ buildTableDeleteMutationFields sourceName tableName tableInfo gqlName = do
defaultDeletePKDesc = "delete single row from the table: " <>> tableName
TableCustomRootFields {..} = _tcCustomRootFields . _tciCustomConfig $ _tiCoreInfo tableInfo
buildFunctionQueryFields ::
forall b r m n.
MonadBuildSchema b r m n =>
buildFunctionQueryFieldsPG ::
forall r m n pgKind.
MonadBuildSchema ('Postgres pgKind) r m n =>
SourceName ->
FunctionName b ->
FunctionInfo b ->
TableName b ->
m [FieldParser n (QueryDB b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b))]
buildFunctionQueryFields sourceName functionName functionInfo tableName = do
FunctionName ('Postgres pgKind) ->
FunctionInfo ('Postgres pgKind) ->
TableName ('Postgres pgKind) ->
m [FieldParser n (QueryDB ('Postgres pgKind) (RemoteRelationshipField UnpreparedValue) (UnpreparedValue ('Postgres pgKind)))]
buildFunctionQueryFieldsPG sourceName functionName functionInfo tableName = do
let -- select function
funcDesc =
Just . G.Description $
@ -259,15 +260,15 @@ buildFunctionQueryFields sourceName functionName functionInfo tableName = do
optionalFieldParser (QDBAggregation) $ selectFunctionAggregate sourceName functionInfo funcAggDesc
]
buildFunctionMutationFields ::
forall b r m n.
MonadBuildSchema b r m n =>
buildFunctionMutationFieldsPG ::
forall r m n pgKind.
MonadBuildSchema ('Postgres pgKind) r m n =>
SourceName ->
FunctionName b ->
FunctionInfo b ->
TableName b ->
m [FieldParser n (MutationDB b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b))]
buildFunctionMutationFields sourceName functionName functionInfo tableName = do
FunctionName ('Postgres pgKind) ->
FunctionInfo ('Postgres pgKind) ->
TableName ('Postgres pgKind) ->
m [FieldParser n (MutationDB ('Postgres pgKind) (RemoteRelationshipField UnpreparedValue) (UnpreparedValue ('Postgres pgKind)))]
buildFunctionMutationFieldsPG sourceName functionName functionInfo tableName = do
let funcDesc = Just $ G.Description $ "execute VOLATILE function " <> functionName <<> " which returns " <>> tableName
jsonAggSelect = _fiJsonAggSelect functionInfo
catMaybes

View File

@ -27,6 +27,7 @@ import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.Column
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.ComputedField
import Hasura.RQL.Types.Function
import Hasura.RQL.Types.Relationships.Local
import Hasura.RQL.Types.SchemaCache hiding (askTableInfo)
import Hasura.RQL.Types.Table
@ -89,18 +90,18 @@ orderByExp sourceName tableInfo = memoizeOn 'orderByExp (sourceName, tableInfoNa
let ComputedFieldFunction {..} = _cfiFunction
mkComputedFieldOrderBy =
let functionArgs =
flip IR.FunctionArgsExp mempty $
IR.functionArgsWithTableRowAndSession P.UVSession _cffTableArgument _cffSessionArgument
flip FunctionArgsExp mempty $
fromComputedFieldImplicitArguments @b P.UVSession _cffComputedFieldImplicitArgs
in IR.ComputedFieldOrderBy _cfiXComputedFieldInfo _cfiName _cffName functionArgs
fieldName <- hoistMaybe $ G.mkName $ toTxt _cfiName
guard $ _cffInputArgs == mempty -- No input arguments other than table row and session argument
case _cfiReturnType of
CFRScalar scalarType -> do
case computedFieldReturnType @b _cfiReturnType of
ReturnsScalar scalarType -> do
let computedFieldOrderBy = mkComputedFieldOrderBy $ IR.CFOBEScalar scalarType
pure $
P.fieldOptional fieldName Nothing (orderByOperator @b)
<&> fmap (pure . mkOrderByItemG @b (IR.AOCComputedField computedFieldOrderBy)) . join
CFRSetofTable table -> do
ReturnsTable table -> do
let aggregateFieldName = fieldName <> G.__aggregate
tableInfo' <- askTableInfo @b sourceName table
perms <- MaybeT $ tableSelectPermissions tableInfo'
@ -117,6 +118,7 @@ orderByExp sourceName tableInfo = memoizeOn 'orderByExp (sourceName, tableInfoNa
. IR.CFOBETableAggregation table newPerms
)
aggregationOrderBy
ReturnsOthers -> empty
FIRemoteRelationship _ -> empty
-- FIXME!

View File

@ -48,6 +48,8 @@ import Data.Text.Extended
import Data.These (partitionThese)
import Data.Traversable (mapAccumL)
import Hasura.Backends.Postgres.SQL.Types qualified as PG
import Hasura.Backends.Postgres.Types.ComputedField qualified as PG
import Hasura.Backends.Postgres.Types.Function qualified as PG
import Hasura.Base.Error
import Hasura.GraphQL.Execute.Types qualified as ET
import Hasura.GraphQL.Parser
@ -533,15 +535,15 @@ tableConnectionSelectionSet sourceName tableInfo = runMaybeT do
-- | User-defined function (AKA custom function)
selectFunction ::
forall b r m n.
MonadBuildSchema b r m n =>
forall r m n pgKind.
MonadBuildSchema ('Postgres pgKind) r m n =>
-- | source name
SourceName ->
-- | SQL function info
FunctionInfo b ->
FunctionInfo ('Postgres pgKind) ->
-- | field description, if any
Maybe G.Description ->
m (Maybe (FieldParser n (SelectExp b)))
m (Maybe (FieldParser n (SelectExp ('Postgres pgKind))))
selectFunction sourceName fi@FunctionInfo {..} description = runMaybeT do
tableInfo <- lift $ askTableInfo sourceName _fiReturnType
selectPermissions <- MaybeT $ tableSelectPermissions tableInfo
@ -569,20 +571,20 @@ selectFunction sourceName fi@FunctionInfo {..} description = runMaybeT do
JASMultipleRows -> tableSelectionList
selectFunctionAggregate ::
forall b r m n.
MonadBuildSchema b r m n =>
forall r m n pgKind.
MonadBuildSchema ('Postgres pgKind) r m n =>
-- | source name
SourceName ->
-- | SQL function info
FunctionInfo b ->
FunctionInfo ('Postgres pgKind) ->
-- | field description, if any
Maybe G.Description ->
m (Maybe (FieldParser n (AggSelectExp b)))
m (Maybe (FieldParser n (AggSelectExp ('Postgres pgKind))))
selectFunctionAggregate sourceName fi@FunctionInfo {..} description = runMaybeT do
targetTableInfo <- askTableInfo sourceName _fiReturnType
selectPermissions <- MaybeT $ tableSelectPermissions targetTableInfo
guard $ spiAllowAgg selectPermissions
xNodesAgg <- hoistMaybe $ nodesAggExtension @b
xNodesAgg <- hoistMaybe $ nodesAggExtension @('Postgres pgKind)
tableInfo <- askTableInfo sourceName _fiReturnType
nodesParser <- MaybeT $ tableSelectionList sourceName tableInfo
lift do
@ -1348,7 +1350,7 @@ computedFieldPG sourceName ComputedFieldInfo {..} parentTable tableInfo = runMay
fieldName <- lift $ textToName $ computedFieldNameToText _cfiName
functionArgsParser <- lift $ computedFieldFunctionArgs _cfiFunction
case _cfiReturnType of
CFRScalar scalarReturnType -> do
PG.CFRScalar scalarReturnType -> do
caseBoolExpMaybe <-
hoistMaybe (Map.lookup _cfiName (spiScalarComputedFields selectPermissions))
let caseBoolExpUnpreparedValue =
@ -1372,7 +1374,7 @@ computedFieldPG sourceName ComputedFieldInfo {..} parentTable tableInfo = runMay
)
dummyParser <- lift $ columnParser @('Postgres pgKind) (ColumnScalar scalarReturnType) (G.Nullability True)
pure $ P.selection fieldName fieldDescription fieldArgsParser dummyParser
CFRSetofTable tableName -> do
PG.CFRSetofTable tableName -> do
otherTableInfo <- lift $ askTableInfo sourceName tableName
remotePerms <- MaybeT $ tableSelectPermissions otherTableInfo
selectionSetParser <- MaybeT (fmap (P.multiple . P.nonNullableParser) <$> tableSelectionSet sourceName otherTableInfo)
@ -1396,28 +1398,28 @@ computedFieldPG sourceName ComputedFieldInfo {..} parentTable tableInfo = runMay
computedFieldFunctionArgs ::
ComputedFieldFunction ('Postgres pgKind) ->
m (InputFieldsParser n (IR.FunctionArgsExpTableRow (UnpreparedValue ('Postgres pgKind))))
m (InputFieldsParser n (FunctionArgsExp ('Postgres pgKind) (UnpreparedValue ('Postgres pgKind))))
computedFieldFunctionArgs ComputedFieldFunction {..} =
functionArgs (FTAComputedField _cfiName sourceName parentTable) (IAUserProvided <$> _cffInputArgs) <&> fmap addTableAndSessionArgument
where
addTableAndSessionArgument args@(IR.FunctionArgsExp positional named) =
let withTable = case _cffTableArgument of
FTAFirst -> IR.FunctionArgsExp (IR.AETableRow : positional) named
FTANamed argName index -> IR.insertFunctionArg argName index IR.AETableRow args
sessionArgVal = IR.AESession UVSession
in case _cffSessionArgument of
addTableAndSessionArgument args@(FunctionArgsExp positional named) =
let withTable = case PG._cffaTableArgument _cffComputedFieldImplicitArgs of
PG.FTAFirst -> FunctionArgsExp (PG.AETableRow : positional) named
PG.FTANamed argName index -> IR.insertFunctionArg argName index PG.AETableRow args
sessionArgVal = PG.AESession UVSession
in case PG._cffaSessionArgument _cffComputedFieldImplicitArgs of
Nothing -> withTable
Just (FunctionSessionArgument argName index) ->
Just (PG.FunctionSessionArgument argName index) ->
IR.insertFunctionArg argName index sessionArgVal withTable
-- | The custom SQL functions' input "args" field parser
-- > function_name(args: function_args)
customSQLFunctionArgs ::
MonadBuildSchema b r m n =>
FunctionInfo b ->
MonadBuildSchema ('Postgres pgKind) r m n =>
FunctionInfo ('Postgres pgKind) ->
G.Name ->
G.Name ->
m (InputFieldsParser n (IR.FunctionArgsExpTableRow (UnpreparedValue b)))
m (InputFieldsParser n (FunctionArgsExp ('Postgres pgKind) (UnpreparedValue ('Postgres pgKind))))
customSQLFunctionArgs FunctionInfo {..} functionName functionArgsName =
functionArgs
( FTACustomFunction $
@ -1440,11 +1442,11 @@ customSQLFunctionArgs FunctionInfo {..} functionName functionArgsName =
-- table row argument in the case of computed fields), the args object will
-- be omitted.
functionArgs ::
forall b r m n.
MonadBuildSchema b r m n =>
FunctionTrackedAs b ->
Seq.Seq (FunctionInputArgument b) ->
m (InputFieldsParser n (IR.FunctionArgsExpTableRow (UnpreparedValue b)))
forall r m n pgKind.
MonadBuildSchema ('Postgres pgKind) r m n =>
FunctionTrackedAs ('Postgres pgKind) ->
Seq.Seq (FunctionInputArgument ('Postgres pgKind)) ->
m (InputFieldsParser n (FunctionArgsExp ('Postgres pgKind) (UnpreparedValue ('Postgres pgKind))))
functionArgs functionTrackedAs (toList -> inputArgs) = do
-- First, we iterate through the original sql arguments in order, to find the
-- corresponding graphql names. At the same time, we create the input field
@ -1452,7 +1454,7 @@ functionArgs functionTrackedAs (toList -> inputArgs) = do
-- mandatory arguments. Optional arguments have a default value, mandatory
-- arguments don't.
let (names, session, optional, mandatory) = mconcat $ snd $ mapAccumL splitArguments 1 inputArgs
defaultArguments = IR.FunctionArgsExp (snd <$> session) Map.empty
defaultArguments = FunctionArgsExp (snd <$> session) Map.empty
if
| length session > 1 ->
@ -1472,7 +1474,7 @@ functionArgs functionTrackedAs (toList -> inputArgs) = do
FTAComputedField computedFieldName sourceName tableName -> do
tableInfo <- askTableInfo sourceName tableName
computedFieldGQLName <- textToName $ computedFieldNameToText computedFieldName
tableGQLName <- getTableGQLName @b tableInfo
tableGQLName <- getTableGQLName @('Postgres pgKind) tableInfo
pure $ computedFieldGQLName <> G.__ <> tableGQLName <> G.__args
FTACustomFunction (CustomFunctionNames {cfnArgsName}) ->
pure cfnArgsName
@ -1507,37 +1509,37 @@ functionArgs functionTrackedAs (toList -> inputArgs) = do
-- We also fail if we find a mandatory argument that was not
-- provided by the user.
named <- Map.fromList . catMaybes <$> traverse (namedArgument foundArguments) left
pure $ IR.FunctionArgsExp positional named
pure $ FunctionArgsExp positional named
pure $ P.field fieldName (Just fieldDesc) objectParser
where
sessionPlaceholder :: IR.ArgumentExp (UnpreparedValue b)
sessionPlaceholder = IR.AEInput P.UVSession
sessionPlaceholder :: PG.ArgumentExp (UnpreparedValue b)
sessionPlaceholder = PG.AEInput P.UVSession
splitArguments ::
Int ->
FunctionInputArgument b ->
FunctionInputArgument ('Postgres pgKind) ->
( Int,
( [Text], -- graphql names, in order
[(Text, IR.ArgumentExp (UnpreparedValue b))], -- session argument
[m (InputFieldsParser n (Maybe (Text, IR.ArgumentExp (UnpreparedValue b))))], -- optional argument
[m (InputFieldsParser n (Maybe (Text, IR.ArgumentExp (UnpreparedValue b))))] -- mandatory argument
[(Text, PG.ArgumentExp (UnpreparedValue ('Postgres pgKind)))], -- session argument
[m (InputFieldsParser n (Maybe (Text, PG.ArgumentExp (UnpreparedValue ('Postgres pgKind)))))], -- optional argument
[m (InputFieldsParser n (Maybe (Text, PG.ArgumentExp (UnpreparedValue ('Postgres pgKind)))))] -- mandatory argument
)
)
splitArguments positionalIndex (IASessionVariables name) =
let argName = getFuncArgNameTxt name
in (positionalIndex, ([argName], [(argName, sessionPlaceholder)], [], []))
splitArguments positionalIndex (IAUserProvided arg) =
let (argName, newIndex) = case faName arg of
let (argName, newIndex) = case PG.faName arg of
Nothing -> ("arg_" <> tshow positionalIndex, positionalIndex + 1)
Just name -> (getFuncArgNameTxt name, positionalIndex)
in if unHasDefault $ faHasDefault arg
in if PG.unHasDefault $ PG.faHasDefault arg
then (newIndex, ([argName], [], [parseArgument arg argName], []))
else (newIndex, ([argName], [], [], [parseArgument arg argName]))
parseArgument :: FunctionArg b -> Text -> m (InputFieldsParser n (Maybe (Text, IR.ArgumentExp (UnpreparedValue b))))
parseArgument :: FunctionArgument ('Postgres pgKind) -> Text -> m (InputFieldsParser n (Maybe (Text, PG.ArgumentExp (UnpreparedValue ('Postgres pgKind)))))
parseArgument arg name = do
typedParser <- columnParser (ColumnScalar $ functionArgScalarType @b $ faType arg) (G.Nullability True)
typedParser <- columnParser (ColumnScalar $ PG.mkFunctionArgScalarType $ PG.faType arg) (G.Nullability True)
fieldName <- textToName name
-- Since all postgres function arguments are nullable, we define the
@ -1552,20 +1554,20 @@ functionArgs functionTrackedAs (toList -> inputArgs) = do
-- explicit value of `null` is used, as long as we don't set a default
-- value, not even `null`.
let argParser = P.fieldOptional fieldName Nothing typedParser
pure $ argParser `mapField` ((name,) . IR.AEInput . mkParameter)
pure $ argParser `mapField` ((name,) . PG.AEInput . mkParameter)
namedArgument ::
HashMap Text (IR.ArgumentExp (UnpreparedValue b)) ->
(Text, FunctionInputArgument b) ->
n (Maybe (Text, IR.ArgumentExp (UnpreparedValue b)))
HashMap Text (PG.ArgumentExp (UnpreparedValue ('Postgres pgKind))) ->
(Text, FunctionInputArgument ('Postgres pgKind)) ->
n (Maybe (Text, PG.ArgumentExp (UnpreparedValue ('Postgres pgKind))))
namedArgument dictionary (name, inputArgument) = case inputArgument of
IASessionVariables _ -> pure $ Just (name, sessionPlaceholder)
IAUserProvided arg -> case Map.lookup name dictionary of
Just parsedValue -> case faName arg of
Just parsedValue -> case PG.faName arg of
Just _ -> pure $ Just (name, parsedValue)
Nothing -> parseErrorWith NotSupported "Only last set of positional arguments can be omitted"
Nothing ->
whenMaybe (not $ unHasDefault $ faHasDefault arg) $
whenMaybe (not $ PG.unHasDefault $ PG.faHasDefault arg) $
parseErrorWith NotSupported "Non default arguments cannot be omitted"
tablePermissionsInfo :: Backend b => SelPermInfo b -> TablePerms b

View File

@ -173,12 +173,13 @@ tableSelectFields sourceName tableInfo = do
tableInfo' <- askTableInfo sourceName $ riRTable relationshipInfo
isJust <$> tableSelectPermissions @b tableInfo'
canBeSelected (Just permissions) (FIComputedField computedFieldInfo) =
case _cfiReturnType computedFieldInfo of
CFRScalar _ ->
case computedFieldReturnType @b (_cfiReturnType computedFieldInfo) of
ReturnsScalar _ ->
pure $ Map.member (_cfiName computedFieldInfo) $ spiScalarComputedFields permissions
CFRSetofTable tableName -> do
ReturnsTable tableName -> do
tableInfo' <- askTableInfo sourceName tableName
isJust <$> tableSelectPermissions @b tableInfo'
ReturnsOthers -> pure False
canBeSelected _ (FIRemoteRelationship _) = pure True
tableColumns ::

View File

@ -269,14 +269,18 @@ buildSelPermInfo source tn fieldInfoMap sp = withPathK "permission" $ do
withPathK "computed_fields" $
indexedForM computedFields $ \fieldName -> do
computedFieldInfo <- askComputedFieldInfo fieldInfoMap fieldName
case _cfiReturnType computedFieldInfo of
CFRScalar _ -> pure fieldName
CFRSetofTable returnTable ->
case computedFieldReturnType @b (_cfiReturnType computedFieldInfo) of
ReturnsScalar _ -> pure fieldName
ReturnsTable returnTable ->
throw400 NotSupported $
"select permissions on computed field " <> fieldName
<<> " are auto-derived from the permissions on its returning table "
<> returnTable
<<> " and cannot be specified manually"
ReturnsOthers ->
throw400 NotSupported $
"cannot define select permissions on computed field " <> fieldName
<<> " which does not return existing table or scalar type"
let deps =
mkParentDep @b source tn :

View File

@ -23,6 +23,7 @@ import Hasura.Base.Error
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.BoolExp
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.Metadata.Backend
import Hasura.RQL.Types.Permission

View File

@ -88,13 +88,16 @@ addNonColumnFields =
buildInfoMapPreservingMetadata
(_cfmName . (^. _4))
(\(s, _, t, c) -> mkComputedFieldMetadataObject (s, t, c))
( proc (a, (b, c, d, e)) -> do
o <- interpretWriter -< buildComputedField a b c d e
( proc ((a, b), (c, d, e, f)) -> do
o <- interpretWriter -< buildComputedField a b c d e f
arrM liftEither -< o
)
-<
(HS.fromList $ M.keys rawTableInfo, map (source,pgFunctions,_nctiTable,) _nctiComputedFields)
( ( HS.fromList $ M.keys rawTableInfo,
HS.fromList $ map ciColumn $ M.elems columns
),
map (source,pgFunctions,_nctiTable,) _nctiComputedFields
)
-- the fields that can be used for defining join conditions to other sources/remote schemas:
-- 1. all columns
-- 2. computed fields which don't expect arguments other than the table row and user session
@ -103,9 +106,10 @@ addNonColumnFields =
computedFields = M.fromList $
flip mapMaybe (M.toList computedFieldInfos) $
\(cfName, (ComputedFieldInfo {..}, _)) -> do
scalarType <- case _cfiReturnType of
CFRScalar ty -> pure ty
CFRSetofTable {} -> Nothing
scalarType <- case computedFieldReturnType @b _cfiReturnType of
ReturnsScalar ty -> pure ty
ReturnsTable {} -> Nothing
ReturnsOthers {} -> Nothing
let ComputedFieldFunction {..} = _cfiFunction
case toList _cffInputArgs of
[] ->
@ -116,8 +120,7 @@ addNonColumnFields =
_cfiXComputedFieldInfo
_cfiName
_cffName
_cffTableArgument
_cffSessionArgument
_cffComputedFieldImplicitArgs
scalarType
_ -> Nothing
in M.union columnFields computedFields
@ -295,19 +298,20 @@ buildComputedField ::
BackendMetadata b
) =>
HashSet (TableName b) ->
HashSet (Column b) ->
SourceName ->
DBFunctionsMetadata b ->
TableName b ->
ComputedFieldMetadata b ->
m (Either QErr (Maybe (ComputedFieldInfo b)))
buildComputedField trackedTableNames source pgFunctions table cf@ComputedFieldMetadata {..} = runExceptT do
buildComputedField trackedTableNames tableColumns source pgFunctions table cf@ComputedFieldMetadata {..} = runExceptT do
let addComputedFieldContext e = "in computed field " <> _cfmName <<> ": " <> e
function = computedFieldFunction @b _cfmDefinition
funcDefs = fromMaybe [] $ M.lookup function pgFunctions
withRecordInconsistencyM (mkComputedFieldMetadataObject (source, table, cf)) $
modifyErr (addTableContext @b table . addComputedFieldContext) $ do
rawfi <- handleMultipleFunctions @b (computedFieldFunction @b _cfmDefinition) funcDefs
buildComputedFieldInfo trackedTableNames table _cfmName _cfmDefinition rawfi _cfmComment
buildComputedFieldInfo trackedTableNames table tableColumns _cfmName _cfmDefinition rawfi _cfmComment
mkRemoteRelationshipMetadataObject ::
forall b.

View File

@ -44,6 +44,7 @@ import Hasura.Base.Error
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.BoolExp
import Hasura.RQL.Types.Column
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.ComputedField

View File

@ -17,8 +17,6 @@ module Hasura.RQL.IR.BoolExp
opExpDepCol,
STIntersectsNbandGeommin (..),
STIntersectsGeomminNband (..),
SessionArgumentPresence (..),
mkSessionArgumentPresence,
ComputedFieldBoolExp (..),
AnnComputedFieldBoolExp (..),
AnnBoolExpFld (..),
@ -55,6 +53,7 @@ import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.Column
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.ComputedField
import Hasura.RQL.Types.Function
import Hasura.RQL.Types.Relationships.Local
import Hasura.SQL.Backend
import Hasura.Session
@ -328,33 +327,6 @@ opExpDepCol = \case
CLTE c -> Just c
_ -> Nothing
-- | The presence of session argument in the SQL function of a computed field.
-- Since we only support computed fields with SQL functions having maximum of 2 arguments in boolean expression,
-- the position (if present) is either first or second. The other mandatory argument is table row input.
data SessionArgumentPresence a
= SAPNotPresent
| SAPFirst a
| SAPSecond a
deriving (Show, Eq, Functor, Foldable, Traversable, Generic)
instance (NFData a) => NFData (SessionArgumentPresence a)
instance (Cacheable a) => Cacheable (SessionArgumentPresence a)
instance (Hashable a) => Hashable (SessionArgumentPresence a)
-- | Determine the position of session argument
mkSessionArgumentPresence :: forall v a. v -> Maybe a -> FunctionTableArgument -> SessionArgumentPresence v
mkSessionArgumentPresence sessionValue = \case
Nothing -> const $ SAPNotPresent
Just _ -> \case
-- If table argument is first, then session argument will be second
FTAFirst -> SAPSecond sessionValue
-- Argument index 0 implies it is first
FTANamed _ 0 -> SAPSecond sessionValue
-- If table argument is second, then session argument will be first
FTANamed {} -> SAPFirst sessionValue
-- | This type is used to represent the kinds of boolean expression used for compouted fields
-- based on the return type of the SQL function
data ComputedFieldBoolExp (b :: BackendType) a
@ -362,15 +334,15 @@ data ComputedFieldBoolExp (b :: BackendType) a
| CFBETable !(TableName b) !(AnnBoolExp b a) -- SQL function returning SET OF table
deriving (Functor, Foldable, Traversable, Generic)
deriving instance (Backend b, Eq (BooleanOperators b a), Eq a) => Eq (ComputedFieldBoolExp b a)
deriving instance (Backend b, Eq (BooleanOperators b a), Eq (FunctionArgumentExp b a), Eq a) => Eq (ComputedFieldBoolExp b a)
deriving instance (Backend b, Show (BooleanOperators b a), Show a) => Show (ComputedFieldBoolExp b a)
deriving instance (Backend b, Show (BooleanOperators b a), Show (FunctionArgumentExp b a), Show a) => Show (ComputedFieldBoolExp b a)
instance (Backend b, NFData (BooleanOperators b a), NFData a) => NFData (ComputedFieldBoolExp b a)
instance (Backend b, NFData (BooleanOperators b a), NFData (FunctionArgumentExp b a), NFData a) => NFData (ComputedFieldBoolExp b a)
instance (Backend b, Cacheable (BooleanOperators b a), Cacheable a) => Cacheable (ComputedFieldBoolExp b a)
instance (Backend b, Cacheable (BooleanOperators b a), Cacheable (FunctionArgumentExp b a), Cacheable a) => Cacheable (ComputedFieldBoolExp b a)
instance (Backend b, Hashable (BooleanOperators b a), Hashable a) => Hashable (ComputedFieldBoolExp b a)
instance (Backend b, Hashable (BooleanOperators b a), Hashable (FunctionArgumentExp b a), Hashable a) => Hashable (ComputedFieldBoolExp b a)
-- | Using a computed field in boolean expression.
-- Example: A computed field "full_name" ("first_name" || "last_name") is defined to the "user"
@ -390,20 +362,26 @@ data AnnComputedFieldBoolExp (b :: BackendType) a = AnnComputedFieldBoolExp
{ _acfbXFieldInfo :: !(XComputedField b),
_acfbName :: !ComputedFieldName,
_acfbFunction :: !(FunctionName b),
_acfbSessionArgumentPresence :: !(SessionArgumentPresence a),
_acfbFunctionArgsExp :: !(FunctionArgsExp b a),
_acfbBoolExp :: !(ComputedFieldBoolExp b a)
}
deriving (Functor, Foldable, Traversable, Generic)
deriving (Generic)
deriving instance (Backend b, Eq (BooleanOperators b a), Eq a) => Eq (AnnComputedFieldBoolExp b a)
deriving instance (Backend b) => Functor (AnnComputedFieldBoolExp b)
deriving instance (Backend b, Show (BooleanOperators b a), Show a) => Show (AnnComputedFieldBoolExp b a)
deriving instance (Backend b) => Foldable (AnnComputedFieldBoolExp b)
instance (Backend b, NFData (BooleanOperators b a), NFData a) => NFData (AnnComputedFieldBoolExp b a)
deriving instance (Backend b) => Traversable (AnnComputedFieldBoolExp b)
instance (Backend b, Cacheable (BooleanOperators b a), Cacheable a) => Cacheable (AnnComputedFieldBoolExp b a)
deriving instance (Backend b, Eq (BooleanOperators b a), Eq (FunctionArgumentExp b a), Eq a) => Eq (AnnComputedFieldBoolExp b a)
instance (Backend b, Hashable (BooleanOperators b a), Hashable a) => Hashable (AnnComputedFieldBoolExp b a)
deriving instance (Backend b, Show (BooleanOperators b a), Show (FunctionArgumentExp b a), Show a) => Show (AnnComputedFieldBoolExp b a)
instance (Backend b, NFData (BooleanOperators b a), NFData (FunctionArgumentExp b a), NFData a) => NFData (AnnComputedFieldBoolExp b a)
instance (Backend b, Cacheable (BooleanOperators b a), Cacheable (FunctionArgumentExp b a), Cacheable a) => Cacheable (AnnComputedFieldBoolExp b a)
instance (Backend b, Hashable (BooleanOperators b a), Hashable (FunctionArgumentExp b a), Hashable a) => Hashable (AnnComputedFieldBoolExp b a)
-- | This type is used for boolean terms in GBoolExp in the schema; there are two kinds boolean
-- terms:
@ -417,15 +395,15 @@ data AnnBoolExpFld (b :: BackendType) a
| AVComputedField !(AnnComputedFieldBoolExp b a)
deriving (Functor, Foldable, Traversable, Generic)
deriving instance (Backend b, Eq (BooleanOperators b a), Eq a) => Eq (AnnBoolExpFld b a)
deriving instance (Backend b, Eq (BooleanOperators b a), Eq (FunctionArgumentExp b a), Eq a) => Eq (AnnBoolExpFld b a)
deriving instance (Backend b, Show (BooleanOperators b a), Show a) => Show (AnnBoolExpFld b a)
deriving instance (Backend b, Show (BooleanOperators b a), Show (FunctionArgumentExp b a), Show a) => Show (AnnBoolExpFld b a)
instance (Backend b, NFData (BooleanOperators b a), NFData a) => NFData (AnnBoolExpFld b a)
instance (Backend b, NFData (BooleanOperators b a), NFData (FunctionArgumentExp b a), NFData a) => NFData (AnnBoolExpFld b a)
instance (Backend b, Cacheable (BooleanOperators b a), Cacheable a) => Cacheable (AnnBoolExpFld b a)
instance (Backend b, Cacheable (BooleanOperators b a), Cacheable (FunctionArgumentExp b a), Cacheable a) => Cacheable (AnnBoolExpFld b a)
instance (Backend b, Hashable (BooleanOperators b a), Hashable a) => Hashable (AnnBoolExpFld b a)
instance (Backend b, Hashable (BooleanOperators b a), Hashable (FunctionArgumentExp b a), Hashable a) => Hashable (AnnBoolExpFld b a)
instance (Backend b, ToJSONKeyValue (BooleanOperators b a), ToJSON a) => ToJSONKeyValue (AnnBoolExpFld b a) where
toJSONKeyValue = \case
@ -538,15 +516,15 @@ $(deriveJSON hasuraJSON ''STIntersectsGeomminNband)
newtype AnnColumnCaseBoolExpField (b :: BackendType) a = AnnColumnCaseBoolExpField {_accColCaseBoolExpField :: AnnBoolExpFld b a}
deriving (Functor, Foldable, Traversable, Generic)
deriving instance (Backend b, Eq (BooleanOperators b a), Eq a) => Eq (AnnColumnCaseBoolExpField b a)
deriving instance (Backend b, Eq (BooleanOperators b a), Eq (FunctionArgumentExp b a), Eq a) => Eq (AnnColumnCaseBoolExpField b a)
deriving instance (Backend b, Show (BooleanOperators b a), Show a) => Show (AnnColumnCaseBoolExpField b a)
deriving instance (Backend b, Show (BooleanOperators b a), Show (FunctionArgumentExp b a), Show a) => Show (AnnColumnCaseBoolExpField b a)
instance (Backend b, NFData (BooleanOperators b a), NFData a) => NFData (AnnColumnCaseBoolExpField b a)
instance (Backend b, NFData (BooleanOperators b a), NFData (FunctionArgumentExp b a), NFData a) => NFData (AnnColumnCaseBoolExpField b a)
instance (Backend b, Cacheable (BooleanOperators b a), Cacheable a) => Cacheable (AnnColumnCaseBoolExpField b a)
instance (Backend b, Cacheable (BooleanOperators b a), Cacheable (FunctionArgumentExp b a), Cacheable a) => Cacheable (AnnColumnCaseBoolExpField b a)
instance (Backend b, Hashable (BooleanOperators b a), Hashable a) => Hashable (AnnColumnCaseBoolExpField b a)
instance (Backend b, Hashable (BooleanOperators b a), Hashable (FunctionArgumentExp b a), Hashable a) => Hashable (AnnColumnCaseBoolExpField b a)
instance (Backend b, ToJSONKeyValue (BooleanOperators b a), ToJSON a) => ToJSONKeyValue (AnnColumnCaseBoolExpField b a) where
toJSONKeyValue = toJSONKeyValue . _accColCaseBoolExpField

View File

@ -30,6 +30,6 @@ data AnnDelG (b :: BackendType) (r :: Type) v = AnnDel
type AnnDel b = AnnDelG b Void (SQLExpression b)
deriving instance (Show (MutationOutputG b r a), Backend b, Show (BooleanOperators b a), Show a) => Show (AnnDelG b r a)
deriving instance (Show (MutationOutputG b r a), Backend b, Show (BooleanOperators b a), Show (FunctionArgumentExp b a), Show a) => Show (AnnDelG b r a)
$(makeLenses ''AnnDelG)

View File

@ -33,7 +33,7 @@ data MutFldG (b :: BackendType) (r :: Type) v
| MRet !(AnnFieldsG b r v)
deriving (Functor, Foldable, Traversable)
deriving instance (Show r, Backend b, Show (BooleanOperators b a), Show a) => Show (MutFldG b r a)
deriving instance (Show r, Backend b, Show (BooleanOperators b a), Show (FunctionArgumentExp b a), Show a) => Show (MutFldG b r a)
type MutFld b = MutFldG b Void (SQLExpression b)
@ -44,7 +44,7 @@ data MutationOutputG (b :: BackendType) (r :: Type) v
| MOutSinglerowObject !(AnnFieldsG b r v)
deriving (Functor, Foldable, Traversable)
deriving instance (Show (MutFldsG b r a), Show r, Backend b, Show (BooleanOperators b a), Show a) => Show (MutationOutputG b r a)
deriving instance (Show (MutFldsG b r a), Show r, Backend b, Show (BooleanOperators b a), Show (FunctionArgumentExp b a), Show a) => Show (MutationOutputG b r a)
type MutationOutput b = MutationOutputG b Void (SQLExpression b)

View File

@ -48,7 +48,6 @@ module Hasura.RQL.IR.Select
AnnotatedOrderByElement (..),
AnnotatedOrderByItem,
AnnotatedOrderByItemG,
ArgumentExp (..),
ArrayAggregateSelect,
ArrayAggregateSelectG,
ArrayConnectionSelect,
@ -70,9 +69,6 @@ module Hasura.RQL.IR.Select
ConnectionSplitKind (..),
EdgeField (..),
EdgeFields,
FunctionArgExp,
FunctionArgsExpG (..),
FunctionArgsExpTableRow,
FIIdentifier (..),
ObjectRelationSelect,
ObjectRelationSelectG,
@ -96,7 +92,6 @@ module Hasura.RQL.IR.Select
TablePerm,
TablePermG (..),
CountDistinct (..),
actionResponsePayloadColumn,
aarRelationshipName,
aarColumnMapping,
aarAnnSelect,
@ -114,14 +109,11 @@ module Hasura.RQL.IR.Select
csSplit,
csSlice,
csSelect,
emptyFunctionArgsExp,
functionArgsWithTableRowAndSession,
insertFunctionArg,
mkAnnColumnField,
mkAnnColumnFieldAsText,
noSelectArgs,
noTablePermissions,
onArgumentExp,
saDistinct,
saLimit,
saOffset,
@ -205,6 +197,7 @@ data AnnSelectG (b :: BackendType) (f :: Type -> Type) (v :: Type) = AnnSelectG
deriving stock instance
( Backend b,
Eq (BooleanOperators b v),
Eq (FunctionArgumentExp b v),
Eq v,
Eq (f v)
) =>
@ -213,6 +206,7 @@ deriving stock instance
deriving stock instance
( Backend b,
Show (BooleanOperators b v),
Show (FunctionArgumentExp b v),
Show v,
Show (f v)
) =>
@ -242,6 +236,7 @@ data
deriving instance
( Backend b,
Eq (BooleanOperators b v),
Eq (FunctionArgumentExp b v),
Eq v,
Eq (f v)
) =>
@ -250,6 +245,7 @@ deriving instance
deriving instance
( Backend b,
Show (BooleanOperators b v),
Show (FunctionArgumentExp b v),
Show v,
Show (f v)
) =>
@ -298,6 +294,7 @@ data ConnectionSelect (b :: BackendType) (r :: Type) v = ConnectionSelect
deriving stock instance
( Backend b,
Eq (BooleanOperators b v),
Eq (FunctionArgumentExp b v),
Eq v,
Eq r
) =>
@ -306,6 +303,7 @@ deriving stock instance
deriving stock instance
( Backend b,
Show (BooleanOperators b v),
Show (FunctionArgumentExp b v),
Show v,
Show r
) =>
@ -326,20 +324,23 @@ data ConnectionSplit (b :: BackendType) v = ConnectionSplit
deriving stock instance
( Backend b,
Eq v,
Eq (BooleanOperators b v)
Eq (BooleanOperators b v),
Eq (FunctionArgumentExp b v)
) =>
Eq (ConnectionSplit b v)
deriving stock instance
( Backend b,
Show v,
Show (BooleanOperators b v)
Show (BooleanOperators b v),
Show (FunctionArgumentExp b v)
) =>
Show (ConnectionSplit b v)
instance
( Backend b,
Hashable (BooleanOperators b v),
Hashable (FunctionArgumentExp b v),
Hashable (ColumnInfo b),
Hashable v
) =>
@ -376,16 +377,22 @@ data SelectFromG (b :: BackendType) v
| FromIdentifier FIIdentifier
| FromFunction
(FunctionName b)
(FunctionArgsExpTableRow v)
(FunctionArgsExp b v)
-- a definition list
(Maybe [(Column b, ScalarType b)])
deriving stock (Functor, Foldable, Traversable, Generic)
deriving stock (Generic)
deriving stock instance (Backend b, Eq v) => Eq (SelectFromG b v)
deriving stock instance (Backend b) => Functor (SelectFromG b)
deriving stock instance (Backend b, Show v) => Show (SelectFromG b v)
deriving stock instance (Backend b) => Foldable (SelectFromG b)
instance (Backend b, Hashable v) => Hashable (SelectFromG b v)
deriving stock instance (Backend b) => Traversable (SelectFromG b)
deriving stock instance (Backend b, Eq v, Eq (FunctionArgumentExp b v)) => Eq (SelectFromG b v)
deriving stock instance (Backend b, Show v, Show (FunctionArgumentExp b v)) => Show (SelectFromG b v)
instance (Backend b, Hashable v, Hashable (FunctionArgumentExp b v)) => Hashable (SelectFromG b v)
type SelectFrom b = SelectFromG b (SQLExpression b)
@ -407,6 +414,7 @@ type SelectStreamArgs b = SelectStreamArgsG b (SQLExpression b)
deriving instance
( Backend b,
Eq (BooleanOperators b v),
Eq (FunctionArgumentExp b v),
Eq v
) =>
Eq (SelectStreamArgsG b v)
@ -414,6 +422,7 @@ deriving instance
deriving instance
( Backend b,
Show (BooleanOperators b v),
Show (FunctionArgumentExp b v),
Show v
) =>
Show (SelectStreamArgsG b v)
@ -430,6 +439,7 @@ data SelectArgsG (b :: BackendType) v = SelectArgs
deriving stock instance
( Backend b,
Eq (BooleanOperators b v),
Eq (FunctionArgumentExp b v),
Eq v
) =>
Eq (SelectArgsG b v)
@ -437,6 +447,7 @@ deriving stock instance
instance
( Backend b,
Hashable (BooleanOperators b v),
Hashable (FunctionArgumentExp b v),
Hashable v
) =>
Hashable (SelectArgsG b v)
@ -444,6 +455,7 @@ instance
deriving stock instance
( Backend b,
Show (BooleanOperators b v),
Show (FunctionArgumentExp b v),
Show v
) =>
Show (SelectArgsG b v)
@ -467,26 +479,32 @@ data ComputedFieldOrderByElement (b :: BackendType) v
-- ^ Sort by aggregation fields of table rows returned by computed field
deriving stock (Generic, Functor, Foldable, Traversable)
deriving stock instance (Backend b, Eq v, Eq (BooleanOperators b v)) => Eq (ComputedFieldOrderByElement b v)
deriving stock instance (Backend b, Eq v, Eq (BooleanOperators b v), Eq (FunctionArgumentExp b v)) => Eq (ComputedFieldOrderByElement b v)
deriving stock instance (Backend b, Show v, Show (BooleanOperators b v)) => Show (ComputedFieldOrderByElement b v)
deriving stock instance (Backend b, Show v, Show (BooleanOperators b v), Show (FunctionArgumentExp b v)) => Show (ComputedFieldOrderByElement b v)
instance (Backend b, Hashable v, Hashable (BooleanOperators b v)) => Hashable (ComputedFieldOrderByElement b v)
instance (Backend b, Hashable v, Hashable (BooleanOperators b v), Hashable (FunctionArgumentExp b v)) => Hashable (ComputedFieldOrderByElement b v)
data ComputedFieldOrderBy (b :: BackendType) v = ComputedFieldOrderBy
{ _cfobXField :: XComputedField b,
_cfobName :: ComputedFieldName,
_cfobFunction :: FunctionName b,
_cfobFunctionArgsExp :: FunctionArgsExpTableRow v,
_cfobFunctionArgsExp :: FunctionArgsExp b v,
_cfobOrderByElement :: (ComputedFieldOrderByElement b v)
}
deriving stock (Generic, Functor, Foldable, Traversable)
deriving stock (Generic)
deriving stock instance (Backend b, Eq v, Eq (BooleanOperators b v)) => Eq (ComputedFieldOrderBy b v)
deriving stock instance (Backend b) => Functor (ComputedFieldOrderBy b)
deriving stock instance (Backend b, Show v, Show (BooleanOperators b v)) => Show (ComputedFieldOrderBy b v)
deriving stock instance (Backend b) => Foldable (ComputedFieldOrderBy b)
instance (Backend b, Hashable v, Hashable (BooleanOperators b v)) => Hashable (ComputedFieldOrderBy b v)
deriving stock instance (Backend b) => Traversable (ComputedFieldOrderBy b)
deriving stock instance (Backend b, Eq v, Eq (BooleanOperators b v), Eq (FunctionArgumentExp b v)) => Eq (ComputedFieldOrderBy b v)
deriving stock instance (Backend b, Show v, Show (BooleanOperators b v), Show (FunctionArgumentExp b v)) => Show (ComputedFieldOrderBy b v)
instance (Backend b, Hashable v, Hashable (BooleanOperators b v), Hashable (FunctionArgumentExp b v)) => Hashable (ComputedFieldOrderBy b v)
data AnnotatedOrderByElement (b :: BackendType) v
= AOCColumn (ColumnInfo b)
@ -503,11 +521,11 @@ data AnnotatedOrderByElement (b :: BackendType) v
| AOCComputedField (ComputedFieldOrderBy b v)
deriving stock (Generic, Functor, Foldable, Traversable)
deriving stock instance (Backend b, Eq v, Eq (BooleanOperators b v)) => Eq (AnnotatedOrderByElement b v)
deriving stock instance (Backend b, Eq v, Eq (BooleanOperators b v), Eq (FunctionArgumentExp b v)) => Eq (AnnotatedOrderByElement b v)
deriving stock instance (Backend b, Show v, Show (BooleanOperators b v)) => Show (AnnotatedOrderByElement b v)
deriving stock instance (Backend b, Show v, Show (BooleanOperators b v), Show (FunctionArgumentExp b v)) => Show (AnnotatedOrderByElement b v)
instance (Backend b, Hashable v, Hashable (BooleanOperators b v)) => Hashable (AnnotatedOrderByElement b v)
instance (Backend b, Hashable v, Hashable (BooleanOperators b v), Hashable (FunctionArgumentExp b v)) => Hashable (AnnotatedOrderByElement b v)
data AnnotatedAggregateOrderBy (b :: BackendType)
= AAOCount
@ -568,6 +586,7 @@ data AnnFieldG (b :: BackendType) (r :: Type) v
deriving stock instance
( Backend b,
Eq (BooleanOperators b v),
Eq (FunctionArgumentExp b v),
Eq v,
Eq r
) =>
@ -576,6 +595,7 @@ deriving stock instance
deriving stock instance
( Backend b,
Show (BooleanOperators b v),
Show (FunctionArgumentExp b v),
Show v,
Show r
) =>
@ -634,6 +654,7 @@ data TableAggregateFieldG (b :: BackendType) (r :: Type) v
deriving stock instance
( Backend b,
Eq (BooleanOperators b v),
Eq (FunctionArgumentExp b v),
Eq v,
Eq r
) =>
@ -642,6 +663,7 @@ deriving stock instance
deriving stock instance
( Backend b,
Show (BooleanOperators b v),
Show (FunctionArgumentExp b v),
Show v,
Show r
) =>
@ -696,6 +718,7 @@ data ConnectionField (b :: BackendType) (r :: Type) v
deriving stock instance
( Backend b,
Eq (BooleanOperators b v),
Eq (FunctionArgumentExp b v),
Eq v,
Eq r
) =>
@ -704,6 +727,7 @@ deriving stock instance
deriving stock instance
( Backend b,
Show (BooleanOperators b v),
Show (FunctionArgumentExp b v),
Show v,
Show r
) =>
@ -732,6 +756,7 @@ data EdgeField (b :: BackendType) (r :: Type) v
deriving stock instance
( Backend b,
Eq (BooleanOperators b v),
Eq (FunctionArgumentExp b v),
Eq v,
Eq r
) =>
@ -740,6 +765,7 @@ deriving stock instance
deriving stock instance
( Backend b,
Show (BooleanOperators b v),
Show (FunctionArgumentExp b v),
Show v,
Show r
) =>
@ -779,6 +805,7 @@ data AnnColumnField (b :: BackendType) v = AnnColumnField
deriving stock instance
( Backend b,
Eq (BooleanOperators b v),
Eq (FunctionArgumentExp b v),
Eq v
) =>
Eq (AnnColumnField b v)
@ -786,6 +813,7 @@ deriving stock instance
deriving stock instance
( Backend b,
Show (BooleanOperators b v),
Show (FunctionArgumentExp b v),
Show v
) =>
Show (AnnColumnField b v)
@ -794,15 +822,20 @@ deriving stock instance
data ComputedFieldScalarSelect (b :: BackendType) v = ComputedFieldScalarSelect
{ _cfssFunction :: FunctionName b,
_cfssArguments :: FunctionArgsExpTableRow v,
_cfssArguments :: FunctionArgsExp b v,
_cfssType :: ScalarType b,
_cfssScalarArguments :: (Maybe (ScalarSelectionArguments b))
}
deriving stock (Functor, Foldable, Traversable)
deriving stock instance (Backend b, Show v) => Show (ComputedFieldScalarSelect b v)
deriving stock instance (Backend b) => Functor (ComputedFieldScalarSelect b)
deriving stock instance (Backend b, Eq v) => Eq (ComputedFieldScalarSelect b v)
deriving stock instance (Backend b) => Foldable (ComputedFieldScalarSelect b)
deriving stock instance (Backend b) => Traversable (ComputedFieldScalarSelect b)
deriving stock instance (Backend b, Show v, Show (FunctionArgumentExp b v)) => Show (ComputedFieldScalarSelect b v)
deriving stock instance (Backend b, Eq v, Eq (FunctionArgumentExp b v)) => Eq (ComputedFieldScalarSelect b v)
data ComputedFieldSelect (b :: BackendType) (r :: Type) v
= CFSScalar
@ -820,6 +853,7 @@ data ComputedFieldSelect (b :: BackendType) (r :: Type) v
deriving stock instance
( Backend b,
Eq (BooleanOperators b v),
Eq (FunctionArgumentExp b v),
Eq v,
Eq r
) =>
@ -828,6 +862,7 @@ deriving stock instance
deriving stock instance
( Backend b,
Show (BooleanOperators b v),
Show (FunctionArgumentExp b v),
Show v,
Show r
) =>
@ -869,6 +904,7 @@ data AnnObjectSelectG (b :: BackendType) (r :: Type) v = AnnObjectSelectG
deriving stock instance
( Backend b,
Eq (BooleanOperators b v),
Eq (FunctionArgumentExp b v),
Eq v,
Eq r
) =>
@ -877,6 +913,7 @@ deriving stock instance
deriving stock instance
( Backend b,
Show (BooleanOperators b v),
Show (FunctionArgumentExp b v),
Show v,
Show r
) =>
@ -901,6 +938,7 @@ data ArraySelectG (b :: BackendType) (r :: Type) v
deriving stock instance
( Backend b,
Eq (BooleanOperators b v),
Eq (FunctionArgumentExp b v),
Eq v,
Eq r
) =>
@ -909,6 +947,7 @@ deriving stock instance
deriving stock instance
( Backend b,
Show (BooleanOperators b v),
Show (FunctionArgumentExp b v),
Show v,
Show r
) =>
@ -937,6 +976,7 @@ data
deriving stock instance
( Backend b,
Eq (BooleanOperators b (v b)),
Eq (FunctionArgumentExp b (v b)),
Eq (v b),
Eq r
) =>
@ -945,6 +985,7 @@ deriving stock instance
deriving stock instance
( Backend b,
Show (BooleanOperators b (v b)),
Show (FunctionArgumentExp b (v b)),
Show (v b),
Show r
) =>
@ -982,6 +1023,7 @@ data TablePermG (b :: BackendType) v = TablePerm
deriving stock instance
( Backend b,
Eq (BooleanOperators b v),
Eq (FunctionArgumentExp b v),
Eq v
) =>
Eq (TablePermG b v)
@ -989,6 +1031,7 @@ deriving stock instance
deriving stock instance
( Backend b,
Show (BooleanOperators b v),
Show (FunctionArgumentExp b v),
Show v
) =>
Show (TablePermG b v)
@ -996,6 +1039,7 @@ deriving stock instance
instance
( Backend b,
Hashable (BooleanOperators b v),
Hashable (FunctionArgumentExp b v),
Hashable (ColumnInfo b),
Hashable v
) =>
@ -1006,65 +1050,6 @@ type TablePerm b = TablePermG b (SQLExpression b)
noTablePermissions :: TablePermG backend v
noTablePermissions = TablePerm annBoolExpTrue Nothing
-- Function arguments
data ArgumentExp a
= -- | Table row accessor
AETableRow
| -- | Hardcoded reference to @hdb_catalog.hdb_action_log.response_payload@
AEActionResponsePayload
| -- | JSON/JSONB hasura session variable object
AESession a
| AEInput a
deriving stock (Eq, Show, Functor, Foldable, Traversable, Generic)
deriving anyclass (Hashable)
-- | Eliminate 'ArgumentExp'
--
-- Used to ensure that the right column is used for 'AEActionResponsePayload'.
onArgumentExp ::
-- | Value to return for 'AETableRow'
a ->
-- | Create value to return for 'AEResponsePayload' given column text
(Text -> a) ->
-- | 'ArgumentExp' to eliminate
ArgumentExp a ->
a
onArgumentExp tableRow fromColumn = \case
AETableRow -> tableRow
AEActionResponsePayload -> fromColumn actionResponsePayloadColumn
AESession a -> a
AEInput a -> a
-- | Hardcoded @hdb_catalog.hdb_action_log.response_payload@ column name
actionResponsePayloadColumn :: Text
actionResponsePayloadColumn = "response_payload"
{-# INLINE actionResponsePayloadColumn #-}
data FunctionArgsExpG a = FunctionArgsExp
{ _faePositional :: [a],
_faeNamed :: (HM.HashMap Text a)
}
deriving stock (Show, Eq, Functor, Foldable, Traversable, Generic)
deriving anyclass (Hashable)
type FunctionArgsExpTableRow v = FunctionArgsExpG (ArgumentExp v)
type FunctionArgExp b = FunctionArgsExpG (SQLExpression b)
emptyFunctionArgsExp :: FunctionArgsExpG a
emptyFunctionArgsExp = FunctionArgsExp [] HM.empty
functionArgsWithTableRowAndSession ::
v ->
FunctionTableArgument ->
Maybe FunctionSessionArgument ->
[ArgumentExp v]
functionArgsWithTableRowAndSession _ _ Nothing = [AETableRow] -- No session argument
functionArgsWithTableRowAndSession sess (FTAFirst) _ = [AETableRow, AESession sess]
functionArgsWithTableRowAndSession sess (FTANamed _ 0) _ = [AETableRow, AESession sess] -- Index is 0 implies table argument is first
functionArgsWithTableRowAndSession sess _ _ = [AESession sess, AETableRow]
-- | If argument positional index is less than or equal to length of
-- 'positional' arguments then insert the value in 'positional' arguments else
-- insert the value with argument name in 'named' arguments

View File

@ -1,12 +1,17 @@
{-# LANGUAGE TemplateHaskell #-}
module Hasura.RQL.Types.Backend
( Backend (..),
Representable,
SessionVarType,
XDisable,
XEnable,
ComputedFieldReturnType (..),
_ReturnsScalar,
)
where
import Control.Lens.TH (makePrisms)
import Data.Aeson.Extended
import Data.Kind (Type)
import Data.Text.Extended
@ -23,6 +28,11 @@ type Representable a = (Show a, Eq a, Hashable a, Cacheable a, NFData a)
type SessionVarType b = CollectableType (ScalarType b)
data ComputedFieldReturnType (b :: BackendType)
= ReturnsScalar (ScalarType b)
| ReturnsTable (TableName b)
| ReturnsOthers
-- Used for extension types.
type XEnable = ()
@ -48,7 +58,7 @@ type XDisable = Void
class
( Representable (TableName b),
Representable (FunctionName b),
Representable (FunctionArgType b),
Representable (FunctionArgument b),
Representable (ConstraintName b),
Representable (BasicOrderType b),
Representable (NullsOrderType b),
@ -60,6 +70,8 @@ class
Representable (ExtraTableMetadata b),
Representable (XComputedField b),
Representable (ComputedFieldDefinition b),
Representable (ComputedFieldImplicitArguments b),
Representable (ComputedFieldReturn b),
Ord (TableName b),
Ord (FunctionName b),
Ord (ScalarType b),
@ -79,7 +91,7 @@ class
ToJSON (BackendConfig b),
ToJSON (Column b),
ToJSON (ConstraintName b),
ToJSON (FunctionArgType b),
ToJSON (FunctionArgument b),
ToJSON (FunctionName b),
ToJSON (ScalarType b),
ToJSON (SourceConfig b),
@ -88,6 +100,8 @@ class
ToJSON (ExtraTableMetadata b),
ToJSON (SQLExpression b),
ToJSON (ComputedFieldDefinition b),
ToJSON (ComputedFieldImplicitArguments b),
ToJSON (ComputedFieldReturn b),
ToJSONKey (Column b),
ToJSONKey (FunctionName b),
ToJSONKey (ScalarType b),
@ -103,6 +117,10 @@ class
Typeable (ConstraintName b),
Typeable b,
HasTag b,
-- constraints of function argument
Functor (FunctionArgumentExp b),
Foldable (FunctionArgumentExp b),
Traversable (FunctionArgumentExp b),
-- Type constraints.
Eq (BackendConfig b),
Show (BackendConfig b),
@ -148,9 +166,6 @@ class
-- database
type RawFunctionInfo b :: Type
-- Type of a function argument
type FunctionArgType b :: Type
-- Fully qualified name of a constraint
type ConstraintName b :: Type
@ -181,6 +196,18 @@ class
type ExtraTableMetadata b :: Type
-- | FunctionArgument
type FunctionArgument b :: Type
-- | Function input argument expression
type FunctionArgumentExp b :: Type -> Type
-- | Computed field function argument values which are being implicitly inferred from table and/or session information
type ComputedFieldImplicitArguments b :: Type
-- | Computed field return information
type ComputedFieldReturn b :: Type
-- Backend-specific IR types
-- | Intermediate Representation of Update Mutations.
@ -206,7 +233,6 @@ class
type XStreamingSubscription b :: Type
-- functions on types
functionArgScalarType :: FunctionArgType b -> ScalarType b
isComparableType :: ScalarType b -> Bool
isNumType :: ScalarType b -> Bool
textToScalarValue :: Maybe Text -> ScalarValue b
@ -215,6 +241,10 @@ class
functionToTable :: FunctionName b -> TableName b
tableToFunction :: TableName b -> FunctionName b
computedFieldFunction :: ComputedFieldDefinition b -> FunctionName b
computedFieldReturnType :: ComputedFieldReturn b -> ComputedFieldReturnType b
-- | Build function arguments expression from computed field implicit arguments
fromComputedFieldImplicitArguments :: v -> ComputedFieldImplicitArguments b -> [FunctionArgumentExp b v]
-- functions on names
tableGraphQLName :: TableName b -> Either QErr G.Name
@ -227,3 +257,6 @@ class
-- TODO: metadata related functions
snakeCaseTableName :: TableName b -> Text
-- Prisms
$(makePrisms ''ComputedFieldReturnType)

View File

@ -0,0 +1,29 @@
module Hasura.RQL.Types.BoolExp
( BoolExpRHSParser (..),
BoolExpResolver (..),
)
where
import Hasura.RQL.IR.BoolExp
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.Column
import Hasura.RQL.Types.Table
import Hasura.SQL.Backend
-- | Context to parse a RHS value in a boolean expression
data BoolExpRHSParser (b :: BackendType) m v = BoolExpRHSParser
{ -- | Parse a JSON value with enforcing a column type
_berpValueParser :: !(ValueParser b m v),
-- | Required for a computed field SQL function with session argument
_berpSessionValue :: !v
}
-- | A function which resolves boolean expression from given table fields
newtype BoolExpResolver b m v = BoolExpResolver
{ getBoolExpResolver ::
BoolExpRHSParser b m v ->
TableName b ->
FieldInfoMap (FieldInfo b) ->
GBoolExp b ColExp ->
m (AnnBoolExp b v)
}

View File

@ -6,10 +6,7 @@ module Hasura.RQL.Types.ComputedField
( ComputedFieldFunction (..),
ComputedFieldInfo (..),
ComputedFieldName (..),
ComputedFieldReturn (..),
CustomFunctionNames (..),
FunctionSessionArgument (..),
FunctionTableArgument (..),
FunctionTrackedAs (..),
cfiDescription,
cfiFunction,
@ -19,14 +16,11 @@ module Hasura.RQL.Types.ComputedField
computedFieldNameToText,
fromComputedField,
onlyScalarComputedFields,
_CFRScalar,
_CFRSetofTable,
)
where
import Control.Lens hiding ((.=))
import Data.Aeson
import Data.Aeson.Casing
import Data.Sequence qualified as Seq
import Data.Text.Extended
import Data.Text.NonEmpty (NonEmptyText (..))
@ -36,7 +30,6 @@ import Hasura.Incremental (Cacheable)
import Hasura.Prelude
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.Function
import Hasura.SQL.Backend
import Language.GraphQL.Draft.Syntax (Name)
@ -49,46 +42,6 @@ computedFieldNameToText = unNonEmptyText . unComputedFieldName
fromComputedField :: ComputedFieldName -> FieldName
fromComputedField = FieldName . computedFieldNameToText
-- | The function table argument is either the very first argument or the named
-- argument with an index. The index is 0 if the named argument is the first.
data FunctionTableArgument
= FTAFirst
| FTANamed
!FunctionArgName
-- ^ argument name
!Int
-- ^ argument index
deriving (Show, Eq, Generic)
instance Cacheable FunctionTableArgument
instance NFData FunctionTableArgument
instance Hashable FunctionTableArgument
instance ToJSON FunctionTableArgument where
toJSON FTAFirst = String "first_argument"
toJSON (FTANamed argName _) = object ["name" .= argName]
-- | The session argument, which passes Hasura session variables to a
-- SQL function as a JSON object.
data FunctionSessionArgument
= FunctionSessionArgument
!FunctionArgName
-- ^ The argument name
!Int
-- ^ The ordinal position in the function input parameters
deriving (Show, Eq, Generic)
instance Cacheable FunctionSessionArgument
instance NFData FunctionSessionArgument
instance Hashable FunctionSessionArgument
instance ToJSON FunctionSessionArgument where
toJSON (FunctionSessionArgument argName _) = toJSON argName
data FunctionTrackedAs (b :: BackendType)
= FTAComputedField ComputedFieldName SourceName (TableName b)
| FTACustomFunction CustomFunctionNames
@ -107,39 +60,17 @@ deriving instance Backend b => Show (FunctionTrackedAs b)
deriving instance Backend b => Eq (FunctionTrackedAs b)
data ComputedFieldReturn (b :: BackendType)
= CFRScalar !(ScalarType b)
| CFRSetofTable !(TableName b)
deriving (Generic)
deriving instance Backend b => Show (ComputedFieldReturn b)
deriving instance Backend b => Eq (ComputedFieldReturn b)
instance Backend b => Cacheable (ComputedFieldReturn b)
instance Backend b => NFData (ComputedFieldReturn b)
instance Backend b => Hashable (ComputedFieldReturn b)
instance Backend b => ToJSON (ComputedFieldReturn b) where
toJSON =
genericToJSON $
defaultOptions
{ constructorTagModifier = snakeCase . drop 3,
sumEncoding = TaggedObject "type" "info"
}
$(makePrisms ''ComputedFieldReturn)
data ComputedFieldFunction (b :: BackendType) = ComputedFieldFunction
{ _cffName :: !(FunctionName b),
_cffInputArgs :: !(Seq.Seq (FunctionArg b)),
_cffTableArgument :: !FunctionTableArgument,
_cffSessionArgument :: !(Maybe FunctionSessionArgument),
_cffInputArgs :: !(Seq.Seq (FunctionArgument b)),
_cffComputedFieldImplicitArgs :: !(ComputedFieldImplicitArguments b),
_cffDescription :: !(Maybe PGDescription)
}
deriving (Show, Eq, Generic)
deriving (Generic)
deriving instance (Backend b) => Show (ComputedFieldFunction b)
deriving instance (Backend b) => Eq (ComputedFieldFunction b)
instance (Backend b) => Cacheable (ComputedFieldFunction b)
@ -176,5 +107,5 @@ instance (Backend b) => ToJSON (ComputedFieldInfo b) where
$(makeLenses ''ComputedFieldInfo)
onlyScalarComputedFields :: [ComputedFieldInfo backend] -> [ComputedFieldInfo backend]
onlyScalarComputedFields = filter (has (cfiReturnType . _CFRScalar))
onlyScalarComputedFields :: forall backend. (Backend backend) => [ComputedFieldInfo backend] -> [ComputedFieldInfo backend]
onlyScalarComputedFields = filter (has _ReturnsScalar . computedFieldReturnType @backend . _cfiReturnType)

View File

@ -2,7 +2,6 @@
module Hasura.RQL.Types.Function
( DBFunctionsMetadata,
FunctionArg (..),
FunctionArgName (..),
FunctionCache,
FunctionConfig (..),
@ -14,8 +13,9 @@ module Hasura.RQL.Types.Function
FunctionPermissionsCtx (..),
FunctionPermissionsMap,
FunctionVolatility (..),
HasDefault (..),
InputArgument (..),
FunctionArgsExpG (..),
FunctionArgsExp,
emptyFunctionConfig,
emptyFunctionCustomRootFields,
fiComment,
@ -37,6 +37,7 @@ module Hasura.RQL.Types.Function
getFunctionArgsGQLName,
getFunctionGQLName,
getInputArgs,
emptyFunctionArgsExp,
_IASessionVariables,
_IAUserProvided,
)
@ -47,6 +48,7 @@ import Data.Aeson
import Data.Aeson.Casing
import Data.Aeson.TH
import Data.Char (toLower)
import Data.HashMap.Strict qualified as HM
import Data.List.Extended as LE
import Data.Sequence qualified as Seq
import Data.Text qualified as T
@ -59,6 +61,7 @@ import Hasura.RQL.Types.Common
import Hasura.SQL.Backend
import Hasura.Session
import Language.GraphQL.Draft.Syntax qualified as G
import Language.Haskell.TH.Syntax
-- | https://www.postgresql.org/docs/current/xfunc-volatility.html
data FunctionVolatility
@ -82,30 +85,7 @@ instance Show FunctionVolatility where
show = T.unpack . funcTypToTxt
newtype FunctionArgName = FunctionArgName {getFuncArgNameTxt :: Text}
deriving (Show, Eq, NFData, ToJSON, FromJSON, ToTxt, IsString, Generic, Cacheable, Hashable)
newtype HasDefault = HasDefault {unHasDefault :: Bool}
deriving (Show, Eq, ToJSON, Cacheable, NFData, Hashable)
data FunctionArg (b :: BackendType) = FunctionArg
{ faName :: !(Maybe FunctionArgName),
faType :: !(FunctionArgType b),
faHasDefault :: !HasDefault
}
deriving (Generic)
deriving instance Backend b => Show (FunctionArg b)
deriving instance Backend b => Eq (FunctionArg b)
instance Backend b => Cacheable (FunctionArg b)
instance Backend b => NFData (FunctionArg b)
instance Backend b => Hashable (FunctionArg b)
instance (Backend b) => ToJSON (FunctionArg b) where
toJSON = genericToJSON hasuraJSON
deriving (Show, Eq, Ord, NFData, ToJSON, ToJSONKey, FromJSON, FromJSONKey, ToTxt, IsString, Generic, Cacheable, Hashable, Lift, Data)
data InputArgument a
= IAUserProvided !a
@ -121,7 +101,7 @@ $( deriveToJSON
)
$(makePrisms ''InputArgument)
type FunctionInputArgument b = InputArgument (FunctionArg b)
type FunctionInputArgument b = InputArgument (FunctionArgument b)
-- | Indicates whether the user requested the corresponding function to be
-- tracked as a mutation or a query/subscription, in @track_function@.
@ -275,7 +255,7 @@ getFunctionAggregateGQLName
]
& fromMaybe (funcGivenName <> G.__aggregate)
getInputArgs :: FunctionInfo b -> Seq.Seq (FunctionArg b)
getInputArgs :: FunctionInfo b -> Seq.Seq (FunctionArgument b)
getInputArgs =
Seq.fromList . mapMaybe (^? _IAUserProvided) . toList . _fiInputArgs
@ -333,3 +313,20 @@ instance ToJSON FunctionPermissionsCtx where
toJSON = \case
FunctionPermissionsInferred -> Bool True
FunctionPermissionsManual -> Bool False
data FunctionArgsExpG a = FunctionArgsExp
{ _faePositional :: [a],
_faeNamed :: (HM.HashMap Text a)
}
deriving stock (Show, Eq, Functor, Foldable, Traversable, Generic)
instance (Hashable a) => Hashable (FunctionArgsExpG a)
instance (Cacheable a) => Cacheable (FunctionArgsExpG a)
instance (NFData a) => NFData (FunctionArgsExpG a)
type FunctionArgsExp b v = FunctionArgsExpG (FunctionArgumentExp b v)
emptyFunctionArgsExp :: FunctionArgsExpG a
emptyFunctionArgsExp = FunctionArgsExp [] HM.empty

View File

@ -10,6 +10,7 @@ import Hasura.Base.Error
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.BoolExp
import Hasura.RQL.Types.Column
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.ComputedField
@ -27,7 +28,9 @@ import Hasura.SQL.Types
class
( Backend b,
Eq (BooleanOperators b (PartialSQLExp b)),
Hashable (BooleanOperators b (PartialSQLExp b))
Eq (FunctionArgumentExp b (PartialSQLExp b)),
Hashable (BooleanOperators b (PartialSQLExp b)),
Hashable (FunctionArgumentExp b (PartialSQLExp b))
) =>
BackendMetadata (b :: BackendType)
where
@ -35,6 +38,7 @@ class
(MonadError QErr m) =>
HashSet (TableName b) ->
TableName b ->
HashSet (Column b) ->
ComputedFieldName ->
ComputedFieldDefinition b ->
RawFunctionInfo b ->
@ -123,6 +127,19 @@ class
m ()
validateRelationship _ _ _ = pure ()
-- | Function that that builds a boolean expression field out of a computed field
buildComputedFieldBooleanExp ::
( MonadError QErr m,
TableCoreInfoRM b m
) =>
BoolExpResolver b m v ->
BoolExpRHSParser b m v ->
TableName b ->
FieldInfoMap (FieldInfo b) ->
ComputedFieldInfo b ->
Value ->
m (AnnComputedFieldBoolExp b v)
-- | Run all operations required to create, update, or migrate the internal
-- catalog used by the backend for internal bookkeeping, if any. The return
-- type indicates whether the performed operations subsequently require

View File

@ -266,8 +266,7 @@ data ScalarComputedField (b :: BackendType) = ScalarComputedField
{ _scfXField :: !(XComputedField b),
_scfName :: !ComputedFieldName,
_scfFunction :: !(FunctionName b),
_scfTableArgument :: !FunctionTableArgument,
_scfSessionArgument :: !(Maybe FunctionSessionArgument),
_scfComputedFieldImplicitArgs :: !(ComputedFieldImplicitArguments b),
_scfType :: !(ScalarType b)
}
deriving (Generic)
@ -285,8 +284,7 @@ instance Backend b => ToJSON (ScalarComputedField b) where
object
[ "name" .= _scfName,
"function" .= _scfFunction,
"table_argument" .= _scfTableArgument,
"session_argument" .= _scfSessionArgument,
"function_implicit_arguments" .= _scfComputedFieldImplicitArgs,
"type" .= _scfType
]

View File

@ -58,7 +58,9 @@ data CombineRolePermInfo (b :: BackendType) = CombineRolePermInfo
instance
( Backend b,
Eq (BooleanOperators b (PartialSQLExp b)),
Hashable (BooleanOperators b (PartialSQLExp b))
Eq (FunctionArgumentExp b (PartialSQLExp b)),
Hashable (BooleanOperators b (PartialSQLExp b)),
Hashable (FunctionArgumentExp b (PartialSQLExp b))
) =>
Semigroup (CombineRolePermInfo b)
where
@ -73,7 +75,9 @@ instance
instance
( Backend b,
Eq (BooleanOperators b (PartialSQLExp b)),
Hashable (BooleanOperators b (PartialSQLExp b))
Eq (FunctionArgumentExp b (PartialSQLExp b)),
Hashable (BooleanOperators b (PartialSQLExp b)),
Hashable (FunctionArgumentExp b (PartialSQLExp b))
) =>
Monoid (CombineRolePermInfo b)
where
@ -129,10 +133,10 @@ instance (Backend b, Eq a, Hashable a) => OnlyRelevantEq (GBoolExp b a) where
BoolFld boolExpL `relevantEq` BoolFld boolExpR = boolExpL == boolExpR
_ `relevantEq` _ = False
instance (Backend b, Eq a, Eq (BooleanOperators b a)) => OnlyRelevantEq (AnnComputedFieldBoolExp b a) where
instance (Backend b, Eq a, Eq (BooleanOperators b a), Eq (FunctionArgumentExp b a)) => OnlyRelevantEq (AnnComputedFieldBoolExp b a) where
relevantEq = (==)
instance (Backend b, Hashable a, Eq a, Hashable (BooleanOperators b a), Eq (BooleanOperators b a)) => OnlyRelevantEq (AnnBoolExpFld b a) where
instance (Backend b, Hashable a, Eq a, Hashable (BooleanOperators b a), Eq (BooleanOperators b a), Eq (FunctionArgumentExp b a), Hashable (FunctionArgumentExp b a)) => OnlyRelevantEq (AnnBoolExpFld b a) where
annBoolExpFldL `relevantEq` annBoolExpFldR =
case (annBoolExpFldL, annBoolExpFldR) of
(AVColumn colInfoL opExpsL, AVColumn colInfoR opExpsR) ->
@ -146,7 +150,9 @@ instance (Backend b, Hashable a, Eq a, Hashable (BooleanOperators b a), Eq (Bool
instance
( Backend b,
Eq (BooleanOperators b (PartialSQLExp b)),
Hashable (BooleanOperators b (PartialSQLExp b))
Hashable (BooleanOperators b (PartialSQLExp b)),
Hashable (FunctionArgumentExp b (PartialSQLExp b)),
Eq (FunctionArgumentExp b (PartialSQLExp b))
) =>
OnlyRelevantEq (InsPermInfo b)
where
@ -161,7 +167,9 @@ instance
instance
( Backend b,
Eq (BooleanOperators b (PartialSQLExp b)),
Hashable (BooleanOperators b (PartialSQLExp b))
Eq (FunctionArgumentExp b (PartialSQLExp b)),
Hashable (BooleanOperators b (PartialSQLExp b)),
Hashable (FunctionArgumentExp b (PartialSQLExp b))
) =>
OnlyRelevantEq (UpdPermInfo b)
where
@ -177,7 +185,9 @@ instance
instance
( Backend b,
Eq (BooleanOperators b (PartialSQLExp b)),
Hashable (BooleanOperators b (PartialSQLExp b))
Eq (FunctionArgumentExp b (PartialSQLExp b)),
Hashable (BooleanOperators b (PartialSQLExp b)),
Hashable (FunctionArgumentExp b (PartialSQLExp b))
) =>
OnlyRelevantEq (DelPermInfo b)
where

View File

@ -27,6 +27,7 @@ module Hasura.RQL.Types.SchemaCache
askTableFieldInfoMap,
askTableMetadata,
askFunctionInfo,
askFieldInfoMapSource,
TableCoreCache,
TableCache,
ActionCache,
@ -108,7 +109,6 @@ module Hasura.RQL.Types.SchemaCache
getDependentObjs,
getDependentObjsWith,
FunctionVolatility (..),
FunctionArg (..),
FunctionArgName (..),
FunctionInfo (..),
FunctionCache,
@ -783,3 +783,14 @@ getColExpDeps bexp = do
IsRoot -> rootTable
IsCurrent -> currTable
pure $ mkColDep @b DROnType source table col
-- | Asking for a table's fields info without explicit @'SourceName' argument.
-- The source name is implicitly inferred from @'SourceM' via @'TableCoreInfoRM'.
askFieldInfoMapSource ::
(QErrM m, Backend b, TableCoreInfoRM b m) =>
TableName b ->
m (FieldInfoMap (FieldInfo b))
askFieldInfoMapSource tableName = do
fmap _tciFieldInfoMap $
onNothingM (lookupTableCoreInfo tableName) $
throw400 NotExists $ "table " <> tableName <<> " does not exist"

View File

@ -314,26 +314,30 @@ data InsPermInfo (b :: BackendType) = InsPermInfo
deriving instance
( Backend b,
Eq (BooleanOperators b (PartialSQLExp b))
Eq (BooleanOperators b (PartialSQLExp b)),
Eq (FunctionArgumentExp b (PartialSQLExp b))
) =>
Eq (InsPermInfo b)
deriving instance
( Backend b,
Show (BooleanOperators b (PartialSQLExp b))
Show (BooleanOperators b (PartialSQLExp b)),
Show (FunctionArgumentExp b (PartialSQLExp b))
) =>
Show (InsPermInfo b)
instance
( Backend b,
NFData (BooleanOperators b (PartialSQLExp b))
NFData (BooleanOperators b (PartialSQLExp b)),
NFData (FunctionArgumentExp b (PartialSQLExp b))
) =>
NFData (InsPermInfo b)
instance
( Backend b,
Hashable (BooleanOperators b (PartialSQLExp b)),
Cacheable (BooleanOperators b (PartialSQLExp b))
Cacheable (BooleanOperators b (PartialSQLExp b)),
Cacheable (FunctionArgumentExp b (PartialSQLExp b))
) =>
Cacheable (InsPermInfo b)
@ -427,26 +431,30 @@ data SelPermInfo (b :: BackendType) = SelPermInfo
deriving instance
( Backend b,
Eq (BooleanOperators b (PartialSQLExp b))
Eq (BooleanOperators b (PartialSQLExp b)),
Eq (FunctionArgumentExp b (PartialSQLExp b))
) =>
Eq (SelPermInfo b)
deriving instance
( Backend b,
Show (BooleanOperators b (PartialSQLExp b))
Show (BooleanOperators b (PartialSQLExp b)),
Show (FunctionArgumentExp b (PartialSQLExp b))
) =>
Show (SelPermInfo b)
instance
( Backend b,
NFData (BooleanOperators b (PartialSQLExp b))
NFData (BooleanOperators b (PartialSQLExp b)),
NFData (FunctionArgumentExp b (PartialSQLExp b))
) =>
NFData (SelPermInfo b)
instance
( Backend b,
Hashable (BooleanOperators b (PartialSQLExp b)),
Cacheable (BooleanOperators b (PartialSQLExp b))
Cacheable (BooleanOperators b (PartialSQLExp b)),
Cacheable (FunctionArgumentExp b (PartialSQLExp b))
) =>
Cacheable (SelPermInfo b)
@ -470,26 +478,30 @@ data UpdPermInfo (b :: BackendType) = UpdPermInfo
deriving instance
( Backend b,
Eq (BooleanOperators b (PartialSQLExp b))
Eq (BooleanOperators b (PartialSQLExp b)),
Eq (FunctionArgumentExp b (PartialSQLExp b))
) =>
Eq (UpdPermInfo b)
deriving instance
( Backend b,
Show (BooleanOperators b (PartialSQLExp b))
Show (BooleanOperators b (PartialSQLExp b)),
Show (FunctionArgumentExp b (PartialSQLExp b))
) =>
Show (UpdPermInfo b)
instance
( Backend b,
NFData (BooleanOperators b (PartialSQLExp b))
NFData (BooleanOperators b (PartialSQLExp b)),
NFData (FunctionArgumentExp b (PartialSQLExp b))
) =>
NFData (UpdPermInfo b)
instance
( Backend b,
Hashable (BooleanOperators b (PartialSQLExp b)),
Cacheable (BooleanOperators b (PartialSQLExp b))
Cacheable (BooleanOperators b (PartialSQLExp b)),
Cacheable (FunctionArgumentExp b (PartialSQLExp b))
) =>
Cacheable (UpdPermInfo b)
@ -510,26 +522,30 @@ data DelPermInfo (b :: BackendType) = DelPermInfo
deriving instance
( Backend b,
Eq (BooleanOperators b (PartialSQLExp b))
Eq (BooleanOperators b (PartialSQLExp b)),
Eq (FunctionArgumentExp b (PartialSQLExp b))
) =>
Eq (DelPermInfo b)
deriving instance
( Backend b,
Show (BooleanOperators b (PartialSQLExp b))
Show (BooleanOperators b (PartialSQLExp b)),
Show (FunctionArgumentExp b (PartialSQLExp b))
) =>
Show (DelPermInfo b)
instance
( Backend b,
NFData (BooleanOperators b (PartialSQLExp b))
NFData (BooleanOperators b (PartialSQLExp b)),
NFData (FunctionArgumentExp b (PartialSQLExp b))
) =>
NFData (DelPermInfo b)
instance
( Backend b,
Hashable (BooleanOperators b (PartialSQLExp b)),
Cacheable (BooleanOperators b (PartialSQLExp b))
Cacheable (BooleanOperators b (PartialSQLExp b)),
Cacheable (FunctionArgumentExp b (PartialSQLExp b))
) =>
Cacheable (DelPermInfo b)
@ -549,7 +565,7 @@ data RolePermInfo (b :: BackendType) = RolePermInfo
}
deriving (Generic)
instance (Backend b, NFData (BooleanOperators b (PartialSQLExp b))) => NFData (RolePermInfo b)
instance (Backend b, NFData (BooleanOperators b (PartialSQLExp b)), NFData (FunctionArgumentExp b (PartialSQLExp b))) => NFData (RolePermInfo b)
instance (Backend b, ToJSONKeyValue (BooleanOperators b (PartialSQLExp b))) => ToJSON (RolePermInfo b) where
toJSON = genericToJSON hasuraJSON

View File

@ -21,7 +21,7 @@ genAnnSelectG :: forall m f a. MonadGen m => m a -> m (f a) -> m (AnnSelectG 'Da
genAnnSelectG genA genFA =
AnnSelectG
<$> genFields genFA defaultRange defaultRange
<*> genSelectFromG genA
<*> genSelectFromG
<*> genTablePermG genA
<*> genArgs
<*> genStringifyNumbers

View File

@ -7,9 +7,11 @@ module Hasura.Backends.DataConnector.RQLGenerator.GenCommon
genTableName,
genScalarType,
genFunctionName,
genFunctionArgumentExp,
)
where
import Data.Functor.Const
import Hasura.Backends.DataConnector.IR.Name qualified as Name
import Hasura.Backends.DataConnector.IR.Scalar.Type qualified as ScalarType
import Hasura.Generator.Common (defaultRange, genArbitraryUnicodeText, genHashMap)
@ -94,6 +96,9 @@ genScalarType =
genFunctionName :: MonadGen m => m (FunctionName 'DataConnector)
genFunctionName = coerce <$> genArbitraryUnicodeText defaultRange
genFunctionArgumentExp :: MonadGen m => m (FunctionArgumentExp 'DataConnector a)
genFunctionArgumentExp = pure (Const ())
--------------------------------------------------------------------------------
-- Unexported

View File

@ -5,6 +5,7 @@ where
import Hasura.Backends.DataConnector.RQLGenerator.GenCommon
( genColumn,
genFunctionArgumentExp,
genFunctionName,
genScalarType,
genTableName,
@ -12,8 +13,7 @@ import Hasura.Backends.DataConnector.RQLGenerator.GenCommon
import Hasura.Generator.Common (defaultRange)
import Hasura.Prelude hiding (choice, maybe)
import Hasura.RQL.IR.Generator
( genArgumentExp,
genFunctionArgsExpG,
( genFunctionArgsExpG,
genIdentifier,
)
import Hasura.RQL.IR.Select (SelectFromG (..))
@ -23,13 +23,13 @@ import Hedgehog.Gen (choice, list, maybe)
--------------------------------------------------------------------------------
genSelectFromG :: MonadGen m => m a -> m (SelectFromG 'DataConnector a)
genSelectFromG genA = choice [fromTable, fromIdentifier, fromFunction]
genSelectFromG :: MonadGen m => m (SelectFromG 'DataConnector a)
genSelectFromG = choice [fromTable, fromIdentifier, fromFunction]
where
fromTable = FromTable <$> genTableName
fromIdentifier = FromIdentifier <$> genIdentifier
fromFunction = do
funcName <- genFunctionName
funcArgsExp <- genFunctionArgsExpG $ genArgumentExp genA
funcArgsExp <- genFunctionArgsExpG genFunctionArgumentExp
defList <- maybe . list defaultRange $ liftA2 (,) genColumn genScalarType
pure $ FromFunction funcName funcArgsExp defList

View File

@ -6,6 +6,7 @@ module Hasura.Backends.Postgres.RQLGenerator.GenAssociatedTypes
genScalarType,
genTableName,
genXComputedField,
genFunctionArgumentExp,
)
where
@ -15,9 +16,11 @@ import Data.Functor ((<$>))
import Data.Int (Int)
import Data.Text (Text)
import Data.Text qualified as T
import Hasura.Backends.Postgres.Instances.Types ()
import Hasura.Backends.Postgres.SQL.Types qualified as PG
import Hasura.Backends.Postgres.SQL.Types qualified as PGTypes
import Hasura.Backends.Postgres.Types.BoolExp qualified as B
import Hasura.Backends.Postgres.Types.Function qualified as PGTypes
import Hasura.Generator.Common (defaultRange, genArbitraryUnicodeText)
import Hasura.RQL.IR.BoolExp
import Hasura.RQL.Types.Backend
@ -118,6 +121,15 @@ genBooleanOperators genA =
B.AMatchesFulltext <$> genA
]
genFunctionArgumentExp :: MonadGen m => m a -> m (FunctionArgumentExp ('Postgres 'Vanilla) a)
genFunctionArgumentExp genA =
Gen.choice
[ pure PGTypes.AETableRow,
pure PGTypes.AEActionResponsePayload,
PGTypes.AESession <$> genA,
PGTypes.AEInput <$> genA
]
--------------------------------------------------------------------------------
-- Unexported Helpers

View File

@ -7,6 +7,7 @@ import Data.Int (Int64)
import Hasura.Backends.Postgres.RQLGenerator.GenAssociatedTypes
( genBooleanOperators,
genColumn,
genFunctionArgumentExp,
genFunctionName,
genScalarType,
genTableName,
@ -51,6 +52,7 @@ genSelectArgsG genA = do
genFunctionName
genXComputedField
(genBooleanOperators genA)
(genFunctionArgumentExp genA)
genA
)
genTableName
@ -68,6 +70,7 @@ genSelectArgsG genA = do
genFunctionName
genXComputedField
(genBooleanOperators genA)
(genFunctionArgumentExp genA)
genA
)

View File

@ -6,7 +6,7 @@ where
import Hasura.Backends.Postgres.RQLGenerator.GenAssociatedTypes
import Hasura.Generator.Common (defaultRange)
import Hasura.Prelude hiding (choice, maybe)
import Hasura.RQL.IR.Generator (genArgumentExp, genFunctionArgsExpG, genIdentifier)
import Hasura.RQL.IR.Generator (genFunctionArgsExpG, genIdentifier)
import Hasura.RQL.IR.Select (SelectFromG (..))
import Hasura.SQL.Backend (BackendType (..), PostgresKind (..))
import Hedgehog (MonadGen)
@ -24,6 +24,6 @@ genSelectFromG genA = Gen.choice [fromTable, fromIdentifier, fromFunction]
fromIdentifier = FromIdentifier <$> genIdentifier
fromFunction = do
funcName <- genFunctionName
funcArgsExp <- genFunctionArgsExpG $ genArgumentExp genA
funcArgsExp <- genFunctionArgsExpG $ genFunctionArgumentExp genA
defList <- Gen.maybe . Gen.list defaultRange $ liftA2 (,) genColumn genScalarType
pure $ FromFunction funcName funcArgsExp defList

View File

@ -6,6 +6,7 @@ where
import Hasura.Backends.Postgres.RQLGenerator.GenAssociatedTypes
( genBooleanOperators,
genColumn,
genFunctionArgumentExp,
genFunctionName,
genScalarType,
genTableName,
@ -23,7 +24,7 @@ import Hedgehog.Gen qualified as Gen
genTablePermG :: MonadGen m => m a -> m (TablePermG ('Postgres 'Vanilla) a)
genTablePermG genA = do
let genV = genAnnBoolExpFld @_ @('Postgres 'Vanilla) genColumn genTableName genScalarType genFunctionName genXComputedField (genBooleanOperators genA) genA
let genV = genAnnBoolExpFld @_ @('Postgres 'Vanilla) genColumn genTableName genScalarType genFunctionName genXComputedField (genBooleanOperators genA) (genFunctionArgumentExp genA) genA
gBoolExp <- genAnnBoolExp @_ @_ @('Postgres 'Vanilla) genV genTableName
limit <- Gen.maybe (Gen.integral defaultRange)
pure $ TablePerm gBoolExp limit

View File

@ -10,7 +10,6 @@ module Hasura.RQL.IR.Generator
genAnnotatedOrderByItemG,
genAnnotatedOrderByElement,
genAnnotatedAggregateOrderBy,
genArgumentExp,
genColumnInfo,
genFields,
genFunctionArgsExpG,
@ -30,6 +29,7 @@ import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.Column
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.ComputedField
import Hasura.RQL.Types.Function
import Hasura.RQL.Types.Relationships.Local
import Hedgehog
import Hedgehog.Gen
@ -50,17 +50,6 @@ genFunctionArgsExpG genA =
<$> list defaultRange genA
<*> genHashMap (genArbitraryUnicodeText defaultRange) genA defaultRange
genArgumentExp :: MonadGen m => m a -> m (ArgumentExp a)
genArgumentExp genA = choice [tableRow, session, input]
where
-- Don't actually generate this except manually, as it presumes
-- that the root table has a specific column.
--
-- responsePayload = pure AEActionResponsePayload
tableRow = pure AETableRow
session = AESession <$> genA
input = AEInput <$> genA
genGExists ::
MonadGen m =>
m a ->
@ -100,6 +89,7 @@ genAnnBoolExpFld ::
m (FunctionName b) ->
m (XComputedField b) ->
m (BooleanOperators b a) ->
m (FunctionArgumentExp b a) ->
m a ->
m (AnnBoolExpFld b a)
genAnnBoolExpFld
@ -109,6 +99,7 @@ genAnnBoolExpFld
genFunctionName
genXComputedField
genBooleanOperators
genFunctionArgumentExp
genA =
choice [column, relationship, computedField]
where
@ -138,6 +129,7 @@ genAnnBoolExpFld
genFunctionName
genXComputedField
genBooleanOperators
genFunctionArgumentExp
genA
)
genTableName
@ -150,6 +142,7 @@ genAnnBoolExpFld
genBooleanOperators
genXComputedField
genFunctionName
genFunctionArgumentExp
genA
genRelInfo ::
@ -189,6 +182,7 @@ genAnnComputedFieldBolExp ::
m (BooleanOperators b a) ->
m (XComputedField b) ->
m (FunctionName b) ->
m (FunctionArgumentExp b a) ->
m a ->
m (AnnComputedFieldBoolExp b a)
genAnnComputedFieldBolExp
@ -198,12 +192,13 @@ genAnnComputedFieldBolExp
genBooleanOperators
genXComputedField
genFunctionName
genFunctionArgumentExp
genA =
AnnComputedFieldBoolExp
<$> genXComputedField
<*> genComputedFieldName
<*> genFunctionName
<*> genSessionArgumentPresence genA
<*> genFunctionArgsExpG genFunctionArgumentExp
<*> genComputedFieldBoolExp
genTableName
genColumn
@ -211,6 +206,7 @@ genAnnComputedFieldBolExp
genFunctionName
genXComputedField
genBooleanOperators
genFunctionArgumentExp
genA
genComputedFieldBoolExp ::
@ -225,6 +221,7 @@ genComputedFieldBoolExp ::
m (FunctionName b) ->
m (XComputedField b) ->
m (BooleanOperators b a) ->
m (FunctionArgumentExp b a) ->
m a ->
m (ComputedFieldBoolExp b a)
genComputedFieldBoolExp
@ -234,6 +231,7 @@ genComputedFieldBoolExp
genFunctionName
genXComputedField
genBooleanOperators
genFunctionArgumentExp
genA =
choice
[ CFBEScalar
@ -256,6 +254,7 @@ genComputedFieldBoolExp
genFunctionName
genXComputedField
genBooleanOperators
genFunctionArgumentExp
genA
)
genTableName
@ -264,14 +263,6 @@ genComputedFieldBoolExp
genComputedFieldName :: MonadGen m => m ComputedFieldName
genComputedFieldName = ComputedFieldName <$> genNonEmptyText defaultRange
genSessionArgumentPresence :: MonadGen m => m a -> m (SessionArgumentPresence a)
genSessionArgumentPresence genA =
choice
[ pure SAPNotPresent,
SAPFirst <$> genA,
SAPSecond <$> genA
]
genOpExpG ::
MonadGen m =>
Eq (ScalarType b) =>
@ -422,6 +413,7 @@ genAnnotatedOrderByElement ::
m (FunctionName b) ->
m (XComputedField b) ->
m (BooleanOperators b a) ->
m (FunctionArgumentExp b a) ->
m a ->
m (AnnotatedOrderByElement b a)
genAnnotatedOrderByElement
@ -431,6 +423,7 @@ genAnnotatedOrderByElement
genFunctionName
genXComputedField
genBooleanOperators
genFunctionArgumentExp
genA =
choice
[ column,
@ -456,6 +449,7 @@ genAnnotatedOrderByElement
genFunctionName
genXComputedField
genBooleanOperators
genFunctionArgumentExp
genA
)
genTableName
@ -466,6 +460,7 @@ genAnnotatedOrderByElement
genFunctionName
genXComputedField
genBooleanOperators
genFunctionArgumentExp
genA
arrayAggregation =
AOCArrayAggregation
@ -478,6 +473,7 @@ genAnnotatedOrderByElement
genFunctionName
genXComputedField
genBooleanOperators
genFunctionArgumentExp
genA
)
genTableName
@ -494,6 +490,7 @@ genAnnotatedOrderByElement
genFunctionName
genXComputedField
genBooleanOperators
genFunctionArgumentExp
genA
genAnnotatedAggregateOrderBy ::
@ -528,6 +525,7 @@ genComputedFieldOrderBy ::
m (FunctionName b) ->
m (XComputedField b) ->
m (BooleanOperators b a) ->
m (FunctionArgumentExp b a) ->
m a ->
m (ComputedFieldOrderBy b a)
genComputedFieldOrderBy
@ -537,13 +535,13 @@ genComputedFieldOrderBy
genFunctionName
genXComputedField
genBooleanOperators
genFunctionArgumentExp
genA =
ComputedFieldOrderBy
<$> genXComputedField
<*> genComputedFieldName
<*> genFunctionName
<*> genFunctionArgsExpG
(genArgumentExp genA)
<*> genFunctionArgsExpG genFunctionArgumentExp
<*> genComputedFieldOrderByElement
genColumn
genScalarType
@ -551,6 +549,7 @@ genComputedFieldOrderBy
genFunctionName
genXComputedField
genBooleanOperators
genFunctionArgumentExp
genA
genComputedFieldOrderByElement ::
@ -565,6 +564,7 @@ genComputedFieldOrderByElement ::
m (FunctionName b) ->
m (XComputedField b) ->
m (BooleanOperators b a) ->
m (FunctionArgumentExp b a) ->
m a ->
m (ComputedFieldOrderByElement b a)
genComputedFieldOrderByElement
@ -574,6 +574,7 @@ genComputedFieldOrderByElement
genFunctionName
genXComputedField
genBooleanOperators
genFunctionArgumentExp
genA =
choice
[ CFOBEScalar <$> genScalarType,
@ -587,6 +588,7 @@ genComputedFieldOrderByElement
genFunctionName
genXComputedField
genBooleanOperators
genFunctionArgumentExp
genA
)
genTableName