dblift 3.3.0__tar.gz → 3.3.2__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 (472) hide show
  1. {dblift-3.3.0 → dblift-3.3.2}/PKG-INFO +1 -1
  2. {dblift-3.3.0 → dblift-3.3.2}/cli/db_utils.py +12 -73
  3. {dblift-3.3.0 → dblift-3.3.2}/core/migration/commands/base_command.py +18 -4
  4. {dblift-3.3.0 → dblift-3.3.2}/core/migration/commands/baseline_command.py +15 -1
  5. {dblift-3.3.0 → dblift-3.3.2}/core/migration/commands/import_flyway_command.py +22 -3
  6. {dblift-3.3.0 → dblift-3.3.2}/core/migration/commands/info_command.py +24 -8
  7. {dblift-3.3.0 → dblift-3.3.2}/core/migration/commands/migrate_command.py +7 -2
  8. {dblift-3.3.0 → dblift-3.3.2}/core/migration/commands/validate_command.py +26 -13
  9. {dblift-3.3.0 → dblift-3.3.2}/core/migration/executor/execution_engine.py +18 -3
  10. {dblift-3.3.0 → dblift-3.3.2}/core/migration/executor/migration_executor.py +4 -0
  11. {dblift-3.3.0 → dblift-3.3.2}/core/migration/executors/python_executor.py +4 -2
  12. {dblift-3.3.0 → dblift-3.3.2}/core/seams/sql_generators.py +6 -1
  13. {dblift-3.3.0 → dblift-3.3.2}/core/sql_validator/_checksum_validator.py +16 -1
  14. {dblift-3.3.0 → dblift-3.3.2}/core/sql_validator/migration_validator.py +9 -1
  15. {dblift-3.3.0 → dblift-3.3.2}/db/error.py +93 -0
  16. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/_pg_compatible.py +78 -24
  17. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/cosmosdb/history_manager.py +34 -28
  18. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/cosmosdb/query_executor.py +22 -0
  19. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/provider.py +8 -0
  20. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/db2/schema_operations.py +10 -10
  21. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mariadb/quirks.py +8 -19
  22. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/provider.py +7 -2
  23. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/yugabytedb/plugin.py +4 -0
  24. {dblift-3.3.0 → dblift-3.3.2}/db/provider_registry.py +15 -6
  25. {dblift-3.3.0 → dblift-3.3.2}/dblift.egg-info/PKG-INFO +1 -1
  26. {dblift-3.3.0 → dblift-3.3.2}/pyproject.toml +1 -1
  27. {dblift-3.3.0 → dblift-3.3.2}/LICENSE +0 -0
  28. {dblift-3.3.0 → dblift-3.3.2}/README.md +0 -0
  29. {dblift-3.3.0 → dblift-3.3.2}/api/__init__.py +0 -0
  30. {dblift-3.3.0 → dblift-3.3.2}/api/_cli_support.py +0 -0
  31. {dblift-3.3.0 → dblift-3.3.2}/api/_client_factory.py +0 -0
  32. {dblift-3.3.0 → dblift-3.3.2}/api/_client_operations.py +0 -0
  33. {dblift-3.3.0 → dblift-3.3.2}/api/_engine_config.py +0 -0
  34. {dblift-3.3.0 → dblift-3.3.2}/api/async_client.py +0 -0
  35. {dblift-3.3.0 → dblift-3.3.2}/api/client.py +0 -0
  36. {dblift-3.3.0 → dblift-3.3.2}/api/events.py +0 -0
  37. {dblift-3.3.0 → dblift-3.3.2}/api/migrations.py +0 -0
  38. {dblift-3.3.0 → dblift-3.3.2}/api/py.typed +0 -0
  39. {dblift-3.3.0 → dblift-3.3.2}/cli/__init__.py +0 -0
  40. {dblift-3.3.0 → dblift-3.3.2}/cli/_command_handlers.py +0 -0
  41. {dblift-3.3.0 → dblift-3.3.2}/cli/_config_helpers.py +0 -0
  42. {dblift-3.3.0 → dblift-3.3.2}/cli/_constants.py +0 -0
  43. {dblift-3.3.0 → dblift-3.3.2}/cli/_output.py +0 -0
  44. {dblift-3.3.0 → dblift-3.3.2}/cli/_parser_setup.py +0 -0
  45. {dblift-3.3.0 → dblift-3.3.2}/cli/commands/__init__.py +0 -0
  46. {dblift-3.3.0 → dblift-3.3.2}/cli/commands/config_command.py +0 -0
  47. {dblift-3.3.0 → dblift-3.3.2}/cli/extensions.py +0 -0
  48. {dblift-3.3.0 → dblift-3.3.2}/cli/handlers/__init__.py +0 -0
  49. {dblift-3.3.0 → dblift-3.3.2}/cli/handlers/_shared.py +0 -0
  50. {dblift-3.3.0 → dblift-3.3.2}/cli/handlers/baseline.py +0 -0
  51. {dblift-3.3.0 → dblift-3.3.2}/cli/handlers/clean.py +0 -0
  52. {dblift-3.3.0 → dblift-3.3.2}/cli/handlers/import_flyway.py +0 -0
  53. {dblift-3.3.0 → dblift-3.3.2}/cli/handlers/info.py +0 -0
  54. {dblift-3.3.0 → dblift-3.3.2}/cli/handlers/migrate.py +0 -0
  55. {dblift-3.3.0 → dblift-3.3.2}/cli/handlers/repair.py +0 -0
  56. {dblift-3.3.0 → dblift-3.3.2}/cli/handlers/undo.py +0 -0
  57. {dblift-3.3.0 → dblift-3.3.2}/cli/handlers/validate.py +0 -0
  58. {dblift-3.3.0 → dblift-3.3.2}/cli/main.py +0 -0
  59. {dblift-3.3.0 → dblift-3.3.2}/cli/premium_manifest.py +0 -0
  60. {dblift-3.3.0 → dblift-3.3.2}/config/__init__.py +0 -0
  61. {dblift-3.3.0 → dblift-3.3.2}/config/_credential_masking.py +0 -0
  62. {dblift-3.3.0 → dblift-3.3.2}/config/_subclasses/__init__.py +0 -0
  63. {dblift-3.3.0 → dblift-3.3.2}/config/_subclasses/dummy_config.py +0 -0
  64. {dblift-3.3.0 → dblift-3.3.2}/config/_url_builder_mixin.py +0 -0
  65. {dblift-3.3.0 → dblift-3.3.2}/config/config_builder.py +0 -0
  66. {dblift-3.3.0 → dblift-3.3.2}/config/database_config.py +0 -0
  67. {dblift-3.3.0 → dblift-3.3.2}/config/dblift_config.py +0 -0
  68. {dblift-3.3.0 → dblift-3.3.2}/config/errors.py +0 -0
  69. {dblift-3.3.0 → dblift-3.3.2}/config/property_registry.py +0 -0
  70. {dblift-3.3.0 → dblift-3.3.2}/config/secrets/__init__.py +0 -0
  71. {dblift-3.3.0 → dblift-3.3.2}/config/secrets/_cache.py +0 -0
  72. {dblift-3.3.0 → dblift-3.3.2}/config/secrets/_provider_base.py +0 -0
  73. {dblift-3.3.0 → dblift-3.3.2}/config/secrets/_registry.py +0 -0
  74. {dblift-3.3.0 → dblift-3.3.2}/config/secrets/_resolver.py +0 -0
  75. {dblift-3.3.0 → dblift-3.3.2}/config/secrets/_secrets_config.py +0 -0
  76. {dblift-3.3.0 → dblift-3.3.2}/core/__init__.py +0 -0
  77. {dblift-3.3.0 → dblift-3.3.2}/core/constants.py +0 -0
  78. {dblift-3.3.0 → dblift-3.3.2}/core/dialect_boundary.py +0 -0
  79. {dblift-3.3.0 → dblift-3.3.2}/core/exceptions.py +0 -0
  80. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/__init__.py +0 -0
  81. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/_column_enricher.py +0 -0
  82. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/_partition_enricher.py +0 -0
  83. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/_schema_orchestrator.py +0 -0
  84. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/_utils.py +0 -0
  85. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/_vendor_property_applier.py +0 -0
  86. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/base_introspector.py +0 -0
  87. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/extractors/__init__.py +0 -0
  88. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/extractors/base_extractor.py +0 -0
  89. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/extractors/column_extractor.py +0 -0
  90. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/extractors/constraint_extractor.py +0 -0
  91. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/extractors/index_extractor.py +0 -0
  92. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/extractors/misc_extractor.py +0 -0
  93. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/extractors/procedure_extractor.py +0 -0
  94. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/extractors/sequence_extractor.py +0 -0
  95. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/extractors/table_extractor.py +0 -0
  96. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/extractors/trigger_extractor.py +0 -0
  97. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/extractors/view_extractor.py +0 -0
  98. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/introspector_factory.py +0 -0
  99. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/result.py +0 -0
  100. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/schema_introspector.py +0 -0
  101. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/vendor_queries_base.py +0 -0
  102. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/vendor_queries_factory.py +0 -0
  103. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/vendor_queries_protocols.py +0 -0
  104. {dblift-3.3.0 → dblift-3.3.2}/core/introspection/version_detector.py +0 -0
  105. {dblift-3.3.0 → dblift-3.3.2}/core/logger/__init__.py +0 -0
  106. {dblift-3.3.0 → dblift-3.3.2}/core/logger/_base.py +0 -0
  107. {dblift-3.3.0 → dblift-3.3.2}/core/logger/_factory.py +0 -0
  108. {dblift-3.3.0 → dblift-3.3.2}/core/logger/_formatters.py +0 -0
  109. {dblift-3.3.0 → dblift-3.3.2}/core/logger/_levels.py +0 -0
  110. {dblift-3.3.0 → dblift-3.3.2}/core/logger/_multi.py +0 -0
  111. {dblift-3.3.0 → dblift-3.3.2}/core/logger/_null.py +0 -0
  112. {dblift-3.3.0 → dblift-3.3.2}/core/logger/console.py +0 -0
  113. {dblift-3.3.0 → dblift-3.3.2}/core/logger/formatters/__init__.py +0 -0
  114. {dblift-3.3.0 → dblift-3.3.2}/core/logger/formatters/_formatter_impl.py +0 -0
  115. {dblift-3.3.0 → dblift-3.3.2}/core/logger/formatters/factory.py +0 -0
  116. {dblift-3.3.0 → dblift-3.3.2}/core/logger/formatters/formatter.py +0 -0
  117. {dblift-3.3.0 → dblift-3.3.2}/core/logger/formatters/htmlformatter.py +0 -0
  118. {dblift-3.3.0 → dblift-3.3.2}/core/logger/formatters/jsonformatter.py +0 -0
  119. {dblift-3.3.0 → dblift-3.3.2}/core/logger/log.py +0 -0
  120. {dblift-3.3.0 → dblift-3.3.2}/core/logger/results.py +0 -0
  121. {dblift-3.3.0 → dblift-3.3.2}/core/logger/templates/oldreport.html +0 -0
  122. {dblift-3.3.0 → dblift-3.3.2}/core/logger/templates/report.html +0 -0
  123. {dblift-3.3.0 → dblift-3.3.2}/core/migration/__init__.py +0 -0
  124. {dblift-3.3.0 → dblift-3.3.2}/core/migration/_type_match.py +0 -0
  125. {dblift-3.3.0 → dblift-3.3.2}/core/migration/clean_summary.py +0 -0
  126. {dblift-3.3.0 → dblift-3.3.2}/core/migration/commands/__init__.py +0 -0
  127. {dblift-3.3.0 → dblift-3.3.2}/core/migration/commands/_script_events.py +0 -0
  128. {dblift-3.3.0 → dblift-3.3.2}/core/migration/commands/clean_command.py +0 -0
  129. {dblift-3.3.0 → dblift-3.3.2}/core/migration/commands/repair_command.py +0 -0
  130. {dblift-3.3.0 → dblift-3.3.2}/core/migration/commands/undo_command.py +0 -0
  131. {dblift-3.3.0 → dblift-3.3.2}/core/migration/encoding.py +0 -0
  132. {dblift-3.3.0 → dblift-3.3.2}/core/migration/executor/__init__.py +0 -0
  133. {dblift-3.3.0 → dblift-3.3.2}/core/migration/executor/migration_helpers.py +0 -0
  134. {dblift-3.3.0 → dblift-3.3.2}/core/migration/executor/placeholder_manager.py +0 -0
  135. {dblift-3.3.0 → dblift-3.3.2}/core/migration/executor/transaction_policy.py +0 -0
  136. {dblift-3.3.0 → dblift-3.3.2}/core/migration/executors/__init__.py +0 -0
  137. {dblift-3.3.0 → dblift-3.3.2}/core/migration/executors/base_executor.py +0 -0
  138. {dblift-3.3.0 → dblift-3.3.2}/core/migration/executors/executor_factory.py +0 -0
  139. {dblift-3.3.0 → dblift-3.3.2}/core/migration/executors/sql_executor.py +0 -0
  140. {dblift-3.3.0 → dblift-3.3.2}/core/migration/formats/__init__.py +0 -0
  141. {dblift-3.3.0 → dblift-3.3.2}/core/migration/formats/format_detector.py +0 -0
  142. {dblift-3.3.0 → dblift-3.3.2}/core/migration/formats/migration_format.py +0 -0
  143. {dblift-3.3.0 → dblift-3.3.2}/core/migration/history/__init__.py +0 -0
  144. {dblift-3.3.0 → dblift-3.3.2}/core/migration/history/migration_history_manager.py +0 -0
  145. {dblift-3.3.0 → dblift-3.3.2}/core/migration/journals/__init__.py +0 -0
  146. {dblift-3.3.0 → dblift-3.3.2}/core/migration/journals/migration_journal.py +0 -0
  147. {dblift-3.3.0 → dblift-3.3.2}/core/migration/migration.py +0 -0
  148. {dblift-3.3.0 → dblift-3.3.2}/core/migration/placeholders/__init__.py +0 -0
  149. {dblift-3.3.0 → dblift-3.3.2}/core/migration/placeholders/placeholder_service.py +0 -0
  150. {dblift-3.3.0 → dblift-3.3.2}/core/migration/rules/__init__.py +0 -0
  151. {dblift-3.3.0 → dblift-3.3.2}/core/migration/rules/migration_rules.py +0 -0
  152. {dblift-3.3.0 → dblift-3.3.2}/core/migration/scripting/__init__.py +0 -0
  153. {dblift-3.3.0 → dblift-3.3.2}/core/migration/scripting/migration_script_manager.py +0 -0
  154. {dblift-3.3.0 → dblift-3.3.2}/core/migration/scripting/undo_script_generator/__init__.py +0 -0
  155. {dblift-3.3.0 → dblift-3.3.2}/core/migration/scripting/undo_script_generator/_ddl_reversers.py +0 -0
  156. {dblift-3.3.0 → dblift-3.3.2}/core/migration/scripting/undo_script_generator/_dml_reversers.py +0 -0
  157. {dblift-3.3.0 → dblift-3.3.2}/core/migration/scripting/undo_script_generator/_extractors.py +0 -0
  158. {dblift-3.3.0 → dblift-3.3.2}/core/migration/scripting/undo_script_generator/_generator.py +0 -0
  159. {dblift-3.3.0 → dblift-3.3.2}/core/migration/scripting/undo_script_generator/_helpers.py +0 -0
  160. {dblift-3.3.0 → dblift-3.3.2}/core/migration/scripting/undo_script_generator/_models.py +0 -0
  161. {dblift-3.3.0 → dblift-3.3.2}/core/migration/scripting/undo_script_generator/_reversers.py +0 -0
  162. {dblift-3.3.0 → dblift-3.3.2}/core/migration/sql/__init__.py +0 -0
  163. {dblift-3.3.0 → dblift-3.3.2}/core/migration/sql/execution_statement.py +0 -0
  164. {dblift-3.3.0 → dblift-3.3.2}/core/migration/sql/sql_analyzer.py +0 -0
  165. {dblift-3.3.0 → dblift-3.3.2}/core/migration/sql/sql_execution_service.py +0 -0
  166. {dblift-3.3.0 → dblift-3.3.2}/core/migration/sql/statement_splitter.py +0 -0
  167. {dblift-3.3.0 → dblift-3.3.2}/core/migration/state/__init__.py +0 -0
  168. {dblift-3.3.0 → dblift-3.3.2}/core/migration/state/migration_data_service.py +0 -0
  169. {dblift-3.3.0 → dblift-3.3.2}/core/migration/state/migration_display_state.py +0 -0
  170. {dblift-3.3.0 → dblift-3.3.2}/core/migration/state/migration_formatter.py +0 -0
  171. {dblift-3.3.0 → dblift-3.3.2}/core/migration/state/migration_state.py +0 -0
  172. {dblift-3.3.0 → dblift-3.3.2}/core/migration/state/migration_state_manager.py +0 -0
  173. {dblift-3.3.0 → dblift-3.3.2}/core/migration/state/migration_state_service.py +0 -0
  174. {dblift-3.3.0 → dblift-3.3.2}/core/migration/ui/__init__.py +0 -0
  175. {dblift-3.3.0 → dblift-3.3.2}/core/migration/ui/data_collector.py +0 -0
  176. {dblift-3.3.0 → dblift-3.3.2}/core/migration/ui/display_formatters.py +0 -0
  177. {dblift-3.3.0 → dblift-3.3.2}/core/migration/ui/migration_analyzer.py +0 -0
  178. {dblift-3.3.0 → dblift-3.3.2}/core/migration/ui/migration_ui.py +0 -0
  179. {dblift-3.3.0 → dblift-3.3.2}/core/migration/ui/table_renderer.py +0 -0
  180. {dblift-3.3.0 → dblift-3.3.2}/core/migration/version_utils.py +0 -0
  181. {dblift-3.3.0 → dblift-3.3.2}/core/normalization/__init__.py +0 -0
  182. {dblift-3.3.0 → dblift-3.3.2}/core/normalization/dependency_resolver.py +0 -0
  183. {dblift-3.3.0 → dblift-3.3.2}/core/normalization/identifier_normalizer.py +0 -0
  184. {dblift-3.3.0 → dblift-3.3.2}/core/normalization/object_orderer.py +0 -0
  185. {dblift-3.3.0 → dblift-3.3.2}/core/normalization/type_constants.py +0 -0
  186. {dblift-3.3.0 → dblift-3.3.2}/core/normalization/type_mapper.py +0 -0
  187. {dblift-3.3.0 → dblift-3.3.2}/core/normalization/type_mappings.py +0 -0
  188. {dblift-3.3.0 → dblift-3.3.2}/core/normalization/type_normalizer.py +0 -0
  189. {dblift-3.3.0 → dblift-3.3.2}/core/seams/__init__.py +0 -0
  190. {dblift-3.3.0 → dblift-3.3.2}/core/seams/capabilities.py +0 -0
  191. {dblift-3.3.0 → dblift-3.3.2}/core/seams/client_factory.py +0 -0
  192. {dblift-3.3.0 → dblift-3.3.2}/core/seams/event_listeners.py +0 -0
  193. {dblift-3.3.0 → dblift-3.3.2}/core/seams/feature_loading.py +0 -0
  194. {dblift-3.3.0 → dblift-3.3.2}/core/seams/introspection.py +0 -0
  195. {dblift-3.3.0 → dblift-3.3.2}/core/seams/license_info.py +0 -0
  196. {dblift-3.3.0 → dblift-3.3.2}/core/seams/runtime_checks.py +0 -0
  197. {dblift-3.3.0 → dblift-3.3.2}/core/seams/tier_resolver.py +0 -0
  198. {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/__init__.py +0 -0
  199. {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/alter/__init__.py +0 -0
  200. {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/alter/alter_generator_factory.py +0 -0
  201. {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/alter/base_alter_generator.py +0 -0
  202. {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/alter_generator.py +0 -0
  203. {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/base_generator.py +0 -0
  204. {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/basic_table_ddl_generator.py +0 -0
  205. {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/dependency_analyzer.py +0 -0
  206. {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/diff_converters/__init__.py +0 -0
  207. {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/diff_converters/base_converter.py +0 -0
  208. {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/formatter.py +0 -0
  209. {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/generator_factory.py +0 -0
  210. {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/options.py +0 -0
  211. {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/script_organizer.py +0 -0
  212. {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/sql_generator.py +0 -0
  213. {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/sql_statement.py +0 -0
  214. {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/table_ddl_render.py +0 -0
  215. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/__init__.py +0 -0
  216. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/_base_parse_result.py +0 -0
  217. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/_base_sql_column.py +0 -0
  218. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/_base_sql_constraint.py +0 -0
  219. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/_base_sql_object.py +0 -0
  220. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/_base_sql_statement.py +0 -0
  221. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/base.py +0 -0
  222. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/constraint_validator.py +0 -0
  223. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/database_link.py +0 -0
  224. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/dialect.py +0 -0
  225. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/event.py +0 -0
  226. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/extension.py +0 -0
  227. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/feature_gates.py +0 -0
  228. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/foreign_data_wrapper.py +0 -0
  229. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/foreign_server.py +0 -0
  230. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/index.py +0 -0
  231. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/linked_server.py +0 -0
  232. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/module.py +0 -0
  233. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/package.py +0 -0
  234. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/partition.py +0 -0
  235. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/procedure.py +0 -0
  236. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/sequence.py +0 -0
  237. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/server_info.py +0 -0
  238. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/synonym.py +0 -0
  239. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/table.py +0 -0
  240. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/table_canonicalizer.py +0 -0
  241. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/table_options.py +0 -0
  242. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/trigger.py +0 -0
  243. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/user_defined_type.py +0 -0
  244. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/view.py +0 -0
  245. {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/view_options.py +0 -0
  246. {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/__init__.py +0 -0
  247. {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/_partition_handler.py +0 -0
  248. {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/_sqlglot_builders.py +0 -0
  249. {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/base_statement_parser.py +0 -0
  250. {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/base_tokenizer.py +0 -0
  251. {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/common/__init__.py +0 -0
  252. {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/common/base_parser.py +0 -0
  253. {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/dialects/__init__.py +0 -0
  254. {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/dialects/base_config.py +0 -0
  255. {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/enhanced_regex_parser.py +0 -0
  256. {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/hybrid_parser.py +0 -0
  257. {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/parser_context.py +0 -0
  258. {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/parser_factory.py +0 -0
  259. {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/parser_interface.py +0 -0
  260. {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/sqlglot_parser.py +0 -0
  261. {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/tokens.py +0 -0
  262. {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/unified_regex_parser.py +0 -0
  263. {dblift-3.3.0 → dblift-3.3.2}/core/sql_validator/__init__.py +0 -0
  264. {dblift-3.3.0 → dblift-3.3.2}/core/sql_validator/_flyway_compatibility.py +0 -0
  265. {dblift-3.3.0 → dblift-3.3.2}/core/sql_validator/_migration_filter.py +0 -0
  266. {dblift-3.3.0 → dblift-3.3.2}/core/sql_validator/_sql_syntax_validator.py +0 -0
  267. {dblift-3.3.0 → dblift-3.3.2}/core/sql_validator/_strict_mode_validator.py +0 -0
  268. {dblift-3.3.0 → dblift-3.3.2}/core/state/sql_script_formatter.py +0 -0
  269. {dblift-3.3.0 → dblift-3.3.2}/core/state/sql_statement.py +0 -0
  270. {dblift-3.3.0 → dblift-3.3.2}/core/utils/__init__.py +0 -0
  271. {dblift-3.3.0 → dblift-3.3.2}/core/utils/database_url_parser.py +0 -0
  272. {dblift-3.3.0 → dblift-3.3.2}/core/utils/metadata_helpers.py +0 -0
  273. {dblift-3.3.0 → dblift-3.3.2}/core/utils/row_access.py +0 -0
  274. {dblift-3.3.0 → dblift-3.3.2}/core/utils/string_utils.py +0 -0
  275. {dblift-3.3.0 → dblift-3.3.2}/core/utils/url_masking.py +0 -0
  276. {dblift-3.3.0 → dblift-3.3.2}/db/__init__.py +0 -0
  277. {dblift-3.3.0 → dblift-3.3.2}/db/base_provider.py +0 -0
  278. {dblift-3.3.0 → dblift-3.3.2}/db/base_quirks.py +0 -0
  279. {dblift-3.3.0 → dblift-3.3.2}/db/constants.py +0 -0
  280. {dblift-3.3.0 → dblift-3.3.2}/db/dml_analysis.py +0 -0
  281. {dblift-3.3.0 → dblift-3.3.2}/db/error_handler.py +0 -0
  282. {dblift-3.3.0 → dblift-3.3.2}/db/exceptions.py +0 -0
  283. {dblift-3.3.0 → dblift-3.3.2}/db/feature_gate.py +0 -0
  284. {dblift-3.3.0 → dblift-3.3.2}/db/native_connection_manager.py +0 -0
  285. {dblift-3.3.0 → dblift-3.3.2}/db/object_naming.py +0 -0
  286. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/__init__.py +0 -0
  287. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/alloydb/__init__.py +0 -0
  288. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/alloydb/plugin.py +0 -0
  289. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/aurora_postgresql/__init__.py +0 -0
  290. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/aurora_postgresql/plugin.py +0 -0
  291. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/base_history_manager.py +0 -0
  292. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/base_locking_manager.py +0 -0
  293. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/base_query_executor.py +0 -0
  294. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/base_schema_operations.py +0 -0
  295. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/base_snapshot_manager.py +0 -0
  296. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/base_undo_manager.py +0 -0
  297. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/citus/__init__.py +0 -0
  298. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/citus/plugin.py +0 -0
  299. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cockroachdb/__init__.py +0 -0
  300. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cockroachdb/plugin.py +0 -0
  301. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cockroachdb/provider.py +0 -0
  302. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cockroachdb/quirks.py +0 -0
  303. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/__init__.py +0 -0
  304. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/config.py +3 -3
  305. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/cosmosdb/__init__.py +0 -0
  306. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/cosmosdb/_sdk.py +0 -0
  307. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/cosmosdb/connection_manager.py +0 -0
  308. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/cosmosdb/locking_manager.py +0 -0
  309. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/cosmosdb/schema_operations.py +0 -0
  310. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/introspection/__init__.py +0 -0
  311. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/plugin.py +0 -0
  312. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/quirks.py +0 -0
  313. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/__init__.py +0 -0
  314. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/config.py +0 -0
  315. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/db2/__init__.py +0 -0
  316. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/db2/history_manager.py +0 -0
  317. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/db2/locking_manager.py +0 -0
  318. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/introspection/__init__.py +0 -0
  319. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/parser/__init__.py +0 -0
  320. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/parser/db2_regex_parser.py +0 -0
  321. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/parser/parser_config.py +0 -0
  322. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/plugin.py +0 -0
  323. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/provider.py +0 -0
  324. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/quirks.py +0 -0
  325. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/sqlalchemy_url.py +0 -0
  326. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/duckdb/__init__.py +0 -0
  327. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/duckdb/config.py +0 -0
  328. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/duckdb/parser/__init__.py +0 -0
  329. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/duckdb/parser/duckdb_regex_parser.py +0 -0
  330. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/duckdb/parser/parser_config.py +0 -0
  331. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/duckdb/plugin.py +0 -0
  332. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/duckdb/provider.py +0 -0
  333. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/duckdb/quirks.py +0 -0
  334. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/duckdb/sqlalchemy_url.py +0 -0
  335. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mariadb/__init__.py +0 -0
  336. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mariadb/plugin.py +0 -0
  337. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mariadb/provider.py +0 -0
  338. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/__init__.py +0 -0
  339. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/config.py +0 -0
  340. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/introspection/__init__.py +0 -0
  341. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/mysql/__init__.py +0 -0
  342. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/mysql/history_manager.py +0 -0
  343. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/mysql/locking_manager.py +0 -0
  344. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/mysql/schema_operations.py +0 -0
  345. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/parser/__init__.py +0 -0
  346. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/parser/mysql_regex_parser.py +0 -0
  347. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/parser/mysql_statement_parser.py +0 -0
  348. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/parser/mysql_tokenizer.py +0 -0
  349. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/parser/parser_config.py +0 -0
  350. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/plugin.py +0 -0
  351. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/provider.py +0 -0
  352. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/quirks.py +0 -0
  353. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/sqlalchemy_url.py +0 -0
  354. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/neon/__init__.py +0 -0
  355. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/neon/plugin.py +0 -0
  356. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/nosql_base/__init__.py +0 -0
  357. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/nosql_base/history.py +0 -0
  358. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/nosql_base/introspection.py +0 -0
  359. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/nosql_base/locking.py +0 -0
  360. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/__init__.py +0 -0
  361. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/config.py +0 -0
  362. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/introspection/__init__.py +0 -0
  363. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/introspection/oracle_utils.py +0 -0
  364. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/oracle/__init__.py +0 -0
  365. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/oracle/dbms_output.py +0 -0
  366. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/oracle/history_manager.py +0 -0
  367. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/oracle/locking_manager.py +0 -0
  368. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/oracle/schema_operations.py +0 -0
  369. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/parser/__init__.py +0 -0
  370. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/parser/_comments.py +0 -0
  371. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/parser/_object_extractor.py +0 -0
  372. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/parser/_plsql_block.py +0 -0
  373. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/parser/_sqlplus.py +0 -0
  374. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/parser/_statement_splitter.py +0 -0
  375. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/parser/oracle_parser.py +0 -0
  376. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/parser/oracle_statement_parser.py +0 -0
  377. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/parser/oracle_tokenizer.py +0 -0
  378. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/parser/parser_config.py +0 -0
  379. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/parser/sqlplus_context.py +0 -0
  380. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/plugin.py +0 -0
  381. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/quirks.py +0 -0
  382. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/sqlalchemy_url.py +0 -0
  383. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/__init__.py +0 -0
  384. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/_provider_query_executor.py +0 -0
  385. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/config.py +0 -0
  386. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/introspection/__init__.py +0 -0
  387. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/parser/__init__.py +0 -0
  388. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/parser/parser_config.py +0 -0
  389. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/parser/postgresql_regex_parser.py +0 -0
  390. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/parser/postgresql_statement_parser.py +0 -0
  391. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/parser/postgresql_tokenizer.py +0 -0
  392. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/plugin.py +0 -0
  393. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/postgresql/__init__.py +0 -0
  394. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/postgresql/history_manager.py +0 -0
  395. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/postgresql/locking_manager.py +0 -0
  396. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/postgresql/schema_operations.py +0 -0
  397. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/provider.py +0 -0
  398. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/quirks.py +0 -0
  399. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/sqlalchemy_url.py +0 -0
  400. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/redshift/__init__.py +0 -0
  401. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/redshift/plugin.py +0 -0
  402. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/redshift/provider.py +0 -0
  403. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/redshift/quirks.py +0 -0
  404. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/redshift/sqlalchemy_url.py +0 -0
  405. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/snowflake/__init__.py +0 -0
  406. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/snowflake/config.py +0 -0
  407. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/snowflake/plugin.py +0 -0
  408. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/snowflake/provider.py +0 -0
  409. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/snowflake/quirks.py +0 -0
  410. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/snowflake/sqlalchemy_url.py +0 -0
  411. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/__init__.py +0 -0
  412. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/config.py +0 -0
  413. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/introspection/__init__.py +0 -0
  414. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/parser/__init__.py +0 -0
  415. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/parser/parser_config.py +0 -0
  416. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/parser/sqlite_regex_parser.py +0 -0
  417. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/plugin.py +0 -0
  418. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/provider.py +0 -0
  419. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/quirks.py +0 -0
  420. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/sqlalchemy_url.py +0 -0
  421. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/sqlite/__init__.py +0 -0
  422. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/sqlite/connection_manager.py +0 -0
  423. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/sqlite/history_manager.py +0 -0
  424. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/sqlite/locking_manager.py +0 -0
  425. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/sqlite/query_executor.py +0 -0
  426. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/sqlite/schema_operations.py +0 -0
  427. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/__init__.py +0 -0
  428. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/config.py +0 -0
  429. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/introspection/__init__.py +0 -0
  430. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/parser/__init__.py +0 -0
  431. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/parser/parser_config.py +0 -0
  432. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/parser/sqlserver_regex_parser.py +0 -0
  433. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/parser/sqlserver_statement_parser.py +0 -0
  434. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/parser/sqlserver_tokenizer.py +0 -0
  435. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/parser/tsql_batch_separator.py +0 -0
  436. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/plugin.py +0 -0
  437. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/provider.py +0 -0
  438. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/quirks.py +0 -0
  439. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/sqlalchemy_url.py +0 -0
  440. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/sqlserver/__init__.py +0 -0
  441. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/sqlserver/history_manager.py +0 -0
  442. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/sqlserver/locking_manager.py +0 -0
  443. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/sqlserver/schema_operations.py +0 -0
  444. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/supabase/__init__.py +0 -0
  445. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/supabase/plugin.py +0 -0
  446. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/timescaledb/__init__.py +0 -0
  447. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/timescaledb/plugin.py +0 -0
  448. {dblift-3.3.0 → dblift-3.3.2}/db/plugins/yugabytedb/__init__.py +0 -0
  449. {dblift-3.3.0 → dblift-3.3.2}/db/provider_capabilities.py +0 -0
  450. {dblift-3.3.0 → dblift-3.3.2}/db/provider_interfaces.py +0 -0
  451. {dblift-3.3.0 → dblift-3.3.2}/db/sqlalchemy_provider.py +0 -0
  452. {dblift-3.3.0 → dblift-3.3.2}/db/value_utils.py +0 -0
  453. {dblift-3.3.0 → dblift-3.3.2}/dblift.egg-info/SOURCES.txt +0 -0
  454. {dblift-3.3.0 → dblift-3.3.2}/dblift.egg-info/dependency_links.txt +0 -0
  455. {dblift-3.3.0 → dblift-3.3.2}/dblift.egg-info/entry_points.txt +0 -0
  456. {dblift-3.3.0 → dblift-3.3.2}/dblift.egg-info/requires.txt +0 -0
  457. {dblift-3.3.0 → dblift-3.3.2}/dblift.egg-info/top_level.txt +0 -0
  458. {dblift-3.3.0 → dblift-3.3.2}/integrations/__init__.py +0 -0
  459. {dblift-3.3.0 → dblift-3.3.2}/integrations/django/__init__.py +0 -0
  460. {dblift-3.3.0 → dblift-3.3.2}/integrations/django/_client.py +0 -0
  461. {dblift-3.3.0 → dblift-3.3.2}/integrations/django/_engine.py +0 -0
  462. {dblift-3.3.0 → dblift-3.3.2}/integrations/django/apps.py +0 -0
  463. {dblift-3.3.0 → dblift-3.3.2}/integrations/django/checks.py +0 -0
  464. {dblift-3.3.0 → dblift-3.3.2}/integrations/django/management/__init__.py +0 -0
  465. {dblift-3.3.0 → dblift-3.3.2}/integrations/django/management/commands/__init__.py +0 -0
  466. {dblift-3.3.0 → dblift-3.3.2}/integrations/django/management/commands/dblift_info.py +0 -0
  467. {dblift-3.3.0 → dblift-3.3.2}/integrations/django/management/commands/dblift_migrate.py +0 -0
  468. {dblift-3.3.0 → dblift-3.3.2}/integrations/django/management/commands/dblift_validate.py +0 -0
  469. {dblift-3.3.0 → dblift-3.3.2}/integrations/fastapi.py +0 -0
  470. {dblift-3.3.0 → dblift-3.3.2}/integrations/flask.py +0 -0
  471. {dblift-3.3.0 → dblift-3.3.2}/integrations/opentelemetry.py +0 -0
  472. {dblift-3.3.0 → dblift-3.3.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dblift
3
- Version: 3.3.0
3
+ Version: 3.3.2
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
@@ -5,7 +5,7 @@ import os
5
5
  import pprint
6
6
  import traceback
7
7
  from pathlib import Path
8
- from typing import Any, Dict, List, Optional
8
+ from typing import Any, Dict, List
9
9
 
10
10
  from api._cli_support import (
11
11
  ProviderRegistry,
@@ -14,6 +14,8 @@ from api._cli_support import (
14
14
  from cli._output import CommandOutput, from_args
15
15
  from config.dblift_config import load_config
16
16
  from core.logger import DbliftLogger, LogFormat
17
+ from core.utils.url_masking import mask_database_url
18
+ from db.error import format_connection_error
17
19
 
18
20
 
19
21
  def _to_python(obj: Any) -> Any:
@@ -317,7 +319,7 @@ def check_connection(args: argparse.Namespace) -> int:
317
319
  try:
318
320
  provider.create_connection()
319
321
  except Exception as connection_error:
320
- friendly = _format_connection_error(connection_error)
322
+ friendly = _format_connection_error(connection_error, db_type)
321
323
  out.error(friendly)
322
324
  results["error"] = friendly
323
325
  print_connection_results(results, out)
@@ -332,7 +334,9 @@ def check_connection(args: argparse.Namespace) -> int:
332
334
 
333
335
  # Update results atomically once all operations succeed
334
336
  results["success"] = True
335
- results["connection_info"]["database_url"] = database_url
337
+ results["connection_info"]["database_url"] = (
338
+ mask_database_url(database_url) if database_url else database_url
339
+ )
336
340
  results["connection_info"]["db_type"] = db_type
337
341
  schema = getattr(config.database, "schema", None)
338
342
  if schema:
@@ -353,76 +357,11 @@ def check_connection(args: argparse.Namespace) -> int:
353
357
  return 1
354
358
 
355
359
 
356
- def _format_connection_error(error: Exception) -> str:
357
- """Map common database connection errors to a one-line user-facing message.
358
-
359
- Before falling back to substring matching, consult SQLState when available:
360
- the 5-character code is set by many drivers and is identical across locales.
361
- The substring fallback remains for wrappers and drivers that do not populate
362
- SQLState.
363
-
364
- SQLState references:
365
- 08001 ``sqlclient_unable_to_establish_sqlconnection``
366
- 08006 ``connection_failure``
367
- 08S01 ``communication_link_failure`` (MS / TDS)
368
- 28000 / 28P01 ``invalid_authorization_specification``
369
- 3D000 ``invalid_catalog_name``
370
- 08004 ``sqlserver_rejected_establishment_of_sqlconnection``
371
- """
372
- message = str(error)
373
- lowered = message.lower()
374
- # SQL Server can report login failures with SQLState 08001, so inspect
375
- # explicit auth markers before classifying broad connection SQLStates.
376
- if _looks_like_auth_error(lowered):
377
- return "Connection failed: invalid credentials"
378
-
379
- sqlstate = _extract_sqlstate(error)
380
- if sqlstate in ("08001", "08006", "08S01"):
381
- return "Connection failed: host unreachable or connection timed out"
382
- if sqlstate in ("28000", "28P01"):
383
- return "Connection failed: invalid credentials"
384
- if sqlstate in ("3D000", "08004"):
385
- return "Connection failed: database not found or connection rejected"
386
-
387
- if "refused" in lowered or "timed out" in lowered or "timeout" in lowered:
388
- return "Connection failed: host unreachable"
389
- if _looks_like_auth_error(lowered):
390
- return "Connection failed: invalid credentials"
391
- if "unknown host" in lowered or "name or service not known" in lowered:
392
- return "Connection failed: host not found"
393
- return f"Connection failed: {message}"
394
-
395
-
396
- def _looks_like_auth_error(lowered_message: str) -> bool:
397
- """Return True when an error message clearly describes an auth failure."""
398
- auth_markers = (
399
- "authentication",
400
- "login failed",
401
- "password",
402
- "error 18456",
403
- "18456",
404
- )
405
- return any(marker in lowered_message for marker in auth_markers)
406
-
407
-
408
- def _extract_sqlstate(error: Exception) -> Optional[str]:
409
- """Return the 5-character SQLState of ``error``, or None.
410
-
411
- Some driver exceptions expose ``getSQLState()``. ``sqlstate`` is also
412
- sometimes attached as a plain attribute — check both.
413
- """
414
- get_ss = getattr(error, "getSQLState", None)
415
- if callable(get_ss):
416
- try:
417
- value = get_ss()
418
- except Exception:
419
- value = None
420
- if value:
421
- return str(value).strip() or None
422
- attr = getattr(error, "sqlstate", None) or getattr(error, "SQLState", None)
423
- if attr:
424
- return str(attr).strip() or None
425
- return None
360
+ # Re-exported so ``db check-connection`` and every other command's own
361
+ # connection-establishment step (``BaseCommand._ensure_connected``) format
362
+ # connection failures identically. See ``db.error.format_connection_error``
363
+ # for the SQLState references and auth-classification rationale.
364
+ _format_connection_error = format_connection_error
426
365
 
427
366
 
428
367
  def print_connection_results(results: Dict[str, Any], out: CommandOutput) -> None:
@@ -546,11 +546,25 @@ class BaseCommand:
546
546
  Providers may expose ``_ensure_connection`` (connect-if-closed).
547
547
  Other providers and stubs fall back to ``connect()`` only
548
548
  when ``is_connected()`` reports False, to avoid duplicate connections.
549
+
550
+ A failed connection attempt is re-raised through
551
+ ``db.error.format_connection_error`` — the same formatter
552
+ ``db check-connection`` uses — so every command reports connection
553
+ failures with the identical friendly one-liner instead of a raw
554
+ driver/SQLAlchemy exception.
549
555
  """
550
- if ensure_provider_connection(self.provider):
551
- return
552
- if not self.provider.is_connected():
553
- self.provider.connect()
556
+ try:
557
+ if ensure_provider_connection(self.provider):
558
+ return
559
+ if not self.provider.is_connected():
560
+ self.provider.connect()
561
+ except Exception as exc:
562
+ from db.error import format_connection_error
563
+
564
+ db_type = getattr(self.provider, "canonical_dialect_key", "") or getattr(
565
+ getattr(self.config, "database", None), "type", ""
566
+ )
567
+ raise ConnectionError(format_connection_error(exc, str(db_type or ""))) from exc
554
568
 
555
569
  def _run_preflight(
556
570
  self,
@@ -27,6 +27,19 @@ class BaselineCommand(BaseCommand):
27
27
 
28
28
  try:
29
29
  if dry_run:
30
+ # Don't create the schema/history table as a side effect of dry-run.
31
+ # If it already exists, run the same "history already has rows"
32
+ # precondition the real run would hit, so dry-run can't report
33
+ # false success for a baseline that would actually fail.
34
+ self._ensure_connected()
35
+ if self.history_manager.has_history_table:
36
+ existing = self.history_manager.get_applied_migration_records()
37
+ if existing:
38
+ raise RuntimeError(
39
+ f"Schema {result.target_schema} already contains a migration "
40
+ f"history table with {len(existing)} migration(s). Baseline "
41
+ "cannot be applied to a schema with existing migrations."
42
+ )
30
43
  result.baseline_version = baseline_version
31
44
  result.message = f"Dry run: baseline {baseline_version} would be created"
32
45
  self._log_command_header_update(
@@ -35,7 +48,8 @@ class BaselineCommand(BaseCommand):
35
48
  self._log_command_completion("baseline", result)
36
49
  return result
37
50
 
38
- # Ensure schema and history table exist before baselining (this establishes the connection)
51
+ # Ensure schema and history table exist before baselining (this establishes the
52
+ # connection).
39
53
  self.history_manager.create_schema_and_history_table(create_schema=True)
40
54
 
41
55
  # Log command execution with connection info (after connection is established)
@@ -5,6 +5,7 @@ from typing import Any, Dict, List
5
5
 
6
6
  from core.logger.results import OperationResult
7
7
  from core.migration.commands.base_command import BaseCommand
8
+ from db.object_naming import get_normalized_object_name
8
9
  from db.provider_registry import ProviderRegistry
9
10
 
10
11
 
@@ -30,7 +31,17 @@ class ImportFlywayCommand(BaseCommand):
30
31
  """
31
32
  result = OperationResult()
32
33
  result.target_schema = self.config.database.schema
33
- source_table = (flyway_table or "flyway_schema_history").strip()
34
+ default_source_table = "flyway_schema_history"
35
+ source_table = (flyway_table or default_source_table).strip()
36
+ db_type = str(getattr(self.config.database, "type", "") or "").lower()
37
+ if (
38
+ source_table == default_source_table
39
+ and ProviderRegistry.get_quirks(db_type).flyway_source_table_case_sensitive
40
+ ):
41
+ # No explicit --flyway-table override: normalize the default name to
42
+ # the dialect's unquoted-identifier case so it matches a real Flyway
43
+ # installation's table (e.g. Oracle/DB2 fold unquoted DDL to uppercase).
44
+ source_table = get_normalized_object_name(source_table, db_type)
34
45
  configured_target = getattr(self.config, "history_table", None)
35
46
  target_table = (
36
47
  configured_target.strip()
@@ -38,12 +49,20 @@ class ImportFlywayCommand(BaseCommand):
38
49
  else "dblift_schema_history"
39
50
  )
40
51
 
52
+ # Ensure the provider has a live connection before reading connection
53
+ # metadata or querying the Flyway table — dry-run skips
54
+ # create_schema_and_history_table below, which would otherwise be the
55
+ # only thing establishing the connection for providers that need it.
56
+ self._ensure_connected()
57
+
41
58
  # Populate database connection information
42
59
  self._populate_database_info(result)
43
60
 
44
61
  try:
45
- # Ensure schema and history table exist (this establishes the connection)
46
- self.history_manager.create_schema_and_history_table(create_schema=False)
62
+ # Ensure schema and history table exist. Skipped in dry-run so no
63
+ # table is created as a side effect.
64
+ if not dry_run:
65
+ self.history_manager.create_schema_and_history_table(create_schema=False)
47
66
 
48
67
  # Log command execution with connection info (after connection is established)
49
68
  self._log_command_header_update("import-flyway", dry_run=dry_run)
@@ -41,6 +41,13 @@ def _migration_type_name(migration_type: object) -> str:
41
41
  return str(migration_type or "").upper()
42
42
 
43
43
 
44
+ def _normalize_filter(value: Optional[str]) -> Optional[List[str]]:
45
+ """Split a comma-separated CLI filter value into a clean list."""
46
+ if value is None:
47
+ return None
48
+ return [part.strip() for part in value.split(",") if part.strip()]
49
+
50
+
44
51
  class InfoCommand(BaseCommand):
45
52
  """Handles the 'info' command execution."""
46
53
 
@@ -50,12 +57,21 @@ class InfoCommand(BaseCommand):
50
57
  recursive: bool = True,
51
58
  additional_dirs: Optional[List[Path]] = None,
52
59
  dir_recursive_map: Optional[Dict[Path, bool]] = None,
60
+ tags: Optional[str] = None,
61
+ exclude_tags: Optional[str] = None,
62
+ versions: Optional[str] = None,
63
+ exclude_versions: Optional[str] = None,
53
64
  display_human: bool = True,
54
65
  ) -> InfoResult:
55
66
  """Get information about migrations using migration rules for state determination."""
56
67
  result = InfoResult()
57
68
  result.target_schema = self.config.database.schema
58
69
 
70
+ normalized_tags = _normalize_filter(tags)
71
+ normalized_exclude_tags = _normalize_filter(exclude_tags)
72
+ normalized_versions = _normalize_filter(versions)
73
+ normalized_exclude_versions = _normalize_filter(exclude_versions)
74
+
59
75
  def _body() -> None:
60
76
  # Use MigrationStateManager to get centralized migration state
61
77
  try:
@@ -122,10 +138,10 @@ class InfoCommand(BaseCommand):
122
138
  all_applied_migrations=all_applied_migrations,
123
139
  scripts_dir=scripts_dir,
124
140
  target_version=None,
125
- tags=None,
126
- exclude_tags=None,
127
- versions=None,
128
- exclude_versions=None,
141
+ tags=normalized_tags,
142
+ exclude_tags=normalized_exclude_tags,
143
+ versions=normalized_versions,
144
+ exclude_versions=normalized_exclude_versions,
129
145
  )
130
146
 
131
147
  # Use the same data processing pipeline as the console output
@@ -135,10 +151,10 @@ class InfoCommand(BaseCommand):
135
151
  all_applied_migrations=all_applied_migrations,
136
152
  scripts_dir=scripts_dir,
137
153
  target_version=None,
138
- tags=None,
139
- exclude_tags=None,
140
- versions=None,
141
- exclude_versions=None,
154
+ tags=normalized_tags,
155
+ exclude_tags=normalized_exclude_tags,
156
+ versions=normalized_versions,
157
+ exclude_versions=normalized_exclude_versions,
142
158
  )
143
159
 
144
160
  # Convert the UI data to MigrationInfo objects for the HTML formatter
@@ -580,9 +580,14 @@ class MigrateCommand(BaseCommand):
580
580
  dir_recursive_map: Optional[Dict[Path, bool]],
581
581
  ) -> None:
582
582
  """Update final schema version after migrations are applied."""
583
- # Rebuild state to get accurate applied migrations after migration
583
+ # Rebuild state to get accurate applied migrations after migration.
584
+ # scripts_dir=None so build_state skips pending-migration computation
585
+ # (only applied_objects is needed here) — this run's tag/version
586
+ # exclusion filters aren't available at this point, so recomputing
587
+ # pending here would misreport excluded, never-applied scripts as
588
+ # out-of-order.
584
589
  migration_state_after = self.state_manager.build_state(
585
- scripts_dir,
590
+ None,
586
591
  recursive=use_recursive,
587
592
  additional_dirs=use_additional_dirs,
588
593
  dir_recursive_map=dir_recursive_map,
@@ -36,22 +36,35 @@ class ValidateCommand(BaseCommand):
36
36
  self._populate_database_info(result)
37
37
 
38
38
  try:
39
- # Validate command may not need connection, but try to establish it for header info
39
+ # Ensure the schema history table exists before validating. A
40
+ # failure here (e.g. missing DB privileges) is a real command
41
+ # failure, not something to swallow: validating scripts against
42
+ # a history table that couldn't be created would report success
43
+ # while the schema was left in an unusable state.
40
44
  try:
41
45
  self.history_manager.create_schema_and_history_table(create_schema=False)
42
- # Log command execution with connection info (after connection is established)
43
- self._log_command_header_update(
44
- "validate",
45
- target_version=target_version,
46
- tags=tags,
47
- exclude_tags=exclude_tags,
48
- versions=versions,
49
- exclude_versions=exclude_versions,
50
- )
51
46
  except Exception as e:
52
- # If connection fails, still log without connection info
53
- self.log.debug(f"Could not establish connection for validate header: {e}")
54
- self.log.info("Command: validate")
47
+ from core.migration.sql.sql_execution_service import _format_execution_error
48
+
49
+ try:
50
+ formatted = _format_execution_error(e)
51
+ except Exception:
52
+ formatted = ""
53
+ error_msg = f"Could not create schema history table: {formatted or str(e)}"
54
+ self.log.error(error_msg)
55
+ result.set_error(error_msg)
56
+ self._log_command_completion("validate", result)
57
+ return result
58
+
59
+ # Log command execution with connection info (after connection is established)
60
+ self._log_command_header_update(
61
+ "validate",
62
+ target_version=target_version,
63
+ tags=tags,
64
+ exclude_tags=exclude_tags,
65
+ versions=versions,
66
+ exclude_versions=exclude_versions,
67
+ )
55
68
 
56
69
  validation_result = self.validator.validate_migrations(
57
70
  scripts_dir,
@@ -38,18 +38,33 @@ from db.provider_registry import ProviderRegistry
38
38
  from db.value_utils import to_python_string
39
39
 
40
40
  _DRIVER_EXCEPTION_PREFIX_RE = re.compile(
41
- r"^(?:[a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)+Exception:\s*)+" r"(?:ERROR:\s*)?",
41
+ r"^(?:"
42
+ r"[a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)+Exception:\s*" # Java/JDBC: dotted.path.Exception:
43
+ r"|"
44
+ r"\([a-z_][a-z0-9_]*(?:\.[a-z0-9_]+)+\)\s*" # SQLAlchemy: (dotted.path.ExceptionClass)
45
+ r")+"
46
+ r"(?:ERROR:\s*)?",
42
47
  re.IGNORECASE,
43
48
  )
49
+ # SQLAlchemy appends a doc-link pointer for every wrapped DBAPI error, e.g.
50
+ # '(Background on this error at: https://sqlalche.me/e/20/e3q8)'.
51
+ _SQLALCHEMY_DOC_LINK_RE = re.compile(
52
+ r"\s*\(Background on this error at:.*\)\s*\Z", re.IGNORECASE | re.DOTALL
53
+ )
44
54
 
45
55
 
46
56
  def _strip_driver_exception_prefix(msg: str) -> str:
47
- """Strip verbose driver exception class prefixes from error strings.
57
+ """Strip verbose driver/SQLAlchemy exception wrapping from error strings.
48
58
 
49
59
  e.g. 'org.postgresql.util.PSQLException: ERROR: column "x" already exists'
50
60
  → 'column "x" already exists'
61
+ e.g. '(_duckdb.IOException) IO Error: Cannot open file "x": No such file or directory
62
+ (Background on this error at: https://sqlalche.me/e/20/e3q8)'
63
+ → 'IO Error: Cannot open file "x": No such file or directory'
51
64
  """
52
- return _DRIVER_EXCEPTION_PREFIX_RE.sub("", str(msg)).strip()
65
+ text = _DRIVER_EXCEPTION_PREFIX_RE.sub("", str(msg)).strip()
66
+ text = _SQLALCHEMY_DOC_LINK_RE.sub("", text).strip()
67
+ return text
53
68
 
54
69
 
55
70
  def _is_ddl_statement_for_success_log(statement: str) -> bool:
@@ -360,6 +360,10 @@ class MigrationExecutor:
360
360
  recursive=recursive,
361
361
  additional_dirs=additional_dirs,
362
362
  dir_recursive_map=dir_recursive_map,
363
+ tags=tags,
364
+ exclude_tags=exclude_tags,
365
+ versions=versions,
366
+ exclude_versions=exclude_versions,
363
367
  display_human=display_human,
364
368
  )
365
369
 
@@ -71,9 +71,11 @@ class MigrationContext:
71
71
  context.execute("INSERT INTO t VALUES (1)")
72
72
  context.log.info("Row inserted")
73
73
 
74
- To support undo, add an ``undo`` function with the same signature::
74
+ A ``U<version>__*.py`` undo script also defines a top-level ``migrate``
75
+ function — the same entry point as any other migration — describing the
76
+ action to perform when undoing::
75
77
 
76
- def undo(context: MigrationContext) -> None:
78
+ def migrate(context: MigrationContext) -> None:
77
79
  context.execute("DELETE FROM t WHERE id = 1")
78
80
 
79
81
  Public interface:
@@ -22,8 +22,13 @@ def attach_registered_sql_generators() -> None:
22
22
  """Run every registered SQL generator registrar."""
23
23
  global _bootstrapped
24
24
  if not _bootstrapped and not _registrars:
25
- _bootstrapped = True
26
25
  load_feature_extensions()
26
+ # Latch only if load_feature_extensions() actually populated
27
+ # _registrars -- same latch bug as AlterGeneratorFactory._ensure_populated
28
+ # and feature_loading.load_feature_extensions: an empty result can be
29
+ # the documented race (a paid package's entry point not yet visible),
30
+ # so it must not be latched permanently and must retry on a later call.
31
+ _bootstrapped = bool(_registrars)
27
32
 
28
33
  for registrar in _registrars:
29
34
  try:
@@ -68,15 +68,24 @@ def validate_checksums(
68
68
  result: "ValidationResult",
69
69
  issues: List[str],
70
70
  strict_mode: bool = False,
71
+ all_scripts: Optional[List[Migration]] = None,
71
72
  ) -> None:
72
73
  """Validate checksums of executed migrations.
73
74
 
74
75
  Compares each applied migration's stored checksum against the current
75
76
  file's checksum, flagging drift either as an error (versioned scripts)
76
77
  or a recorded reapply (repeatable scripts).
78
+
79
+ ``scripts`` may be scoped by ``--tags``/``--versions`` filters; ``all_scripts``,
80
+ when provided, is the full unfiltered set of on-disk scripts and is used only to
81
+ decide whether an applied migration is genuinely missing from the migration
82
+ directory (as opposed to merely filtered out of the current run's scope).
77
83
  """
78
84
  checksum_mismatches = []
79
85
  script_names = [s.script_name for s in scripts]
86
+ full_script_names = (
87
+ [s.script_name for s in all_scripts] if all_scripts is not None else script_names
88
+ )
80
89
 
81
90
  for applied in applied_migrations:
82
91
  script_name = getattr(applied, "script_name", None)
@@ -98,7 +107,7 @@ def validate_checksums(
98
107
  if migration_type == MigrationType.BASELINE:
99
108
  continue
100
109
 
101
- if script_name not in script_names:
110
+ if script_name not in full_script_names:
102
111
  if migration_type != MigrationType.BASELINE and str(version_val).lower() != "baseline":
103
112
  # Check if this script has been marked as deleted
104
113
  is_deleted = any(
@@ -144,6 +153,12 @@ def validate_checksums(
144
153
  "marked as deleted - OK"
145
154
  )
146
155
  continue
156
+ if script_name not in script_names:
157
+ # Present on disk but filtered out of scope by --tags/--versions - not missing.
158
+ mv.log.debug(
159
+ f"Migration '{script_name}' is out of scope for this run's filters - skipping"
160
+ )
161
+ continue
147
162
  if migration_type == MigrationType.BASELINE:
148
163
  mv.log.debug(f"Skipping checksum verification for {script_name} (baseline)")
149
164
  continue
@@ -425,6 +425,11 @@ class MigrationValidator:
425
425
  # Handle baseline filtering
426
426
  valid_scripts = self._handle_baseline_filtering(valid_scripts)
427
427
 
428
+ # Full set of on-disk scripts before tag/version scoping, used to tell a
429
+ # genuinely missing migration apart from one merely out of the current
430
+ # --tags/--versions filter scope.
431
+ all_valid_scripts = valid_scripts
432
+
428
433
  valid_scripts = self._apply_filters(
429
434
  valid_scripts,
430
435
  target_version=target_version,
@@ -485,6 +490,7 @@ class MigrationValidator:
485
490
  validation_result,
486
491
  issues,
487
492
  strict_mode,
493
+ all_valid_scripts,
488
494
  )
489
495
  if issues:
490
496
  validation_result.success = False
@@ -593,6 +599,7 @@ class MigrationValidator:
593
599
  validation_result,
594
600
  issues,
595
601
  strict_mode,
602
+ all_valid_scripts,
596
603
  )
597
604
  self.log.debug(
598
605
  f"[DEBUG] validate_migrations: after _validate_checksums: success={validation_result.success}, error='{validation_result.error_message}', issues={issues}"
@@ -744,6 +751,7 @@ class MigrationValidator:
744
751
  result: ValidationResult,
745
752
  issues: List[str],
746
753
  strict_mode: bool = False,
754
+ all_scripts: Optional[List[Migration]] = None,
747
755
  ) -> None:
748
756
  """Delegate to :func:`core.sql_validator._checksum_validator.validate_checksums`.
749
757
 
@@ -752,7 +760,7 @@ class MigrationValidator:
752
760
  """
753
761
  from core.sql_validator._checksum_validator import validate_checksums as _impl
754
762
 
755
- _impl(self, scripts, applied_migrations, result, issues, strict_mode)
763
+ _impl(self, scripts, applied_migrations, result, issues, strict_mode, all_scripts)
756
764
 
757
765
  def _check_repeatable_migrations(
758
766
  self,
@@ -143,6 +143,99 @@ class DatabaseErrorClassifier:
143
143
  return category in _RETRYABLE_CATEGORIES and retry_count < max_retries
144
144
 
145
145
 
146
+ def format_connection_error(error: Exception, db_type: str = "") -> str:
147
+ """Map common database connection errors to a one-line user-facing message.
148
+
149
+ Shared by ``db check-connection`` and every other command's own
150
+ connection-establishment step (see ``BaseCommand._ensure_connected``), so a
151
+ connection failure is reported identically no matter which command
152
+ triggered it.
153
+
154
+ Before falling back to substring matching, consult SQLState when available:
155
+ the 5-character code is set by many drivers and is identical across locales.
156
+ Auth-error detection also consults ``DatabaseErrorClassifier`` (dialect
157
+ quirks ``error_patterns()`` + the generic patterns above), so vendor codes
158
+ such as Oracle's ORA-01017 are recognized without hardcoding vendor-specific
159
+ substrings here. The substring fallback remains for wrappers and drivers
160
+ that do not populate SQLState or match a quirks pattern.
161
+
162
+ SQLState references:
163
+ 08001 ``sqlclient_unable_to_establish_sqlconnection``
164
+ 08006 ``connection_failure``
165
+ 08S01 ``communication_link_failure`` (MS / TDS)
166
+ 28000 / 28P01 ``invalid_authorization_specification``
167
+ 3D000 ``invalid_catalog_name``
168
+ 08004 ``sqlserver_rejected_establishment_of_sqlconnection``
169
+ """
170
+ from core.migration.executor.execution_engine import _strip_driver_exception_prefix
171
+
172
+ message = _strip_driver_exception_prefix(str(error))
173
+ lowered = message.lower()
174
+ # SQL Server can report login failures with SQLState 08001, so inspect
175
+ # explicit auth markers before classifying broad connection SQLStates.
176
+ if _is_auth_error(error, lowered, db_type):
177
+ return "Connection failed: invalid credentials"
178
+
179
+ sqlstate = _extract_sqlstate(error)
180
+ if sqlstate in ("08001", "08006", "08S01"):
181
+ return "Connection failed: host unreachable or connection timed out"
182
+ if sqlstate in ("28000", "28P01"):
183
+ return "Connection failed: invalid credentials"
184
+ if sqlstate in ("3D000", "08004"):
185
+ return "Connection failed: database not found or connection rejected"
186
+
187
+ if "refused" in lowered or "timed out" in lowered or "timeout" in lowered:
188
+ return "Connection failed: host unreachable"
189
+ if "unknown host" in lowered or "name or service not known" in lowered:
190
+ return "Connection failed: host not found"
191
+ return f"Connection failed: {message}"
192
+
193
+
194
+ def _is_auth_error(error: Exception, lowered_message: str, db_type: str) -> bool:
195
+ """Return True when *error* clearly describes an auth failure.
196
+
197
+ Checks cheap substring markers first, then falls back to the dialect's
198
+ quirks-based ``DatabaseErrorClassifier`` so vendor error codes (e.g.
199
+ Oracle's ORA-01017) are recognized generically across every dialect that
200
+ declares ``error_patterns()``, not just the ones with a hardcoded marker
201
+ below.
202
+ """
203
+ auth_markers = (
204
+ "authentication",
205
+ "login failed",
206
+ "password",
207
+ "error 18456",
208
+ "18456",
209
+ )
210
+ if any(marker in lowered_message for marker in auth_markers):
211
+ return True
212
+ try:
213
+ category = DatabaseErrorClassifier(db_type).categorize_error(error)
214
+ except Exception:
215
+ return False
216
+ return category in (ErrorCategory.AUTHENTICATION, ErrorCategory.AUTHORIZATION)
217
+
218
+
219
+ def _extract_sqlstate(error: Exception) -> Optional[str]:
220
+ """Return the 5-character SQLState of *error*, or None.
221
+
222
+ Some driver exceptions expose ``getSQLState()``. ``sqlstate`` is also
223
+ sometimes attached as a plain attribute — check both.
224
+ """
225
+ get_ss = getattr(error, "getSQLState", None)
226
+ if callable(get_ss):
227
+ try:
228
+ value = get_ss()
229
+ except Exception:
230
+ value = None
231
+ if value:
232
+ return str(value).strip() or None
233
+ attr = getattr(error, "sqlstate", None) or getattr(error, "SQLState", None)
234
+ if attr:
235
+ return str(attr).strip() or None
236
+ return None
237
+
238
+
146
239
  class RetryManager:
147
240
  """Executes operations with exponential-backoff retry on transient errors."""
148
241