From: brian z. <bz...@us...> - 2002-04-21 14:22:18
|
Update of /cvsroot/jython/jython/com/ziclix/python/sql In directory usw-pr-cvs1:/tmp/cvs-serv7571/com/ziclix/python/sql Modified Files: PyStatement.java PyCursor.java PyConnection.java Log Message: prepared statements can live outside the cursor Index: PyStatement.java =================================================================== RCS file: /cvsroot/jython/jython/com/ziclix/python/sql/PyStatement.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** PyStatement.java 19 Apr 2002 19:01:05 -0000 1.1 --- PyStatement.java 21 Apr 2002 14:22:15 -0000 1.2 *************** *** 258,261 **** --- 258,327 ---- /** + * Method prepare + * + * @param PyCursor cursor + * @param PyObject params + * @param PyObject bindings + * + * @throws SQLException + * + */ + void prepare(PyCursor cursor, PyObject params, PyObject bindings) throws SQLException { + + if ((params == Py.None) || (this.style == STATEMENT_STATIC)) { + return; + } + + // [3, 4] or (3, 4) + final DataHandler datahandler = cursor.datahandler; + int columns = 0, column = 0, index = params.__len__(); + final PreparedStatement preparedStatement = (PreparedStatement)statement; + final Procedure procedure = (this.style == STATEMENT_CALLABLE) ? (Procedure)this.sql : null; + + if (this.style != STATEMENT_CALLABLE) { + columns = params.__len__(); + + // clear the statement so all new bindings take affect only if not a callproc + // this is because Procedure already registered the OUT parameters and we + // don't want to lose those + preparedStatement.clearParameters(); + } else { + columns = (procedure.columns == Py.None) ? 0 : procedure.columns.__len__(); + } + + // count backwards through all the columns + while (columns-- > 0) { + column = columns + 1; + + if ((procedure != null) && (!procedure.isInput(column))) { + continue; + } + + // working from right to left + PyObject param = params.__getitem__(--index); + + if (bindings != Py.None) { + PyObject binding = bindings.__finditem__(Py.newInteger(index)); + + if (binding != null) { + try { + int bindingValue = binding.__int__().getValue(); + + datahandler.setJDBCObject(preparedStatement, column, param, bindingValue); + } catch (PyException e) { + throw zxJDBC.makeException(zxJDBC.ProgrammingError, zxJDBC.getString("bindingValue")); + } + + continue; + } + } + + datahandler.setJDBCObject(preparedStatement, column, param); + } + + return; + } + + /** * Method close * Index: PyCursor.java =================================================================== RCS file: /cvsroot/jython/jython/com/ziclix/python/sql/PyCursor.java,v retrieving revision 1.23 retrieving revision 1.24 diff -C2 -d -r1.23 -r1.24 *** PyCursor.java 19 Apr 2002 19:47:45 -0000 1.23 --- PyCursor.java 21 Apr 2002 14:22:15 -0000 1.24 *************** *** 66,72 **** protected PyStatement statement; - /** A set of statements which this cursor prepared and distributed. */ - protected Set preparedStatements; - // they are stateless instances, so we only need to instantiate it once private static DataHandler DATAHANDLER = null; --- 66,69 ---- *************** *** 107,111 **** this.datahandler = DATAHANDLER; this.dynamicFetch = dynamicFetch; - this.preparedStatements = new HashSet(3); // constructs the appropriate Fetch among other things --- 104,107 ---- *************** *** 281,285 **** dict.__setitem__("rsConcur", null); dict.__setitem__("rsType", null); - dict.__setitem__("preparedStatements", null); } --- 277,280 ---- *************** *** 303,315 **** try { this.clear(); ! ! for (Iterator i = this.preparedStatements.iterator(); i.hasNext(); ) { ! try { ! ((PyStatement)i.next()).close(); ! } catch (Throwable t) {} ! } ! ! this.preparedStatements.clear(); ! this.connection.unregister(this); } finally { this.closed = true; --- 298,302 ---- try { this.clear(); ! this.connection.remove(this); } finally { this.closed = true; *************** *** 494,499 **** // prepare the statement ! prepare(params, callableBindings, procedure); ! this.statement.execute(this); } else { throw zxJDBC.makeException(zxJDBC.NotSupportedError, zxJDBC.getString("noStoredProc")); --- 481,486 ---- // prepare the statement ! this.statement.prepare(this, params, callableBindings); ! this.execute(); } else { throw zxJDBC.makeException(zxJDBC.NotSupportedError, zxJDBC.getString("noStoredProc")); *************** *** 567,571 **** boolean hasParams = hasParams(params); ! PyStatement stmt = prepareStatement(sql, maxRows, hasParams); if (stmt == null) { --- 554,558 ---- boolean hasParams = hasParams(params); ! PyStatement stmt = this.prepareStatement(sql, maxRows, hasParams); if (stmt == null) { *************** *** 576,599 **** try { ! if (hasParams) { ! // if we have a sequence of sequences, let's run through them and finish ! if (isSeqSeq(params)) { ! // [(3, 4)] or [(3, 4), (5, 6)] ! for (int i = 0, len = params.__len__(); i < len; i++) { ! PyObject param = params.__getitem__(i); ! prepare(param, bindings, null); ! execute(); } } else { ! prepare(params, bindings, null); execute(); } - } else { - - // execute the sql string straight up - execute(); } } catch (PyException e) { --- 563,588 ---- try { ! synchronized (this.statement) { ! if (hasParams) { ! // if we have a sequence of sequences, let's run through them and finish ! if (isSeqSeq(params)) { ! // [(3, 4)] or [(3, 4), (5, 6)] ! for (int i = 0, len = params.__len__(); i < len; i++) { ! PyObject param = params.__getitem__(i); ! this.statement.prepare(this, param, bindings); ! this.execute(); ! } ! } else { ! this.statement.prepare(this, params, bindings); ! this.execute(); } } else { ! ! // execute the sql string straight up execute(); } } } catch (PyException e) { *************** *** 642,709 **** /** - * Properly prepare the parameters of a prepared statement. - * - * @param params - * @param bindings - * @param procedure - * - * @throws SQLException - * - */ - protected void prepare(PyObject params, final PyObject bindings, final Procedure procedure) throws SQLException { - - if (params == Py.None) { - return; - } - - // [3, 4] or (3, 4) - final PreparedStatement preparedStatement = (PreparedStatement)this.statement.statement; - int columns = 0, column = 0, index = params.__len__(); - - if (procedure == null) { - columns = params.__len__(); - - // clear the statement so all new bindings take affect only if not a callproc - // this is because Procedure already registered the OUT parameters and we - // don't want to lose those - preparedStatement.clearParameters(); - } else { - columns = (procedure.columns == Py.None) ? 0 : procedure.columns.__len__(); - } - - // count backwards through all the columns - while (columns-- > 0) { - column = columns + 1; - - if ((procedure != null) && (!procedure.isInput(column))) { - continue; - } - - // working from right to left - PyObject param = params.__getitem__(--index); - - if (bindings != Py.None) { - PyObject binding = bindings.__finditem__(Py.newInteger(index)); - - if (binding != null) { - try { - int bindingValue = binding.__int__().getValue(); - - this.datahandler.setJDBCObject(preparedStatement, column, param, bindingValue); - } catch (PyException e) { - throw zxJDBC.makeException(zxJDBC.ProgrammingError, zxJDBC.getString("bindingValue")); - } - - continue; - } - } - - this.datahandler.setJDBCObject(preparedStatement, column, param); - } - - return; - } - - /** * Fetch the next row of a query result set, returning a single sequence, * or None when no more data is available. --- 631,634 ---- *************** *** 780,784 **** // add to the set of statements which are leaving our control ! this.preparedStatements.add(s); return s; --- 705,709 ---- // add to the set of statements which are leaving our control ! this.connection.add(s); return s; *************** *** 875,879 **** // it underneath someone; we can check this by looking in the set try { ! if (this.dynamicFetch && (!this.preparedStatements.contains(this.statement))) { this.statement.close(); } --- 800,804 ---- // it underneath someone; we can check this by looking in the set try { ! if (this.dynamicFetch && (!this.connection.contains(this.statement))) { this.statement.close(); } Index: PyConnection.java =================================================================== RCS file: /cvsroot/jython/jython/com/ziclix/python/sql/PyConnection.java,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** PyConnection.java 19 Apr 2002 19:01:06 -0000 1.8 --- PyConnection.java 21 Apr 2002 14:22:15 -0000 1.9 *************** *** 34,38 **** /** Field cursors */ ! protected List cursors; /** Field __class__ */ --- 34,41 ---- /** Field cursors */ ! private Set cursors; ! ! /** Field statements */ ! private Set statements; /** Field __class__ */ *************** *** 64,68 **** m[4] = new PyString("nativesql"); __methods__ = new PyList(m); ! m = new PyObject[8]; m[0] = new PyString("autocommit"); m[1] = new PyString("dbname"); --- 67,71 ---- m[4] = new PyString("nativesql"); __methods__ = new PyList(m); ! m = new PyObject[9]; m[0] = new PyString("autocommit"); m[1] = new PyString("dbname"); *************** *** 72,76 **** m[5] = new PyString("__connection__"); m[6] = new PyString("__cursors__"); ! m[7] = new PyString("closed"); __members__ = new PyList(m); } --- 75,80 ---- m[5] = new PyString("__connection__"); m[6] = new PyString("__cursors__"); ! m[7] = new PyString("__statements__"); ! m[8] = new PyString("closed"); __members__ = new PyList(m); } *************** *** 86,91 **** this.closed = false; this.connection = connection; ! this.cursors = new LinkedList(); this.supportsTransactions = this.connection.getMetaData().supportsTransactions(); --- 90,96 ---- this.closed = false; + this.cursors = new HashSet(); this.connection = connection; ! this.statements = new HashSet(); this.supportsTransactions = this.connection.getMetaData().supportsTransactions(); *************** *** 200,204 **** return Py.java2py(this.connection); } else if ("__cursors__".equals(name)) { ! return Py.java2py(Collections.unmodifiableList(this.cursors)); } else if ("__methods__".equals(name)) { return __methods__; --- 205,211 ---- return Py.java2py(this.connection); } else if ("__cursors__".equals(name)) { ! return Py.java2py(Collections.unmodifiableSet(this.cursors)); ! } else if ("__statements__".equals(name)) { ! return Py.java2py(Collections.unmodifiableSet(this.statements)); } else if ("__methods__".equals(name)) { return __methods__; *************** *** 226,234 **** } synchronized (this.cursors) { // close the cursors ! for (int i = this.cursors.size() - 1; i >= 0; i--) { ! ((PyCursor)this.cursors.get(i)).close(); } --- 233,246 ---- } + // mark ourselves closed now so that any callbacks we + // get from closing down cursors and statements to not + // try and modify our internal sets + this.closed = true; + synchronized (this.cursors) { // close the cursors ! for (Iterator i = this.cursors.iterator(); i.hasNext(); ) { ! ((PyCursor)i.next()).close(); } *************** *** 236,245 **** } try { this.connection.close(); } catch (SQLException e) { throw zxJDBC.makeException(e); - } finally { - this.closed = true; } } --- 248,265 ---- } + synchronized (this.statements) { + + // close the cursors + for (Iterator i = this.statements.iterator(); i.hasNext(); ) { + ((PyStatement)i.next()).close(); + } + + this.statements.clear(); + } + try { this.connection.close(); } catch (SQLException e) { throw zxJDBC.makeException(e); } } *************** *** 370,374 **** PyCursor cursor = new PyExtendedCursor(this, dynamicFetch, rsType, rsConcur); ! cursors.add(cursor); return cursor; --- 390,394 ---- PyCursor cursor = new PyExtendedCursor(this, dynamicFetch, rsType, rsConcur); ! this.cursors.add(cursor); return cursor; *************** *** 376,387 **** /** ! * Unregister an open PyCursor. ! * * * @param cursor * */ ! void unregister(PyCursor cursor) { this.cursors.remove(cursor); } } --- 396,443 ---- /** ! * Remove an open PyCursor. * * @param cursor * */ ! void remove(PyCursor cursor) { ! ! if (closed) { ! return; ! } ! this.cursors.remove(cursor); + } + + /** + * Method register + * + * @param PyStatement statement + * + */ + void add(PyStatement statement) { + + if (closed) { + return; + } + + this.statements.add(statement); + } + + /** + * Method contains + * + * @param PyStatement statement + * + * @return boolean + * + */ + boolean contains(PyStatement statement) { + + if (closed) { + return false; + } + + return this.statements.contains(statement); } } |