fdc-shared-kernel 0.0.190__tar.gz → 0.0.192__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 (197) hide show
  1. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/PKG-INFO +1 -1
  2. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/fdc_shared_kernel.egg-info/PKG-INFO +1 -1
  3. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/fdc_shared_kernel.egg-info/SOURCES.txt +3 -0
  4. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/pyproject.toml +1 -1
  5. fdc_shared_kernel-0.0.192/shared_kernel/data_warehouse_handlers/connections/fabric_sql_warehouse_connection.py +218 -0
  6. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/connections/mssql_warehouse_connection.py +3 -0
  7. fdc_shared_kernel-0.0.192/shared_kernel/data_warehouse_handlers/fabric_sql_handler.py +75 -0
  8. fdc_shared_kernel-0.0.192/shared_kernel/data_warehouse_handlers/query_executors/fabric_sql_query_executor.py +142 -0
  9. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/query_executors/mssql_query_executor.py +2 -0
  10. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/warehouse_handlers_map.py +2 -0
  11. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/dataclasses/warehouse_configs.py +13 -0
  12. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/enums/connection_engine.py +1 -0
  13. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/README.md +0 -0
  14. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/README_pypi.md +0 -0
  15. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/fdc_shared_kernel.egg-info/dependency_links.txt +0 -0
  16. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/fdc_shared_kernel.egg-info/requires.txt +0 -0
  17. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/fdc_shared_kernel.egg-info/top_level.txt +0 -0
  18. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/requirements.txt +0 -0
  19. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/setup.cfg +0 -0
  20. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/__init__.py +0 -0
  21. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/agent_communication_channel/__init__.py +0 -0
  22. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/agent_communication_channel/agent_channel.py +0 -0
  23. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/agent_communication_channel/contexts.py +0 -0
  24. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/agent_communication_channel/event_channel.py +0 -0
  25. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/ai_audit_log/__init__.py +0 -0
  26. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/ai_chat_persistence/__init__.py +0 -0
  27. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/ai_chat_persistence/chat_persistence.py +0 -0
  28. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/async_task_executor/__init__.py +0 -0
  29. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/async_task_executor/async_task_executor.py +0 -0
  30. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/auth/__init__.py +0 -0
  31. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/auth/jwt_helper.py +0 -0
  32. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/auth/token_handler.py +0 -0
  33. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/auth/workbook_permission_handler.py +0 -0
  34. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/batch_job/__init__.py +0 -0
  35. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/batch_job/batch_job_status_tracker/container_job_status_tracker.py +0 -0
  36. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/batch_job/job_handlers/__init__.py +0 -0
  37. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/batch_job/job_handlers/aws_batch_job_handler.py +0 -0
  38. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/batch_job/job_handlers/azure_apps_job_handler.py +0 -0
  39. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/batch_job/job_handlers/job_handler_factory.py +0 -0
  40. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/batch_job/job_handlers/job_status_mapper.py +0 -0
  41. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/batch_job/job_storage_managers/__init__.py +0 -0
  42. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/batch_job/job_storage_managers/azure_blob_storage_manager.py +0 -0
  43. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/batch_job/job_storage_managers/job_storage_manager_factory.py +0 -0
  44. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/batch_job/job_storage_managers/s3_job_storage_manager.py +0 -0
  45. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/config/__init__.py +0 -0
  46. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/constants/constants.py +0 -0
  47. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/__init__.py +0 -0
  48. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/connections/databricks_warehouse_connection.py +0 -0
  49. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/connections/jdbc_warehouse_connection.py +0 -0
  50. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/connections/mysql_warehouse_connection.py +0 -0
  51. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/connections/postgresql_warehouse_connection.py +0 -0
  52. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/connections/redshift_warehouse_connection.py +0 -0
  53. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/connections/snowflake_warehouse_connection.py +0 -0
  54. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/custom_query_builders/databricks_query.py +0 -0
  55. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/databricks_handler.py +0 -0
  56. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/factory.py +0 -0
  57. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/jdbc_driver_registry.py +0 -0
  58. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/jdbc_handler.py +0 -0
  59. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/mssql_handler.py +0 -0
  60. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/mysql_handler.py +0 -0
  61. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/odbc_handler.py +0 -0
  62. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/postgresql_handler.py +0 -0
  63. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/query_executors/databricks_query_executor.py +0 -0
  64. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/query_executors/jdbc_query_executor.py +0 -0
  65. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/query_executors/mysql_query_executor.py +0 -0
  66. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/query_executors/postgresql_query_executor.py +0 -0
  67. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/query_executors/redshift_query_executor.py +0 -0
  68. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/query_executors/snowflake_query_executor.py +0 -0
  69. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/redshift_handler.py +0 -0
  70. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/snowflake_handler.py +0 -0
  71. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/data_warehouse_handlers/utils.py +0 -0
  72. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/database/__init__.py +0 -0
  73. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/dataclasses/__init__.py +0 -0
  74. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/dataclasses/aws_batch_job_context.py +0 -0
  75. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/dataclasses/azure_container_app_job_context.py +0 -0
  76. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/dataclasses/event_executor.py +0 -0
  77. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/dataclasses/job_context.py +0 -0
  78. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/dataclasses/job_record_dataclasses.py +0 -0
  79. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/datatype_mappings/__init__.py +0 -0
  80. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/datatype_mappings/connectors_to_system/__init__.py +0 -0
  81. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/datatype_mappings/connectors_to_system/csv.py +0 -0
  82. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/datatype_mappings/connectors_to_system/databricks.py +0 -0
  83. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/datatype_mappings/connectors_to_system/db2.py +0 -0
  84. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/datatype_mappings/connectors_to_system/jdbc.py +0 -0
  85. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/datatype_mappings/connectors_to_system/jira.py +0 -0
  86. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/datatype_mappings/connectors_to_system/mssql.py +0 -0
  87. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/datatype_mappings/connectors_to_system/mysql.py +0 -0
  88. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/datatype_mappings/connectors_to_system/oracle.py +0 -0
  89. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/datatype_mappings/connectors_to_system/postgres.py +0 -0
  90. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/datatype_mappings/connectors_to_system/redshift.py +0 -0
  91. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/datatype_mappings/connectors_to_system/salesforce.py +0 -0
  92. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/datatype_mappings/connectors_to_system/snowflake.py +0 -0
  93. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/datatype_mappings/connectors_to_system/sqlalchemy.py +0 -0
  94. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/datatype_mappings/system_to_warehouse/__init__.py +0 -0
  95. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/datatype_mappings/system_to_warehouse/postgres.py +0 -0
  96. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/datatype_mappings/system_to_warehouse/redshift.py +0 -0
  97. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/enums/__init__.py +0 -0
  98. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/enums/async_task_executor.py +0 -0
  99. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/enums/status_tracker.py +0 -0
  100. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/event_executor/__init__.py +0 -0
  101. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/event_executor/event_executor.py +0 -0
  102. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/event_executor/job_executor.py +0 -0
  103. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/event_executor/utils.py +0 -0
  104. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/exceptions/__init__.py +0 -0
  105. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/exceptions/batch_job_exceptions.py +0 -0
  106. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/exceptions/configuration_exceptions.py +0 -0
  107. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/exceptions/custom_exceptions.py +0 -0
  108. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/exceptions/data_validation_exceptions.py +0 -0
  109. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/exceptions/http_exceptions.py +0 -0
  110. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/exceptions/infrastructure_exceptions.py +0 -0
  111. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/exceptions/operational_exceptions.py +0 -0
  112. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/exceptions/security_exceptions.py +0 -0
  113. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/exceptions/user_intervention_exception.py +0 -0
  114. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/http/__init__.py +0 -0
  115. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/http/httpx_http_client.py +0 -0
  116. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/http/request_http_client.py +0 -0
  117. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/interfaces/__init__.py +0 -0
  118. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/interfaces/base_job_handler.py +0 -0
  119. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/interfaces/data_warehouse_handler.py +0 -0
  120. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/interfaces/databus.py +0 -0
  121. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/interfaces/encryption.py +0 -0
  122. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/interfaces/http.py +0 -0
  123. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/interfaces/keyvault.py +0 -0
  124. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/interfaces/query_executor.py +0 -0
  125. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/interfaces/storage_manager.py +0 -0
  126. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/interfaces/warehouse_connection.py +0 -0
  127. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/logger/__init__.py +0 -0
  128. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/messaging/__init__.py +0 -0
  129. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/messaging/aws_databus.py +0 -0
  130. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/messaging/azure_databus.py +0 -0
  131. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/messaging/http_databus.py +0 -0
  132. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/messaging/nats_databus.py +0 -0
  133. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/messaging/nats_publisher.py +0 -0
  134. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/messaging/nats_test.py +0 -0
  135. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/messaging/utils/aws_utility.py +0 -0
  136. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/messaging/utils/azure_utility.py +0 -0
  137. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/messaging/utils/event_messages.py +0 -0
  138. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/metrics/__init__.py +0 -0
  139. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/metrics/status_tracker.py +0 -0
  140. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/models/__init__.py +0 -0
  141. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/registries/__init__.py +0 -0
  142. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/registries/schema_onboarding_event_registry.py +0 -0
  143. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/registries/service_event_registry.py +0 -0
  144. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/schema_onboarding_tracker/__init__.py +0 -0
  145. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/schema_onboarding_tracker/base_tracker.py +0 -0
  146. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/schema_onboarding_tracker/enums.py +0 -0
  147. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/schema_onboarding_tracker/exceptions.py +0 -0
  148. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/schema_onboarding_tracker/run_manager.py +0 -0
  149. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/schema_onboarding_tracker/schema_onboarding_tracker.py +0 -0
  150. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/schema_onboarding_tracker/shared_helpers.py +0 -0
  151. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/schema_onboarding_tracker/task_determination.py +0 -0
  152. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/schema_onboarding_tracker/task_helpers.py +0 -0
  153. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/schema_onboarding_tracker/task_manager.py +0 -0
  154. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/schema_onboarding_tracker/template_manager.py +0 -0
  155. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/schema_onboarding_tracker/utility_manager.py +0 -0
  156. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/security/__init__.py +0 -0
  157. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/security/encryption/__init__.py +0 -0
  158. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/security/encryption/manager.py +0 -0
  159. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/security/encryption/providers.py +0 -0
  160. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/security/key_vault/__init__.py +0 -0
  161. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/security/key_vault/aws_secret_manager.py +0 -0
  162. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/security/key_vault/azure_keyvault.py +0 -0
  163. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/status_tracker/__init__.py +0 -0
  164. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/status_tracker/status_tracker.py +0 -0
  165. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/storage_handlers/__init__.py +0 -0
  166. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/storage_handlers/blob_file_handler.py +0 -0
  167. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/storage_handlers/s3_storage_handler.py +0 -0
  168. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/tests/__init__.py +0 -0
  169. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/tests/config/__init__.py +0 -0
  170. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/tests/config/test_config.py +0 -0
  171. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/tests/logger/__init__.py +0 -0
  172. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/tests/logger/test_logger.py +0 -0
  173. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/tests/messaging/__init__.py +0 -0
  174. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/tests/messaging/test_aws_databus.py +0 -0
  175. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/tests/messaging/test_event_executor.py +0 -0
  176. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/tests/messaging/test_nats_interface.py +0 -0
  177. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/tests/security/test_encryption.py +0 -0
  178. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/tests/utils/__init__.py +0 -0
  179. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/tests/utils/test_data_validators.py +0 -0
  180. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/tests/utils/test_date_format_utils.py +0 -0
  181. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/tests/utils/test_string_utils.py +0 -0
  182. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/traceability/__init__.py +0 -0
  183. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/traceability/traceability_handler.py +0 -0
  184. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/utils/__init__.py +0 -0
  185. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/utils/data_validators_utils.py +0 -0
  186. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/utils/date_format_utils.py +0 -0
  187. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/utils/date_utils.py +0 -0
  188. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/utils/string_utils.py +0 -0
  189. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/utils/template_renderer.py +0 -0
  190. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/utils/thread_debug_utils.py +0 -0
  191. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/utils/thread_local_storage.py +0 -0
  192. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/shared_kernel/utils/thread_log_traker.py +0 -0
  193. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/tests/__init__.py +0 -0
  194. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/tests/messaging/__init__.py +0 -0
  195. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/tests/messaging/utils/__init__.py +0 -0
  196. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/tests/messaging/utils/test_aws_utility.py +0 -0
  197. {fdc_shared_kernel-0.0.190 → fdc_shared_kernel-0.0.192}/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.190
