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
336 stars 67 forks source link

Detect, undo, and forget setinputsizes() on cursor #411

Open deonav opened 2 days ago

deonav commented 2 days ago

If setinputsizes is not called, then one can reuse the cursor for different SQL statements without problems like so

cur.execute("select :a, :b from dual", a="foo", b="bar")
cur.execute("select :c from dual", c=999)

If it is called, however, then an exception may be raised. Consider

cur.execute("select :a, :b from dual", a="foo", b="bar")
cur.setinputsizes(**cur.bindvars)
cur.execute("select :c from dual", c=999)

>> DPY-4008: no bind placeholder named ":a" was found in the SQL text

There doesn't appear to be any way to undo this, for example

cur.execute("select :a, :b from dual", a="foo", b="bar")
cur.setinputsizes(**cur.bindvars)

# attempt to reset
cur.setinputsizes()

cur.execute("select :c from dual", c=999)

>> DPY-4008: no bind placeholder named ":a" was found in the SQL text

If we could detect if setinputsizes were called, and if the empty call setinputsizes() would have it forget, then we could safely reuse cursors in procedural programming, such as

def foo(cur):
    if cur.inputsizes_called:
        oldvars = cur.bindvars.copy()
        cur.setinputsizes() # reset
        cur.execute(...)
        if isinstance(oldvars, list): 
            cur.setinputsizes(*oldvars) # restore
        elif isinstance(oldvars, dict): 
            cur.setinputsizes(**oldvars)
    else:
        cur.execute(...)

Alternatively, the cursor could detect if a different sql statement (string id) were used and then forget on its own.

cjbj commented 1 day ago

@deonav thanks for the suggestions.

anthony-tuininga commented 1 day ago

I have pushed a patch that adds the requested support and have initated a build from which you can download pre-built development wheels once it completes. You can also build from source if you prefer.