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,121 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
import streamlit as st
|
|
3
|
+
|
|
4
|
+
import testgen.ui.services.database_service as db
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def get_by_id(connection_id):
|
|
8
|
+
str_schema = st.session_state["dbschema"]
|
|
9
|
+
str_sql = f"""
|
|
10
|
+
SELECT id::VARCHAR(50), project_code, connection_id, connection_name,
|
|
11
|
+
sql_flavor, project_host, project_port, project_user, project_qc_schema,
|
|
12
|
+
project_db, project_pw_encrypted, NULL as password,
|
|
13
|
+
max_threads, max_query_chars, url, connect_by_url, connect_by_key, private_key, private_key_passphrase
|
|
14
|
+
FROM {str_schema}.connections
|
|
15
|
+
WHERE connection_id = '{connection_id}'
|
|
16
|
+
"""
|
|
17
|
+
return db.retrieve_data(str_sql)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def get_connections(project_code):
|
|
21
|
+
str_schema = st.session_state["dbschema"]
|
|
22
|
+
str_sql = f"""
|
|
23
|
+
SELECT id::VARCHAR(50), project_code, connection_id, connection_name,
|
|
24
|
+
sql_flavor, project_host, project_port, project_user, project_qc_schema,
|
|
25
|
+
project_db, project_pw_encrypted, NULL as password,
|
|
26
|
+
max_threads, max_query_chars, connect_by_url, url, connect_by_key, private_key,
|
|
27
|
+
private_key_passphrase
|
|
28
|
+
FROM {str_schema}.connections
|
|
29
|
+
WHERE project_code = '{project_code}'
|
|
30
|
+
ORDER BY connection_id
|
|
31
|
+
"""
|
|
32
|
+
return db.retrieve_data(str_sql)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_table_group_names_by_connection(schema: str, connection_ids: list[str]) -> pd.DataFrame:
|
|
36
|
+
items = [f"'{item}'" for item in connection_ids]
|
|
37
|
+
str_sql = f"""select table_groups_name from {schema}.table_groups where connection_id in ({",".join(items)})"""
|
|
38
|
+
return db.retrieve_data(str_sql)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def edit_connection(schema, connection, encrypted_password, encrypted_private_key, encrypted_private_key_passphrase):
|
|
42
|
+
sql = f"""UPDATE {schema}.connections SET
|
|
43
|
+
project_code = '{connection["project_code"]}',
|
|
44
|
+
sql_flavor = '{connection["sql_flavor"]}',
|
|
45
|
+
project_host = '{connection["project_host"]}',
|
|
46
|
+
project_port = '{connection["project_port"]}',
|
|
47
|
+
project_user = '{connection["project_user"]}',
|
|
48
|
+
project_db = '{connection["project_db"]}',
|
|
49
|
+
project_qc_schema = '{connection["project_qc_schema"]}',
|
|
50
|
+
connection_name = '{connection["connection_name"]}',
|
|
51
|
+
max_threads = '{connection["max_threads"]}',
|
|
52
|
+
max_query_chars = '{connection["max_query_chars"]}',
|
|
53
|
+
url = '{connection["url"]}',
|
|
54
|
+
connect_by_key = '{connection["connect_by_key"]}',
|
|
55
|
+
connect_by_url = '{connection["connect_by_url"]}'"""
|
|
56
|
+
|
|
57
|
+
if encrypted_password:
|
|
58
|
+
sql += f""", project_pw_encrypted = '{encrypted_password}' """
|
|
59
|
+
|
|
60
|
+
if encrypted_private_key:
|
|
61
|
+
sql += f""", private_key = '{encrypted_private_key}' """
|
|
62
|
+
|
|
63
|
+
if encrypted_private_key_passphrase:
|
|
64
|
+
sql += f""", private_key_passphrase = '{encrypted_private_key_passphrase}' """
|
|
65
|
+
|
|
66
|
+
sql += f""" WHERE connection_id = '{connection["connection_id"]}';"""
|
|
67
|
+
db.execute_sql(sql)
|
|
68
|
+
st.cache_data.clear()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def add_connection(schema, connection, encrypted_password, encrypted_private_key, encrypted_private_key_passphrase):
|
|
72
|
+
|
|
73
|
+
sql_header = f"""INSERT INTO {schema}.connections
|
|
74
|
+
(project_code, sql_flavor, url, connect_by_url, connect_by_key,
|
|
75
|
+
project_host, project_port, project_user, project_db, project_qc_schema,
|
|
76
|
+
connection_name,"""
|
|
77
|
+
|
|
78
|
+
sql_footer = f""" SELECT
|
|
79
|
+
'{connection["project_code"]}' as project_code,
|
|
80
|
+
'{connection["sql_flavor"]}' as sql_flavor,
|
|
81
|
+
'{connection["url"]}' as url,
|
|
82
|
+
{connection["connect_by_url"]} as connect_by_url,
|
|
83
|
+
{connection["connect_by_key"]} as connect_by_key,
|
|
84
|
+
'{connection["project_host"]}' as project_host,
|
|
85
|
+
'{connection["project_port"]}' as project_port,
|
|
86
|
+
'{connection["project_user"]}' as project_user,
|
|
87
|
+
'{connection["project_db"]}' as project_db,
|
|
88
|
+
'{connection["project_qc_schema"]}' as project_qc_schema,
|
|
89
|
+
'{connection["connection_name"]}' as connection_name, """
|
|
90
|
+
|
|
91
|
+
if encrypted_password:
|
|
92
|
+
sql_header += "project_pw_encrypted, "
|
|
93
|
+
sql_footer += f""" '{encrypted_password}' as project_pw_encrypted, """
|
|
94
|
+
|
|
95
|
+
if encrypted_private_key:
|
|
96
|
+
sql_header += "private_key, "
|
|
97
|
+
sql_footer += f""" '{encrypted_private_key}' as private_key, """
|
|
98
|
+
|
|
99
|
+
if encrypted_private_key_passphrase:
|
|
100
|
+
sql_header += "private_key_passphrase, "
|
|
101
|
+
sql_footer += f""" '{encrypted_private_key_passphrase}' as private_key_passphrase, """
|
|
102
|
+
|
|
103
|
+
sql_header += """max_threads, max_query_chars) """
|
|
104
|
+
|
|
105
|
+
sql_footer += f""" '{connection["max_threads"]}' as max_threads,
|
|
106
|
+
'{connection["max_query_chars"]}' as max_query_chars;"""
|
|
107
|
+
|
|
108
|
+
sql = sql_header + sql_footer
|
|
109
|
+
|
|
110
|
+
db.execute_sql(sql)
|
|
111
|
+
st.cache_data.clear()
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def delete_connections(schema, connection_ids):
|
|
115
|
+
if connection_ids is None or len(connection_ids) == 0:
|
|
116
|
+
raise ValueError("No connection is specified.")
|
|
117
|
+
|
|
118
|
+
items = [f"'{item}'" for item in connection_ids]
|
|
119
|
+
sql = f"""DELETE FROM {schema}.connections WHERE connection_id in ({",".join(items)})"""
|
|
120
|
+
db.execute_sql(sql)
|
|
121
|
+
st.cache_data.clear()
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import streamlit as st
|
|
2
|
+
|
|
3
|
+
import testgen.ui.services.database_service as db
|
|
4
|
+
import testgen.ui.services.query_service as dq
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@st.cache_data(show_spinner=False)
|
|
8
|
+
def run_table_groups_lookup_query(str_project_code):
|
|
9
|
+
str_schema = st.session_state["dbschema"]
|
|
10
|
+
return dq.run_table_groups_lookup_query(str_schema, str_project_code)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@st.cache_data(show_spinner=False)
|
|
14
|
+
def get_latest_profile_run(str_table_group):
|
|
15
|
+
str_schema = st.session_state["dbschema"]
|
|
16
|
+
str_sql = f"""
|
|
17
|
+
WITH last_profile_run
|
|
18
|
+
AS (SELECT table_groups_id, MAX(profiling_starttime) as last_profile_run_date
|
|
19
|
+
FROM {str_schema}.profiling_runs
|
|
20
|
+
GROUP BY table_groups_id)
|
|
21
|
+
SELECT id as profile_run_id
|
|
22
|
+
FROM {str_schema}.profiling_runs r
|
|
23
|
+
INNER JOIN last_profile_run l
|
|
24
|
+
ON (r.table_groups_id = l.table_groups_id
|
|
25
|
+
AND r.profiling_starttime = l.last_profile_run_date)
|
|
26
|
+
WHERE r.table_groups_id = '{str_table_group}';
|
|
27
|
+
"""
|
|
28
|
+
str_profile_run_id = db.retrieve_single_result(str_sql)
|
|
29
|
+
|
|
30
|
+
return str_profile_run_id
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@st.cache_data(show_spinner=False)
|
|
34
|
+
def get_db_profile_run_choices(str_table_groups_id):
|
|
35
|
+
str_schema = st.session_state["dbschema"]
|
|
36
|
+
# Define the query
|
|
37
|
+
str_sql = f"""
|
|
38
|
+
SELECT DISTINCT profiling_starttime as profile_run_date, id
|
|
39
|
+
FROM {str_schema}.profiling_runs pr
|
|
40
|
+
WHERE pr.table_groups_id = '{str_table_groups_id}'
|
|
41
|
+
ORDER BY profiling_starttime DESC;
|
|
42
|
+
"""
|
|
43
|
+
# Retrieve and return data as df
|
|
44
|
+
return db.retrieve_data(str_sql)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@st.cache_data(show_spinner=False)
|
|
48
|
+
def run_table_lookup_query(str_table_groups_id):
|
|
49
|
+
str_schema = st.session_state["dbschema"]
|
|
50
|
+
str_sql = f"""
|
|
51
|
+
SELECT DISTINCT table_name
|
|
52
|
+
FROM {str_schema}.profile_results
|
|
53
|
+
WHERE table_groups_id = '{str_table_groups_id}'::UUID
|
|
54
|
+
ORDER BY table_name
|
|
55
|
+
"""
|
|
56
|
+
return db.retrieve_data(str_sql)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@st.cache_data(show_spinner=False)
|
|
60
|
+
def run_column_lookup_query(str_table_groups_id, str_table_name):
|
|
61
|
+
str_schema = st.session_state["dbschema"]
|
|
62
|
+
return dq.run_column_lookup_query(str_schema, str_table_groups_id, str_table_name)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@st.cache_data(show_spinner=False)
|
|
66
|
+
def lookup_db_parentage_from_run(str_profile_run_id):
|
|
67
|
+
str_schema = st.session_state["dbschema"]
|
|
68
|
+
# Define the query
|
|
69
|
+
str_sql = f"""
|
|
70
|
+
SELECT profiling_starttime as profile_run_date, g.table_groups_name
|
|
71
|
+
FROM {str_schema}.profiling_runs pr
|
|
72
|
+
INNER JOIN {str_schema}.table_groups g
|
|
73
|
+
ON pr.table_groups_id = g.id
|
|
74
|
+
WHERE pr.id = '{str_profile_run_id}'
|
|
75
|
+
"""
|
|
76
|
+
df = db.retrieve_data(str_sql)
|
|
77
|
+
if not df.empty:
|
|
78
|
+
return df.at[0, "profile_run_date"], df.at[0, "table_groups_name"]
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@st.cache_data(show_spinner="Retrieving Data")
|
|
82
|
+
def get_profiling_detail(str_profile_run_id, str_table_name, str_column_name):
|
|
83
|
+
str_schema = st.session_state["dbschema"]
|
|
84
|
+
str_sql = f"""
|
|
85
|
+
SELECT -- Identifiers
|
|
86
|
+
id::VARCHAR, dk_id,
|
|
87
|
+
p.project_code, connection_id, p.table_groups_id::VARCHAR,
|
|
88
|
+
p.profile_run_id::VARCHAR,
|
|
89
|
+
run_date, sample_ratio,
|
|
90
|
+
-- Column basics
|
|
91
|
+
p.schema_name, p.table_name, position, p.column_name,
|
|
92
|
+
p.column_type, general_type as general_type_abbr,
|
|
93
|
+
CASE general_type
|
|
94
|
+
WHEN 'A' THEN 'Alpha'
|
|
95
|
+
WHEN 'N' THEN 'Numeric'
|
|
96
|
+
WHEN 'D' THEN 'Date'
|
|
97
|
+
WHEN 'T' THEN 'Time'
|
|
98
|
+
WHEN 'B' THEN 'Boolean'
|
|
99
|
+
ELSE 'N/A'
|
|
100
|
+
END as general_type,
|
|
101
|
+
functional_table_type as semantic_table_type,
|
|
102
|
+
functional_data_type as semantic_data_type,
|
|
103
|
+
datatype_suggestion,
|
|
104
|
+
CASE WHEN s.column_name IS NOT NULL THEN 'Yes' END as anomalies,
|
|
105
|
+
-- Shared counts
|
|
106
|
+
record_ct, value_ct, distinct_value_ct, null_value_ct,
|
|
107
|
+
-- Shared except for B and X
|
|
108
|
+
min_length, max_length, avg_length,
|
|
109
|
+
-- Alpha counts
|
|
110
|
+
distinct_std_value_ct,
|
|
111
|
+
numeric_ct, date_ct,
|
|
112
|
+
filled_value_ct as dummy_value_ct,
|
|
113
|
+
CASE WHEN general_type = 'A' THEN COALESCE(zero_length_ct, 0) END as zero_length_ct,
|
|
114
|
+
CASE WHEN general_type = 'A' THEN COALESCE(lead_space_ct, 0) END as lead_space_ct,
|
|
115
|
+
CASE WHEN general_type = 'A' THEN COALESCE(quoted_value_ct, 0) END as quoted_value_ct,
|
|
116
|
+
CASE WHEN general_type = 'A' THEN COALESCE(includes_digit_ct, 0) END as includes_digit_ct,
|
|
117
|
+
CASE WHEN general_type = 'A' THEN COALESCE(embedded_space_ct, 0) END as embedded_space_ct,
|
|
118
|
+
avg_embedded_spaces,
|
|
119
|
+
min_text, max_text,
|
|
120
|
+
std_pattern_match,
|
|
121
|
+
top_patterns,
|
|
122
|
+
top_freq_values, distinct_value_hash,
|
|
123
|
+
distinct_pattern_ct,
|
|
124
|
+
-- A and N
|
|
125
|
+
zero_value_ct,
|
|
126
|
+
-- Numeric
|
|
127
|
+
min_value, min_value_over_0, max_value,
|
|
128
|
+
avg_value, stdev_value, percentile_25, percentile_50, percentile_75,
|
|
129
|
+
fractional_sum,
|
|
130
|
+
-- Dates
|
|
131
|
+
min_date, max_date,
|
|
132
|
+
before_1yr_date_ct, before_5yr_date_ct, within_1yr_date_ct, within_1mo_date_ct, future_date_ct,
|
|
133
|
+
date_days_present, date_weeks_present, date_months_present,
|
|
134
|
+
-- Boolean
|
|
135
|
+
boolean_true_ct
|
|
136
|
+
FROM {str_schema}.profile_results p
|
|
137
|
+
LEFT JOIN (SELECT DISTINCT profile_run_id, table_name, column_name
|
|
138
|
+
FROM {str_schema}.profile_anomaly_results) s
|
|
139
|
+
ON (p.profile_run_id = s.profile_run_id
|
|
140
|
+
AND p.table_name = s.table_name
|
|
141
|
+
AND p.column_name = s.column_name)
|
|
142
|
+
WHERE p.profile_run_id = '{str_profile_run_id}'::UUID
|
|
143
|
+
AND p.table_name ILIKE '{str_table_name}'
|
|
144
|
+
AND p.column_name ILIKE '{str_column_name}'
|
|
145
|
+
ORDER BY p.schema_name, p.table_name, position;
|
|
146
|
+
"""
|
|
147
|
+
|
|
148
|
+
return db.retrieve_data(str_sql)
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import streamlit as st
|
|
2
|
+
|
|
3
|
+
import testgen.ui.services.database_service as db
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def _get_select_statement(schema):
|
|
7
|
+
return f"""
|
|
8
|
+
SELECT id::VARCHAR(50), project_code, connection_id, table_groups_name,
|
|
9
|
+
table_group_schema,
|
|
10
|
+
profiling_include_mask, profiling_exclude_mask,
|
|
11
|
+
profiling_table_set,
|
|
12
|
+
profile_id_column_mask, profile_sk_column_mask,
|
|
13
|
+
data_source, source_system, data_location, business_domain,
|
|
14
|
+
transform_level, source_process, stakeholder_group,
|
|
15
|
+
profile_use_sampling, profile_sample_percent, profile_sample_min_count,
|
|
16
|
+
profiling_delay_days
|
|
17
|
+
FROM {schema}.table_groups
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@st.cache_data(show_spinner=False)
|
|
22
|
+
def get_by_id(schema, table_group_id):
|
|
23
|
+
sql = _get_select_statement(schema)
|
|
24
|
+
sql += f"""WHERE id = '{table_group_id}'
|
|
25
|
+
ORDER BY table_groups_name
|
|
26
|
+
"""
|
|
27
|
+
return db.retrieve_data(sql)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def get_test_suite_names_by_table_group_names(schema, table_group_names):
|
|
31
|
+
items = [f"'{item}'" for item in table_group_names]
|
|
32
|
+
sql = f"""select test_suite
|
|
33
|
+
from {schema}.test_suites ts
|
|
34
|
+
inner join {schema}.table_groups tg on tg.id = ts.table_groups_id
|
|
35
|
+
where tg.table_groups_name in ({",".join(items)})
|
|
36
|
+
"""
|
|
37
|
+
return db.retrieve_data(sql)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def get_table_group_dependencies(schema, table_group_names):
|
|
41
|
+
if table_group_names is None or len(table_group_names) == 0:
|
|
42
|
+
raise ValueError("No Table Group is specified.")
|
|
43
|
+
|
|
44
|
+
table_group_items = [f"'{item}'" for item in table_group_names]
|
|
45
|
+
sql = f"""select ppr.profile_run_id from {schema}.profile_pair_rules ppr
|
|
46
|
+
INNER JOIN {schema}.profiling_runs pr ON pr.id = ppr.profile_run_id
|
|
47
|
+
INNER JOIN {schema}.table_groups tg ON tg.id = pr.table_groups_id
|
|
48
|
+
where tg.table_groups_name in ({",".join(table_group_items)})
|
|
49
|
+
union
|
|
50
|
+
select par.table_groups_id from {schema}.profile_anomaly_results par INNER JOIN {schema}.table_groups tg ON tg.id = par.table_groups_id where tg.table_groups_name in ({",".join(table_group_items)})
|
|
51
|
+
union
|
|
52
|
+
select pr.table_groups_id from {schema}.profile_results pr INNER JOIN {schema}.table_groups tg ON tg.id = pr.table_groups_id where tg.table_groups_name in ({",".join(table_group_items)})
|
|
53
|
+
union
|
|
54
|
+
select pr.table_groups_id from {schema}.profiling_runs pr INNER JOIN {schema}.table_groups tg ON tg.id = pr.table_groups_id where tg.table_groups_name in ({",".join(table_group_items)})
|
|
55
|
+
union
|
|
56
|
+
select dtc.table_groups_id from {schema}.data_table_chars dtc INNER JOIN {schema}.table_groups tg ON tg.id = dtc.table_groups_id where tg.table_groups_name in ({",".join(table_group_items)})
|
|
57
|
+
union
|
|
58
|
+
select dcs.table_groups_id from {schema}.data_column_chars dcs INNER JOIN {schema}.table_groups tg ON tg.id = dcs.table_groups_id where tg.table_groups_name in ({",".join(table_group_items)});"""
|
|
59
|
+
return db.retrieve_data(sql)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def get_table_group_usage(schema, table_group_names):
|
|
63
|
+
items = [f"'{item}'" for item in table_group_names]
|
|
64
|
+
sql = f"""select distinct pr.id from {schema}.profiling_runs pr
|
|
65
|
+
INNER JOIN {schema}.table_groups tg ON tg.id = pr.table_groups_id
|
|
66
|
+
where tg.table_groups_name in ({",".join(items)}) and pr.status = 'Running'"""
|
|
67
|
+
return db.retrieve_data(sql)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@st.cache_data(show_spinner=False)
|
|
71
|
+
def get_by_connection(schema, project_code, connection_id):
|
|
72
|
+
sql = _get_select_statement(schema)
|
|
73
|
+
sql += f"""WHERE project_code = '{project_code}'
|
|
74
|
+
AND connection_id = '{connection_id}'
|
|
75
|
+
ORDER BY table_groups_name
|
|
76
|
+
"""
|
|
77
|
+
return db.retrieve_data(sql)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def edit(schema, table_group):
|
|
81
|
+
sql = f"""UPDATE {schema}.table_groups
|
|
82
|
+
SET
|
|
83
|
+
table_groups_name='{table_group["table_groups_name"]}',
|
|
84
|
+
table_group_schema='{table_group["table_group_schema"]}',
|
|
85
|
+
profiling_table_set=NULLIF('{table_group["profiling_table_set"]}', ''),
|
|
86
|
+
profiling_include_mask='{table_group["profiling_include_mask"]}',
|
|
87
|
+
profiling_exclude_mask='{table_group["profiling_exclude_mask"]}',
|
|
88
|
+
profile_id_column_mask='{table_group["profile_id_column_mask"]}',
|
|
89
|
+
profile_sk_column_mask='{table_group["profile_sk_column_mask"]}',
|
|
90
|
+
profile_use_sampling='{'Y' if table_group["profile_use_sampling"] else 'N'}',
|
|
91
|
+
profile_sample_percent='{table_group["profile_sample_percent"]}',
|
|
92
|
+
profile_sample_min_count={int(table_group["profile_sample_min_count"])},
|
|
93
|
+
profiling_delay_days='{table_group["profiling_delay_days"]}',
|
|
94
|
+
data_source='{table_group["data_source"]}',
|
|
95
|
+
source_system='{table_group["source_system"]}',
|
|
96
|
+
data_location='{table_group["data_location"]}',
|
|
97
|
+
business_domain='{table_group["business_domain"]}',
|
|
98
|
+
transform_level='{table_group["transform_level"]}',
|
|
99
|
+
source_process='{table_group["source_process"]}',
|
|
100
|
+
stakeholder_group='{table_group["stakeholder_group"]}'
|
|
101
|
+
where
|
|
102
|
+
id = '{table_group["id"]}'
|
|
103
|
+
;
|
|
104
|
+
"""
|
|
105
|
+
db.execute_sql(sql)
|
|
106
|
+
st.cache_data.clear()
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def add(schema, table_group):
|
|
110
|
+
sql = f"""INSERT INTO {schema}.table_groups
|
|
111
|
+
(id,
|
|
112
|
+
project_code,
|
|
113
|
+
connection_id,
|
|
114
|
+
table_groups_name,
|
|
115
|
+
table_group_schema,
|
|
116
|
+
profiling_table_set,
|
|
117
|
+
profiling_include_mask,
|
|
118
|
+
profiling_exclude_mask,
|
|
119
|
+
profile_id_column_mask,
|
|
120
|
+
profile_sk_column_mask,
|
|
121
|
+
profile_use_sampling,
|
|
122
|
+
profile_sample_percent,
|
|
123
|
+
profile_sample_min_count,
|
|
124
|
+
profiling_delay_days,
|
|
125
|
+
data_source,
|
|
126
|
+
source_system,
|
|
127
|
+
data_location,
|
|
128
|
+
business_domain,
|
|
129
|
+
transform_level,
|
|
130
|
+
source_process,
|
|
131
|
+
stakeholder_group)
|
|
132
|
+
SELECT
|
|
133
|
+
gen_random_uuid(),
|
|
134
|
+
'{table_group["project_code"]}',
|
|
135
|
+
'{table_group["connection_id"]}',
|
|
136
|
+
'{table_group["table_groups_name"]}',
|
|
137
|
+
'{table_group["table_group_schema"]}',
|
|
138
|
+
NULLIF('{table_group["profiling_table_set"]}', ''),
|
|
139
|
+
'{table_group["profiling_include_mask"]}',
|
|
140
|
+
'{table_group["profiling_exclude_mask"]}',
|
|
141
|
+
'{table_group["profile_id_column_mask"]}'::character varying(2000),
|
|
142
|
+
'{table_group["profile_sk_column_mask"]}'::character varying,
|
|
143
|
+
'{'Y' if table_group["profile_use_sampling"]=='True' else 'N' }'::character varying,
|
|
144
|
+
'{table_group["profile_sample_percent"]}'::character varying,
|
|
145
|
+
{table_group["profile_sample_min_count"]}, '{table_group["profiling_delay_days"]}'::character varying,
|
|
146
|
+
'{table_group["data_source"]}',
|
|
147
|
+
'{table_group["source_system"]}',
|
|
148
|
+
'{table_group["data_location"]}',
|
|
149
|
+
'{table_group["business_domain"]}',
|
|
150
|
+
'{table_group["transform_level"]}',
|
|
151
|
+
'{table_group["source_process"]}',
|
|
152
|
+
'{table_group["stakeholder_group"]}'
|
|
153
|
+
;"""
|
|
154
|
+
db.execute_sql(sql)
|
|
155
|
+
st.cache_data.clear()
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def delete(schema, table_group_ids):
|
|
159
|
+
if table_group_ids is None or len(table_group_ids) == 0:
|
|
160
|
+
raise ValueError("No table group is specified.")
|
|
161
|
+
|
|
162
|
+
items = [f"'{item}'" for item in table_group_ids]
|
|
163
|
+
sql = f"""DELETE FROM {schema}.table_groups WHERE id in ({",".join(items)})"""
|
|
164
|
+
db.execute_sql(sql)
|
|
165
|
+
st.cache_data.clear()
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def cascade_delete(schema, table_group_names):
|
|
169
|
+
if table_group_names is None or len(table_group_names) == 0:
|
|
170
|
+
raise ValueError("No Table Group is specified.")
|
|
171
|
+
|
|
172
|
+
table_group_items = [f"'{item}'" for item in table_group_names]
|
|
173
|
+
sql = f"""delete from {schema}.profile_pair_rules ppr
|
|
174
|
+
USING {schema}.profiling_runs pr, {schema}.table_groups tg
|
|
175
|
+
WHERE
|
|
176
|
+
pr.id = ppr.profile_run_id
|
|
177
|
+
AND tg.id = pr.table_groups_id
|
|
178
|
+
AND tg.table_groups_name in ({",".join(table_group_items)});
|
|
179
|
+
delete from {schema}.profile_anomaly_results par USING {schema}.table_groups tg where tg.id = par.table_groups_id and tg.table_groups_name in ({",".join(table_group_items)});
|
|
180
|
+
delete from {schema}.profile_results pr USING {schema}.table_groups tg where tg.id = pr.table_groups_id and tg.table_groups_name in ({",".join(table_group_items)});
|
|
181
|
+
delete from {schema}.profiling_runs pr USING {schema}.table_groups tg where tg.id = pr.table_groups_id and tg.table_groups_name in ({",".join(table_group_items)});
|
|
182
|
+
delete from {schema}.data_table_chars dtc USING {schema}.table_groups tg where tg.id = dtc.table_groups_id and tg.table_groups_name in ({",".join(table_group_items)});
|
|
183
|
+
delete from {schema}.data_column_chars dcs USING {schema}.table_groups tg where tg.id = dcs.table_groups_id and tg.table_groups_name in ({",".join(table_group_items)});
|
|
184
|
+
delete from {schema}.table_groups where table_groups_name in ({",".join(table_group_items)});"""
|
|
185
|
+
db.execute_sql(sql)
|
|
186
|
+
st.cache_data.clear()
|