2020-03-31 17:00:12 +03:00
|
|
|
|
{-# LANGUAGE RecordWildCards #-}
|
2018-06-27 16:11:32 +03:00
|
|
|
|
module Hasura.RQL.DDL.Metadata
|
2019-12-14 09:47:38 +03:00
|
|
|
|
( runReplaceMetadata
|
2018-12-13 10:26:15 +03:00
|
|
|
|
, runExportMetadata
|
2020-11-12 12:25:48 +03:00
|
|
|
|
, fetchMetadataFromHdbTables
|
2018-12-13 10:26:15 +03:00
|
|
|
|
, runClearMetadata
|
|
|
|
|
, runReloadMetadata
|
|
|
|
|
, runDumpInternalState
|
2019-04-17 19:29:39 +03:00
|
|
|
|
, runGetInconsistentMetadata
|
|
|
|
|
, runDropInconsistentMetadata
|
2019-12-14 09:47:38 +03:00
|
|
|
|
|
|
|
|
|
, module Hasura.RQL.DDL.Metadata.Types
|
2018-06-27 16:11:32 +03:00
|
|
|
|
) where
|
|
|
|
|
|
2020-10-27 16:53:49 +03:00
|
|
|
|
import Hasura.Prelude
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
2019-12-14 09:47:38 +03:00
|
|
|
|
import qualified Data.Aeson.Ordered as AO
|
2020-11-12 12:25:48 +03:00
|
|
|
|
import qualified Data.HashMap.Strict as HM
|
2019-11-06 05:11:03 +03:00
|
|
|
|
import qualified Data.HashMap.Strict.InsOrd as HMIns
|
2019-04-17 19:29:39 +03:00
|
|
|
|
import qualified Data.HashSet as HS
|
2020-11-12 12:25:48 +03:00
|
|
|
|
import qualified Data.HashSet.InsOrd as HSIns
|
2019-04-17 19:29:39 +03:00
|
|
|
|
import qualified Data.List as L
|
2020-10-27 16:53:49 +03:00
|
|
|
|
import qualified Database.PG.Query as Q
|
|
|
|
|
|
|
|
|
|
import Control.Lens hiding ((.=))
|
|
|
|
|
import Data.Aeson
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
2020-10-27 16:53:49 +03:00
|
|
|
|
import qualified Hasura.RQL.DDL.Action as Action
|
|
|
|
|
import qualified Hasura.RQL.DDL.ComputedField as ComputedField
|
|
|
|
|
import qualified Hasura.RQL.DDL.CustomTypes as CustomTypes
|
|
|
|
|
import qualified Hasura.RQL.DDL.Permission as Permission
|
|
|
|
|
import qualified Hasura.RQL.DDL.QueryCollection as Collection
|
|
|
|
|
import qualified Hasura.RQL.DDL.Relationship as Relationship
|
|
|
|
|
import qualified Hasura.RQL.DDL.RemoteRelationship as RemoteRelationship
|
|
|
|
|
import qualified Hasura.RQL.DDL.Schema as Schema
|
|
|
|
|
|
|
|
|
|
import Hasura.Backends.Postgres.SQL.Types
|
2019-03-18 19:22:21 +03:00
|
|
|
|
import Hasura.EncJSON
|
2019-11-06 05:11:03 +03:00
|
|
|
|
import Hasura.RQL.DDL.ComputedField (dropComputedFieldFromCatalog)
|
2020-11-12 12:25:48 +03:00
|
|
|
|
import Hasura.RQL.DDL.EventTrigger (delEventTriggerFromCatalog,
|
|
|
|
|
replaceEventTriggersInCatalog)
|
2020-01-23 00:55:55 +03:00
|
|
|
|
import Hasura.RQL.DDL.Metadata.Types
|
2019-11-06 05:11:03 +03:00
|
|
|
|
import Hasura.RQL.DDL.Permission.Internal (dropPermFromCatalog)
|
2020-11-12 12:25:48 +03:00
|
|
|
|
import Hasura.RQL.DDL.RemoteSchema (addRemoteSchemaToCatalog,
|
2019-12-13 00:46:33 +03:00
|
|
|
|
removeRemoteSchemaFromCatalog)
|
2020-05-13 15:33:16 +03:00
|
|
|
|
import Hasura.RQL.DDL.ScheduledTrigger (addCronTriggerToCatalog,
|
|
|
|
|
deleteCronTriggerFromCatalog)
|
2020-03-31 17:00:12 +03:00
|
|
|
|
import Hasura.RQL.DDL.Schema.Catalog (saveTableToCatalog)
|
2018-06-27 16:11:32 +03:00
|
|
|
|
import Hasura.RQL.Types
|
|
|
|
|
|
2020-03-31 17:00:12 +03:00
|
|
|
|
-- | Purge all user-defined metadata; metadata with is_system_defined = false
|
|
|
|
|
clearUserMetadata :: MonadTx m => m ()
|
|
|
|
|
clearUserMetadata = liftTx $ Q.catchE defaultTxErrorHandler $ do
|
2020-11-12 12:25:48 +03:00
|
|
|
|
-- Note: we don’t drop event triggers here because we update them a different
|
|
|
|
|
-- way; see Note [Diff-and-patch event triggers on replace] in Hasura.RQL.DDL.EventTrigger.
|
2019-01-25 06:31:54 +03:00
|
|
|
|
Q.unitQ "DELETE FROM hdb_catalog.hdb_function WHERE is_system_defined <> 'true'" () False
|
2018-06-27 16:11:32 +03:00
|
|
|
|
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
|
2019-11-07 17:39:48 +03:00
|
|
|
|
Q.unitQ "DELETE FROM hdb_catalog.hdb_computed_field" () False
|
2020-05-27 18:02:58 +03:00
|
|
|
|
Q.unitQ "DELETE FROM hdb_catalog.hdb_remote_relationship" () False
|
2019-03-01 16:59:24 +03:00
|
|
|
|
Q.unitQ "DELETE FROM hdb_catalog.hdb_table WHERE is_system_defined <> 'true'" () False
|
2018-11-23 16:02:46 +03:00
|
|
|
|
Q.unitQ "DELETE FROM hdb_catalog.remote_schemas" () False
|
2019-05-16 09:13:25 +03:00
|
|
|
|
Q.unitQ "DELETE FROM hdb_catalog.hdb_allowlist" () False
|
|
|
|
|
Q.unitQ "DELETE FROM hdb_catalog.hdb_query_collection WHERE is_system_defined <> 'true'" () False
|
2020-02-13 20:38:23 +03:00
|
|
|
|
Q.unitQ "DELETE FROM hdb_catalog.hdb_custom_types" () False
|
|
|
|
|
Q.unitQ "DELETE FROM hdb_catalog.hdb_action_permission" () False
|
|
|
|
|
Q.unitQ "DELETE FROM hdb_catalog.hdb_action WHERE is_system_defined <> 'true'" () False
|
2020-05-13 15:33:16 +03:00
|
|
|
|
Q.unitQ "DELETE FROM hdb_catalog.hdb_cron_triggers WHERE include_in_metadata" () False
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
2018-12-13 10:26:15 +03:00
|
|
|
|
runClearMetadata
|
2019-11-20 21:21:30 +03:00
|
|
|
|
:: (MonadTx m, CacheRWM m)
|
2019-03-18 19:22:21 +03:00
|
|
|
|
=> ClearMetadata -> m EncJSON
|
2018-12-13 10:26:15 +03:00
|
|
|
|
runClearMetadata _ = do
|
2020-03-31 17:00:12 +03:00
|
|
|
|
clearUserMetadata
|
2020-11-12 12:25:48 +03:00
|
|
|
|
replaceEventTriggersInCatalog mempty
|
2019-11-20 21:21:30 +03:00
|
|
|
|
buildSchemaCacheStrict
|
2018-12-13 10:26:15 +03:00
|
|
|
|
return successMsg
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
2020-11-12 12:25:48 +03:00
|
|
|
|
saveMetadata :: (MonadTx m, HasSystemDefined m) => Metadata -> m ()
|
|
|
|
|
saveMetadata (Metadata tables functions
|
2020-05-13 15:33:16 +03:00
|
|
|
|
schemas collections allowlist customTypes actions cronTriggers) = do
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
|
|
|
|
withPathK "tables" $ do
|
2020-11-12 12:25:48 +03:00
|
|
|
|
indexedForM_ tables $ \TableMetadata{..} -> do
|
2020-03-31 17:00:12 +03:00
|
|
|
|
-- Save table
|
|
|
|
|
saveTableToCatalog _tmTable _tmIsEnum _tmConfiguration
|
|
|
|
|
|
2019-11-07 17:39:48 +03:00
|
|
|
|
-- Relationships
|
2018-06-27 16:11:32 +03:00
|
|
|
|
withPathK "object_relationships" $
|
2020-03-31 17:00:12 +03:00
|
|
|
|
indexedForM_ _tmObjectRelationships $ \objRel ->
|
|
|
|
|
Relationship.insertRelationshipToCatalog _tmTable ObjRel objRel
|
2018-06-27 16:11:32 +03:00
|
|
|
|
withPathK "array_relationships" $
|
2020-03-31 17:00:12 +03:00
|
|
|
|
indexedForM_ _tmArrayRelationships $ \arrRel ->
|
|
|
|
|
Relationship.insertRelationshipToCatalog _tmTable ArrRel arrRel
|
|
|
|
|
|
2019-11-07 17:39:48 +03:00
|
|
|
|
-- Computed Fields
|
|
|
|
|
withPathK "computed_fields" $
|
2020-03-31 17:00:12 +03:00
|
|
|
|
indexedForM_ _tmComputedFields $
|
2020-11-12 12:25:48 +03:00
|
|
|
|
\(ComputedFieldMetadata name definition comment) ->
|
2019-11-20 21:21:30 +03:00
|
|
|
|
ComputedField.addComputedFieldToCatalog $
|
2020-03-31 17:00:12 +03:00
|
|
|
|
ComputedField.AddComputedField _tmTable name definition comment
|
|
|
|
|
|
2020-05-27 18:02:58 +03:00
|
|
|
|
-- Remote Relationships
|
|
|
|
|
withPathK "remote_relationships" $
|
|
|
|
|
indexedForM_ _tmRemoteRelationships $
|
2020-11-12 12:25:48 +03:00
|
|
|
|
\(RemoteRelationshipMetadata name def) -> do
|
2020-05-27 18:02:58 +03:00
|
|
|
|
let RemoteRelationshipDef rs hf rf = def
|
|
|
|
|
liftTx $ RemoteRelationship.persistRemoteRelationship $
|
|
|
|
|
RemoteRelationship name _tmTable hf rs rf
|
|
|
|
|
|
2020-03-31 17:00:12 +03:00
|
|
|
|
-- Permissions
|
|
|
|
|
withPathK "insert_permissions" $ processPerms _tmTable _tmInsertPermissions
|
|
|
|
|
withPathK "select_permissions" $ processPerms _tmTable _tmSelectPermissions
|
|
|
|
|
withPathK "update_permissions" $ processPerms _tmTable _tmUpdatePermissions
|
|
|
|
|
withPathK "delete_permissions" $ processPerms _tmTable _tmDeletePermissions
|
|
|
|
|
|
2020-11-12 12:25:48 +03:00
|
|
|
|
-- Event triggers
|
|
|
|
|
let allEventTriggers = HMIns.elems tables & map \table ->
|
|
|
|
|
(_tmTable table,) <$> HMIns.toHashMap (_tmEventTriggers table)
|
|
|
|
|
replaceEventTriggersInCatalog $ HM.unions allEventTriggers
|
2018-09-05 14:26:46 +03:00
|
|
|
|
|
2019-01-25 06:31:54 +03:00
|
|
|
|
-- sql functions
|
2020-11-12 12:25:48 +03:00
|
|
|
|
withPathK "functions" $ indexedForM_ functions $
|
|
|
|
|
\(FunctionMetadata function config) -> Schema.saveFunctionToCatalog function config
|
2019-01-25 06:31:54 +03:00
|
|
|
|
|
2019-05-16 09:13:25 +03:00
|
|
|
|
-- query collections
|
2020-01-14 10:09:10 +03:00
|
|
|
|
systemDefined <- askSystemDefined
|
2019-05-16 09:13:25 +03:00
|
|
|
|
withPathK "query_collections" $
|
2019-11-20 09:47:06 +03:00
|
|
|
|
indexedForM_ collections $ \c -> liftTx $ Collection.addCollectionToCatalog c systemDefined
|
2019-05-16 09:13:25 +03:00
|
|
|
|
|
|
|
|
|
-- allow list
|
2020-11-25 17:18:58 +03:00
|
|
|
|
withPathK "allowlist" $
|
2019-11-20 21:21:30 +03:00
|
|
|
|
indexedForM_ allowlist $ \(Collection.CollectionReq name) ->
|
|
|
|
|
liftTx $ Collection.addCollectionToAllowlistCatalog name
|
2019-05-16 09:13:25 +03:00
|
|
|
|
|
2018-11-27 14:26:10 +03:00
|
|
|
|
-- remote schemas
|
2019-12-14 09:47:38 +03:00
|
|
|
|
withPathK "remote_schemas" $
|
2020-03-31 17:00:12 +03:00
|
|
|
|
indexedMapM_ (liftTx . addRemoteSchemaToCatalog) schemas
|
2019-04-17 19:29:39 +03:00
|
|
|
|
|
2020-03-31 17:00:12 +03:00
|
|
|
|
-- custom types
|
|
|
|
|
withPathK "custom_types" $
|
|
|
|
|
CustomTypes.persistCustomTypes customTypes
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
2020-05-13 15:33:16 +03:00
|
|
|
|
-- cron triggers
|
|
|
|
|
withPathK "cron_triggers" $
|
2020-11-25 17:18:58 +03:00
|
|
|
|
indexedForM_ cronTriggers $ \ct -> liftTx $
|
2020-05-13 15:33:16 +03:00
|
|
|
|
addCronTriggerToCatalog ct
|
|
|
|
|
|
2020-03-31 17:00:12 +03:00
|
|
|
|
-- actions
|
|
|
|
|
withPathK "actions" $
|
|
|
|
|
indexedForM_ actions $ \action -> do
|
|
|
|
|
let createAction =
|
|
|
|
|
CreateAction (_amName action) (_amDefinition action) (_amComment action)
|
|
|
|
|
Action.persistCreateAction createAction
|
|
|
|
|
withPathK "permissions" $
|
|
|
|
|
indexedForM_ (_amPermissions action) $ \permission -> do
|
|
|
|
|
let createActionPermission = CreateActionPermission (_amName action)
|
|
|
|
|
(_apmRole permission) Nothing (_apmComment permission)
|
|
|
|
|
Action.persistCreateActionPermission createActionPermission
|
2020-05-13 15:33:16 +03:00
|
|
|
|
|
2018-06-27 16:11:32 +03:00
|
|
|
|
where
|
2020-03-31 17:00:12 +03:00
|
|
|
|
processPerms tableName perms = indexedForM_ perms $ Permission.addPermP2 tableName
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
2018-12-13 10:26:15 +03:00
|
|
|
|
runReplaceMetadata
|
2020-03-31 17:00:12 +03:00
|
|
|
|
:: ( MonadTx m
|
2019-11-20 21:21:30 +03:00
|
|
|
|
, CacheRWM m
|
2019-10-11 08:13:57 +03:00
|
|
|
|
, HasSystemDefined m
|
2019-03-01 14:45:04 +03:00
|
|
|
|
)
|
2020-11-12 12:25:48 +03:00
|
|
|
|
=> Metadata -> m EncJSON
|
|
|
|
|
runReplaceMetadata metadata = do
|
|
|
|
|
clearUserMetadata
|
|
|
|
|
saveMetadata metadata
|
|
|
|
|
buildSchemaCacheStrict
|
|
|
|
|
pure successMsg
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
2020-11-12 12:25:48 +03:00
|
|
|
|
fetchMetadataFromHdbTables :: MonadTx m => m Metadata
|
|
|
|
|
fetchMetadataFromHdbTables = liftTx do
|
2018-06-27 16:11:32 +03:00
|
|
|
|
tables <- Q.catchE defaultTxErrorHandler fetchTables
|
2019-11-06 05:11:03 +03:00
|
|
|
|
let tableMetaMap = HMIns.fromList . flip map tables $
|
2019-09-19 07:47:36 +03:00
|
|
|
|
\(schema, name, isEnum, maybeConfig) ->
|
|
|
|
|
let qualifiedName = QualifiedObject schema name
|
|
|
|
|
configuration = maybe emptyTableConfig Q.getAltJ maybeConfig
|
|
|
|
|
in (qualifiedName, mkTableMeta qualifiedName isEnum configuration)
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
|
|
|
|
-- Fetch all the relationships
|
|
|
|
|
relationships <- Q.catchE defaultTxErrorHandler fetchRelationships
|
|
|
|
|
|
|
|
|
|
objRelDefs <- mkRelDefs ObjRel relationships
|
|
|
|
|
arrRelDefs <- mkRelDefs ArrRel relationships
|
|
|
|
|
|
|
|
|
|
-- Fetch all the permissions
|
|
|
|
|
permissions <- Q.catchE defaultTxErrorHandler fetchPermissions
|
|
|
|
|
|
|
|
|
|
-- Parse all the permissions
|
|
|
|
|
insPermDefs <- mkPermDefs PTInsert permissions
|
|
|
|
|
selPermDefs <- mkPermDefs PTSelect permissions
|
|
|
|
|
updPermDefs <- mkPermDefs PTUpdate permissions
|
|
|
|
|
delPermDefs <- mkPermDefs PTDelete permissions
|
|
|
|
|
|
2018-09-05 14:26:46 +03:00
|
|
|
|
-- Fetch all event triggers
|
|
|
|
|
eventTriggers <- Q.catchE defaultTxErrorHandler fetchEventTriggers
|
|
|
|
|
triggerMetaDefs <- mkTriggerMetaDefs eventTriggers
|
|
|
|
|
|
2019-11-07 17:39:48 +03:00
|
|
|
|
-- Fetch all computed fields
|
|
|
|
|
computedFields <- fetchComputedFields
|
|
|
|
|
|
2020-05-27 18:02:58 +03:00
|
|
|
|
-- Fetch all remote relationships
|
|
|
|
|
remoteRelationships <- Q.catchE defaultTxErrorHandler fetchRemoteRelationships
|
|
|
|
|
|
2020-11-12 12:25:48 +03:00
|
|
|
|
let (_, fullTableMetaMap) = flip runState tableMetaMap $ do
|
|
|
|
|
modMetaMap tmObjectRelationships _rdName objRelDefs
|
|
|
|
|
modMetaMap tmArrayRelationships _rdName arrRelDefs
|
|
|
|
|
modMetaMap tmInsertPermissions _pdRole insPermDefs
|
|
|
|
|
modMetaMap tmSelectPermissions _pdRole selPermDefs
|
|
|
|
|
modMetaMap tmUpdatePermissions _pdRole updPermDefs
|
|
|
|
|
modMetaMap tmDeletePermissions _pdRole delPermDefs
|
|
|
|
|
modMetaMap tmEventTriggers etcName triggerMetaDefs
|
|
|
|
|
modMetaMap tmComputedFields _cfmName computedFields
|
|
|
|
|
modMetaMap tmRemoteRelationships _rrmName remoteRelationships
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
2019-01-25 06:31:54 +03:00
|
|
|
|
-- fetch all functions
|
2020-11-12 12:25:48 +03:00
|
|
|
|
functions <- Q.catchE defaultTxErrorHandler fetchFunctions
|
2019-01-25 06:31:54 +03:00
|
|
|
|
|
2020-05-27 18:02:58 +03:00
|
|
|
|
-- fetch all remote schemas
|
2020-11-12 12:25:48 +03:00
|
|
|
|
remoteSchemas <- oMapFromL _arsqName <$> fetchRemoteSchemas
|
2018-11-23 16:02:46 +03:00
|
|
|
|
|
2019-05-16 09:13:25 +03:00
|
|
|
|
-- fetch all collections
|
2020-11-12 12:25:48 +03:00
|
|
|
|
collections <- oMapFromL _ccName <$> fetchCollections
|
2019-05-16 09:13:25 +03:00
|
|
|
|
|
|
|
|
|
-- fetch allow list
|
2020-11-12 12:25:48 +03:00
|
|
|
|
allowlist <- HSIns.fromList . map CollectionReq <$> fetchAllowlists
|
2019-05-16 09:13:25 +03:00
|
|
|
|
|
2020-02-13 20:38:23 +03:00
|
|
|
|
customTypes <- fetchCustomTypes
|
|
|
|
|
|
2020-11-12 12:25:48 +03:00
|
|
|
|
-- fetch actions
|
|
|
|
|
actions <- oMapFromL _amName <$> fetchActions
|
2020-02-13 20:38:23 +03:00
|
|
|
|
|
2020-05-13 15:33:16 +03:00
|
|
|
|
cronTriggers <- fetchCronTriggers
|
|
|
|
|
|
2020-11-12 12:25:48 +03:00
|
|
|
|
pure $ Metadata fullTableMetaMap functions remoteSchemas collections
|
|
|
|
|
allowlist customTypes actions cronTriggers
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
|
|
|
|
where
|
2020-11-12 12:25:48 +03:00
|
|
|
|
modMetaMap l f xs = do
|
2018-06-27 16:11:32 +03:00
|
|
|
|
st <- get
|
2020-11-12 12:25:48 +03:00
|
|
|
|
put $ foldl' (\b (qt, dfn) -> b & at qt._Just.l %~ HMIns.insert (f dfn) dfn) st xs
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
|
|
|
|
mkPermDefs pt = mapM permRowToDef . filter (\pr -> pr ^. _4 == pt)
|
|
|
|
|
|
|
|
|
|
permRowToDef (sn, tn, rn, _, Q.AltJ pDef, mComment) = do
|
|
|
|
|
perm <- decodeValue pDef
|
2020-11-12 12:25:48 +03:00
|
|
|
|
return (QualifiedObject sn tn, PermDef rn perm mComment)
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
|
|
|
|
mkRelDefs rt = mapM relRowToDef . filter (\rr -> rr ^. _4 == rt)
|
|
|
|
|
|
|
|
|
|
relRowToDef (sn, tn, rn, _, Q.AltJ rDef, mComment) = do
|
|
|
|
|
using <- decodeValue rDef
|
2020-11-12 12:25:48 +03:00
|
|
|
|
return (QualifiedObject sn tn, RelDef rn using mComment)
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
2018-09-05 14:26:46 +03:00
|
|
|
|
mkTriggerMetaDefs = mapM trigRowToDef
|
|
|
|
|
|
2018-11-14 10:13:01 +03:00
|
|
|
|
trigRowToDef (sn, tn, Q.AltJ configuration) = do
|
|
|
|
|
conf <- decodeValue configuration
|
2019-01-25 06:31:54 +03:00
|
|
|
|
return (QualifiedObject sn tn, conf::EventTriggerConf)
|
2018-09-05 14:26:46 +03:00
|
|
|
|
|
2018-06-27 16:11:32 +03:00
|
|
|
|
fetchTables =
|
|
|
|
|
Q.listQ [Q.sql|
|
2019-09-19 07:47:36 +03:00
|
|
|
|
SELECT table_schema, table_name, is_enum, configuration::json
|
|
|
|
|
FROM hdb_catalog.hdb_table
|
2018-06-27 16:11:32 +03:00
|
|
|
|
WHERE is_system_defined = 'false'
|
2019-11-06 05:11:03 +03:00
|
|
|
|
ORDER BY table_schema ASC, table_name ASC
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|] () False
|
|
|
|
|
|
|
|
|
|
fetchRelationships =
|
|
|
|
|
Q.listQ [Q.sql|
|
|
|
|
|
SELECT table_schema, table_name, rel_name, rel_type, rel_def::json, comment
|
|
|
|
|
FROM hdb_catalog.hdb_relationship
|
|
|
|
|
WHERE is_system_defined = 'false'
|
2019-11-06 05:11:03 +03:00
|
|
|
|
ORDER BY table_schema ASC, table_name ASC, rel_name ASC
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|] () False
|
|
|
|
|
|
|
|
|
|
fetchPermissions =
|
|
|
|
|
Q.listQ [Q.sql|
|
|
|
|
|
SELECT table_schema, table_name, role_name, perm_type, perm_def::json, comment
|
|
|
|
|
FROM hdb_catalog.hdb_permission
|
|
|
|
|
WHERE is_system_defined = 'false'
|
2019-11-06 05:11:03 +03:00
|
|
|
|
ORDER BY table_schema ASC, table_name ASC, role_name ASC, perm_type ASC
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|] () False
|
|
|
|
|
|
2018-09-05 14:26:46 +03:00
|
|
|
|
fetchEventTriggers =
|
|
|
|
|
Q.listQ [Q.sql|
|
2018-11-14 10:13:01 +03:00
|
|
|
|
SELECT e.schema_name, e.table_name, e.configuration::json
|
2018-09-05 14:26:46 +03:00
|
|
|
|
FROM hdb_catalog.event_triggers e
|
2019-11-06 05:11:03 +03:00
|
|
|
|
ORDER BY e.schema_name ASC, e.table_name ASC, e.name ASC
|
2018-09-05 14:26:46 +03:00
|
|
|
|
|] () False
|
2019-10-21 19:01:05 +03:00
|
|
|
|
|
2019-11-20 09:47:06 +03:00
|
|
|
|
fetchFunctions = do
|
|
|
|
|
l <- Q.listQ [Q.sql|
|
|
|
|
|
SELECT function_schema, function_name, configuration::json
|
2019-01-25 06:31:54 +03:00
|
|
|
|
FROM hdb_catalog.hdb_function
|
|
|
|
|
WHERE is_system_defined = 'false'
|
2019-11-06 05:11:03 +03:00
|
|
|
|
ORDER BY function_schema ASC, function_name ASC
|
2019-01-25 06:31:54 +03:00
|
|
|
|
|] () False
|
2020-11-12 12:25:48 +03:00
|
|
|
|
pure $ oMapFromL _fmFunction $
|
|
|
|
|
flip map l $ \(sn, fn, Q.AltJ config) ->
|
|
|
|
|
FunctionMetadata (QualifiedObject sn fn) config
|
|
|
|
|
|
|
|
|
|
fetchRemoteSchemas =
|
|
|
|
|
map fromRow <$> Q.listQE defaultTxErrorHandler
|
|
|
|
|
[Q.sql|
|
|
|
|
|
SELECT name, definition, comment
|
|
|
|
|
FROM hdb_catalog.remote_schemas
|
|
|
|
|
ORDER BY name ASC
|
|
|
|
|
|] () True
|
|
|
|
|
where
|
|
|
|
|
fromRow (name, Q.AltJ def, comment) =
|
|
|
|
|
AddRemoteSchemaQuery name def comment
|
|
|
|
|
|
2018-09-05 14:26:46 +03:00
|
|
|
|
|
2019-11-06 05:11:03 +03:00
|
|
|
|
fetchCollections =
|
|
|
|
|
map fromRow <$> Q.listQE defaultTxErrorHandler [Q.sql|
|
2019-10-21 19:01:05 +03:00
|
|
|
|
SELECT collection_name, collection_defn::json, comment
|
|
|
|
|
FROM hdb_catalog.hdb_query_collection
|
|
|
|
|
WHERE is_system_defined = 'false'
|
2019-11-06 05:11:03 +03:00
|
|
|
|
ORDER BY collection_name ASC
|
2019-10-21 19:01:05 +03:00
|
|
|
|
|] () False
|
2019-11-06 05:11:03 +03:00
|
|
|
|
where
|
|
|
|
|
fromRow (name, Q.AltJ defn, mComment) =
|
2020-11-12 12:25:48 +03:00
|
|
|
|
CreateCollection name defn mComment
|
2019-11-06 05:11:03 +03:00
|
|
|
|
|
|
|
|
|
fetchAllowlists = map runIdentity <$>
|
|
|
|
|
Q.listQE defaultTxErrorHandler [Q.sql|
|
|
|
|
|
SELECT collection_name
|
|
|
|
|
FROM hdb_catalog.hdb_allowlist
|
|
|
|
|
ORDER BY collection_name ASC
|
|
|
|
|
|] () False
|
|
|
|
|
|
2019-11-07 17:39:48 +03:00
|
|
|
|
fetchComputedFields = do
|
|
|
|
|
r <- Q.listQE defaultTxErrorHandler [Q.sql|
|
|
|
|
|
SELECT table_schema, table_name, computed_field_name,
|
|
|
|
|
definition::json, comment
|
|
|
|
|
FROM hdb_catalog.hdb_computed_field
|
|
|
|
|
|] () False
|
|
|
|
|
pure $ flip map r $ \(schema, table, name, Q.AltJ definition, comment) ->
|
|
|
|
|
( QualifiedObject schema table
|
2020-11-12 12:25:48 +03:00
|
|
|
|
, ComputedFieldMetadata name definition comment
|
2019-11-07 17:39:48 +03:00
|
|
|
|
)
|
|
|
|
|
|
2020-05-13 15:33:16 +03:00
|
|
|
|
fetchCronTriggers =
|
2020-11-12 12:25:48 +03:00
|
|
|
|
(oMapFromL ctName . map uncurryCronTrigger)
|
2020-05-13 15:33:16 +03:00
|
|
|
|
<$> Q.listQE defaultTxErrorHandler
|
|
|
|
|
[Q.sql|
|
|
|
|
|
SELECT ct.name, ct.webhook_conf, ct.cron_schedule, ct.payload,
|
|
|
|
|
ct.retry_conf, ct.header_conf, ct.include_in_metadata, ct.comment
|
|
|
|
|
FROM hdb_catalog.hdb_cron_triggers ct
|
|
|
|
|
WHERE include_in_metadata
|
|
|
|
|
|] () False
|
|
|
|
|
where
|
|
|
|
|
uncurryCronTrigger
|
|
|
|
|
(name, webhook, schedule, payload, retryConfig, headerConfig, includeMetadata, comment) =
|
|
|
|
|
CronTriggerMetadata
|
|
|
|
|
{ ctName = name,
|
|
|
|
|
ctWebhook = Q.getAltJ webhook,
|
|
|
|
|
ctSchedule = schedule,
|
|
|
|
|
ctPayload = Q.getAltJ <$> payload,
|
|
|
|
|
ctRetryConf = Q.getAltJ retryConfig,
|
|
|
|
|
ctHeaders = Q.getAltJ headerConfig,
|
|
|
|
|
ctIncludeInMetadata = includeMetadata,
|
|
|
|
|
ctComment = comment
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-13 20:38:23 +03:00
|
|
|
|
fetchCustomTypes :: Q.TxE QErr CustomTypes
|
|
|
|
|
fetchCustomTypes =
|
|
|
|
|
Q.getAltJ . runIdentity . Q.getRow <$>
|
|
|
|
|
Q.rawQE defaultTxErrorHandler [Q.sql|
|
|
|
|
|
select coalesce((select custom_types::json from hdb_catalog.hdb_custom_types), '{}'::json)
|
|
|
|
|
|] [] False
|
2020-11-12 12:25:48 +03:00
|
|
|
|
|
2020-02-13 20:38:23 +03:00
|
|
|
|
fetchActions =
|
|
|
|
|
Q.getAltJ . runIdentity . Q.getRow <$> Q.rawQE defaultTxErrorHandler [Q.sql|
|
|
|
|
|
select
|
|
|
|
|
coalesce(
|
|
|
|
|
json_agg(
|
|
|
|
|
json_build_object(
|
|
|
|
|
'name', a.action_name,
|
|
|
|
|
'definition', a.action_defn,
|
|
|
|
|
'comment', a.comment,
|
|
|
|
|
'permissions', ap.permissions
|
|
|
|
|
) order by a.action_name asc
|
|
|
|
|
),
|
|
|
|
|
'[]'
|
|
|
|
|
)
|
|
|
|
|
from
|
|
|
|
|
hdb_catalog.hdb_action as a
|
|
|
|
|
left outer join lateral (
|
|
|
|
|
select
|
|
|
|
|
coalesce(
|
|
|
|
|
json_agg(
|
|
|
|
|
json_build_object(
|
|
|
|
|
'role', ap.role_name,
|
|
|
|
|
'comment', ap.comment
|
|
|
|
|
) order by ap.role_name asc
|
|
|
|
|
),
|
|
|
|
|
'[]'
|
|
|
|
|
) as permissions
|
|
|
|
|
from
|
|
|
|
|
hdb_catalog.hdb_action_permission ap
|
|
|
|
|
where
|
|
|
|
|
ap.action_name = a.action_name
|
|
|
|
|
) ap on true;
|
|
|
|
|
|] [] False
|
|
|
|
|
|
2020-05-27 18:02:58 +03:00
|
|
|
|
fetchRemoteRelationships = do
|
|
|
|
|
r <- Q.listQ [Q.sql|
|
|
|
|
|
SELECT table_schema, table_name,
|
|
|
|
|
remote_relationship_name, definition::json
|
|
|
|
|
FROM hdb_catalog.hdb_remote_relationship
|
|
|
|
|
|] () False
|
|
|
|
|
pure $ flip map r $ \(schema, table, name, Q.AltJ definition) ->
|
|
|
|
|
( QualifiedObject schema table
|
2020-11-12 12:25:48 +03:00
|
|
|
|
, RemoteRelationshipMetadata name definition
|
2020-05-27 18:02:58 +03:00
|
|
|
|
)
|
|
|
|
|
|
2018-12-13 10:26:15 +03:00
|
|
|
|
runExportMetadata
|
2019-11-26 15:14:21 +03:00
|
|
|
|
:: (QErrM m, MonadTx m)
|
2019-03-18 19:22:21 +03:00
|
|
|
|
=> ExportMetadata -> m EncJSON
|
2019-11-26 15:14:21 +03:00
|
|
|
|
runExportMetadata _ =
|
2020-11-12 12:25:48 +03:00
|
|
|
|
AO.toEncJSON . metadataToOrdJSON <$> fetchMetadataFromHdbTables
|
2018-09-05 18:25:30 +03:00
|
|
|
|
|
2019-11-20 21:21:30 +03:00
|
|
|
|
runReloadMetadata :: (QErrM m, CacheRWM m) => ReloadMetadata -> m EncJSON
|
2020-03-26 14:52:20 +03:00
|
|
|
|
runReloadMetadata (ReloadMetadata reloadRemoteSchemas) = do
|
|
|
|
|
sc <- askSchemaCache
|
|
|
|
|
let remoteSchemaInvalidations =
|
|
|
|
|
if reloadRemoteSchemas then HS.fromList (getAllRemoteSchemas sc) else mempty
|
|
|
|
|
buildSchemaCacheWithOptions CatalogUpdate CacheInvalidations
|
|
|
|
|
{ ciMetadata = True
|
|
|
|
|
, ciRemoteSchemas = remoteSchemaInvalidations
|
|
|
|
|
}
|
|
|
|
|
pure successMsg
|
2018-09-05 18:25:30 +03:00
|
|
|
|
|
2018-12-13 10:26:15 +03:00
|
|
|
|
runDumpInternalState
|
2019-11-26 15:14:21 +03:00
|
|
|
|
:: (QErrM m, CacheRM m)
|
2019-03-18 19:22:21 +03:00
|
|
|
|
=> DumpInternalState -> m EncJSON
|
2019-11-26 15:14:21 +03:00
|
|
|
|
runDumpInternalState _ =
|
2019-03-18 19:22:21 +03:00
|
|
|
|
encJFromJValue <$> askSchemaCache
|
2019-04-17 19:29:39 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
runGetInconsistentMetadata
|
2019-11-26 15:14:21 +03:00
|
|
|
|
:: (QErrM m, CacheRM m)
|
2019-04-17 19:29:39 +03:00
|
|
|
|
=> GetInconsistentMetadata -> m EncJSON
|
|
|
|
|
runGetInconsistentMetadata _ = do
|
|
|
|
|
inconsObjs <- scInconsistentObjs <$> askSchemaCache
|
|
|
|
|
return $ encJFromJValue $ object
|
|
|
|
|
[ "is_consistent" .= null inconsObjs
|
|
|
|
|
, "inconsistent_objects" .= inconsObjs
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
runDropInconsistentMetadata
|
2019-11-26 15:14:21 +03:00
|
|
|
|
:: (QErrM m, CacheRWM m, MonadTx m)
|
2019-04-17 19:29:39 +03:00
|
|
|
|
=> DropInconsistentMetadata -> m EncJSON
|
|
|
|
|
runDropInconsistentMetadata _ = do
|
|
|
|
|
sc <- askSchemaCache
|
2019-11-27 01:49:42 +03:00
|
|
|
|
let inconsSchObjs = L.nub . concatMap imObjectIds $ scInconsistentObjs sc
|
2019-11-20 21:21:30 +03:00
|
|
|
|
-- Note: when building the schema cache, we try to put dependents after their dependencies in the
|
|
|
|
|
-- list of inconsistent objects, so reverse the list to start with dependents first. This is not
|
|
|
|
|
-- perfect — a completely accurate solution would require performing a topological sort — but it
|
|
|
|
|
-- seems to work well enough for now.
|
|
|
|
|
mapM_ purgeMetadataObj (reverse inconsSchObjs)
|
|
|
|
|
buildSchemaCacheStrict
|
2019-04-17 19:29:39 +03:00
|
|
|
|
return successMsg
|
|
|
|
|
|
|
|
|
|
purgeMetadataObj :: MonadTx m => MetadataObjId -> m ()
|
|
|
|
|
purgeMetadataObj = liftTx . \case
|
2020-10-27 16:53:49 +03:00
|
|
|
|
MOTable qt -> Schema.deleteTableFromCatalog qt
|
|
|
|
|
MOFunction qf -> Schema.delFunctionFromCatalog qf
|
|
|
|
|
MORemoteSchema rsn -> removeRemoteSchemaFromCatalog rsn
|
|
|
|
|
MOTableObj qt (MTORel rn _) -> Relationship.delRelFromCatalog qt rn
|
|
|
|
|
MOTableObj qt (MTOPerm rn pt) -> dropPermFromCatalog qt rn pt
|
|
|
|
|
MOTableObj _ (MTOTrigger trn) -> delEventTriggerFromCatalog trn
|
|
|
|
|
MOTableObj qt (MTOComputedField ccn) -> dropComputedFieldFromCatalog qt ccn
|
|
|
|
|
MOTableObj qt (MTORemoteRelationship rn) -> RemoteRelationship.delRemoteRelFromCatalog qt rn
|
|
|
|
|
MOCustomTypes -> CustomTypes.clearCustomTypes
|
|
|
|
|
MOAction action -> Action.deleteActionFromCatalog action Nothing
|
|
|
|
|
MOActionPermission action role -> Action.deleteActionPermissionFromCatalog action role
|
|
|
|
|
MOCronTrigger ctName -> deleteCronTriggerFromCatalog ctName
|