dataops-testgen 2.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (270) hide show
  1. dataops_testgen-2.2.0.dist-info/LICENSE +203 -0
  2. dataops_testgen-2.2.0.dist-info/METADATA +287 -0
  3. dataops_testgen-2.2.0.dist-info/NOTICE +5 -0
  4. dataops_testgen-2.2.0.dist-info/RECORD +270 -0
  5. dataops_testgen-2.2.0.dist-info/WHEEL +5 -0
  6. dataops_testgen-2.2.0.dist-info/entry_points.txt +2 -0
  7. dataops_testgen-2.2.0.dist-info/top_level.txt +1 -0
  8. testgen/__init__.py +0 -0
  9. testgen/__main__.py +770 -0
  10. testgen/commands/__init__.py +0 -0
  11. testgen/commands/queries/__init__.py +0 -0
  12. testgen/commands/queries/execute_cat_tests_query.py +95 -0
  13. testgen/commands/queries/execute_tests_query.py +160 -0
  14. testgen/commands/queries/generate_tests_query.py +94 -0
  15. testgen/commands/queries/profiling_query.py +366 -0
  16. testgen/commands/queries/test_parameter_validation_query.py +88 -0
  17. testgen/commands/run_execute_cat_tests.py +162 -0
  18. testgen/commands/run_execute_tests.py +168 -0
  19. testgen/commands/run_generate_tests.py +107 -0
  20. testgen/commands/run_get_entities.py +122 -0
  21. testgen/commands/run_launch_db_config.py +84 -0
  22. testgen/commands/run_observability_exporter.py +330 -0
  23. testgen/commands/run_profiling_bridge.py +495 -0
  24. testgen/commands/run_quick_start.py +168 -0
  25. testgen/commands/run_setup_profiling_tools.py +96 -0
  26. testgen/commands/run_test_definition.py +146 -0
  27. testgen/commands/run_test_parameter_validation.py +135 -0
  28. testgen/commands/run_upgrade_db_config.py +156 -0
  29. testgen/common/__init__.py +8 -0
  30. testgen/common/clean_sql.py +53 -0
  31. testgen/common/credentials.py +25 -0
  32. testgen/common/database/__init__.py +0 -0
  33. testgen/common/database/database_service.py +629 -0
  34. testgen/common/database/flavor/__init__.py +0 -0
  35. testgen/common/database/flavor/flavor_service.py +75 -0
  36. testgen/common/database/flavor/mssql_flavor_service.py +34 -0
  37. testgen/common/database/flavor/postgresql_flavor_service.py +5 -0
  38. testgen/common/database/flavor/redshift_flavor_service.py +22 -0
  39. testgen/common/database/flavor/snowflake_flavor_service.py +69 -0
  40. testgen/common/database/flavor/trino_flavor_service.py +21 -0
  41. testgen/common/date_service.py +68 -0
  42. testgen/common/display_service.py +85 -0
  43. testgen/common/docker_service.py +76 -0
  44. testgen/common/encrypt.py +55 -0
  45. testgen/common/get_pipeline_parms.py +57 -0
  46. testgen/common/logs.py +79 -0
  47. testgen/common/process_service.py +62 -0
  48. testgen/common/read_file.py +69 -0
  49. testgen/settings.py +440 -0
  50. testgen/template/dbsetup/010_create_base_schema.sql +2 -0
  51. testgen/template/dbsetup/020_create_standard_functions_sprocs.sql +179 -0
  52. testgen/template/dbsetup/030_initialize_new_schema_structure.sql +735 -0
  53. testgen/template/dbsetup/040_populate_new_schema_project.sql +59 -0
  54. testgen/template/dbsetup/050_populate_new_schema_metadata.sql +1517 -0
  55. testgen/template/dbsetup/060_create_standard_views.sql +248 -0
  56. testgen/template/dbsetup/070_create_default_users.sql +17 -0
  57. testgen/template/dbsetup/075_grant_role_rights.sql +43 -0
  58. testgen/template/dbsetup/080_set_current_revision.sql +5 -0
  59. testgen/template/dbupgrade/0100_incremental_upgrade.sql +5 -0
  60. testgen/template/dbupgrade/0101_incremental_upgrade.sql +15 -0
  61. testgen/template/dbupgrade/0102_incremental_upgrade.sql +4 -0
  62. testgen/template/dbupgrade/0103_incremental_upgrade.sql +22 -0
  63. testgen/template/dbupgrade/0104_incremental_upgrade.sql +44 -0
  64. testgen/template/dbupgrade/0105_incremental_upgrade.sql +1 -0
  65. testgen/template/dbupgrade/0106_incremental_upgrade.sql +5 -0
  66. testgen/template/dbupgrade/0107_incremental_upgrade.sql +3 -0
  67. testgen/template/dbupgrade_helpers/get_tg_revision.sql +2 -0
  68. testgen/template/exec_cat_tests/ex_cat_build_agg_table_tests.sql +116 -0
  69. testgen/template/exec_cat_tests/ex_cat_get_distinct_tables.sql +11 -0
  70. testgen/template/exec_cat_tests/ex_cat_results_parse.sql +69 -0
  71. testgen/template/exec_cat_tests/ex_cat_retrieve_agg_test_parms.sql +6 -0
  72. testgen/template/exec_cat_tests/ex_cat_test_query.sql +8 -0
  73. testgen/template/execution/ex_finalize_test_run_results.sql +37 -0
  74. testgen/template/execution/ex_get_tests_non_cat.sql +47 -0
  75. testgen/template/execution/ex_update_test_record_in_testrun_table.sql +27 -0
  76. testgen/template/execution/ex_write_test_record_to_testrun_table.sql +6 -0
  77. testgen/template/flavors/generic/exec_query_tests/ex_aggregate_match_no_drops_generic.sql +48 -0
  78. testgen/template/flavors/generic/exec_query_tests/ex_aggregate_match_num_incr_generic.sql +34 -0
  79. testgen/template/flavors/generic/exec_query_tests/ex_aggregate_match_percent_above_generic.sql +49 -0
  80. testgen/template/flavors/generic/exec_query_tests/ex_aggregate_match_percent_within_generic.sql +49 -0
  81. testgen/template/flavors/generic/exec_query_tests/ex_aggregate_match_same_generic.sql +49 -0
  82. testgen/template/flavors/generic/exec_query_tests/ex_custom_query_generic.sql +39 -0
  83. testgen/template/flavors/generic/exec_query_tests/ex_data_match_2way_generic.sql +58 -0
  84. testgen/template/flavors/generic/exec_query_tests/ex_data_match_generic.sql +44 -0
  85. testgen/template/flavors/generic/exec_query_tests/ex_prior_match_generic.sql +37 -0
  86. testgen/template/flavors/generic/exec_query_tests/ex_relative_entropy_generic.sql +53 -0
  87. testgen/template/flavors/generic/exec_query_tests/ex_window_match_no_drops_generic.sql +46 -0
  88. testgen/template/flavors/generic/exec_query_tests/ex_window_match_same_generic.sql +59 -0
  89. testgen/template/flavors/generic/profiling/contingency_counts.sql +3 -0
  90. testgen/template/flavors/generic/validate_tests/ex_get_project_column_list_generic.sql +3 -0
  91. testgen/template/flavors/mssql/exec_query_tests/ex_relative_entropy_mssql.sql +53 -0
  92. testgen/template/flavors/mssql/profiling/project_ddf_query_mssql.sql +35 -0
  93. testgen/template/flavors/mssql/profiling/project_profiling_query_mssql.yaml +246 -0
  94. testgen/template/flavors/mssql/profiling/project_secondary_profiling_query_mssql.sql +36 -0
  95. testgen/template/flavors/mssql/setup_profiling_tools/00_drop_existing_functions_mssql.sql +8 -0
  96. testgen/template/flavors/mssql/setup_profiling_tools/01_create_functions_mssql.sql +12 -0
  97. testgen/template/flavors/mssql/setup_profiling_tools/02_create_functions_mssql.sql +54 -0
  98. testgen/template/flavors/mssql/setup_profiling_tools/create_qc_schema_mssql.sql +4 -0
  99. testgen/template/flavors/mssql/setup_profiling_tools/grant_execute_privileges_mssql.sql +1 -0
  100. testgen/template/flavors/postgresql/exec_query_tests/ex_window_match_no_drops_postgresql.sql +46 -0
  101. testgen/template/flavors/postgresql/exec_query_tests/ex_window_match_same_postgresql.sql +59 -0
  102. testgen/template/flavors/postgresql/profiling/project_ddf_query_postgresql.sql +42 -0
  103. testgen/template/flavors/postgresql/profiling/project_profiling_query_postgresql.yaml +225 -0
  104. testgen/template/flavors/postgresql/profiling/project_secondary_profiling_query_postgresql.sql +28 -0
  105. testgen/template/flavors/postgresql/setup_profiling_tools/create_functions_postgresql.sql +157 -0
  106. testgen/template/flavors/postgresql/setup_profiling_tools/create_qc_schema_postgresql.sql +1 -0
  107. testgen/template/flavors/postgresql/setup_profiling_tools/grant_execute_privileges_postgresql.sql +2 -0
  108. testgen/template/flavors/redshift/profiling/project_ddf_query_redshift.sql +38 -0
  109. testgen/template/flavors/redshift/profiling/project_profiling_query_redshift.yaml +221 -0
  110. testgen/template/flavors/redshift/profiling/project_secondary_profiling_query_redshift.sql +29 -0
  111. testgen/template/flavors/redshift/setup_profiling_tools/create_functions_redshift.sql +115 -0
  112. testgen/template/flavors/redshift/setup_profiling_tools/create_qc_schema_redshift.sql +1 -0
  113. testgen/template/flavors/redshift/setup_profiling_tools/grant_execute_privileges_redshift.sql +2 -0
  114. testgen/template/flavors/snowflake/profiling/project_ddf_query_snowflake.sql +38 -0
  115. testgen/template/flavors/snowflake/profiling/project_profiling_query_snowflake.yaml +220 -0
  116. testgen/template/flavors/snowflake/profiling/project_secondary_profiling_query_snowflake.sql +29 -0
  117. testgen/template/flavors/snowflake/setup_profiling_tools/create_functions_snowflake.sql +69 -0
  118. testgen/template/flavors/snowflake/setup_profiling_tools/create_qc_schema_snowflake.sql +1 -0
  119. testgen/template/flavors/snowflake/setup_profiling_tools/grant_execute_privileges_snowflake.sql +6 -0
  120. testgen/template/flavors/trino/profiling/project_profiling_query_trino.yaml +219 -0
  121. testgen/template/flavors/trino/setup_profiling_tools/create_functions_trino.sql +92 -0
  122. testgen/template/flavors/trino/setup_profiling_tools/create_qc_schema_trino.sql +1 -0
  123. testgen/template/gen_funny_cat_tests/gen_test_constant.sql +104 -0
  124. testgen/template/gen_funny_cat_tests/gen_test_distinct_value_ct.sql +98 -0
  125. testgen/template/gen_funny_cat_tests/gen_test_row_ct.sql +57 -0
  126. testgen/template/gen_funny_cat_tests/gen_test_row_ct_pct.sql +59 -0
  127. testgen/template/generation/gen_delete_old_tests.sql +5 -0
  128. testgen/template/generation/gen_insert_test_suite.sql +5 -0
  129. testgen/template/generation/gen_retrieve_or_insert_test_suite.sql +58 -0
  130. testgen/template/generation/gen_standard_test_type_list.sql +13 -0
  131. testgen/template/generation/gen_standard_tests.sql +48 -0
  132. testgen/template/get_entities/get_connection.sql +21 -0
  133. testgen/template/get_entities/get_connections_list.sql +9 -0
  134. testgen/template/get_entities/get_latest.sql +4 -0
  135. testgen/template/get_entities/get_profile.sql +12 -0
  136. testgen/template/get_entities/get_profile_info.sql +17 -0
  137. testgen/template/get_entities/get_profile_list.sql +17 -0
  138. testgen/template/get_entities/get_profile_screen.sql +275 -0
  139. testgen/template/get_entities/get_project_list.sql +6 -0
  140. testgen/template/get_entities/get_table_group_list.sql +10 -0
  141. testgen/template/get_entities/get_test_generation_list.sql +18 -0
  142. testgen/template/get_entities/get_test_info.sql +41 -0
  143. testgen/template/get_entities/get_test_results_for_run_cli.sql +16 -0
  144. testgen/template/get_entities/get_test_run_list.sql +24 -0
  145. testgen/template/get_entities/get_test_suite.sql +13 -0
  146. testgen/template/get_entities/get_test_suite_list.sql +18 -0
  147. testgen/template/get_entities/list_test_types.sql +4 -0
  148. testgen/template/observability/get_event_data.sql +23 -0
  149. testgen/template/observability/get_test_results.sql +41 -0
  150. testgen/template/observability/update_test_results_exported_to_observability.sql +12 -0
  151. testgen/template/parms/parms_profiling.sql +34 -0
  152. testgen/template/parms/parms_test_execution.sql +13 -0
  153. testgen/template/parms/parms_test_gen.sql +23 -0
  154. testgen/template/profiling/contingency_columns.sql +7 -0
  155. testgen/template/profiling/datatype_suggestions.sql +56 -0
  156. testgen/template/profiling/functional_datatype.sql +523 -0
  157. testgen/template/profiling/functional_tabletype_stage.sql +48 -0
  158. testgen/template/profiling/functional_tabletype_update.sql +8 -0
  159. testgen/template/profiling/pii_flag.sql +133 -0
  160. testgen/template/profiling/profile_anomalies_screen_column.sql +22 -0
  161. testgen/template/profiling/profile_anomalies_screen_multi_column.sql +58 -0
  162. testgen/template/profiling/profile_anomalies_screen_table.sql +22 -0
  163. testgen/template/profiling/profile_anomalies_screen_table_dates.sql +30 -0
  164. testgen/template/profiling/profile_anomalies_screen_variants.sql +40 -0
  165. testgen/template/profiling/profile_anomaly_types_get.sql +3 -0
  166. testgen/template/profiling/project_get_table_sample_count.sql +22 -0
  167. testgen/template/profiling/project_profile_run_record_insert.sql +8 -0
  168. testgen/template/profiling/project_profile_run_record_update.sql +5 -0
  169. testgen/template/profiling/project_profile_run_record_update_status.sql +5 -0
  170. testgen/template/profiling/project_update_profile_results_to_estimates.sql +32 -0
  171. testgen/template/profiling/refresh_anomalies.sql +33 -0
  172. testgen/template/profiling/refresh_data_chars_from_profiling.sql +156 -0
  173. testgen/template/profiling/secondary_profiling_columns.sql +12 -0
  174. testgen/template/profiling/secondary_profiling_delete.sql +4 -0
  175. testgen/template/profiling/secondary_profiling_update.sql +18 -0
  176. testgen/template/quick_start/populate_target_data.sql +1077 -0
  177. testgen/template/quick_start/recreate_target_data_schema.sql +167 -0
  178. testgen/template/quick_start/update_target_data.sql +100 -0
  179. testgen/template/updates/create_tmp_test_definition.sql +19 -0
  180. testgen/template/updates/get_test_def_parms.sql +38 -0
  181. testgen/template/updates/populate_stg_test_definitions.sql +184 -0
  182. testgen/template/validate_tests/ex_disable_tests_test_definitions.sql +5 -0
  183. testgen/template/validate_tests/ex_flag_tests_test_definitions.sql +64 -0
  184. testgen/template/validate_tests/ex_get_project_column_list_generic.sql +3 -0
  185. testgen/template/validate_tests/ex_get_test_column_list_tg.sql +65 -0
  186. testgen/template/validate_tests/ex_write_test_val_errors.sql +22 -0
  187. testgen/ui/__init__.py +0 -0
  188. testgen/ui/app.py +98 -0
  189. testgen/ui/assets/dk_logo.svg +46 -0
  190. testgen/ui/assets/question_mark.png +0 -0
  191. testgen/ui/assets/scripts.js +68 -0
  192. testgen/ui/assets/style.css +140 -0
  193. testgen/ui/bootstrap.py +109 -0
  194. testgen/ui/components/__init__.py +0 -0
  195. testgen/ui/components/frontend/css/KFOlCnqEu92Fr1MmEU9fBBc4.woff2 +0 -0
  196. testgen/ui/components/frontend/css/KFOlCnqEu92Fr1MmEU9fChc4EsA.woff2 +0 -0
  197. testgen/ui/components/frontend/css/KFOmCnqEu92Fr1Mu4mxK.woff2 +0 -0
  198. testgen/ui/components/frontend/css/KFOmCnqEu92Fr1Mu7GxKOzY.woff2 +0 -0
  199. testgen/ui/components/frontend/css/material-symbols-rounded.css +24 -0
  200. testgen/ui/components/frontend/css/material-symbols-rounded.woff2 +0 -0
  201. testgen/ui/components/frontend/css/roboto-font-faces.css +35 -0
  202. testgen/ui/components/frontend/css/shared.css +36 -0
  203. testgen/ui/components/frontend/img/dk_logo.svg +46 -0
  204. testgen/ui/components/frontend/index.html +17 -0
  205. testgen/ui/components/frontend/js/components/breadcrumbs.js +86 -0
  206. testgen/ui/components/frontend/js/components/button.js +66 -0
  207. testgen/ui/components/frontend/js/components/location.js +62 -0
  208. testgen/ui/components/frontend/js/components/select.js +75 -0
  209. testgen/ui/components/frontend/js/components/sidebar.js +358 -0
  210. testgen/ui/components/frontend/js/main.js +99 -0
  211. testgen/ui/components/frontend/js/streamlit.js +19 -0
  212. testgen/ui/components/frontend/js/van.min.js +1 -0
  213. testgen/ui/components/utils/__init__.py +0 -0
  214. testgen/ui/components/utils/callbacks.py +51 -0
  215. testgen/ui/components/utils/component.py +13 -0
  216. testgen/ui/components/widgets/__init__.py +6 -0
  217. testgen/ui/components/widgets/breadcrumbs.py +32 -0
  218. testgen/ui/components/widgets/location.py +65 -0
  219. testgen/ui/components/widgets/modal.py +97 -0
  220. testgen/ui/components/widgets/sidebar.py +69 -0
  221. testgen/ui/navigation/__init__.py +0 -0
  222. testgen/ui/navigation/menu.py +42 -0
  223. testgen/ui/navigation/page.py +20 -0
  224. testgen/ui/navigation/router.py +63 -0
  225. testgen/ui/queries/__init__.py +0 -0
  226. testgen/ui/queries/authentication_queries.py +47 -0
  227. testgen/ui/queries/connection_queries.py +121 -0
  228. testgen/ui/queries/profiling_queries.py +148 -0
  229. testgen/ui/queries/project_queries.py +9 -0
  230. testgen/ui/queries/table_group_queries.py +186 -0
  231. testgen/ui/queries/test_definition_queries.py +270 -0
  232. testgen/ui/queries/test_run_queries.py +32 -0
  233. testgen/ui/queries/test_suite_queries.py +145 -0
  234. testgen/ui/scripts/__init__.py +0 -0
  235. testgen/ui/scripts/patch_streamlit.py +111 -0
  236. testgen/ui/services/__init__.py +0 -0
  237. testgen/ui/services/authentication_service.py +119 -0
  238. testgen/ui/services/connection_service.py +220 -0
  239. testgen/ui/services/database_service.py +282 -0
  240. testgen/ui/services/form_service.py +1008 -0
  241. testgen/ui/services/javascript_service.py +44 -0
  242. testgen/ui/services/query_service.py +316 -0
  243. testgen/ui/services/string_service.py +12 -0
  244. testgen/ui/services/table_group_service.py +130 -0
  245. testgen/ui/services/test_definition_service.py +117 -0
  246. testgen/ui/services/test_run_service.py +13 -0
  247. testgen/ui/services/test_suite_service.py +76 -0
  248. testgen/ui/services/toolbar_service.py +77 -0
  249. testgen/ui/session.py +46 -0
  250. testgen/ui/views/__init__.py +0 -0
  251. testgen/ui/views/app_log_modal.py +92 -0
  252. testgen/ui/views/connections.py +72 -0
  253. testgen/ui/views/connections_base.py +367 -0
  254. testgen/ui/views/login.py +40 -0
  255. testgen/ui/views/not_found.py +16 -0
  256. testgen/ui/views/overview.py +34 -0
  257. testgen/ui/views/profiling_anomalies.py +501 -0
  258. testgen/ui/views/profiling_details.py +335 -0
  259. testgen/ui/views/profiling_modal.py +40 -0
  260. testgen/ui/views/profiling_results.py +206 -0
  261. testgen/ui/views/profiling_summary.py +177 -0
  262. testgen/ui/views/project_settings.py +74 -0
  263. testgen/ui/views/table_groups.py +530 -0
  264. testgen/ui/views/test_definitions.py +1020 -0
  265. testgen/ui/views/test_results.py +908 -0
  266. testgen/ui/views/test_runs.py +195 -0
  267. testgen/ui/views/test_suites.py +545 -0
  268. testgen/utils/__init__.py +0 -0
  269. testgen/utils/plugins.py +17 -0
  270. testgen/utils/singleton.py +14 -0
