Root cause of the "mypass%25123" != "mypass%123" and "p%40ss%21word"
!= "p@ss!word" round-trip failures in test_database_password_encoding.py:
Database.sqlalchemy_uri_decrypted manually percent-encoded the password
with urllib.parse.quote() before handing it to
URL.render_as_string(hide_password=False). Under SQLAlchemy 1.4,
render_as_string() rendered URL.password as a literal value, so the
manual pre-encoding was necessary. Under SQLAlchemy 2.0,
render_as_string() always percent-encodes the password itself - the
pre-encoded value gets encoded a second time (a literal "%" becomes
"%25", which decodes back to "%25" instead of "%" on the next parse).
Passing the raw password straight through and letting
render_as_string() do the (now single) encoding fixes the round-trip.
Confirmed the double-encoding mechanism directly against this branch's
sqlalchemy==2.0.51: URL.set(password=<pre-encoded>).render_as_string()
produces "mypass%2525123"; URL.set(password=<raw>).render_as_string()
correctly produces "mypass%25123".
Separately, model_tests.py::test_impersonate_user_trino (and the
mysqlclient-only test_adjust_engine_params_mysql, exercised on real CI
runners but skipped here where mysqlclient isn't importable) asserted
on str(url) for URLs containing a password. SQLAlchemy 2.0 also changed
URL.__str__() to hide the password by default (a deliberate hardening
change - 1.4 rendered it in full); switched those assertions to
render_as_string(hide_password=False) to compare against the real,
unmasked URL the engine was actually constructed with, rather than
relaxing what's being verified.
Verified locally (sqlite): test_database_password_encoding.py (5/5)
and model_tests.py (21 passed, 5 skipped - the mysqlclient-gated ones)
both pass clean.
* pass datasource_type and datasource_id to form_data
* add datasource_type to delete command
* add datasource_type to delete command
* fix old keys implementation
* add more tests
* Update db setup fixture scope
* Load data into db only once
* Update fixture scopes for data loading
* cleanup imports
* try import
* Update scope
* fix cleanup
* Import all fixtures
* Separate data log and metadata creation
* Retain table description
* fix dtype
Co-authored-by: Bogdan Kyryliuk <bogdankyryliuk@dropbox.com>
* abstract boilerplate code into class and rename csv to file
* add db migration
* fix some stuff
* more renaming of csv to file
* rename in translations
* update down revision
* update down revision
* bump chart version
* switch to alter column name approach in db migration
* fix db migration for MySQL
* db migration conflict
* feat: add support for generic series limit
* refine series_columns logic
* update docs
* bump superset-ui
* add note to UPDATING.md
* remove default value for timeseries_limit
* feat(cross-filters): add support for temporal filters
* fix test
* make filter optional
* remove mocks
* fix more tests
* remove unnecessary optionality
* fix even more tests
* bump superset-ui
* add isExtra to schema
* address comments
* fix presto test