]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- cx_Oracle.makedsn can now be passed service_name; squash
authorSławek Ehlert <slafs@op.pl>
Wed, 2 Apr 2014 17:45:53 +0000 (13:45 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 2 Apr 2014 17:45:53 +0000 (13:45 -0400)
commit of pr152

doc/build/changelog/changelog_10.rst
lib/sqlalchemy/dialects/oracle/cx_oracle.py
test/dialect/test_oracle.py

index ca0ae4d5260e3b0fc43e057db43a8f25fa2d0511..10d6dc786d9ceecaae3a9c94b91aac0e3a5b0e0f 100644 (file)
     series as well.  For changes that are specific to 1.0 with an emphasis
     on compatibility concerns, see :doc:`/changelog/migration_10`.
 
+    .. change::
+        :tags: feature, oracle
+        :pullreq: github:152
+
+        Added support for cx_oracle connections to a specific service 
+        name, as opposed to a tns name, by passing ``?service_name=<name>`` 
+        to the URL.  Pull request courtesy Sławomir Ehlert.
+
     .. change::
         :tags: feature, mysql
         :tickets: 3155
index 4a1ceecb155c6ec5ae2958bd9b4f9b4cdf20dcaf..4cd6fe63961f4218df376968b836ba3e1eabe3a2 100644 (file)
@@ -61,6 +61,12 @@ on the URL, or as keyword arguments to :func:`.create_engine()` are:
   Defaults to ``True``.  Note that this is the opposite default of the
   cx_Oracle DBAPI itself.
 
+* ``service_name`` - An option to use connection string (DSN) with
+  ``SERVICE_NAME`` instead of ``SID``. It can't be passed when a ``database``
+  part is given.
+  E.g. ``oracle+cx_oracle://scott:tiger@host:1521/?service_name=hr``
+  is a valid url. This value is only available as a URL query string argument.
+
 .. _cx_oracle_unicode:
 
 Unicode
@@ -862,14 +868,26 @@ class OracleDialect_cx_oracle(OracleDialect):
                 util.coerce_kw_type(dialect_opts, opt, bool)
                 setattr(self, opt, dialect_opts[opt])
 
-        if url.database:
+        database = url.database
+        service_name = dialect_opts.get('service_name', None)
+        if database or service_name:
             # if we have a database, then we have a remote host
             port = url.port
             if port:
                 port = int(port)
             else:
                 port = 1521
-            dsn = self.dbapi.makedsn(url.host, port, url.database)
+
+            if database and service_name:
+                raise exc.InvalidRequestError(
+                    '"service_name" option shouldn\'t '
+                    'be used with a "database" part of the url')
+            if database:
+                makedsn_kwargs = {'sid': database}
+            if service_name:
+                makedsn_kwargs = {'service_name': service_name}
+
+            dsn = self.dbapi.makedsn(url.host, port, **makedsn_kwargs)
         else:
             # we have a local tnsname
             dsn = url.host
index 1e50b90701662b73a823135e4b7b93c473fa77fe..3c67f15903c1c94e9fa8495a7c0ba13dbfc8fb6a 100644 (file)
@@ -2074,3 +2074,23 @@ class DBLinkReflectionTest(fixtures.TestBase):
                 autoload_with=testing.db, oracle_resolve_synonyms=True)
         eq_(list(t.c.keys()), ['id', 'data'])
         eq_(list(t.primary_key), [t.c.id])
+
+
+class ServiceNameTest(fixtures.TestBase):
+    __only_on__ = 'oracle+cx_oracle'
+
+    def test_cx_oracle_service_name(self):
+        url_string = 'oracle+cx_oracle://scott:tiger@host/?service_name=hr'
+        eng = create_engine(url_string, _initialize=False)
+        cargs, cparams = eng.dialect.create_connect_args(eng.url)
+
+        assert 'SERVICE_NAME=hr' in cparams['dsn']
+        assert 'SID=hr' not in cparams['dsn']
+
+    def test_cx_oracle_service_name_bad(self):
+        url_string = 'oracle+cx_oracle://scott:tiger@host/hr1?service_name=hr2'
+        assert_raises(
+            exc.InvalidRequestError,
+            create_engine, url_string,
+            _initialize=False
+        )