diff --git a/server/graphql-engine.cabal b/server/graphql-engine.cabal index 354b75bf011..29d8c175ce7 100644 --- a/server/graphql-engine.cabal +++ b/server/graphql-engine.cabal @@ -602,6 +602,7 @@ library , Hasura.Backends.Postgres.Instances.API , Hasura.Backends.Postgres.Instances.Execute , Hasura.Backends.Postgres.Instances.Metadata + , Hasura.Backends.Postgres.Instances.NativeQueries , Hasura.Backends.Postgres.Instances.PingSource , Hasura.Backends.Postgres.Instances.Schema , Hasura.Backends.Postgres.Instances.SchemaCache @@ -807,6 +808,7 @@ library , Hasura.RQL.Types.SchemaCache.Instances , Hasura.RQL.Types.SchemaCacheTypes , Hasura.RQL.Types.Source + , Hasura.RQL.Types.SourceConfiguration , Hasura.RQL.Types.SourceCustomization , Hasura.RQL.Types.Subscription , Hasura.RQL.Types.Table diff --git a/server/lib/api-tests/src/Test/API/Metadata/NativeQuerySpec.hs b/server/lib/api-tests/src/Test/API/Metadata/NativeQuerySpec.hs index 79fb8a71a31..d2738915ffe 100644 --- a/server/lib/api-tests/src/Test/API/Metadata/NativeQuerySpec.hs +++ b/server/lib/api-tests/src/Test/API/Metadata/NativeQuerySpec.hs @@ -47,6 +47,12 @@ schema = { tableColumns = [ Schema.column "divided" Schema.TInt ] + }, + (table "stuff") + { tableColumns = + [ Schema.column "thing" Schema.TInt, + Schema.column "date" Schema.TUTCTime + ] } ] @@ -314,3 +320,86 @@ tests opts = do [yaml| [] |] + + describe "Validation fails on track a native query when query" do + it "has a syntax error" $ + \testEnv -> do + let schemaName = Schema.getSchemaName testEnv + let spicyQuery :: Text + spicyQuery = "query bad" + shouldReturnYaml + opts + ( GraphqlEngine.postMetadataWithStatus + 400 + testEnv + [yaml| + type: pg_track_native_query + args: + type: query + source: postgres + root_field_name: divided_stuff + code: *spicyQuery + arguments: + denominator: int + target_date: date + returns: + name: already_tracked_return_type + schema: *schemaName + |] + ) + [yaml| + code: validation-failed + error: Failed to validate query + internal: + arguments: [] + error: + description: null + exec_status: "FatalError" + hint: null + message: "syntax error at or near \"query\"" + status_code: "42601" + prepared: false + statement: "PREPARE _naqi_vali_divided_stuff AS query bad" + path: "$.args" + |] + + it "refers to non existing table" $ + \testEnv -> do + let schemaName = Schema.getSchemaName testEnv + let spicyQuery :: Text + spicyQuery = "SELECT thing / {{denominator}} AS divided FROM does_not_exist WHERE date = {{target_date}}" + shouldReturnYaml + opts + ( GraphqlEngine.postMetadataWithStatus + 400 + testEnv + [yaml| + type: pg_track_native_query + args: + type: query + source: postgres + root_field_name: divided_stuff + code: *spicyQuery + arguments: + denominator: int + target_date: date + returns: + name: already_tracked_return_type + schema: *schemaName + |] + ) + [yaml| + code: validation-failed + error: Failed to validate query + internal: + arguments: [] + error: + description: null + exec_status: "FatalError" + hint: null + message: "relation \"does_not_exist\" does not exist" + status_code: "42P01" + prepared: false + statement: "PREPARE _naqi_vali_divided_stuff AS SELECT thing / $1 AS divided FROM does_not_exist WHERE date = $2" + path: "$.args" + |] diff --git a/server/lib/api-tests/src/Test/Queries/NativeAccess/NativeAccessQueriesSpec.hs b/server/lib/api-tests/src/Test/Queries/NativeAccess/NativeAccessQueriesSpec.hs index d9dde5df8d9..a1815e19ace 100644 --- a/server/lib/api-tests/src/Test/Queries/NativeAccess/NativeAccessQueriesSpec.hs +++ b/server/lib/api-tests/src/Test/Queries/NativeAccess/NativeAccessQueriesSpec.hs @@ -183,6 +183,59 @@ tests opts = do actual `shouldBe` expected + it "Runs a simple query that takes no parameters but ends with a comment" $ \testEnvironment -> do + let spicyQuery :: Text + spicyQuery = "SELECT * FROM (VALUES ('hello', 'world'), ('welcome', 'friend')) as t(\"one\", \"two\") -- my query" + + let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment + source = BackendType.backendSourceName backendTypeMetadata + schemaName = Schema.getSchemaName testEnvironment + + shouldReturnYaml + opts + ( GraphqlEngine.postMetadata + testEnvironment + [yaml| + type: pg_track_native_query + args: + type: query + source: *source + root_field_name: hello_comment_function + code: *spicyQuery + returns: + name: hello_world_table + schema: *schemaName + |] + ) + [yaml| + message: success + |] + + let expected = + [yaml| + data: + hello_comment_function: + - one: "hello" + two: "world" + - one: "welcome" + two: "friend" + |] + + actual :: IO Value + actual = + GraphqlEngine.postGraphql + testEnvironment + [graphql| + query { + hello_comment_function { + one + two + } + } + |] + + actual `shouldBe` expected + it "Runs a simple query that takes one parameter and uses it multiple times" $ \testEnvironment -> do let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment source = BackendType.backendSourceName backendTypeMetadata @@ -387,7 +440,7 @@ tests opts = do expected = [yaml| data: - first: + first: - excerpt: "I like to eat dog food I am a dogs..." second: - excerpt: "I like to eat..." diff --git a/server/src-lib/Hasura/Backends/BigQuery/Instances/Types.hs b/server/src-lib/Hasura/Backends/BigQuery/Instances/Types.hs index 2fc8e64bda1..fc0c148efb8 100644 --- a/server/src-lib/Hasura/Backends/BigQuery/Instances/Types.hs +++ b/server/src-lib/Hasura/Backends/BigQuery/Instances/Types.hs @@ -20,8 +20,6 @@ import Language.GraphQL.Draft.Syntax qualified as G instance Backend 'BigQuery where type BackendConfig 'BigQuery = () type BackendInfo 'BigQuery = () - type SourceConfig 'BigQuery = BigQuery.BigQuerySourceConfig - type SourceConnConfiguration 'BigQuery = BigQuery.BigQueryConnSourceConfig type TableName 'BigQuery = BigQuery.TableName type FunctionName 'BigQuery = BigQuery.FunctionName type RawFunctionInfo 'BigQuery = BigQuery.RestRoutine @@ -117,4 +115,8 @@ instance Backend 'BigQuery where defaultTriggerOnReplication = Nothing +instance HasSourceConfiguration 'BigQuery where + type SourceConfig 'BigQuery = BigQuery.BigQuerySourceConfig + type SourceConnConfiguration 'BigQuery = BigQuery.BigQueryConnSourceConfig + instance NativeQueryMetadata 'BigQuery diff --git a/server/src-lib/Hasura/Backends/DataConnector/Adapter/Backend.hs b/server/src-lib/Hasura/Backends/DataConnector/Adapter/Backend.hs index ca26dd63514..49e74c89857 100644 --- a/server/src-lib/Hasura/Backends/DataConnector/Adapter/Backend.hs +++ b/server/src-lib/Hasura/Backends/DataConnector/Adapter/Backend.hs @@ -24,7 +24,7 @@ import Hasura.Base.Error (Code (ValidationFailed), QErr, runAesonParser, throw40 import Hasura.NativeQuery.Types (NativeQueryMetadata) import Hasura.Prelude import Hasura.RQL.IR.BoolExp -import Hasura.RQL.Types.Backend (Backend (..), ComputedFieldReturnType, SupportedNamingCase (..), XDisable, XEnable) +import Hasura.RQL.Types.Backend (Backend (..), ComputedFieldReturnType, HasSourceConfiguration (..), SupportedNamingCase (..), XDisable, XEnable) import Hasura.RQL.Types.Column (ColumnType (..)) import Hasura.RQL.Types.ResizePool (ServerReplicas) import Hasura.SQL.Backend (BackendType (DataConnector)) @@ -43,8 +43,6 @@ type Unimplemented = () instance Backend 'DataConnector where type BackendConfig 'DataConnector = InsOrdHashMap DC.DataConnectorName DC.DataConnectorOptions type BackendInfo 'DataConnector = HashMap DC.DataConnectorName DC.DataConnectorInfo - type SourceConfig 'DataConnector = DC.SourceConfig - type SourceConnConfiguration 'DataConnector = DC.ConnSourceConfig type TableName 'DataConnector = DC.TableName type FunctionName 'DataConnector = DC.FunctionName @@ -159,6 +157,10 @@ instance Backend 'DataConnector where defaultTriggerOnReplication = Nothing +instance HasSourceConfiguration 'DataConnector where + type SourceConfig 'DataConnector = DC.SourceConfig + type SourceConnConfiguration 'DataConnector = DC.ConnSourceConfig + instance NativeQueryMetadata 'DataConnector data CustomBooleanOperator a = CustomBooleanOperator diff --git a/server/src-lib/Hasura/Backends/MSSQL/Instances/Types.hs b/server/src-lib/Hasura/Backends/MSSQL/Instances/Types.hs index 511cc5a38da..4e4f54405c1 100644 --- a/server/src-lib/Hasura/Backends/MSSQL/Instances/Types.hs +++ b/server/src-lib/Hasura/Backends/MSSQL/Instances/Types.hs @@ -29,8 +29,6 @@ import Language.GraphQL.Draft.Syntax qualified as G instance Backend 'MSSQL where type BackendConfig 'MSSQL = () type BackendInfo 'MSSQL = () - type SourceConfig 'MSSQL = MSSQL.MSSQLSourceConfig - type SourceConnConfiguration 'MSSQL = MSSQL.MSSQLConnConfiguration type TableName 'MSSQL = MSSQL.TableName type RawFunctionInfo 'MSSQL = Void @@ -125,4 +123,8 @@ instance Backend 'MSSQL where defaultTriggerOnReplication = Just ((), TOREnableTrigger) +instance HasSourceConfiguration 'MSSQL where + type SourceConfig 'MSSQL = MSSQL.MSSQLSourceConfig + type SourceConnConfiguration 'MSSQL = MSSQL.MSSQLConnConfiguration + instance NativeQueryMetadata 'MSSQL diff --git a/server/src-lib/Hasura/Backends/MySQL/Instances/Types.hs b/server/src-lib/Hasura/Backends/MySQL/Instances/Types.hs index 773d57c472f..13f3b3834fa 100644 --- a/server/src-lib/Hasura/Backends/MySQL/Instances/Types.hs +++ b/server/src-lib/Hasura/Backends/MySQL/Instances/Types.hs @@ -19,8 +19,6 @@ import Language.GraphQL.Draft.Syntax qualified as G instance Backend 'MySQL where type BackendConfig 'MySQL = () type BackendInfo 'MySQL = () - type SourceConfig 'MySQL = MySQL.SourceConfig - type SourceConnConfiguration 'MySQL = MySQL.ConnSourceConfig type TableName 'MySQL = MySQL.TableName type FunctionName 'MySQL = MySQL.FunctionName type RawFunctionInfo 'MySQL = Void -- MySQL.FunctionName @@ -149,4 +147,8 @@ instance Backend 'MySQL where defaultTriggerOnReplication = Nothing +instance HasSourceConfiguration 'MySQL where + type SourceConfig 'MySQL = MySQL.SourceConfig + type SourceConnConfiguration 'MySQL = MySQL.ConnSourceConfig + instance NativeQueryMetadata 'MySQL diff --git a/server/src-lib/Hasura/Backends/Postgres/Instances/NativeQueries.hs b/server/src-lib/Hasura/Backends/Postgres/Instances/NativeQueries.hs new file mode 100644 index 00000000000..fb30f9f701f --- /dev/null +++ b/server/src-lib/Hasura/Backends/Postgres/Instances/NativeQueries.hs @@ -0,0 +1,46 @@ +-- | Validate native queries against postgres-like flavors. +module Hasura.Backends.Postgres.Instances.NativeQueries + ( validateNativeQuery, + ) +where + +import Data.Aeson (toJSON) +import Database.PG.Query qualified as PG +import Hasura.Backends.Postgres.Connection qualified as PG +import Hasura.Backends.Postgres.Connection.Connect (withPostgresDB) +import Hasura.Base.Error +import Hasura.NativeQuery.Metadata +import Hasura.Prelude +import Hasura.SQL.Backend + +-- | Prepare a native query against a postgres-like database to validate it. +validateNativeQuery :: (MonadIO m, MonadError NativeQueryError m) => PG.PostgresConnConfiguration -> NativeQueryInfoImpl ('Postgres pgKind) -> m () +validateNativeQuery connConf nativeQuery = do + let name = getNativeQueryNameImpl $ nqiiRootFieldName nativeQuery + let code :: Text + code = fold $ flip evalState (1 :: Int) do + for (getInterpolatedQuery $ nqiiCode nativeQuery) \case + IIText t -> pure t + IIVariable _v -> do + i <- get + modify (+ 1) + pure $ "$" <> tshow i + result <- + liftIO $ + withPostgresDB connConf $ + PG.rawQE + ( \e -> + (err400 ValidationFailed "Failed to validate query") + { qeInternal = Just $ ExtraInternal $ toJSON e + } + ) + (PG.fromText $ "PREPARE _naqi_vali_" <> name <> " AS " <> code) + [] + False + case result of + -- running the query failed + Left err -> + throwError $ NativeQueryValidationError err + -- running the query succeeded + Right () -> + pure () diff --git a/server/src-lib/Hasura/Backends/Postgres/Instances/Types.hs b/server/src-lib/Hasura/Backends/Postgres/Instances/Types.hs index eba97881b77..77f3718cb49 100644 --- a/server/src-lib/Hasura/Backends/Postgres/Instances/Types.hs +++ b/server/src-lib/Hasura/Backends/Postgres/Instances/Types.hs @@ -17,6 +17,7 @@ import Data.Typeable import Hasura.Backends.Postgres.Connection qualified as Postgres import Hasura.Backends.Postgres.Connection.VersionCheck (runCockroachVersionCheck) import Hasura.Backends.Postgres.Execute.ConnectionTemplate qualified as Postgres +import Hasura.Backends.Postgres.Instances.NativeQueries (validateNativeQuery) import Hasura.Backends.Postgres.Instances.PingSource (runCockroachDBPing) import Hasura.Backends.Postgres.SQL.DML qualified as Postgres import Hasura.Backends.Postgres.SQL.Types qualified as Postgres @@ -89,8 +90,6 @@ instance where type BackendConfig ('Postgres pgKind) = () type BackendInfo ('Postgres pgKind) = () - type SourceConfig ('Postgres pgKind) = Postgres.PGSourceConfig - type SourceConnConfiguration ('Postgres pgKind) = Postgres.PostgresConnConfiguration type TableName ('Postgres pgKind) = Postgres.QualifiedTable type FunctionName ('Postgres pgKind) = Postgres.QualifiedFunction type FunctionArgument ('Postgres pgKind) = Postgres.FunctionArg @@ -166,6 +165,14 @@ instance resolveConnectionTemplate = Postgres.pgResolveConnectionTemplate +instance + ( HasTag ('Postgres pgKind) + ) => + HasSourceConfiguration ('Postgres pgKind) + where + type SourceConfig ('Postgres pgKind) = Postgres.PGSourceConfig + type SourceConnConfiguration ('Postgres pgKind) = Postgres.PostgresConnConfiguration + instance ( HasTag ('Postgres pgKind), Typeable ('Postgres pgKind), @@ -181,3 +188,4 @@ instance trackNativeQuerySource = tnqSource nativeQueryInfoName = nqiiRootFieldName nativeQueryTrackToInfo = defaultNativeQueryTrackToInfo + validateNativeQueryAgainstSource = validateNativeQuery diff --git a/server/src-lib/Hasura/Backends/Postgres/SQL/DML.hs b/server/src-lib/Hasura/Backends/Postgres/SQL/DML.hs index f4c5da02c43..1fd0b6510ea 100644 --- a/server/src-lib/Hasura/Backends/Postgres/SQL/DML.hs +++ b/server/src-lib/Hasura/Backends/Postgres/SQL/DML.hs @@ -1186,6 +1186,8 @@ instance ToSQL TopLevelCTE where IIVariable v -> toSQL v ) parts + -- if the user has a comment on the last line, this will make sure it doesn't interrupt the rest of the query + <> "\n" -- | A @SELECT@ statement with Common Table Expressions. -- diff --git a/server/src-lib/Hasura/NativeQuery/API.hs b/server/src-lib/Hasura/NativeQuery/API.hs index d5e416c600d..3503aa6d043 100644 --- a/server/src-lib/Hasura/NativeQuery/API.hs +++ b/server/src-lib/Hasura/NativeQuery/API.hs @@ -19,14 +19,14 @@ module Hasura.NativeQuery.API ) where -import Control.Lens ((^?)) +import Control.Lens (preview, (^?)) import Data.Aeson import Hasura.Base.Error import Hasura.EncJSON import Hasura.NativeQuery.Types import Hasura.Prelude import Hasura.RQL.Types.Backend (Backend) -import Hasura.RQL.Types.Common (SourceName, successMsg) +import Hasura.RQL.Types.Common (SourceName, sourceNameToText, successMsg) import Hasura.RQL.Types.Metadata import Hasura.RQL.Types.Metadata.Backend import Hasura.RQL.Types.Metadata.Object @@ -94,10 +94,17 @@ runTrackNativeQuery :: runTrackNativeQuery (BackendTrackNativeQuery trackNativeQueryRequest) = do throwIfFeatureDisabled - (metadata :: NativeQueryInfo b) <- - case nativeQueryTrackToInfo @b trackNativeQueryRequest of + sourceConnConfig <- + maybe (throw400 NotFound $ "Source " <> sourceNameToText source <> " not found.") pure + . preview (metaSources . ix source . toSourceMetadata @b . smConfiguration) + =<< getMetadata + + (metadata :: NativeQueryInfo b) <- do + r <- liftIO $ runExceptT $ nativeQueryTrackToInfo @b sourceConnConfig trackNativeQueryRequest + case r of Right nq -> pure nq Left (NativeQueryParseError e) -> throw400 ParseFailed e + Left (NativeQueryValidationError e) -> throwError e let fieldName = nativeQueryInfoName @b metadata metadataObj = diff --git a/server/src-lib/Hasura/NativeQuery/Metadata.hs b/server/src-lib/Hasura/NativeQuery/Metadata.hs index 832f88c9484..bbdfdfffb40 100644 --- a/server/src-lib/Hasura/NativeQuery/Metadata.hs +++ b/server/src-lib/Hasura/NativeQuery/Metadata.hs @@ -182,16 +182,27 @@ data TrackNativeQueryImpl (b :: BackendType) = TrackNativeQueryImpl } -- | Default implementation of the method 'nativeQueryTrackToInfo'. -defaultNativeQueryTrackToInfo :: TrackNativeQueryImpl b -> Either NativeQueryParseError (NativeQueryInfoImpl b) -defaultNativeQueryTrackToInfo TrackNativeQueryImpl {..} = do - nqiiCode <- mapLeft NativeQueryParseError (parseInterpolatedQuery tnqCode) +defaultNativeQueryTrackToInfo :: + forall b m. + ( MonadIO m, + MonadError NativeQueryError m, + NativeQueryMetadata b, + NativeQueryInfo b ~ NativeQueryInfoImpl b + ) => + SourceConnConfiguration b -> + TrackNativeQueryImpl b -> + m (NativeQueryInfoImpl b) +defaultNativeQueryTrackToInfo sourceConnConfig TrackNativeQueryImpl {..} = do + nqiiCode <- liftEither $ mapLeft NativeQueryParseError (parseInterpolatedQuery tnqCode) + let nqiiRootFieldName = tnqRootFieldName + nqiiReturns = tnqReturns + nqiiArguments = tnqArguments + nqiiDescription = tnqDescription + nqInfoImpl = NativeQueryInfoImpl {..} - pure $ NativeQueryInfoImpl {..} - where - nqiiRootFieldName = tnqRootFieldName - nqiiReturns = tnqReturns - nqiiArguments = tnqArguments - nqiiDescription = tnqDescription + validateNativeQueryAgainstSource @b sourceConnConfig nqInfoImpl + + pure nqInfoImpl instance (Backend b, HasCodec (ScalarType b)) => HasCodec (TrackNativeQueryImpl b) where codec = diff --git a/server/src-lib/Hasura/NativeQuery/Types.hs b/server/src-lib/Hasura/NativeQuery/Types.hs index 16752e3cf32..b3e0ec2883c 100644 --- a/server/src-lib/Hasura/NativeQuery/Types.hs +++ b/server/src-lib/Hasura/NativeQuery/Types.hs @@ -6,7 +6,7 @@ -- are free to provide their own as needed. module Hasura.NativeQuery.Types ( NativeQueryMetadata (..), - NativeQueryParseError (..), + NativeQueryError (..), BackendTrackNativeQuery (..), ) where @@ -15,12 +15,12 @@ import Autodocodec import Data.Aeson import Data.Kind import Data.Text.Extended (ToTxt) +import Hasura.Base.Error import Hasura.Prelude import Hasura.RQL.Types.Common +import Hasura.RQL.Types.SourceConfiguration import Hasura.SQL.Backend -type Representable a = (Show a, Eq a, Hashable a, NFData a) - type APIType a = (ToJSON a, FromJSON a) -- | This type class models the types and functions necessary to talk about @@ -65,9 +65,14 @@ class nativeQueryInfoName = absurd -- | Projection function, producing a 'NativeQueryInfo b' from a 'TrackNativeQuery b'. - nativeQueryTrackToInfo :: TrackNativeQuery b -> Either NativeQueryParseError (NativeQueryInfo b) - default nativeQueryTrackToInfo :: (TrackNativeQuery b ~ Void) => TrackNativeQuery b -> Either NativeQueryParseError (NativeQueryInfo b) - nativeQueryTrackToInfo = absurd + nativeQueryTrackToInfo :: SourceConnConfiguration b -> TrackNativeQuery b -> ExceptT NativeQueryError IO (NativeQueryInfo b) + default nativeQueryTrackToInfo :: (TrackNativeQuery b ~ Void) => SourceConnConfiguration b -> TrackNativeQuery b -> ExceptT NativeQueryError IO (NativeQueryInfo b) + nativeQueryTrackToInfo _ = absurd + + -- | Validate the native query against the database. + validateNativeQueryAgainstSource :: (MonadIO m, MonadError NativeQueryError m) => SourceConnConfiguration b -> NativeQueryInfo b -> m () + default validateNativeQueryAgainstSource :: (NativeQueryInfo b ~ Void) => SourceConnConfiguration b -> NativeQueryInfo b -> m () + validateNativeQueryAgainstSource _ = absurd -- | Our API endpoint solution wraps all request payload types in 'AnyBackend' -- for its multi-backend support, but type families must be fully applied to @@ -81,4 +86,6 @@ deriving newtype instance NativeQueryMetadata b => FromJSON (BackendTrackNativeQ -- Things that might go wrong when converting a Native Query metadata request -- into a valid metadata item (such as failure to interpolate the query) -newtype NativeQueryParseError = NativeQueryParseError Text +data NativeQueryError + = NativeQueryParseError Text + | NativeQueryValidationError QErr diff --git a/server/src-lib/Hasura/RQL/Types/Backend.hs b/server/src-lib/Hasura/RQL/Types/Backend.hs index a1bfb8fe726..4bae4cd50bb 100644 --- a/server/src-lib/Hasura/RQL/Types/Backend.hs +++ b/server/src-lib/Hasura/RQL/Types/Backend.hs @@ -2,13 +2,14 @@ module Hasura.RQL.Types.Backend ( Backend (..), - Representable, SessionVarType, XDisable, XEnable, ComputedFieldReturnType (..), _ReturnsTable, SupportedNamingCase (..), + HasSourceConfiguration (..), + Representable, ) where @@ -27,13 +28,12 @@ import Hasura.Prelude import Hasura.RQL.Types.Common import Hasura.RQL.Types.HealthCheckImplementation (HealthCheckImplementation) import Hasura.RQL.Types.ResizePool (ServerReplicas) +import Hasura.RQL.Types.SourceConfiguration import Hasura.SQL.Backend import Hasura.SQL.Tag import Hasura.SQL.Types import Language.GraphQL.Draft.Syntax qualified as G -type Representable a = (Show a, Hashable a, NFData a) - type SessionVarType b = CollectableType (ScalarType b) data ComputedFieldReturnType (b :: BackendType) @@ -71,7 +71,8 @@ data SupportedNamingCase = OnlyHasuraCase | AllConventions -- type application or a 'Proxy' parameter to disambiguate between -- different backends at the call site. class - ( Representable (BasicOrderType b), + ( HasSourceConfiguration b, + Representable (BasicOrderType b), Representable (Column b), Representable (ComputedFieldDefinition b), Representable (ComputedFieldImplicitArguments b), @@ -85,7 +86,6 @@ class Representable (SQLExpression b), Representable (ScalarSelectionArguments b), Representable (ScalarType b), - Representable (SourceConnConfiguration b), Representable (XComputedField b), Representable (TableName b), Eq (RawFunctionInfo b), @@ -105,13 +105,11 @@ class FromJSON (HealthCheckTest b), FromJSON (RawFunctionInfo b), FromJSON (ScalarType b), - FromJSON (SourceConnConfiguration b), FromJSON (TableName b), FromJSONKey (Column b), HasCodec (BackendSourceKind b), HasCodec (Column b), HasCodec (FunctionName b), - HasCodec (SourceConnConfiguration b), HasCodec (TableName b), ToJSON (BackendConfig b), ToJSON (Column b), @@ -119,9 +117,7 @@ class ToJSON (FunctionArgument b), ToJSON (FunctionName b), ToJSON (ScalarType b), - ToJSON (SourceConfig b), ToJSON (TableName b), - ToJSON (SourceConnConfiguration b), ToJSON (ExtraTableMetadata b), ToJSON (SQLExpression b), ToJSON (ComputedFieldDefinition b), @@ -153,7 +149,6 @@ class Show (CountType b), Eq (ScalarValue b), Show (ScalarValue b), - Eq (SourceConfig b), -- Extension constraints. Eq (XNodesAgg b), Show (XNodesAgg b), @@ -179,13 +174,6 @@ class -- | Runtime backend info derived from (possibly enriched) BackendConfig and stored in SchemaCache type BackendInfo b :: Type - -- | User facing connection configuration for a database. - type SourceConnConfiguration b :: Type - - -- | Internal connection configuration for a database - connection string, - -- connection pool etc - type SourceConfig b :: Type - -- Fully qualified name of a table type TableName b :: Type @@ -298,7 +286,7 @@ class type BackendInsert b = Const Void - -- | Intermediate representation of Native Queries + -- | Intermediate representation of Native Queries. -- The default implementation makes native queries uninstantiable. -- -- It is parameterised over the type of fields, which changes during the IR diff --git a/server/src-lib/Hasura/RQL/Types/SourceConfiguration.hs b/server/src-lib/Hasura/RQL/Types/SourceConfiguration.hs new file mode 100644 index 00000000000..952129bada2 --- /dev/null +++ b/server/src-lib/Hasura/RQL/Types/SourceConfiguration.hs @@ -0,0 +1,36 @@ +{-# LANGUAGE UndecidableInstances #-} + +module Hasura.RQL.Types.SourceConfiguration + ( HasSourceConfiguration (..), + Representable, + ) +where + +import Autodocodec (HasCodec) +import Data.Aeson.Extended +import Data.Kind (Type) +import Hasura.Prelude +import Hasura.SQL.Backend +import Hasura.SQL.Tag + +type Representable a = (Show a, Eq a, Hashable a, NFData a) + +class + ( Representable (SourceConnConfiguration b), + HasCodec (SourceConnConfiguration b), + FromJSON (SourceConnConfiguration b), + ToJSON (SourceConfig b), + ToJSON (SourceConnConfiguration b), + Eq (SourceConfig b), + HasTag b + ) => + HasSourceConfiguration (b :: BackendType) + where + -- types + + -- | User facing connection configuration for a database. + type SourceConnConfiguration b :: Type + + -- | Internal connection configuration for a database - connection string, + -- connection pool etc + type SourceConfig b :: Type