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.
- dataops_testgen-2.2.0.dist-info/LICENSE +203 -0
- dataops_testgen-2.2.0.dist-info/METADATA +287 -0
- dataops_testgen-2.2.0.dist-info/NOTICE +5 -0
- dataops_testgen-2.2.0.dist-info/RECORD +270 -0
- dataops_testgen-2.2.0.dist-info/WHEEL +5 -0
- dataops_testgen-2.2.0.dist-info/entry_points.txt +2 -0
- dataops_testgen-2.2.0.dist-info/top_level.txt +1 -0
- testgen/__init__.py +0 -0
- testgen/__main__.py +770 -0
- testgen/commands/__init__.py +0 -0
- testgen/commands/queries/__init__.py +0 -0
- testgen/commands/queries/execute_cat_tests_query.py +95 -0
- testgen/commands/queries/execute_tests_query.py +160 -0
- testgen/commands/queries/generate_tests_query.py +94 -0
- testgen/commands/queries/profiling_query.py +366 -0
- testgen/commands/queries/test_parameter_validation_query.py +88 -0
- testgen/commands/run_execute_cat_tests.py +162 -0
- testgen/commands/run_execute_tests.py +168 -0
- testgen/commands/run_generate_tests.py +107 -0
- testgen/commands/run_get_entities.py +122 -0
- testgen/commands/run_launch_db_config.py +84 -0
- testgen/commands/run_observability_exporter.py +330 -0
- testgen/commands/run_profiling_bridge.py +495 -0
- testgen/commands/run_quick_start.py +168 -0
- testgen/commands/run_setup_profiling_tools.py +96 -0
- testgen/commands/run_test_definition.py +146 -0
- testgen/commands/run_test_parameter_validation.py +135 -0
- testgen/commands/run_upgrade_db_config.py +156 -0
- testgen/common/__init__.py +8 -0
- testgen/common/clean_sql.py +53 -0
- testgen/common/credentials.py +25 -0
- testgen/common/database/__init__.py +0 -0
- testgen/common/database/database_service.py +629 -0
- testgen/common/database/flavor/__init__.py +0 -0
- testgen/common/database/flavor/flavor_service.py +75 -0
- testgen/common/database/flavor/mssql_flavor_service.py +34 -0
- testgen/common/database/flavor/postgresql_flavor_service.py +5 -0
- testgen/common/database/flavor/redshift_flavor_service.py +22 -0
- testgen/common/database/flavor/snowflake_flavor_service.py +69 -0
- testgen/common/database/flavor/trino_flavor_service.py +21 -0
- testgen/common/date_service.py +68 -0
- testgen/common/display_service.py +85 -0
- testgen/common/docker_service.py +76 -0
- testgen/common/encrypt.py +55 -0
- testgen/common/get_pipeline_parms.py +57 -0
- testgen/common/logs.py +79 -0
- testgen/common/process_service.py +62 -0
- testgen/common/read_file.py +69 -0
- testgen/settings.py +440 -0
- testgen/template/dbsetup/010_create_base_schema.sql +2 -0
- testgen/template/dbsetup/020_create_standard_functions_sprocs.sql +179 -0
- testgen/template/dbsetup/030_initialize_new_schema_structure.sql +735 -0
- testgen/template/dbsetup/040_populate_new_schema_project.sql +59 -0
- testgen/template/dbsetup/050_populate_new_schema_metadata.sql +1517 -0
- testgen/template/dbsetup/060_create_standard_views.sql +248 -0
- testgen/template/dbsetup/070_create_default_users.sql +17 -0
- testgen/template/dbsetup/075_grant_role_rights.sql +43 -0
- testgen/template/dbsetup/080_set_current_revision.sql +5 -0
- testgen/template/dbupgrade/0100_incremental_upgrade.sql +5 -0
- testgen/template/dbupgrade/0101_incremental_upgrade.sql +15 -0
- testgen/template/dbupgrade/0102_incremental_upgrade.sql +4 -0
- testgen/template/dbupgrade/0103_incremental_upgrade.sql +22 -0
- testgen/template/dbupgrade/0104_incremental_upgrade.sql +44 -0
- testgen/template/dbupgrade/0105_incremental_upgrade.sql +1 -0
- testgen/template/dbupgrade/0106_incremental_upgrade.sql +5 -0
- testgen/template/dbupgrade/0107_incremental_upgrade.sql +3 -0
- testgen/template/dbupgrade_helpers/get_tg_revision.sql +2 -0
- testgen/template/exec_cat_tests/ex_cat_build_agg_table_tests.sql +116 -0
- testgen/template/exec_cat_tests/ex_cat_get_distinct_tables.sql +11 -0
- testgen/template/exec_cat_tests/ex_cat_results_parse.sql +69 -0
- testgen/template/exec_cat_tests/ex_cat_retrieve_agg_test_parms.sql +6 -0
- testgen/template/exec_cat_tests/ex_cat_test_query.sql +8 -0
- testgen/template/execution/ex_finalize_test_run_results.sql +37 -0
- testgen/template/execution/ex_get_tests_non_cat.sql +47 -0
- testgen/template/execution/ex_update_test_record_in_testrun_table.sql +27 -0
- testgen/template/execution/ex_write_test_record_to_testrun_table.sql +6 -0
- testgen/template/flavors/generic/exec_query_tests/ex_aggregate_match_no_drops_generic.sql +48 -0
- testgen/template/flavors/generic/exec_query_tests/ex_aggregate_match_num_incr_generic.sql +34 -0
- testgen/template/flavors/generic/exec_query_tests/ex_aggregate_match_percent_above_generic.sql +49 -0
- testgen/template/flavors/generic/exec_query_tests/ex_aggregate_match_percent_within_generic.sql +49 -0
- testgen/template/flavors/generic/exec_query_tests/ex_aggregate_match_same_generic.sql +49 -0
- testgen/template/flavors/generic/exec_query_tests/ex_custom_query_generic.sql +39 -0
- testgen/template/flavors/generic/exec_query_tests/ex_data_match_2way_generic.sql +58 -0
- testgen/template/flavors/generic/exec_query_tests/ex_data_match_generic.sql +44 -0
- testgen/template/flavors/generic/exec_query_tests/ex_prior_match_generic.sql +37 -0
- testgen/template/flavors/generic/exec_query_tests/ex_relative_entropy_generic.sql +53 -0
- testgen/template/flavors/generic/exec_query_tests/ex_window_match_no_drops_generic.sql +46 -0
- testgen/template/flavors/generic/exec_query_tests/ex_window_match_same_generic.sql +59 -0
- testgen/template/flavors/generic/profiling/contingency_counts.sql +3 -0
- testgen/template/flavors/generic/validate_tests/ex_get_project_column_list_generic.sql +3 -0
- testgen/template/flavors/mssql/exec_query_tests/ex_relative_entropy_mssql.sql +53 -0
- testgen/template/flavors/mssql/profiling/project_ddf_query_mssql.sql +35 -0
- testgen/template/flavors/mssql/profiling/project_profiling_query_mssql.yaml +246 -0
- testgen/template/flavors/mssql/profiling/project_secondary_profiling_query_mssql.sql +36 -0
- testgen/template/flavors/mssql/setup_profiling_tools/00_drop_existing_functions_mssql.sql +8 -0
- testgen/template/flavors/mssql/setup_profiling_tools/01_create_functions_mssql.sql +12 -0
- testgen/template/flavors/mssql/setup_profiling_tools/02_create_functions_mssql.sql +54 -0
- testgen/template/flavors/mssql/setup_profiling_tools/create_qc_schema_mssql.sql +4 -0
- testgen/template/flavors/mssql/setup_profiling_tools/grant_execute_privileges_mssql.sql +1 -0
- testgen/template/flavors/postgresql/exec_query_tests/ex_window_match_no_drops_postgresql.sql +46 -0
- testgen/template/flavors/postgresql/exec_query_tests/ex_window_match_same_postgresql.sql +59 -0
- testgen/template/flavors/postgresql/profiling/project_ddf_query_postgresql.sql +42 -0
- testgen/template/flavors/postgresql/profiling/project_profiling_query_postgresql.yaml +225 -0
- testgen/template/flavors/postgresql/profiling/project_secondary_profiling_query_postgresql.sql +28 -0
- testgen/template/flavors/postgresql/setup_profiling_tools/create_functions_postgresql.sql +157 -0
- testgen/template/flavors/postgresql/setup_profiling_tools/create_qc_schema_postgresql.sql +1 -0
- testgen/template/flavors/postgresql/setup_profiling_tools/grant_execute_privileges_postgresql.sql +2 -0
- testgen/template/flavors/redshift/profiling/project_ddf_query_redshift.sql +38 -0
- testgen/template/flavors/redshift/profiling/project_profiling_query_redshift.yaml +221 -0
- testgen/template/flavors/redshift/profiling/project_secondary_profiling_query_redshift.sql +29 -0
- testgen/template/flavors/redshift/setup_profiling_tools/create_functions_redshift.sql +115 -0
- testgen/template/flavors/redshift/setup_profiling_tools/create_qc_schema_redshift.sql +1 -0
- testgen/template/flavors/redshift/setup_profiling_tools/grant_execute_privileges_redshift.sql +2 -0
- testgen/template/flavors/snowflake/profiling/project_ddf_query_snowflake.sql +38 -0
- testgen/template/flavors/snowflake/profiling/project_profiling_query_snowflake.yaml +220 -0
- testgen/template/flavors/snowflake/profiling/project_secondary_profiling_query_snowflake.sql +29 -0
- testgen/template/flavors/snowflake/setup_profiling_tools/create_functions_snowflake.sql +69 -0
- testgen/template/flavors/snowflake/setup_profiling_tools/create_qc_schema_snowflake.sql +1 -0
- testgen/template/flavors/snowflake/setup_profiling_tools/grant_execute_privileges_snowflake.sql +6 -0
- testgen/template/flavors/trino/profiling/project_profiling_query_trino.yaml +219 -0
- testgen/template/flavors/trino/setup_profiling_tools/create_functions_trino.sql +92 -0
- testgen/template/flavors/trino/setup_profiling_tools/create_qc_schema_trino.sql +1 -0
- testgen/template/gen_funny_cat_tests/gen_test_constant.sql +104 -0
- testgen/template/gen_funny_cat_tests/gen_test_distinct_value_ct.sql +98 -0
- testgen/template/gen_funny_cat_tests/gen_test_row_ct.sql +57 -0
- testgen/template/gen_funny_cat_tests/gen_test_row_ct_pct.sql +59 -0
- testgen/template/generation/gen_delete_old_tests.sql +5 -0
- testgen/template/generation/gen_insert_test_suite.sql +5 -0
- testgen/template/generation/gen_retrieve_or_insert_test_suite.sql +58 -0
- testgen/template/generation/gen_standard_test_type_list.sql +13 -0
- testgen/template/generation/gen_standard_tests.sql +48 -0
- testgen/template/get_entities/get_connection.sql +21 -0
- testgen/template/get_entities/get_connections_list.sql +9 -0
- testgen/template/get_entities/get_latest.sql +4 -0
- testgen/template/get_entities/get_profile.sql +12 -0
- testgen/template/get_entities/get_profile_info.sql +17 -0
- testgen/template/get_entities/get_profile_list.sql +17 -0
- testgen/template/get_entities/get_profile_screen.sql +275 -0
- testgen/template/get_entities/get_project_list.sql +6 -0
- testgen/template/get_entities/get_table_group_list.sql +10 -0
- testgen/template/get_entities/get_test_generation_list.sql +18 -0
- testgen/template/get_entities/get_test_info.sql +41 -0
- testgen/template/get_entities/get_test_results_for_run_cli.sql +16 -0
- testgen/template/get_entities/get_test_run_list.sql +24 -0
- testgen/template/get_entities/get_test_suite.sql +13 -0
- testgen/template/get_entities/get_test_suite_list.sql +18 -0
- testgen/template/get_entities/list_test_types.sql +4 -0
- testgen/template/observability/get_event_data.sql +23 -0
- testgen/template/observability/get_test_results.sql +41 -0
- testgen/template/observability/update_test_results_exported_to_observability.sql +12 -0
- testgen/template/parms/parms_profiling.sql +34 -0
- testgen/template/parms/parms_test_execution.sql +13 -0
- testgen/template/parms/parms_test_gen.sql +23 -0
- testgen/template/profiling/contingency_columns.sql +7 -0
- testgen/template/profiling/datatype_suggestions.sql +56 -0
- testgen/template/profiling/functional_datatype.sql +523 -0
- testgen/template/profiling/functional_tabletype_stage.sql +48 -0
- testgen/template/profiling/functional_tabletype_update.sql +8 -0
- testgen/template/profiling/pii_flag.sql +133 -0
- testgen/template/profiling/profile_anomalies_screen_column.sql +22 -0
- testgen/template/profiling/profile_anomalies_screen_multi_column.sql +58 -0
- testgen/template/profiling/profile_anomalies_screen_table.sql +22 -0
- testgen/template/profiling/profile_anomalies_screen_table_dates.sql +30 -0
- testgen/template/profiling/profile_anomalies_screen_variants.sql +40 -0
- testgen/template/profiling/profile_anomaly_types_get.sql +3 -0
- testgen/template/profiling/project_get_table_sample_count.sql +22 -0
- testgen/template/profiling/project_profile_run_record_insert.sql +8 -0
- testgen/template/profiling/project_profile_run_record_update.sql +5 -0
- testgen/template/profiling/project_profile_run_record_update_status.sql +5 -0
- testgen/template/profiling/project_update_profile_results_to_estimates.sql +32 -0
- testgen/template/profiling/refresh_anomalies.sql +33 -0
- testgen/template/profiling/refresh_data_chars_from_profiling.sql +156 -0
- testgen/template/profiling/secondary_profiling_columns.sql +12 -0
- testgen/template/profiling/secondary_profiling_delete.sql +4 -0
- testgen/template/profiling/secondary_profiling_update.sql +18 -0
- testgen/template/quick_start/populate_target_data.sql +1077 -0
- testgen/template/quick_start/recreate_target_data_schema.sql +167 -0
- testgen/template/quick_start/update_target_data.sql +100 -0
- testgen/template/updates/create_tmp_test_definition.sql +19 -0
- testgen/template/updates/get_test_def_parms.sql +38 -0
- testgen/template/updates/populate_stg_test_definitions.sql +184 -0
- testgen/template/validate_tests/ex_disable_tests_test_definitions.sql +5 -0
- testgen/template/validate_tests/ex_flag_tests_test_definitions.sql +64 -0
- testgen/template/validate_tests/ex_get_project_column_list_generic.sql +3 -0
- testgen/template/validate_tests/ex_get_test_column_list_tg.sql +65 -0
- testgen/template/validate_tests/ex_write_test_val_errors.sql +22 -0
- testgen/ui/__init__.py +0 -0
- testgen/ui/app.py +98 -0
- testgen/ui/assets/dk_logo.svg +46 -0
- testgen/ui/assets/question_mark.png +0 -0
- testgen/ui/assets/scripts.js +68 -0
- testgen/ui/assets/style.css +140 -0
- testgen/ui/bootstrap.py +109 -0
- testgen/ui/components/__init__.py +0 -0
- testgen/ui/components/frontend/css/KFOlCnqEu92Fr1MmEU9fBBc4.woff2 +0 -0
- testgen/ui/components/frontend/css/KFOlCnqEu92Fr1MmEU9fChc4EsA.woff2 +0 -0
- testgen/ui/components/frontend/css/KFOmCnqEu92Fr1Mu4mxK.woff2 +0 -0
- testgen/ui/components/frontend/css/KFOmCnqEu92Fr1Mu7GxKOzY.woff2 +0 -0
- testgen/ui/components/frontend/css/material-symbols-rounded.css +24 -0
- testgen/ui/components/frontend/css/material-symbols-rounded.woff2 +0 -0
- testgen/ui/components/frontend/css/roboto-font-faces.css +35 -0
- testgen/ui/components/frontend/css/shared.css +36 -0
- testgen/ui/components/frontend/img/dk_logo.svg +46 -0
- testgen/ui/components/frontend/index.html +17 -0
- testgen/ui/components/frontend/js/components/breadcrumbs.js +86 -0
- testgen/ui/components/frontend/js/components/button.js +66 -0
- testgen/ui/components/frontend/js/components/location.js +62 -0
- testgen/ui/components/frontend/js/components/select.js +75 -0
- testgen/ui/components/frontend/js/components/sidebar.js +358 -0
- testgen/ui/components/frontend/js/main.js +99 -0
- testgen/ui/components/frontend/js/streamlit.js +19 -0
- testgen/ui/components/frontend/js/van.min.js +1 -0
- testgen/ui/components/utils/__init__.py +0 -0
- testgen/ui/components/utils/callbacks.py +51 -0
- testgen/ui/components/utils/component.py +13 -0
- testgen/ui/components/widgets/__init__.py +6 -0
- testgen/ui/components/widgets/breadcrumbs.py +32 -0
- testgen/ui/components/widgets/location.py +65 -0
- testgen/ui/components/widgets/modal.py +97 -0
- testgen/ui/components/widgets/sidebar.py +69 -0
- testgen/ui/navigation/__init__.py +0 -0
- testgen/ui/navigation/menu.py +42 -0
- testgen/ui/navigation/page.py +20 -0
- testgen/ui/navigation/router.py +63 -0
- testgen/ui/queries/__init__.py +0 -0
- testgen/ui/queries/authentication_queries.py +47 -0
- testgen/ui/queries/connection_queries.py +121 -0
- testgen/ui/queries/profiling_queries.py +148 -0
- testgen/ui/queries/project_queries.py +9 -0
- testgen/ui/queries/table_group_queries.py +186 -0
- testgen/ui/queries/test_definition_queries.py +270 -0
- testgen/ui/queries/test_run_queries.py +32 -0
- testgen/ui/queries/test_suite_queries.py +145 -0
- testgen/ui/scripts/__init__.py +0 -0
- testgen/ui/scripts/patch_streamlit.py +111 -0
- testgen/ui/services/__init__.py +0 -0
- testgen/ui/services/authentication_service.py +119 -0
- testgen/ui/services/connection_service.py +220 -0
- testgen/ui/services/database_service.py +282 -0
- testgen/ui/services/form_service.py +1008 -0
- testgen/ui/services/javascript_service.py +44 -0
- testgen/ui/services/query_service.py +316 -0
- testgen/ui/services/string_service.py +12 -0
- testgen/ui/services/table_group_service.py +130 -0
- testgen/ui/services/test_definition_service.py +117 -0
- testgen/ui/services/test_run_service.py +13 -0
- testgen/ui/services/test_suite_service.py +76 -0
- testgen/ui/services/toolbar_service.py +77 -0
- testgen/ui/session.py +46 -0
- testgen/ui/views/__init__.py +0 -0
- testgen/ui/views/app_log_modal.py +92 -0
- testgen/ui/views/connections.py +72 -0
- testgen/ui/views/connections_base.py +367 -0
- testgen/ui/views/login.py +40 -0
- testgen/ui/views/not_found.py +16 -0
- testgen/ui/views/overview.py +34 -0
- testgen/ui/views/profiling_anomalies.py +501 -0
- testgen/ui/views/profiling_details.py +335 -0
- testgen/ui/views/profiling_modal.py +40 -0
- testgen/ui/views/profiling_results.py +206 -0
- testgen/ui/views/profiling_summary.py +177 -0
- testgen/ui/views/project_settings.py +74 -0
- testgen/ui/views/table_groups.py +530 -0
- testgen/ui/views/test_definitions.py +1020 -0
- testgen/ui/views/test_results.py +908 -0
- testgen/ui/views/test_runs.py +195 -0
- testgen/ui/views/test_suites.py +545 -0
- testgen/utils/__init__.py +0 -0
- testgen/utils/plugins.py +17 -0
- 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,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
|