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.
Files changed (189) hide show
  1. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/PKG-INFO +3 -1
  2. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/fdc_shared_kernel.egg-info/PKG-INFO +3 -1
  3. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/fdc_shared_kernel.egg-info/SOURCES.txt +6 -0
  4. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/fdc_shared_kernel.egg-info/requires.txt +2 -0
  5. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/pyproject.toml +1 -1
  6. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/requirements.txt +2 -0
  7. fdc_shared_kernel-0.0.181/shared_kernel/data_warehouse_handlers/connections/jdbc_warehouse_connection.py +183 -0
  8. fdc_shared_kernel-0.0.181/shared_kernel/data_warehouse_handlers/jdbc_driver_registry.py +82 -0
  9. fdc_shared_kernel-0.0.181/shared_kernel/data_warehouse_handlers/jdbc_handler.py +118 -0
  10. fdc_shared_kernel-0.0.181/shared_kernel/data_warehouse_handlers/odbc_handler.py +13 -0
  11. fdc_shared_kernel-0.0.181/shared_kernel/data_warehouse_handlers/query_executors/jdbc_query_executor.py +127 -0
  12. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/warehouse_handlers_map.py +2 -0
  13. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/dataclasses/warehouse_configs.py +27 -3
  14. fdc_shared_kernel-0.0.181/shared_kernel/datatype_mappings/connectors_to_system/jdbc.py +66 -0
  15. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/enums/connection_engine.py +1 -0
  16. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/README.md +0 -0
  17. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/README_pypi.md +0 -0
  18. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/fdc_shared_kernel.egg-info/dependency_links.txt +0 -0
  19. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/fdc_shared_kernel.egg-info/top_level.txt +0 -0
  20. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/setup.cfg +0 -0
  21. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/__init__.py +0 -0
  22. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/agent_communication_channel/__init__.py +0 -0
  23. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/agent_communication_channel/agent_channel.py +0 -0
  24. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/agent_communication_channel/contexts.py +0 -0
  25. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/agent_communication_channel/event_channel.py +0 -0
  26. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/ai_audit_log/__init__.py +0 -0
  27. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/ai_chat_persistence/__init__.py +0 -0
  28. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/ai_chat_persistence/chat_persistence.py +0 -0
  29. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/async_task_executor/__init__.py +0 -0
  30. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/async_task_executor/async_task_executor.py +0 -0
  31. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/auth/__init__.py +0 -0
  32. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/auth/jwt_helper.py +0 -0
  33. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/auth/token_handler.py +0 -0
  34. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/auth/workbook_permission_handler.py +0 -0
  35. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/batch_job/__init__.py +0 -0
  36. {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
  37. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/batch_job/job_handlers/__init__.py +0 -0
  38. {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
  39. {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
  40. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/batch_job/job_handlers/job_handler_factory.py +0 -0
  41. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/batch_job/job_handlers/job_status_mapper.py +0 -0
  42. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/batch_job/job_storage_managers/__init__.py +0 -0
  43. {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
  44. {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
  45. {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
  46. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/config/__init__.py +0 -0
  47. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/constants/constants.py +0 -0
  48. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/__init__.py +0 -0
  49. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/connections/databricks_warehouse_connection.py +0 -0
  50. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/connections/mssql_warehouse_connection.py +0 -0
  51. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/connections/mysql_warehouse_connection.py +0 -0
  52. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/connections/postgresql_warehouse_connection.py +0 -0
  53. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/connections/redshift_warehouse_connection.py +0 -0
  54. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/connections/snowflake_warehouse_connection.py +0 -0
  55. {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
  56. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/databricks_handler.py +0 -0
  57. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/factory.py +0 -0
  58. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/mssql_handler.py +0 -0
  59. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/mysql_handler.py +0 -0
  60. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/postgresql_handler.py +0 -0
  61. {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
  62. {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
  63. {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
  64. {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
  65. {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
  66. {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
  67. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/redshift_handler.py +0 -0
  68. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/snowflake_handler.py +0 -0
  69. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/data_warehouse_handlers/utils.py +0 -0
  70. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/database/__init__.py +0 -0
  71. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/dataclasses/__init__.py +0 -0
  72. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/dataclasses/aws_batch_job_context.py +0 -0
  73. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/dataclasses/azure_container_app_job_context.py +0 -0
  74. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/dataclasses/event_executor.py +0 -0
  75. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/dataclasses/job_context.py +0 -0
  76. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/dataclasses/job_record_dataclasses.py +0 -0
  77. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/__init__.py +0 -0
  78. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/__init__.py +0 -0
  79. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/csv.py +0 -0
  80. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/databricks.py +0 -0
  81. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/db2.py +0 -0
  82. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/jira.py +0 -0
  83. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/mssql.py +0 -0
  84. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/mysql.py +0 -0
  85. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/oracle.py +0 -0
  86. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/postgres.py +0 -0
  87. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/redshift.py +0 -0
  88. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/salesforce.py +0 -0
  89. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/snowflake.py +0 -0
  90. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/connectors_to_system/sqlalchemy.py +0 -0
  91. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/system_to_warehouse/__init__.py +0 -0
  92. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/system_to_warehouse/postgres.py +0 -0
  93. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/datatype_mappings/system_to_warehouse/redshift.py +0 -0
  94. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/enums/__init__.py +0 -0
  95. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/enums/async_task_executor.py +0 -0
  96. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/enums/status_tracker.py +0 -0
  97. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/event_executor/__init__.py +0 -0
  98. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/event_executor/event_executor.py +0 -0
  99. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/event_executor/job_executor.py +0 -0
  100. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/event_executor/utils.py +0 -0
  101. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/exceptions/__init__.py +0 -0
  102. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/exceptions/batch_job_exceptions.py +0 -0
  103. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/exceptions/configuration_exceptions.py +0 -0
  104. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/exceptions/custom_exceptions.py +0 -0
  105. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/exceptions/data_validation_exceptions.py +0 -0
  106. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/exceptions/http_exceptions.py +0 -0
  107. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/exceptions/infrastructure_exceptions.py +0 -0
  108. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/exceptions/operational_exceptions.py +0 -0
  109. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/exceptions/security_exceptions.py +0 -0
  110. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/exceptions/user_intervention_exception.py +0 -0
  111. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/http/__init__.py +0 -0
  112. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/http/httpx_http_client.py +0 -0
  113. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/http/request_http_client.py +0 -0
  114. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/interfaces/__init__.py +0 -0
  115. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/interfaces/base_job_handler.py +0 -0
  116. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/interfaces/data_warehouse_handler.py +0 -0
  117. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/interfaces/databus.py +0 -0
  118. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/interfaces/http.py +0 -0
  119. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/interfaces/keyvault.py +0 -0
  120. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/interfaces/query_executor.py +0 -0
  121. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/interfaces/storage_manager.py +0 -0
  122. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/interfaces/warehouse_connection.py +0 -0
  123. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/logger/__init__.py +0 -0
  124. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/messaging/__init__.py +0 -0
  125. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/messaging/aws_databus.py +0 -0
  126. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/messaging/azure_databus.py +0 -0
  127. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/messaging/http_databus.py +0 -0
  128. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/messaging/nats_databus.py +0 -0
  129. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/messaging/nats_publisher.py +0 -0
  130. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/messaging/nats_test.py +0 -0
  131. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/messaging/utils/aws_utility.py +0 -0
  132. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/messaging/utils/azure_utility.py +0 -0
  133. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/messaging/utils/event_messages.py +0 -0
  134. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/metrics/__init__.py +0 -0
  135. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/metrics/status_tracker.py +0 -0
  136. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/models/__init__.py +0 -0
  137. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/registries/__init__.py +0 -0
  138. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/registries/schema_onboarding_event_registry.py +0 -0
  139. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/registries/service_event_registry.py +0 -0
  140. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/__init__.py +0 -0
  141. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/base_tracker.py +0 -0
  142. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/enums.py +0 -0
  143. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/exceptions.py +0 -0
  144. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/run_manager.py +0 -0
  145. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/schema_onboarding_tracker.py +0 -0
  146. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/shared_helpers.py +0 -0
  147. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/task_determination.py +0 -0
  148. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/task_helpers.py +0 -0
  149. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/task_manager.py +0 -0
  150. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/template_manager.py +0 -0
  151. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/schema_onboarding_tracker/utility_manager.py +0 -0
  152. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/security/__init__.py +0 -0
  153. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/security/key_vault/__init__.py +0 -0
  154. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/security/key_vault/aws_secret_manager.py +0 -0
  155. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/security/key_vault/azure_keyvault.py +0 -0
  156. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/status_tracker/__init__.py +0 -0
  157. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/status_tracker/status_tracker.py +0 -0
  158. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/storage_handlers/__init__.py +0 -0
  159. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/storage_handlers/blob_file_handler.py +0 -0
  160. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/storage_handlers/s3_storage_handler.py +0 -0
  161. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/__init__.py +0 -0
  162. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/config/__init__.py +0 -0
  163. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/config/test_config.py +0 -0
  164. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/logger/__init__.py +0 -0
  165. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/logger/test_logger.py +0 -0
  166. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/messaging/__init__.py +0 -0
  167. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/messaging/test_aws_databus.py +0 -0
  168. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/messaging/test_event_executor.py +0 -0
  169. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/messaging/test_nats_interface.py +0 -0
  170. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/utils/__init__.py +0 -0
  171. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/utils/test_data_validators.py +0 -0
  172. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/utils/test_date_format_utils.py +0 -0
  173. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/tests/utils/test_string_utils.py +0 -0
  174. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/traceability/__init__.py +0 -0
  175. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/traceability/traceability_handler.py +0 -0
  176. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/utils/__init__.py +0 -0
  177. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/utils/data_validators_utils.py +0 -0
  178. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/utils/date_format_utils.py +0 -0
  179. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/utils/date_utils.py +0 -0
  180. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/utils/string_utils.py +0 -0
  181. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/utils/template_renderer.py +0 -0
  182. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/utils/thread_debug_utils.py +0 -0
  183. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/utils/thread_local_storage.py +0 -0
  184. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/shared_kernel/utils/thread_log_traker.py +0 -0
  185. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/tests/__init__.py +0 -0
  186. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/tests/messaging/__init__.py +0 -0
  187. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/tests/messaging/utils/__init__.py +0 -0
  188. {fdc_shared_kernel-0.0.179 → fdc_shared_kernel-0.0.181}/tests/messaging/utils/test_aws_utility.py +0 -0
  189. {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.179
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.179
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
 
@@ -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
@@ -35,3 +35,5 @@ redshift_connector==2.1.2
35
35
  pypika==0.48.9
36
36
  snowflake-connector-python==3.16.0
37
37
  PyMySQL==1.1.1
38
+ jaydebeapi==1.2.3
39
+ JPype1==1.5.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fdc_shared_kernel"
7
- version = "0.0.179"
7
+ version = "0.0.181"
8
8
  requires-python = ">=3.7"
9
9
  readme = "README_pypi.md"
10
10
  description = "Shared library for microservice"
@@ -35,3 +35,5 @@ redshift_connector==2.1.2
35
35
  pypika==0.48.9
36
36
  snowflake-connector-python==3.16.0
37
37
  PyMySQL==1.1.1
38
+ jaydebeapi==1.2.3
39
+ JPype1==1.5.0
@@ -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,13 @@
1
+ from shared_kernel.interfaces.data_warehouse_handler import WarehouseHandler
2
+
3
+
4
+ class ODBCWarehouseHandler(WarehouseHandler):
5
+
6
+ def get_config(self):
7
+ pass
8
+
9
+ def get_executor(self):
10
+ pass
11
+
12
+ def get_query_object(self):
13
+ pass
@@ -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
  }