]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
postgresql.psycopg2 dialect: Correctly handle complete absence of connection parameters. 4563/head
authorJulian Mehnle <julian@mehnle.net>
Thu, 21 Mar 2019 16:56:27 +0000 (16:56 +0000)
committerJulian Mehnle <julian@mehnle.net>
Thu, 21 Mar 2019 21:32:24 +0000 (21:32 +0000)
psycopg2/libpq will read connection parameters from environment variables, provided an empty (not-None) connection string is passed.
<https://www.postgresql.org/docs/current/libpq-envars.html>

Fixes: #4562
doc/build/core/engines.rst
lib/sqlalchemy/dialects/postgresql/psycopg2.py
test/dialect/postgresql/test_dialect.py

index a22b7f22b351064359288169c1a668e4d3bd8366..e67ae3e10bc2ffd97b1f3ab14c7214371092ca39 100644 (file)
@@ -102,6 +102,15 @@ also available as a pure-Python substitute::
     # pg8000
     engine = create_engine('postgresql+pg8000://scott:tiger@localhost/mydatabase')
 
+With the psycopg2 DBAPI, you can omit any connection parameters that are defined as
+`PG... environment variables <https://www.postgresql.org/docs/current/libpq-envars.html>`_.
+If *all* your connection parameters are defined as environment variables, you can
+specify an empty URL::
+
+    engine = create_engine('postgresql://')
+
+Again, this works only with the psycopg2 DBAPI.
+
 More notes on connecting to PostgreSQL at :ref:`postgresql_toplevel`.
 
 MySQL
index 8a15a8559308b598a98678786ee3641214465f5f..bba353235b9bf57a7d2ed6e75ec86d09702c1c3b 100644 (file)
@@ -85,6 +85,17 @@ using ``host`` as an additional keyword argument::
 
 .. _psycopg2_execution_options:
 
+Environment Connection Parameters
+----------------------------------
+
+psycopg2, via its underlying ``libpq`` client library, allows any connection
+parameters to be omitted that are defined as `PG... environment variables
+<https://www.postgresql.org/docs/current/libpq-envars.html>`_. If *all* your
+required connection parameters are defined as environment variables, you can
+specify an empty URL::
+
+    create_engine("postgresql+psycopg2://")
+
 Per-Statement/Connection Execution Options
 -------------------------------------------
 
@@ -735,10 +746,13 @@ class PGDialect_psycopg2(PGDialect):
 
     def create_connect_args(self, url):
         opts = url.translate_connect_args(username="user")
-        if "port" in opts:
-            opts["port"] = int(opts["port"])
-        opts.update(url.query)
-        return ([], opts)
+        if opts:
+            if "port" in opts:
+                opts["port"] = int(opts["port"])
+            opts.update(url.query)
+            return ([], opts)
+        else:
+            return ([''], opts)
 
     def is_disconnect(self, e, connection, cursor):
         if isinstance(e, self.dbapi.Error):
index cadcbdc1c04997a711f38483f5e25b0765033fbf..b55c78adffd52310c97ac8bd279879a8352c0816 100644 (file)
@@ -27,6 +27,7 @@ from sqlalchemy import testing
 from sqlalchemy import text
 from sqlalchemy import TypeDecorator
 from sqlalchemy.dialects.postgresql import base as postgresql
+from sqlalchemy.dialects.postgresql import psycopg2 as psycopg2_dialect
 from sqlalchemy.engine import engine_from_config
 from sqlalchemy.engine import url
 from sqlalchemy.testing import engines
@@ -114,6 +115,20 @@ class DialectTest(fixtures.TestBase):
         e = engine_from_config(config, _initialize=False)
         eq_(e.dialect.use_native_unicode, True)
 
+    def test_psycopg2_empty_connection_string(self):
+        dialect = psycopg2_dialect.dialect()
+        u = url.make_url("postgresql://")
+        cargs, cparams = dialect.create_connect_args(u)
+        assert cargs == ['']
+        assert cparams == {}
+
+    def test_psycopg2_nonempty_connection_string(self):
+        dialect = psycopg2_dialect.dialect()
+        u = url.make_url("postgresql://host")
+        cargs, cparams = dialect.create_connect_args(u)
+        assert cargs == []
+        assert cparams == {"host": "host"}
+
 
 class BatchInsertsTest(fixtures.TablesTest):
     __only_on__ = "postgresql+psycopg2"