@@ -0,0 +1,96 @@
1
+ import logging
2
+
3
+ from testgen.commands.run_get_entities import run_get_connection
4
+ from testgen.common import AssignConnectParms, RunActionQueryList
5
+ from testgen.common.database.database_service import get_queries_for_command
6
+
7
+ LOG = logging.getLogger("testgen")
8
+
9
+
10
+ def _get_params_mapping(project_qc_schema: str, user: str, user_role: str | None) -> dict:
11
+ return {
12
+ "DATA_QC_SCHEMA": project_qc_schema,
13
+ "DB_USER": user,
14
+ "DB_USER_ROLE": user_role,
15
+ }
16
+
17
+
18
+ def get_setup_profiling_tools_queries(sql_flavor, create_qc_schema, skip_granting_privileges, project_qc_schema, user, user_role=None):
19
+ queries = []
20
+
21
+ params_mapping = _get_params_mapping(project_qc_schema, user, user_role)
22
+
23
+ if create_qc_schema:
24
+ queries.extend(
25
+ get_queries_for_command(
26
+ f"flavors/{sql_flavor}/setup_profiling_tools",
27
+ params_mapping,
28
+ mask=rf"^.*create_qc_schema_{sql_flavor}.sql$",
29
+ )
30
+ )
31
+
32
+ queries.extend(
33
+ get_queries_for_command(
34
+ f"flavors/{sql_flavor}/setup_profiling_tools", params_mapping, mask=rf"^.*functions_{sql_flavor}.sql$"
35
+ )
36
+ )
37
+
38
+ if not skip_granting_privileges:
39
+ queries.extend(
40
+ get_queries_for_command(
41
+ f"flavors/{sql_flavor}/setup_profiling_tools",
42
+ params_mapping,
43
+ mask=rf"^.*grant_execute_privileges_{sql_flavor}.sql$",
44
+ )
45
+ )
46
+
47
+ return queries
48
+
49
+
50
+ def run_setup_profiling_tools(
51
+ connection_id: str | int,
52
+ dry_run: bool,
53
+ create_qc_schema: bool = True,
54
+ db_user: str | None = None,
55
+ db_password: str | None = None,
56
+ skip_granting_privileges: bool = False,
57
+ admin_private_key_passphrase: str | None = None,
58
+ admin_private_key: str | None = None,
59
+ user_role: str | None = None,
60
+ ) -> str:
61
+ connection = run_get_connection(str(connection_id))
62
+
63
+ # Set Project Connection Parms in common.db_bridgers from retrieved parms
64
+ LOG.info("CurrentStep: Assigning Connection Parms")
65
+ user = db_user or connection["project_user"]
66
+ connect_by_key = admin_private_key is not None or connection["connect_by_key"]
67
+ private_key_passphrase = admin_private_key_passphrase if admin_private_key is not None else connection["private_key_passphrase"]
68
+ private_key = admin_private_key if admin_private_key is not None else connection["private_key"]
69
+
70
+ AssignConnectParms(
71
+ connection["project_key"],
72
+ connection["connection_id"],
73
+ connection["project_host"],
74
+ connection["project_port"],
75
+ connection["project_db"],
76
+ connection["project_qc_schema"],
77
+ user,
78
+ connection["sql_flavor"],
79
+ connection["url"],
80
+ connection["connect_by_url"],
81
+ connect_by_key,
82
+ private_key,
83
+ private_key_passphrase,
84
+ "PROJECT",
85
+ )
86
+
87
+ project_qc_schema = connection["project_qc_schema"]
88
+ sql_flavor = connection["sql_flavor"]
89
+ user = connection["project_user"]
90
+
91
+ queries = get_setup_profiling_tools_queries(sql_flavor, create_qc_schema, skip_granting_privileges, project_qc_schema, user, user_role)
92
+
93
+ if not dry_run:
94
+ RunActionQueryList("PROJECT", queries, user_override=db_user, pwd_override=db_password)
95
+
96
+ return project_qc_schema
@@ -0,0 +1,146 @@
1
+ from testgen.common import RetrieveDBResultsToDictList, RunActionQueryList, WriteListToDB, read_template_sql_file
2
+
3
+
4
+ def get_test_def_parms(project_code, test_suite):
5
+ lstResults = run_test_def_parms(project_code, test_suite)
6
+
7
+ if lstResults is None:
8
+ raise ValueError("Test Definition Parameters not found")
9
+
10
+ yaml_dict = {}
11
+
12
+ for row in lstResults:
13
+ project_code = row["project_code"]
14
+ test_suite = row["test_suite"]
15
+ schema = row["schema_name"]
16
+ table_name = row["table_name"]
17
+ column_name = row["column_name"]
18
+ row_id = (row["id"],)
19
+ test_type = (row["test_type"],)
20
+ test_description = (row["test_description"],)
21
+ test_action = (row["test_action"],)
22
+ test_active = (row["test_active"],)
23
+ lock_refresh = (row["lock_refresh"],)
24
+ severity = (row["severity"],)
25
+ test_parameters = (row["test_parameters"],)
26
+
27
+ if project_code not in yaml_dict:
28
+ yaml_dict[project_code] = {}
29
+ if test_suite not in yaml_dict[project_code]:
30
+ yaml_dict[project_code][test_suite] = {}
31
+ if schema not in yaml_dict[project_code][test_suite]:
32
+ yaml_dict[project_code][test_suite][schema] = {}
33
+ if table_name not in yaml_dict[project_code][test_suite][schema]:
34
+ yaml_dict[project_code][test_suite][schema][table_name] = {}
35
+ if column_name not in yaml_dict[project_code][test_suite][schema][table_name]:
36
+ yaml_dict[project_code][test_suite][schema][table_name][column_name] = []
37
+
38
+ parm_columns = test_parameters[0].split(",")
39
+ parm_dict = {}
40
+
41
+ for column in parm_columns:
42
+ parm_dict[column] = row[column]
43
+
44
+ yaml_dict[project_code][test_suite][schema][table_name][column_name].append(
45
+ {
46
+ "id": str(row_id[0]),
47
+ "test_type": str(test_type[0]),
48
+ "test_description": str(test_description[0]),
49
+ "test_action": str(test_action[0]),
50
+ "test_active": str(test_active[0]),
51
+ "lock_refresh": str(lock_refresh[0]),
52
+ "severity": str(severity[0]),
53
+ "test_parameters": parm_dict,
54
+ }
55
+ )
56
+
57
+ return yaml_dict
58
+
59
+
60
+ def run_test_def_parms(project_code, test_suite):
61
+ sql_template = read_template_sql_file("get_test_def_parms.sql", "updates")
62
+
63
+ sql_template = sql_template.replace("{PROJECT_CODE}", project_code)
64
+ sql_template = sql_template.replace("{TEST_SUITE}", test_suite)
65
+
66
+ return RetrieveDBResultsToDictList("DKTG", sql_template)
67
+
68
+
69
+ def update_test_def_parms_dict(yaml_dict):
70
+ if yaml_dict is None:
71
+ raise ValueError("Test Definition Parameters not found")
72
+
73
+ updResults = update_test_definitions(yaml_dict)
74
+ RunActionQueryList("DKTG", updResults)
75
+
76
+
77
+ def update_test_definitions(data):
78
+ list_columns = []
79
+ list_update_insert_queries = []
80
+
81
+ for project_code, test_suite_dict in data.items():
82
+ for test_suite, schema_dict in test_suite_dict.items():
83
+ for schema, table_dict in schema_dict.items():
84
+ for table, column_dict in table_dict.items():
85
+ for column, attributes_list in column_dict.items():
86
+ for attribute in attributes_list:
87
+ id_col = attribute["id"]
88
+ test_type = attribute["test_type"]
89
+ test_description = attribute["test_description"]
90
+ test_action = attribute["test_action"]
91
+ test_active = attribute["test_active"]
92
+ lock_refresh = attribute["lock_refresh"]
93
+ severity = attribute["severity"]
94
+ test_parameters = attribute["test_parameters"]
95
+
96
+ column_keys = test_parameters.keys()
97
+ column_values = test_parameters.values()
98
+
99
+ for col, value in zip(column_keys, column_values, strict=False):
100
+ list_columns.append(
101
+ [
102
+ project_code,
103
+ test_suite,
104
+ schema,
105
+ table,
106
+ column,
107
+ id_col,
108
+ test_type,
109
+ test_description,
110
+ test_action,
111
+ test_active,
112
+ lock_refresh,
113
+ severity,
114
+ col,
115
+ value,
116
+ ]
117
+ )
118
+
119
+ col_list = [
120
+ "project_code",
121
+ "test_suite",
122
+ "schema_name",
123
+ "table_name",
124
+ "column_name",
125
+ "id",
126
+ "test_type",
127
+ "test_description",
128
+ "test_action",
129
+ "test_active",
130
+ "lock_refresh",
131
+ "severity",
132
+ "test_parameter",
133
+ "test_parameter_value",
134
+ ]
135
+
136
+ list_create_queries = []
137
+ create_table = read_template_sql_file("create_tmp_test_definition.sql", "updates")
138
+ list_create_queries.append(create_table)
139
+ RunActionQueryList("DKTG", list_create_queries)
140
+
141
+ # Write to tmp_test_definition
142
+ WriteListToDB("DKTG", list_columns, col_list, "tmp_test_definition")
143
+
144
+ sql_template = read_template_sql_file("populate_stg_test_definitions.sql", "updates")
145
+ list_update_insert_queries.append(sql_template)
146
+ return list_update_insert_queries
@@ -0,0 +1,135 @@
1
+ import logging
2
+
3
+ from testgen.commands.queries.test_parameter_validation_query import CTestParamValidationSQL
4
+ from testgen.common import AssignConnectParms, RetrieveDBResultsToDictList, RetrieveTestExecParms, RunActionQueryList
5
+
6
+ LOG = logging.getLogger("testgen")
7
+
8
+
9
+ def run_parameter_validation_queries(
10
+ test_run_id="", test_time="", strProjectCode="", strTestSuite="", booRunFromTestExec=True
11
+ ):
12
+ LOG.info("CurrentStep: Retrieving TestzVal Parameters")
13
+ dctParms = RetrieveTestExecParms(strProjectCode, strTestSuite)
14
+ LOG.debug("Test Parameter Validation - Parameters retrieved")
15
+
16
+ # Set Project Connection Parms in db_bridgers from retrieved parms
17
+ LOG.info("CurrentStep: Assigning Connection Parms")
18
+ AssignConnectParms(
19
+ dctParms["project_code"],
20
+ dctParms["connection_id"],
21
+ dctParms["project_host"],
22
+ dctParms["project_port"],
23
+ dctParms["project_db"],
24
+ dctParms["table_group_schema"],
25
+ dctParms["project_user"],
26
+ dctParms["sql_flavor"],
27
+ dctParms["url"],
28
+ dctParms["connect_by_url"],
29
+ dctParms["connect_by_key"],
30
+ dctParms["private_key"],
31
+ dctParms["private_key_passphrase"],
32
+ "PROJECT",
33
+ )
34
+
35
+ LOG.debug("Validating parameters for Test Suite %s")
36
+
37
+ LOG.info("CurrentStep: Initializing Test Parameter Validation")
38
+ clsExecute = CTestParamValidationSQL(strProjectCode, dctParms["sql_flavor"], strTestSuite)
39
+ clsExecute.run_date = test_time
40
+ clsExecute.test_run_id = test_run_id
41
+ LOG.info("CurrentStep: Validation Class successfully initialized")
42
+
43
+ booClean = False
44
+
45
+ # Retrieve Test Column list
46
+ LOG.info("CurrentStep: Retrieve Test Columns for Validation")
47
+ strColumnList = clsExecute.GetTestValidationColumns(booClean)
48
+ lstTestColumns = RetrieveDBResultsToDictList("DKTG", strColumnList)
49
+
50
+ if len(lstTestColumns) == 0:
51
+ LOG.warning(f"No test columns are present to validate in Test Suite {strTestSuite}")
52
+ missing_columns = []
53
+ else:
54
+ # Derive test schema list -- make CSV string from list of columns
55
+ # to be used as criteria for retrieving data dictionary
56
+ setSchemas = {s["columns"].split(".")[0] for s in lstTestColumns}
57
+ strSchemas = ", ".join([f"'{value}'" for value in setSchemas])
58
+ LOG.debug("Test column list successfully retrieved")
59
+
60
+ # Retrieve Project Column list
61
+ LOG.info("CurrentStep: Retrieve Test Columns for Validation")
62
+ clsExecute.test_schemas = strSchemas
63
+ strProjectColumnList = clsExecute.GetProjectTestValidationColumns()
64
+ if "where table_schema in ()" in strProjectColumnList:
65
+ raise ValueError("No schema specified in Validation Columns check")
66
+ lstProjectTestColumns = RetrieveDBResultsToDictList("PROJECT", strProjectColumnList)
67
+
68
+ if len(lstProjectTestColumns) == 0:
69
+ LOG.info("Project Test Column list is empty")
70
+
71
+ LOG.debug("Project column list successfully received")
72
+ LOG.info("CurrentStep: Compare column sets")
73
+ # load results into sets
74
+ result_set1 = {item["columns"].lower() for item in set(lstTestColumns)}
75
+ result_set2 = {item["columns"].lower() for item in set(lstProjectTestColumns)}
76
+
77
+ # Check if all columns exist in the table
78
+ missing_columns = result_set1.difference(result_set2)
79
+
80
+ if len(missing_columns) == 0:
81
+ LOG.info("No missing column in Project Column list.")
82
+
83
+ strMissingColumns = ", ".join(f"'{x}'" for x in missing_columns)
84
+ srtNoQuoteMissingCols = strMissingColumns.replace("'", "")
85
+
86
+ if missing_columns:
87
+ LOG.debug("Test Columns are missing in target database: %s", srtNoQuoteMissingCols)
88
+
89
+ # Extracting schema.tables that are missing from the result sets
90
+ tables_set1 = {elem.rsplit(".", 1)[0] for elem in result_set1}
91
+ tables_set2 = {elem.rsplit(".", 1)[0] for elem in result_set2}
92
+
93
+ # Check if all the tables exist in the schema
94
+ missing_tables = tables_set1.difference(tables_set2)
95
+
96
+ if missing_tables:
97
+ strMissingtables = ", ".join(f"'{x}'" for x in missing_tables)
98
+ else:
99
+ LOG.info("No missing tables in Project Column list.")
100
+ strMissingtables = "''"
101
+
102
+ # Flag test_definitions tests with missing columns:
103
+ LOG.info("CurrentStep: Flagging Tests That Failed Validation")
104
+ clsExecute.missing_columns = strMissingColumns
105
+ clsExecute.missing_tables = strMissingtables
106
+ # Flag Value is D if called from execute_tests_qry.py, otherwise N to disable now
107
+ if booRunFromTestExec:
108
+ clsExecute.flag_val = "D"
109
+ strTempMessage = "Tests that failed parameter validation have been flagged."
110
+ else:
111
+ clsExecute.flag_val = "N"
112
+ strTempMessage = "Tests that failed parameter validation have been set to inactive."
113
+ strFlagTests = clsExecute.FlagTestsWithFailedValidation()
114
+ RunActionQueryList("DKTG", [strFlagTests])
115
+ LOG.debug(strTempMessage)
116
+
117
+ # when run_parameter_validation_queries() is called from execute_tests_query.py:
118
+ # we disable tests and write validation errors to test_results table.
119
+ if booRunFromTestExec:
120
+ # Copy test results to DK DB, using temporary flagged -1 value to identify
121
+ LOG.info("CurrentStep: Saving error results for invalid tests")
122
+ strReportValErrors = clsExecute.ReportTestValidationErrors()
123
+ RunActionQueryList("DKTG", [strReportValErrors])
124
+ LOG.debug("Results inserted for invalid tests")
125
+
126
+ # Set to Inactive those test_definitions tests that are flagged D: set to N
127
+
128
+ LOG.info("CurrentStep: Disabling Tests That Failed Validation")
129
+ strDisableTests = clsExecute.DisableTestsWithFailedValidation()
130
+ RunActionQueryList("DKTG", [strDisableTests])
131
+ LOG.debug("Tests that failed parameter validation have been disabled.")
132
+
133
+ LOG.info("Validation Complete: tests referencing missing columns have been disabled.")
134
+ else:
135
+ LOG.info("Validation Successful: No columns missing from target database.")
@@ -0,0 +1,156 @@
1
+ import logging
2
+
3
+ from testgen import settings
4
+ from testgen.common import RetrieveSingleResultValue, RunActionQueryList, read_template_sql_file
5
+ from testgen.common.credentials import get_tg_schema
6
+ from testgen.common.database.database_service import replace_params
7
+ from testgen.common.read_file import get_template_files
8
+
9
+ LOG = logging.getLogger("testgen")
10
+
11
+
12
+ def _get_params_mapping() -> dict:
13
+ return {
14
+ "SCHEMA_NAME": get_tg_schema(),
15
+ "TESTGEN_ADMIN_USER": settings.DATABASE_ADMIN_USER,
16
+ "TESTGEN_ADMIN_PASSWORD": settings.DATABASE_ADMIN_PASSWORD,
17
+ "OBSERVABILITY_URL": settings.OBSERVABILITY_API_URL,
18
+ }
19
+
20
+
21
+ def _get_revision_prefix(params_mapping):
22
+ strQuery = read_template_sql_file("get_tg_revision.sql", "dbupgrade_helpers")
23
+ strQuery = replace_params(strQuery, params_mapping)
24
+
25
+ intNextRevision = RetrieveSingleResultValue("DKTG", strQuery)
26
+
27
+ return intNextRevision
28
+
29
+
30
+ def _get_next_revision_prefix(params_mapping):
31
+ return _get_revision_prefix(params_mapping) + 1
32
+
33
+
34
+ def get_schema_revision():
35
+ params_mapping = {"SCHEMA_NAME": get_tg_schema()}
36
+ try:
37
+ schema_revision = str(_get_revision_prefix(params_mapping))
38
+ except Exception:
39
+ schema_revision = "UNKNOWN"
40
+ return schema_revision
41
+
42
+
43
+ def _format_revision_prefix(intNextRevision: int):
44
+ if intNextRevision < 1 or intNextRevision > 9999:
45
+ raise ValueError(f"The prefix {intNextRevision} for the upgrade script is out of range.")
46
+
47
+ return str(intNextRevision).zfill(4)
48
+
49
+
50
+ def _get_upgrade_template_directory():
51
+ return "dbupgrade"
52
+
53
+
54
+ def _get_upgrade_scripts(sub_directory: str, params_mapping: dict, mask: str = r"^.*sql$", min_val: str = ""):
55
+ files = sorted(get_template_files(mask=mask, sub_directory=sub_directory), key=lambda key: str(key))
56
+
57
+ max_prefix = ""
58
+ queries = []
59
+ for file in files:
60
+ if file.name > min_val:
61
+ template = file.read_text("utf-8")
62
+ query = replace_params(template, params_mapping)
63
+ queries.append(query)
64
+ max_prefix = file.name[0:4]
65
+
66
+ if len(queries) == 0:
67
+ LOG.debug(f"No sql files were found for the mask {mask} in subdirectory {sub_directory}")
68
+
69
+ return queries, max_prefix
70
+
71
+
72
+ def _execute_upgrade_scripts(params_mapping, lstScripts):
73
+ # Run scripts using admin credentials
74
+ RunActionQueryList(
75
+ "DKTG",
76
+ lstScripts,
77
+ "S",
78
+ user_override=params_mapping["TESTGEN_ADMIN_USER"],
79
+ pwd_override=params_mapping["TESTGEN_ADMIN_PASSWORD"],
80
+ )
81
+ return True
82
+
83
+
84
+ def _refresh_static_metadata(params_mapping):
85
+ # Refresh static metadata -- shouldn't affect user data
86
+ strQueryMetadata = read_template_sql_file("050_populate_new_schema_metadata.sql", "dbsetup")
87
+ strQueryMetadata = replace_params(strQueryMetadata, params_mapping)
88
+ # Recreate standard views
89
+ strQueryViews = read_template_sql_file("060_create_standard_views.sql", "dbsetup")
90
+ strQueryViews = replace_params(strQueryViews, params_mapping)
91
+ # Reassign rights to standard roles
92
+ strQueryRights = read_template_sql_file("075_grant_role_rights.sql", "dbsetup")
93
+ strQueryRights = replace_params(strQueryRights, params_mapping)
94
+
95
+ RunActionQueryList(
96
+ "DKTG",
97
+ [strQueryMetadata, strQueryViews, strQueryRights],
98
+ "S",
99
+ user_override=params_mapping["TESTGEN_ADMIN_USER"],
100
+ pwd_override=params_mapping["TESTGEN_ADMIN_PASSWORD"],
101
+ )
102
+
103
+
104
+ def _update_revision_number(params_mapping, latest_prefix_applied):
105
+ # Update extant revision number to highest script prefix applied
106
+ strQuery = read_template_sql_file("080_set_current_revision.sql", "dbsetup")
107
+ strQuery = strQuery.replace("{DB_REVISION}", str(int(latest_prefix_applied)))
108
+ strQuery = replace_params(strQuery, params_mapping)
109
+
110
+ RunActionQueryList(
111
+ "DKTG",
112
+ [strQuery],
113
+ "S",
114
+ user_override=params_mapping["TESTGEN_ADMIN_USER"],
115
+ pwd_override=params_mapping["TESTGEN_ADMIN_PASSWORD"],
116
+ )
117
+
118
+
119
+ def run_upgrade_db_config() -> bool:
120
+ LOG.info("Running run_upgrade_db_config")
121
+
122
+ params_mapping = _get_params_mapping()
123
+
124
+ # Look for prefix one higher than last revision extant in db
125
+ strNextPrefix = _format_revision_prefix(_get_next_revision_prefix(params_mapping))
126
+ # Retrieve template upgrade directory name
127
+ upgrade_dir = _get_upgrade_template_directory()
128
+
129
+ # Retrieve and execute upgrade scripts, if any
130
+ lstQueries, max_prefix = _get_upgrade_scripts(upgrade_dir, params_mapping, min_val=strNextPrefix)
131
+ LOG.info(f"Updating db config qty of queries: {len(lstQueries)}. New prefix: {max_prefix}. Queries: {lstQueries}")
132
+ if len(lstQueries) > 0:
133
+ has_been_upgraded = _execute_upgrade_scripts(params_mapping, lstQueries)
134
+ else:
135
+ has_been_upgraded = False
136
+
137
+ _refresh_static_metadata(params_mapping)
138
+
139
+ if has_been_upgraded:
140
+ # Update revision number to max prefix found in update scripts
141
+ _update_revision_number(params_mapping, max_prefix)
142
+ LOG.info("Application data was successfully upgraded, and static metadata was refreshed.")
143
+ else:
144
+ LOG.info("Database upgrade was not required. Static metadata was refreshed.")
145
+
146
+ return has_been_upgraded
147
+
148
+
149
+ def is_db_revision_up_to_date():
150
+ params_mapping = {"SCHEMA_NAME": get_tg_schema()}
151
+ strNextPrefix = _format_revision_prefix(_get_next_revision_prefix(params_mapping))
152
+ upgrade_dir = _get_upgrade_template_directory()
153
+
154
+ # Retrieve and execute upgrade scripts, if any
155
+ lstQueries, max_prefix = _get_upgrade_scripts(upgrade_dir, params_mapping, min_val=strNextPrefix)
156
+ return len(lstQueries) == 0
@@ -0,0 +1,8 @@
1
+ from testgen.common.database.database_service import *
2
+
3
+ from .clean_sql import *
4
+ from .credentials import *
5
+ from .encrypt import *
6
+ from .get_pipeline_parms import *
7
+ from .logs import *
8
+ from .read_file import *
@@ -0,0 +1,53 @@
1
+ __all__ = ["AddQuotesToIdentifierCSV", "CleanSQL", "ConcatColumnList"]
2
+
3
+ import re
4
+
5
+
6
+ def CleanSQL(strInput: str) -> str:
7
+ # Use regular expression to remove comment text fenced by /*...*/
8
+ strInput = re.sub(r"/\*.*?\*/", "", strInput, flags=re.DOTALL)
9
+ # Use regular expression to remove comment text starting with --
10
+ strInput = re.sub(r"--.*$", "", strInput, flags=re.MULTILINE)
11
+ # Use regular expression to replace any tab with one space
12
+ strInput = re.sub(r"\t", " ", strInput)
13
+ # Use regular expression to remove spaces outside quotes
14
+ parts = re.split(r"""("[^"]*"|'[^']*')""", strInput)
15
+ parts[::2] = (" ".join(s.split()) for s in parts[::2]) # outside quotes
16
+ return " ".join(parts)
17
+
18
+
19
+ def AddQuotesToIdentifierCSV(strInput: str) -> str:
20
+ # Keywords -- identifiers to quote
21
+ keywords = [
22
+ "select",
23
+ "from",
24
+ "where",
25
+ "order",
26
+ "by",
27
+ "having",
28
+ ]
29
+
30
+ quoted_values = []
31
+ for value in strInput.split(","):
32
+ value = value.strip()
33
+ if value.startswith('"') and value.endswith('"'):
34
+ quoted_values.append(value)
35
+ elif any(c.isupper() or c.isspace() or value.lower() in keywords for c in value):
36
+ quoted_values.append(f'"{value}"')
37
+ else:
38
+ quoted_values.append(value)
39
+ return ", ".join(quoted_values)
40
+
41
+
42
+ def ConcatColumnList(str_column_list, str_null_value):
43
+ # Prepares SQL expression to concatenate comma-separated column list into single SQL expression
44
+ str_expression = ""
45
+ if str_column_list:
46
+ if "," in str_column_list:
47
+ # Split each comma separated column name into individual list items
48
+ cols = [s.strip() for s in str_column_list.split(",")]
49
+ str_each = [f"COALESCE({i}, '{str_null_value}')" for i in cols]
50
+ str_expression = "CONCAT(" + ", ".join(str_each) + ")"
51
+ else:
52
+ str_expression = str_column_list
53
+ return str_expression
@@ -0,0 +1,25 @@
1
+ from testgen import settings
2
+
3
+
4
+ def get_tg_host() -> str:
5
+ return settings.DATABASE_HOST
6
+
7
+
8
+ def get_tg_port() -> str:
9
+ return settings.DATABASE_PORT
10
+
11
+
12
+ def get_tg_db() -> str:
13
+ return settings.DATABASE_NAME
14
+
15
+
16
+ def get_tg_schema() -> str:
17
+ return settings.DATABASE_SCHEMA
18
+
19
+
20
+ def get_tg_username() -> str:
21
+ return settings.DATABASE_USER
22
+
23
+
24
+ def get_tg_password() -> str:
25
+ return settings.DATABASE_PASSWORD
File without changes