3
+ Version: 0.0.192
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fdc_shared_kernel
3
- Version: 0.0.190
3
+ Version: 0.0.192
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
@@ -36,6 +36,7 @@ shared_kernel/config/__init__.py
36
36
  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
+ shared_kernel/data_warehouse_handlers/fabric_sql_handler.py
39
40
  shared_kernel/data_warehouse_handlers/factory.py
40
41
  shared_kernel/data_warehouse_handlers/jdbc_driver_registry.py
41
42
  shared_kernel/data_warehouse_handlers/jdbc_handler.py
@@ -48,6 +49,7 @@ shared_kernel/data_warehouse_handlers/snowflake_handler.py
48
49
  shared_kernel/data_warehouse_handlers/utils.py
49
50
  shared_kernel/data_warehouse_handlers/warehouse_handlers_map.py
50
51
  shared_kernel/data_warehouse_handlers/connections/databricks_warehouse_connection.py
52
+ shared_kernel/data_warehouse_handlers/connections/fabric_sql_warehouse_connection.py
51
53
  shared_kernel/data_warehouse_handlers/connections/jdbc_warehouse_connection.py
52
54
  shared_kernel/data_warehouse_handlers/connections/mssql_warehouse_connection.py
53
55
  shared_kernel/data_warehouse_handlers/connections/mysql_warehouse_connection.py
