dblift 2.5.2__tar.gz → 2.6.0__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 (485) hide show
  1. {dblift-2.5.2 → dblift-2.6.0}/PKG-INFO +4 -1
  2. {dblift-2.5.2 → dblift-2.6.0}/README.md +1 -0
  3. dblift-2.6.0/db/plugins/snowflake/__init__.py +12 -0
  4. dblift-2.6.0/db/plugins/snowflake/config.py +67 -0
  5. dblift-2.6.0/db/plugins/snowflake/plugin.py +22 -0
  6. dblift-2.6.0/db/plugins/snowflake/provider.py +449 -0
  7. dblift-2.6.0/db/plugins/snowflake/quirks.py +70 -0
  8. dblift-2.6.0/db/plugins/snowflake/sqlalchemy_url.py +83 -0
  9. {dblift-2.5.2 → dblift-2.6.0}/db/provider_registry.py +4 -1
  10. {dblift-2.5.2 → dblift-2.6.0}/dblift.egg-info/PKG-INFO +4 -1
  11. {dblift-2.5.2 → dblift-2.6.0}/dblift.egg-info/SOURCES.txt +6 -0
  12. {dblift-2.5.2 → dblift-2.6.0}/dblift.egg-info/entry_points.txt +1 -0
  13. {dblift-2.5.2 → dblift-2.6.0}/dblift.egg-info/requires.txt +3 -0
  14. {dblift-2.5.2 → dblift-2.6.0}/pyproject.toml +3 -1
  15. {dblift-2.5.2 → dblift-2.6.0}/LICENSE +0 -0
  16. {dblift-2.5.2 → dblift-2.6.0}/api/__init__.py +0 -0
  17. {dblift-2.5.2 → dblift-2.6.0}/api/_cli_support.py +0 -0
  18. {dblift-2.5.2 → dblift-2.6.0}/api/_client_factory.py +0 -0
  19. {dblift-2.5.2 → dblift-2.6.0}/api/_client_operations.py +0 -0
  20. {dblift-2.5.2 → dblift-2.6.0}/api/_engine_config.py +0 -0
  21. {dblift-2.5.2 → dblift-2.6.0}/api/async_client.py +0 -0
  22. {dblift-2.5.2 → dblift-2.6.0}/api/client.py +0 -0
  23. {dblift-2.5.2 → dblift-2.6.0}/api/events.py +0 -0
  24. {dblift-2.5.2 → dblift-2.6.0}/api/migrations.py +0 -0
  25. {dblift-2.5.2 → dblift-2.6.0}/api/py.typed +0 -0
  26. {dblift-2.5.2 → dblift-2.6.0}/cli/__init__.py +0 -0
  27. {dblift-2.5.2 → dblift-2.6.0}/cli/_command_handlers.py +0 -0
  28. {dblift-2.5.2 → dblift-2.6.0}/cli/_config_helpers.py +0 -0
  29. {dblift-2.5.2 → dblift-2.6.0}/cli/_constants.py +0 -0
  30. {dblift-2.5.2 → dblift-2.6.0}/cli/_output.py +0 -0
  31. {dblift-2.5.2 → dblift-2.6.0}/cli/_parser_setup.py +0 -0
  32. {dblift-2.5.2 → dblift-2.6.0}/cli/commands/__init__.py +0 -0
  33. {dblift-2.5.2 → dblift-2.6.0}/cli/commands/config_command.py +0 -0
  34. {dblift-2.5.2 → dblift-2.6.0}/cli/db_utils.py +0 -0
  35. {dblift-2.5.2 → dblift-2.6.0}/cli/extensions.py +0 -0
  36. {dblift-2.5.2 → dblift-2.6.0}/cli/handlers/__init__.py +0 -0
  37. {dblift-2.5.2 → dblift-2.6.0}/cli/handlers/_shared.py +0 -0
  38. {dblift-2.5.2 → dblift-2.6.0}/cli/handlers/baseline.py +0 -0
  39. {dblift-2.5.2 → dblift-2.6.0}/cli/handlers/clean.py +0 -0
  40. {dblift-2.5.2 → dblift-2.6.0}/cli/handlers/import_flyway.py +0 -0
  41. {dblift-2.5.2 → dblift-2.6.0}/cli/handlers/info.py +0 -0
  42. {dblift-2.5.2 → dblift-2.6.0}/cli/handlers/migrate.py +0 -0
  43. {dblift-2.5.2 → dblift-2.6.0}/cli/handlers/repair.py +0 -0
  44. {dblift-2.5.2 → dblift-2.6.0}/cli/handlers/undo.py +0 -0
  45. {dblift-2.5.2 → dblift-2.6.0}/cli/handlers/validate.py +0 -0
  46. {dblift-2.5.2 → dblift-2.6.0}/cli/main.py +0 -0
  47. {dblift-2.5.2 → dblift-2.6.0}/config/__init__.py +0 -0
  48. {dblift-2.5.2 → dblift-2.6.0}/config/_credential_masking.py +0 -0
  49. {dblift-2.5.2 → dblift-2.6.0}/config/_subclasses/__init__.py +0 -0
  50. {dblift-2.5.2 → dblift-2.6.0}/config/_subclasses/dummy_config.py +0 -0
  51. {dblift-2.5.2 → dblift-2.6.0}/config/_url_builder_mixin.py +0 -0
  52. {dblift-2.5.2 → dblift-2.6.0}/config/config_builder.py +0 -0
  53. {dblift-2.5.2 → dblift-2.6.0}/config/database_config.py +0 -0
  54. {dblift-2.5.2 → dblift-2.6.0}/config/dblift_config.py +0 -0
  55. {dblift-2.5.2 → dblift-2.6.0}/config/errors.py +0 -0
  56. {dblift-2.5.2 → dblift-2.6.0}/config/property_registry.py +0 -0
  57. {dblift-2.5.2 → dblift-2.6.0}/config/secrets/__init__.py +0 -0
  58. {dblift-2.5.2 → dblift-2.6.0}/config/secrets/_cache.py +0 -0
  59. {dblift-2.5.2 → dblift-2.6.0}/config/secrets/_provider_base.py +0 -0
  60. {dblift-2.5.2 → dblift-2.6.0}/config/secrets/_registry.py +0 -0
  61. {dblift-2.5.2 → dblift-2.6.0}/config/secrets/_resolver.py +0 -0
  62. {dblift-2.5.2 → dblift-2.6.0}/config/secrets/_secrets_config.py +0 -0
  63. {dblift-2.5.2 → dblift-2.6.0}/core/__init__.py +0 -0
  64. {dblift-2.5.2 → dblift-2.6.0}/core/constants.py +0 -0
  65. {dblift-2.5.2 → dblift-2.6.0}/core/dialect_boundary.py +0 -0
  66. {dblift-2.5.2 → dblift-2.6.0}/core/exceptions.py +0 -0
  67. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/__init__.py +0 -0
  68. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/_column_enricher.py +0 -0
  69. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/_partition_enricher.py +0 -0
  70. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/_schema_orchestrator.py +0 -0
  71. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/_utils.py +0 -0
  72. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/_vendor_property_applier.py +0 -0
  73. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/base_introspector.py +0 -0
  74. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/extractors/__init__.py +0 -0
  75. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/extractors/base_extractor.py +0 -0
  76. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/extractors/column_extractor.py +0 -0
  77. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/extractors/constraint_extractor.py +0 -0
  78. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/extractors/index_extractor.py +0 -0
  79. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/extractors/misc_extractor.py +0 -0
  80. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/extractors/procedure_extractor.py +0 -0
  81. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/extractors/sequence_extractor.py +0 -0
  82. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/extractors/table_extractor.py +0 -0
  83. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/extractors/trigger_extractor.py +0 -0
  84. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/extractors/view_extractor.py +0 -0
  85. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/introspector_factory.py +0 -0
  86. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/result.py +0 -0
  87. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/schema_introspector.py +0 -0
  88. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/vendor_queries_base.py +0 -0
  89. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/vendor_queries_factory.py +0 -0
  90. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/vendor_queries_protocols.py +0 -0
  91. {dblift-2.5.2 → dblift-2.6.0}/core/introspection/version_detector.py +0 -0
  92. {dblift-2.5.2 → dblift-2.6.0}/core/logger/__init__.py +0 -0
  93. {dblift-2.5.2 → dblift-2.6.0}/core/logger/_base.py +0 -0
  94. {dblift-2.5.2 → dblift-2.6.0}/core/logger/_factory.py +0 -0
  95. {dblift-2.5.2 → dblift-2.6.0}/core/logger/_formatters.py +0 -0
  96. {dblift-2.5.2 → dblift-2.6.0}/core/logger/_levels.py +0 -0
  97. {dblift-2.5.2 → dblift-2.6.0}/core/logger/_multi.py +0 -0
  98. {dblift-2.5.2 → dblift-2.6.0}/core/logger/_null.py +0 -0
  99. {dblift-2.5.2 → dblift-2.6.0}/core/logger/console.py +0 -0
  100. {dblift-2.5.2 → dblift-2.6.0}/core/logger/formatters/__init__.py +0 -0
  101. {dblift-2.5.2 → dblift-2.6.0}/core/logger/formatters/_formatter_impl.py +0 -0
  102. {dblift-2.5.2 → dblift-2.6.0}/core/logger/formatters/factory.py +0 -0
  103. {dblift-2.5.2 → dblift-2.6.0}/core/logger/formatters/formatter.py +0 -0
  104. {dblift-2.5.2 → dblift-2.6.0}/core/logger/formatters/htmlformatter.py +0 -0
  105. {dblift-2.5.2 → dblift-2.6.0}/core/logger/formatters/jsonformatter.py +0 -0
  106. {dblift-2.5.2 → dblift-2.6.0}/core/logger/log.py +0 -0
  107. {dblift-2.5.2 → dblift-2.6.0}/core/logger/results.py +0 -0
  108. {dblift-2.5.2 → dblift-2.6.0}/core/logger/templates/oldreport.html +0 -0
  109. {dblift-2.5.2 → dblift-2.6.0}/core/logger/templates/report.html +0 -0
  110. {dblift-2.5.2 → dblift-2.6.0}/core/migration/__init__.py +0 -0
  111. {dblift-2.5.2 → dblift-2.6.0}/core/migration/_type_match.py +0 -0
  112. {dblift-2.5.2 → dblift-2.6.0}/core/migration/clean_summary.py +0 -0
  113. {dblift-2.5.2 → dblift-2.6.0}/core/migration/commands/__init__.py +0 -0
  114. {dblift-2.5.2 → dblift-2.6.0}/core/migration/commands/_script_events.py +0 -0
  115. {dblift-2.5.2 → dblift-2.6.0}/core/migration/commands/base_command.py +0 -0
  116. {dblift-2.5.2 → dblift-2.6.0}/core/migration/commands/baseline_command.py +0 -0
  117. {dblift-2.5.2 → dblift-2.6.0}/core/migration/commands/clean_command.py +0 -0
  118. {dblift-2.5.2 → dblift-2.6.0}/core/migration/commands/import_flyway_command.py +0 -0
  119. {dblift-2.5.2 → dblift-2.6.0}/core/migration/commands/info_command.py +0 -0
  120. {dblift-2.5.2 → dblift-2.6.0}/core/migration/commands/migrate_command.py +0 -0
  121. {dblift-2.5.2 → dblift-2.6.0}/core/migration/commands/repair_command.py +0 -0
  122. {dblift-2.5.2 → dblift-2.6.0}/core/migration/commands/undo_command.py +0 -0
  123. {dblift-2.5.2 → dblift-2.6.0}/core/migration/commands/validate_command.py +0 -0
  124. {dblift-2.5.2 → dblift-2.6.0}/core/migration/encoding.py +0 -0
  125. {dblift-2.5.2 → dblift-2.6.0}/core/migration/executor/__init__.py +0 -0
  126. {dblift-2.5.2 → dblift-2.6.0}/core/migration/executor/execution_engine.py +0 -0
  127. {dblift-2.5.2 → dblift-2.6.0}/core/migration/executor/migration_executor.py +0 -0
  128. {dblift-2.5.2 → dblift-2.6.0}/core/migration/executor/migration_helpers.py +0 -0
  129. {dblift-2.5.2 → dblift-2.6.0}/core/migration/executor/placeholder_manager.py +0 -0
  130. {dblift-2.5.2 → dblift-2.6.0}/core/migration/executor/transaction_policy.py +0 -0
  131. {dblift-2.5.2 → dblift-2.6.0}/core/migration/executors/__init__.py +0 -0
  132. {dblift-2.5.2 → dblift-2.6.0}/core/migration/executors/base_executor.py +0 -0
  133. {dblift-2.5.2 → dblift-2.6.0}/core/migration/executors/executor_factory.py +0 -0
  134. {dblift-2.5.2 → dblift-2.6.0}/core/migration/executors/python_executor.py +0 -0
  135. {dblift-2.5.2 → dblift-2.6.0}/core/migration/executors/sql_executor.py +0 -0
  136. {dblift-2.5.2 → dblift-2.6.0}/core/migration/formats/__init__.py +0 -0
  137. {dblift-2.5.2 → dblift-2.6.0}/core/migration/formats/format_detector.py +0 -0
  138. {dblift-2.5.2 → dblift-2.6.0}/core/migration/formats/migration_format.py +0 -0
  139. {dblift-2.5.2 → dblift-2.6.0}/core/migration/history/__init__.py +0 -0
  140. {dblift-2.5.2 → dblift-2.6.0}/core/migration/history/migration_history_manager.py +0 -0
  141. {dblift-2.5.2 → dblift-2.6.0}/core/migration/journals/__init__.py +0 -0
  142. {dblift-2.5.2 → dblift-2.6.0}/core/migration/journals/migration_journal.py +0 -0
  143. {dblift-2.5.2 → dblift-2.6.0}/core/migration/migration.py +0 -0
  144. {dblift-2.5.2 → dblift-2.6.0}/core/migration/placeholders/__init__.py +0 -0
  145. {dblift-2.5.2 → dblift-2.6.0}/core/migration/placeholders/placeholder_service.py +0 -0
  146. {dblift-2.5.2 → dblift-2.6.0}/core/migration/rules/__init__.py +0 -0
  147. {dblift-2.5.2 → dblift-2.6.0}/core/migration/rules/migration_rules.py +0 -0
  148. {dblift-2.5.2 → dblift-2.6.0}/core/migration/scripting/__init__.py +0 -0
  149. {dblift-2.5.2 → dblift-2.6.0}/core/migration/scripting/migration_script_manager.py +0 -0
  150. {dblift-2.5.2 → dblift-2.6.0}/core/migration/scripting/undo_script_generator/__init__.py +0 -0
  151. {dblift-2.5.2 → dblift-2.6.0}/core/migration/scripting/undo_script_generator/_ddl_reversers.py +0 -0
  152. {dblift-2.5.2 → dblift-2.6.0}/core/migration/scripting/undo_script_generator/_dml_reversers.py +0 -0
  153. {dblift-2.5.2 → dblift-2.6.0}/core/migration/scripting/undo_script_generator/_extractors.py +0 -0
  154. {dblift-2.5.2 → dblift-2.6.0}/core/migration/scripting/undo_script_generator/_generator.py +0 -0
  155. {dblift-2.5.2 → dblift-2.6.0}/core/migration/scripting/undo_script_generator/_helpers.py +0 -0
  156. {dblift-2.5.2 → dblift-2.6.0}/core/migration/scripting/undo_script_generator/_models.py +0 -0
  157. {dblift-2.5.2 → dblift-2.6.0}/core/migration/scripting/undo_script_generator/_reversers.py +0 -0
  158. {dblift-2.5.2 → dblift-2.6.0}/core/migration/sql/__init__.py +0 -0
  159. {dblift-2.5.2 → dblift-2.6.0}/core/migration/sql/execution_statement.py +0 -0
  160. {dblift-2.5.2 → dblift-2.6.0}/core/migration/sql/sql_analyzer.py +0 -0
  161. {dblift-2.5.2 → dblift-2.6.0}/core/migration/sql/sql_execution_service.py +0 -0
  162. {dblift-2.5.2 → dblift-2.6.0}/core/migration/sql/statement_splitter.py +0 -0
  163. {dblift-2.5.2 → dblift-2.6.0}/core/migration/state/__init__.py +0 -0
  164. {dblift-2.5.2 → dblift-2.6.0}/core/migration/state/migration_data_service.py +0 -0
  165. {dblift-2.5.2 → dblift-2.6.0}/core/migration/state/migration_display_state.py +0 -0
  166. {dblift-2.5.2 → dblift-2.6.0}/core/migration/state/migration_formatter.py +0 -0
  167. {dblift-2.5.2 → dblift-2.6.0}/core/migration/state/migration_state.py +0 -0
  168. {dblift-2.5.2 → dblift-2.6.0}/core/migration/state/migration_state_manager.py +0 -0
  169. {dblift-2.5.2 → dblift-2.6.0}/core/migration/state/migration_state_service.py +0 -0
  170. {dblift-2.5.2 → dblift-2.6.0}/core/migration/ui/__init__.py +0 -0
  171. {dblift-2.5.2 → dblift-2.6.0}/core/migration/ui/data_collector.py +0 -0
  172. {dblift-2.5.2 → dblift-2.6.0}/core/migration/ui/display_formatters.py +0 -0
  173. {dblift-2.5.2 → dblift-2.6.0}/core/migration/ui/migration_analyzer.py +0 -0
  174. {dblift-2.5.2 → dblift-2.6.0}/core/migration/ui/migration_ui.py +0 -0
  175. {dblift-2.5.2 → dblift-2.6.0}/core/migration/ui/table_renderer.py +0 -0
  176. {dblift-2.5.2 → dblift-2.6.0}/core/migration/version_utils.py +0 -0
  177. {dblift-2.5.2 → dblift-2.6.0}/core/normalization/__init__.py +0 -0
  178. {dblift-2.5.2 → dblift-2.6.0}/core/normalization/dependency_resolver.py +0 -0
  179. {dblift-2.5.2 → dblift-2.6.0}/core/normalization/identifier_normalizer.py +0 -0
  180. {dblift-2.5.2 → dblift-2.6.0}/core/normalization/object_orderer.py +0 -0
  181. {dblift-2.5.2 → dblift-2.6.0}/core/normalization/type_constants.py +0 -0
  182. {dblift-2.5.2 → dblift-2.6.0}/core/normalization/type_mapper.py +0 -0
  183. {dblift-2.5.2 → dblift-2.6.0}/core/normalization/type_mappings.py +0 -0
  184. {dblift-2.5.2 → dblift-2.6.0}/core/normalization/type_normalizer.py +0 -0
  185. {dblift-2.5.2 → dblift-2.6.0}/core/seams/__init__.py +0 -0
  186. {dblift-2.5.2 → dblift-2.6.0}/core/seams/capabilities.py +0 -0
  187. {dblift-2.5.2 → dblift-2.6.0}/core/seams/event_listeners.py +0 -0
  188. {dblift-2.5.2 → dblift-2.6.0}/core/seams/feature_loading.py +0 -0
  189. {dblift-2.5.2 → dblift-2.6.0}/core/seams/introspection.py +0 -0
  190. {dblift-2.5.2 → dblift-2.6.0}/core/seams/license_info.py +0 -0
  191. {dblift-2.5.2 → dblift-2.6.0}/core/seams/runtime_checks.py +0 -0
  192. {dblift-2.5.2 → dblift-2.6.0}/core/seams/sql_generators.py +0 -0
  193. {dblift-2.5.2 → dblift-2.6.0}/core/seams/tier_resolver.py +0 -0
  194. {dblift-2.5.2 → dblift-2.6.0}/core/sql_generator/__init__.py +0 -0
  195. {dblift-2.5.2 → dblift-2.6.0}/core/sql_generator/alter/__init__.py +0 -0
  196. {dblift-2.5.2 → dblift-2.6.0}/core/sql_generator/alter/alter_generator_factory.py +0 -0
  197. {dblift-2.5.2 → dblift-2.6.0}/core/sql_generator/alter/base_alter_generator.py +0 -0
  198. {dblift-2.5.2 → dblift-2.6.0}/core/sql_generator/alter_generator.py +0 -0
  199. {dblift-2.5.2 → dblift-2.6.0}/core/sql_generator/base_generator.py +0 -0
  200. {dblift-2.5.2 → dblift-2.6.0}/core/sql_generator/basic_table_ddl_generator.py +0 -0
  201. {dblift-2.5.2 → dblift-2.6.0}/core/sql_generator/dependency_analyzer.py +0 -0
  202. {dblift-2.5.2 → dblift-2.6.0}/core/sql_generator/diff_converters/__init__.py +0 -0
  203. {dblift-2.5.2 → dblift-2.6.0}/core/sql_generator/diff_converters/base_converter.py +0 -0
  204. {dblift-2.5.2 → dblift-2.6.0}/core/sql_generator/formatter.py +0 -0
  205. {dblift-2.5.2 → dblift-2.6.0}/core/sql_generator/generator_factory.py +0 -0
  206. {dblift-2.5.2 → dblift-2.6.0}/core/sql_generator/options.py +0 -0
  207. {dblift-2.5.2 → dblift-2.6.0}/core/sql_generator/script_organizer.py +0 -0
  208. {dblift-2.5.2 → dblift-2.6.0}/core/sql_generator/sql_generator.py +0 -0
  209. {dblift-2.5.2 → dblift-2.6.0}/core/sql_generator/sql_statement.py +0 -0
  210. {dblift-2.5.2 → dblift-2.6.0}/core/sql_generator/table_ddl_render.py +0 -0
  211. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/__init__.py +0 -0
  212. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/_base_parse_result.py +0 -0
  213. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/_base_sql_column.py +0 -0
  214. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/_base_sql_constraint.py +0 -0
  215. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/_base_sql_object.py +0 -0
  216. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/_base_sql_statement.py +0 -0
  217. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/base.py +0 -0
  218. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/constraint_validator.py +0 -0
  219. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/database_link.py +0 -0
  220. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/dialect.py +0 -0
  221. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/event.py +0 -0
  222. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/extension.py +0 -0
  223. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/foreign_data_wrapper.py +0 -0
  224. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/foreign_server.py +0 -0
  225. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/index.py +0 -0
  226. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/linked_server.py +0 -0
  227. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/module.py +0 -0
  228. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/package.py +0 -0
  229. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/partition.py +0 -0
  230. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/procedure.py +0 -0
  231. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/sequence.py +0 -0
  232. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/synonym.py +0 -0
  233. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/table.py +0 -0
  234. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/table_canonicalizer.py +0 -0
  235. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/table_options.py +0 -0
  236. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/trigger.py +0 -0
  237. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/user_defined_type.py +0 -0
  238. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/view.py +0 -0
  239. {dblift-2.5.2 → dblift-2.6.0}/core/sql_model/view_options.py +0 -0
  240. {dblift-2.5.2 → dblift-2.6.0}/core/sql_parser/__init__.py +0 -0
  241. {dblift-2.5.2 → dblift-2.6.0}/core/sql_parser/_partition_handler.py +0 -0
  242. {dblift-2.5.2 → dblift-2.6.0}/core/sql_parser/_sqlglot_builders.py +0 -0
  243. {dblift-2.5.2 → dblift-2.6.0}/core/sql_parser/base_statement_parser.py +0 -0
  244. {dblift-2.5.2 → dblift-2.6.0}/core/sql_parser/base_tokenizer.py +0 -0
  245. {dblift-2.5.2 → dblift-2.6.0}/core/sql_parser/common/__init__.py +0 -0
  246. {dblift-2.5.2 → dblift-2.6.0}/core/sql_parser/common/base_parser.py +0 -0
  247. {dblift-2.5.2 → dblift-2.6.0}/core/sql_parser/dialects/__init__.py +0 -0
  248. {dblift-2.5.2 → dblift-2.6.0}/core/sql_parser/dialects/base_config.py +0 -0
  249. {dblift-2.5.2 → dblift-2.6.0}/core/sql_parser/enhanced_regex_parser.py +0 -0
  250. {dblift-2.5.2 → dblift-2.6.0}/core/sql_parser/hybrid_parser.py +0 -0
  251. {dblift-2.5.2 → dblift-2.6.0}/core/sql_parser/parser_context.py +0 -0
  252. {dblift-2.5.2 → dblift-2.6.0}/core/sql_parser/parser_factory.py +0 -0
  253. {dblift-2.5.2 → dblift-2.6.0}/core/sql_parser/parser_interface.py +0 -0
  254. {dblift-2.5.2 → dblift-2.6.0}/core/sql_parser/sqlglot_parser.py +0 -0
  255. {dblift-2.5.2 → dblift-2.6.0}/core/sql_parser/tokens.py +0 -0
  256. {dblift-2.5.2 → dblift-2.6.0}/core/sql_parser/unified_regex_parser.py +0 -0
  257. {dblift-2.5.2 → dblift-2.6.0}/core/sql_validator/__init__.py +0 -0
  258. {dblift-2.5.2 → dblift-2.6.0}/core/sql_validator/_checksum_validator.py +0 -0
  259. {dblift-2.5.2 → dblift-2.6.0}/core/sql_validator/_flyway_compatibility.py +0 -0
  260. {dblift-2.5.2 → dblift-2.6.0}/core/sql_validator/_migration_filter.py +0 -0
  261. {dblift-2.5.2 → dblift-2.6.0}/core/sql_validator/_sql_syntax_validator.py +0 -0
  262. {dblift-2.5.2 → dblift-2.6.0}/core/sql_validator/_strict_mode_validator.py +0 -0
  263. {dblift-2.5.2 → dblift-2.6.0}/core/sql_validator/migration_validator.py +0 -0
  264. {dblift-2.5.2 → dblift-2.6.0}/core/state/sql_script_formatter.py +0 -0
  265. {dblift-2.5.2 → dblift-2.6.0}/core/state/sql_statement.py +0 -0
  266. {dblift-2.5.2 → dblift-2.6.0}/core/utils/__init__.py +0 -0
  267. {dblift-2.5.2 → dblift-2.6.0}/core/utils/database_url_parser.py +0 -0
  268. {dblift-2.5.2 → dblift-2.6.0}/core/utils/metadata_helpers.py +0 -0
  269. {dblift-2.5.2 → dblift-2.6.0}/core/utils/row_access.py +0 -0
  270. {dblift-2.5.2 → dblift-2.6.0}/core/utils/string_utils.py +0 -0
  271. {dblift-2.5.2 → dblift-2.6.0}/core/utils/url_masking.py +0 -0
  272. {dblift-2.5.2 → dblift-2.6.0}/db/__init__.py +0 -0
  273. {dblift-2.5.2 → dblift-2.6.0}/db/base_provider.py +0 -0
  274. {dblift-2.5.2 → dblift-2.6.0}/db/base_quirks.py +0 -0
  275. {dblift-2.5.2 → dblift-2.6.0}/db/constants.py +0 -0
  276. {dblift-2.5.2 → dblift-2.6.0}/db/dml_analysis.py +0 -0
  277. {dblift-2.5.2 → dblift-2.6.0}/db/error.py +0 -0
  278. {dblift-2.5.2 → dblift-2.6.0}/db/error_handler.py +0 -0
  279. {dblift-2.5.2 → dblift-2.6.0}/db/exceptions.py +0 -0
  280. {dblift-2.5.2 → dblift-2.6.0}/db/native_connection_manager.py +0 -0
  281. {dblift-2.5.2 → dblift-2.6.0}/db/object_naming.py +0 -0
  282. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/__init__.py +0 -0
  283. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/alloydb/__init__.py +0 -0
  284. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/alloydb/plugin.py +0 -0
  285. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/alloydb/provider.py +0 -0
  286. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/alloydb/quirks.py +0 -0
  287. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/aurora_postgresql/__init__.py +0 -0
  288. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/aurora_postgresql/plugin.py +0 -0
  289. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/aurora_postgresql/provider.py +0 -0
  290. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/aurora_postgresql/quirks.py +0 -0
  291. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/base_history_manager.py +0 -0
  292. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/base_locking_manager.py +0 -0
  293. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/base_query_executor.py +0 -0
  294. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/base_schema_operations.py +0 -0
  295. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/base_snapshot_manager.py +0 -0
  296. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/base_undo_manager.py +0 -0
  297. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/citus/__init__.py +0 -0
  298. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/citus/plugin.py +0 -0
  299. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/citus/provider.py +0 -0
  300. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/citus/quirks.py +0 -0
  301. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cockroachdb/__init__.py +0 -0
  302. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cockroachdb/plugin.py +0 -0
  303. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cockroachdb/provider.py +0 -0
  304. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cockroachdb/quirks.py +0 -0
  305. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cosmosdb/__init__.py +0 -0
  306. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cosmosdb/config.py +0 -0
  307. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cosmosdb/cosmosdb/__init__.py +0 -0
  308. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cosmosdb/cosmosdb/_sdk.py +0 -0
  309. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cosmosdb/cosmosdb/connection_manager.py +0 -0
  310. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cosmosdb/cosmosdb/history_manager.py +0 -0
  311. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cosmosdb/cosmosdb/locking_manager.py +0 -0
  312. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cosmosdb/cosmosdb/query_executor.py +0 -0
  313. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cosmosdb/cosmosdb/schema_operations.py +0 -0
  314. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cosmosdb/introspection/__init__.py +0 -0
  315. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cosmosdb/parser/__init__.py +0 -0
  316. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cosmosdb/parser/cosmosdb_regex_parser.py +0 -0
  317. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cosmosdb/plugin.py +0 -0
  318. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cosmosdb/provider.py +0 -0
  319. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cosmosdb/quirks.py +0 -0
  320. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cosmosdb/sdk_translator/__init__.py +0 -0
  321. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cosmosdb/sdk_translator/_executor.py +0 -0
  322. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cosmosdb/sdk_translator/_executors.py +0 -0
  323. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cosmosdb/sdk_translator/_parsing.py +0 -0
  324. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cosmosdb/sdk_translator/_script_generation.py +0 -0
  325. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cosmosdb/sdk_translator/_translator.py +0 -0
  326. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/cosmosdb/sdk_translator/_translators.py +0 -0
  327. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/db2/__init__.py +0 -0
  328. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/db2/config.py +0 -0
  329. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/db2/db2/__init__.py +0 -0
  330. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/db2/db2/history_manager.py +0 -0
  331. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/db2/db2/locking_manager.py +0 -0
  332. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/db2/db2/schema_operations.py +0 -0
  333. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/db2/introspection/__init__.py +0 -0
  334. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/db2/parser/__init__.py +0 -0
  335. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/db2/parser/db2_regex_parser.py +0 -0
  336. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/db2/parser/parser_config.py +0 -0
  337. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/db2/plugin.py +0 -0
  338. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/db2/provider.py +0 -0
  339. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/db2/quirks.py +0 -0
  340. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/db2/sqlalchemy_url.py +0 -0
  341. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/duckdb/__init__.py +0 -0
  342. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/duckdb/config.py +0 -0
  343. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/duckdb/parser/__init__.py +0 -0
  344. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/duckdb/parser/duckdb_regex_parser.py +0 -0
  345. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/duckdb/parser/parser_config.py +0 -0
  346. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/duckdb/plugin.py +0 -0
  347. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/duckdb/provider.py +0 -0
  348. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/duckdb/quirks.py +0 -0
  349. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/duckdb/sqlalchemy_url.py +0 -0
  350. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/mariadb/__init__.py +0 -0
  351. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/mariadb/plugin.py +0 -0
  352. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/mariadb/provider.py +0 -0
  353. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/mariadb/quirks.py +0 -0
  354. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/mysql/__init__.py +0 -0
  355. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/mysql/config.py +0 -0
  356. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/mysql/introspection/__init__.py +0 -0
  357. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/mysql/mysql/__init__.py +0 -0
  358. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/mysql/mysql/history_manager.py +0 -0
  359. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/mysql/mysql/locking_manager.py +0 -0
  360. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/mysql/mysql/schema_operations.py +0 -0
  361. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/mysql/parser/__init__.py +0 -0
  362. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/mysql/parser/mysql_regex_parser.py +0 -0
  363. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/mysql/parser/mysql_statement_parser.py +0 -0
  364. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/mysql/parser/mysql_tokenizer.py +0 -0
  365. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/mysql/parser/parser_config.py +0 -0
  366. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/mysql/plugin.py +0 -0
  367. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/mysql/provider.py +0 -0
  368. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/mysql/quirks.py +0 -0
  369. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/mysql/sqlalchemy_url.py +0 -0
  370. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/neon/__init__.py +0 -0
  371. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/neon/plugin.py +0 -0
  372. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/neon/provider.py +0 -0
  373. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/neon/quirks.py +0 -0
  374. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/__init__.py +0 -0
  375. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/config.py +0 -0
  376. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/introspection/__init__.py +0 -0
  377. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/introspection/oracle_utils.py +0 -0
  378. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/oracle/__init__.py +0 -0
  379. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/oracle/dbms_output.py +0 -0
  380. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/oracle/history_manager.py +0 -0
  381. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/oracle/locking_manager.py +0 -0
  382. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/oracle/schema_operations.py +0 -0
  383. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/parser/__init__.py +0 -0
  384. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/parser/_comments.py +0 -0
  385. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/parser/_object_extractor.py +0 -0
  386. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/parser/_plsql_block.py +0 -0
  387. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/parser/_sqlplus.py +0 -0
  388. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/parser/_statement_splitter.py +0 -0
  389. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/parser/oracle_parser.py +0 -0
  390. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/parser/oracle_statement_parser.py +0 -0
  391. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/parser/oracle_tokenizer.py +0 -0
  392. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/parser/parser_config.py +0 -0
  393. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/parser/sqlplus_context.py +0 -0
  394. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/plugin.py +0 -0
  395. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/provider.py +0 -0
  396. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/quirks.py +0 -0
  397. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/oracle/sqlalchemy_url.py +0 -0
  398. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/postgresql/__init__.py +0 -0
  399. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/postgresql/_provider_query_executor.py +0 -0
  400. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/postgresql/config.py +0 -0
  401. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/postgresql/introspection/__init__.py +0 -0
  402. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/postgresql/parser/__init__.py +0 -0
  403. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/postgresql/parser/parser_config.py +0 -0
  404. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/postgresql/parser/postgresql_regex_parser.py +0 -0
  405. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/postgresql/parser/postgresql_statement_parser.py +0 -0
  406. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/postgresql/parser/postgresql_tokenizer.py +0 -0
  407. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/postgresql/plugin.py +0 -0
  408. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/postgresql/postgresql/__init__.py +0 -0
  409. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/postgresql/postgresql/history_manager.py +0 -0
  410. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/postgresql/postgresql/locking_manager.py +0 -0
  411. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/postgresql/postgresql/schema_operations.py +0 -0
  412. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/postgresql/provider.py +0 -0
  413. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/postgresql/quirks.py +0 -0
  414. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/postgresql/sqlalchemy_url.py +0 -0
  415. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/redshift/__init__.py +0 -0
  416. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/redshift/plugin.py +0 -0
  417. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/redshift/provider.py +0 -0
  418. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/redshift/quirks.py +0 -0
  419. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/redshift/sqlalchemy_url.py +0 -0
  420. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlite/__init__.py +0 -0
  421. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlite/config.py +0 -0
  422. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlite/introspection/__init__.py +0 -0
  423. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlite/parser/__init__.py +0 -0
  424. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlite/parser/parser_config.py +0 -0
  425. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlite/parser/sqlite_regex_parser.py +0 -0
  426. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlite/plugin.py +0 -0
  427. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlite/provider.py +0 -0
  428. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlite/quirks.py +0 -0
  429. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlite/sqlalchemy_url.py +0 -0
  430. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlite/sqlite/__init__.py +0 -0
  431. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlite/sqlite/connection_manager.py +0 -0
  432. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlite/sqlite/history_manager.py +0 -0
  433. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlite/sqlite/locking_manager.py +0 -0
  434. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlite/sqlite/query_executor.py +0 -0
  435. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlite/sqlite/schema_operations.py +0 -0
  436. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlserver/__init__.py +0 -0
  437. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlserver/config.py +0 -0
  438. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlserver/introspection/__init__.py +0 -0
  439. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlserver/parser/__init__.py +0 -0
  440. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlserver/parser/parser_config.py +0 -0
  441. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlserver/parser/sqlserver_regex_parser.py +0 -0
  442. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlserver/parser/sqlserver_statement_parser.py +0 -0
  443. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlserver/parser/sqlserver_tokenizer.py +0 -0
  444. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlserver/parser/tsql_batch_separator.py +0 -0
  445. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlserver/plugin.py +0 -0
  446. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlserver/provider.py +0 -0
  447. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlserver/quirks.py +0 -0
  448. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlserver/sqlalchemy_url.py +0 -0
  449. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlserver/sqlserver/__init__.py +0 -0
  450. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlserver/sqlserver/history_manager.py +0 -0
  451. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlserver/sqlserver/locking_manager.py +0 -0
  452. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/sqlserver/sqlserver/schema_operations.py +0 -0
  453. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/supabase/__init__.py +0 -0
  454. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/supabase/plugin.py +0 -0
  455. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/supabase/provider.py +0 -0
  456. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/supabase/quirks.py +0 -0
  457. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/timescaledb/__init__.py +0 -0
  458. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/timescaledb/plugin.py +0 -0
  459. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/timescaledb/provider.py +0 -0
  460. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/timescaledb/quirks.py +0 -0
  461. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/yugabytedb/__init__.py +0 -0
  462. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/yugabytedb/plugin.py +0 -0
  463. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/yugabytedb/provider.py +0 -0
  464. {dblift-2.5.2 → dblift-2.6.0}/db/plugins/yugabytedb/quirks.py +0 -0
  465. {dblift-2.5.2 → dblift-2.6.0}/db/provider_capabilities.py +0 -0
  466. {dblift-2.5.2 → dblift-2.6.0}/db/provider_interfaces.py +0 -0
  467. {dblift-2.5.2 → dblift-2.6.0}/db/sqlalchemy_provider.py +0 -0
  468. {dblift-2.5.2 → dblift-2.6.0}/db/value_utils.py +0 -0
  469. {dblift-2.5.2 → dblift-2.6.0}/dblift.egg-info/dependency_links.txt +0 -0
  470. {dblift-2.5.2 → dblift-2.6.0}/dblift.egg-info/top_level.txt +0 -0
  471. {dblift-2.5.2 → dblift-2.6.0}/integrations/__init__.py +0 -0
  472. {dblift-2.5.2 → dblift-2.6.0}/integrations/django/__init__.py +0 -0
  473. {dblift-2.5.2 → dblift-2.6.0}/integrations/django/_client.py +0 -0
  474. {dblift-2.5.2 → dblift-2.6.0}/integrations/django/_engine.py +0 -0
  475. {dblift-2.5.2 → dblift-2.6.0}/integrations/django/apps.py +0 -0
  476. {dblift-2.5.2 → dblift-2.6.0}/integrations/django/checks.py +0 -0
  477. {dblift-2.5.2 → dblift-2.6.0}/integrations/django/management/__init__.py +0 -0
  478. {dblift-2.5.2 → dblift-2.6.0}/integrations/django/management/commands/__init__.py +0 -0
  479. {dblift-2.5.2 → dblift-2.6.0}/integrations/django/management/commands/dblift_info.py +0 -0
  480. {dblift-2.5.2 → dblift-2.6.0}/integrations/django/management/commands/dblift_migrate.py +0 -0
  481. {dblift-2.5.2 → dblift-2.6.0}/integrations/django/management/commands/dblift_validate.py +0 -0
  482. {dblift-2.5.2 → dblift-2.6.0}/integrations/fastapi.py +0 -0
  483. {dblift-2.5.2 → dblift-2.6.0}/integrations/flask.py +0 -0
  484. {dblift-2.5.2 → dblift-2.6.0}/integrations/opentelemetry.py +0 -0
  485. {dblift-2.5.2 → dblift-2.6.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dblift
3
- Version: 2.5.2
3
+ Version: 2.6.0
4
4
  Summary: A database migration tool that supports multiple databases with native Python drivers
5
5
  Classifier: Development Status :: 5 - Production/Stable
6
6
  Classifier: Intended Audience :: Developers
@@ -88,6 +88,8 @@ Requires-Dist: psycopg[binary]>=3.1; extra == "cockroachdb"
88
88
  Provides-Extra: redshift
89
89
  Requires-Dist: sqlalchemy-redshift>=1.0.0; extra == "redshift"
90
90
  Requires-Dist: redshift-connector>=2.1.0; extra == "redshift"
91
+ Provides-Extra: snowflake
92
+ Requires-Dist: snowflake-sqlalchemy>=1.11.0; extra == "snowflake"
91
93
  Provides-Extra: fastapi
92
94
  Requires-Dist: fastapi>=0.100; extra == "fastapi"
93
95
  Provides-Extra: flask
@@ -734,6 +736,7 @@ DBLift works with these databases:
734
736
  | PostgreSQL | `postgresql+psycopg://localhost:5432/mydb` | `dblift[postgresql]` |
735
737
  | CockroachDB | `postgresql+psycopg://localhost:26257/mydb` | `dblift[cockroachdb]` |
736
738
  | Redshift | `postgresql+psycopg://cluster.example.com:5439/dev` | `dblift[redshift]` |
739
+ | Snowflake | `snowflake://user:password@account_identifier/database/schema?warehouse=WH&role=ROLE` | `dblift[snowflake]` |
737
740
  | SQL Server | `mssql+pymssql://localhost:1433/mydb` | `dblift[sqlserver]` |
738
741
  | Oracle | `oracle+oracledb://localhost:1521?sid=SID` | `dblift[oracle]` |
739
742
  | MySQL | `mysql+pymysql://localhost:3306/mydb` | `dblift[mysql]` |
@@ -632,6 +632,7 @@ DBLift works with these databases:
632
632
  | PostgreSQL | `postgresql+psycopg://localhost:5432/mydb` | `dblift[postgresql]` |
633
633
  | CockroachDB | `postgresql+psycopg://localhost:26257/mydb` | `dblift[cockroachdb]` |
634
634
  | Redshift | `postgresql+psycopg://cluster.example.com:5439/dev` | `dblift[redshift]` |
635
+ | Snowflake | `snowflake://user:password@account_identifier/database/schema?warehouse=WH&role=ROLE` | `dblift[snowflake]` |
635
636
  | SQL Server | `mssql+pymssql://localhost:1433/mydb` | `dblift[sqlserver]` |
636
637
  | Oracle | `oracle+oracledb://localhost:1521?sid=SID` | `dblift[oracle]` |
637
638
  | MySQL | `mysql+pymysql://localhost:3306/mydb` | `dblift[mysql]` |
@@ -0,0 +1,12 @@
1
+ """Snowflake database provider plugin."""
2
+
3
+ __plugin_name__ = "snowflake"
4
+ __plugin_version__ = "1.0.0"
5
+ __plugin_description__ = "Snowflake database provider"
6
+ __plugin_dialects__ = ["snowflake"]
7
+ __plugin_transport__ = "native"
8
+ __plugin_class__ = "SnowflakeProvider"
9
+
10
+ from .provider import SnowflakeProvider
11
+
12
+ __all__ = ["SnowflakeProvider"]
@@ -0,0 +1,67 @@
1
+ """Snowflake-specific ``BaseDatabaseConfig`` subclass."""
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Any, Dict, Optional
5
+
6
+ from config.database_config import BaseDatabaseConfig, register_database_type
7
+
8
+
9
+ # lint: allow-dialect-string: config type registration
10
+ @register_database_type("snowflake")
11
+ @dataclass
12
+ class SnowflakeConfig(BaseDatabaseConfig):
13
+ """Configuration for Snowflake SQLAlchemy connections."""
14
+
15
+ account: Optional[str] = None
16
+ warehouse: Optional[str] = None
17
+ role: Optional[str] = None
18
+ authenticator: Optional[str] = None
19
+
20
+ def __post_init__(self) -> None:
21
+ """Resolve account/database/schema from Snowflake URL fields."""
22
+ super().__post_init__()
23
+ # lint: allow-dialect-string: config type identity
24
+ self.type = "snowflake"
25
+
26
+ if not self.account and self.host:
27
+ self.account = str(self.host)
28
+
29
+ database_value = getattr(self, "database", None)
30
+ if database_value and "/" in str(database_value):
31
+ database, schema = str(database_value).split("/", 1)
32
+ self.database = database or None
33
+ if schema and not getattr(self, "schema", ""):
34
+ self.schema = schema
35
+
36
+ def build_connection_string(self) -> str:
37
+ """Build the Snowflake plugin-owned SQLAlchemy URL."""
38
+ return self.build_database_url()
39
+
40
+ def build_database_url(self) -> str:
41
+ """Build the Snowflake SQLAlchemy URL through the provider registry."""
42
+ from db.provider_registry import ProviderRegistry
43
+
44
+ url: str = ProviderRegistry.build_sqlalchemy_url(self)
45
+ return url
46
+
47
+ def to_dict(self) -> Dict[str, Any]:
48
+ """Convert to dictionary with Snowflake-specific parameters."""
49
+ result: Dict[str, Any] = super().to_dict()
50
+ result["account"] = self.account
51
+ result["warehouse"] = self.warehouse
52
+ result["role"] = self.role
53
+ result["authenticator"] = self.authenticator
54
+ return result
55
+
56
+ def get_connection_props(self) -> Dict[str, str]:
57
+ """Return Snowflake connection properties."""
58
+ props: Dict[str, str] = super().get_connection_props()
59
+ if self.account:
60
+ props["account"] = self.account
61
+ if self.warehouse:
62
+ props["warehouse"] = self.warehouse
63
+ if self.role:
64
+ props["role"] = self.role
65
+ if self.authenticator:
66
+ props["authenticator"] = self.authenticator
67
+ return props
@@ -0,0 +1,22 @@
1
+ """Entry-point declaration for the Snowflake plugin."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from db.plugins.snowflake.config import SnowflakeConfig
6
+ from db.plugins.snowflake.provider import SnowflakeProvider
7
+ from db.plugins.snowflake.quirks import SnowflakeQuirks
8
+ from db.plugins.snowflake.sqlalchemy_url import build_sqlalchemy_url
9
+ from db.provider_registry import PluginInfo
10
+
11
+ PLUGIN: PluginInfo = PluginInfo(
12
+ name="snowflake",
13
+ version="1.0.0",
14
+ description="Snowflake database provider",
15
+ dialects=["snowflake"],
16
+ provider_class=SnowflakeProvider,
17
+ transport="native",
18
+ quirks_class=SnowflakeQuirks,
19
+ config_class=SnowflakeConfig,
20
+ sqlalchemy_url_builder=build_sqlalchemy_url,
21
+ native_driver_module="snowflake.connector",
22
+ )
@@ -0,0 +1,449 @@
1
+ """Snowflake native provider backed by SQLAlchemy Core."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Dict, List, Optional
6
+
7
+ from sqlalchemy.engine import Connection, Transaction
8
+
9
+ from config import DbliftConfig
10
+ from core.logger import Log
11
+ from core.migration.clean_summary import CleanExecutionSummary
12
+ from db.provider_interfaces import DroppableObject
13
+ from db.sqlalchemy_provider import SqlAlchemyProvider
14
+
15
+
16
+ def _quote_identifier(identifier: str) -> str:
17
+ return '"' + identifier.upper().replace('"', '""') + '"'
18
+
19
+
20
+ def _is_lock_timeout_error(error: Exception) -> bool:
21
+ message = " ".join(
22
+ str(value or "").lower()
23
+ for value in (
24
+ getattr(error, "msg", None),
25
+ getattr(error, "raw_msg", None),
26
+ str(error),
27
+ )
28
+ )
29
+ markers = (
30
+ "lock timeout",
31
+ "lock wait timeout",
32
+ "waiting for this lock",
33
+ "waited too long for a lock",
34
+ )
35
+ return any(marker in message for marker in markers)
36
+
37
+
38
+ class SnowflakeProvider(SqlAlchemyProvider):
39
+ """Snowflake provider using the Snowflake SQLAlchemy dialect."""
40
+
41
+ canonical_dialect_key = "snowflake"
42
+ MIGRATION_LOCK_TABLE = "DBLIFT_MIGRATION_LOCK"
43
+ _migration_lock_connection: Connection | None = None
44
+ _migration_lock_transaction: Transaction | None = None
45
+
46
+ def __init__(
47
+ self,
48
+ config: DbliftConfig,
49
+ log: Optional[Log] = None,
50
+ ) -> None:
51
+ super().__init__(config, log)
52
+
53
+ def execute_statement(
54
+ self,
55
+ sql: str,
56
+ schema: Optional[str] = None,
57
+ params: Optional[List[Any]] = None,
58
+ ) -> int:
59
+ """Execute a SQL statement, optionally preparing the schema first."""
60
+ if schema:
61
+ self.create_schema_if_not_exists(schema)
62
+ self.set_current_schema(schema)
63
+ rowcount: int = super().execute_statement(
64
+ sql,
65
+ schema=schema,
66
+ params=params,
67
+ )
68
+ return rowcount
69
+
70
+ def create_schema_if_not_exists(self, schema: str) -> None:
71
+ """Create a Snowflake schema if it is missing."""
72
+ schema_name = _quote_identifier(schema)
73
+ self.execute_statement(f"CREATE SCHEMA IF NOT EXISTS {schema_name}")
74
+
75
+ def table_exists(self, schema: str, table_name: str) -> bool:
76
+ """Return whether a table exists in the given schema."""
77
+ rows = self.execute_query(
78
+ """
79
+ SELECT 1 AS present
80
+ FROM INFORMATION_SCHEMA.TABLES
81
+ WHERE TABLE_SCHEMA = UPPER(?)
82
+ AND TABLE_NAME = UPPER(?)
83
+ """,
84
+ [schema, table_name],
85
+ )
86
+ return bool(rows)
87
+
88
+ def get_database_version(self) -> str:
89
+ """Return Snowflake version information."""
90
+ rows = self.execute_query("SELECT CURRENT_VERSION() AS version")
91
+ if rows:
92
+ return f"Snowflake {rows[0]['version']}"
93
+ return "Unknown Snowflake Version"
94
+
95
+ def supports_transactional_ddl(self) -> bool:
96
+ """Snowflake DDL auto-commits."""
97
+ return False
98
+
99
+ def set_current_schema(self, schema: str) -> None:
100
+ """Set the current Snowflake schema for this session."""
101
+ super().execute_statement(f"USE SCHEMA {_quote_identifier(schema)}")
102
+
103
+ def get_schema_qualified_name(self, schema: str, object_name: str) -> str:
104
+ """Return a quoted schema-qualified object name."""
105
+ return f"{_quote_identifier(schema)}.{_quote_identifier(object_name)}"
106
+
107
+ def clean_schema(self, schema: str) -> CleanExecutionSummary:
108
+ """Drop Snowflake views, tables, and sequences in a schema."""
109
+ summary = self.get_clean_preview(schema)
110
+ for stmt in summary.statements:
111
+ self.execute_statement(stmt)
112
+ return summary
113
+
114
+ def get_clean_preview(self, schema: str) -> CleanExecutionSummary:
115
+ """Return Snowflake objects that clean would drop."""
116
+ summary = CleanExecutionSummary()
117
+
118
+ for view_name in self._object_names(_SNOWFLAKE_VIEWS_QUERY, schema):
119
+ qualified = self.get_schema_qualified_name(schema, view_name)
120
+ summary.record_drop(
121
+ f"DROP VIEW IF EXISTS {qualified}",
122
+ object_type="view",
123
+ name=view_name,
124
+ schema=schema,
125
+ )
126
+
127
+ for table_name in self._object_names(_SNOWFLAKE_TABLES_QUERY, schema):
128
+ qualified = self.get_schema_qualified_name(schema, table_name)
129
+ summary.record_drop(
130
+ f"DROP TABLE IF EXISTS {qualified} CASCADE",
131
+ object_type="table",
132
+ name=table_name,
133
+ schema=schema,
134
+ )
135
+
136
+ sequence_names = self._object_names(_SNOWFLAKE_SEQUENCES_QUERY, schema)
137
+ for sequence_name in sequence_names:
138
+ qualified = self.get_schema_qualified_name(schema, sequence_name)
139
+ summary.record_drop(
140
+ f"DROP SEQUENCE IF EXISTS {qualified}",
141
+ object_type="sequence",
142
+ name=sequence_name,
143
+ schema=schema,
144
+ )
145
+
146
+ return summary
147
+
148
+ def list_droppable_objects(self, schema: str) -> List[DroppableObject]:
149
+ """Return Snowflake clean candidates in preview order."""
150
+ summary = self.get_clean_preview(schema)
151
+ return [
152
+ DroppableObject(
153
+ name=obj.name,
154
+ object_type=obj.object_type,
155
+ drop_sql=drop_sql,
156
+ )
157
+ for obj, drop_sql in zip(summary.objects, summary.statements)
158
+ ]
159
+
160
+ def _object_names(self, query: str, schema: str) -> List[str]:
161
+ rows = self.execute_query(query, [schema])
162
+ return [
163
+ str(row.get("object_name") or row.get("OBJECT_NAME"))
164
+ for row in rows
165
+ if row.get("object_name") or row.get("OBJECT_NAME")
166
+ ]
167
+
168
+ def create_migration_lock_table_sql(self, schema: str) -> str:
169
+ """Return the Snowflake migration lock table DDL."""
170
+ qualified = self.get_schema_qualified_name(
171
+ schema,
172
+ self.MIGRATION_LOCK_TABLE,
173
+ )
174
+ return f"""
175
+ CREATE TABLE IF NOT EXISTS {qualified} (
176
+ lock_name VARCHAR(128) NOT NULL,
177
+ locked_at TIMESTAMP_NTZ DEFAULT CURRENT_TIMESTAMP()
178
+ )
179
+ """
180
+
181
+ def acquire_migration_lock_sql(self, schema: str) -> str:
182
+ """Return the DML statement holding the migration lock row."""
183
+ qualified = self.get_schema_qualified_name(
184
+ schema,
185
+ self.MIGRATION_LOCK_TABLE,
186
+ )
187
+ return (
188
+ f"UPDATE {qualified} "
189
+ "SET locked_at = CURRENT_TIMESTAMP() WHERE lock_name = 'migration'"
190
+ )
191
+
192
+ def create_migration_lock_table_if_not_exists(self, schema: str) -> None:
193
+ """Create and seed the Snowflake migration lock table."""
194
+ self.create_schema_if_not_exists(schema)
195
+ self.execute_statement(self.create_migration_lock_table_sql(schema))
196
+ lock_table = self.MIGRATION_LOCK_TABLE
197
+ qualified = self.get_schema_qualified_name(schema, lock_table)
198
+ # Snowflake accepts UNIQUE/PRIMARY KEY syntax on standard tables but
199
+ # does not enforce it, so seed the singleton lock row with one MERGE.
200
+ self.execute_statement(f"""
201
+ MERGE INTO {qualified} target
202
+ USING (
203
+ SELECT
204
+ 'migration' AS lock_name,
205
+ CURRENT_TIMESTAMP() AS locked_at
206
+ ) source
207
+ ON target.lock_name = source.lock_name
208
+ WHEN NOT MATCHED THEN
209
+ INSERT (lock_name, locked_at)
210
+ VALUES (source.lock_name, source.locked_at)
211
+ """)
212
+
213
+ def acquire_migration_lock(
214
+ self,
215
+ schema: str,
216
+ wait_timeout_seconds: int = 60,
217
+ ) -> bool:
218
+ """Acquire the migration lock with a DML transaction."""
219
+ if self._migration_lock_transaction is not None:
220
+ return True
221
+
222
+ self.create_migration_lock_table_if_not_exists(schema)
223
+ connection = self.engine.connect()
224
+ try:
225
+ timeout = max(0, int(wait_timeout_seconds))
226
+ set_timeout = f"ALTER SESSION SET LOCK_TIMEOUT = {timeout}"
227
+ connection.exec_driver_sql(set_timeout)
228
+ connection.commit()
229
+ transaction = connection.begin()
230
+ connection.exec_driver_sql(self.acquire_migration_lock_sql(schema))
231
+ except Exception as exc:
232
+ try:
233
+ connection.rollback()
234
+ finally:
235
+ connection.close()
236
+ if _is_lock_timeout_error(exc):
237
+ return False
238
+ raise
239
+
240
+ self._migration_lock_connection = connection
241
+ self._migration_lock_transaction = transaction
242
+ return True
243
+
244
+ def release_migration_lock(self, schema: str) -> bool:
245
+ """Release the Snowflake migration lock by ending its transaction."""
246
+ transaction = self._migration_lock_transaction
247
+ connection = self._migration_lock_connection
248
+ if transaction is None or connection is None:
249
+ return True
250
+
251
+ try:
252
+ transaction.commit()
253
+ return True
254
+ except Exception:
255
+ try:
256
+ transaction.rollback()
257
+ except Exception:
258
+ pass
259
+ return False
260
+ finally:
261
+ try:
262
+ connection.close()
263
+ finally:
264
+ self._migration_lock_connection = None
265
+ self._migration_lock_transaction = None
266
+
267
+ def close(self) -> None:
268
+ """Close SQLAlchemy resources and release any held migration lock."""
269
+ try:
270
+ self.release_migration_lock("")
271
+ finally:
272
+ super().close()
273
+
274
+ def get_applied_migrations(
275
+ self, schema: str, table_name: str = "dblift_schema_history"
276
+ ) -> List[Dict[str, Any]]:
277
+ """Return applied migration rows from the history table."""
278
+ normalized_table = table_name.upper()
279
+ if not self.table_exists(schema, normalized_table):
280
+ return []
281
+ rows: List[Dict[str, Any]] = self.execute_query(f"""
282
+ SELECT *
283
+ FROM {self.get_schema_qualified_name(schema, normalized_table)}
284
+ ORDER BY installed_rank
285
+ """)
286
+ return rows
287
+
288
+ def create_migration_history_table_if_not_exists(
289
+ self,
290
+ schema: str,
291
+ create_schema: bool = False,
292
+ table_name: str = "dblift_schema_history",
293
+ ) -> None:
294
+ """Create the Snowflake migration history table if missing."""
295
+ normalized_table = table_name.upper()
296
+ if create_schema:
297
+ self.create_schema_if_not_exists(schema)
298
+ if self.table_exists(schema, normalized_table):
299
+ if create_schema:
300
+ self._check_baseline_safety(schema, normalized_table)
301
+ return
302
+ create_sql = self.create_history_table(schema, normalized_table)
303
+ self.execute_statement(create_sql)
304
+
305
+ def _check_baseline_safety(self, schema: str, table_name: str) -> None:
306
+ """Refuse baseline when history already contains migrations."""
307
+ qualified_table = self.get_schema_qualified_name(schema, table_name)
308
+ count_sql = f"SELECT COUNT(1) AS count FROM {qualified_table}"
309
+ rows = self.execute_query(count_sql)
310
+ migration_count = 0
311
+ if rows:
312
+ count = rows[0].get("count", rows[0].get("COUNT", 0))
313
+ migration_count = int(count or 0)
314
+ if migration_count > 0:
315
+ baseline_error = "Baseline cannot run with existing migrations."
316
+ raise RuntimeError(
317
+ f"Schema {schema} already contains a migration history table "
318
+ f"{table_name} with {migration_count} migration(s). "
319
+ f"{baseline_error}"
320
+ )
321
+
322
+ def record_migration(
323
+ self,
324
+ schema: str,
325
+ migration_info: Dict[str, Any],
326
+ table_name: str = "dblift_schema_history",
327
+ ) -> None:
328
+ """Insert a migration record into the Snowflake history table."""
329
+ normalized_table = table_name.upper()
330
+ self.create_migration_history_table_if_not_exists(
331
+ schema,
332
+ table_name=normalized_table,
333
+ )
334
+ qualified_table = self.get_schema_qualified_name(
335
+ schema,
336
+ normalized_table,
337
+ )
338
+ self.execute_statement(
339
+ f"""
340
+ INSERT INTO {qualified_table}
341
+ (version, description, type, script, checksum,
342
+ installed_by, execution_time, success)
343
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
344
+ """,
345
+ params=[
346
+ migration_info.get("version"),
347
+ migration_info.get("description", ""),
348
+ migration_info.get("type", "SQL"),
349
+ migration_info.get("script", ""),
350
+ migration_info.get("checksum"),
351
+ migration_info.get("installed_by", "dblift"),
352
+ migration_info.get("execution_time", 0),
353
+ migration_info.get("success", True),
354
+ ],
355
+ )
356
+
357
+ def record_undo(
358
+ self,
359
+ schema: str,
360
+ version: str,
361
+ table_name: Optional[str] = None,
362
+ script_name: Optional[str] = None,
363
+ ) -> bool:
364
+ """Record a successful undo in Snowflake migration history."""
365
+ undo_script = script_name or f"UNDO_{version}.sql"
366
+ self.record_migration(
367
+ schema,
368
+ {
369
+ "version": version,
370
+ "description": f"Undo migration {version}",
371
+ "type": "UNDO_SQL",
372
+ "script": undo_script,
373
+ "checksum": 0,
374
+ "success": True,
375
+ },
376
+ table_name or "dblift_schema_history",
377
+ )
378
+ return True
379
+
380
+ def repair_migration_history(
381
+ self,
382
+ schema: str,
383
+ script_name: str,
384
+ checksum: Any,
385
+ table_name: str = "dblift_schema_history",
386
+ success_value: Optional[Any] = None,
387
+ ) -> bool:
388
+ """Update checksum and success state for an existing migration row."""
389
+ normalized_table = table_name.upper()
390
+ if not self.table_exists(schema, normalized_table):
391
+ return False
392
+ qualified_table = self.get_schema_qualified_name(
393
+ schema,
394
+ normalized_table,
395
+ )
396
+ result = self.execute_statement(
397
+ f"""
398
+ UPDATE {qualified_table}
399
+ SET checksum = ?, success = COALESCE(?, success)
400
+ WHERE script = ?
401
+ """,
402
+ params=[checksum, success_value, script_name],
403
+ )
404
+ return result > 0
405
+
406
+ def create_history_table(self, schema: str, table_name: str) -> str:
407
+ """Return SQL for the Snowflake migration history table."""
408
+ qualified_table = self.get_schema_qualified_name(schema, table_name)
409
+ return f"""
410
+ CREATE TABLE IF NOT EXISTS {qualified_table} (
411
+ installed_rank INTEGER AUTOINCREMENT
412
+ START 1 INCREMENT 1 PRIMARY KEY,
413
+ version VARCHAR(50),
414
+ description VARCHAR(200) NOT NULL,
415
+ type VARCHAR(20) NOT NULL,
416
+ script VARCHAR(1000) NOT NULL,
417
+ checksum VARCHAR(64),
418
+ installed_by VARCHAR(100) NOT NULL,
419
+ installed_on TIMESTAMP_NTZ DEFAULT CURRENT_TIMESTAMP(),
420
+ execution_time INTEGER NOT NULL,
421
+ success BOOLEAN NOT NULL
422
+ )
423
+ """
424
+
425
+
426
+ __all__ = ["SnowflakeProvider"]
427
+
428
+
429
+ _SNOWFLAKE_VIEWS_QUERY = """
430
+ SELECT table_name AS object_name
431
+ FROM INFORMATION_SCHEMA.VIEWS
432
+ WHERE TABLE_SCHEMA = UPPER(?)
433
+ ORDER BY table_name
434
+ """
435
+
436
+ _SNOWFLAKE_TABLES_QUERY = """
437
+ SELECT table_name AS object_name
438
+ FROM INFORMATION_SCHEMA.TABLES
439
+ WHERE TABLE_SCHEMA = UPPER(?)
440
+ AND TABLE_TYPE = 'BASE TABLE'
441
+ ORDER BY table_name
442
+ """
443
+
444
+ _SNOWFLAKE_SEQUENCES_QUERY = """
445
+ SELECT sequence_name AS object_name
446
+ FROM INFORMATION_SCHEMA.SEQUENCES
447
+ WHERE SEQUENCE_SCHEMA = UPPER(?)
448
+ ORDER BY sequence_name
449
+ """
@@ -0,0 +1,70 @@
1
+ """Snowflake :class:`DialectQuirks`."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Any, Optional, Type
6
+
7
+ from db.base_quirks import BaseQuirks
8
+
9
+ if TYPE_CHECKING:
10
+ from core.sql_generator.alter.base_alter_generator import (
11
+ BaseAlterGenerator,
12
+ )
13
+ from core.sql_generator.base_generator import BaseSqlGenerator
14
+
15
+
16
+ class SnowflakeQuirks(BaseQuirks):
17
+ """Snowflake-specific dialect behaviour."""
18
+
19
+ supports_transactions = True
20
+ supports_transactional_ddl = False
21
+ schema_required = True
22
+ uppercase_identifiers = True
23
+ clean_strategy = "native"
24
+ sqlglot_dialect = "snowflake"
25
+ default_schema_name = "PUBLIC"
26
+ drop_supports_if_exists = True
27
+ table_drop_style = "if_exists_cascade"
28
+ unquoted_identifier_case = "uppercase"
29
+ quote_qualified_folds_to_uppercase = True
30
+ connection_identifier_attrs = ("url", "account")
31
+ missing_connection_identifier_hint = "Snowflake requires url or account"
32
+ native_url_schema_params = ("schema",)
33
+ native_driver_display = "snowflake-connector-python"
34
+ pygments_lexer = "sql"
35
+
36
+ def __init__(self, dialect_name: str = "snowflake") -> None:
37
+ super().__init__(dialect_name=dialect_name)
38
+
39
+ def has_connection_identifier(self, database_config: Any) -> bool:
40
+ """Snowflake accepts a URL or an account identifier."""
41
+ if isinstance(database_config, dict):
42
+ url = database_config.get("url")
43
+ account = database_config.get("account")
44
+ if not account:
45
+ account = database_config.get("host")
46
+ else:
47
+ url = getattr(database_config, "url", None)
48
+ account = getattr(database_config, "account", None) or getattr(
49
+ database_config, "host", None
50
+ )
51
+ return bool(str(url or "").strip() or str(account or "").strip())
52
+
53
+ def ddl_generator_class(self) -> Optional[Type["BaseSqlGenerator"]]:
54
+ """Snowflake rich DDL generation is registered by higher tiers."""
55
+ return None
56
+
57
+ def alter_generator_class(self) -> Optional[Type["BaseAlterGenerator"]]:
58
+ """Snowflake ALTER generation is registered by higher tiers."""
59
+ return None
60
+
61
+ def introspector_class(self) -> Optional[Type[Any]]:
62
+ """Snowflake rich introspection is registered by higher tiers."""
63
+ return None
64
+
65
+ def vendor_queries_class(self) -> Optional[Type[Any]]:
66
+ """Snowflake metadata queries are registered by higher tiers."""
67
+ return None
68
+
69
+
70
+ __all__ = ["SnowflakeQuirks"]