Summary
In the mssql_python adapter, build_connection_config returns early when connection_string is present, so every discrete field in the same connection_config (server, database, uid, pwd, encrypt, extra, ...) is dropped without a warning or error.
# sqlspec/adapters/mssql_python/core.py
connection_string = config.pop("connection_string", None)
if connection_string is not None:
return str(connection_string), connect_kwargs
Why it matters
A common pattern is to hold one base config and derive per-database configs from it by overriding database:
base = {"connection_string": "Server=host,1433;UID=app;PWD=...;Encrypt=yes;"}
per_db = MssqlPythonConfig(connection_config={**base, "database": "sales"})
per_db connects to the login's default database, not sales. Nothing fails — queries simply run against the wrong database, which is hard to notice when iterating over several databases on one instance.
Reproduction
from sqlspec.adapters.mssql_python.core import build_connection_config
conn_str, _ = build_connection_config(
{"connection_string": "Server=host;UID=u;PWD=p;", "database": "sales"}
)
assert "sales" in conn_str # fails: "Server=host;UID=u;PWD=p;"
Expected
Either of these would remove the silent wrong answer:
- Merge discrete fields with the explicit string, with a documented precedence. The
arrow_odbc adapter already does this (its build_connection_config composes the discrete fields and appends connection_string as a suffix, with the precedence described in the docstring), so the two ODBC-style adapters would behave the same way.
- Raise a
ValueError (or ImproperConfigurationError) when connection_string is combined with any connection-string-level field, naming the conflicting keys.
Option 1 seems the friendlier of the two, provided the precedence is stated (an explicit field overriding the same key inside the string is the least surprising for the per-database case above).
Version
sqlspec 0.63.1; still present on main.
Summary
In the
mssql_pythonadapter,build_connection_configreturns early whenconnection_stringis present, so every discrete field in the sameconnection_config(server,database,uid,pwd,encrypt,extra, ...) is dropped without a warning or error.Why it matters
A common pattern is to hold one base config and derive per-database configs from it by overriding
database:per_dbconnects to the login's default database, notsales. Nothing fails — queries simply run against the wrong database, which is hard to notice when iterating over several databases on one instance.Reproduction
Expected
Either of these would remove the silent wrong answer:
arrow_odbcadapter already does this (itsbuild_connection_configcomposes the discrete fields and appendsconnection_stringas a suffix, with the precedence described in the docstring), so the two ODBC-style adapters would behave the same way.ValueError(orImproperConfigurationError) whenconnection_stringis combined with any connection-string-level field, naming the conflicting keys.Option 1 seems the friendlier of the two, provided the precedence is stated (an explicit field overriding the same key inside the string is the least surprising for the per-database case above).
Version
sqlspec 0.63.1; still present on
main.