@@ -56,6 +58,7 @@ shared_kernel/data_warehouse_handlers/connections/redshift_warehouse_connection.
56
58
  shared_kernel/data_warehouse_handlers/connections/snowflake_warehouse_connection.py
57
59
  shared_kernel/data_warehouse_handlers/custom_query_builders/databricks_query.py
58
60
  shared_kernel/data_warehouse_handlers/query_executors/databricks_query_executor.py
61
+ shared_kernel/data_warehouse_handlers/query_executors/fabric_sql_query_executor.py
59
62
  shared_kernel/data_warehouse_handlers/query_executors/jdbc_query_executor.py
60
63
  shared_kernel/data_warehouse_handlers/query_executors/mssql_query_executor.py
61
64
  shared_kernel/data_warehouse_handlers/query_executors/mysql_query_executor.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fdc_shared_kernel"
7
- version = "0.0.190"
7
+ version = "0.0.192"
8
8
  requires-python = ">=3.7"
9
9
  readme = "README_pypi.md"
10
10
  description = "Shared library for microservice"
@@ -0,0 +1,218 @@
1
+ import hashlib
2
+ import time
3
+ import threading
4
+
5
+ from contextlib import contextmanager
6
+ from typing import Dict
7
+
8
+ from sqlalchemy import create_engine, text
9
+ from sqlalchemy.engine import Engine
10
+ from sqlalchemy.exc import InterfaceError, OperationalError, ProgrammingError
11
+
12
+ from shared_kernel.dataclasses.warehouse_configs import FabricSQLConfig
13
+ from shared_kernel.exceptions.http_exceptions import BadRequest
14
+ from shared_kernel.interfaces.warehouse_connection import DataWarehouseConnection
15
+ from shared_kernel.data_warehouse_handlers.utils import extract_sql_server_error_message
16
+ from shared_kernel.logger import Logger
17
+ from shared_kernel.config import Config
18
+
19
+ config = Config()
20
+ logger = Logger(config.get("APP_NAME"))
21
+
22
+
23
+ class FabricSQLWarehouseConnection(DataWarehouseConnection):
24
+
25
+ _engines: Dict[str, Engine] = {}
26
+ _tokens: Dict[str, dict] = {}
27
+ _lock = threading.Lock()
28
+
29
+ def __init__(
30
+ self,
31
+ source_config: FabricSQLConfig,
32
+ set_default_schema: bool = True,
33
+ ):
34
+ if source_config is None:
35
+ raise ValueError("Missing required parameter: source_config (FabricSQLConfig)")
36
+
37
+ self._fabric_config = source_config
38
+ self.org_schema = source_config.schema if source_config.schema else None
39
+ self.set_default_schema = set_default_schema
40
+
41
+ pagination = getattr(source_config, "pagination", None) or {}
42
+ self.page = pagination.get("page") if isinstance(pagination, dict) else None
43
+ self.limit = pagination.get("limit") if isinstance(pagination, dict) else None
44
+ self.search = pagination.get("search") if isinstance(pagination, dict) else None
45
+
46
+ def _engine_key(self, cfg: FabricSQLConfig) -> str:
47
+ h = hashlib.md5(f"{cfg.host}:{cfg.port}:{cfg.database}:{cfg.username}".encode()).hexdigest()
48
+ return h
49
+
50
+ def _get_fabric_connection_params(self, cfg: FabricSQLConfig) -> str:
51
+ """
52
+ Builds the base connection parameters for Microsoft Fabric SQL.
53
+
54
+ Returns:
55
+ str: Connection string
56
+ """
57
+ import urllib.parse
58
+ # Build ODBC params. We omit UID and Password fields entirely from the connection string.
59
+ # Authentication is handled solely by injecting the access token into the connection handle.
60
+ odbc_params = urllib.parse.quote_plus(
61
+ f"DRIVER={{ODBC Driver 18 for SQL Server}};"
62
+ f"SERVER={cfg.host},{int(cfg.port)};"
63
+ f"DATABASE={cfg.database};"
64
+ "Encrypt=yes;"
65
+ "TrustServerCertificate=no;"
66
+ )
67
+ # We use odbc_connect query param to prevent SQLAlchemy dialect from auto-injecting
68
+ # conflicting credentials/parameters (avoiding error FA005).
69
+ connection_string = f"mssql+pyodbc:///?odbc_connect={odbc_params}"
70
+ return connection_string
71
+
72
+ def _get_engine(self) -> Engine:
73
+ cfg = self._fabric_config
74
+ key = self._engine_key(cfg)
75
+
76
+ if key not in self._engines:
77
+ with self.__class__._lock: # thread-safe
78
+ if key not in self._engines: # recheck
79
+ from sqlalchemy import event
80
+
81
+ connection_string = self._get_fabric_connection_params(cfg)
82
+
83
+ engine = create_engine(
84
+ connection_string,
85
+ pool_size=10,
86
+ max_overflow=5,
87
+ pool_timeout=30,
88
+ pool_recycle=1800,
89
+ pool_pre_ping=True,
90
+ )
91
+
92
+ # Ensure a thread-safe token cache structure exists for this database key.
93
+ # Each unique database configuration gets its own token cache, expiration tracker, and lock.
94
+ if key not in self._tokens:
95
+ self._tokens[key] = {
96
+ "token": None, # Stores the packed binary token structure
97
+ "expires_at": 0, # Unix timestamp indicating token expiration time
98
+ "lock": threading.Lock() # Lock to synchronize concurrent token refreshes
99
+ }
100
+
101
+ # Register an event listener on the engine to intercept connection establishment.
102
+ # Every time SQLAlchemy checks out or opens a new raw DBAPI connection from the pool,
103
+ # this listener executes to inject a valid, fresh Entra ID access token.
104
+ @event.listens_for(engine, "do_connect")
105
+ def provide_token(dialect, conn_rec, cargs, cparams):
106
+ now = time.time()
107
+ token_info = self._tokens[key]
108
+
109
+ # Check if the token is missing or near expiration (within 5 minutes / 300 seconds).
110
+ # This buffer ensures we don't send a token that is about to expire.
111
+ if token_info["token"] is None or now >= token_info["expires_at"] - 300:
112
+ # Acquire the database-specific lock to serialize token generation.
113
+ # If 10 threads try to connect concurrently when a token expires,
114
+ # only the first thread executes the token fetch; others block here.
115
+ with token_info["lock"]:
116
+ # Double-checked locking pattern: once the lock is acquired,
117
+ # re-verify if another thread updated the token while we were waiting.
118
+ if token_info["token"] is None or now >= token_info["expires_at"] - 300:
119
+ tenant_id = getattr(cfg, "tenant_id", None)
120
+ if not tenant_id:
121
+ raise ValueError(
122
+ "tenant_id is required in FabricSQLConfig for authenticating to Microsoft Fabric via Active Directory Service Principal."
123
+ )
124
+
125
+ from azure.identity import ClientSecretCredential
126
+ import struct
127
+
128
+ logger.info("Fetching fresh Entra ID access token for Fabric SQL connection...")
129
+ # Instantiate the credential to retrieve a token for the Azure SQL Endpoint
130
+ cred = ClientSecretCredential(
131
+ tenant_id=tenant_id,
132
+ client_id=cfg.username,
133
+ client_secret=cfg.password
134
+ )
135
+ token_obj = cred.get_token("https://database.windows.net/.default")
136
+
137
+ # Encode the OAuth token to UTF-16-LE bytes.
138
+ # Pack the payload into the binary structure required by ODBC Driver 18:
139
+ # [4 bytes representing the length of the token string] followed by [the token string bytes].
140
+ token_bytes = token_obj.token.encode("utf-16-le")
141
+ token_info["token"] = struct.pack(f"<I{len(token_bytes)}s", len(token_bytes), token_bytes)
142
+ token_info["expires_at"] = token_obj.expires_on
143
+ logger.info("Successfully fetched and cached fresh Entra ID access token.")
144
+
145
+ # Inject the packed binary token structure into pyodbc's attrs_before connection attribute list.
146
+ # Attribute ID 1256 maps to SQL_COPT_SS_ACCESS_TOKEN.
147
+ cparams["attrs_before"] = {1256: token_info["token"]}
148
+
149
+ self._engines[key] = engine
150
+ logger.info(
151
+ f"Created new Fabric SQL engine for {cfg.host}:{cfg.port}/{cfg.database} with dynamic token provider"
152
+ )
153
+
154
+ return self._engines[key]
155
+
156
+ @contextmanager
157
+ def get_connection(self, retries: int = 3, delay: int = 5, query_timeout: int = 30):
158
+ """Context manager for database connections with retry mechanism"""
159
+ engine = self._get_engine()
160
+ last_exception = None
161
+
162
+ for attempt in range(retries):
163
+ conn = None
164
+ try:
165
+ conn = engine.connect()
166
+ yield conn
167
+ return
168
+
169
+ except (OperationalError, InterfaceError, ProgrammingError) as e:
170
+ last_exception = e
171
+ if conn is not None:
172
+ conn.close()
173
+ conn = None
174
+
175
+ error_message = extract_sql_server_error_message(str(e))
176
+ logger.warning(
177
+ f"Fabric SQL connection failed (attempt {attempt + 1}/{retries}): {error_message}"
178
+ )
179
+
180
+ if attempt < retries - 1:
181
+ time.sleep(delay)
182
+ delay += 5
183
+ continue
184
+
185
+ break
186
+
187
+ finally:
188
+ if conn is not None:
189
+ conn.close()
190
+
191
+ raise BadRequest(
192
+ f"Failed to connect to Fabric SQL after {retries} attempts"
193
+ ) from last_exception
194
+
195
+ def close_connection(self):
196
+ """Dispose all pooled engines managed by this class."""
197
+ for engine in self._engines.values():
198
+ engine.dispose()
199
+ self._engines.clear()
200
+ self._tokens.clear()
201
+ logger.info("All Fabric SQL engine pools disposed.")
202
+
203
+ def is_valid_connection(self) -> bool:
204
+ """Pool health is managed by pool_pre_ping; no manual check needed."""
205
+ return True
206
+
207
+ def test_connection(self) -> bool:
208
+ """Verify the connection is reachable. Raises on failure."""
209
+ try:
210
+ with self.get_connection() as conn:
211
+ conn.execute(text("SELECT 1"))
212
+ return True
213
+ except OperationalError as e:
214
+ if "authentication failed" in str(e).lower():
215
+ raise ValueError("Invalid username or password")
216
+ raise ConnectionError(f"Database error: {str(e)}")
217
+ except InterfaceError:
218
+ raise ConnectionError("Cannot connect to database server")
@@ -56,12 +56,15 @@ class MSSQLWarehouseConnection(DataWarehouseConnection):
56
56
  with self.__class__._lock: # thread-safe
