From 4facb3c780cbfde96d899c8aff52f38a4f08f9a6 Mon Sep 17 00:00:00 2001 From: Vamshi Surabhi <0x777@users.noreply.github.com> Date: Wed, 24 Jul 2019 00:41:34 +0530 Subject: [PATCH 01/18] remove support for query templates (#2560) query templates is a little known feature that lets you template rql queries and serve them as rest apis. This is not relevant anymore given the GraphQL interface and getting rid of it reduces the dev time when adding features in few subsystems. This feature has never been used outside hasura's internal projects or documented or exposed through console and hence can safely be removed. --- cli/commands/migrate_test.go | 12 +- server/graphql-engine.cabal | 2 - server/src-exec/Migrate.hs | 17 +- server/src-exec/Ops.hs | 1 - server/src-lib/Hasura/RQL/DDL/Metadata.hs | 32 +-- .../src-lib/Hasura/RQL/DDL/QueryTemplate.hs | 236 ------------------ .../src-lib/Hasura/RQL/DDL/Schema/Rename.hs | 11 +- server/src-lib/Hasura/RQL/DDL/Schema/Table.hs | 19 +- .../src-lib/Hasura/RQL/DML/QueryTemplate.hs | 148 ----------- server/src-lib/Hasura/RQL/Types.hs | 14 -- server/src-lib/Hasura/RQL/Types/Catalog.hs | 8 - server/src-lib/Hasura/RQL/Types/Common.hs | 21 -- server/src-lib/Hasura/RQL/Types/Metadata.hs | 3 - .../src-lib/Hasura/RQL/Types/SchemaCache.hs | 57 +---- .../Hasura/RQL/Types/SchemaCacheTypes.hs | 3 - server/src-lib/Hasura/Server/App.hs | 31 --- server/src-lib/Hasura/Server/Query.hs | 17 -- server/src-rsr/catalog_metadata.sql | 15 -- server/src-rsr/hdb_metadata.yaml | 5 - server/src-rsr/initialise.sql | 8 - .../queries/v1/metadata/clear_metadata.yaml | 1 - .../queries/v1/metadata/export_metadata.yaml | 1 - .../queries/v1/metadata/replace_metadata.yaml | 1 - .../v1/metadata/replace_metadata_wo_rs.yaml | 1 - 24 files changed, 30 insertions(+), 634 deletions(-) delete mode 100644 server/src-lib/Hasura/RQL/DDL/QueryTemplate.hs delete mode 100644 server/src-lib/Hasura/RQL/DML/QueryTemplate.hs diff --git a/cli/commands/migrate_test.go b/cli/commands/migrate_test.go index 970d0ad18220f..6a4d500903448 100644 --- a/cli/commands/migrate_test.go +++ b/cli/commands/migrate_test.go @@ -31,7 +31,9 @@ var ravenVersions = []mt.Version{ } var testMetadataPrev = map[string][]byte{ - "metadata": []byte(`functions: [] + "metadata": []byte(`allowlist: [] +functions: [] +query_collections: [] query_templates: [] remote_schemas: [] tables: @@ -44,7 +46,9 @@ tables: table: test update_permissions: [] `), - "empty-metadata": []byte(`functions: [] + "empty-metadata": []byte(`allowlist: [] +functions: [] +query_collections: [] query_templates: [] remote_schemas: [] tables: [] @@ -55,7 +59,6 @@ var testMetadataCurrent = map[string][]byte{ "metadata": []byte(`allowlist: [] functions: [] query_collections: [] -query_templates: [] remote_schemas: [] tables: - array_relationships: [] @@ -70,7 +73,6 @@ tables: "empty-metadata": []byte(`allowlist: [] functions: [] query_collections: [] -query_templates: [] remote_schemas: [] tables: [] `), @@ -262,7 +264,7 @@ func mustWriteFile(t testing.TB, dir, file string, body string) { func compareMetadata(t testing.TB, metadataFile string, actualType string, serverVersion *semver.Version) { var actualData []byte - c, err := semver.NewConstraint("<= 1.0.0-alpha45") + c, err := semver.NewConstraint("<= v1.0.0-beta.3") if err != nil { t.Fatal(err) } diff --git a/server/graphql-engine.cabal b/server/graphql-engine.cabal index f44c5a28f9881..c6f1602e7d5f2 100644 --- a/server/graphql-engine.cabal +++ b/server/graphql-engine.cabal @@ -188,7 +188,6 @@ library , Hasura.RQL.DDL.Relationship , Hasura.RQL.DDL.Relationship.Rename , Hasura.RQL.DDL.Relationship.Types - , Hasura.RQL.DDL.QueryTemplate , Hasura.RQL.DDL.Schema.Table , Hasura.RQL.DDL.Schema.Rename , Hasura.RQL.DDL.Schema.Function @@ -209,7 +208,6 @@ library , Hasura.RQL.DML.Select , Hasura.RQL.DML.Update , Hasura.RQL.DML.Count - , Hasura.RQL.DML.QueryTemplate , Hasura.RQL.GBoolExp , Hasura.GraphQL.Transport.HTTP.Protocol diff --git a/server/src-exec/Migrate.hs b/server/src-exec/Migrate.hs index 619446b0b656d..90684ce217336 100644 --- a/server/src-exec/Migrate.hs +++ b/server/src-exec/Migrate.hs @@ -19,7 +19,7 @@ import qualified Data.Yaml.TH as Y import qualified Database.PG.Query as Q curCatalogVer :: T.Text -curCatalogVer = "17" +curCatalogVer = "18" migrateMetadata :: ( MonadTx m @@ -327,6 +327,16 @@ from16To17 = AND table_name = 'hdb_allowlist'; |] +from17To18 :: MonadTx m => m () +from17To18 = + liftTx $ Q.catchE defaultTxErrorHandler $ + Q.multiQ [Q.sql| + DELETE FROM hdb_catalog.hdb_table + WHERE table_schema = 'hdb_catalog' + AND table_name = 'hdb_query_template'; + DROP table hdb_catalog.hdb_query_template + |] + migrateCatalog :: ( MonadTx m , CacheRWM m @@ -358,10 +368,13 @@ migrateCatalog migrationTime = do | preVer == "14" -> from14ToCurrent | preVer == "15" -> from15ToCurrent | preVer == "16" -> from16ToCurrent + | preVer == "17" -> from17ToCurrent | otherwise -> throw400 NotSupported $ "unsupported version : " <> preVer where - from16ToCurrent = from16To17 >> postMigrate + from17ToCurrent = from17To18 >> postMigrate + + from16ToCurrent = from16To17 >> from17ToCurrent from15ToCurrent = from15To16 >> from16ToCurrent diff --git a/server/src-exec/Ops.hs b/server/src-exec/Ops.hs index baf759b271750..a10ec65b741ca 100644 --- a/server/src-exec/Ops.hs +++ b/server/src-exec/Ops.hs @@ -123,7 +123,6 @@ setAllAsSystemDefined = liftTx $ Q.catchE defaultTxErrorHandler $ do Q.unitQ "UPDATE hdb_catalog.hdb_table SET is_system_defined = 'true'" () False Q.unitQ "UPDATE hdb_catalog.hdb_relationship SET is_system_defined = 'true'" () False Q.unitQ "UPDATE hdb_catalog.hdb_permission SET is_system_defined = 'true'" () False - Q.unitQ "UPDATE hdb_catalog.hdb_query_template SET is_system_defined = 'true'" () False cleanCatalog :: (MonadTx m) => m () cleanCatalog = liftTx $ Q.catchE defaultTxErrorHandler $ do diff --git a/server/src-lib/Hasura/RQL/DDL/Metadata.hs b/server/src-lib/Hasura/RQL/DDL/Metadata.hs index fdaf6acc3875c..8369e1f5520df 100644 --- a/server/src-lib/Hasura/RQL/DDL/Metadata.hs +++ b/server/src-lib/Hasura/RQL/DDL/Metadata.hs @@ -45,7 +45,6 @@ import qualified Hasura.RQL.DDL.EventTrigger as DE import qualified Hasura.RQL.DDL.Permission as DP import qualified Hasura.RQL.DDL.Permission.Internal as DP import qualified Hasura.RQL.DDL.QueryCollection as DQC -import qualified Hasura.RQL.DDL.QueryTemplate as DQ import qualified Hasura.RQL.DDL.Relationship as DR import qualified Hasura.RQL.DDL.RemoteSchema as DRS import qualified Hasura.RQL.DDL.Schema.Function as DF @@ -120,7 +119,6 @@ instance FromJSON ClearMetadata where clearMetadata :: Q.TxE QErr () clearMetadata = Q.catchE defaultTxErrorHandler $ do - Q.unitQ "DELETE FROM hdb_catalog.hdb_query_template WHERE is_system_defined <> 'true'" () False Q.unitQ "DELETE FROM hdb_catalog.hdb_function WHERE is_system_defined <> 'true'" () False Q.unitQ "DELETE FROM hdb_catalog.hdb_permission WHERE is_system_defined <> 'true'" () False Q.unitQ "DELETE FROM hdb_catalog.hdb_relationship WHERE is_system_defined <> 'true'" () False @@ -144,7 +142,6 @@ runClearMetadata _ = do data ReplaceMetadata = ReplaceMetadata { aqTables :: ![TableMeta] - , aqQueryTemplates :: ![DQ.CreateQueryTemplate] , aqFunctions :: !(Maybe [QualifiedFunction]) , aqRemoteSchemas :: !(Maybe [TRS.AddRemoteSchemaQuery]) , aqQueryCollections :: !(Maybe [DQC.CreateCollection]) @@ -156,7 +153,7 @@ $(deriveJSON (aesonDrop 2 snakeCase){omitNothingFields=True} ''ReplaceMetadata) applyQP1 :: (QErrM m, UserInfoM m) => ReplaceMetadata -> m () -applyQP1 (ReplaceMetadata tables templates mFunctions mSchemas mCollections mAllowlist) = do +applyQP1 (ReplaceMetadata tables mFunctions mSchemas mCollections mAllowlist) = do adminOnly @@ -182,9 +179,6 @@ applyQP1 (ReplaceMetadata tables templates mFunctions mSchemas mCollections mAll checkMultipleDecls "delete permissions" delPerms checkMultipleDecls "event triggers" eventTriggers - withPathK "queryTemplates" $ - checkMultipleDecls "query templates" $ map DQ.cqtName templates - withPathK "functions" $ checkMultipleDecls "functions" functions @@ -223,7 +217,7 @@ applyQP2 ) => ReplaceMetadata -> m EncJSON -applyQP2 (ReplaceMetadata tables templates mFunctions mSchemas mCollections mAllowlist) = do +applyQP2 (ReplaceMetadata tables mFunctions mSchemas mCollections mAllowlist) = do liftTx clearMetadata DT.buildSchemaCacheStrict @@ -261,12 +255,6 @@ applyQP2 (ReplaceMetadata tables templates mFunctions mSchemas mCollections mAll indexedForM_ (table ^. tmEventTriggers) $ \etc -> DE.subTableP2 (table ^. tmTable) False etc - -- query templates - withPathK "queryTemplates" $ - indexedForM_ templates $ \template -> do - qti <- DQ.createQueryTemplateP1 template - void $ DQ.createQueryTemplateP2 template qti - -- sql functions withPathK "functions" $ indexedMapM_ (void . DF.trackFunctionP2) functions @@ -341,13 +329,6 @@ fetchMetadata = do updPermDefs <- mkPermDefs PTUpdate permissions delPermDefs <- mkPermDefs PTDelete permissions - -- Fetch all the query templates - qTmpltRows <- Q.catchE defaultTxErrorHandler fetchQTemplates - - qTmpltDefs <- forM qTmpltRows $ \(qtn, Q.AltJ qtDefVal, mComment) -> do - qtDef <- decodeValue qtDefVal - return $ DQ.CreateQueryTemplate qtn qtDef mComment - -- Fetch all event triggers eventTriggers <- Q.catchE defaultTxErrorHandler fetchEventTriggers triggerMetaDefs <- mkTriggerMetaDefs eventTriggers @@ -374,7 +355,7 @@ fetchMetadata = do -- fetch allow list allowlist <- map DQC.CollectionReq <$> DQC.fetchAllowlist - return $ ReplaceMetadata (M.elems postRelMap) qTmpltDefs (Just functions) + return $ ReplaceMetadata (M.elems postRelMap) (Just functions) (Just schemas) (Just collections) (Just allowlist) where @@ -421,12 +402,6 @@ fetchMetadata = do WHERE is_system_defined = 'false' |] () False - fetchQTemplates = - Q.listQ [Q.sql| - SELECT template_name, template_defn :: json, comment - FROM hdb_catalog.hdb_query_template - WHERE is_system_defined = 'false' - |] () False fetchEventTriggers = Q.listQ [Q.sql| SELECT e.schema_name, e.table_name, e.configuration::json @@ -528,7 +503,6 @@ purgeMetadataObj = liftTx . \case Q.catchE defaultTxErrorHandler $ DT.delTableFromCatalog qt (MOFunction qf) -> DF.delFunctionFromCatalog qf (MORemoteSchema rsn) -> DRS.removeRemoteSchemaFromCatalog rsn - (MOQTemplate qtn) -> DQ.delQTemplateFromCatalog qtn (MOTableObj qt (MTORel rn _)) -> DR.delRelFromCatalog qt rn (MOTableObj qt (MTOPerm rn pt)) -> DP.dropPermFromCatalog qt rn pt (MOTableObj _ (MTOTrigger trn)) -> DE.delEventTriggerFromCatalog trn diff --git a/server/src-lib/Hasura/RQL/DDL/QueryTemplate.hs b/server/src-lib/Hasura/RQL/DDL/QueryTemplate.hs deleted file mode 100644 index 0ad21ff038420..0000000000000 --- a/server/src-lib/Hasura/RQL/DDL/QueryTemplate.hs +++ /dev/null @@ -1,236 +0,0 @@ -module Hasura.RQL.DDL.QueryTemplate - ( createQueryTemplateP1 - , createQueryTemplateP2 - , delQTemplateFromCatalog - , TemplateParamConf(..) - , CreateQueryTemplate(..) - , runCreateQueryTemplate - , QueryTP1 - - , DropQueryTemplate(..) - , runDropQueryTemplate - - , SetQueryTemplateComment(..) - , runSetQueryTemplateComment - ) where - -import Hasura.EncJSON -import Hasura.Prelude -import Hasura.RQL.DML.Internal (sessVarFromCurrentSetting) -import Hasura.RQL.GBoolExp (txtRHSBuilder) -import Hasura.RQL.Types -import Hasura.SQL.Types -import Hasura.SQL.Value - -import qualified Database.PG.Query as Q -import qualified Hasura.RQL.DML.Count as R -import qualified Hasura.RQL.DML.Delete as R -import qualified Hasura.RQL.DML.Insert as R -import qualified Hasura.RQL.DML.Select as R -import qualified Hasura.RQL.DML.Update as R -import qualified Hasura.SQL.DML as PS - -import Data.Aeson -import Data.Aeson.Casing -import Data.Aeson.TH -import Instances.TH.Lift () -import Language.Haskell.TH.Syntax (Lift) - -import qualified Data.HashMap.Strict as M -import qualified Data.Text as T - -data TemplateParamConf - = TemplateParamConf - { tpcParam :: !TemplateParam - , tpcDefault :: !(Maybe Value) - } deriving (Show, Eq, Lift) - -$(deriveJSON (aesonDrop 3 snakeCase){omitNothingFields=True} ''TemplateParamConf) - -data CreateQueryTemplate - = CreateQueryTemplate - { cqtName :: !TQueryName - , cqtTemplate :: !QueryT - , cqtComment :: !(Maybe T.Text) - } deriving (Show, Eq, Lift) - -$(deriveJSON (aesonDrop 3 snakeCase){omitNothingFields=True} ''CreateQueryTemplate) - -validateParam - :: (QErrM m) - => PGColType - -> Value - -> m PS.SQLExp -validateParam pct val = - case val of - Object _ -> do - tpc <- decodeValue val - withPathK "default" $ - maybe (return ()) validateDefault $ tpcDefault tpc - return $ PS.SELit "NULL" - _ -> txtRHSBuilder pct val - where - validateDefault = - void . runAesonParser (convToBin pct) - -mkSelQ :: (QErrM m) => SelectQueryT -> m SelectQuery -mkSelQ (DMLQuery tn (SelectG c w o lim offset)) = do - intLim <- withPathK "limit" $ maybe returnNothing parseAsInt lim - intOffset <- withPathK "offset" $ maybe returnNothing parseAsInt offset - return $ DMLQuery tn $ SelectG c w o intLim intOffset - where - returnNothing = return Nothing - parseAsInt v = case v of - Object _ -> do - tpc <- decodeValue v - withPathK "default" $ - mapM decodeValue $ tpcDefault tpc - _ -> Just <$> decodeValue v - -data QueryTP1 - = QTP1Insert R.InsertQueryP1 - | QTP1Select R.AnnSimpleSel - | QTP1Update R.AnnUpd - | QTP1Delete R.AnnDel - | QTP1Count R.CountQueryP1 - | QTP1Bulk [QueryTP1] - deriving (Show, Eq) - -validateTQuery - :: (QErrM m, UserInfoM m, CacheRM m, HasSQLGenCtx m) - => QueryT - -> m QueryTP1 -validateTQuery qt = withPathK "args" $ case qt of - QTInsert q -> QTP1Insert <$> - R.convInsertQuery decodeInsObjs sessVarFromCurrentSetting validateParam q - QTSelect q -> QTP1Select <$> - (mkSelQ q >>= R.convSelectQuery sessVarFromCurrentSetting validateParam) - QTUpdate q -> QTP1Update <$> - R.validateUpdateQueryWith sessVarFromCurrentSetting validateParam q - QTDelete q -> QTP1Delete <$> - R.validateDeleteQWith sessVarFromCurrentSetting validateParam q - QTCount q -> QTP1Count <$> - R.validateCountQWith sessVarFromCurrentSetting validateParam q - QTBulk q -> QTP1Bulk <$> mapM validateTQuery q - where - decodeInsObjs val = do - tpc <- decodeValue val - mDefObjs <- mapM decodeValue $ tpcDefault tpc - return $ fromMaybe [] mDefObjs - -collectDeps - :: QueryTP1 -> [SchemaDependency] -collectDeps qt = case qt of - QTP1Insert qp1 -> R.getInsertDeps qp1 - QTP1Select qp1 -> R.getSelectDeps qp1 - QTP1Update qp1 -> R.getUpdateDeps qp1 - QTP1Delete qp1 -> R.getDeleteDeps qp1 - QTP1Count qp1 -> R.getCountDeps qp1 - QTP1Bulk qp1 -> concatMap collectDeps qp1 - -createQueryTemplateP1 - :: (UserInfoM m, QErrM m, CacheRM m, HasSQLGenCtx m) - => CreateQueryTemplate - -> m (WithDeps QueryTemplateInfo) -createQueryTemplateP1 (CreateQueryTemplate qtn qt _) = do - adminOnly - sc <- askSchemaCache - withPathK "name" $ when (isJust $ M.lookup qtn $ scQTemplates sc) $ - throw400 AlreadyExists $ "the query template already exists : " <>> qtn - qtp1 <- withPathK "template" $ liftP1 $ validateTQuery qt - let deps = collectDeps qtp1 - return (QueryTemplateInfo qtn qt, deps) - -addQTemplateToCatalog - :: CreateQueryTemplate - -> Q.TxE QErr () -addQTemplateToCatalog (CreateQueryTemplate qtName qtDef mComment) = - Q.unitQE defaultTxErrorHandler [Q.sql| - INSERT INTO - hdb_catalog.hdb_query_template - (template_name, template_defn, comment) - VALUES ($1, $2 :: jsonb, $3) - |] (qtName, Q.AltJ qtDef, mComment) False - -createQueryTemplateP2 - :: (QErrM m, CacheRWM m, MonadTx m) - => CreateQueryTemplate - -> WithDeps QueryTemplateInfo - -> m EncJSON -createQueryTemplateP2 cqt (qti, deps) = do - addQTemplateToCache qti deps - liftTx $ addQTemplateToCatalog cqt - return successMsg - -runCreateQueryTemplate - :: (QErrM m, UserInfoM m, CacheRWM m, MonadTx m, HasSQLGenCtx m) - => CreateQueryTemplate -> m EncJSON -runCreateQueryTemplate q = - createQueryTemplateP1 q >>= createQueryTemplateP2 q - -data DropQueryTemplate - = DropQueryTemplate - { dqtName :: !TQueryName - } deriving (Show, Eq, Lift) - -$(deriveJSON (aesonDrop 3 snakeCase){omitNothingFields=True} ''DropQueryTemplate) - -delQTemplateFromCatalog - :: TQueryName - -> Q.TxE QErr () -delQTemplateFromCatalog qtn = - Q.unitQE defaultTxErrorHandler [Q.sql| - DELETE FROM - hdb_catalog.hdb_query_template - WHERE template_name = $1 - |] (Identity qtn) False - -runDropQueryTemplate - :: (QErrM m, UserInfoM m, CacheRWM m, MonadTx m) - => DropQueryTemplate -> m EncJSON -runDropQueryTemplate q = do - withPathK "name" $ void $ askQTemplateInfo qtn - delQTemplateFromCache qtn - liftTx $ delQTemplateFromCatalog qtn - return successMsg - where - qtn = dqtName q - -data SetQueryTemplateComment - = SetQueryTemplateComment - { sqtcName :: !TQueryName - , sqtcComment :: !(Maybe T.Text) - } deriving (Show, Eq, Lift) - -$(deriveJSON (aesonDrop 4 snakeCase) ''SetQueryTemplateComment) - -setQueryTemplateCommentP1 - :: (UserInfoM m, QErrM m, CacheRM m) - => SetQueryTemplateComment -> m () -setQueryTemplateCommentP1 (SetQueryTemplateComment qtn _) = do - adminOnly - void $ askQTemplateInfo qtn - -setQueryTemplateCommentP2 - :: (QErrM m, MonadTx m) => SetQueryTemplateComment -> m EncJSON -setQueryTemplateCommentP2 apc = do - liftTx $ setQueryTemplateCommentTx apc - return successMsg - -setQueryTemplateCommentTx - :: SetQueryTemplateComment - -> Q.TxE QErr () -setQueryTemplateCommentTx (SetQueryTemplateComment qtn comment) = - Q.unitQE defaultTxErrorHandler - [Q.sql| - UPDATE hdb_catalog.hdb_query_template - SET comment = $1 - WHERE template_name = $2 - |] (comment, qtn) False - -runSetQueryTemplateComment - :: (QErrM m, UserInfoM m, CacheRWM m, MonadTx m) - => SetQueryTemplateComment -> m EncJSON -runSetQueryTemplateComment q = do - setQueryTemplateCommentP1 q - setQueryTemplateCommentP2 q diff --git a/server/src-lib/Hasura/RQL/DDL/Schema/Rename.hs b/server/src-lib/Hasura/RQL/DDL/Schema/Rename.hs index 6a3109851e961..059bab4d671ce 100644 --- a/server/src-lib/Hasura/RQL/DDL/Schema/Rename.hs +++ b/server/src-lib/Hasura/RQL/DDL/Schema/Rename.hs @@ -36,14 +36,9 @@ data RenameField type RenameTable = (QualifiedTable, QualifiedTable) otherDeps :: QErrM m => Text -> SchemaObjId -> m () -otherDeps errMsg = \case - SOQTemplate name -> - throw400 NotSupported $ - "found dependant query template " <> name <<> "; " <> errMsg - d -> - throw500 $ "unexpected dependancy " - <> reportSchemaObj d <> "; " <> errMsg - +otherDeps errMsg d = + throw500 $ "unexpected dependancy " + <> reportSchemaObj d <> "; " <> errMsg renameTableInCatalog :: (MonadTx m, CacheRM m) diff --git a/server/src-lib/Hasura/RQL/DDL/Schema/Table.hs b/server/src-lib/Hasura/RQL/DDL/Schema/Table.hs index 63f29151cfc6f..e6b7452aa5edc 100644 --- a/server/src-lib/Hasura/RQL/DDL/Schema/Table.hs +++ b/server/src-lib/Hasura/RQL/DDL/Schema/Table.hs @@ -13,7 +13,6 @@ import Hasura.RQL.DDL.Deps import Hasura.RQL.DDL.EventTrigger import Hasura.RQL.DDL.Permission import Hasura.RQL.DDL.Permission.Internal -import Hasura.RQL.DDL.QueryTemplate import Hasura.RQL.DDL.Relationship import Hasura.RQL.DDL.RemoteSchema import Hasura.RQL.DDL.Schema.Diff @@ -123,10 +122,6 @@ purgeDep schemaObjId = case schemaObjId of liftTx $ delRelFromCatalog qt rn delRelFromCache rn qt - (SOQTemplate qtn) -> do - liftTx $ delQTemplateFromCatalog qtn - delQTemplateFromCache qtn - (SOFunction qf) -> do liftTx $ delFunctionFromCatalog qf delFunctionFromCache qf @@ -352,7 +347,7 @@ buildSchemaCacheG withSetup = do sqlGenCtx <- askSQLGenCtx -- fetch all catalog metadata - CatalogMetadata tables relationships permissions qTemplates + CatalogMetadata tables relationships permissions eventTriggers remoteSchemas functions fkeys' allowlistDefs <- liftTx fetchCatalogData @@ -403,18 +398,6 @@ buildSchemaCacheG withSetup = do PTUpdate -> permHelper withSetup sqlGenCtx qt rn pDef PAUpdate PTDelete -> permHelper withSetup sqlGenCtx qt rn pDef PADelete - -- query templates - forM_ qTemplates $ \(CatalogQueryTemplate qtn qtDefVal) -> do - let def = object ["name" .= qtn, "template" .= qtDefVal] - mkInconsObj = - InconsistentMetadataObj (MOQTemplate qtn) MOTQTemplate def - handleInconsistentObj mkInconsObj $ do - qtDef <- decodeValue qtDefVal - qCtx <- mkAdminQCtx sqlGenCtx <$> askSchemaCache - (qti, deps) <- liftP1WithQCtx qCtx $ createQueryTemplateP1 $ - CreateQueryTemplate qtn qtDef Nothing - addQTemplateToCache qti deps - -- event triggers forM_ eventTriggers $ \(CatalogEventTrigger qt trn configuration) -> do let objId = MOTableObj qt $ MTOTrigger trn diff --git a/server/src-lib/Hasura/RQL/DML/QueryTemplate.hs b/server/src-lib/Hasura/RQL/DML/QueryTemplate.hs deleted file mode 100644 index 67c865ea34862..0000000000000 --- a/server/src-lib/Hasura/RQL/DML/QueryTemplate.hs +++ /dev/null @@ -1,148 +0,0 @@ -module Hasura.RQL.DML.QueryTemplate - ( ExecQueryTemplate(..) - , runExecQueryTemplate - ) where - -import Hasura.EncJSON -import Hasura.Prelude -import Hasura.RQL.DDL.QueryTemplate -import Hasura.RQL.DML.Internal -import Hasura.RQL.GBoolExp (txtRHSBuilder) -import Hasura.RQL.Instances () -import Hasura.RQL.Types -import Hasura.SQL.Types - -import qualified Database.PG.Query as Q -import qualified Hasura.RQL.DML.Count as RC -import qualified Hasura.RQL.DML.Delete as R -import qualified Hasura.RQL.DML.Insert as R -import qualified Hasura.RQL.DML.Select as R -import qualified Hasura.RQL.DML.Update as R -import qualified Hasura.SQL.DML as S - -import Data.Aeson.Casing -import Data.Aeson.TH -import Data.Aeson.Types -import Instances.TH.Lift () -import Language.Haskell.TH.Syntax (Lift) - -import qualified Data.HashMap.Strict as M -import qualified Data.Sequence as DS - -type TemplateArgs = M.HashMap TemplateParam Value - -data ExecQueryTemplate - = ExecQueryTemplate - { eqtName :: !TQueryName - , eqtArgs :: !TemplateArgs - } deriving (Show, Eq, Lift) - -$(deriveJSON (aesonDrop 3 snakeCase){omitNothingFields=True} ''ExecQueryTemplate) - -getParamValue - :: TemplateArgs - -> TemplateParamConf - -> DMLP1 Value -getParamValue params (TemplateParamConf paramName paramVal) = - maybe paramMissing return $ M.lookup paramName params <|> paramVal - where - paramMissing = throw400 InvalidParams $ - "missing parameter : " <>> paramName - -data QueryTProc - = QTPInsert !(R.InsertQueryP1, DS.Seq Q.PrepArg) - | QTPSelect !(R.AnnSimpleSel, DS.Seq Q.PrepArg) - | QTPUpdate !(R.AnnUpd, DS.Seq Q.PrepArg) - | QTPDelete !(R.AnnDel, DS.Seq Q.PrepArg) - | QTPCount !(RC.CountQueryP1, DS.Seq Q.PrepArg) - | QTPBulk ![QueryTProc] - deriving (Show, Eq) - -buildPrepArg - :: TemplateArgs - -> PGColType - -> Value - -> DMLP1 S.SQLExp -buildPrepArg args pct val = - case val of - Object _ -> do - tpc <- decodeValue val - v <- getParamValue args tpc - modifyErr (withParamErrMsg tpc) $ binRHSBuilder pct v - _ -> txtRHSBuilder pct val - where - withParamErrMsg tpc t = - "when processing parameter " <> tpcParam tpc <<> " : " <> t - -decodeIntValue :: TemplateArgs -> Value -> DMLP1 Int -decodeIntValue args val = - case val of - Object _ -> do - tpc <- decodeValue val - v <- getParamValue args tpc - decodeValue v - _ -> decodeValue val - -mkSelQWithArgs :: SelectQueryT -> TemplateArgs -> DMLP1 SelectQuery -mkSelQWithArgs (DMLQuery tn (SelectG c w o lim offset)) args = do - intLim <- mapM (decodeIntValue args) lim - intOffset <- mapM (decodeIntValue args) offset - return $ DMLQuery tn $ SelectG c w o intLim intOffset - -convQT - :: (UserInfoM m, QErrM m, CacheRM m, HasSQLGenCtx m) - => TemplateArgs - -> QueryT - -> m QueryTProc -convQT args qt = case qt of - QTInsert q -> - fmap QTPInsert $ liftDMLP1 $ - R.convInsertQuery decodeParam sessVarFromCurrentSetting binRHSBuilder q - QTSelect q -> - fmap QTPSelect $ liftDMLP1 $ mkSelQWithArgs q args - >>= R.convSelectQuery sessVarFromCurrentSetting f - QTUpdate q -> - fmap QTPUpdate $ liftDMLP1 $ - R.validateUpdateQueryWith sessVarFromCurrentSetting f q - QTDelete q -> - fmap QTPDelete $ liftDMLP1 $ - R.validateDeleteQWith sessVarFromCurrentSetting f q - QTCount q -> - fmap QTPCount $ liftDMLP1 $ - RC.validateCountQWith sessVarFromCurrentSetting f q - QTBulk q -> fmap QTPBulk $ mapM (convQT args) q - where - decodeParam val = do - tpc <- decodeValue val - v <- getParamValue args tpc - R.decodeInsObjs v - - f = buildPrepArg args - -execQueryTemplateP1 - :: (UserInfoM m, QErrM m, CacheRM m, HasSQLGenCtx m) - => ExecQueryTemplate -> m QueryTProc -execQueryTemplateP1 (ExecQueryTemplate qtn args) = do - (QueryTemplateInfo _ qt) <- askQTemplateInfo qtn - convQT args qt - -execQueryTP2 - :: (QErrM m, CacheRM m, MonadTx m, HasSQLGenCtx m) - => QueryTProc -> m EncJSON -execQueryTP2 qtProc = do - strfyNum <- stringifyNum <$> askSQLGenCtx - case qtProc of - QTPInsert qp -> liftTx $ R.insertP2 strfyNum qp - QTPSelect qp -> liftTx $ R.selectP2 False qp - QTPUpdate qp -> liftTx $ R.updateQueryToTx strfyNum qp - QTPDelete qp -> liftTx $ R.deleteQueryToTx strfyNum qp - QTPCount qp -> RC.countQToTx qp - QTPBulk qps -> encJFromList <$> mapM execQueryTP2 qps - -runExecQueryTemplate - :: ( QErrM m, UserInfoM m, CacheRM m - , MonadTx m, HasSQLGenCtx m - ) - => ExecQueryTemplate -> m EncJSON -runExecQueryTemplate q = - execQueryTemplateP1 q >>= execQueryTP2 diff --git a/server/src-lib/Hasura/RQL/Types.hs b/server/src-lib/Hasura/RQL/Types.hs index 593d46b940a18..4e83aa7a0679a 100644 --- a/server/src-lib/Hasura/RQL/Types.hs +++ b/server/src-lib/Hasura/RQL/Types.hs @@ -29,8 +29,6 @@ module Hasura.RQL.Types , askEventTriggerInfo , askTabInfoFromTrigger - , askQTemplateInfo - , adminOnly , HeaderObj @@ -85,8 +83,6 @@ mkAdminQCtx soc sc = QCtx adminUserInfo sc soc class (Monad m) => UserInfoM m where askUserInfo :: m UserInfo -type P1C m = (UserInfoM m, QErrM m, CacheRM m) - askTabInfo :: (QErrM m, CacheRM m) => QualifiedTable -> m TableInfo @@ -116,16 +112,6 @@ askEventTriggerInfo trn = do where errMsg = "event trigger " <> triggerNameToTxt trn <<> " does not exist" -askQTemplateInfo - :: (P1C m) - => TQueryName - -> m QueryTemplateInfo -askQTemplateInfo qtn = do - rawSchemaCache <- askSchemaCache - liftMaybe (err400 NotExists errMsg) $ M.lookup qtn $ scQTemplates rawSchemaCache - where - errMsg = "query-template " <> qtn <<> " does not exist" - instance UserInfoM P1 where askUserInfo = qcUserInfo <$> ask diff --git a/server/src-lib/Hasura/RQL/Types/Catalog.hs b/server/src-lib/Hasura/RQL/Types/Catalog.hs index 5e1072eddae63..2e6b53291399a 100644 --- a/server/src-lib/Hasura/RQL/Types/Catalog.hs +++ b/server/src-lib/Hasura/RQL/Types/Catalog.hs @@ -43,13 +43,6 @@ data CatalogPermission } deriving (Show, Eq) $(deriveJSON (aesonDrop 3 snakeCase) ''CatalogPermission) -data CatalogQueryTemplate - = CatalogQueryTemplate - { _cqtName :: !TQueryName - , _cqtDef :: !Value - } deriving (Show, Eq) -$(deriveJSON (aesonDrop 4 snakeCase) ''CatalogQueryTemplate) - data CatalogEventTrigger = CatalogEventTrigger { _cetTable :: !QualifiedTable @@ -70,7 +63,6 @@ data CatalogMetadata { _cmTables :: ![CatalogTable] , _cmRelations :: ![CatalogRelation] , _cmPermissions :: ![CatalogPermission] - , _cmQueryTemplates :: ![CatalogQueryTemplate] , _cmEventTriggers :: ![CatalogEventTrigger] , _cmRemoteSchemas :: ![AddRemoteSchemaQuery] , _cmFunctions :: ![CatalogFunction] diff --git a/server/src-lib/Hasura/RQL/Types/Common.hs b/server/src-lib/Hasura/RQL/Types/Common.hs index d05330ae28ddd..908262b708b87 100644 --- a/server/src-lib/Hasura/RQL/Types/Common.hs +++ b/server/src-lib/Hasura/RQL/Types/Common.hs @@ -11,9 +11,6 @@ module Hasura.RQL.Types.Common , fromPGCol , fromRel - , TQueryName(..) - , TemplateParam(..) - , ToAesonPairs(..) , WithTable(..) , ColVals @@ -146,24 +143,6 @@ fromPGCol (PGCol c) = FieldName c fromRel :: RelName -> FieldName fromRel = FieldName . relNameToTxt -newtype TQueryName - = TQueryName { getTQueryName :: NonEmptyText } - deriving ( Show, Eq, Hashable, FromJSONKey, ToJSONKey - , FromJSON, ToJSON, Q.ToPrepArg, Q.FromCol, Lift) - -instance IsIden TQueryName where - toIden (TQueryName r) = Iden $ unNonEmptyText r - -instance DQuote TQueryName where - dquoteTxt (TQueryName r) = unNonEmptyText r - -newtype TemplateParam - = TemplateParam { getTemplateParam :: T.Text } - deriving (Show, Eq, Hashable, FromJSON, FromJSONKey, ToJSONKey, ToJSON, Lift) - -instance DQuote TemplateParam where - dquoteTxt (TemplateParam r) = r - class ToAesonPairs a where toAesonPairs :: (KeyValue v) => a -> [v] diff --git a/server/src-lib/Hasura/RQL/Types/Metadata.hs b/server/src-lib/Hasura/RQL/Types/Metadata.hs index 3284a3d1fce23..41afd1d507140 100644 --- a/server/src-lib/Hasura/RQL/Types/Metadata.hs +++ b/server/src-lib/Hasura/RQL/Types/Metadata.hs @@ -15,7 +15,6 @@ data MetadataObjType = MOTTable | MOTRel !RelType | MOTPerm !PermType - | MOTQTemplate | MOTEventTrigger | MOTFunction | MOTRemoteSchema @@ -25,7 +24,6 @@ instance Show MetadataObjType where show MOTTable = "table" show (MOTRel ty) = T.unpack (relTypeToTxt ty) <> "_relation" show (MOTPerm ty) = show ty <> "_permission" - show MOTQTemplate = "query_template" show MOTEventTrigger = "event_trigger" show MOTFunction = "function" show MOTRemoteSchema = "remote_schema" @@ -43,7 +41,6 @@ instance Hashable TableMetadataObjId data MetadataObjId = MOTable !QualifiedTable - | MOQTemplate !TQueryName | MOFunction !QualifiedFunction | MORemoteSchema !RemoteSchemaName | MOTableObj !QualifiedTable !TableMetadataObjId diff --git a/server/src-lib/Hasura/RQL/Types/SchemaCache.hs b/server/src-lib/Hasura/RQL/Types/SchemaCache.hs index ae3d7b6c3ef29..d9ac834b9d8ac 100644 --- a/server/src-lib/Hasura/RQL/Types/SchemaCache.hs +++ b/server/src-lib/Hasura/RQL/Types/SchemaCache.hs @@ -73,11 +73,6 @@ module Hasura.RQL.Types.SchemaCache , delPermFromCache , PreSetColsPartial - , QueryTemplateInfo(..) - , addQTemplateToCache - , delQTemplateFromCache - , TemplateParamInfo(..) - , addEventTriggerToCache , delEventTriggerFromCache , EventTriggerInfo(..) @@ -112,7 +107,6 @@ import qualified Hasura.GraphQL.Context as GC import Hasura.Prelude import Hasura.RQL.Types.BoolExp import Hasura.RQL.Types.Common -import Hasura.RQL.Types.DML import Hasura.RQL.Types.Error import Hasura.RQL.Types.EventTrigger import Hasura.RQL.Types.Metadata @@ -142,16 +136,6 @@ mkColDep :: T.Text -> QualifiedTable -> PGCol -> SchemaDependency mkColDep reason tn col = flip SchemaDependency reason . SOTableObj tn $ TOCol col -data QueryTemplateInfo - = QueryTemplateInfo - { qtiName :: !TQueryName - , qtiQuery :: !QueryT - } deriving (Show, Eq) - -$(deriveToJSON (aesonDrop 3 snakeCase) ''QueryTemplateInfo) - -type QTemplateCache = M.HashMap TQueryName QueryTemplateInfo - onlyIntCols :: [PGColInfo] -> [PGColInfo] onlyIntCols = filter (isIntegerType . pgiType) @@ -460,7 +444,6 @@ data SchemaCache = SchemaCache { scTables :: !TableCache , scFunctions :: !FunctionCache - , scQTemplates :: !QTemplateCache , scRemoteSchemas :: !RemoteSchemaMap , scAllowlist :: !(HS.HashSet GQLQuery) , scGCtxMap :: !GC.GCtxMap @@ -497,41 +480,9 @@ class (CacheRM m) => CacheRWM m where instance (Monad m) => CacheRWM (StateT SchemaCache m) where writeSchemaCache = put -addQTemplateToCache - :: (QErrM m, CacheRWM m) - => QueryTemplateInfo - -> [SchemaDependency] - -> m () -addQTemplateToCache qti deps = do - sc <- askSchemaCache - let templateCache = scQTemplates sc - case M.lookup qtn templateCache of - Just _ -> throw500 $ "template already exists in cache " <>> qtn - Nothing -> do - let newTemplateCache = M.insert qtn qti templateCache - writeSchemaCache $ sc {scQTemplates = newTemplateCache} - modDepMapInCache (addToDepMap objId deps) - where - qtn = qtiName qti - objId = SOQTemplate qtn - -delQTemplateFromCache :: (QErrM m, CacheRWM m) - => TQueryName -> m () -delQTemplateFromCache qtn = do - sc <- askSchemaCache - let templateCache = scQTemplates sc - case M.lookup qtn templateCache of - Nothing -> throw500 $ "template does not exist in cache " <>> qtn - Just _ -> do - let newTemplateCache = M.delete qtn templateCache - writeSchemaCache $ sc {scQTemplates = newTemplateCache} - modDepMapInCache (removeFromDepMap objId) - where - objId = SOQTemplate qtn - emptySchemaCache :: SchemaCache emptySchemaCache = - SchemaCache M.empty M.empty M.empty M.empty + SchemaCache M.empty M.empty M.empty HS.empty M.empty GC.emptyGCtx mempty [] modTableCache :: (CacheRWM m) => TableCache -> m () @@ -801,12 +752,6 @@ delPermFromCache pa rn tn = do return $ ti { tiRolePermInfoMap = M.insert rn newRPI rpim } schObjId = SOTableObj tn $ TOPerm rn $ permAccToType pa -data TemplateParamInfo - = TemplateParamInfo - { tpiName :: !TemplateParam - , tpiDefault :: !(Maybe Value) - } deriving (Show, Eq) - addRemoteSchemaToCache :: (QErrM m, CacheRWM m) => RemoteSchemaCtx -> m () addRemoteSchemaToCache rmCtx = do diff --git a/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs b/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs index 0833504aa1283..7afc86e42a332 100644 --- a/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs +++ b/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs @@ -25,7 +25,6 @@ instance Hashable TableObjId data SchemaObjId = SOTable !QualifiedTable - | SOQTemplate !TQueryName | SOTableObj !QualifiedTable !TableObjId | SOFunction !QualifiedFunction deriving (Eq, Generic) @@ -35,8 +34,6 @@ instance Hashable SchemaObjId reportSchemaObj :: SchemaObjId -> T.Text reportSchemaObj (SOTable tn) = "table " <> qualObjectToText tn reportSchemaObj (SOFunction fn) = "function " <> qualObjectToText fn -reportSchemaObj (SOQTemplate qtn) = - "query-template " <> unNonEmptyText (getTQueryName qtn) reportSchemaObj (SOTableObj tn (TOCol cn)) = "column " <> qualObjectToText tn <> "." <> getPGColTxt cn reportSchemaObj (SOTableObj tn (TORel cn)) = diff --git a/server/src-lib/Hasura/Server/App.hs b/server/src-lib/Hasura/Server/App.hs index 502c392460e1b..229eed905d30c 100644 --- a/server/src-lib/Hasura/Server/App.hs +++ b/server/src-lib/Hasura/Server/App.hs @@ -4,7 +4,6 @@ module Hasura.Server.App where -import Control.Arrow ((***)) import Control.Concurrent.MVar import Control.Exception (IOException, try) import Data.Aeson hiding (json) @@ -47,7 +46,6 @@ import qualified Hasura.Server.PGDump as PGD import Hasura.EncJSON import Hasura.Prelude hiding (get, put) import Hasura.RQL.DDL.Schema.Table -import Hasura.RQL.DML.QueryTemplate import Hasura.RQL.Types import Hasura.Server.Auth (AuthMode (..), getUserInfo) @@ -515,10 +513,6 @@ httpApp corsCfg serverCtx enableConsole consoleAssetsDir enableTelemetry = do lazyBytes $ encode $ object [ "version" .= currentVersion ] when enableMetadata $ do - get ("v1/template" var) tmpltGetOrDeleteH - post ("v1/template" var) tmpltPutOrPostH - put ("v1/template" var) tmpltPutOrPostH - delete ("v1/template" var) tmpltGetOrDeleteH post "v1/query" $ mkSpockAction encodeQErr id serverCtx $ mkPostHandler $ mkAPIRespHandler v1QueryHandler @@ -585,36 +579,11 @@ httpApp corsCfg serverCtx enableConsole consoleAssetsDir enableTelemetry = do mkSpockAction encodeQErr id serverCtx $ mkPostHandler $ mkAPIRespHandler gqlExplainHandler - mkTmpltName tmpltText = - onNothing (mkNonEmptyText tmpltText) $ throw400 NotSupported "template name is empty string" - enableGraphQL = isGraphQLEnabled serverCtx enableMetadata = isMetadataEnabled serverCtx enablePGDump = isPGDumpEnabled serverCtx enableConfig = isConfigEnabled serverCtx - tmpltGetOrDeleteH tmpltText = do - tmpltArgs <- tmpltArgsFromQueryParams - mkSpockAction encodeQErr id serverCtx $ mkGetHandler $ do - tmpltName <- mkTmpltName tmpltText - JSONResp <$> mkQTemplateAction tmpltName tmpltArgs - - tmpltPutOrPostH tmpltText = do - tmpltArgs <- tmpltArgsFromQueryParams - mkSpockAction encodeQErr id serverCtx $ mkPostHandler $ - mkAPIRespHandler $ \bodyTmpltArgs -> do - tmpltName <- mkTmpltName tmpltText - mkQTemplateAction tmpltName $ M.union bodyTmpltArgs tmpltArgs - - tmpltArgsFromQueryParams = do - qparams <- params - return $ M.fromList $ flip map qparams $ - TemplateParam *** String - - mkQTemplateAction tmpltName tmpltArgs = - v1QueryHandler $ RQExecuteQueryTemplate $ - ExecQueryTemplate (TQueryName tmpltName) tmpltArgs - serveApiConsole = do -- redirect / to /console get root $ redirect "console" diff --git a/server/src-lib/Hasura/Server/Query.hs b/server/src-lib/Hasura/Server/Query.hs index c7f6e9c321b35..9640992dec937 100644 --- a/server/src-lib/Hasura/Server/Query.hs +++ b/server/src-lib/Hasura/Server/Query.hs @@ -13,7 +13,6 @@ import Hasura.RQL.DDL.EventTrigger import Hasura.RQL.DDL.Metadata import Hasura.RQL.DDL.Permission import Hasura.RQL.DDL.QueryCollection -import Hasura.RQL.DDL.QueryTemplate import Hasura.RQL.DDL.Relationship import Hasura.RQL.DDL.Relationship.Rename import Hasura.RQL.DDL.RemoteSchema @@ -22,7 +21,6 @@ import Hasura.RQL.DDL.Schema.Table import Hasura.RQL.DML.Count import Hasura.RQL.DML.Delete import Hasura.RQL.DML.Insert -import Hasura.RQL.DML.QueryTemplate import Hasura.RQL.DML.Select import Hasura.RQL.DML.Update import Hasura.RQL.Types @@ -76,11 +74,6 @@ data RQLQuery | RQRedeliverEvent !RedeliverEventQuery | RQInvokeEventTrigger !InvokeEventTriggerQuery - | RQCreateQueryTemplate !CreateQueryTemplate - | RQDropQueryTemplate !DropQueryTemplate - | RQExecuteQueryTemplate !ExecQueryTemplate - | RQSetQueryTemplateComment !SetQueryTemplateComment - -- query collections, allow list related | RQCreateQueryCollection !CreateCollection | RQDropQueryCollection !DropCollection @@ -222,11 +215,6 @@ queryNeedsReload qi = case qi of RQRedeliverEvent _ -> False RQInvokeEventTrigger _ -> False - RQCreateQueryTemplate _ -> True - RQDropQueryTemplate _ -> True - RQExecuteQueryTemplate _ -> False - RQSetQueryTemplateComment _ -> False - RQCreateQueryCollection _ -> True RQDropQueryCollection _ -> True RQAddQueryToCollection _ -> True @@ -299,11 +287,6 @@ runQueryM rq = RQRedeliverEvent q -> runRedeliverEvent q RQInvokeEventTrigger q -> runInvokeEventTrigger q - RQCreateQueryTemplate q -> runCreateQueryTemplate q - RQDropQueryTemplate q -> runDropQueryTemplate q - RQExecuteQueryTemplate q -> runExecQueryTemplate q - RQSetQueryTemplateComment q -> runSetQueryTemplateComment q - RQCreateQueryCollection q -> runCreateCollection q RQDropQueryCollection q -> runDropCollection q RQAddQueryToCollection q -> runAddQueryToCollection q diff --git a/server/src-rsr/catalog_metadata.sql b/server/src-rsr/catalog_metadata.sql index d08976a4a57f2..efed613b804ce 100644 --- a/server/src-rsr/catalog_metadata.sql +++ b/server/src-rsr/catalog_metadata.sql @@ -3,7 +3,6 @@ select 'tables', tables.items, 'relations', relations.items, 'permissions', permissions.items, - 'query_templates', query_templates.items, 'event_triggers', event_triggers.items, 'remote_schemas', remote_schemas.items, 'functions', functions.items, @@ -90,20 +89,6 @@ from from hdb_catalog.hdb_permission ) as permissions, - ( - select - coalesce( - json_agg( - json_build_object( - 'name', template_name, - 'def', template_defn :: json - ) - ), - '[]' - ) as items - from - hdb_catalog.hdb_query_template - ) as query_templates, ( select coalesce( diff --git a/server/src-rsr/hdb_metadata.yaml b/server/src-rsr/hdb_metadata.yaml index 80f2827b825bd..fe1146bcadb8b 100644 --- a/server/src-rsr/hdb_metadata.yaml +++ b/server/src-rsr/hdb_metadata.yaml @@ -175,11 +175,6 @@ args: table_schema : table_schema table_name : table_name -- type: add_existing_table_or_view - args: - schema: hdb_catalog - name: hdb_query_template - - type: add_existing_table_or_view args: schema: hdb_catalog diff --git a/server/src-rsr/initialise.sql b/server/src-rsr/initialise.sql index 5bad136224575..8807fe0d0ce9d 100644 --- a/server/src-rsr/initialise.sql +++ b/server/src-rsr/initialise.sql @@ -73,14 +73,6 @@ FROM GROUP BY table_schema, table_name, role_name; -CREATE TABLE hdb_catalog.hdb_query_template -( - template_name TEXT PRIMARY KEY, - template_defn JSONB NOT NULL, - comment TEXT NULL, - is_system_defined boolean default false -); - CREATE VIEW hdb_catalog.hdb_foreign_key_constraint AS SELECT q.table_schema :: text, diff --git a/server/tests-py/queries/v1/metadata/clear_metadata.yaml b/server/tests-py/queries/v1/metadata/clear_metadata.yaml index bb2500d07c94e..c073b585b6e90 100644 --- a/server/tests-py/queries/v1/metadata/clear_metadata.yaml +++ b/server/tests-py/queries/v1/metadata/clear_metadata.yaml @@ -14,7 +14,6 @@ allowlist: [] functions: [] query_collections: [] - query_templates: [] tables: [] remote_schemas: [] query: diff --git a/server/tests-py/queries/v1/metadata/export_metadata.yaml b/server/tests-py/queries/v1/metadata/export_metadata.yaml index c98e904b788c9..c7e4846e451eb 100644 --- a/server/tests-py/queries/v1/metadata/export_metadata.yaml +++ b/server/tests-py/queries/v1/metadata/export_metadata.yaml @@ -30,7 +30,6 @@ response: update_permissions: [] delete_permissions: [] event_triggers: [] - query_templates: [] query_collections: [] allowlist: [] functions: diff --git a/server/tests-py/queries/v1/metadata/replace_metadata.yaml b/server/tests-py/queries/v1/metadata/replace_metadata.yaml index c38481d80efdf..c9f41069e968b 100644 --- a/server/tests-py/queries/v1/metadata/replace_metadata.yaml +++ b/server/tests-py/queries/v1/metadata/replace_metadata.yaml @@ -6,7 +6,6 @@ response: query: type: replace_metadata args: - query_templates: [] remote_schemas: - name: test comment: testing replace metadata with remote schemas diff --git a/server/tests-py/queries/v1/metadata/replace_metadata_wo_rs.yaml b/server/tests-py/queries/v1/metadata/replace_metadata_wo_rs.yaml index ba3763239bf5d..3d30f26e2fec5 100644 --- a/server/tests-py/queries/v1/metadata/replace_metadata_wo_rs.yaml +++ b/server/tests-py/queries/v1/metadata/replace_metadata_wo_rs.yaml @@ -6,7 +6,6 @@ response: query: type: replace_metadata args: - query_templates: [] functions: - schema: public name: search_articles From 02ae91c64d3794fada2b1452e62acb8983dffbb3 Mon Sep 17 00:00:00 2001 From: Brandon Simmons Date: Wed, 24 Jul 2019 10:41:52 +0530 Subject: [PATCH 02/18] Increase idle GC interval to workaround CPU leak issue (#2581) This seems to resolve the issue locally (and has worked in the past), but it's not clear what exactly is going on here (in particular, why this should resolve what looks like a memory leak). It certainly seems like a GHC issue of some sort. Closes #2565 --- server/graphql-engine.cabal | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/graphql-engine.cabal b/server/graphql-engine.cabal index c6f1602e7d5f2..13d1606e51e79 100644 --- a/server/graphql-engine.cabal +++ b/server/graphql-engine.cabal @@ -362,4 +362,5 @@ executable graphql-engine -Wincomplete-uni-patterns -Wredundant-constraints -threaded -rtsopts - -with-rtsopts=-N + -- Re. `-I2` see #2565 + "-with-rtsopts=-N -I2" From 3445de36300d81292a12b8ec0361945588871c73 Mon Sep 17 00:00:00 2001 From: Rikin Kachhia Date: Wed, 24 Jul 2019 12:57:00 +0530 Subject: [PATCH 03/18] update console UI for RawSQL page / Migration page / Notifications (#2563) --- console/src/components/App/500-logo.png | Bin 7781 -> 0 bytes console/src/components/App/Actions.js | 32 +-- console/src/components/App/App.js | 74 +----- .../App/{progress-bar.scss => App.scss} | 7 - console/src/components/App/ErrorPage.scss | 47 ---- console/src/components/App/JSONFormat.js | 11 - console/src/components/App/State.js | 3 - .../components/Common/TableCommon/Table.scss | 14 -- console/src/components/Main/Main.js | 2 - .../components/Main/NotificationOverrides.css | 3 - .../Services/Common/Notification.js | 217 +++++++++--------- .../Common/Notification/Notification.scss | 1 + .../Notification/NotificationOverrides.css | 28 +++ .../components/Services/Data/Add/AddTable.js | 15 +- .../Services/Data/Add/AddWarning.js | 6 - .../Services/Data/Common/GraphQLValidation.js | 5 - .../components/Services/Data/DataActions.js | 6 +- .../Services/Data/Migrations/Migrations.js | 86 +++++++ .../Data/Migrations/MigrationsHome.js | 74 ------ .../Services/Data/RawSQL/Actions.js | 7 +- .../components/Services/Data/RawSQL/RawSQL.js | 91 ++++---- .../Services/Data/Schema/Actions.js | 2 +- .../Data/TableModify/ColumnCreator.js | 7 +- .../Data/TableModify/ModifyActions.js | 8 +- .../Data/TableRelationships/Actions.js | 5 +- .../TableRelationships/RelationshipEditor.js | 4 +- .../Data/TableRelationships/Relationships.js | 5 +- console/src/components/Services/Data/index.js | 2 +- .../Metadata/MetadataOptions/ResetMetadata.js | 10 +- 29 files changed, 304 insertions(+), 468 deletions(-) delete mode 100644 console/src/components/App/500-logo.png rename console/src/components/App/{progress-bar.scss => App.scss} (93%) delete mode 100644 console/src/components/App/ErrorPage.scss delete mode 100644 console/src/components/App/JSONFormat.js delete mode 100644 console/src/components/Main/NotificationOverrides.css create mode 100644 console/src/components/Services/Common/Notification/Notification.scss create mode 100644 console/src/components/Services/Common/Notification/NotificationOverrides.css create mode 100644 console/src/components/Services/Data/Migrations/Migrations.js delete mode 100644 console/src/components/Services/Data/Migrations/MigrationsHome.js diff --git a/console/src/components/App/500-logo.png b/console/src/components/App/500-logo.png deleted file mode 100644 index 9d556f0d973e1b1652321360643bcc441c5985a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7781 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 diff --git a/console/src/components/App/Actions.js b/console/src/components/App/Actions.js index 66ef1fd048aa5..ee0edce997f3d 100644 --- a/console/src/components/App/Actions.js +++ b/console/src/components/App/Actions.js @@ -1,5 +1,4 @@ import defaultState from './State'; -import jsonFormat from './JSONFormat'; import Notifications from 'react-notification-system-redux'; const LOAD_REQUEST = 'App/ONGOING_REQUEST'; @@ -7,9 +6,6 @@ const DONE_REQUEST = 'App/DONE_REQUEST'; const FAILED_REQUEST = 'App/FAILED_REQUEST'; const ERROR_REQUEST = 'App/ERROR_REQUEST'; const CONNECTION_FAILED = 'App/CONNECTION_FAILED'; -const CLOSE_MODAL = 'App/CLOSE_MODAL'; -const NOTIF_EXPANDED = 'App/NOTIF_EXPANDED'; -const NOTIF_MSG = 'App/NOTIF_MSG'; /** * Global notification function @@ -29,20 +25,19 @@ const NOTIF_MSG = 'App/NOTIF_MSG'; const showNotification = ({ level = 'info', position = 'tr', - json, ...options } = {}) => { return dispatch => { if (level === 'success') { dispatch(Notifications.removeAll()); } + dispatch( Notifications.show( { position, autoDismiss: ['error', 'warning'].includes(level) ? 0 : 5, dismissible: ['error', 'warning'].includes(level) ? 'button' : 'both', - children: json ? jsonFormat(json) : null, ...options, }, level @@ -51,9 +46,6 @@ const showNotification = ({ }; }; -const notifExpand = isExpanded => ({ type: NOTIF_EXPANDED, data: isExpanded }); -const notifMsg = finalMsg => ({ type: NOTIF_MSG, data: finalMsg }); - const progressBarReducer = (state = defaultState, action) => { switch (action.type) { case LOAD_REQUEST: @@ -103,24 +95,6 @@ const progressBarReducer = (state = defaultState, action) => { error: true, connectionFailed: true, }; - - case CLOSE_MODAL: - return { - ...state, - modalOpen: false, - }; - - case NOTIF_EXPANDED: - return { - ...state, - isNotifExpanded: action.data, - }; - case NOTIF_MSG: - return { - ...state, - notifMsg: action.data, - }; - default: return state; } @@ -132,10 +106,6 @@ export { DONE_REQUEST, FAILED_REQUEST, ERROR_REQUEST, - CLOSE_MODAL, CONNECTION_FAILED, - NOTIF_EXPANDED, - notifExpand, - notifMsg, showNotification, }; diff --git a/console/src/components/App/App.js b/console/src/components/App/App.js index 2c6dfc4fb76d0..7967d88a9d233 100644 --- a/console/src/components/App/App.js +++ b/console/src/components/App/App.js @@ -3,12 +3,7 @@ import React, { Component } from 'react'; import { connect } from 'react-redux'; import ProgressBar from 'react-progress-bar-plus'; import Notifications from 'react-notification-system-redux'; -import Modal from 'react-bootstrap/lib/Modal'; import { hot } from 'react-hot-loader'; -import './progress-bar.scss'; -import { NOTIF_EXPANDED } from './Actions'; -import AceEditor from 'react-ace'; -import 'brace/mode/json'; import ErrorBoundary from '../Error/ErrorBoundary'; import { telemetryNotificationShown } from '../../telemetry/Actions'; import { showTelemetryNotification } from '../../telemetry/Notifications'; @@ -22,12 +17,8 @@ class App extends Component { document.getElementById('loading').style.display = 'none'; } - onModalClose = () => { - this.props.dispatch({ type: NOTIF_EXPANDED, data: false }); - }; - render() { - const styles = require('./progress-bar.scss'); + const styles = require('./App.scss'); const { requestError, error, @@ -37,8 +28,6 @@ class App extends Component { children, notifications, connectionFailed, - isNotifExpanded, - notifMsg, telemetry, dispatch, metadata, @@ -48,29 +37,9 @@ class App extends Component { // console.error(requestError, error); } - const notificationStyle = { - Containers: { - DefaultStyle: { - width: '400px', - height: 'auto', - }, - }, - NotificationItem: { - DefaultStyle: { - height: 'auto', - }, - error: { - height: 'auto', - }, - }, - }; - if (isNotifExpanded) { - notificationStyle.Containers.DefaultStyle.width = '800px'; - } - - let hasuraCliDown = null; + let connectionFailMsg = null; if (connectionFailed) { - hasuraCliDown = ( + connectionFailMsg = (
- {hasuraCliDown} + {connectionFailMsg} {ongoingRequest && ( )}
{children}
- - - - Error - - -
-
-
- -
-
-
-
-
+
); @@ -146,7 +85,6 @@ App.propTypes = { reqData: PropTypes.object, statusCode: PropTypes.number, - modalOpen: PropTypes.bool, error: PropTypes.object, ongoingRequest: PropTypes.bool, requestError: PropTypes.bool, @@ -159,8 +97,6 @@ App.propTypes = { dispatch: PropTypes.func.isRequired, notifications: PropTypes.array, - isNotifExpanded: PropTypes.bool, - notifMsg: PropTypes.string, }; const mapStateToProps = state => { diff --git a/console/src/components/App/progress-bar.scss b/console/src/components/App/App.scss similarity index 93% rename from console/src/components/App/progress-bar.scss rename to console/src/components/App/App.scss index cacab44a5d448..df8d5b87734fc 100644 --- a/console/src/components/App/progress-bar.scss +++ b/console/src/components/App/App.scss @@ -1,12 +1,5 @@ @import "../Common/Common.scss"; -.notifModalDialog { - width: 800px; - margin: 30px auto; - right: 100px; - top: -15px; -} - :global { @keyframes react-progress-spinner { 0% { diff --git a/console/src/components/App/ErrorPage.scss b/console/src/components/App/ErrorPage.scss deleted file mode 100644 index bc49f6931b342..0000000000000 --- a/console/src/components/App/ErrorPage.scss +++ /dev/null @@ -1,47 +0,0 @@ -.container { - padding: 0; -} - -.viewContainer { - height: 100vh; - width: 100vw; - display: table; - - .centerContent{ - display: table-cell; - vertical-align: middle; - - .message { - padding: 50px 20%; - } - - .message h1 { - font-size: 54px; - font-weight: bold; - } - - .message p { - margin-left: 15px; - } - - .message p > a { - font-weight: bold; - } - } -} - -.header { - background: #eee; - - h2 { - margin: 0; - padding: 26px; - float: left; - line-height: 26px; - } - - .nav { - padding: 20px; - float: left; - } -} diff --git a/console/src/components/App/JSONFormat.js b/console/src/components/App/JSONFormat.js deleted file mode 100644 index ac6f89ab35aa7..0000000000000 --- a/console/src/components/App/JSONFormat.js +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; - -const jsonFormat = json => { - return ( -
-
{JSON.stringify(json, null, 2)}
-
- ); -}; - -export default jsonFormat; diff --git a/console/src/components/App/State.js b/console/src/components/App/State.js index 6e20a547b3034..43c920a0dabb4 100644 --- a/console/src/components/App/State.js +++ b/console/src/components/App/State.js @@ -4,9 +4,6 @@ const defaultState = { ongoingRequest: false, requestSuccess: null, requestError: null, - modalOpen: false, error: null, - isNotifExpanded: false, - notifMsg: null, }; export default defaultState; diff --git a/console/src/components/Common/TableCommon/Table.scss b/console/src/components/Common/TableCommon/Table.scss index ec7207b30b2cf..9a3b2e2a8f699 100644 --- a/console/src/components/Common/TableCommon/Table.scss +++ b/console/src/components/Common/TableCommon/Table.scss @@ -31,20 +31,6 @@ } } -.aceBlock { - max-height: 300px; - position: relative; - margin-top: 10px; -} - -.aceBlockExpand { - position: absolute; - top: -25px; - right: 5px; - z-index: 1; - cursor: pointer; -} - .viewRowsContainer { border-left: 1px solid #ddd; } diff --git a/console/src/components/Main/Main.js b/console/src/components/Main/Main.js index b8cc94d50641d..219266253c25b 100644 --- a/console/src/components/Main/Main.js +++ b/console/src/components/Main/Main.js @@ -4,7 +4,6 @@ import { Link } from 'react-router'; import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger'; import globals from '../../Globals'; import * as tooltip from './Tooltips'; -import 'react-toggle/style.css'; import Spinner from '../Common/Spinner/Spinner'; import { loadServerVersion, @@ -13,7 +12,6 @@ import { featureCompatibilityInit, } from './Actions'; import { loadConsoleTelemetryOpts } from '../../telemetry/Actions.js'; -import './NotificationOverrides.css'; import { loadInconsistentObjects, redirectToMetadataStatus, diff --git a/console/src/components/Main/NotificationOverrides.css b/console/src/components/Main/NotificationOverrides.css deleted file mode 100644 index 3ee43d193905f..0000000000000 --- a/console/src/components/Main/NotificationOverrides.css +++ /dev/null @@ -1,3 +0,0 @@ -.notifications-wrapper .notification { - height: auto !important; -} diff --git a/console/src/components/Services/Common/Notification.js b/console/src/components/Services/Common/Notification.js index ecaf587da69ff..3d1b7595b752f 100644 --- a/console/src/components/Services/Common/Notification.js +++ b/console/src/components/Services/Common/Notification.js @@ -1,107 +1,125 @@ import React from 'react'; import AceEditor from 'react-ace'; import { showNotification } from '../../App/Actions'; -import { notifExpand, notifMsg } from '../../App/Actions'; import Button from '../../Common/Button/Button'; -const styles = require('../../Common/TableCommon/Table.scss'); +import './Notification/NotificationOverrides.css'; + +const styles = require('./Notification/Notification.scss'); + +const getNotificationDetails = (detailsJson, children = null) => { + return ( +
+ + {children} +
+ ); +}; const showErrorNotification = (title, message, error) => { - let modMessage; - let refreshBtn; - - if ( - error && - error.message && - (error.message.error === 'postgres query error' || - error.message.error === 'query execution failed') - ) { - if (error.message.internal) { - modMessage = - error.message.code + ': ' + error.message.internal.error.message; - } else { - modMessage = error.code + ': ' + error.message.error; - } - } else if (error && 'info' in error) { - modMessage = error.info; - } else if (error && 'message' in error) { - if (error.code) { - if (error.message.error) { - modMessage = error.message.error.message; + const getErrorMessage = () => { + let notificationMessage; + if ( + error && + error.message && + (error.message.error === 'postgres query error' || + error.message.error === 'query execution failed') + ) { + if (error.message.internal) { + notificationMessage = + error.message.code + ': ' + error.message.internal.error.message; } else { - modMessage = error.message; + notificationMessage = error.code + ': ' + error.message.error; } - } else if (error && error.message && 'code' in error.message) { - modMessage = error.message.code + ' : ' + message; + } else if (error && 'info' in error) { + notificationMessage = error.info; + } else if (error && 'message' in error) { + if (error.code) { + if (error.message.error) { + notificationMessage = error.message.error.message; + } else { + notificationMessage = error.message; + } + } else if (error && error.message && 'code' in error.message) { + notificationMessage = error.message.code + ' : ' + message; + } else { + notificationMessage = error.code; + } + } else if (error && 'internal' in error && 'error' in error.internal) { + notificationMessage = error.code + ' : ' + error.internal.error.message; + } else if (error && 'custom' in error) { + notificationMessage = error.custom; + } else if ( + error && + 'code' in error && + 'error' in error && + 'path' in error + ) { + // Data API error + notificationMessage = error.error; } else { - modMessage = error.code; + notificationMessage = error ? error : message; } - } else if (error && 'internal' in error && 'error' in error.internal) { - modMessage = error.code + ' : ' + error.internal.error.message; - } else if (error && 'custom' in error) { - modMessage = error.custom; - } else if (error && 'code' in error && 'error' in error && 'path' in error) { - // Data API error - modMessage = error.error; - } else { - modMessage = error ? error : message; - } - let finalJson = error ? error.message : null; - - if (error && 'action' in error) { - refreshBtn = ( - - ); - finalJson = error.action; - } else if (error && 'internal' in error) { - finalJson = error.internal; - } + return notificationMessage; + }; - return dispatch => { - const expandClicked = finalMsg => { - // trigger a modal with a bigger view - dispatch(notifExpand(true)); - dispatch(notifMsg(JSON.stringify(finalMsg, null, 4))); - }; + const getRefreshBtn = () => { + let refreshBtn; + if (error && 'action' in error) { + refreshBtn = ( + + ); + } + + return refreshBtn; + }; + + const getErrorJson = () => { + let errorJson; + + if (error && 'action' in error) { + errorJson = error.action; + } else if (error && 'internal' in error) { + errorJson = error.internal; + } else if (error && 'message' in error) { + errorJson = error.message; + } + return errorJson; + }; + + const errorMessage = getErrorMessage(); + const errorJson = getErrorJson(); + + return dispatch => { const getNotificationAction = () => { let action = null; - if (finalJson) { - const notification = [ -
- { - e.preventDefault(); - expandClicked(finalJson); - }} - className={styles.aceBlockExpand + ' fa fa-expand'} - /> - - {refreshBtn} -
, + if (errorJson) { + const errorDetails = [ + getNotificationDetails(errorJson, getRefreshBtn()), ]; action = { @@ -110,10 +128,10 @@ const showErrorNotification = (title, message, error) => { dispatch( showNotification({ level: 'error', + position: 'br', // HACK: to avoid expansion of existing notifications title, - message: modMessage, - dismissible: 'button', - children: notification, + message: errorMessage, + children: errorDetails, }) ); }, @@ -127,7 +145,7 @@ const showErrorNotification = (title, message, error) => { showNotification({ level: 'error', title, - message: modMessage, + message: errorMessage, action: getNotificationAction(), }) ); @@ -160,22 +178,7 @@ const showInfoNotification = title => { const showWarningNotification = (title, message, dataObj) => { const children = []; if (dataObj) { - children.push( -
- -
- ); + children.push(getNotificationDetails(dataObj)); } return dispatch => { diff --git a/console/src/components/Services/Common/Notification/Notification.scss b/console/src/components/Services/Common/Notification/Notification.scss new file mode 100644 index 0000000000000..f6f31885698a9 --- /dev/null +++ b/console/src/components/Services/Common/Notification/Notification.scss @@ -0,0 +1 @@ +@import "../../../Common/Common.scss"; diff --git a/console/src/components/Services/Common/Notification/NotificationOverrides.css b/console/src/components/Services/Common/Notification/NotificationOverrides.css new file mode 100644 index 0000000000000..afa8231d32e88 --- /dev/null +++ b/console/src/components/Services/Common/Notification/NotificationOverrides.css @@ -0,0 +1,28 @@ +.notifications-wrapper .notification { + height: auto !important; + width: auto !important; +} + +.notifications-wrapper .notifications-tr, +.notifications-wrapper .notifications-br { + width: auto !important; +} + +/* make position same as tr */ +.notifications-wrapper .notifications-br { + top: 0px !important; + bottom: auto !important; + left: auto !important; + right: 0px !important; +} + +.notifications-wrapper .notification > * { + width: 400px; +} + +.notifications-wrapper .notification .notification-details { + width: 75vw; + max-height: 300px; + position: relative; + margin-top: 10px; +} diff --git a/console/src/components/Services/Data/Add/AddTable.js b/console/src/components/Services/Data/Add/AddTable.js index 50df2aafca570..b080e4ee14dba 100644 --- a/console/src/components/Services/Data/Add/AddTable.js +++ b/console/src/components/Services/Data/Add/AddTable.js @@ -166,19 +166,15 @@ class AddTable extends Component { showErrorNotification( notificationArray[0], notificationArray[1], - notificationArray[2], - notificationArray[3] + notificationArray[2] ) ); return false; } else if (typeof validated === 'string') { this.props.dispatch( - showErrorNotification( - notificationArray[0], - validated, - notificationArray[2], - { custom: validated } - ) + showErrorNotification(notificationArray[0], validated, { + custom: validated, + }) ); return false; } else if (typeof validated === 'object') { @@ -186,8 +182,7 @@ class AddTable extends Component { showErrorNotification( notificationArray[0], notificationArray[1], - notificationArray[2], - notificationArray[3] + notificationArray[2] ) ); return false; diff --git a/console/src/components/Services/Data/Add/AddWarning.js b/console/src/components/Services/Data/Add/AddWarning.js index 6ffbc8ad73366..c7bd7e47372f3 100644 --- a/console/src/components/Services/Data/Add/AddWarning.js +++ b/console/src/components/Services/Data/Add/AddWarning.js @@ -1,7 +1,6 @@ const tableColumnNoDups = [ 'Error adding column', 'Column name is duplicated', - '', { custom: 'Column name is duplicated', }, @@ -10,7 +9,6 @@ const tableColumnNoDups = [ const tableMinPrimaryKey = [ 'Error adding table', 'A primary key is required', - '', { custom: 'A primary key is required', }, @@ -19,7 +17,6 @@ const tableMinPrimaryKey = [ const tableNameNullNotif = [ 'Error creating table!', 'Table name cannot be empty', - '', { custom: 'Table name cannot be empty. Please add a name', }, @@ -28,7 +25,6 @@ const tableNameNullNotif = [ const tableEnufColumns = [ 'Error creating table!', 'Table must have at least one column', - '', { custom: 'Table must have at least one column.', }, @@ -37,7 +33,6 @@ const tableEnufColumns = [ const tableColumnDefaults = [ 'Error creating table!', 'Default value is invalid', - '', { custom: 'Default value is invalid', }, @@ -46,7 +41,6 @@ const tableColumnDefaults = [ const tableColumnTypes = [ 'Error creating table!', 'Column type is invalid', - '', { custom: 'Column type is invalid', }, diff --git a/console/src/components/Services/Data/Common/GraphQLValidation.js b/console/src/components/Services/Data/Common/GraphQLValidation.js index f1b79799c3d9c..ef0292339c9dc 100644 --- a/console/src/components/Services/Data/Common/GraphQLValidation.js +++ b/console/src/components/Services/Data/Common/GraphQLValidation.js @@ -3,7 +3,6 @@ const gqlPattern = /^[_A-Za-z][_0-9A-Za-z]*$/; const gqlTableErrorNotif = [ 'Error creating table!', 'Table name cannot contain special characters', - '', { custom: 'Table name cannot contain special characters. It can have alphabets, numbers and _ (cannot start with numbers)', @@ -14,7 +13,6 @@ const gqlTableErrorNotif = [ const gqlColumnErrorNotif = [ 'Error adding column!', 'Column name cannot contain special characters', - '', { custom: 'Column name cannot contain special characters. It can have alphabets, numbers and _ (cannot start with numbers)', @@ -25,7 +23,6 @@ const gqlColumnErrorNotif = [ const gqlViewErrorNotif = [ 'Error creating view!', 'View name cannot contain special characters', - '', { custom: 'View name cannot contain special characters. It can have alphabets, numbers and _ (cannot start with numbers)', @@ -36,7 +33,6 @@ const gqlViewErrorNotif = [ const gqlRelErrorNotif = [ 'Error adding relationship!', 'Relationship name cannot contain special characters', - '', { custom: 'Relationship name cannot contain special characters. It can have alphabets, numbers and _ (cannot start with numbers)', @@ -47,7 +43,6 @@ const gqlRelErrorNotif = [ const gqlSchemaErrorNotif = [ 'Error creating schema!', 'Schema name cannot contain special characters', - '', { custom: 'Schema name cannot contain special characters. It can have alphabets, numbers and _ (cannot start with numbers)', diff --git a/console/src/components/Services/Data/DataActions.js b/console/src/components/Services/Data/DataActions.js index 45d927da325f7..e4cd7403bc0c5 100644 --- a/console/src/components/Services/Data/DataActions.js +++ b/console/src/components/Services/Data/DataActions.js @@ -584,11 +584,7 @@ const fetchColumnTypeInfo = () => { }, error => { dispatch( - showErrorNotification( - 'Error fetching column types', - 'Kindly reach out to us in case you face this issue again', - error - ) + showErrorNotification('Error fetching column types', null, error) ); return dispatch({ type: FETCH_COLUMN_TYPE_INFO_FAIL, diff --git a/console/src/components/Services/Data/Migrations/Migrations.js b/console/src/components/Services/Data/Migrations/Migrations.js new file mode 100644 index 0000000000000..d00054c991f19 --- /dev/null +++ b/console/src/components/Services/Data/Migrations/Migrations.js @@ -0,0 +1,86 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Helmet from 'react-helmet'; + +import Toggle from 'react-toggle'; +import 'react-toggle/style.css'; +import '../../../Common/ReactToggle/ReactToggleOverrides.css'; + +import { updateMigrationModeStatus } from '../../../Main/Actions'; + +const Migrations = ({ dispatch, migrationMode }) => { + const styles = require('./Migrations.scss'); + + const handleMigrationModeToggle = () => { + const isConfirm = window.confirm('Are you sure?'); + if (isConfirm) { + dispatch(updateMigrationModeStatus()); + } + }; + + const getNotesSection = () => { + return ( +
    +
  • Migrations are used to track changes to the database schema.
  • +
  • + If you are managing database migrations externally, it is recommended + that you disable making schema changes via the console. +
  • +
  • + Read more about managing migrations with Hasura at the{' '} + + Hasura migrations guide + +
  • +
+ ); + }; + + return ( +
+ +
+

+ Database Migrations +

+
+
+
+
+ {getNotesSection()} +
+
+
+ +
+
+
+ ); +}; + +Migrations.propTypes = { + dispatch: PropTypes.func.isRequired, + migrationMode: PropTypes.bool.isRequired, +}; + +const mapStateToProps = state => ({ + ...state.rawSQL, + migrationMode: state.main.migrationMode, +}); + +const migrationsConnector = connect => connect(mapStateToProps)(Migrations); + +export default migrationsConnector; diff --git a/console/src/components/Services/Data/Migrations/MigrationsHome.js b/console/src/components/Services/Data/Migrations/MigrationsHome.js deleted file mode 100644 index 0803c47672ca9..0000000000000 --- a/console/src/components/Services/Data/Migrations/MigrationsHome.js +++ /dev/null @@ -1,74 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import Helmet from 'react-helmet'; -import 'brace/mode/sql'; - -import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger'; -import Tooltip from 'react-bootstrap/lib/Tooltip'; -import Toggle from 'react-toggle'; -import '../../../Common/ReactToggle/ReactToggleOverrides.css'; - -import { updateMigrationModeStatus } from '../../../Main/Actions'; - -const MigrationsHome = ({ dispatch, migrationMode }) => { - const styles = require('./Migrations.scss'); - - const handleMigrationModeToggle = () => { - const isConfirm = window.confirm('Are you sure?'); - if (isConfirm) { - dispatch(updateMigrationModeStatus()); - } - }; - - const migrationTip = ( - - Modifications to the underlying postgres schema should be tracked as - migrations. - - ); - - return ( -
- -
- -