dblift 3.4.0__tar.gz → 3.4.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 (461) hide show
  1. {dblift-3.4.0 → dblift-3.4.2}/PKG-INFO +1 -1
  2. {dblift-3.4.0 → dblift-3.4.2}/api/_client_operations.py +35 -6
  3. {dblift-3.4.0 → dblift-3.4.2}/api/client.py +93 -35
  4. {dblift-3.4.0 → dblift-3.4.2}/cli/_config_helpers.py +15 -2
  5. {dblift-3.4.0 → dblift-3.4.2}/cli/_parser_setup.py +7 -2
  6. {dblift-3.4.0 → dblift-3.4.2}/cli/db_utils.py +28 -1
  7. {dblift-3.4.0 → dblift-3.4.2}/cli/main.py +71 -3
  8. {dblift-3.4.0 → dblift-3.4.2}/config/dblift_config.py +57 -2
  9. {dblift-3.4.0 → dblift-3.4.2}/core/logger/log.py +10 -0
  10. {dblift-3.4.0 → dblift-3.4.2}/core/migration/commands/base_command.py +35 -11
  11. {dblift-3.4.0 → dblift-3.4.2}/core/migration/commands/baseline_command.py +9 -8
  12. {dblift-3.4.0 → dblift-3.4.2}/core/migration/commands/migrate_command.py +31 -3
  13. {dblift-3.4.0 → dblift-3.4.2}/core/migration/commands/undo_command.py +45 -62
  14. {dblift-3.4.0 → dblift-3.4.2}/core/migration/executor/execution_engine.py +19 -16
  15. {dblift-3.4.0 → dblift-3.4.2}/core/migration/executor/migration_executor.py +6 -1
  16. {dblift-3.4.0 → dblift-3.4.2}/core/migration/executors/executor_factory.py +28 -18
  17. {dblift-3.4.0 → dblift-3.4.2}/core/migration/executors/python_executor.py +14 -0
  18. {dblift-3.4.0 → dblift-3.4.2}/core/migration/scripting/migration_script_manager.py +16 -11
  19. {dblift-3.4.0 → dblift-3.4.2}/core/migration/scripting/undo_script_generator/_generator.py +5 -1
  20. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/table.py +22 -4
  21. {dblift-3.4.0 → dblift-3.4.2}/core/sql_validator/migration_validator.py +50 -2
  22. {dblift-3.4.0 → dblift-3.4.2}/db/error.py +8 -0
  23. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/cosmosdb/quirks.py +5 -1
  24. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/db2/quirks.py +29 -0
  25. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/duckdb/quirks.py +2 -0
  26. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/mysql/parser/parser_config.py +11 -4
  27. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/mysql/quirks.py +3 -0
  28. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/parser/_sqlplus.py +8 -1
  29. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/quirks.py +3 -0
  30. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/postgresql/provider.py +44 -7
  31. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/postgresql/quirks.py +4 -0
  32. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlite/quirks.py +2 -0
  33. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlserver/provider.py +84 -6
  34. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlserver/quirks.py +2 -0
  35. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlserver/sqlserver/schema_operations.py +72 -9
  36. {dblift-3.4.0 → dblift-3.4.2}/db/sqlalchemy_provider.py +115 -59
  37. {dblift-3.4.0 → dblift-3.4.2}/dblift.egg-info/PKG-INFO +1 -1
  38. {dblift-3.4.0 → dblift-3.4.2}/integrations/opentelemetry.py +28 -2
  39. {dblift-3.4.0 → dblift-3.4.2}/pyproject.toml +1 -1
  40. {dblift-3.4.0 → dblift-3.4.2}/LICENSE +0 -0
  41. {dblift-3.4.0 → dblift-3.4.2}/README.md +0 -0
  42. {dblift-3.4.0 → dblift-3.4.2}/api/__init__.py +0 -0
  43. {dblift-3.4.0 → dblift-3.4.2}/api/_cli_support.py +0 -0
  44. {dblift-3.4.0 → dblift-3.4.2}/api/_client_factory.py +0 -0
  45. {dblift-3.4.0 → dblift-3.4.2}/api/_engine_config.py +0 -0
  46. {dblift-3.4.0 → dblift-3.4.2}/api/async_client.py +0 -0
  47. {dblift-3.4.0 → dblift-3.4.2}/api/events.py +0 -0
  48. {dblift-3.4.0 → dblift-3.4.2}/api/migrations.py +0 -0
  49. {dblift-3.4.0 → dblift-3.4.2}/api/py.typed +0 -0
  50. {dblift-3.4.0 → dblift-3.4.2}/cli/__init__.py +0 -0
  51. {dblift-3.4.0 → dblift-3.4.2}/cli/_command_handlers.py +0 -0
  52. {dblift-3.4.0 → dblift-3.4.2}/cli/_constants.py +0 -0
  53. {dblift-3.4.0 → dblift-3.4.2}/cli/_output.py +0 -0
  54. {dblift-3.4.0 → dblift-3.4.2}/cli/commands/__init__.py +0 -0
  55. {dblift-3.4.0 → dblift-3.4.2}/cli/commands/config_command.py +0 -0
  56. {dblift-3.4.0 → dblift-3.4.2}/cli/extensions.py +0 -0
  57. {dblift-3.4.0 → dblift-3.4.2}/cli/handlers/__init__.py +0 -0
  58. {dblift-3.4.0 → dblift-3.4.2}/cli/handlers/_shared.py +0 -0
  59. {dblift-3.4.0 → dblift-3.4.2}/cli/handlers/baseline.py +0 -0
  60. {dblift-3.4.0 → dblift-3.4.2}/cli/handlers/clean.py +0 -0
  61. {dblift-3.4.0 → dblift-3.4.2}/cli/handlers/import_flyway.py +0 -0
  62. {dblift-3.4.0 → dblift-3.4.2}/cli/handlers/info.py +0 -0
  63. {dblift-3.4.0 → dblift-3.4.2}/cli/handlers/migrate.py +0 -0
  64. {dblift-3.4.0 → dblift-3.4.2}/cli/handlers/repair.py +0 -0
  65. {dblift-3.4.0 → dblift-3.4.2}/cli/handlers/undo.py +0 -0
  66. {dblift-3.4.0 → dblift-3.4.2}/cli/handlers/validate.py +0 -0
  67. {dblift-3.4.0 → dblift-3.4.2}/cli/premium_manifest.py +0 -0
  68. {dblift-3.4.0 → dblift-3.4.2}/config/__init__.py +0 -0
  69. {dblift-3.4.0 → dblift-3.4.2}/config/_credential_masking.py +0 -0
  70. {dblift-3.4.0 → dblift-3.4.2}/config/_subclasses/__init__.py +0 -0
  71. {dblift-3.4.0 → dblift-3.4.2}/config/_subclasses/dummy_config.py +0 -0
  72. {dblift-3.4.0 → dblift-3.4.2}/config/_url_builder_mixin.py +0 -0
  73. {dblift-3.4.0 → dblift-3.4.2}/config/config_builder.py +0 -0
  74. {dblift-3.4.0 → dblift-3.4.2}/config/database_config.py +0 -0
  75. {dblift-3.4.0 → dblift-3.4.2}/config/errors.py +0 -0
  76. {dblift-3.4.0 → dblift-3.4.2}/config/property_registry.py +0 -0
  77. {dblift-3.4.0 → dblift-3.4.2}/config/secrets/__init__.py +0 -0
  78. {dblift-3.4.0 → dblift-3.4.2}/config/secrets/_cache.py +0 -0
  79. {dblift-3.4.0 → dblift-3.4.2}/config/secrets/_provider_base.py +0 -0
  80. {dblift-3.4.0 → dblift-3.4.2}/config/secrets/_registry.py +0 -0
  81. {dblift-3.4.0 → dblift-3.4.2}/config/secrets/_resolver.py +0 -0
  82. {dblift-3.4.0 → dblift-3.4.2}/config/secrets/_secrets_config.py +0 -0
  83. {dblift-3.4.0 → dblift-3.4.2}/core/__init__.py +0 -0
  84. {dblift-3.4.0 → dblift-3.4.2}/core/constants.py +0 -0
  85. {dblift-3.4.0 → dblift-3.4.2}/core/dialect_boundary.py +0 -0
  86. {dblift-3.4.0 → dblift-3.4.2}/core/exceptions.py +0 -0
  87. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/__init__.py +0 -0
  88. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/_column_enricher.py +0 -0
  89. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/_partition_enricher.py +0 -0
  90. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/_schema_orchestrator.py +0 -0
  91. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/_utils.py +0 -0
  92. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/_vendor_property_applier.py +0 -0
  93. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/base_introspector.py +0 -0
  94. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/extractors/__init__.py +0 -0
  95. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/extractors/base_extractor.py +0 -0
  96. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/extractors/column_extractor.py +0 -0
  97. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/extractors/constraint_extractor.py +0 -0
  98. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/extractors/index_extractor.py +0 -0
  99. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/extractors/misc_extractor.py +0 -0
  100. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/extractors/procedure_extractor.py +0 -0
  101. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/extractors/sequence_extractor.py +0 -0
  102. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/extractors/table_extractor.py +0 -0
  103. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/extractors/trigger_extractor.py +0 -0
  104. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/extractors/view_extractor.py +0 -0
  105. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/introspector_factory.py +0 -0
  106. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/result.py +0 -0
  107. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/schema_introspector.py +0 -0
  108. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/vendor_queries_base.py +0 -0
  109. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/vendor_queries_factory.py +0 -0
  110. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/vendor_queries_protocols.py +0 -0
  111. {dblift-3.4.0 → dblift-3.4.2}/core/introspection/version_detector.py +0 -0
  112. {dblift-3.4.0 → dblift-3.4.2}/core/logger/__init__.py +0 -0
  113. {dblift-3.4.0 → dblift-3.4.2}/core/logger/_base.py +0 -0
  114. {dblift-3.4.0 → dblift-3.4.2}/core/logger/_factory.py +0 -0
  115. {dblift-3.4.0 → dblift-3.4.2}/core/logger/_formatters.py +0 -0
  116. {dblift-3.4.0 → dblift-3.4.2}/core/logger/_levels.py +0 -0
  117. {dblift-3.4.0 → dblift-3.4.2}/core/logger/_multi.py +0 -0
  118. {dblift-3.4.0 → dblift-3.4.2}/core/logger/_null.py +0 -0
  119. {dblift-3.4.0 → dblift-3.4.2}/core/logger/console.py +0 -0
  120. {dblift-3.4.0 → dblift-3.4.2}/core/logger/formatters/__init__.py +0 -0
  121. {dblift-3.4.0 → dblift-3.4.2}/core/logger/formatters/_formatter_impl.py +0 -0
  122. {dblift-3.4.0 → dblift-3.4.2}/core/logger/formatters/factory.py +0 -0
  123. {dblift-3.4.0 → dblift-3.4.2}/core/logger/formatters/formatter.py +0 -0
  124. {dblift-3.4.0 → dblift-3.4.2}/core/logger/formatters/htmlformatter.py +0 -0
  125. {dblift-3.4.0 → dblift-3.4.2}/core/logger/formatters/jsonformatter.py +0 -0
  126. {dblift-3.4.0 → dblift-3.4.2}/core/logger/results.py +0 -0
  127. {dblift-3.4.0 → dblift-3.4.2}/core/logger/templates/oldreport.html +0 -0
  128. {dblift-3.4.0 → dblift-3.4.2}/core/logger/templates/report.html +0 -0
  129. {dblift-3.4.0 → dblift-3.4.2}/core/migration/__init__.py +0 -0
  130. {dblift-3.4.0 → dblift-3.4.2}/core/migration/_type_match.py +0 -0
  131. {dblift-3.4.0 → dblift-3.4.2}/core/migration/clean_summary.py +0 -0
  132. {dblift-3.4.0 → dblift-3.4.2}/core/migration/commands/__init__.py +0 -0
  133. {dblift-3.4.0 → dblift-3.4.2}/core/migration/commands/_script_events.py +0 -0
  134. {dblift-3.4.0 → dblift-3.4.2}/core/migration/commands/clean_command.py +0 -0
  135. {dblift-3.4.0 → dblift-3.4.2}/core/migration/commands/import_flyway_command.py +0 -0
  136. {dblift-3.4.0 → dblift-3.4.2}/core/migration/commands/info_command.py +0 -0
  137. {dblift-3.4.0 → dblift-3.4.2}/core/migration/commands/repair_command.py +0 -0
  138. {dblift-3.4.0 → dblift-3.4.2}/core/migration/commands/validate_command.py +0 -0
  139. {dblift-3.4.0 → dblift-3.4.2}/core/migration/encoding.py +0 -0
  140. {dblift-3.4.0 → dblift-3.4.2}/core/migration/executor/__init__.py +0 -0
  141. {dblift-3.4.0 → dblift-3.4.2}/core/migration/executor/migration_helpers.py +0 -0
  142. {dblift-3.4.0 → dblift-3.4.2}/core/migration/executor/placeholder_manager.py +0 -0
  143. {dblift-3.4.0 → dblift-3.4.2}/core/migration/executor/transaction_policy.py +0 -0
  144. {dblift-3.4.0 → dblift-3.4.2}/core/migration/executors/__init__.py +0 -0
  145. {dblift-3.4.0 → dblift-3.4.2}/core/migration/executors/base_executor.py +0 -0
  146. {dblift-3.4.0 → dblift-3.4.2}/core/migration/executors/sql_executor.py +0 -0
  147. {dblift-3.4.0 → dblift-3.4.2}/core/migration/formats/__init__.py +0 -0
  148. {dblift-3.4.0 → dblift-3.4.2}/core/migration/formats/format_detector.py +0 -0
  149. {dblift-3.4.0 → dblift-3.4.2}/core/migration/formats/migration_format.py +0 -0
  150. {dblift-3.4.0 → dblift-3.4.2}/core/migration/history/__init__.py +0 -0
  151. {dblift-3.4.0 → dblift-3.4.2}/core/migration/history/migration_history_manager.py +0 -0
  152. {dblift-3.4.0 → dblift-3.4.2}/core/migration/journals/__init__.py +0 -0
  153. {dblift-3.4.0 → dblift-3.4.2}/core/migration/journals/migration_journal.py +0 -0
  154. {dblift-3.4.0 → dblift-3.4.2}/core/migration/migration.py +0 -0
  155. {dblift-3.4.0 → dblift-3.4.2}/core/migration/placeholders/__init__.py +0 -0
  156. {dblift-3.4.0 → dblift-3.4.2}/core/migration/placeholders/placeholder_service.py +0 -0
  157. {dblift-3.4.0 → dblift-3.4.2}/core/migration/rules/__init__.py +0 -0
  158. {dblift-3.4.0 → dblift-3.4.2}/core/migration/rules/migration_rules.py +0 -0
  159. {dblift-3.4.0 → dblift-3.4.2}/core/migration/scripting/__init__.py +0 -0
  160. {dblift-3.4.0 → dblift-3.4.2}/core/migration/scripting/undo_script_generator/__init__.py +0 -0
  161. {dblift-3.4.0 → dblift-3.4.2}/core/migration/scripting/undo_script_generator/_extractors.py +0 -0
  162. {dblift-3.4.0 → dblift-3.4.2}/core/migration/scripting/undo_script_generator/_helpers.py +0 -0
  163. {dblift-3.4.0 → dblift-3.4.2}/core/migration/scripting/undo_script_generator/_models.py +0 -0
  164. {dblift-3.4.0 → dblift-3.4.2}/core/migration/scripting/undo_script_generator/_reversers.py +0 -0
  165. {dblift-3.4.0 → dblift-3.4.2}/core/migration/sql/__init__.py +0 -0
  166. {dblift-3.4.0 → dblift-3.4.2}/core/migration/sql/execution_statement.py +0 -0
  167. {dblift-3.4.0 → dblift-3.4.2}/core/migration/sql/sql_analyzer.py +0 -0
  168. {dblift-3.4.0 → dblift-3.4.2}/core/migration/sql/sql_execution_service.py +0 -0
  169. {dblift-3.4.0 → dblift-3.4.2}/core/migration/sql/statement_splitter.py +0 -0
  170. {dblift-3.4.0 → dblift-3.4.2}/core/migration/state/__init__.py +0 -0
  171. {dblift-3.4.0 → dblift-3.4.2}/core/migration/state/migration_data_service.py +0 -0
  172. {dblift-3.4.0 → dblift-3.4.2}/core/migration/state/migration_display_state.py +0 -0
  173. {dblift-3.4.0 → dblift-3.4.2}/core/migration/state/migration_state.py +0 -0
  174. {dblift-3.4.0 → dblift-3.4.2}/core/migration/state/migration_state_manager.py +0 -0
  175. {dblift-3.4.0 → dblift-3.4.2}/core/migration/state/migration_state_service.py +0 -0
  176. {dblift-3.4.0 → dblift-3.4.2}/core/migration/ui/__init__.py +0 -0
  177. {dblift-3.4.0 → dblift-3.4.2}/core/migration/ui/data_collector.py +0 -0
  178. {dblift-3.4.0 → dblift-3.4.2}/core/migration/ui/migration_ui.py +0 -0
  179. {dblift-3.4.0 → dblift-3.4.2}/core/migration/ui/table_renderer.py +0 -0
  180. {dblift-3.4.0 → dblift-3.4.2}/core/migration/version_utils.py +0 -0
  181. {dblift-3.4.0 → dblift-3.4.2}/core/normalization/__init__.py +0 -0
  182. {dblift-3.4.0 → dblift-3.4.2}/core/normalization/type_constants.py +0 -0
  183. {dblift-3.4.0 → dblift-3.4.2}/core/normalization/type_normalizer.py +0 -0
  184. {dblift-3.4.0 → dblift-3.4.2}/core/premium_manifest.py +0 -0
  185. {dblift-3.4.0 → dblift-3.4.2}/core/seams/__init__.py +0 -0
  186. {dblift-3.4.0 → dblift-3.4.2}/core/seams/capabilities.py +0 -0
  187. {dblift-3.4.0 → dblift-3.4.2}/core/seams/client_factory.py +0 -0
  188. {dblift-3.4.0 → dblift-3.4.2}/core/seams/event_listeners.py +0 -0
  189. {dblift-3.4.0 → dblift-3.4.2}/core/seams/feature_loading.py +0 -0
  190. {dblift-3.4.0 → dblift-3.4.2}/core/seams/introspection.py +0 -0
  191. {dblift-3.4.0 → dblift-3.4.2}/core/seams/license_info.py +0 -0
  192. {dblift-3.4.0 → dblift-3.4.2}/core/seams/runtime_checks.py +0 -0
  193. {dblift-3.4.0 → dblift-3.4.2}/core/seams/sql_generators.py +0 -0
  194. {dblift-3.4.0 → dblift-3.4.2}/core/seams/tier_resolver.py +0 -0
  195. {dblift-3.4.0 → dblift-3.4.2}/core/sql_generator/__init__.py +0 -0
  196. {dblift-3.4.0 → dblift-3.4.2}/core/sql_generator/alter/__init__.py +0 -0
  197. {dblift-3.4.0 → dblift-3.4.2}/core/sql_generator/alter/alter_generator_factory.py +0 -0
  198. {dblift-3.4.0 → dblift-3.4.2}/core/sql_generator/alter/base_alter_generator.py +0 -0
  199. {dblift-3.4.0 → dblift-3.4.2}/core/sql_generator/base_generator.py +0 -0
  200. {dblift-3.4.0 → dblift-3.4.2}/core/sql_generator/basic_table_ddl_generator.py +0 -0
  201. {dblift-3.4.0 → dblift-3.4.2}/core/sql_generator/dependency_analyzer.py +0 -0
  202. {dblift-3.4.0 → dblift-3.4.2}/core/sql_generator/diff_converters/__init__.py +0 -0
  203. {dblift-3.4.0 → dblift-3.4.2}/core/sql_generator/diff_converters/base_converter.py +0 -0
  204. {dblift-3.4.0 → dblift-3.4.2}/core/sql_generator/formatter.py +0 -0
  205. {dblift-3.4.0 → dblift-3.4.2}/core/sql_generator/generator_factory.py +0 -0
  206. {dblift-3.4.0 → dblift-3.4.2}/core/sql_generator/options.py +0 -0
  207. {dblift-3.4.0 → dblift-3.4.2}/core/sql_generator/script_organizer.py +0 -0
  208. {dblift-3.4.0 → dblift-3.4.2}/core/sql_generator/sql_generator.py +0 -0
  209. {dblift-3.4.0 → dblift-3.4.2}/core/sql_generator/sql_statement.py +0 -0
  210. {dblift-3.4.0 → dblift-3.4.2}/core/sql_generator/table_ddl_render.py +0 -0
  211. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/__init__.py +0 -0
  212. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/_base_parse_result.py +0 -0
  213. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/_base_sql_column.py +0 -0
  214. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/_base_sql_constraint.py +0 -0
  215. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/_base_sql_object.py +0 -0
  216. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/_base_sql_statement.py +0 -0
  217. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/base.py +0 -0
  218. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/constraint_validator.py +0 -0
  219. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/database_link.py +0 -0
  220. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/dialect.py +0 -0
  221. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/event.py +0 -0
  222. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/extension.py +0 -0
  223. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/feature_gates.py +0 -0
  224. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/foreign_data_wrapper.py +0 -0
  225. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/foreign_server.py +0 -0
  226. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/index.py +0 -0
  227. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/linked_server.py +0 -0
  228. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/module.py +0 -0
  229. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/package.py +0 -0
  230. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/partition.py +0 -0
  231. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/procedure.py +0 -0
  232. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/sequence.py +0 -0
  233. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/server_info.py +0 -0
  234. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/synonym.py +0 -0
  235. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/table_canonicalizer.py +0 -0
  236. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/table_options.py +0 -0
  237. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/trigger.py +0 -0
  238. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/user_defined_type.py +0 -0
  239. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/view.py +0 -0
  240. {dblift-3.4.0 → dblift-3.4.2}/core/sql_model/view_options.py +0 -0
  241. {dblift-3.4.0 → dblift-3.4.2}/core/sql_parser/__init__.py +0 -0
  242. {dblift-3.4.0 → dblift-3.4.2}/core/sql_parser/_partition_handler.py +0 -0
  243. {dblift-3.4.0 → dblift-3.4.2}/core/sql_parser/_sqlglot_builders.py +0 -0
  244. {dblift-3.4.0 → dblift-3.4.2}/core/sql_parser/base_statement_parser.py +0 -0
  245. {dblift-3.4.0 → dblift-3.4.2}/core/sql_parser/base_tokenizer.py +0 -0
  246. {dblift-3.4.0 → dblift-3.4.2}/core/sql_parser/common/__init__.py +0 -0
  247. {dblift-3.4.0 → dblift-3.4.2}/core/sql_parser/common/base_parser.py +0 -0
  248. {dblift-3.4.0 → dblift-3.4.2}/core/sql_parser/dialects/__init__.py +0 -0
  249. {dblift-3.4.0 → dblift-3.4.2}/core/sql_parser/dialects/base_config.py +0 -0
  250. {dblift-3.4.0 → dblift-3.4.2}/core/sql_parser/enhanced_regex_parser.py +0 -0
  251. {dblift-3.4.0 → dblift-3.4.2}/core/sql_parser/hybrid_parser.py +0 -0
  252. {dblift-3.4.0 → dblift-3.4.2}/core/sql_parser/parser_context.py +0 -0
  253. {dblift-3.4.0 → dblift-3.4.2}/core/sql_parser/parser_factory.py +0 -0
  254. {dblift-3.4.0 → dblift-3.4.2}/core/sql_parser/parser_interface.py +0 -0
  255. {dblift-3.4.0 → dblift-3.4.2}/core/sql_parser/sqlglot_parser.py +0 -0
  256. {dblift-3.4.0 → dblift-3.4.2}/core/sql_parser/tokens.py +0 -0
  257. {dblift-3.4.0 → dblift-3.4.2}/core/sql_parser/unified_regex_parser.py +0 -0
  258. {dblift-3.4.0 → dblift-3.4.2}/core/sql_validator/__init__.py +0 -0
  259. {dblift-3.4.0 → dblift-3.4.2}/core/sql_validator/_checksum_validator.py +0 -0
  260. {dblift-3.4.0 → dblift-3.4.2}/core/sql_validator/_flyway_compatibility.py +0 -0
  261. {dblift-3.4.0 → dblift-3.4.2}/core/sql_validator/_migration_filter.py +0 -0
  262. {dblift-3.4.0 → dblift-3.4.2}/core/sql_validator/_sql_syntax_validator.py +0 -0
  263. {dblift-3.4.0 → dblift-3.4.2}/core/sql_validator/_strict_mode_validator.py +0 -0
  264. {dblift-3.4.0 → dblift-3.4.2}/core/state/sql_statement.py +0 -0
  265. {dblift-3.4.0 → dblift-3.4.2}/core/utils/__init__.py +0 -0
  266. {dblift-3.4.0 → dblift-3.4.2}/core/utils/database_url_parser.py +0 -0
  267. {dblift-3.4.0 → dblift-3.4.2}/core/utils/metadata_helpers.py +0 -0
  268. {dblift-3.4.0 → dblift-3.4.2}/core/utils/row_access.py +0 -0
  269. {dblift-3.4.0 → dblift-3.4.2}/core/utils/string_utils.py +0 -0
  270. {dblift-3.4.0 → dblift-3.4.2}/core/utils/url_masking.py +0 -0
  271. {dblift-3.4.0 → dblift-3.4.2}/db/__init__.py +0 -0
  272. {dblift-3.4.0 → dblift-3.4.2}/db/base_provider.py +0 -0
  273. {dblift-3.4.0 → dblift-3.4.2}/db/base_quirks.py +0 -0
  274. {dblift-3.4.0 → dblift-3.4.2}/db/constants.py +0 -0
  275. {dblift-3.4.0 → dblift-3.4.2}/db/dml_analysis.py +0 -0
  276. {dblift-3.4.0 → dblift-3.4.2}/db/exceptions.py +0 -0
  277. {dblift-3.4.0 → dblift-3.4.2}/db/feature_gate.py +0 -0
  278. {dblift-3.4.0 → dblift-3.4.2}/db/native_connection_manager.py +0 -0
  279. {dblift-3.4.0 → dblift-3.4.2}/db/object_naming.py +0 -0
  280. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/__init__.py +0 -0
  281. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/_pg_compatible.py +0 -0
  282. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/alloydb/__init__.py +0 -0
  283. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/alloydb/plugin.py +0 -0
  284. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/aurora_postgresql/__init__.py +0 -0
  285. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/aurora_postgresql/plugin.py +0 -0
  286. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/base_history_manager.py +0 -0
  287. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/base_locking_manager.py +0 -0
  288. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/base_query_executor.py +0 -0
  289. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/base_schema_operations.py +0 -0
  290. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/base_snapshot_manager.py +0 -0
  291. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/citus/__init__.py +0 -0
  292. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/citus/plugin.py +0 -0
  293. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/cockroachdb/__init__.py +0 -0
  294. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/cockroachdb/plugin.py +0 -0
  295. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/cockroachdb/provider.py +0 -0
  296. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/cockroachdb/quirks.py +0 -0
  297. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/cockroachdb/sqlalchemy_dialect.py +0 -0
  298. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/cockroachdb/sqlalchemy_url.py +0 -0
  299. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/cosmosdb/__init__.py +0 -0
  300. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/cosmosdb/config.py +0 -0
  301. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/cosmosdb/cosmosdb/__init__.py +0 -0
  302. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/cosmosdb/cosmosdb/_sdk.py +0 -0
  303. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/cosmosdb/cosmosdb/connection_manager.py +0 -0
  304. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/cosmosdb/cosmosdb/history_manager.py +0 -0
  305. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/cosmosdb/cosmosdb/locking_manager.py +0 -0
  306. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/cosmosdb/cosmosdb/query_executor.py +0 -0
  307. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/cosmosdb/cosmosdb/schema_operations.py +0 -0
  308. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/cosmosdb/introspection/__init__.py +0 -0
  309. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/cosmosdb/plugin.py +0 -0
  310. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/cosmosdb/provider.py +0 -0
  311. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/db2/__init__.py +0 -0
  312. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/db2/config.py +0 -0
  313. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/db2/db2/__init__.py +0 -0
  314. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/db2/db2/history_manager.py +0 -0
  315. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/db2/db2/locking_manager.py +0 -0
  316. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/db2/db2/schema_operations.py +0 -0
  317. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/db2/introspection/__init__.py +0 -0
  318. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/db2/parser/__init__.py +0 -0
  319. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/db2/parser/db2_regex_parser.py +0 -0
  320. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/db2/parser/parser_config.py +0 -0
  321. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/db2/plugin.py +0 -0
  322. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/db2/provider.py +0 -0
  323. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/db2/sqlalchemy_url.py +0 -0
  324. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/duckdb/__init__.py +0 -0
  325. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/duckdb/config.py +0 -0
  326. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/duckdb/parser/__init__.py +0 -0
  327. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/duckdb/parser/duckdb_regex_parser.py +0 -0
  328. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/duckdb/parser/parser_config.py +0 -0
  329. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/duckdb/plugin.py +0 -0
  330. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/duckdb/provider.py +0 -0
  331. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/duckdb/sqlalchemy_url.py +0 -0
  332. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/mariadb/__init__.py +0 -0
  333. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/mariadb/plugin.py +0 -0
  334. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/mariadb/provider.py +0 -0
  335. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/mariadb/quirks.py +0 -0
  336. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/mysql/__init__.py +0 -0
  337. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/mysql/config.py +0 -0
  338. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/mysql/introspection/__init__.py +0 -0
  339. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/mysql/mysql/__init__.py +0 -0
  340. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/mysql/mysql/history_manager.py +0 -0
  341. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/mysql/mysql/locking_manager.py +0 -0
  342. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/mysql/mysql/schema_operations.py +0 -0
  343. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/mysql/parser/__init__.py +0 -0
  344. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/mysql/parser/mysql_regex_parser.py +0 -0
  345. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/mysql/parser/mysql_statement_parser.py +0 -0
  346. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/mysql/parser/mysql_tokenizer.py +0 -0
  347. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/mysql/plugin.py +0 -0
  348. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/mysql/provider.py +0 -0
  349. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/mysql/sqlalchemy_url.py +0 -0
  350. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/neon/__init__.py +0 -0
  351. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/neon/plugin.py +0 -0
  352. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/nosql_base/__init__.py +0 -0
  353. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/nosql_base/history.py +0 -0
  354. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/nosql_base/introspection.py +0 -0
  355. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/nosql_base/locking.py +0 -0
  356. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/__init__.py +0 -0
  357. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/config.py +0 -0
  358. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/introspection/__init__.py +0 -0
  359. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/introspection/oracle_utils.py +0 -0
  360. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/oracle/__init__.py +0 -0
  361. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/oracle/dbms_output.py +0 -0
  362. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/oracle/history_manager.py +0 -0
  363. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/oracle/locking_manager.py +0 -0
  364. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/oracle/schema_operations.py +0 -0
  365. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/parser/__init__.py +0 -0
  366. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/parser/_comments.py +0 -0
  367. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/parser/_object_extractor.py +0 -0
  368. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/parser/_plsql_block.py +0 -0
  369. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/parser/_statement_splitter.py +0 -0
  370. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/parser/oracle_parser.py +0 -0
  371. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/parser/oracle_statement_parser.py +0 -0
  372. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/parser/oracle_tokenizer.py +0 -0
  373. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/parser/sqlplus_context.py +0 -0
  374. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/plugin.py +0 -0
  375. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/provider.py +0 -0
  376. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/oracle/sqlalchemy_url.py +0 -0
  377. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/postgresql/__init__.py +0 -0
  378. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/postgresql/_provider_query_executor.py +0 -0
  379. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/postgresql/config.py +0 -0
  380. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/postgresql/introspection/__init__.py +0 -0
  381. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/postgresql/parser/__init__.py +0 -0
  382. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/postgresql/parser/parser_config.py +0 -0
  383. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/postgresql/parser/postgresql_regex_parser.py +0 -0
  384. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/postgresql/parser/postgresql_statement_parser.py +0 -0
  385. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/postgresql/parser/postgresql_tokenizer.py +0 -0
  386. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/postgresql/plugin.py +0 -0
  387. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/postgresql/postgresql/__init__.py +0 -0
  388. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/postgresql/postgresql/history_manager.py +0 -0
  389. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/postgresql/postgresql/locking_manager.py +0 -0
  390. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/postgresql/postgresql/schema_operations.py +0 -0
  391. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/postgresql/search_path.py +0 -0
  392. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/postgresql/sqlalchemy_url.py +0 -0
  393. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/redshift/__init__.py +0 -0
  394. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/redshift/plugin.py +0 -0
  395. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/redshift/provider.py +0 -0
  396. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/redshift/quirks.py +0 -0
  397. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/redshift/sqlalchemy_url.py +0 -0
  398. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/snowflake/__init__.py +0 -0
  399. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/snowflake/config.py +0 -0
  400. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/snowflake/plugin.py +0 -0
  401. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/snowflake/provider.py +0 -0
  402. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/snowflake/quirks.py +0 -0
  403. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/snowflake/sqlalchemy_url.py +0 -0
  404. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlite/__init__.py +0 -0
  405. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlite/config.py +0 -0
  406. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlite/introspection/__init__.py +0 -0
  407. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlite/parser/__init__.py +0 -0
  408. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlite/parser/parser_config.py +0 -0
  409. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlite/parser/sqlite_regex_parser.py +0 -0
  410. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlite/plugin.py +0 -0
  411. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlite/provider.py +0 -0
  412. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlite/sqlalchemy_url.py +0 -0
  413. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlite/sqlite/__init__.py +0 -0
  414. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlite/sqlite/connection_manager.py +0 -0
  415. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlite/sqlite/history_manager.py +0 -0
  416. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlite/sqlite/locking_manager.py +0 -0
  417. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlite/sqlite/query_executor.py +0 -0
  418. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlite/sqlite/schema_operations.py +0 -0
  419. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlserver/__init__.py +0 -0
  420. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlserver/config.py +0 -0
  421. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlserver/introspection/__init__.py +0 -0
  422. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlserver/parser/__init__.py +0 -0
  423. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlserver/parser/parser_config.py +0 -0
  424. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlserver/parser/sqlserver_regex_parser.py +0 -0
  425. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlserver/parser/sqlserver_statement_parser.py +0 -0
  426. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlserver/parser/sqlserver_tokenizer.py +0 -0
  427. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlserver/parser/tsql_batch_separator.py +0 -0
  428. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlserver/plugin.py +0 -0
  429. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlserver/sqlalchemy_url.py +0 -0
  430. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlserver/sqlserver/__init__.py +0 -0
  431. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlserver/sqlserver/history_manager.py +0 -0
  432. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/sqlserver/sqlserver/locking_manager.py +0 -0
  433. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/supabase/__init__.py +0 -0
  434. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/supabase/plugin.py +0 -0
  435. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/timescaledb/__init__.py +0 -0
  436. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/timescaledb/plugin.py +0 -0
  437. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/yugabytedb/__init__.py +0 -0
  438. {dblift-3.4.0 → dblift-3.4.2}/db/plugins/yugabytedb/plugin.py +0 -0
  439. {dblift-3.4.0 → dblift-3.4.2}/db/provider_capabilities.py +0 -0
  440. {dblift-3.4.0 → dblift-3.4.2}/db/provider_interfaces.py +0 -0
  441. {dblift-3.4.0 → dblift-3.4.2}/db/provider_registry.py +0 -0
  442. {dblift-3.4.0 → dblift-3.4.2}/db/value_utils.py +0 -0
  443. {dblift-3.4.0 → dblift-3.4.2}/dblift.egg-info/SOURCES.txt +0 -0
  444. {dblift-3.4.0 → dblift-3.4.2}/dblift.egg-info/dependency_links.txt +0 -0
  445. {dblift-3.4.0 → dblift-3.4.2}/dblift.egg-info/entry_points.txt +0 -0
  446. {dblift-3.4.0 → dblift-3.4.2}/dblift.egg-info/requires.txt +0 -0
  447. {dblift-3.4.0 → dblift-3.4.2}/dblift.egg-info/top_level.txt +0 -0
  448. {dblift-3.4.0 → dblift-3.4.2}/integrations/__init__.py +0 -0
  449. {dblift-3.4.0 → dblift-3.4.2}/integrations/django/__init__.py +0 -0
  450. {dblift-3.4.0 → dblift-3.4.2}/integrations/django/_client.py +0 -0
  451. {dblift-3.4.0 → dblift-3.4.2}/integrations/django/_engine.py +0 -0
  452. {dblift-3.4.0 → dblift-3.4.2}/integrations/django/apps.py +0 -0
  453. {dblift-3.4.0 → dblift-3.4.2}/integrations/django/checks.py +0 -0
  454. {dblift-3.4.0 → dblift-3.4.2}/integrations/django/management/__init__.py +0 -0
  455. {dblift-3.4.0 → dblift-3.4.2}/integrations/django/management/commands/__init__.py +0 -0
  456. {dblift-3.4.0 → dblift-3.4.2}/integrations/django/management/commands/dblift_info.py +0 -0
  457. {dblift-3.4.0 → dblift-3.4.2}/integrations/django/management/commands/dblift_migrate.py +0 -0
  458. {dblift-3.4.0 → dblift-3.4.2}/integrations/django/management/commands/dblift_validate.py +0 -0
  459. {dblift-3.4.0 → dblift-3.4.2}/integrations/fastapi.py +0 -0
  460. {dblift-3.4.0 → dblift-3.4.2}/integrations/flask.py +0 -0
  461. {dblift-3.4.0 → dblift-3.4.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dblift
3
- Version: 3.4.0
3
+ Version: 3.4.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
@@ -37,6 +37,19 @@ def _apply_sql_script_warning_scan(
37
37
  result.add_warning(warning_msg)
38
38
 
39
39
 
40
+ def _resolve_configured_schema(client: Any) -> Optional[str]:
41
+ """Get the actually-configured database schema from a client, if any.
42
+
43
+ Used so undo statements are qualified with the schema the client is
44
+ really connected to instead of a dialect-specific guess. Returns
45
+ ``None`` when ``client.config.database.schema`` isn't a usable string
46
+ (e.g. unset, or a test double without real config).
47
+ """
48
+ database = getattr(getattr(client, "config", None), "database", None)
49
+ schema = getattr(database, "schema", None)
50
+ return schema if isinstance(schema, str) and schema else None
51
+
52
+
40
53
  def generate_undo_script_operation(
41
54
  client: Any,
42
55
  *,
@@ -91,14 +104,24 @@ def generate_undo_scripts_operation(
91
104
  **kwargs: Any,
92
105
  ) -> List[GenerateUndoScriptResult]:
93
106
  """Generate many undo scripts for ``DBLiftClient.generate_undo_scripts``."""
107
+ from core.migration.formats import MigrationFormatDetector
108
+
94
109
  results: List[GenerateUndoScriptResult] = []
95
110
 
96
111
  if migration_paths is None:
97
112
  migrations_dir = (
98
113
  client._get_scripts_dir() if migrations_dir is None else Path(migrations_dir)
99
114
  )
100
- pattern = "**/V*.sql" if recursive else "V*.sql"
101
- migration_paths = [f for f in migrations_dir.glob(pattern) if f.is_file()]
115
+ # Discover versioned migration files of any supported format (not just
116
+ # .sql) so that non-SQL migrations (e.g. CosmosDB's Python-only
117
+ # migrations) still show up as per-file results below explaining why
118
+ # they were skipped, instead of vanishing from a SQL-only glob.
119
+ pattern = "**/V*" if recursive else "V*"
120
+ migration_paths = [
121
+ f
122
+ for f in migrations_dir.glob(pattern)
123
+ if f.is_file() and MigrationFormatDetector.is_migration_file(f)
124
+ ]
102
125
  else:
103
126
  migration_paths = [Path(p) for p in migration_paths]
104
127
 
@@ -147,13 +170,15 @@ def generate_undo_scripts_operation(
147
170
  {"error": error_msg, "operation": "generate_undo_script"},
148
171
  )
149
172
 
173
+ success_count = sum(1 for r in results if r.success)
174
+ failure_count = sum(1 for r in results if not r.success)
150
175
  client.events.emit(
151
- EventType.MIGRATION_COMPLETED,
176
+ EventType.MIGRATION_FAILED if failure_count > 0 else EventType.MIGRATION_COMPLETED,
152
177
  {
153
178
  "operation": "generate_undo_scripts",
154
179
  "results": results,
155
- "success_count": sum(1 for r in results if r.success),
156
- "failure_count": sum(1 for r in results if not r.success),
180
+ "success_count": success_count,
181
+ "failure_count": failure_count,
157
182
  },
158
183
  )
159
184
  return results
@@ -211,7 +236,11 @@ def _generate_undo_script_for_migration(
211
236
  if output_dir_path is None:
212
237
  output_dir_path = migration_path.parent
213
238
 
214
- generator = UndoScriptGenerator(dialect=client.dialect, logger=client.logger)
239
+ generator = UndoScriptGenerator(
240
+ dialect=client.dialect,
241
+ logger=client.logger,
242
+ default_schema=_resolve_configured_schema(client),
243
+ )
215
244
  expected_undo_path = generator.get_undo_script_path_for_migration(
216
245
  migration,
217
246
  output_dir=output_dir_path,
@@ -511,7 +511,7 @@ class DBLiftClient:
511
511
  """
512
512
  self._guard_scripts_dir_kwarg(kwargs)
513
513
  self.events.emit(
514
- EventType.MIGRATION_STARTED,
514
+ EventType.UNDO_STARTED,
515
515
  {
516
516
  "target_version": target_version,
517
517
  "dry_run": dry_run,
@@ -539,7 +539,7 @@ class DBLiftClient:
539
539
 
540
540
  if result.success:
541
541
  self.events.emit(
542
- EventType.MIGRATION_COMPLETED,
542
+ EventType.UNDO_COMPLETED,
543
543
  {
544
544
  "result": result,
545
545
  "operation": "undo",
@@ -547,7 +547,7 @@ class DBLiftClient:
547
547
  )
548
548
  else:
549
549
  self.events.emit(
550
- EventType.MIGRATION_FAILED,
550
+ EventType.UNDO_FAILED,
551
551
  {
552
552
  "error": getattr(result, "error_message", None),
553
553
  "operation": "undo",
@@ -557,7 +557,7 @@ class DBLiftClient:
557
557
  return result
558
558
  except Exception as e:
559
559
  self.events.emit(
560
- EventType.MIGRATION_FAILED,
560
+ EventType.UNDO_FAILED,
561
561
  {
562
562
  "error": str(e),
563
563
  "operation": "undo",
@@ -616,7 +616,10 @@ class DBLiftClient:
616
616
 
617
617
  Args:
618
618
  migration_paths: List of paths to versioned SQL migration files (V*__.sql).
619
- If None, finds all versioned SQL migrations in migrations_dir.
619
+ If None, finds all versioned migrations in migrations_dir.
620
+ Non-SQL migrations (e.g. Python) are included in the results
621
+ with an error explaining why they were skipped, since automatic
622
+ undo generation only supports SQL migrations.
620
623
  migrations_dir: Directory to search for migrations (default: configured migrations dir)
621
624
  overwrite: Whether to overwrite existing undo scripts
622
625
  recursive: Search migrations directory recursively
@@ -671,7 +674,7 @@ class DBLiftClient:
671
674
  """
672
675
  self._guard_scripts_dir_kwarg(kwargs)
673
676
  self.events.emit(
674
- EventType.MIGRATION_STARTED,
677
+ EventType.CLEAN_STARTED,
675
678
  {
676
679
  "operation": "clean",
677
680
  "dry_run": dry_run,
@@ -688,18 +691,27 @@ class DBLiftClient:
688
691
  **kwargs,
689
692
  )
690
693
 
691
- self.events.emit(
692
- EventType.MIGRATION_COMPLETED,
693
- {
694
- "result": result,
695
- "operation": "clean",
696
- },
697
- )
694
+ if result.success:
695
+ self.events.emit(
696
+ EventType.CLEAN_COMPLETED,
697
+ {
698
+ "result": result,
699
+ "operation": "clean",
700
+ },
701
+ )
702
+ else:
703
+ self.events.emit(
704
+ EventType.CLEAN_FAILED,
705
+ {
706
+ "error": getattr(result, "error_message", None),
707
+ "operation": "clean",
708
+ },
709
+ )
698
710
 
699
711
  return result
700
712
  except Exception as e:
701
713
  self.events.emit(
702
- EventType.MIGRATION_FAILED,
714
+ EventType.CLEAN_FAILED,
703
715
  {
704
716
  "error": str(e),
705
717
  "operation": "clean",
@@ -725,7 +737,7 @@ class DBLiftClient:
725
737
  BaselineResult with baseline details
726
738
  """
727
739
  self.events.emit(
728
- EventType.MIGRATION_STARTED,
740
+ EventType.BASELINE_STARTED,
729
741
  {
730
742
  "operation": "baseline",
731
743
  "version": version,
@@ -739,18 +751,27 @@ class DBLiftClient:
739
751
  **kwargs,
740
752
  )
741
753
 
742
- self.events.emit(
743
- EventType.MIGRATION_COMPLETED,
744
- {
745
- "result": result,
746
- "operation": "baseline",
747
- },
748
- )
754
+ if result.success:
755
+ self.events.emit(
756
+ EventType.BASELINE_COMPLETED,
757
+ {
758
+ "result": result,
759
+ "operation": "baseline",
760
+ },
761
+ )
762
+ else:
763
+ self.events.emit(
764
+ EventType.BASELINE_FAILED,
765
+ {
766
+ "error": getattr(result, "error_message", None),
767
+ "operation": "baseline",
768
+ },
769
+ )
749
770
 
750
771
  return result
751
772
  except Exception as e:
752
773
  self.events.emit(
753
- EventType.MIGRATION_FAILED,
774
+ EventType.BASELINE_FAILED,
754
775
  {
755
776
  "error": str(e),
756
777
  "operation": "baseline",
@@ -781,7 +802,7 @@ class DBLiftClient:
781
802
  """
782
803
  self._guard_scripts_dir_kwarg(kwargs)
783
804
  self.events.emit(
784
- EventType.MIGRATION_STARTED,
805
+ EventType.REPAIR_STARTED,
785
806
  {
786
807
  "operation": "repair",
787
808
  "dry_run": dry_run,
@@ -798,18 +819,27 @@ class DBLiftClient:
798
819
  **kwargs,
799
820
  )
800
821
 
801
- self.events.emit(
802
- EventType.MIGRATION_COMPLETED,
803
- {
804
- "result": result,
805
- "operation": "repair",
806
- },
807
- )
822
+ if result.success:
823
+ self.events.emit(
824
+ EventType.REPAIR_COMPLETED,
825
+ {
826
+ "result": result,
827
+ "operation": "repair",
828
+ },
829
+ )
830
+ else:
831
+ self.events.emit(
832
+ EventType.REPAIR_FAILED,
833
+ {
834
+ "error": getattr(result, "error_message", None),
835
+ "operation": "repair",
836
+ },
837
+ )
808
838
 
809
839
  return result
810
840
  except Exception as e:
811
841
  self.events.emit(
812
- EventType.MIGRATION_FAILED,
842
+ EventType.REPAIR_FAILED,
813
843
  {
814
844
  "error": str(e),
815
845
  "operation": "repair",
@@ -883,6 +913,30 @@ class DBLiftClient:
883
913
  plan = _make_premium_stub_method("plan")
884
914
  preflight = _make_premium_stub_method("preflight")
885
915
 
916
+ @classmethod
917
+ def _resolve_factory_client_cls(cls) -> type:
918
+ """The class ``from_config``/``from_config_file``/``from_sqlalchemy``
919
+ should construct.
920
+
921
+ Called on the base ``DBLiftClient`` class, this consults the same
922
+ ``dblift.client`` seam the CLI already uses
923
+ (``core.seams.client_factory.resolve_client_class``) so a
924
+ tier-provided subclass is returned when one is registered — the
925
+ documented ``from api.client import DBLiftClient`` entry point then
926
+ behaves like the CLI instead of always constructing the OSS class
927
+ (issue #753). Called on any other class — a caller already
928
+ constructing a specific subclass directly — the seam is not
929
+ consulted, so that explicit choice is never overridden.
930
+ """
931
+ if cls is not DBLiftClient:
932
+ return cls
933
+ # Imported here (not at module top) so tests can monkeypatch
934
+ # core.seams.client_factory.resolve_client_class per-call; a top-level
935
+ # `from ... import` would bind the function once and ignore later patches.
936
+ from core.seams.client_factory import resolve_client_class
937
+
938
+ return resolve_client_class()
939
+
886
940
  @classmethod
887
941
  def from_config(
888
942
  cls,
@@ -913,7 +967,9 @@ class DBLiftClient:
913
967
  kwargs["migrations_dir"] = migrations_dir
914
968
  return cast(
915
969
  Self,
916
- client_from_config(config, logger, client_cls=cls, **kwargs),
970
+ client_from_config(
971
+ config, logger, client_cls=cls._resolve_factory_client_cls(), **kwargs
972
+ ),
917
973
  )
918
974
 
919
975
  @classmethod
@@ -939,7 +995,9 @@ class DBLiftClient:
939
995
  overrides["environment"] = environment
940
996
  return cast(
941
997
  Self,
942
- client_from_config_file(config_path, logger, client_cls=cls, **overrides),
998
+ client_from_config_file(
999
+ config_path, logger, client_cls=cls._resolve_factory_client_cls(), **overrides
1000
+ ),
943
1001
  )
944
1002
 
945
1003
  @classmethod
@@ -983,7 +1041,7 @@ class DBLiftClient:
983
1041
  log_file,
984
1042
  connection=connection,
985
1043
  config=config,
986
- client_cls=cls,
1044
+ client_cls=cls._resolve_factory_client_cls(),
987
1045
  **kwargs,
988
1046
  ),
989
1047
  )
@@ -178,7 +178,7 @@ def _build_args_namespace(
178
178
  args.dry_run = False
179
179
  args.log_dir = "logs"
180
180
  args.log_format = "text"
181
- args.log_level = "info"
181
+ args.log_level = None
182
182
  args.log_file = None
183
183
  args.database_url = None
184
184
  args.database_username = None
@@ -458,7 +458,13 @@ def _configure_logging(
458
458
  "warn": LogLevel.WARN,
459
459
  "error": LogLevel.ERROR,
460
460
  }
461
- log_level = _LOG_LEVEL_MAP.get(args.log_level, LogLevel.INFO)
461
+ # ``config.log_level`` is the already-merged value (file -> env -> CLI
462
+ # precedence applied in config.dblift_config.load_config); prefer it over
463
+ # the raw CLI namespace, which only reflects an explicit --log-level and
464
+ # otherwise carries no signal about file/env config. Fall back to
465
+ # args.log_level when the merged config has none set.
466
+ effective_log_level = getattr(config, "log_level", None) or args.log_level
467
+ log_level = _LOG_LEVEL_MAP.get(effective_log_level, LogLevel.INFO)
462
468
  # ``--quiet`` raises the *console* threshold to NOTICE so info/debug
463
469
  # lines disappear from the terminal while NOTICE (success
464
470
  # confirmations, "Command completed"), WARN, and ERROR still show
@@ -557,6 +563,13 @@ def _resolve_scripts_directories(
557
563
  parser.error(f"Migration scripts directory not found: {args.scripts_list[0]}")
558
564
 
559
565
  config.migrations.directory = str(scripts_dir)
566
+ # --scripts fully replaces any config-file migrations.directories
567
+ # list. Without this, get_directory_configs() (called later by
568
+ # api._client_factory.client_from_config(), the CLI's actual path
569
+ # to resolving the primary migrations dir) would keep preferring the
570
+ # stale plural list over the singular `directory` set above, silently
571
+ # dropping this first --scripts value.
572
+ config.migrations.directories = []
560
573
 
561
574
  if len(args.scripts_list) > 1:
562
575
  for scripts_path in args.scripts_list[1:]:
@@ -444,10 +444,15 @@ def create_parser(
444
444
  parser.add_argument("--log-format", default="text", help="Log format (text, json, html)")
445
445
  parser.add_argument(
446
446
  "--log-level",
447
- default="info",
447
+ # No default here: a non-None default is indistinguishable from an
448
+ # explicit choice once merged with config-file/env values (CLI > env >
449
+ # file precedence), so it would always win and silently discard
450
+ # DBLIFT_LOG_LEVEL / a config file's log_level. _configure_logging()
451
+ # falls back to LogLevel.INFO when nothing sets a level.
452
+ default=None,
448
453
  type=str.lower,
449
454
  choices=["debug", "info", "warn", "error"],
450
- help="Log level (case-insensitive)",
455
+ help="Log level (case-insensitive, default: info)",
451
456
  )
452
457
  parser.add_argument("--log-file", help="Log file name")
453
458
  parser.add_argument(
@@ -7,12 +7,14 @@ import traceback
7
7
  from pathlib import Path
8
8
  from typing import Any, Dict, List
9
9
 
10
+ import yaml
11
+
10
12
  from api._cli_support import (
11
13
  ProviderRegistry,
12
14
  get_provider_display_url,
13
15
  )
14
16
  from cli._output import CommandOutput, from_args
15
- from config.dblift_config import load_config
17
+ from config.dblift_config import DbliftConfig, load_config, unrecognized_top_level_keys
16
18
  from core.logger import DbliftLogger, LogFormat
17
19
  from core.utils.url_masking import mask_database_url
18
20
  from db.error import format_connection_error
@@ -87,6 +89,7 @@ def validate_config(args: argparse.Namespace) -> int:
87
89
  except (FileNotFoundError, RuntimeError) as load_err:
88
90
  out.error(f"Error: {load_err}")
89
91
  return 1
92
+ _warn_if_unrecognized_top_level_keys(config_file, out)
90
93
  else:
91
94
  # Batch-6 BUG-04: without ``--config`` and without ``--db-url`` (or
92
95
  # the ``DBLIFT_DB_URL`` env var), ``load_config`` returns a config
@@ -122,6 +125,30 @@ def validate_config(args: argparse.Namespace) -> int:
122
125
  return 1
123
126
 
124
127
 
128
+ def _warn_if_unrecognized_top_level_keys(config_file: str, out: CommandOutput) -> None:
129
+ """Emit a stderr warning when the config file has an unrecognized top-level key.
130
+
131
+ Config file loading is permissive by construction: an unknown top-level
132
+ key (e.g. a typo like ``migratoins_dir``) is silently dropped rather than
133
+ rejected, so the command runs as if the key wasn't there. ``validate-config``
134
+ is the natural place to surface that, since checking config correctness is
135
+ its whole purpose. Re-reading the file here is best-effort — any error is
136
+ swallowed since ``load_config`` already loaded it successfully.
137
+ """
138
+ try:
139
+ raw_data = DbliftConfig.load_config_data_from_yaml(config_file)
140
+ except (OSError, yaml.YAMLError):
141
+ return
142
+ unknown = unrecognized_top_level_keys(raw_data)
143
+ if not unknown:
144
+ return
145
+ keys = ", ".join(unknown)
146
+ out.error(
147
+ f"Warning: unrecognized configuration key(s): {keys}. "
148
+ f"Check for typos — unrecognized keys are ignored."
149
+ )
150
+
151
+
125
152
  _CREDENTIALLESS_TEST_TYPES = frozenset({"dummy"})
126
153
 
127
154
 
@@ -220,6 +220,32 @@ def _resolve_core_version() -> Optional[str]:
220
220
  return None
221
221
 
222
222
 
223
+ def _resolve_manifest_version() -> Optional[str]:
224
+ """Return the ``version`` field of a ``DISTRIBUTION-MANIFEST.json`` sitting
225
+ next to the running entry point, if one is present.
226
+
227
+ An archive/frozen distribution ships this file at its root, stamped at
228
+ build time with the version of the code it actually bundles. Unlike
229
+ ``importlib.metadata``, it cannot be shadowed by an unrelated distribution
230
+ that happens to be installed elsewhere on the host — so when present, it
231
+ is the most authoritative source for "what version is this". A real
232
+ ``pip install`` never ships this file, so this is a no-op there.
233
+ """
234
+ import json
235
+
236
+ manifest_file = _project_root / "DISTRIBUTION-MANIFEST.json"
237
+ try:
238
+ with open(manifest_file, "r", encoding="utf-8") as f:
239
+ manifest = json.load(f)
240
+ if isinstance(manifest, dict):
241
+ version = manifest.get("version")
242
+ if isinstance(version, str) and version:
243
+ return version
244
+ except (OSError, ValueError):
245
+ pass
246
+ return None
247
+
248
+
223
249
  def _format_version() -> str:
224
250
  """Render the ``--version`` output.
225
251
 
@@ -231,11 +257,30 @@ def _format_version() -> str:
231
257
  is present, list every component so a bare number is never ambiguous. In a
232
258
  plain OSS install only the core is present, so the output stays a single
233
259
  ``dblift version X`` line — unchanged from before.
260
+
261
+ An archive/frozen distribution's ``DISTRIBUTION-MANIFEST.json``, when
262
+ present, overrides the headline: it is stamped at build time and immune to
263
+ whatever unrelated ``dblift``/``dblift-pro``/``dblift-enterprise``
264
+ metadata happens to be installed on the host running it.
265
+
266
+ The breakdown lines apply that same preference at the component level: a
267
+ directly-importable package's own ``__version__`` attribute is tried
268
+ before ``importlib.metadata.version``, for consistency with how the
269
+ headline already avoids stale host-installed metadata.
234
270
  """
271
+ import importlib
235
272
  from importlib.metadata import PackageNotFoundError
236
273
  from importlib.metadata import version as _version
237
274
 
238
275
  def _get(dist: str) -> Optional[str]:
276
+ try:
277
+ module = importlib.import_module(dist.replace("-", "_"))
278
+ module_version = getattr(module, "__version__", None)
279
+ if isinstance(module_version, str) and module_version:
280
+ return module_version
281
+ except Exception:
282
+ # A broken install shouldn't crash --version; fall back to metadata.
283
+ pass
239
284
  try:
240
285
  return _version(dist)
241
286
  except PackageNotFoundError:
@@ -245,8 +290,9 @@ def _format_version() -> str:
245
290
  pro = _get("dblift-pro")
246
291
  enterprise = _get("dblift-enterprise")
247
292
 
248
- # Headline = most-derived installed tier (the product actually running).
249
- product = enterprise or pro or core
293
+ # Headline = manifest version (bundled distribution) if present, else the
294
+ # most-derived installed tier (the product actually running).
295
+ product = _resolve_manifest_version() or enterprise or pro or core
250
296
  lines = [f"dblift version {product}"]
251
297
  # Component manifest only when a paid tier is present; OSS stays one line.
252
298
  if pro or enterprise:
@@ -519,6 +565,28 @@ def _apply_configured_output_format(ctx: _CliContext) -> None:
519
565
  ctx.args.format = output_format
520
566
 
521
567
 
568
+ def _effective_scripts_dir_for_log(client: Any, fallback: Optional[Path]) -> Any:
569
+ """Return the directory ``client`` will actually scan, for debug logging.
570
+
571
+ ``_resolve_scripts_directories`` computes ``scripts_dir`` locally
572
+ (resolving relative paths against the config file's parent directory),
573
+ but that value is never handed to the client — ``_build_command_client``
574
+ builds it straight from ``ctx.config``, which re-resolves the migrations
575
+ directory independently (relative paths are resolved against the
576
+ current working directory at scan time). The two can disagree, so the
577
+ debug line must reflect the client's own resolution, not the local one.
578
+ Falls back to the locally-computed value for clients without
579
+ ``_get_scripts_dir`` (e.g. config-only stand-ins).
580
+ """
581
+ get_scripts_dir = getattr(client, "_get_scripts_dir", None)
582
+ if not callable(get_scripts_dir):
583
+ return fallback
584
+ try:
585
+ return get_scripts_dir().resolve()
586
+ except (OSError, RuntimeError, TypeError):
587
+ return fallback
588
+
589
+
522
590
  def _dispatch_command(ctx: _CliContext, command_output: CommandOutput) -> int:
523
591
  """Phase 4: build full workflow context and run the command loop.
524
592
 
@@ -532,7 +600,7 @@ def _dispatch_command(ctx: _CliContext, command_output: CommandOutput) -> int:
532
600
  )
533
601
 
534
602
  client = _build_command_client(ctx)
535
- ctx.log.debug(f"scripts_dir: {scripts_dir}")
603
+ ctx.log.debug(f"scripts_dir: {_effective_scripts_dir_for_log(client, scripts_dir)}")
536
604
  ctx.log.debug(
537
605
  f"config.migrations.directories: {getattr(ctx.config.migrations, 'directories', None)}"
538
606
  )
@@ -4,7 +4,7 @@ import os
4
4
  import re
5
5
  from dataclasses import dataclass, field
6
6
  from pathlib import Path
7
- from typing import Any, Dict, List, Mapping, Optional, Tuple, Type, Union, cast
7
+ from typing import Any, Dict, FrozenSet, List, Mapping, Optional, Tuple, Type, Union, cast
8
8
 
9
9
  import yaml
10
10
 
@@ -44,6 +44,56 @@ _ENVIRONMENT_SECTION_KEYS: Tuple[str, ...] = ("environments", "resolve")
44
44
  #: ``--config``, it selects configuration rather than being configuration.
45
45
  DEFAULT_ENV_SELECTOR_VAR = "DBLIFT_ENV"
46
46
 
47
+ # Every top-level key ``DbliftConfig.from_dict`` (and its supporting helpers)
48
+ # actually reads. File loading is permissive by construction — an unrecognized
49
+ # key is silently dropped rather than rejected — so this set exists to let
50
+ # ``db validate-config`` flag likely typos (e.g. ``migratoins_dir``) that would
51
+ # otherwise run unnoticed. Keep in sync with the ``data.get(...)`` reads in
52
+ # :meth:`DbliftConfig.from_dict`.
53
+ KNOWN_TOP_LEVEL_CONFIG_KEYS: FrozenSet[str] = frozenset(
54
+ (
55
+ "database",
56
+ "migrations",
57
+ "migrations_dir", # deprecated alias for migrations.directory
58
+ "logging",
59
+ "log_dir",
60
+ "log_file",
61
+ "log_format",
62
+ "log_level",
63
+ "baseline_version",
64
+ "target_version",
65
+ "dry_run",
66
+ "undo",
67
+ "installed_by",
68
+ "extra_params",
69
+ "tags",
70
+ "exclude_tags",
71
+ "versions",
72
+ "exclude_versions",
73
+ "mark_as_executed",
74
+ "strict_mode",
75
+ "clean_disabled",
76
+ "placeholders",
77
+ "history_table",
78
+ "snapshot_table",
79
+ "max_snapshots",
80
+ "secrets",
81
+ )
82
+ + _ENVIRONMENT_SECTION_KEYS
83
+ + _PAID_RAW_CONFIG_KEYS
84
+ )
85
+
86
+
87
+ def unrecognized_top_level_keys(data: Dict[str, Any]) -> List[str]:
88
+ """Return the top-level keys in *data* that the config schema doesn't recognize, sorted.
89
+
90
+ Used by ``db validate-config`` to warn about likely typos instead of
91
+ silently ignoring the key, as plain config loading does.
92
+ """
93
+ if not isinstance(data, dict):
94
+ return []
95
+ return sorted(key for key in data if key not in KNOWN_TOP_LEVEL_CONFIG_KEYS)
96
+
47
97
 
48
98
  # ``validate-sql`` only needs a dialect-typed DbliftConfig; connection is never opened.
49
99
  # Placeholder database URLs satisfy :meth:`DbliftConfig.validate_complete_data` and are never
@@ -336,8 +386,13 @@ class DirectoryConfig:
336
386
  if isinstance(data, str):
337
387
  return cls(path=data, recursive=True)
338
388
  elif isinstance(data, dict):
389
+ # Accept 'directory' as an alias for 'path' — it mirrors the
390
+ # top-level migrations.directory field name, so it's a natural
391
+ # key for users to reach for here. Without this, an entry keyed
392
+ # on 'directory' silently resolves to an empty path and finds
393
+ # nothing.
339
394
  return cls(
340
- path=data.get("path", ""),
395
+ path=data.get("path", data.get("directory", "")),
341
396
  recursive=data.get("recursive", True),
342
397
  )
343
398
  else:
@@ -499,6 +499,16 @@ class FileLog(AbstractLog):
499
499
  # If no extension in the pattern and no format placeholder, add the extension
500
500
  elif "." not in log_file_name.split("/")[-1]:
501
501
  log_file_name += f".{extension}"
502
+
503
+ # A pattern that already has its own directory component (e.g.
504
+ # "logs/info.html" from --log-file) is a path meant to be
505
+ # resolved relative to the current working directory — joining
506
+ # it onto log_dir would double-nest it when log_dir happens to
507
+ # share a name with that directory. Only a bare filename (no
508
+ # directory component) nests under log_dir.
509
+ log_file_path = Path(log_file_name)
510
+ if log_file_path.parent != Path("."):
511
+ return log_file_path
502
512
  else:
503
513
  # Use default naming convention
504
514
  log_file_name = (