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.
- {dblift-3.3.0 → dblift-3.3.2}/PKG-INFO +1 -1
- {dblift-3.3.0 → dblift-3.3.2}/cli/db_utils.py +12 -73
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/commands/base_command.py +18 -4
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/commands/baseline_command.py +15 -1
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/commands/import_flyway_command.py +22 -3
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/commands/info_command.py +24 -8
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/commands/migrate_command.py +7 -2
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/commands/validate_command.py +26 -13
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/executor/execution_engine.py +18 -3
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/executor/migration_executor.py +4 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/executors/python_executor.py +4 -2
- {dblift-3.3.0 → dblift-3.3.2}/core/seams/sql_generators.py +6 -1
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_validator/_checksum_validator.py +16 -1
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_validator/migration_validator.py +9 -1
- {dblift-3.3.0 → dblift-3.3.2}/db/error.py +93 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/_pg_compatible.py +78 -24
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/cosmosdb/history_manager.py +34 -28
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/cosmosdb/query_executor.py +22 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/provider.py +8 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/db2/schema_operations.py +10 -10
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mariadb/quirks.py +8 -19
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/provider.py +7 -2
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/yugabytedb/plugin.py +4 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/provider_registry.py +15 -6
- {dblift-3.3.0 → dblift-3.3.2}/dblift.egg-info/PKG-INFO +1 -1
- {dblift-3.3.0 → dblift-3.3.2}/pyproject.toml +1 -1
- {dblift-3.3.0 → dblift-3.3.2}/LICENSE +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/README.md +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/api/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/api/_cli_support.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/api/_client_factory.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/api/_client_operations.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/api/_engine_config.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/api/async_client.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/api/client.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/api/events.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/api/migrations.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/api/py.typed +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/cli/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/cli/_command_handlers.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/cli/_config_helpers.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/cli/_constants.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/cli/_output.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/cli/_parser_setup.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/cli/commands/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/cli/commands/config_command.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/cli/extensions.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/cli/handlers/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/cli/handlers/_shared.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/cli/handlers/baseline.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/cli/handlers/clean.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/cli/handlers/import_flyway.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/cli/handlers/info.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/cli/handlers/migrate.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/cli/handlers/repair.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/cli/handlers/undo.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/cli/handlers/validate.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/cli/main.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/cli/premium_manifest.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/config/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/config/_credential_masking.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/config/_subclasses/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/config/_subclasses/dummy_config.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/config/_url_builder_mixin.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/config/config_builder.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/config/database_config.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/config/dblift_config.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/config/errors.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/config/property_registry.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/config/secrets/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/config/secrets/_cache.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/config/secrets/_provider_base.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/config/secrets/_registry.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/config/secrets/_resolver.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/config/secrets/_secrets_config.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/constants.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/dialect_boundary.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/exceptions.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/_column_enricher.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/_partition_enricher.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/_schema_orchestrator.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/_utils.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/_vendor_property_applier.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/base_introspector.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/extractors/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/extractors/base_extractor.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/extractors/column_extractor.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/extractors/constraint_extractor.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/extractors/index_extractor.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/extractors/misc_extractor.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/extractors/procedure_extractor.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/extractors/sequence_extractor.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/extractors/table_extractor.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/extractors/trigger_extractor.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/extractors/view_extractor.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/introspector_factory.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/result.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/schema_introspector.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/vendor_queries_base.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/vendor_queries_factory.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/vendor_queries_protocols.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/introspection/version_detector.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/logger/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/logger/_base.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/logger/_factory.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/logger/_formatters.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/logger/_levels.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/logger/_multi.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/logger/_null.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/logger/console.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/logger/formatters/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/logger/formatters/_formatter_impl.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/logger/formatters/factory.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/logger/formatters/formatter.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/logger/formatters/htmlformatter.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/logger/formatters/jsonformatter.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/logger/log.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/logger/results.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/logger/templates/oldreport.html +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/logger/templates/report.html +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/_type_match.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/clean_summary.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/commands/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/commands/_script_events.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/commands/clean_command.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/commands/repair_command.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/commands/undo_command.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/encoding.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/executor/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/executor/migration_helpers.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/executor/placeholder_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/executor/transaction_policy.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/executors/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/executors/base_executor.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/executors/executor_factory.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/executors/sql_executor.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/formats/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/formats/format_detector.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/formats/migration_format.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/history/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/history/migration_history_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/journals/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/journals/migration_journal.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/migration.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/placeholders/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/placeholders/placeholder_service.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/rules/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/rules/migration_rules.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/scripting/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/scripting/migration_script_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/scripting/undo_script_generator/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/scripting/undo_script_generator/_ddl_reversers.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/scripting/undo_script_generator/_dml_reversers.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/scripting/undo_script_generator/_extractors.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/scripting/undo_script_generator/_generator.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/scripting/undo_script_generator/_helpers.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/scripting/undo_script_generator/_models.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/scripting/undo_script_generator/_reversers.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/sql/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/sql/execution_statement.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/sql/sql_analyzer.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/sql/sql_execution_service.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/sql/statement_splitter.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/state/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/state/migration_data_service.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/state/migration_display_state.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/state/migration_formatter.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/state/migration_state.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/state/migration_state_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/state/migration_state_service.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/ui/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/ui/data_collector.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/ui/display_formatters.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/ui/migration_analyzer.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/ui/migration_ui.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/ui/table_renderer.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/migration/version_utils.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/normalization/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/normalization/dependency_resolver.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/normalization/identifier_normalizer.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/normalization/object_orderer.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/normalization/type_constants.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/normalization/type_mapper.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/normalization/type_mappings.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/normalization/type_normalizer.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/seams/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/seams/capabilities.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/seams/client_factory.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/seams/event_listeners.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/seams/feature_loading.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/seams/introspection.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/seams/license_info.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/seams/runtime_checks.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/seams/tier_resolver.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/alter/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/alter/alter_generator_factory.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/alter/base_alter_generator.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/alter_generator.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/base_generator.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/basic_table_ddl_generator.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/dependency_analyzer.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/diff_converters/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/diff_converters/base_converter.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/formatter.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/generator_factory.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/options.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/script_organizer.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/sql_generator.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/sql_statement.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_generator/table_ddl_render.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/_base_parse_result.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/_base_sql_column.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/_base_sql_constraint.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/_base_sql_object.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/_base_sql_statement.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/base.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/constraint_validator.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/database_link.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/dialect.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/event.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/extension.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/feature_gates.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/foreign_data_wrapper.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/foreign_server.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/index.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/linked_server.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/module.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/package.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/partition.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/procedure.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/sequence.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/server_info.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/synonym.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/table.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/table_canonicalizer.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/table_options.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/trigger.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/user_defined_type.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/view.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_model/view_options.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/_partition_handler.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/_sqlglot_builders.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/base_statement_parser.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/base_tokenizer.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/common/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/common/base_parser.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/dialects/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/dialects/base_config.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/enhanced_regex_parser.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/hybrid_parser.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/parser_context.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/parser_factory.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/parser_interface.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/sqlglot_parser.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/tokens.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_parser/unified_regex_parser.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_validator/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_validator/_flyway_compatibility.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_validator/_migration_filter.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_validator/_sql_syntax_validator.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/sql_validator/_strict_mode_validator.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/state/sql_script_formatter.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/state/sql_statement.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/utils/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/utils/database_url_parser.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/utils/metadata_helpers.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/utils/row_access.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/utils/string_utils.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/core/utils/url_masking.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/base_provider.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/base_quirks.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/constants.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/dml_analysis.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/error_handler.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/exceptions.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/feature_gate.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/native_connection_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/object_naming.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/alloydb/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/alloydb/plugin.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/aurora_postgresql/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/aurora_postgresql/plugin.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/base_history_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/base_locking_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/base_query_executor.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/base_schema_operations.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/base_snapshot_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/base_undo_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/citus/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/citus/plugin.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cockroachdb/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cockroachdb/plugin.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cockroachdb/provider.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cockroachdb/quirks.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/config.py +3 -3
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/cosmosdb/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/cosmosdb/_sdk.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/cosmosdb/connection_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/cosmosdb/locking_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/cosmosdb/schema_operations.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/introspection/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/plugin.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/cosmosdb/quirks.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/config.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/db2/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/db2/history_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/db2/locking_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/introspection/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/parser/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/parser/db2_regex_parser.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/parser/parser_config.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/plugin.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/provider.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/quirks.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/db2/sqlalchemy_url.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/duckdb/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/duckdb/config.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/duckdb/parser/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/duckdb/parser/duckdb_regex_parser.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/duckdb/parser/parser_config.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/duckdb/plugin.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/duckdb/provider.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/duckdb/quirks.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/duckdb/sqlalchemy_url.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mariadb/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mariadb/plugin.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mariadb/provider.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/config.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/introspection/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/mysql/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/mysql/history_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/mysql/locking_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/mysql/schema_operations.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/parser/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/parser/mysql_regex_parser.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/parser/mysql_statement_parser.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/parser/mysql_tokenizer.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/parser/parser_config.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/plugin.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/provider.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/quirks.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/mysql/sqlalchemy_url.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/neon/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/neon/plugin.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/nosql_base/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/nosql_base/history.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/nosql_base/introspection.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/nosql_base/locking.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/config.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/introspection/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/introspection/oracle_utils.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/oracle/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/oracle/dbms_output.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/oracle/history_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/oracle/locking_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/oracle/schema_operations.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/parser/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/parser/_comments.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/parser/_object_extractor.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/parser/_plsql_block.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/parser/_sqlplus.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/parser/_statement_splitter.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/parser/oracle_parser.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/parser/oracle_statement_parser.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/parser/oracle_tokenizer.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/parser/parser_config.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/parser/sqlplus_context.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/plugin.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/quirks.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/oracle/sqlalchemy_url.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/_provider_query_executor.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/config.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/introspection/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/parser/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/parser/parser_config.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/parser/postgresql_regex_parser.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/parser/postgresql_statement_parser.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/parser/postgresql_tokenizer.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/plugin.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/postgresql/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/postgresql/history_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/postgresql/locking_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/postgresql/schema_operations.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/provider.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/quirks.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/postgresql/sqlalchemy_url.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/redshift/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/redshift/plugin.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/redshift/provider.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/redshift/quirks.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/redshift/sqlalchemy_url.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/snowflake/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/snowflake/config.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/snowflake/plugin.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/snowflake/provider.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/snowflake/quirks.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/snowflake/sqlalchemy_url.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/config.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/introspection/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/parser/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/parser/parser_config.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/parser/sqlite_regex_parser.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/plugin.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/provider.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/quirks.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/sqlalchemy_url.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/sqlite/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/sqlite/connection_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/sqlite/history_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/sqlite/locking_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/sqlite/query_executor.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlite/sqlite/schema_operations.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/config.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/introspection/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/parser/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/parser/parser_config.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/parser/sqlserver_regex_parser.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/parser/sqlserver_statement_parser.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/parser/sqlserver_tokenizer.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/parser/tsql_batch_separator.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/plugin.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/provider.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/quirks.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/sqlalchemy_url.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/sqlserver/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/sqlserver/history_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/sqlserver/locking_manager.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/sqlserver/sqlserver/schema_operations.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/supabase/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/supabase/plugin.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/timescaledb/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/timescaledb/plugin.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/plugins/yugabytedb/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/provider_capabilities.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/provider_interfaces.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/sqlalchemy_provider.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/db/value_utils.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/dblift.egg-info/SOURCES.txt +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/dblift.egg-info/dependency_links.txt +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/dblift.egg-info/entry_points.txt +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/dblift.egg-info/requires.txt +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/dblift.egg-info/top_level.txt +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/integrations/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/integrations/django/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/integrations/django/_client.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/integrations/django/_engine.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/integrations/django/apps.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/integrations/django/checks.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/integrations/django/management/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/integrations/django/management/commands/__init__.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/integrations/django/management/commands/dblift_info.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/integrations/django/management/commands/dblift_migrate.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/integrations/django/management/commands/dblift_validate.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/integrations/fastapi.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/integrations/flask.py +0 -0
- {dblift-3.3.0 → dblift-3.3.2}/integrations/opentelemetry.py +0 -0
- {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.
|
|
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
|
|
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"] =
|
|
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
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
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
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
self.provider.
|
|
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
|
|
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
|
-
|
|
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
|
|
46
|
-
|
|
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=
|
|
126
|
-
exclude_tags=
|
|
127
|
-
versions=
|
|
128
|
-
exclude_versions=
|
|
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=
|
|
139
|
-
exclude_tags=
|
|
140
|
-
versions=
|
|
141
|
-
exclude_versions=
|
|
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
|
-
|
|
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
|
-
#
|
|
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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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"^(?:
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|