]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Support DNS-less connections for psycopg2
authorJulian Mehnle <julian@mehnle.net>
Thu, 21 Mar 2019 21:54:22 +0000 (17:54 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 24 Mar 2019 16:03:28 +0000 (12:03 -0400)
Added support for parameter-less connection URLs for the psycopg2 dialect,
meaning, the URL can be passed to :func:`.create_engine` as
``"postgresql+psycopg2://"`` with no additional arguments to indicate an
empty DSN passed to libpq, which indicates to connect to "localhost" with
no username, password, or database given. Pull request courtesy Julian
Mehnle.

Fixes: #4562
Closes: #4563
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/4563
Pull-request-sha: 8a05c96944a0523b06e9772cfe1832e500a43641

Change-Id: Ib6fca3c3c9eebeaf590d7f7fb0bc8cd4b6e4a55a

doc/build/changelog/unreleased_13/4562.rst [new file with mode: 0644]
lib/sqlalchemy/dialects/postgresql/psycopg2.py
test/dialect/postgresql/test_dialect.py

diff --git a/doc/build/changelog/unreleased_13/4562.rst b/doc/build/changelog/unreleased_13/4562.rst
new file mode 100644 (file)
index 0000000..bbf534c
--- /dev/null
@@ -0,0 +1,10 @@
+.. change::
+    :tags: feature, postgresql
+    :tickets: 4562
+
+    Added support for parameter-less connection URLs for the psycopg2 dialect,
+    meaning, the URL can be passed to :func:`.create_engine` as
+    ``"postgresql+psycopg2://"`` with no additional arguments to indicate an
+    empty DSN passed to libpq, which indicates to connect to "localhost" with
+    no username, password, or database given. Pull request courtesy Julian
+    Mehnle.
\ No newline at end of file
index 8a15a8559308b598a98678786ee3641214465f5f..199c1c776486aeeb41b7374abac074b0a422738f 100644 (file)
@@ -83,6 +83,33 @@ using ``host`` as an additional keyword argument::
     `PQconnectdbParams \
     <http://www.postgresql.org/docs/9.1/static/libpq-connect.html#LIBPQ-PQCONNECTDBPARAMS>`_
 
+Empty DSN Connections / Environment Variable Connections
+---------------------------------------------------------
+
+The psycopg2 DBAPI can connect to PostgreSQL by passing an empty DSN to the
+libpq client library, which by default indicates to connect to a localhost
+PostgreSQL database that is open for "trust" connections.  This behavior can be
+further tailored using a particular set of environment variables which are
+prefixed with ``PG_...``, which are  consumed by ``libpq`` to take the place of
+any or all elements of the connection string.
+
+For this form, the URL can be passed without any elements other than the
+initial scheme::
+
+    engine = create_engine('postgresql+psycopg2://')
+
+In the above form, a blank "dsn" string is passed to the ``psycopg2.connect()``
+function which in turn represents an empty DSN passed to libpq.
+
+.. versionadded:: 1.3.2 support for parameter-less connections with psycopg2.
+
+.. seealso::
+
+    `Environment Variables\
+    <https://www.postgresql.org/docs/current/libpq-envars.html>`_ -
+    PostgreSQL documentation on how to use ``PG_...``
+    environment variables for connections.
+
 .. _psycopg2_execution_options:
 
 Per-Statement/Connection Execution Options
@@ -735,10 +762,16 @@ 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)
+            # send individual dbname, user, password, host, port
+            # parameters to psycopg2.connect()
+            return ([], opts)
+        else:
+            # send a blank string for "dsn" to psycopg2.connect()
+            return ([''], opts)
 
     def is_disconnect(self, e, connection, cursor):
         if isinstance(e, self.dbapi.Error):
index cadcbdc1c04997a711f38483f5e25b0765033fbf..8c19e31bb3b1b90b19332fefb77b18da2469aa8e 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)
+        eq_(cargs, [''])
+        eq_(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)
+        eq_(cargs, [])
+        eq_(cparams, {"host": "host"})
+
 
 class BatchInsertsTest(fixtures.TablesTest):
     __only_on__ = "postgresql+psycopg2"