57
57
  if key not in self._engines: # recheck
58
58
  password = quote(cfg.password)
59
+ logger.info(f"Using MSSQL connector (pyodbc native) for standard SQL Server connection on {cfg.host}")
59
60
  connection_string = get_constant("mssql", "CONNECTION_STRING").format(
60
61
  cfg.username, password, cfg.host, int(cfg.port), cfg.database
61
62
  )
63
+ connect_args = {}
62
64
 
63
65
  self._engines[key] = create_engine(
64
66
  connection_string,
67
+ connect_args=connect_args,
65
68
  pool_size=10,
66
69
  max_overflow=5,
67
70
  pool_timeout=30,
@@ -0,0 +1,75 @@
1
+ from pypika import MSSQLQuery
2
+
3
+ from shared_kernel.data_warehouse_handlers.connections.fabric_sql_warehouse_connection import (
4
+ FabricSQLWarehouseConnection,
5
+ )
6
+ from shared_kernel.data_warehouse_handlers.query_executors.fabric_sql_query_executor import (
7
+ FabricSQLQueryExecutor,
8
+ )
9
+ from shared_kernel.dataclasses.warehouse_configs import FabricSQLConfig
10
+ from shared_kernel.interfaces.data_warehouse_handler import WarehouseHandler
11
+
12
+
13
+ class FabricSQLWarehouseHandler(WarehouseHandler):
14
+
15
+ def __init__(self, payload: dict = None):
16
+ super().__init__(payload)
17
+ self.set_default_schema = self.payload.get("set_default_schema", True)
18
+
19
+ def get_config(self) -> FabricSQLConfig:
20
+ source_config: FabricSQLConfig = self.payload.get("source_config")
21
+ if source_config and isinstance(source_config, FabricSQLConfig):
22
+ return source_config
23
+
24
+ required = ("host", "user", "password", "database", "tenant_id")
25
+ missing = [f for f in required if not self.payload.get(f)]
26
+ if missing:
27
+ raise ValueError(f"Fabric SQL payload is missing required fields: {missing}.")
28
+
29
+ return FabricSQLConfig(
30
+ username=str(self.payload.get("user")).strip(),
31
+ password=str(self.payload.get("password")).strip(),
32
+ host=str(self.payload.get("host")).strip(),
33
+ database=str(self.payload.get("database")).strip(),
34
+ tenant_id=str(self.payload.get("tenant_id")).strip(),
35
+ port=str(self.payload.get("port", "1433")).strip(),
36
+ schema=(
37
+ str(self.payload.get("schema")).strip()
38
+ if self.payload.get("schema")
39
+ else None
40
+ ),
41
+ schema_list=self.payload.get("schema_list"),
42
+ pagination=self.pagination,
43
+ )
44
+
45
+ def _build_connection(self) -> FabricSQLWarehouseConnection:
46
+ return FabricSQLWarehouseConnection(
47
+ source_config=self.get_config(),
48
+ set_default_schema=self.set_default_schema,
49
+ )
50
+
51
+ def get_executor(self) -> FabricSQLQueryExecutor:
52
+ connection = self._build_connection()
53
+ return FabricSQLQueryExecutor(warehouse_connection=connection)
54
+
55
+ def get_query_object(self) -> MSSQLQuery:
56
+ return MSSQLQuery
57
+
58
+ def create_records_and_count_query(
59
+ self,
60
+ query: str,
61
+ limit: str,
62
+ page: str,
63
+ ) -> tuple[str, str]:
64
+ count_query = f"SELECT COUNT(*) FROM ({query}) AS _count"
65
+
66
+ if limit:
67
+ offset = (int(page) - 1) * int(limit) if page else 0
68
+ query = (
69
+ f"{query} "
70
+ f"ORDER BY (SELECT NULL) "
71
+ f"OFFSET {offset} ROWS "
72
+ f"FETCH NEXT {int(limit)} ROWS ONLY"
73
+ )
74
+
75
+ return count_query, query
@@ -0,0 +1,142 @@
1
+ import time
2
+
3
+ from concurrent.futures import ThreadPoolExecutor, as_completed
4
+ from typing import Any, Dict, List, Optional, Tuple
5
+
6
+ from sqlalchemy import text
7
+ from sqlalchemy.exc import InterfaceError, OperationalError, ProgrammingError
8
+
9
+ from shared_kernel.config import Config
10
+ from shared_kernel.data_warehouse_handlers.utils import extract_error_message
11
+ from shared_kernel.interfaces.query_executor import DataWarehouseQueryExecutor
12
+ from shared_kernel.interfaces.warehouse_connection import DataWarehouseConnection
13
+ from shared_kernel.logger import Logger
14
+
15
+ config = Config()
16
+ logger = Logger(config.get("APP_NAME"))
17
+ MAX_QUERY_CONCURRENCY = 5
18
+
19
+
20
+ class FabricSQLQueryExecutor(DataWarehouseQueryExecutor):
21
+ """
22
+ Query executor for Microsoft Fabric SQL Server
23
+ """
24
+
25
+ def __init__(self, warehouse_connection: DataWarehouseConnection) -> None:
26
+ self.warehouse_connection = warehouse_connection
27
+
28
+ def execute_query(
29
+ self,
30
+ query: str,
31
+ params: Optional[tuple] = None,
32
+ ) -> List[Dict[str, Any]]:
33
+ """
34
+ Execute a single SQL query and return all rows as a list of dicts.
35
+ """
36
+ with self.warehouse_connection.get_connection() as conn:
37
+ try:
38
+ logger.info(f"Executing query: {query}")
39
+ start = time.perf_counter()
40
+
41
+ result = (
42
+ conn.execute(text(query), params)
43
+ if params
44
+ else conn.execute(text(query))
45
+ )
46
+
47
+ elapsed = time.perf_counter() - start
48
+ logger.info(f"Query executed in {elapsed:.6f}s")
49
+
50
+ # Check if the query returns rows
51
+ if result.returns_rows:
52
+ # Optimize fetch performance for Microsoft Fabric by batching
53
+ result.cursor.arraysize = 5000
54
+ columns = [col for col in result.keys()]
55
+ return [dict(zip(columns, row)) for row in result.fetchall()]
56
+ else:
57
+ # Return an empty list for DDL queries
58
+ return []
59
+
60
+ except (OperationalError, ProgrammingError, InterfaceError) as e:
61
+ logger.error(f"Query failed: {query} — {e}", exc_info=True)
62
+ user_msg = extract_error_message(str(e))
63
+ raise Exception(f"Query execution failed: {user_msg}") from e
64
+ except Exception as e:
65
+ user_msg = extract_error_message(str(e))
66
+ raise Exception(f"Query execution failed: {user_msg}") from e
67
+
68
+ def execute_queries(
69
+ self,
70
+ queries: List[str],
71
+ ) -> List[List[Dict[str, Any]]]:
72
+ """
73
+ Execute multiple SQL queries in parallel and return results in input order.
74
+ """
75
+ if not queries:
76
+ return []
77
+
78
+ indexed: List[Tuple[int, str]] = list(enumerate(queries))
79
+ results: List[Optional[List[Dict[str, Any]]]] = [None] * len(queries)
80
+
81
+ with ThreadPoolExecutor(max_workers=MAX_QUERY_CONCURRENCY) as pool:
82
+ future_to_index = {
83
+ pool.submit(self.execute_query, query): idx
84
+ for idx, query in indexed
85
+ }
86
+
87
+ for future in as_completed(future_to_index):
88
+ idx = future_to_index[future]
89
+ try:
90
+ results[idx] = future.result()
91
+ except Exception as e:
92
+ # Cancel all pending futures
93
+ for pending in future_to_index:
94
+ if not pending.done():
95
+ pending.cancel()
96
+ raise Exception(
97
+ f"Parallel query execution failed on query index {idx}: {e}"
98
+ ) from e
99
+
100
+ return results
101
+
102
+ def execute_query_with_column_types(
103
+ self,
104
+ query: str,
105
+ params: Optional[tuple] = None,
106
+ ) -> Tuple[List[Dict[str, Any]], List[Tuple]]:
107
+ """
108
+ Execute a query and return both rows and raw DBAPI cursor description.
109
+ """
110
+ with self.warehouse_connection.get_connection() as conn:
111
+ try:
112
+ logger.info(f"Executing query with column types: {query}")
113
+ start = time.perf_counter()
114
+
115
+ result = (
116
+ conn.execute(text(query), params)
117
+ if params
118
+ else conn.execute(text(query))
119
+ )
120
+
121
+ elapsed = time.perf_counter() - start
122
+ logger.info(f"Query executed in {elapsed:.6f}s")
123
+
124
+ # Check if the query returns rows
125
+ if result.returns_rows:
126
+ # Optimize fetch performance for Microsoft Fabric by batching
127
+ result.cursor.arraysize = 5000
128
+ description = result.cursor.description
129
+ columns = [col for col in result.keys()]
130
+ rows = [dict(zip(columns, row)) for row in result.fetchall()]
131
+ return rows, description
132
+ else:
133
+ # Return empty rows and description for DDL queries
134
+ return [], []
135
+
136
+ except (OperationalError, ProgrammingError, InterfaceError) as e:
137
+ logger.error(f"Query failed: {query} — {e}", exc_info=True)
138
+ user_msg = extract_error_message(str(e))
139
+ raise Exception(f"Query execution failed: {user_msg}") from e
140
+ except Exception as e:
141
+ user_msg = extract_error_message(str(e))
142
+ raise Exception(f"Query execution failed: {user_msg}") from e
@@ -49,6 +49,7 @@ class MSSQLQueryExecutor(DataWarehouseQueryExecutor):
49
49
 
50
50
  # Check if the query returns rows
51
51
  if result.returns_rows:
52
+ result.cursor.arraysize = 5000
52
53
  columns = [col for col in result.keys()]
53
54
  return [dict(zip(columns, row)) for row in result.fetchall()]
54
55
  else:
@@ -128,6 +129,7 @@ class MSSQLQueryExecutor(DataWarehouseQueryExecutor):
128
129
 
129
130
  # Check if the query returns rows
130
131
  if result.returns_rows:
132
+ result.cursor.arraysize = 5000
131
133
  description = result.cursor.description
132
134
  columns = [col for col in result.keys()]
133
135
  rows = [dict(zip(columns, row)) for row in result.fetchall()]
@@ -7,6 +7,7 @@ from shared_kernel.data_warehouse_handlers.postgresql_handler import PostgreSQLW
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
9
  from shared_kernel.data_warehouse_handlers.jdbc_handler import JDBCWarehouseHandler
10
+ from shared_kernel.data_warehouse_handlers.fabric_sql_handler import FabricSQLWarehouseHandler
10
11
  from shared_kernel.enums.connection_engine import ConnectionEngine
11
12
 
12
13
 
@@ -20,4 +21,5 @@ warehouse_handlers = {
20
21
  ConnectionEngine.AZURESQL.value: MSSQLWarehouseHandler,
21
22
  ConnectionEngine.DATABRICKS.value: DatabricksWarehouseHandler,
22
23
  ConnectionEngine.JDBC.value: JDBCWarehouseHandler,
24
+ ConnectionEngine.FABRIC_SQL.value: FabricSQLWarehouseHandler,
23
25
  }
@@ -46,6 +46,19 @@ class MSSQLConfig(BaseConfig):
46
46
  default_schema: str = "dbo"
47
47
 
48
48
 
49
+ @dataclass
50
+ class FabricSQLConfig(BaseConfig):
51
+ """Configuration for Microsoft Fabric SQL Server connections."""
52
+
53
+ username: str
54
+ password: str
55
+ host: str
56
+ database: str
57
+ tenant_id: str
58
+ port: str = "1433"
59
+ default_schema: str = "dbo"
60
+
61
+
49
62
  @dataclass
50
63
  class DatabricksConfig(BaseConfig):
51
64
  """Configuration for Databricks connections."""
@@ -11,3 +11,4 @@ class ConnectionEngine(Enum):
11
11
  SNOWFLAKE = "snowflake"
12
12
  FACTWEAVERS_DW = "factweavers-dw"
13
13
  JDBC = "jdbc"
14
+ FABRIC_SQL = "fabric_sql"