mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-10-05 06:18:04 +03:00
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:
parent
8a05ff207b
commit
acde210fdc
@ -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
|
||||
|
@ -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 ->
|
||||
|
158
server/src-lib/Hasura/Backends/BigQuery/DDL/ComputedField.hs
Normal file
158
server/src-lib/Hasura/Backends/BigQuery/DDL/ComputedField.hs
Normal 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)
|
@ -4,6 +4,7 @@ module Hasura.Backends.BigQuery.DDL.Source
|
||||
( resolveSource,
|
||||
postDropSourceHook,
|
||||
resolveSourceConfig,
|
||||
restTypeToScalarType,
|
||||
)
|
||||
where
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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"
|
||||
|
@ -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?
|
||||
|
@ -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.
|
||||
[]
|
||||
|
@ -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")]
|
||||
|
@ -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
|
||||
--
|
||||
|
@ -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
|
||||
|
@ -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 =>
|
||||
|
@ -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 ::
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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."
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 =
|
||||
|
@ -130,3 +130,4 @@ instance
|
||||
parseCollectableType = PG.parseCollectableType
|
||||
postDropSourceHook = PG.postDropSourceHook
|
||||
validateRelationship = validateRel @pgKind
|
||||
buildComputedFieldBooleanExp = PG.buildComputedFieldBooleanExp
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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) =
|
||||
|
127
server/src-lib/Hasura/Backends/Postgres/Types/ComputedField.hs
Normal file
127
server/src-lib/Hasura/Backends/Postgres/Types/ComputedField.hs
Normal 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)
|
@ -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}
|
72
server/src-lib/Hasura/Backends/Postgres/Types/Function.hs
Normal file
72
server/src-lib/Hasura/Backends/Postgres/Types/Function.hs
Normal 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 #-}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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!
|
||||
|
@ -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
|
||||
|
@ -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 ::
|
||||
|
@ -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 :
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
29
server/src-lib/Hasura/RQL/Types/BoolExp.hs
Normal file
29
server/src-lib/Hasura/RQL/Types/BoolExp.hs
Normal 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)
|
||||
}
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
]
|
||||
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user