oracle / python-cx_Oracle

Python interface to Oracle Database now superseded by python-oracledb
https://oracle.github.io/python-cx_Oracle
Other
886 stars 360 forks source link

Important cursor methods are unavailable when connected via self-defined class. #502

Closed bergen288 closed 3 years ago

bergen288 commented 3 years ago
  1. What versions are you using?

platform.platform: Windows-10-10.0.17763-SP0 sys.maxsize > 2**32: True platform.python_version: 3.8.2 cx_Oracle.version: 8.1.0 cx_Oracle.clientversion: (19, 6, 0, 0, 0)

  1. Is it an error or a hang or a crash? Important cursor methods are unavailable via self-defined class. Only dunders are available.
  2. What error(s) or behavior you are seeing? I wrote OracleDB class to connect to Oracle DB via cx_Oracle package.
    
    ora_config = {
            'host':         'jxppoezi-scan.onefiserv.net',
            'port':         2501,
            "user":         "riskread",
            "password":     "xxxxxxxx",
            'service':      'pcedidbx_jxppoezi'
            }

with OracleDB(ora_config) as conn: cursor = conn.cursor for attr in dir(cursor): print(attr)


Below is the output.  The 1st line is the connection.  As you can see, some important cursor methods (such as execute, fetchall, close) are not available.  I have a similar connect_oracle_db function which gives me the complete list of cursor methods.

Oracle ODBC Connection established: <cx_Oracle.Connection to riskread@jxppoezi-scan.onefiserv.net:2501/pcedidbx_jxppoezi> call class delattr dir doc eq format ge getattribute gt hash init init_subclass le lt module name ne new qualname reduce reduce_ex repr self setattr sizeof str subclasshook __text_signature__

<!--

Cut and paste text showing the command you ran.  No screenshots.

Use a gist for long screen output and logs: see https://gist.github.com/

-->

4. Include a runnable Python script that shows the problem.

Include all SQL needed to create the database schema.

Below is my OracleDB class:

class OracleDB: def init(self, config) -> None: self.configuration = config

def __enter__(self) -> 'conn':
    try:
        CONN_STR = '{user}/{password}@{host}:{port}/{service}'.format(**self.configuration)
        self.conn = cx_Oracle.connect(CONN_STR)
        # self.cursor = self.conn.cursor
        print('Oracle ODBC Connection established:',self.conn)
        return self.conn
    except cx_Oracle.InterfaceError as err:
        raise ConnectionError(err)
    except cx_Oracle.ProgrammingError as err:
        raise CredentialsError(err)

def __exit__(self, exc_type, exc_value, exc_trace) -> None:
    self.conn.commit()
    # self.cursor.close()
    self.conn.close()
    if exc_type is cx_Oracle.ProgrammingError:
        raise SQLError(exc_value)
    elif exc_type:
        raise exc_type(exc_value)
anthony-tuininga commented 3 years ago

Why do you think those methods should be available? Your class doesn't inherit anything from cx_Oracle so it will only have whatever it has defined itself.

bergen288 commented 3 years ago

Sorry, it's my fault. I missed (). It should be cursor = conn.cursor(). Now all missing methods are available.

Thanks.