From: Mike Bayer Date: Mon, 25 Jan 2021 18:22:34 +0000 (-0500) Subject: Add more docs on engine connecting w/ URL parameters X-Git-Tag: rel_1_3_23~5 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ce81f016fbc599e5773a253e9c919ea90d192313;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Add more docs on engine connecting w/ URL parameters We have a special section for connect_args but didn't appropriately introduce that URL keywords may be used as well, which otherwise does not seem to be documented in a generalized way. Add this additional detail and contrast between URL query string and connect_args including providing some transparency for how to see what URL query string parameters will do for a given dialect, as we do not handle these parameters consistently right now. Change-Id: I2227554732e307d4b525a9931e8d03ccc2c16726 References: #5874 (cherry picked from commit 57db20a187e80950037dd5a2141a560fe879e054) --- diff --git a/doc/build/core/engines.rst b/doc/build/core/engines.rst index 0f3b92c89c..c8a57ee7b1 100644 --- a/doc/build/core/engines.rst +++ b/doc/build/core/engines.rst @@ -233,14 +233,62 @@ are described in the following sub-sections. Special Keyword Arguments Passed to dbapi.connect() --------------------------------------------------- -For special arguments that must be passed to the DBAPI for which the -SQLAlchemy dialect does not parse from the query string correctly, -the :paramref:`_sa.create_engine.connect_args` dictionary can be used. -This is often when special sub-structures or objects must be passed to -the DBAPI, or sometimes it's just that a particular flag must be sent as +All Python DBAPIs accept additional arguments beyond the basics of connecting. +Common parameters include those to specify character set encodings and timeout +values; more complex data includes special DBAPI constants and objects and SSL +sub-parameters. There are two rudimentary means of passing these arguments +without complexity. + +Add Parameters to the URL Query string +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Simple string values, as well as some numeric values and boolean flags, may be +often specified in the query string of the URL directly. A common example of +this is DBAPIs that accept an argument ``encoding`` for character encodings, +such as most MySQL DBAPIs:: + + engine = create_engine( + "mysql+pymysql://user:pass@host/test?charset=utf8mb4" + ) + +The advantage of using the query string is that additional DBAPI options may be +specified in configuration files in a manner that's portable to the DBAPI +specified in the URL. The specific parameters passed through at this level vary +by SQLAlchemy dialect. Some dialects pass all arguments through as strings, +while others will parse for specific datatypes and move parameters to different +places, such as into driver-level DSNs and connect strings. As per-dialect +behavior in this area currently varies, the dialect documentation should be +consulted for the specific dialect in use to see if particular parameters are +supported at this level. + +.. tip:: + + A general technique to display the exact arguments passed to the DBAPI + for a given URL may be performed using the :meth:`.Dialect.create_connect_args` + method directly as follows:: + + >>> from sqlalchemy import create_engine + >>> engine = create_engine("mysql+pymysql://some_user:some_pass@some_host/test?charset=utf8mb4") + >>> args, kwargs = engine.dialect.create_connect_args(engine.url) + >>> args, kwargs + ([], {'host': 'some_host', 'database': 'test', 'user': 'some_user', 'password': 'some_pass', 'charset': 'utf8mb4', 'client_flag': 2}) + + The above ``args, kwargs`` pair is normally passed to the DBAPI as + ``dbapi.connect(*args, **kwargs)``. + +Use the connect_args dictionary parameter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A more general system of passing any parameter to the ``dbapi.connect()`` +function that is guaranteed to pass all parameters at all times is the +:paramref:`_sa.create_engine.connect_args` dictionary parameter. This may be +used for parameters that are otherwise not handled by the dialect when added to +the query string, as well as when special sub-structures or objects must be +passed to the DBAPI. Sometimes it's just that a particular flag must be sent as the ``True`` symbol and the SQLAlchemy dialect is not aware of this keyword -argument. Below illustrates the use of a psycopg2 "connection factory" -that replaces the underlying implementation the connection:: +argument to coerce it from its string form as presented in the URL. Below +illustrates the use of a psycopg2 "connection factory" that replaces the +underlying implementation the connection:: engine = create_engine( @@ -248,15 +296,26 @@ that replaces the underlying implementation the connection:: connect_args={"connection_factory": MyConnectionFactory} ) +Another example is the pyodbc "timeout" parameter:: + + engine = create_engine( + "mssql+pyodbc://user:pass@sqlsrvr?driver=ODBC+Driver+13+for+SQL+Server", + connect_args={"timeout": 30} + ) + +The above example also illustrates that both URL "query string" parameters as +well as :paramref:`_sa.create_engine.connect_args` may be used at the same +time; in the case of pyodbc, the "driver" keyword has special meaning +within the URL. Controlling how parameters are passed to the DBAPI connect() function --------------------------------------------------------------------- -At the next level, we can customize how the DBAPI ``connect()`` function -itself is called using the :meth:`.DialectEvents.do_connect` event hook. -This hook is passed the full ``*args, **kwargs`` that the dialect would -send to ``connect()``. These collections can then be modified in place -to alter how they are used:: +Beyond manipulating the parameters passed to ``connect()``, we can further +customize how the DBAPI ``connect()`` function itself is called using the +:meth:`.DialectEvents.do_connect` event hook. This hook is passed the full +``*args, **kwargs`` that the dialect would send to ``connect()``. These +collections can then be modified in place to alter how they are used:: from sqlalchemy import event