fdc-shared-kernel 0.0.179__tar.gz → 0.0.181__tar.gz
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.
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/PKG-INFO +3 -1
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/fdc_shared_kernel.egg-info/PKG-INFO +3 -1
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/fdc_shared_kernel.egg-info/SOURCES.txt +6 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/fdc_shared_kernel.egg-info/requires.txt +2 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/pyproject.toml +1 -1
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/requirements.txt +2 -0
- fdc_shared_kernel-0.0.181/shared_kernel/data_warehouse_handlers/connections/jdbc_warehouse_connection.py +183 -0
- fdc_shared_kernel-0.0.181/shared_kernel/data_warehouse_handlers/jdbc_driver_registry.py +82 -0
- fdc_shared_kernel-0.0.181/shared_kernel/data_warehouse_handlers/jdbc_handler.py +118 -0
- fdc_shared_kernel-0.0.181/shared_kernel/data_warehouse_handlers/odbc_handler.py +13 -0
- fdc_shared_kernel-0.0.181/shared_kernel/data_warehouse_handlers/query_executors/jdbc_query_executor.py +127 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/warehouse_handlers_map.py +2 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/dataclasses/warehouse_configs.py +27 -3
- fdc_shared_kernel-0.0.181/shared_kernel/datatype_mappings/connectors_to_system/jdbc.py +66 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/enums/connection_engine.py +1 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/README.md +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/README_pypi.md +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/fdc_shared_kernel.egg-info/dependency_links.txt +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/fdc_shared_kernel.egg-info/top_level.txt +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/setup.cfg +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/agent_communication_channel/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/agent_communication_channel/agent_channel.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/agent_communication_channel/contexts.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/agent_communication_channel/event_channel.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/ai_audit_log/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/ai_chat_persistence/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/ai_chat_persistence/chat_persistence.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/async_task_executor/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/async_task_executor/async_task_executor.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/auth/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/auth/jwt_helper.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/auth/token_handler.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/auth/workbook_permission_handler.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/batch_job/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/batch_job/batch_job_status_tracker/container_job_status_tracker.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/batch_job/job_handlers/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/batch_job/job_handlers/aws_batch_job_handler.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/batch_job/job_handlers/azure_apps_job_handler.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/batch_job/job_handlers/job_handler_factory.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/batch_job/job_handlers/job_status_mapper.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/batch_job/job_storage_managers/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/batch_job/job_storage_managers/azure_blob_storage_manager.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/batch_job/job_storage_managers/job_storage_manager_factory.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/batch_job/job_storage_managers/s3_job_storage_manager.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/config/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/constants/constants.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/connections/databricks_warehouse_connection.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/connections/mssql_warehouse_connection.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/connections/mysql_warehouse_connection.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/connections/postgresql_warehouse_connection.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/connections/redshift_warehouse_connection.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/connections/snowflake_warehouse_connection.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/custom_query_builders/databricks_query.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/databricks_handler.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/factory.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/mssql_handler.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/mysql_handler.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/postgresql_handler.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/query_executors/databricks_query_executor.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/query_executors/mssql_query_executor.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/query_executors/mysql_query_executor.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/query_executors/postgresql_query_executor.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/query_executors/redshift_query_executor.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/query_executors/snowflake_query_executor.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/redshift_handler.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/snowflake_handler.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/utils.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/database/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/dataclasses/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/dataclasses/aws_batch_job_context.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/dataclasses/azure_container_app_job_context.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/dataclasses/event_executor.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/dataclasses/job_context.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/dataclasses/job_record_dataclasses.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/csv.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/databricks.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/db2.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/jira.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/mssql.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/mysql.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/oracle.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/postgres.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/redshift.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/salesforce.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/snowflake.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/sqlalchemy.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/system_to_warehouse/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/system_to_warehouse/postgres.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/system_to_warehouse/redshift.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/enums/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/enums/async_task_executor.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/enums/status_tracker.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/event_executor/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/event_executor/event_executor.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/event_executor/job_executor.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/event_executor/utils.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/exceptions/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/exceptions/batch_job_exceptions.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/exceptions/configuration_exceptions.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/exceptions/custom_exceptions.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/exceptions/data_validation_exceptions.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/exceptions/http_exceptions.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/exceptions/infrastructure_exceptions.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/exceptions/operational_exceptions.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/exceptions/security_exceptions.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/exceptions/user_intervention_exception.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/http/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/http/httpx_http_client.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/http/request_http_client.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/interfaces/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/interfaces/base_job_handler.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/interfaces/data_warehouse_handler.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/interfaces/databus.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/interfaces/http.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/interfaces/keyvault.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/interfaces/query_executor.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/interfaces/storage_manager.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/interfaces/warehouse_connection.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/logger/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/messaging/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/messaging/aws_databus.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/messaging/azure_databus.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/messaging/http_databus.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/messaging/nats_databus.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/messaging/nats_publisher.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/messaging/nats_test.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/messaging/utils/aws_utility.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/messaging/utils/azure_utility.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/messaging/utils/event_messages.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/metrics/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/metrics/status_tracker.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/models/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/registries/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/registries/schema_onboarding_event_registry.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/registries/service_event_registry.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/base_tracker.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/enums.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/exceptions.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/run_manager.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/schema_onboarding_tracker.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/shared_helpers.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/task_determination.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/task_helpers.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/task_manager.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/template_manager.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/utility_manager.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/security/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/security/key_vault/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/security/key_vault/aws_secret_manager.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/security/key_vault/azure_keyvault.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/status_tracker/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/status_tracker/status_tracker.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/storage_handlers/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/storage_handlers/blob_file_handler.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/storage_handlers/s3_storage_handler.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/config/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/config/test_config.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/logger/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/logger/test_logger.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/messaging/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/messaging/test_aws_databus.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/messaging/test_event_executor.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/messaging/test_nats_interface.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/utils/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/utils/test_data_validators.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/utils/test_date_format_utils.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/utils/test_string_utils.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/traceability/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/traceability/traceability_handler.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/utils/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/utils/data_validators_utils.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/utils/date_format_utils.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/utils/date_utils.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/utils/string_utils.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/utils/template_renderer.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/utils/thread_debug_utils.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/utils/thread_local_storage.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/utils/thread_log_traker.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/tests/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/tests/messaging/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/tests/messaging/utils/__init__.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/tests/messaging/utils/test_aws_utility.py +0 -0
- {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/tests/test_job_executor.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fdc_shared_kernel
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.181
|
|
4
4
|
Summary: Shared library for microservice
|
|
5
5
|
Author-email: Shikhil S <shikhil.s@dbizsolution.com>, Ahammed Akdham N <ahammedakdham.n@dbizsolution.com>
|
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -45,6 +45,8 @@ Requires-Dist: redshift_connector==2.1.2
|
|
|
45
45
|
Requires-Dist: pypika==0.48.9
|
|
46
46
|
Requires-Dist: snowflake-connector-python==3.16.0
|
|
47
47
|
Requires-Dist: PyMySQL==1.1.1
|
|
48
|
+
Requires-Dist: jaydebeapi==1.2.3
|
|
49
|
+
Requires-Dist: JPype1==1.5.0
|
|
48
50
|
|
|
49
51
|
# FDC Shared Kernel
|
|
50
52
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fdc_shared_kernel
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.181
|
|
4
4
|
Summary: Shared library for microservice
|
|
5
5
|
Author-email: Shikhil S <shikhil.s@dbizsolution.com>, Ahammed Akdham N <ahammedakdham.n@dbizsolution.com>
|
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -45,6 +45,8 @@ Requires-Dist: redshift_connector==2.1.2
|
|
|
45
45
|
Requires-Dist: pypika==0.48.9
|
|
46
46
|
Requires-Dist: snowflake-connector-python==3.16.0
|
|
47
47
|
Requires-Dist: PyMySQL==1.1.1
|
|
48
|
+
Requires-Dist: jaydebeapi==1.2.3
|
|
49
|
+
Requires-Dist: JPype1==1.5.0
|
|
48
50
|
|
|
49
51
|
# FDC Shared Kernel
|
|
50
52
|
|
{fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/fdc_shared_kernel.egg-info/SOURCES.txt
RENAMED
|
@@ -37,14 +37,18 @@ shared_kernel/constants/constants.py
|
|
|
37
37
|
shared_kernel/data_warehouse_handlers/__init__.py
|
|
38
38
|
shared_kernel/data_warehouse_handlers/databricks_handler.py
|
|
39
39
|
shared_kernel/data_warehouse_handlers/factory.py
|
|
40
|
+
shared_kernel/data_warehouse_handlers/jdbc_driver_registry.py
|
|
41
|
+
shared_kernel/data_warehouse_handlers/jdbc_handler.py
|
|
40
42
|
shared_kernel/data_warehouse_handlers/mssql_handler.py
|
|
41
43
|
shared_kernel/data_warehouse_handlers/mysql_handler.py
|
|
44
|
+
shared_kernel/data_warehouse_handlers/odbc_handler.py
|
|
42
45
|
shared_kernel/data_warehouse_handlers/postgresql_handler.py
|
|
43
46
|
shared_kernel/data_warehouse_handlers/redshift_handler.py
|
|
44
47
|
shared_kernel/data_warehouse_handlers/snowflake_handler.py
|
|
45
48
|
shared_kernel/data_warehouse_handlers/utils.py
|
|
46
49
|
shared_kernel/data_warehouse_handlers/warehouse_handlers_map.py
|
|
47
50
|
shared_kernel/data_warehouse_handlers/connections/databricks_warehouse_connection.py
|
|
51
|
+
shared_kernel/data_warehouse_handlers/connections/jdbc_warehouse_connection.py
|
|
48
52
|
shared_kernel/data_warehouse_handlers/connections/mssql_warehouse_connection.py
|
|
49
53
|
shared_kernel/data_warehouse_handlers/connections/mysql_warehouse_connection.py
|
|
50
54
|
shared_kernel/data_warehouse_handlers/connections/postgresql_warehouse_connection.py
|
|
@@ -52,6 +56,7 @@ shared_kernel/data_warehouse_handlers/connections/redshift_warehouse_connection.
|
|
|
52
56
|
shared_kernel/data_warehouse_handlers/connections/snowflake_warehouse_connection.py
|
|
53
57
|
shared_kernel/data_warehouse_handlers/custom_query_builders/databricks_query.py
|
|
54
58
|
shared_kernel/data_warehouse_handlers/query_executors/databricks_query_executor.py
|
|
59
|
+
shared_kernel/data_warehouse_handlers/query_executors/jdbc_query_executor.py
|
|
55
60
|
shared_kernel/data_warehouse_handlers/query_executors/mssql_query_executor.py
|
|
56
61
|
shared_kernel/data_warehouse_handlers/query_executors/mysql_query_executor.py
|
|
57
62
|
shared_kernel/data_warehouse_handlers/query_executors/postgresql_query_executor.py
|
|
@@ -70,6 +75,7 @@ shared_kernel/datatype_mappings/connectors_to_system/__init__.py
|
|
|
70
75
|
shared_kernel/datatype_mappings/connectors_to_system/csv.py
|
|
71
76
|
shared_kernel/datatype_mappings/connectors_to_system/databricks.py
|
|
72
77
|
shared_kernel/datatype_mappings/connectors_to_system/db2.py
|
|
78
|
+
shared_kernel/datatype_mappings/connectors_to_system/jdbc.py
|
|
73
79
|
shared_kernel/datatype_mappings/connectors_to_system/jira.py
|
|
74
80
|
shared_kernel/datatype_mappings/connectors_to_system/mssql.py
|
|
75
81
|
shared_kernel/datatype_mappings/connectors_to_system/mysql.py
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import hashlib
|
|
2
|
+
import time
|
|
3
|
+
import threading
|
|
4
|
+
import jaydebeapi
|
|
5
|
+
import jpype
|
|
6
|
+
import os
|
|
7
|
+
from contextlib import contextmanager
|
|
8
|
+
from typing import Dict, Any, Optional
|
|
9
|
+
|
|
10
|
+
from shared_kernel.dataclasses.warehouse_configs import JDBCConfig
|
|
11
|
+
from shared_kernel.exceptions.http_exceptions import BadRequest
|
|
12
|
+
from shared_kernel.interfaces.warehouse_connection import DataWarehouseConnection
|
|
13
|
+
from shared_kernel.logger import Logger
|
|
14
|
+
from shared_kernel.config import Config
|
|
15
|
+
from shared_kernel.data_warehouse_handlers.jdbc_driver_registry import get_jdbc_driver_config
|
|
16
|
+
|
|
17
|
+
config = Config()
|
|
18
|
+
logger = Logger(config.get("APP_NAME"))
|
|
19
|
+
|
|
20
|
+
class JDBCWarehouseConnection(DataWarehouseConnection):
|
|
21
|
+
"""
|
|
22
|
+
JDBC warehouse connection using jaydebeapi and JPype1.
|
|
23
|
+
"""
|
|
24
|
+
_jvm_lock = threading.Lock()
|
|
25
|
+
_jvm_started = False
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
source_config: JDBCConfig,
|
|
30
|
+
set_default_schema: bool = True,
|
|
31
|
+
):
|
|
32
|
+
if source_config is None:
|
|
33
|
+
raise ValueError("Missing required parameter: source_config (JDBCConfig)")
|
|
34
|
+
|
|
35
|
+
self._jdbc_config = source_config
|
|
36
|
+
self.set_default_schema = set_default_schema
|
|
37
|
+
|
|
38
|
+
# Get driver config from registry
|
|
39
|
+
self.driver_info = get_jdbc_driver_config(source_config.jdbc_subtype)
|
|
40
|
+
|
|
41
|
+
# Build or use the JDBC URL depending on connection_method
|
|
42
|
+
if source_config.connection_method == "url":
|
|
43
|
+
if not source_config.jdbc_url:
|
|
44
|
+
raise ValueError("connection_method is 'url' but 'jdbc_url' is not set in JDBCConfig.")
|
|
45
|
+
self.jdbc_url = source_config.jdbc_url
|
|
46
|
+
else:
|
|
47
|
+
# Default: host mode — build URL from template
|
|
48
|
+
# We pass the entire config __dict__ to handle all fields (host, port, workspace_id, etc.)
|
|
49
|
+
self.jdbc_url = self.driver_info["url_template"].format(
|
|
50
|
+
**source_config.__dict__
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
self._start_jvm_if_needed()
|
|
54
|
+
|
|
55
|
+
def _start_jvm_if_needed(self):
|
|
56
|
+
"""Starts the JVM for JPype if not already running."""
|
|
57
|
+
with self.__class__._jvm_lock:
|
|
58
|
+
if not jpype.isJVMStarted():
|
|
59
|
+
jar_path = self.driver_info["jar_path"]
|
|
60
|
+
if not os.path.exists(jar_path):
|
|
61
|
+
logger.error(f"JDBC Driver JAR not found at: {jar_path}")
|
|
62
|
+
# Note: We don't raise here yet, as it might be downloaded later or
|
|
63
|
+
# specific to the environment. But for production, it should be there.
|
|
64
|
+
|
|
65
|
+
# Start JVM with the specific JAR in classpath
|
|
66
|
+
# We add all jars in the drivers directory to be safe
|
|
67
|
+
drivers_dir = os.path.dirname(jar_path)
|
|
68
|
+
|
|
69
|
+
# Ensure drivers directory exists
|
|
70
|
+
if not os.path.exists(drivers_dir):
|
|
71
|
+
logger.info(f"Creating missing JDBC drivers directory: {drivers_dir}")
|
|
72
|
+
os.makedirs(drivers_dir, exist_ok=True)
|
|
73
|
+
|
|
74
|
+
# List jars if directory exists
|
|
75
|
+
classpath = []
|
|
76
|
+
if os.path.exists(drivers_dir):
|
|
77
|
+
# Add EVERYTHING in the drivers folder to the initial classpath
|
|
78
|
+
classpath = [os.path.join(drivers_dir, f) for f in os.listdir(drivers_dir) if f.endswith('.jar')]
|
|
79
|
+
logger.info(f"Initial JDBC Classpath: {classpath}")
|
|
80
|
+
|
|
81
|
+
try:
|
|
82
|
+
# Note: startJVM can only be called ONCE.
|
|
83
|
+
# We load all JARs now to support future "plug-and-play" connections.
|
|
84
|
+
jpype.startJVM(jpype.getDefaultJVMPath(), classpath=classpath, convertStrings=True)
|
|
85
|
+
logger.info("JVM started for JDBC connections.")
|
|
86
|
+
except Exception as e:
|
|
87
|
+
logger.error(f"Failed to start JVM: {e}")
|
|
88
|
+
|
|
89
|
+
# Check if the specific driver JAR is actually present in the drivers folder
|
|
90
|
+
# We look for a JAR that contains the subtype name (e.g. 'postgres' or 'mssql')
|
|
91
|
+
jar_path = self.driver_info["jar_path"]
|
|
92
|
+
if not os.path.exists(jar_path):
|
|
93
|
+
drivers_dir = os.path.dirname(jar_path)
|
|
94
|
+
subtype = self._jdbc_config.jdbc_subtype.lower()
|
|
95
|
+
|
|
96
|
+
logger.warning(f"Exact JAR not found at {jar_path}. Searching for '{subtype}' JAR in {drivers_dir}...")
|
|
97
|
+
|
|
98
|
+
# Smart search: find any jar that starts with or contains the subtype name
|
|
99
|
+
found_jars = [f for f in os.listdir(drivers_dir) if subtype in f.lower() and f.endswith('.jar')]
|
|
100
|
+
if found_jars:
|
|
101
|
+
# Use the first one found
|
|
102
|
+
self.driver_info["jar_path"] = os.path.join(drivers_dir, found_jars[0])
|
|
103
|
+
logger.info(f"Smart-matched JDBC driver to: {self.driver_info['jar_path']}")
|
|
104
|
+
else:
|
|
105
|
+
logger.error(f"No JAR file matching '{subtype}' found in {drivers_dir}")
|
|
106
|
+
# We don't raise yet, as the class might somehow be in the global classpath
|
|
107
|
+
|
|
108
|
+
@contextmanager
|
|
109
|
+
def get_connection(self, retries: int = 3, delay: int = 5):
|
|
110
|
+
"""Context manager for JDBC database connections with retry mechanism."""
|
|
111
|
+
last_exception = None
|
|
112
|
+
cfg = self._jdbc_config
|
|
113
|
+
driver_class = self.driver_info["driver_class"]
|
|
114
|
+
jar_path = self.driver_info["jar_path"]
|
|
115
|
+
|
|
116
|
+
for attempt in range(retries):
|
|
117
|
+
conn = None
|
|
118
|
+
try:
|
|
119
|
+
logger.info(f"Connecting to JDBC: {self.jdbc_url} (Driver: {driver_class})")
|
|
120
|
+
|
|
121
|
+
# Establish connection
|
|
122
|
+
conn = jaydebeapi.connect(
|
|
123
|
+
jclassname=driver_class,
|
|
124
|
+
url=self.jdbc_url,
|
|
125
|
+
driver_args=[cfg.username, cfg.password],
|
|
126
|
+
jars=jar_path
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
yield conn
|
|
130
|
+
return
|
|
131
|
+
|
|
132
|
+
except Exception as e:
|
|
133
|
+
last_exception = e
|
|
134
|
+
if conn is not None:
|
|
135
|
+
try:
|
|
136
|
+
conn.close()
|
|
137
|
+
except:
|
|
138
|
+
pass
|
|
139
|
+
conn = None
|
|
140
|
+
|
|
141
|
+
logger.warning(f"JDBC connection failed (attempt {attempt + 1}/{retries}): {e}")
|
|
142
|
+
|
|
143
|
+
if attempt < retries - 1:
|
|
144
|
+
time.sleep(delay)
|
|
145
|
+
continue
|
|
146
|
+
break
|
|
147
|
+
finally:
|
|
148
|
+
if conn is not None:
|
|
149
|
+
try:
|
|
150
|
+
conn.close()
|
|
151
|
+
except:
|
|
152
|
+
pass
|
|
153
|
+
|
|
154
|
+
raise BadRequest(f"Failed to connect to JDBC after {retries} attempts: {last_exception}")
|
|
155
|
+
|
|
156
|
+
def close_connection(self):
|
|
157
|
+
"""JDBC connections are closed in the context manager."""
|
|
158
|
+
pass
|
|
159
|
+
|
|
160
|
+
def is_valid_connection(self) -> bool:
|
|
161
|
+
"""Returns True if connection can be established."""
|
|
162
|
+
try:
|
|
163
|
+
with self.get_connection():
|
|
164
|
+
return True
|
|
165
|
+
except:
|
|
166
|
+
return False
|
|
167
|
+
|
|
168
|
+
def test_connection(self) -> bool:
|
|
169
|
+
"""Verify the connection is reachable."""
|
|
170
|
+
try:
|
|
171
|
+
with self.get_connection() as conn:
|
|
172
|
+
# Use a simple generic query for testing
|
|
173
|
+
cursor = conn.cursor()
|
|
174
|
+
# Most DBs support SELECT 1, but we might need variations
|
|
175
|
+
try:
|
|
176
|
+
cursor.execute("SELECT 1")
|
|
177
|
+
except:
|
|
178
|
+
# Fallback for Oracle or others that don't support SELECT 1 without FROM
|
|
179
|
+
pass
|
|
180
|
+
cursor.close()
|
|
181
|
+
return True
|
|
182
|
+
except Exception as e:
|
|
183
|
+
raise ConnectionError(f"JDBC Connection failed: {str(e)}")
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""Registry for JDBC driver configurations."""
|
|
2
|
+
|
|
3
|
+
from typing import Dict, Any
|
|
4
|
+
|
|
5
|
+
JDBC_DRIVER_REGISTRY: Dict[str, Dict[str, Any]] = {
|
|
6
|
+
"mssql": {
|
|
7
|
+
"driver_class": "com.microsoft.sqlserver.jdbc.SQLServerDriver",
|
|
8
|
+
"url_template": "jdbc:sqlserver://{host}:{port};databaseName={database};encrypt=true;trustServerCertificate=true;loginTimeout=30;",
|
|
9
|
+
"jar_path": "/app/drivers/mssql.jar",
|
|
10
|
+
"default_schema": "dbo",
|
|
11
|
+
"constants_section": "jdbc_mssql",
|
|
12
|
+
},
|
|
13
|
+
"postgres": {
|
|
14
|
+
"driver_class": "org.postgresql.Driver",
|
|
15
|
+
"url_template": "jdbc:postgresql://{host}:{port}/{database}",
|
|
16
|
+
"jar_path": "/app/drivers/postgresql.jar",
|
|
17
|
+
"default_schema": "public",
|
|
18
|
+
"constants_section": "jdbc_postgres",
|
|
19
|
+
},
|
|
20
|
+
"mysql": {
|
|
21
|
+
"driver_class": "com.mysql.cj.jdbc.Driver",
|
|
22
|
+
"url_template": "jdbc:mysql://{host}:{port}/{database}?useSSL=false",
|
|
23
|
+
"jar_path": "/app/drivers/mysql.jar",
|
|
24
|
+
"default_schema": None,
|
|
25
|
+
"constants_section": "jdbc_mysql",
|
|
26
|
+
},
|
|
27
|
+
"redshift": {
|
|
28
|
+
"driver_class": "com.amazon.redshift.jdbc42.Driver",
|
|
29
|
+
"url_template": "jdbc:redshift://{host}:{port}/{database}",
|
|
30
|
+
"jar_path": "/app/drivers/redshift.jar",
|
|
31
|
+
"default_schema": "public",
|
|
32
|
+
"constants_section": "jdbc_redshift",
|
|
33
|
+
},
|
|
34
|
+
"fabric_spark": {
|
|
35
|
+
"driver_class": "com.microsoft.spark.livy.jdbc.LivyDriver",
|
|
36
|
+
"url_template": (
|
|
37
|
+
"jdbc:fabricspark://api.fabric.microsoft.com;"
|
|
38
|
+
"FabricWorkspaceID={workspace_id};"
|
|
39
|
+
"FabricLakehouseID={lakehouse_id};"
|
|
40
|
+
"AuthFlow=3;"
|
|
41
|
+
"AuthTenantID={tenant_id};"
|
|
42
|
+
"LogLevel=INFO"
|
|
43
|
+
),
|
|
44
|
+
"jar_path": "/app/drivers/fabricspark.jar",
|
|
45
|
+
"default_schema": "default",
|
|
46
|
+
"constants_section": "jdbc_fabric_spark",
|
|
47
|
+
},
|
|
48
|
+
"fabric_sql": {
|
|
49
|
+
"driver_class": "com.microsoft.sqlserver.jdbc.SQLServerDriver",
|
|
50
|
+
"url_template": (
|
|
51
|
+
"jdbc:sqlserver://{host}:1433;"
|
|
52
|
+
"database={database};"
|
|
53
|
+
"encrypt=true;"
|
|
54
|
+
"trustServerCertificate=false;"
|
|
55
|
+
"hostNameInCertificate=*.datawarehouse.fabric.microsoft.com;"
|
|
56
|
+
"loginTimeout=30;"
|
|
57
|
+
"authentication=ActiveDirectoryServicePrincipal"
|
|
58
|
+
),
|
|
59
|
+
"jar_path": "/app/drivers/mssql.jar",
|
|
60
|
+
"default_schema": "dbo",
|
|
61
|
+
"constants_section": "jdbc_mssql",
|
|
62
|
+
},
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
def get_jdbc_driver_config(jdbc_subtype: str) -> Dict[str, Any]:
|
|
66
|
+
"""
|
|
67
|
+
Get JDBC driver configuration for a specific subtype.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
jdbc_subtype: The database subtype (e.g., 'mssql', 'postgres')
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
Dict: Driver configuration
|
|
74
|
+
|
|
75
|
+
Raises:
|
|
76
|
+
ValueError: If subtype is not supported
|
|
77
|
+
"""
|
|
78
|
+
config = JDBC_DRIVER_REGISTRY.get(jdbc_subtype.lower())
|
|
79
|
+
if not config:
|
|
80
|
+
supported = ", ".join(JDBC_DRIVER_REGISTRY.keys())
|
|
81
|
+
raise ValueError(f"Unsupported JDBC subtype: {jdbc_subtype}. Supported: {supported}")
|
|
82
|
+
return config
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
from pypika import Query
|
|
2
|
+
|
|
3
|
+
from shared_kernel.data_warehouse_handlers.connections.jdbc_warehouse_connection import (
|
|
4
|
+
JDBCWarehouseConnection,
|
|
5
|
+
)
|
|
6
|
+
from shared_kernel.data_warehouse_handlers.query_executors.jdbc_query_executor import (
|
|
7
|
+
JDBCQueryExecutor,
|
|
8
|
+
)
|
|
9
|
+
from shared_kernel.dataclasses.warehouse_configs import JDBCConfig
|
|
10
|
+
from shared_kernel.interfaces.data_warehouse_handler import WarehouseHandler
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class JDBCWarehouseHandler(WarehouseHandler):
|
|
14
|
+
"""
|
|
15
|
+
Handler for JDBC-based data warehouses.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, payload: dict = None):
|
|
19
|
+
super().__init__(payload)
|
|
20
|
+
self.set_default_schema = self.payload.get("set_default_schema", True)
|
|
21
|
+
|
|
22
|
+
def get_config(self) -> JDBCConfig:
|
|
23
|
+
"""
|
|
24
|
+
Extracts JDBC configuration from payload.
|
|
25
|
+
Supports two connection methods:
|
|
26
|
+
- 'host': build URL from host/port/database (default)
|
|
27
|
+
- 'url': use a pre-built JDBC URL directly
|
|
28
|
+
"""
|
|
29
|
+
source_config: JDBCConfig = self.payload.get("source_config")
|
|
30
|
+
if source_config and isinstance(source_config, JDBCConfig):
|
|
31
|
+
return source_config
|
|
32
|
+
|
|
33
|
+
jdbc_subtype = str(self.payload.get("jdbc_subtype", "mssql")).strip().lower()
|
|
34
|
+
connection_method = (
|
|
35
|
+
str(self.payload.get("connection_method", "host")).strip().lower()
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
if connection_method == "url":
|
|
39
|
+
_required = ("jdbc_url", "user", "password")
|
|
40
|
+
elif jdbc_subtype == "fabric_spark":
|
|
41
|
+
_required = ("workspace_id", "lakehouse_id", "tenant_id", "user", "password")
|
|
42
|
+
elif jdbc_subtype == "fabric_sql":
|
|
43
|
+
_required = ("host", "database", "tenant_id", "user", "password")
|
|
44
|
+
else:
|
|
45
|
+
_required = ("host", "port", "database", "user", "password")
|
|
46
|
+
|
|
47
|
+
missing = [f for f in _required if not self.payload.get(f)]
|
|
48
|
+
if missing:
|
|
49
|
+
raise ValueError(
|
|
50
|
+
f"JDBC payload (method='{connection_method}', subtype='{jdbc_subtype}') is missing required fields: {missing}."
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
return JDBCConfig(
|
|
54
|
+
connection_method=connection_method,
|
|
55
|
+
jdbc_url=str(self.payload.get("jdbc_url", "")).strip() or None,
|
|
56
|
+
host=str(self.payload.get("host", "")).strip() or None,
|
|
57
|
+
port=str(self.payload.get("port", "")).strip() or None,
|
|
58
|
+
database=str(self.payload.get("database", "")).strip() or None,
|
|
59
|
+
workspace_id=str(self.payload.get("workspace_id", "")).strip() or None,
|
|
60
|
+
lakehouse_id=str(self.payload.get("lakehouse_id", "")).strip() or None,
|
|
61
|
+
tenant_id=str(self.payload.get("tenant_id", "")).strip() or None,
|
|
62
|
+
username=str(self.payload.get("user")).strip(),
|
|
63
|
+
password=str(self.payload.get("password")).strip(),
|
|
64
|
+
jdbc_subtype=jdbc_subtype,
|
|
65
|
+
schema=(
|
|
66
|
+
str(self.payload.get("schema")).strip()
|
|
67
|
+
if self.payload.get("schema")
|
|
68
|
+
else None
|
|
69
|
+
),
|
|
70
|
+
schema_list=self.payload.get("schema_list"),
|
|
71
|
+
pagination=self.pagination,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
def _build_connection(self) -> JDBCWarehouseConnection:
|
|
75
|
+
"""Builds a JDBC connection instance."""
|
|
76
|
+
return JDBCWarehouseConnection(
|
|
77
|
+
source_config=self.get_config(),
|
|
78
|
+
set_default_schema=self.set_default_schema,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
def get_constants_section(self) -> str:
|
|
82
|
+
"""
|
|
83
|
+
Returns the constants.ini section to use for SQL queries.
|
|
84
|
+
Pulls from the driver registry mapping.
|
|
85
|
+
"""
|
|
86
|
+
from shared_kernel.data_warehouse_handlers.jdbc_driver_registry import get_jdbc_driver_config
|
|
87
|
+
config_dict = get_jdbc_driver_config(self.get_config().jdbc_subtype)
|
|
88
|
+
return config_dict["constants_section"]
|
|
89
|
+
|
|
90
|
+
def get_executor(self) -> JDBCQueryExecutor:
|
|
91
|
+
"""Returns the JDBC query executor."""
|
|
92
|
+
connection = self._build_connection()
|
|
93
|
+
connection.test_connection()
|
|
94
|
+
return JDBCQueryExecutor(warehouse_connection=connection)
|
|
95
|
+
|
|
96
|
+
def get_query_object(self) -> Query:
|
|
97
|
+
"""Returns a generic Query object (dialect-neutral)."""
|
|
98
|
+
return Query
|
|
99
|
+
|
|
100
|
+
def create_records_and_count_query(
|
|
101
|
+
self,
|
|
102
|
+
query: str,
|
|
103
|
+
limit: str,
|
|
104
|
+
page: str,
|
|
105
|
+
) -> tuple[str, str]:
|
|
106
|
+
"""
|
|
107
|
+
Builds a count query and a paginated query.
|
|
108
|
+
Using standard SQL syntax which works for most JDBC drivers.
|
|
109
|
+
"""
|
|
110
|
+
count_query = f"SELECT COUNT(*) FROM ({query}) AS _count"
|
|
111
|
+
|
|
112
|
+
if limit:
|
|
113
|
+
query = f"{query} LIMIT {int(limit)}"
|
|
114
|
+
if page:
|
|
115
|
+
offset = (int(page) - 1) * int(limit)
|
|
116
|
+
query = f"{query} OFFSET {offset}"
|
|
117
|
+
|
|
118
|
+
return count_query, query
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import time
|
|
2
|
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
3
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
4
|
+
|
|
5
|
+
from shared_kernel.config import Config
|
|
6
|
+
from shared_kernel.interfaces.query_executor import DataWarehouseQueryExecutor
|
|
7
|
+
from shared_kernel.interfaces.warehouse_connection import DataWarehouseConnection
|
|
8
|
+
from shared_kernel.logger import Logger
|
|
9
|
+
|
|
10
|
+
config = Config()
|
|
11
|
+
logger = Logger(config.get("APP_NAME"))
|
|
12
|
+
MAX_QUERY_CONCURRENCY = 5
|
|
13
|
+
|
|
14
|
+
class JDBCQueryExecutor(DataWarehouseQueryExecutor):
|
|
15
|
+
"""
|
|
16
|
+
Query executor for JDBC connections.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, warehouse_connection: DataWarehouseConnection) -> None:
|
|
20
|
+
self.warehouse_connection = warehouse_connection
|
|
21
|
+
|
|
22
|
+
def execute_query(
|
|
23
|
+
self,
|
|
24
|
+
query: str,
|
|
25
|
+
params: Optional[tuple] = None,
|
|
26
|
+
) -> List[Dict[str, Any]]:
|
|
27
|
+
"""
|
|
28
|
+
Execute a single SQL query and return all rows as a list of dicts.
|
|
29
|
+
"""
|
|
30
|
+
with self.warehouse_connection.get_connection() as conn:
|
|
31
|
+
cursor = conn.cursor()
|
|
32
|
+
try:
|
|
33
|
+
logger.info(f"Executing JDBC query: {query}")
|
|
34
|
+
start = time.perf_counter()
|
|
35
|
+
|
|
36
|
+
if params:
|
|
37
|
+
cursor.execute(query, params)
|
|
38
|
+
else:
|
|
39
|
+
cursor.execute(query)
|
|
40
|
+
|
|
41
|
+
elapsed = time.perf_counter() - start
|
|
42
|
+
logger.info(f"JDBC Query executed in {elapsed:.6f}s")
|
|
43
|
+
|
|
44
|
+
description = cursor.description
|
|
45
|
+
if description:
|
|
46
|
+
# Normalize column names to lowercase — JDBC drivers return
|
|
47
|
+
# column names in varying cases (MySQL → uppercase, PG → lowercase)
|
|
48
|
+
columns = [col[0] for col in description]
|
|
49
|
+
rows = cursor.fetchall()
|
|
50
|
+
return [dict(zip(columns, row)) for row in rows]
|
|
51
|
+
else:
|
|
52
|
+
return []
|
|
53
|
+
|
|
54
|
+
except Exception as e:
|
|
55
|
+
logger.error(f"JDBC Query failed: {query} — {e}", exc_info=True)
|
|
56
|
+
raise Exception(f"JDBC Query execution failed: {str(e)}") from e
|
|
57
|
+
finally:
|
|
58
|
+
cursor.close()
|
|
59
|
+
|
|
60
|
+
def execute_queries(
|
|
61
|
+
self,
|
|
62
|
+
queries: List[str],
|
|
63
|
+
) -> List[List[Dict[str, Any]]]:
|
|
64
|
+
"""
|
|
65
|
+
Execute multiple SQL queries in parallel and return results in input order.
|
|
66
|
+
"""
|
|
67
|
+
if not queries:
|
|
68
|
+
return []
|
|
69
|
+
|
|
70
|
+
results: List[Optional[List[Dict[str, Any]]]] = [None] * len(queries)
|
|
71
|
+
|
|
72
|
+
with ThreadPoolExecutor(max_workers=MAX_QUERY_CONCURRENCY) as pool:
|
|
73
|
+
future_to_index = {
|
|
74
|
+
pool.submit(self.execute_query, query): idx
|
|
75
|
+
for idx, query in enumerate(queries)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
for future in as_completed(future_to_index):
|
|
79
|
+
idx = future_to_index[future]
|
|
80
|
+
try:
|
|
81
|
+
results[idx] = future.result()
|
|
82
|
+
except Exception as e:
|
|
83
|
+
for pending in future_to_index:
|
|
84
|
+
if not pending.done():
|
|
85
|
+
pending.cancel()
|
|
86
|
+
raise Exception(f"Parallel JDBC query failed at index {idx}: {e}") from e
|
|
87
|
+
|
|
88
|
+
return results
|
|
89
|
+
|
|
90
|
+
def execute_query_with_column_types(
|
|
91
|
+
self,
|
|
92
|
+
query: str,
|
|
93
|
+
params: Optional[tuple] = None,
|
|
94
|
+
) -> Tuple[List[Dict[str, Any]], List[Tuple]]:
|
|
95
|
+
"""
|
|
96
|
+
Execute a query and return both rows and raw cursor description.
|
|
97
|
+
"""
|
|
98
|
+
with self.warehouse_connection.get_connection() as conn:
|
|
99
|
+
cursor = conn.cursor()
|
|
100
|
+
try:
|
|
101
|
+
logger.info(f"Executing JDBC query with column types: {query}")
|
|
102
|
+
start = time.perf_counter()
|
|
103
|
+
|
|
104
|
+
if params:
|
|
105
|
+
cursor.execute(query, params)
|
|
106
|
+
else:
|
|
107
|
+
cursor.execute(query)
|
|
108
|
+
|
|
109
|
+
elapsed = time.perf_counter() - start
|
|
110
|
+
logger.info(f"JDBC Query executed in {elapsed:.6f}s")
|
|
111
|
+
|
|
112
|
+
description = cursor.description
|
|
113
|
+
if description:
|
|
114
|
+
# Normalize column names to lowercase
|
|
115
|
+
columns = [col[0] for col in description]
|
|
116
|
+
raw_rows = cursor.fetchall()
|
|
117
|
+
rows = [dict(zip(columns, row)) for row in raw_rows]
|
|
118
|
+
# For JDBC, description[i][1] is the java.sql.Types integer constant
|
|
119
|
+
return rows, description
|
|
120
|
+
else:
|
|
121
|
+
return [], []
|
|
122
|
+
|
|
123
|
+
except Exception as e:
|
|
124
|
+
logger.error(f"JDBC Query failed: {query} — {e}", exc_info=True)
|
|
125
|
+
raise Exception(f"JDBC Query execution failed: {str(e)}") from e
|
|
126
|
+
finally:
|
|
127
|
+
cursor.close()
|
|
@@ -6,6 +6,7 @@ from shared_kernel.data_warehouse_handlers.mssql_handler import MSSQLWarehouseHa
|
|
|
6
6
|
from shared_kernel.data_warehouse_handlers.postgresql_handler import PostgreSQLWarehouseHandler
|
|
7
7
|
from shared_kernel.data_warehouse_handlers.redshift_handler import RedshiftWarehouseHandler
|
|
8
8
|
from shared_kernel.data_warehouse_handlers.snowflake_handler import SnowflakeWarehouseHandler
|
|
9
|
+
from shared_kernel.data_warehouse_handlers.jdbc_handler import JDBCWarehouseHandler
|
|
9
10
|
from shared_kernel.enums.connection_engine import ConnectionEngine
|
|
10
11
|
|
|
11
12
|
|
|
@@ -18,4 +19,5 @@ warehouse_handlers = {
|
|
|
18
19
|
ConnectionEngine.MYSQL.value: MySQLWarehouseHandler,
|
|
19
20
|
ConnectionEngine.AZURESQL.value: MSSQLWarehouseHandler,
|
|
20
21
|
ConnectionEngine.DATABRICKS.value: DatabricksWarehouseHandler,
|
|
22
|
+
ConnectionEngine.JDBC.value: JDBCWarehouseHandler,
|
|
21
23
|
}
|