From: brian z. <bz...@us...> - 2001-12-17 03:44:45
|
Update of /cvsroot/jython/jython/com/ziclix/python/sql In directory usw-pr-cvs1:/tmp/cvs-serv25308/ziclix/python/sql Modified Files: Fetch.java PyCursor.java PyExtendedCursor.java Added Files: Procedure.java Log Message: execution of procedures with no output works --- NEW FILE: Procedure.java --- /* * Jython Database Specification API 2.0 * * $Id: Procedure.java,v 1.1 2001/12/17 03:44:42 bzimmer Exp $ * * Copyright (c) 2001 brian zimmer <bz...@zi...> * */ package com.ziclix.python.sql; import java.sql.*; import org.python.core.*; /** * Class Procedure * * @author brian zimmer * @date $today.date$ * @author last modified by $Author: bzimmer $ * @date last modified on $Date: 2001/12/17 03:44:42 $ * @version $Revision: 1.1 $ * @copyright 2001 brian zimmer */ public class Procedure extends Object { /** Field COLUMN_TYPE */ protected static final int COLUMN_TYPE = 4; /** Field DATA_TYPE */ protected static final int DATA_TYPE = 5; /** Field PLACEHOLDER */ public static final PyObject PLACEHOLDER = new PyObject(); /** Field cursor */ protected PyCursor cursor; /** Field name */ protected PyObject name; /** Field columns */ protected PyObject columns; /** * Constructor Procedure * * @param PyCursor cursor an open cursor * @param PyObject name a string or tuple representing the name * */ public Procedure(PyCursor cursor, PyObject name) { this.cursor = cursor; this.name = name; } /** * Method prepareCall * * @return CallableStatement * * @throws SQLException * */ public CallableStatement prepareCall() throws SQLException { // prepare the statement CallableStatement statement = null; try { // fetch the column information fetchColumns(); // build the full call syntax String sqlString = buildSql(); statement = cursor.connection.connection.prepareCall(sqlString); // register the OUT parameters registerOutParameters(statement); } catch (SQLException e) { if (statement == null) { try { statement.close(); } catch (Exception ex) {} } throw e; } return statement; } /** * Construct a list of the params in the proper order for the .setXXX methods of * a PreparedStatement. In the special case for a CallableStatement, insert * Procedure.PLACEHOLDER to notify the cursor to skip the slot. * * @param params a non-None list of params * * @return PyObject a list of params with Procedure.PLACEHOLDER in index for all * non IN and INOUT parameters * */ public PyObject normalizeParams(PyObject params) { if (columns == Py.None) { throw zxJDBC.makeException(zxJDBC.ProgrammingError, "too many params for input"); } if (params == Py.None) { return Py.None; } int j = 0, plen = params.__len__(); PyList population = new PyList(); for (int i = 0, len = columns.__len__(); i < len; i++) { PyObject column = columns.__getitem__(i); int colType = column.__getitem__(COLUMN_TYPE).__int__().getValue(); switch (colType) { case DatabaseMetaData.procedureColumnIn : case DatabaseMetaData.procedureColumnInOut : if (j + 1 > plen) { throw zxJDBC.makeException(zxJDBC.ProgrammingError, "too few params for input, attempting [" + (j + 1) + "] found [" + plen + "]"); } population.append(params.__getitem__(j++)); break; default : population.append(PLACEHOLDER); break; } } if (j != plen) { throw zxJDBC.makeException(zxJDBC.ProgrammingError, "too many params for input"); } return population; } /** * Returns the call in the syntax: * * {? = call <procedure-name>(?, ?, ...)} * {call <procedure-name>(?, ?, ...)} * * As of now, all parameters variables are created and no support for named variable * calling is supported. * @return String * */ protected String buildSql() throws SQLException { int colParam = 0; int colReturn = 0; if (columns != Py.None) { for (int i = 0, len = columns.__len__(); i < len; i++) { PyObject column = columns.__getitem__(i); int colType = column.__getitem__(COLUMN_TYPE).__int__().getValue(); switch (colType) { case DatabaseMetaData.procedureColumnUnknown : throw zxJDBC.makeException(zxJDBC.NotSupportedError, "procedureColumnUnknown"); case DatabaseMetaData.procedureColumnResult : throw zxJDBC.makeException(zxJDBC.NotSupportedError, "procedureColumnResult"); // these go on the right hand side case DatabaseMetaData.procedureColumnIn : case DatabaseMetaData.procedureColumnInOut : case DatabaseMetaData.procedureColumnOut : colParam++; break; // these go on the left hand side case DatabaseMetaData.procedureColumnReturn : colReturn++; break; default : throw zxJDBC.makeException(zxJDBC.DataError, "unknown column type [" + colType + "]"); } } } StringBuffer sql = new StringBuffer("{"); if (colReturn > 0) { PyList list = new PyList(); for (; colReturn > 0; colReturn--) { list.append(Py.newString("?")); } sql.append(Py.newString(",").join(list)).append(" = "); } sql.append("call ").append(name).append("("); if (colParam > 0) { PyList list = new PyList(); for (; colParam > 0; colParam--) { list.append(Py.newString("?")); } sql.append(Py.newString(",").join(list)); } return sql.append(")}").toString(); } /** * Method registerOutParameters * * @param CallableStatement statement * * @throws SQLException * */ private final void registerOutParameters(CallableStatement statement) throws SQLException { if (columns == Py.None) { return; } for (int i = 0, len = columns.__len__(); i < len; i++) { PyObject column = columns.__getitem__(i); int colType = column.__getitem__(COLUMN_TYPE).__int__().getValue(); int dataType = column.__getitem__(DATA_TYPE).__int__().getValue(); switch (colType) { case DatabaseMetaData.procedureColumnIn : case DatabaseMetaData.procedureColumnInOut : case DatabaseMetaData.procedureColumnOut : case DatabaseMetaData.procedureColumnReturn : doRegister(statement, i + 1, colType, dataType); break; } } } /** * Method doRegister * * @param CallableStatement statement * @param int index * @param int colType * @param int dataType * * @throws SQLException * */ protected void doRegister(CallableStatement statement, int index, int colType, int dataType) throws SQLException { statement.registerOutParameter(index, dataType); } /** * Method fetchColumns * * @throws SQLException * */ protected void fetchColumns() throws SQLException { PyExtendedCursor pec = (PyExtendedCursor)cursor.connection.cursor(); try { pec.datahandler = this.cursor.datahandler; pec.procedurecolumns(Py.newString(""), Py.newString(""), name, Py.None); this.columns = pec.fetchall(); } finally { pec.close(); } } } Index: Fetch.java =================================================================== RCS file: /cvsroot/jython/jython/com/ziclix/python/sql/Fetch.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** Fetch.java 2001/11/20 04:55:18 1.1 --- Fetch.java 2001/12/17 03:44:42 1.2 *************** *** 83,87 **** /** ! * Method add * * @param ResultSet resultSet --- 83,87 ---- /** ! * Create the results after a successful execution and manages the result set. * * @param ResultSet resultSet *************** *** 91,95 **** /** ! * Method add * * @param ResultSet resultSet --- 91,98 ---- /** ! * Create the results after a successful execution and manages the result set. ! * Optionally takes a set of JDBC-indexed columns to automatically set to None ! * primarily to support getTypeInfo() which sets a column type of a number but ! * doesn't use the value so a driver is free to put anything it wants there. * * @param ResultSet resultSet *************** *** 100,103 **** --- 103,117 ---- /** + * Method add + * + * @param CallableStatement callableStatement + * @param Procedure procedure + * + */ + public void add(CallableStatement callableStatement, Procedure procedure) { + return; + } + + /** * Fetch the next row of a query result set, returning a single sequence, * or None when no more data is available. *************** *** 129,133 **** * @return a sequence of sequences from the result set, or None when no more data is available */ ! abstract public PyObject fetchall(); /** --- 143,157 ---- * @return a sequence of sequences from the result set, or None when no more data is available */ ! public final PyObject fetchall() { ! return doFetchall(); ! } ! ! /** ! * Method doFetchall ! * ! * @return PyObject ! * ! */ ! abstract protected PyObject doFetchall(); /** *************** *** 152,163 **** * @return a sequence of sequences from the result set, or None when no more data is available */ ! abstract public PyObject fetchmany(int size); /** * Move the result pointer to the next set if available. * * @return true if more sets exist, else None */ ! abstract public PyObject nextset(); /** --- 176,214 ---- * @return a sequence of sequences from the result set, or None when no more data is available */ ! public final PyObject fetchmany(int size) { ! return doFetchmany(size); ! } /** + * Method doFetchmany + * + * @param int size + * + * @return PyObject + * + */ + abstract protected PyObject doFetchmany(int size); + + /** * Move the result pointer to the next set if available. * * @return true if more sets exist, else None */ ! public final PyObject nextset() { ! return doNextset(); ! } ! ! /** ! * Method doNextset ! * ! * @return PyObject ! * ! */ ! abstract protected PyObject doNextset(); ! ! /** ! * Cleanup any resources. ! */ ! abstract public void close() throws SQLException; /** *************** *** 270,280 **** return this.description; } - - /** - * Cleanup any resources. - */ - public void close() throws SQLException { - return; - } } --- 321,324 ---- *************** *** 302,306 **** super(cursor); ! this.results = new ArrayList(); this.counter = -1; } --- 346,350 ---- super(cursor); ! this.results = new LinkedList(); this.counter = -1; } *************** *** 360,364 **** * @return a sequence of sequences from the result set, or None when no more data is available */ ! public PyObject fetchall() { return fetchmany(this.rowcount); } --- 404,408 ---- * @return a sequence of sequences from the result set, or None when no more data is available */ ! public PyObject doFetchall() { return fetchmany(this.rowcount); } *************** *** 385,389 **** * @return a sequence of sequences from the result set, or None when no more data is available */ ! public PyObject fetchmany(int size) { PyObject res = Py.None, current = Py.None; --- 429,433 ---- * @return a sequence of sequences from the result set, or None when no more data is available */ ! public PyObject doFetchmany(int size) { PyObject res = Py.None, current = Py.None; *************** *** 414,418 **** * @return true if more sets exist, else None */ ! public PyObject nextset() { PyObject next = Py.None; --- 458,462 ---- * @return true if more sets exist, else None */ ! public PyObject doNextset() { PyObject next = Py.None; *************** *** 501,504 **** --- 545,562 ---- /** + * Iterate the remaining contents of the ResultSet and return. + */ + public PyObject doFetchall() { + return fetch(0, true); + } + + /** + * Iterate up to size rows remaining in the ResultSet and return. + */ + public PyObject doFetchmany(int size) { + return fetch(size, false); + } + + /** * Internal use only. If <i>all</i> is true, return everything * that's left in the result set, otherwise return up to size. Fewer *************** *** 506,510 **** * the set. */ ! private PyObject fetchmany(int size, boolean all) { if (this.resultSet == null) { --- 564,568 ---- * the set. */ ! private PyObject fetch(int size, boolean all) { if (this.resultSet == null) { *************** *** 535,539 **** * Always returns None. */ ! public PyObject nextset() { return Py.None; } --- 593,597 ---- * Always returns None. */ ! public PyObject doNextset() { return Py.None; } *************** *** 551,568 **** this.resultSet = null; - } - - /** - * Iterate the remaining contents of the ResultSet and return. - */ - public PyObject fetchall() { - return fetchmany(0, true); - } - - /** - * Iterate up to size rows remaining in the ResultSet and return. - */ - public PyObject fetchmany(int size) { - return fetchmany(size, false); } } --- 609,612 ---- Index: PyCursor.java =================================================================== RCS file: /cvsroot/jython/jython/com/ziclix/python/sql/PyCursor.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** PyCursor.java 2001/12/16 05:01:27 1.9 --- PyCursor.java 2001/12/17 03:44:42 1.10 *************** *** 39,42 **** --- 39,45 ---- protected PyObject rowid; + /** Field updatecount */ + protected PyObject updatecount; + /** Field dynamicFetch */ protected boolean dynamicFetch; *************** *** 115,119 **** m[6] = new PyString("callproc"); __methods__ = new PyList(m); ! m = new PyObject[6]; m[0] = new PyString("arraysize"); m[1] = new PyString("rowcount"); --- 118,122 ---- m[6] = new PyString("callproc"); __methods__ = new PyList(m); ! m = new PyObject[7]; m[0] = new PyString("arraysize"); m[1] = new PyString("rowcount"); *************** *** 122,125 **** --- 125,129 ---- m[4] = new PyString("warnings"); m[5] = new PyString("rowid"); + m[6] = new PyString("updatecount"); __members__ = new PyList(m); } *************** *** 173,176 **** --- 177,182 ---- } else if ("rowid".equals(name)) { return rowid; + } else if ("updatecount".equals(name)) { + return updatecount; } else if ("datahandler".equals(name)) { return Py.java2py(this.datahandler); *************** *** 312,316 **** * through the standard fetchXXX() methods. */ ! public void callproc(String sqlString, PyObject params, PyObject bindings, PyObject maxRows) { clear(); --- 318,322 ---- * through the standard fetchXXX() methods. */ ! public void callproc(PyObject name, PyObject params, PyObject bindings, PyObject maxRows) { clear(); *************** *** 318,328 **** try { if (getMetaData().supportsStoredProcedures()) { ! this.sqlStatement = this.connection.connection.prepareCall(sqlString); if (maxRows != Py.None) { this.sqlStatement.setMaxRows(maxRows.__int__().getValue()); } ! execute(params, bindings); } else { throw zxJDBC.makeException(zxJDBC.NotSupportedError, zxJDBC.getString("noStoredProc")); --- 324,352 ---- try { if (getMetaData().supportsStoredProcedures()) { ! if (isSeqSeq(params)) { ! throw zxJDBC.makeException(zxJDBC.NotSupportedError, "sequence of sequences is not supported"); ! } + final Procedure procedure = new Procedure(this, name); + + this.sqlStatement = procedure.prepareCall(); + if (maxRows != Py.None) { this.sqlStatement.setMaxRows(maxRows.__int__().getValue()); } ! params = procedure.normalizeParams(params); ! ! prepare(params, bindings); ! execute(new ExecuteSQL() { ! ! public void executeSQL() throws SQLException { ! ! final CallableStatement callableStatement = (CallableStatement)sqlStatement; ! ! callableStatement.execute(); ! fetch.add(callableStatement, procedure); ! } ! }); } else { throw zxJDBC.makeException(zxJDBC.NotSupportedError, zxJDBC.getString("noStoredProc")); *************** *** 390,393 **** --- 414,426 ---- if (hasParams) { + ExecuteSQL esql = new ExecuteSQL() { + + public void executeSQL() throws SQLException { + + if (((PreparedStatement)sqlStatement).execute()) { + fetch.add(sqlStatement.getResultSet()); + } + } + }; // if we have a sequence of sequences, let's run through them and finish *************** *** 398,405 **** PyObject param = params.__getitem__(i); ! execute(param, bindings); } } else { ! execute(params, bindings); } } else { --- 431,440 ---- PyObject param = params.__getitem__(i); ! prepare(param, bindings); ! execute(esql); } } else { ! prepare(params, bindings); ! execute(esql); } } else { *************** *** 411,415 **** if (sqlStatement.execute(sqlString)) { ! create(sqlStatement.getResultSet()); } } --- 446,450 ---- if (sqlStatement.execute(sqlString)) { ! fetch.add(sqlStatement.getResultSet()); } } *************** *** 439,442 **** --- 474,478 ---- this.rowid = this.datahandler.getRowId(this.sqlStatement); + this.updatecount = Py.newInteger(this.sqlStatement.getUpdateCount()); addWarning(this.sqlStatement.getWarnings()); *************** *** 445,450 **** /** ! * The workhorse for properly preparing the parameters and executing a ! * prepared statement. * * @param PyObject params a non-None seq of sequences or entities --- 481,485 ---- /** ! * Properly prepare the parameters of a prepared statement. * * @param PyObject params a non-None seq of sequences or entities *************** *** 454,459 **** * */ ! protected void execute(PyObject params, PyObject bindings) throws SQLException { // [3, 4] or (3, 4) final PreparedStatement preparedStatement = (PreparedStatement)this.sqlStatement; --- 489,498 ---- * */ ! protected void prepare(PyObject params, PyObject bindings) throws SQLException { + if (params == Py.None) { + return; + } + // [3, 4] or (3, 4) final PreparedStatement preparedStatement = (PreparedStatement)this.sqlStatement; *************** *** 465,468 **** --- 504,511 ---- PyObject param = params.__getitem__(i); + if (param == Procedure.PLACEHOLDER) { + continue; + } + if (bindings != Py.None) { PyObject binding = bindings.__finditem__(Py.newInteger(i)); *************** *** 486,499 **** } - execute(new ExecuteSQL() { - - public void executeSQL() throws SQLException { - - if (preparedStatement.execute()) { - create(preparedStatement.getResultSet()); - } - } - }); - return; } --- 529,532 ---- *************** *** 561,586 **** /** - * Create the results after a successful execution and manages the result set. - * - * @param rs A ResultSet. - */ - protected void create(ResultSet rs) { - create(rs, null); - } - - /** - * Create the results after a successful execution and manages the result set. - * Optionally takes a set of JDBC-indexed columns to automatically set to None - * primarily to support getTypeInfo() which sets a column type of a number but - * doesn't use the value so a driver is free to put anything it wants there. - * - * @param rs A ResultSet. - * @param skipCols set of JDBC-indexed columns to automatically set as None - */ - protected void create(ResultSet rs, Set skipCols) { - this.fetch.add(rs, skipCols); - } - - /** * Adds a warning to the tuple and will follow the chain as necessary. */ --- 594,597 ---- *************** *** 621,624 **** --- 632,636 ---- this.warnings = Py.None; this.rowid = Py.None; + this.updatecount = Py.newInteger(-1); try { *************** *** 807,811 **** case 8 : ! cursor.callproc(arg.__str__().toString(), Py.None, Py.None, Py.None); return Py.None; --- 819,823 ---- case 8 : ! cursor.callproc(arg, Py.None, Py.None, Py.None); return Py.None; *************** *** 845,849 **** case 8 : ! cursor.callproc(arga.__str__().toString(), argb, Py.None, Py.None); return Py.None; --- 857,861 ---- case 8 : ! cursor.callproc(arga, argb, Py.None, Py.None); return Py.None; *************** *** 881,885 **** case 8 : ! cursor.callproc(arga.__str__().toString(), argb, argc, Py.None); return Py.None; --- 893,897 ---- case 8 : ! cursor.callproc(arga, argb, argc, Py.None); return Py.None; *************** *** 908,912 **** PyCursor cursor = (PyCursor)__self__; PyArgParser parser = new PyArgParser(args, keywords); ! String sql = parser.arg(0).__str__().toString(); PyObject params = parser.kw("params", Py.None); PyObject bindings = parser.kw("bindings", Py.None); --- 920,924 ---- PyCursor cursor = (PyCursor)__self__; PyArgParser parser = new PyArgParser(args, keywords); ! PyObject sql = parser.arg(0); PyObject params = parser.kw("params", Py.None); PyObject bindings = parser.kw("bindings", Py.None); *************** *** 920,924 **** case 5 : ! cursor.execute(sql, params, bindings, maxrows); return Py.None; --- 932,936 ---- case 5 : ! cursor.execute(sql.__str__().toString(), params, bindings, maxrows); return Py.None; *************** *** 930,934 **** case 9 : ! cursor.executemany(sql, params, bindings, maxrows); return Py.None; --- 942,946 ---- case 9 : ! cursor.executemany(sql.__str__().toString(), params, bindings, maxrows); return Py.None; Index: PyExtendedCursor.java =================================================================== RCS file: /cvsroot/jython/jython/com/ziclix/python/sql/PyExtendedCursor.java,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** PyExtendedCursor.java 2001/12/12 17:19:45 1.5 --- PyExtendedCursor.java 2001/12/17 03:44:42 1.6 *************** *** 44,48 **** static { ! PyObject[] m = new PyObject[7]; m[0] = new PyString("tables"); --- 44,48 ---- static { ! PyObject[] m = new PyObject[9]; m[0] = new PyString("tables"); *************** *** 53,56 **** --- 53,58 ---- m[5] = new PyString("procedurecolumns"); m[6] = new PyString("statistics"); + m[7] = new PyString("bestrow"); + m[8] = new PyString("versioncolumns"); __methods__ = new PyList(m); *************** *** 111,114 **** --- 113,118 ---- dict.__setitem__("gettypeinfo", new ExtendedCursorFunc("gettypeinfo", 107, 0, 1, "query for sql type info")); dict.__setitem__("gettabletypeinfo", new ExtendedCursorFunc("gettabletypeinfo", 108, 0, 1, "query for table types")); + dict.__setitem__("bestrow", new ExtendedCursorFunc("bestrow", 109, 4, 4, "query for table types")); + dict.__setitem__("versioncolumns", new ExtendedCursorFunc("versioncolumns", 110, 3, 3, "query for table types")); // hide from python *************** *** 169,173 **** try { ! create(getMetaData().getTables(q, o, t, y)); } catch (SQLException e) { throw zxJDBC.newError(e); --- 173,177 ---- try { ! this.fetch.add(getMetaData().getTables(q, o, t, y)); } catch (SQLException e) { throw zxJDBC.newError(e); *************** *** 193,197 **** try { ! create(getMetaData().getColumns(q, o, t, c)); } catch (SQLException e) { throw zxJDBC.newError(e); --- 197,201 ---- try { ! this.fetch.add(getMetaData().getColumns(q, o, t, c)); } catch (SQLException e) { throw zxJDBC.newError(e); *************** *** 215,219 **** try { ! create(getMetaData().getProcedures(q, o, p)); } catch (SQLException e) { throw zxJDBC.newError(e); --- 219,223 ---- try { ! this.fetch.add(getMetaData().getProcedures(q, o, p)); } catch (SQLException e) { throw zxJDBC.newError(e); *************** *** 239,243 **** try { ! create(getMetaData().getProcedureColumns(q, o, p, c)); } catch (SQLException e) { throw zxJDBC.newError(e); --- 243,247 ---- try { ! this.fetch.add(getMetaData().getProcedureColumns(q, o, p, c)); } catch (SQLException e) { throw zxJDBC.newError(e); *************** *** 262,266 **** try { ! create(getMetaData().getPrimaryKeys(q, o, t)); } catch (SQLException e) { throw zxJDBC.newError(e); --- 266,270 ---- try { ! this.fetch.add(getMetaData().getPrimaryKeys(q, o, t)); } catch (SQLException e) { throw zxJDBC.newError(e); *************** *** 295,299 **** try { ! create(getMetaData().getCrossReference(pq, po, pt, fq, fo, ft)); } catch (SQLException e) { throw zxJDBC.newError(e); --- 299,303 ---- try { ! this.fetch.add(getMetaData().getCrossReference(pq, po, pt, fq, fo, ft)); } catch (SQLException e) { throw zxJDBC.newError(e); *************** *** 326,330 **** try { ! create(getMetaData().getIndexInfo(q, o, t, u, a), skipCols); } catch (SQLException e) { throw zxJDBC.newError(e); --- 330,334 ---- try { ! this.fetch.add(getMetaData().getIndexInfo(q, o, t, u, a), skipCols); } catch (SQLException e) { throw zxJDBC.newError(e); *************** *** 347,351 **** try { ! create(getMetaData().getTypeInfo(), skipCols); } catch (SQLException e) { throw zxJDBC.newError(e); --- 351,355 ---- try { ! this.fetch.add(getMetaData().getTypeInfo(), skipCols); } catch (SQLException e) { throw zxJDBC.newError(e); *************** *** 375,383 **** try { ! create(getMetaData().getTableTypes()); } catch (SQLException e) { throw zxJDBC.newError(e); } } } --- 379,435 ---- try { ! this.fetch.add(getMetaData().getTableTypes()); ! } catch (SQLException e) { ! throw zxJDBC.newError(e); ! } ! } ! ! /** ! * Gets a description of a table's optimal set of columns that uniquely ! * identifies a row. They are ordered by SCOPE. ! * ! * @param qualifier ! * @param owner ! * @param table ! */ ! protected void bestrow(PyObject qualifier, PyObject owner, PyObject table) { ! ! clear(); ! ! String c = datahandler.getMetaDataName(qualifier); ! String s = datahandler.getMetaDataName(owner); ! String t = datahandler.getMetaDataName(table); ! int p = DatabaseMetaData.bestRowUnknown; // scope ! boolean n = true; // nullable ! ! try { ! this.fetch.add(getMetaData().getBestRowIdentifier(c, s, t, p, n)); } catch (SQLException e) { throw zxJDBC.newError(e); } } + + /** + * Gets a description of a table's columns that are automatically + * updated when any value in a row is updated. They are unordered. + * + * @param qualifier a schema name + * @param owner an owner name + * @param table a table name + */ + protected void versioncolumns(PyObject qualifier, PyObject owner, PyObject table) { + + clear(); + + String q = datahandler.getMetaDataName(qualifier); + String o = datahandler.getMetaDataName(owner); + String t = datahandler.getMetaDataName(table); + + try { + this.fetch.add(getMetaData().getVersionColumns(q, o, t)); + } catch (SQLException e) { + throw zxJDBC.newError(e); + } + } } *************** *** 494,497 **** --- 546,559 ---- case 104 : cursor.procedures(arga, argb, argc); + + return Py.None; + + case 109 : + cursor.bestrow(arga, argb, argc); + + return Py.None; + + case 110 : + cursor.versioncolumns(arga, argb, argc); return Py.None; |