oracle / python-oracledb

Python driver for Oracle Database conforming to the Python DB API 2.0 specification. This is the renamed, new major release of cx_Oracle
https://oracle.github.io/python-oracledb
Other
307 stars 59 forks source link

DPY-4000 when using EZCONNECT syntax (which worked with 1.2.1) #352

Open hvbtup opened 2 days ago

hvbtup commented 2 days ago
  1. What versions are you using?

DB: Oracle Database 12c Standard Edition Release 12.2.0.1.0 - 64bit Production

Also run Python and show the output of ...:

platform.platform: Windows-2012ServerR2-6.3.9600-SP0 sys.maxsize > 2**32: True platform.python_version: 3.10.7

oracledb.version: 2.2.1

  1. Is it an error or a hang or a crash?

Crash

While this worked with oracledb-1.2.1. I only switched to 2.2.1 because I saw the exception from https://github.com/oracle/python-oracledb/issues/30 in a call to executemany with 1.2.1.

  1. What error(s) or behavior you are seeing?

    ... File "E:...\ROG\import_service\python\import_service.py", line 144, in connect self._conn = oracledb.connect(self.connect_string) File "E:...import_service\3rdParty\python-3.10\lib\site-packages\oracledb\connection.py", line 1158, in connect return conn_class(dsn=dsn, pool=pool, params=params, **kwargs) File "E:...\import_service\3rdParty\python-3.10\lib\site-packages\oracledb\connection.py", line 517, in init dsn = params_impl.process_args(dsn, kwargs, thin) File "src\oracledb\impl/base/connect_params.pyx", line 623, in oracledb.base_impl.ConnectParamsImpl.process_args File "src\oracledb\impl/base/connect_params.pyx", line 560, in oracledb.base_impl.ConnectParamsImpl.parse_connect_string File "src\oracledb\impl/base/connect_params.pyx", line 558, in oracledb.base_impl.ConnectParamsImpl.parse_connect_string File "src\oracledb\impl/base/connect_params.pyx", line 338, in oracledb.base_impl.ConnectParamsImpl._parse_connect_string File "E:...\import_service\3rdParty\python-3.10\lib\site-packages\oracledb\errors.py", line 182, in _raise_err raise error.exc_type(error) from cause oracledb.exceptions.DatabaseError: DPY-4000: unable to find "//rocket:1521/E122" in E:...\import_service\conf\tnsnames.ora

The application uses a string of the following form as self.connect_string:

username/password@//rocket:1521/E122

Username and password contain only ASCII letters.

  1. Does your application call init_oracle_client()?

No (Thin mode).

This is probably important:

The program just calls oracledb.connect(x) with a single string x of the form mentioned above.

The environment variable TNS_ADMIN is set and points to a directory with sqlnet.ora and tnsnames.ora. I know that these files are not necessary when using EZCONNECT syntax, but the program is written generic (also supports Thick Mode and TNS aliases).

Contents of tnsnames.ora:

TEST.world =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = oracle-db.local)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = TEST)
    )
  )

Contents of sqlnet.ora:

NAMES.DIRECTORY_PATH= (TNSNAMES,EZCONNECT)
  1. Include a runnable Python script that shows the problem.

Format code by using three backticks on a line before and after code snippets, for example:

import oracledb
import os
os.environ["TNS_ADMIN"] = r"E:\...\import_service\conf"
oracledb.connect("username/password@//rocket:1521/E122")
hvbtup commented 2 days ago

Of course you have to adapt the TNS_ADMIN path accordingly in order to test.

cjbj commented 1 day ago

This is a 'known feature' - I don't even remember it working at all, but guess it must have. Just this week we were talking about it, and the need for a better parser.

The solution is to remove the nominally-optional "//". Try oracledb.connect("username/password@rocket:1521/E122")

anthony-tuininga commented 1 day ago

It wouldn't have worked in thin mode at any time, but it would have (and still does) work in thick mode. The main reason it wouldn't have worked in thin mode is because I didn't even know about it until very recently. :-) As Chris mentioned, remove the "//" which shouldn't be there. Or add the protocol ("tcp:") before the "//". As Chris mentioned a better parser is being considered, but this is the least of the issues that needs to be resolved!

cjbj commented 1 day ago

Well, considering I used to favor & document the use of the optional '//', and it's part of the official syntax, I wouldn't go so far as to say it shouldn't be there!