From: brian z. <bz...@us...> - 2002-01-14 04:28:44
|
Update of /cvsroot/jython/jython/com/ziclix/python/sql In directory usw-pr-cvs1:/tmp/cvs-serv20896/com/ziclix/python/sql Modified Files: Fetch.java PyCursor.java Log Message: added .scroll() and .rownumber Index: Fetch.java =================================================================== RCS file: /cvsroot/jython/jython/com/ziclix/python/sql/Fetch.java,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** Fetch.java 2002/01/11 21:46:01 1.6 --- Fetch.java 2002/01/14 04:28:41 1.7 *************** *** 39,45 **** abstract public class Fetch { ! /** Field rowcount */ protected int rowcount; /** Field cursor */ protected PyCursor cursor; --- 39,54 ---- abstract public class Fetch { ! /** ! * The total number of rows in the result set. ! * ! * Note: since JDBC provides no means to get this information without iterating ! * the entire result set, only those fetches which build the result statically ! * will have an accurate row count. ! */ protected int rowcount; + /** The current row of the cursor (-1 if off either end). */ + protected int rownumber; + /** Field cursor */ protected PyCursor cursor; *************** *** 57,60 **** --- 66,70 ---- this.rowcount = -1; + this.rownumber = -1; this.cursor = cursor; this.description = Py.None; *************** *** 171,174 **** --- 181,208 ---- /** + * Scroll the cursor in the result set to a new position according + * to mode. + * + * If mode is 'relative' (default), value is taken as offset to + * the current position in the result set, if set to 'absolute', + * value states an absolute target position. + * + * An IndexError should be raised in case a scroll operation would + * leave the result set. In this case, the cursor position is left + * undefined (ideal would be to not move the cursor at all). + * + * Note: This method should use native scrollable cursors, if + * available, or revert to an emulation for forward-only + * scrollable cursors. The method may raise NotSupportedErrors to + * signal that a specific operation is not supported by the + * database (e.g. backward scrolling). + * + * @param int value + * @param String mode + * + */ + public abstract void scroll(int value, String mode); + + /** * Cleanup any resources. */ *************** *** 385,404 **** return tuple; } - - /** - * Return the total row count. Note: since JDBC provides no means to get this information - * without iterating the entire result set, only those fetches which build the result - * statically will have an accurate row count. - */ - public int getRowCount() { - return this.rowcount; - } - - /** - * Return the description of the result. - */ - public PyObject getDescription() { - return this.description; - } } --- 419,422 ---- *************** *** 412,418 **** class StaticFetch extends Fetch { - /** Field counter */ - protected int counter; - /** Field results */ protected List results; --- 430,433 ---- *************** *** 431,435 **** this.results = new LinkedList(); this.descriptions = new LinkedList(); - this.counter = -1; } --- 446,449 ---- *************** *** 458,469 **** PyObject result = this.createResults(resultSet, skipCols, metadata); ! this.results.add(result); ! this.descriptions.add(metadata); ! // we want the rowcount of the first result set ! this.rowcount = ((PyObject)this.results.get(0)).__len__(); ! // we want the description of the first result set ! this.description = ((PyObject)this.descriptions.get(0)); } } catch (PyException e) { --- 472,488 ---- PyObject result = this.createResults(resultSet, skipCols, metadata); ! if (result.__len__() > 0) { ! this.results.add(result); ! this.descriptions.add(metadata); ! // we want the rowcount of the first result set ! this.rowcount = ((PyObject)this.results.get(0)).__len__(); ! // we want the description of the first result set ! this.description = ((PyObject)this.descriptions.get(0)); ! ! // set the current rownumber ! this.rownumber = 0; ! } } } catch (PyException e) { *************** *** 491,503 **** PyObject result = this.createResults(callableStatement, procedure, params); ! if (result != Py.None) { this.results.add(result); this.descriptions.add(this.createDescription(procedure)); // we want the description of the first result set this.description = ((PyObject)this.descriptions.get(0)); ! // we want the rowcount of the first result set ! this.rowcount = ((PyObject)this.results.get(0)).__len__(); } } catch (PyException e) { --- 510,525 ---- PyObject result = this.createResults(callableStatement, procedure, params); ! if ((result != Py.None) && (result.__len__() > 0)) { this.results.add(result); this.descriptions.add(this.createDescription(procedure)); + // we want the rowcount of the first result set + this.rowcount = ((PyObject)this.results.get(0)).__len__(); + // we want the description of the first result set this.description = ((PyObject)this.descriptions.get(0)); ! // set the current rownumber ! this.rownumber = 0; } } catch (PyException e) { *************** *** 557,565 **** } ! if ((counter + 1) < this.rowcount) { ! int start = counter + 1; ! ! counter += size; ! res = current.__getslice__(Py.newInteger(start), Py.newInteger(counter + 1), Py.newInteger(1)); } --- 579,585 ---- } ! if (this.rownumber < this.rowcount) { ! res = current.__getslice__(Py.newInteger(this.rownumber), Py.newInteger(this.rownumber + size), Py.newInteger(1)); ! this.rownumber += size; } *************** *** 568,571 **** --- 588,617 ---- /** + * Method scroll + * + * @param int value + * @param String mode 'relative' or 'absolute' + * + */ + public void scroll(int value, String mode) { + + int pos; + + if ("relative".equals(mode)) { + pos = this.rownumber + value; + } else if ("absolute".equals(mode)) { + pos = value; + } else { + throw zxJDBC.makeException(zxJDBC.ProgrammingError, "invalid cursor scroll mode [" + mode + "]"); + } + + if ((pos >= 0) && (pos < this.rowcount)) { + this.rownumber = pos; + } else { + throw zxJDBC.makeException(Py.IndexError, "cursor index [" + pos + "] out of range"); + } + } + + /** * Move the result pointer to the next set if available. * *************** *** 583,587 **** this.description = (PyObject)this.descriptions.get(0); this.rowcount = next.__len__(); ! this.counter = -1; } --- 629,633 ---- this.description = (PyObject)this.descriptions.get(0); this.rowcount = next.__len__(); ! this.rownumber = 0; } *************** *** 594,598 **** public void close() throws SQLException { ! this.counter = -1; this.results.clear(); --- 640,644 ---- public void close() throws SQLException { ! this.rownumber = -1; this.results.clear(); *************** *** 654,657 **** --- 700,709 ---- this.resultSet = resultSet; this.skipCols = skipCols; + + // it would be more compliant if we knew the resultSet actually + // contained some rows, but since we don't make a stab at it so + // everything else looks better + this.rowcount = 0; + this.rownumber = 0; } } catch (PyException e) { *************** *** 671,675 **** */ public void add(CallableStatement callableStatement, Procedure procedure, PyObject params) { ! return; } --- 723,727 ---- */ public void add(CallableStatement callableStatement, Procedure procedure, PyObject params) { ! throw zxJDBC.makeException(zxJDBC.NotSupportedError, "dynamic cursor does not support callproc(); use static cursors instead"); } *************** *** 710,715 **** res.append(tuple); ! // since the rowcount == -1 initially, bump it to one the first time through ! this.rowcount = (this.rowcount == -1) ? 1 : this.rowcount + 1; } } catch (PyException e) { --- 762,768 ---- res.append(tuple); ! this.rowcount++; ! ! this.rownumber = this.resultSet.getRow(); } } catch (PyException e) { *************** *** 730,733 **** --- 783,831 ---- /** + * Method scroll + * + * @param int value + * @param String mode + * + */ + public void scroll(int value, String mode) { + + try { + int type = this.resultSet.getType(); + + if ((type == ResultSet.TYPE_SCROLL_SENSITIVE) || (type == ResultSet.TYPE_SCROLL_INSENSITIVE)) { + if ("relative".equals(mode)) { + if (value < 0) { + value = Math.abs(this.rownumber + value); + } else if (value > 0) { + value = this.rownumber + value + 1; + } + } else if ("absolute".equals(mode)) { + if (value < 0) { + throw zxJDBC.makeException(Py.IndexError, "cursor index [" + value + "] out of range"); + } + } else { + throw zxJDBC.makeException(zxJDBC.ProgrammingError, "invalid cursor scroll mode [" + mode + "]"); + } + + if (value == 0) { + this.resultSet.beforeFirst(); + } else { + if (!this.resultSet.absolute(value)) { + throw zxJDBC.makeException(Py.IndexError, "cursor index [" + value + "] out of range"); + } + } + + // since .rownumber is the *next* row, then the JDBC value suits us fine + this.rownumber = this.resultSet.getRow(); + } else { + throw zxJDBC.makeException(zxJDBC.NotSupportedError, "dynamic result set does not support scrolling"); + } + } catch (SQLException e) { + throw zxJDBC.makeException(e); + } + } + + /** * Close the underlying ResultSet. */ *************** *** 738,744 **** } ! this.resultSet.close(); ! this.resultSet = null; } } --- 836,846 ---- } ! this.rownumber = -1; ! try { ! this.resultSet.close(); ! } finally { ! this.resultSet = null; ! } } } Index: PyCursor.java =================================================================== RCS file: /cvsroot/jython/jython/com/ziclix/python/sql/PyCursor.java,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** PyCursor.java 2002/01/11 21:46:01 1.16 --- PyCursor.java 2002/01/14 04:28:41 1.17 *************** *** 123,134 **** m[7] = new PyString("next"); __methods__ = new PyList(m); ! m = new PyObject[7]; m[0] = new PyString("arraysize"); m[1] = new PyString("rowcount"); ! m[2] = new PyString("description"); ! m[3] = new PyString("datahandler"); ! m[4] = new PyString("warnings"); ! m[5] = new PyString("lastrowid"); ! m[6] = new PyString("updatecount"); __members__ = new PyList(m); } --- 123,135 ---- m[7] = new PyString("next"); __methods__ = new PyList(m); ! m = new PyObject[8]; m[0] = new PyString("arraysize"); m[1] = new PyString("rowcount"); ! m[2] = new PyString("rownumber"); ! m[3] = new PyString("description"); ! m[4] = new PyString("datahandler"); ! m[5] = new PyString("warnings"); ! m[6] = new PyString("lastrowid"); ! m[7] = new PyString("updatecount"); __members__ = new PyList(m); } *************** *** 175,181 **** return __members__; } else if ("description".equals(name)) { ! return this.fetch.getDescription(); } else if ("rowcount".equals(name)) { ! return Py.newInteger(this.fetch.getRowCount()); } else if ("warnings".equals(name)) { return warnings; --- 176,186 ---- return __members__; } else if ("description".equals(name)) { ! return this.fetch.description; } else if ("rowcount".equals(name)) { ! return Py.newInteger(this.fetch.rowcount); ! } else if ("rownumber".equals(name)) { ! int rn = this.fetch.rownumber; ! ! return (rn < 0) ? Py.None : Py.newInteger(rn); } else if ("warnings".equals(name)) { return warnings; *************** *** 213,216 **** --- 218,222 ---- dict.__setitem__("callproc", new CursorFunc("callproc", 8, 1, 4, "executes a stored procedure")); dict.__setitem__("executemany", new CursorFunc("executemany", 9, 1, 3, "execute sql with the parameter list")); + dict.__setitem__("scroll", new CursorFunc("scroll", 10, 1, 2, "scroll the cursor in the result set to a new position according to mode")); // hide from python *************** *** 663,666 **** --- 669,698 ---- /** + * Scroll the cursor in the result set to a new position according + * to mode. + * + * If mode is 'relative' (default), value is taken as offset to + * the current position in the result set, if set to 'absolute', + * value states an absolute target position. + * + * An IndexError should be raised in case a scroll operation would + * leave the result set. In this case, the cursor position is left + * undefined (ideal would be to not move the cursor at all). + * + * Note: This method should use native scrollable cursors, if + * available, or revert to an emulation for forward-only + * scrollable cursors. The method may raise NotSupportedErrors to + * signal that a specific operation is not supported by the + * database (e.g. backward scrolling). + * + * @param int value + * @param String mode + * + */ + public void scroll(int value, String mode) { + this.fetch.scroll(value, mode); + } + + /** * Adds a warning to the tuple and will follow the chain as necessary. */ *************** *** 903,906 **** --- 935,943 ---- return Py.None; + case 10 : + cursor.scroll(arg.__int__().getValue(), "relative"); + + return Py.None; + default : throw argCountError(1); *************** *** 938,941 **** --- 975,983 ---- case 9 : cursor.executemany(arga.__str__().toString(), argb, Py.None, Py.None); + + return Py.None; + + case 10 : + cursor.scroll(arga.__int__().getValue(), argb.toString()); return Py.None; |