/* Read-only verification for the module architecture cutover. */ SET NOCOUNT ON; IF DB_NAME() <> N'FMS' THROW 53500, N'This verification can only run against the FMS database.', 1; IF EXISTS ( SELECT required.name FROM (VALUES (N's_module'), (N's_module_page'), (N's_module_data'), (N's_module_report'), (N's_module_dashboard'), (N's_module_workflow'), (N's_function_node'), (N's_page_node'), (N's_module_profile'), (N's_module_field'), (N's_module_field_list'), (N's_module_field_form'), (N's_module_field_query'), (N's_module_action'), (N's_module_relation'), (N'b_role'), (N'b_user_role'), (N'b_role_data_scope') ) AS required(name) LEFT JOIN sys.tables AS actual ON actual.name = required.name AND actual.schema_id = SCHEMA_ID(N'dbo') WHERE actual.object_id IS NULL ) THROW 53501, N'Required module architecture tables are missing.', 1; IF EXISTS ( SELECT required.name FROM (VALUES (N'v_s_function_node'), (N'v_s_page_node'), (N'v_s_module_runtime'), (N'v_s_module_profile'), (N'v_s_module_action'), (N'v_s_user_function_permission'), (N'v_s_user_page_permission'), (N'v_s_user_action_permission') ) AS required(name) LEFT JOIN sys.views AS actual ON actual.name = required.name AND actual.schema_id = SCHEMA_ID(N'dbo') WHERE actual.object_id IS NULL ) THROW 53502, N'Required module runtime views are missing.', 1; IF EXISTS ( SELECT 1 FROM (VALUES (N's_module_field_edit'), (N's_module_power'), (N'b_user_module'), (N'b_user_power'), (N'b_other_bmfl') ) AS legacy(name) INNER JOIN sys.tables AS actual ON actual.name = legacy.name AND actual.schema_id = SCHEMA_ID(N'dbo') ) THROW 53503, N'Legacy module metadata tables still exist.', 1; IF EXISTS ( SELECT 1 FROM dbo.s_module AS module_row LEFT JOIN dbo.s_module_page AS page_row ON page_row.b_module_id = module_row.b_id LEFT JOIN dbo.s_module_data AS data_row ON data_row.b_module_id = module_row.b_id LEFT JOIN dbo.s_module_report AS report_row ON report_row.b_module_id = module_row.b_id LEFT JOIN dbo.s_module_dashboard AS dashboard_row ON dashboard_row.b_module_id = module_row.b_id LEFT JOIN dbo.s_module_workflow AS workflow_row ON workflow_row.b_module_id = module_row.b_id WHERE (CASE WHEN page_row.b_module_id IS NULL THEN 0 ELSE 1 END + CASE WHEN data_row.b_module_id IS NULL THEN 0 ELSE 1 END + CASE WHEN report_row.b_module_id IS NULL THEN 0 ELSE 1 END + CASE WHEN dashboard_row.b_module_id IS NULL THEN 0 ELSE 1 END + CASE WHEN workflow_row.b_module_id IS NULL THEN 0 ELSE 1 END) <> 1 OR (module_row.b_module_type = 'page' AND page_row.b_module_id IS NULL) OR (module_row.b_module_type = 'data' AND data_row.b_module_id IS NULL) OR (module_row.b_module_type = 'report' AND report_row.b_module_id IS NULL) OR (module_row.b_module_type = 'dashboard' AND dashboard_row.b_module_id IS NULL) OR (module_row.b_module_type = 'workflow' AND workflow_row.b_module_id IS NULL) ) THROW 53504, N'Module subtype records are incomplete or conflicting.', 1; IF EXISTS ( SELECT 1 FROM dbo.s_module AS module_row LEFT JOIN dbo.s_module_profile AS profile_row ON profile_row.b_module_id = module_row.b_id AND profile_row.b_default = 1 WHERE module_row.b_module_type = 'data' AND profile_row.b_id IS NULL ) THROW 53505, N'A data module has no default profile.', 1; IF EXISTS ( SELECT 1 FROM dbo.s_module_profile AS profile_row INNER JOIN dbo.s_module AS module_row ON module_row.b_id = profile_row.b_module_id WHERE module_row.b_module_type <> 'data' ) THROW 53506, N'A profile belongs to a non-data module.', 1; IF EXISTS ( SELECT 1 FROM dbo.s_function_node AS child INNER JOIN dbo.s_function_node AS parent_row ON parent_row.b_id = child.b_parent_id WHERE parent_row.b_node_type <> 'directory' ) THROW 53507, N'A function node is placed below a non-directory node.', 1; IF EXISTS ( SELECT 1 FROM dbo.s_page_node AS child INNER JOIN dbo.s_page_node AS parent_row ON parent_row.b_page_module_id = child.b_page_module_id AND parent_row.b_id = child.b_parent_id WHERE parent_row.b_node_type = 'module_ref' ) THROW 53508, N'A page node is placed below a module reference.', 1; DECLARE @FunctionCycle bit = 0; ;WITH function_tree AS ( SELECT b_id AS origin_id, b_parent_id AS current_id, CAST(N'/' + CONVERT(nvarchar(30), b_id) + N'/' AS nvarchar(max)) AS visited FROM dbo.s_function_node WHERE b_parent_id IS NOT NULL UNION ALL SELECT tree.origin_id, parent_row.b_parent_id, tree.visited + CONVERT(nvarchar(30), parent_row.b_id) + N'/' FROM function_tree AS tree INNER JOIN dbo.s_function_node AS parent_row ON parent_row.b_id = tree.current_id WHERE tree.current_id IS NOT NULL AND tree.visited NOT LIKE N'%/' + CONVERT(nvarchar(30), parent_row.b_id) + N'/%' ) SELECT TOP (1) @FunctionCycle = 1 FROM function_tree WHERE current_id = origin_id OPTION (MAXRECURSION 32767); IF @FunctionCycle = 1 THROW 53509, N'The function tree contains a cycle.', 1; DECLARE @PageCycle bit = 0; ;WITH page_tree AS ( SELECT b_page_module_id AS page_id, b_id AS origin_id, b_parent_id AS current_id, CAST(N'/' + CONVERT(nvarchar(30), b_id) + N'/' AS nvarchar(max)) AS visited FROM dbo.s_page_node WHERE b_parent_id IS NOT NULL UNION ALL SELECT tree.page_id, tree.origin_id, parent_row.b_parent_id, tree.visited + CONVERT(nvarchar(30), parent_row.b_id) + N'/' FROM page_tree AS tree INNER JOIN dbo.s_page_node AS parent_row ON parent_row.b_page_module_id = tree.page_id AND parent_row.b_id = tree.current_id WHERE tree.current_id IS NOT NULL AND tree.visited NOT LIKE N'%/' + CONVERT(nvarchar(30), parent_row.b_id) + N'/%' ) SELECT TOP (1) @PageCycle = 1 FROM page_tree WHERE current_id = origin_id OPTION (MAXRECURSION 32767); IF @PageCycle = 1 THROW 53510, N'The page tree contains a cycle.', 1; IF EXISTS (SELECT 1 FROM dbo.s_module WHERE b_i18n <> 'meta.module.' + CONVERT(varchar(30), b_id)) THROW 53511, N'Module i18n keys are not ID based.', 1; IF EXISTS (SELECT 1 FROM dbo.s_function_node WHERE b_i18n <> 'meta.node.' + CONVERT(varchar(30), b_id)) THROW 53512, N'Function node i18n keys are not ID based.', 1; IF EXISTS (SELECT 1 FROM dbo.s_page_node WHERE b_i18n <> 'meta.node.' + CONVERT(varchar(30), b_id)) THROW 53513, N'Page node i18n keys are not ID based.', 1; IF EXISTS (SELECT 1 FROM dbo.s_module_profile WHERE b_i18n <> 'meta.profile.' + CONVERT(varchar(30), b_id)) THROW 53514, N'Profile i18n keys are not ID based.', 1; IF EXISTS (SELECT 1 FROM dbo.s_module_field WHERE b_i18n <> 'meta.field.' + CONVERT(varchar(30), b_id)) THROW 53515, N'Field i18n keys are not ID based.', 1; IF EXISTS (SELECT 1 FROM dbo.s_module_action WHERE b_i18n <> 'meta.action.' + CONVERT(varchar(30), b_id)) THROW 53516, N'Action i18n keys are not ID based.', 1; SELECT (SELECT COUNT(*) FROM dbo.s_module) AS module_count, (SELECT COUNT(*) FROM dbo.s_function_node) AS function_node_count, (SELECT COUNT(*) FROM dbo.s_page_node) AS page_node_count, (SELECT COUNT(*) FROM dbo.s_module_profile) AS profile_count, (SELECT COUNT(*) FROM dbo.s_module_field) AS field_count, (SELECT COUNT(*) FROM dbo.s_module_action) AS action_count;