📄 resultsetimpl.java
字号:
this.reallyResult = true; // Check for no results if (this.rowData.size() > 0) { if (this.updateCount == 1) { if (this.thisRow == null) { this.rowData.close(); // empty result set this.updateCount = -1; } } } else { this.thisRow = null; } this.rowData.setOwner(this); if (this.fields != null) { initializeWithMetadata(); } // else called by Connection.initializeResultsMetadataFromCache() when cached useLegacyDatetimeCode = this.connection.getUseLegacyDatetimeCode(); this.useColumnNamesInFindColumn = this.connection.getUseColumnNamesInFindColumn(); setRowPositionValidity(); } public void initializeWithMetadata() throws SQLException { this.rowData.setMetadata(this.fields); if (this.profileSql || this.connection.getUseUsageAdvisor()) { this.columnUsed = new boolean[this.fields.length]; this.pointOfOrigin = new Throwable(); this.resultId = resultCounter++; this.useUsageAdvisor = this.connection.getUseUsageAdvisor(); this.eventSink = ProfilerEventHandlerFactory.getInstance(this.connection); } if (this.connection.getGatherPerformanceMetrics()) { this.connection.incrementNumberOfResultSetsCreated(); Map tableNamesMap = new HashMap(); for (int i = 0; i < this.fields.length; i++) { Field f = this.fields[i]; String tableName = f.getOriginalTableName(); if (tableName == null) { tableName = f.getTableName(); } if (tableName != null) { if (this.connection.lowerCaseTableNames()) { tableName = tableName.toLowerCase(); // on windows, table // names are not case-sens. } tableNamesMap.put(tableName, null); } } this.connection.reportNumberOfTablesAccessed(tableNamesMap.size()); } } private synchronized void createCalendarIfNeeded() { if (this.fastDateCal == null) { this.fastDateCal = new GregorianCalendar(Locale.US); this.fastDateCal.setTimeZone(this.getDefaultTimeZone()); } } /** * JDBC 2.0 * * <p> * Move to an absolute row number in the result set. * </p> * * <p> * If row is positive, moves to an absolute row with respect to the * beginning of the result set. The first row is row 1, the second is row 2, * etc. * </p> * * <p> * If row is negative, moves to an absolute row position with respect to the * end of result set. For example, calling absolute(-1) positions the cursor * on the last row, absolute(-2) indicates the next-to-last row, etc. * </p> * * <p> * An attempt to position the cursor beyond the first/last row in the result * set, leaves the cursor before/after the first/last row, respectively. * </p> * * <p> * Note: Calling absolute(1) is the same as calling first(). Calling * absolute(-1) is the same as calling last(). * </p> * * @param row * the row number to move to * * @return true if on the result set, false if off. * * @exception SQLException * if a database-access error occurs, or row is 0, or result * set type is TYPE_FORWARD_ONLY. */ public boolean absolute(int row) throws SQLException { checkClosed(); boolean b; if (this.rowData.size() == 0) { b = false; } else { if (row == 0) { throw SQLError.createSQLException( Messages .getString("ResultSet.Cannot_absolute_position_to_row_0_110"), //$NON-NLS-1$ SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } if (this.onInsertRow) { this.onInsertRow = false; } if (this.doingUpdates) { this.doingUpdates = false; } if (this.thisRow != null) { this.thisRow.closeOpenStreams(); } if (row == 1) { b = first(); } else if (row == -1) { b = last(); } else if (row > this.rowData.size()) { afterLast(); b = false; } else { if (row < 0) { // adjust to reflect after end of result set int newRowPosition = this.rowData.size() + row + 1; if (newRowPosition <= 0) { beforeFirst(); b = false; } else { b = absolute(newRowPosition); } } else { row--; // adjust for index difference this.rowData.setCurrentRow(row); this.thisRow = this.rowData.getAt(row); b = true; } } } setRowPositionValidity(); return b; } /** * JDBC 2.0 * * <p> * Moves to the end of the result set, just after the last row. Has no * effect if the result set contains no rows. * </p> * * @exception SQLException * if a database-access error occurs, or result set type is * TYPE_FORWARD_ONLY. */ public void afterLast() throws SQLException { checkClosed(); if (this.onInsertRow) { this.onInsertRow = false; } if (this.doingUpdates) { this.doingUpdates = false; } if (this.thisRow != null) { this.thisRow.closeOpenStreams(); } if (this.rowData.size() != 0) { this.rowData.afterLast(); this.thisRow = null; } setRowPositionValidity(); } /** * JDBC 2.0 * * <p> * Moves to the front of the result set, just before the first row. Has no * effect if the result set contains no rows. * </p> * * @exception SQLException * if a database-access error occurs, or result set type is * TYPE_FORWARD_ONLY */ public void beforeFirst() throws SQLException { checkClosed(); if (this.onInsertRow) { this.onInsertRow = false; } if (this.doingUpdates) { this.doingUpdates = false; } if (this.rowData.size() == 0) { return; } if (this.thisRow != null) { this.thisRow.closeOpenStreams(); } this.rowData.beforeFirst(); this.thisRow = null; setRowPositionValidity(); } // --------------------------------------------------------------------- // Traversal/Positioning // --------------------------------------------------------------------- /** * Builds a hash between column names and their indices for fast retrieval. */ public void buildIndexMapping() throws SQLException { int numFields = this.fields.length; this.columnLabelToIndex = new TreeMap(String.CASE_INSENSITIVE_ORDER); this.fullColumnNameToIndex = new TreeMap(String.CASE_INSENSITIVE_ORDER); this.columnNameToIndex = new TreeMap(String.CASE_INSENSITIVE_ORDER); this.columnToIndexCache = new HashMap(); // We do this in reverse order, so that the 'first' column // with a given name ends up as the final mapping in the // hashtable... // // Quoting the JDBC Spec: // // "Column names used as input to getter // methods are case insensitive. When a getter method is called with a // column // name and several columns have the same name, the value of the first // matching column will be returned. " // for (int i = numFields - 1; i >= 0; i--) { Integer index = Constants.integerValueOf(i); String columnName = this.fields[i].getOriginalName(); String columnLabel = this.fields[i].getName(); String fullColumnName = this.fields[i].getFullName(); if (columnLabel != null) { this.columnLabelToIndex.put(columnLabel, index); } if (fullColumnName != null) { this.fullColumnNameToIndex.put(fullColumnName, index); } if (columnName != null) { this.columnNameToIndex.put(columnName, index); } } // set the flag to prevent rebuilding... this.hasBuiltIndexMapping = true; } /** * JDBC 2.0 The cancelRowUpdates() method may be called after calling an * updateXXX() method(s) and before calling updateRow() to rollback the * updates made to a row. If no updates have been made or updateRow() has * already been called, then this method has no effect. * * @exception SQLException * if a database-access error occurs, or if called when on * the insert row. * @throws NotUpdatable * DOCUMENT ME! */ public void cancelRowUpdates() throws SQLException { throw new NotUpdatable(); } /** * Ensures that the result set is not closed * * @throws SQLException * if the result set is closed */ protected final void checkClosed() throws SQLException { if (this.isClosed) { throw SQLError.createSQLException( Messages .getString("ResultSet.Operation_not_allowed_after_ResultSet_closed_144"), //$NON-NLS-1$ SQLError.SQL_STATE_GENERAL_ERROR); } } /** * Checks if columnIndex is within the number of columns in this result set. * * @param columnIndex * the index to check * * @throws SQLException * if the index is out of bounds */ protected final void checkColumnBounds(int columnIndex) throws SQLException { if ((columnIndex < 1)) { throw SQLError.createSQLException(Messages.getString( "ResultSet.Column_Index_out_of_range_low", new Object[] { Constants.integerValueOf(columnIndex), Constants.integerValueOf(this.fields.length) }), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ } else if ((columnIndex > this.fields.length)) { throw SQLError.createSQLException(Messages.getString( "ResultSet.Column_Index_out_of_range_high", new Object[] { Constants.integerValueOf(columnIndex), Constants.integerValueOf(this.fields.length) }), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ } if (this.profileSql || this.useUsageAdvisor) { this.columnUsed[columnIndex - 1] = true; } } /** * Ensures that the cursor is positioned on a valid row and that the result * set is not closed * * @throws SQLException * if the result set is not in a valid state for traversal */ protected void checkRowPos() throws SQLException { checkClosed(); if (!this.onValidRow) { throw SQLError.createSQLException(this.invalidRowReason, SQLError.SQL_STATE_GENERAL_ERROR); } } private boolean onValidRow = false; private String invalidRowReason = null; protected boolean useLegacyDatetimeCode; private TimeZone serverTimeZoneTz; private void setRowPositionValidity() throws SQLException { if (!this.rowData.isDynamic() && (this.rowData.size() == 0)) { this.invalidRowReason = Messages .getString("ResultSet.Illegal_operation_on_empty_result_set");//$NON-NLS-1$ this.onValidRow = false; } else if (this.rowData.isBeforeFirst()) { this.invalidRowReason = Messages .getString("ResultSet.Before_start_of_result_set_146"); //$NON-NLS-1$ this.onValidRow = false; } else if (this.rowData.isAfterLast()) { this.invalidRowReason = Messages .getString("ResultSet.After_end_of_result_set_148"); //$NON-NLS-1$ this.onValidRow = false; } else { this.onValidRow = true; this.invalidRowReason = null; } } /** * We can't do this ourselves, otherwise the contract for * Statement.getMoreResults() won't work correctly. */ public void clearNextResult() { this.nextResultSet = null; } /** * After this call, getWarnings returns null until a new warning is reported * for this ResultSet * * @exception SQLException * if a database access error occurs */ public void clearWarnings() throws SQLException { this.warningChain = null; } /** * In some cases, it is desirable to immediately release a ResultSet * database and JDBC resources instead of waiting for this to happen when it * is automatically closed. The close method provides this immediate * release. * * <p> * <B>Note:</B> A ResultSet is automatically closed by the Statement the * Statement that generated it when that Statement is closed, re-executed, * or is used to retrieve the next result from a sequence of multiple * results. A ResultSet is also automatically closed when it is garbage * collected. * </p> * * @exception SQLException * if a database access error occurs */ public void close() throws SQLException { realClose(true); } /** * @return */ private int convertToZeroWithEmptyCheck() throws SQLException { if (this.connection.getEmptyStringsConvertToZero()) { return 0; } throw SQLError.createSQLException("Can't convert empty string ('') to numeric", SQLError.SQL_STATE_INVALID_CHARACTER_VALUE_FOR_CAST); } private String convertToZeroLiteralStringWithEmptyCheck() throws SQLException { if (this.connection.getEmptyStringsConvertToZero()) { return "0"; } throw SQLError.createSQLException("Can't convert empty string ('') to numeric", SQLError.SQL_STATE_INVALID_CHARACTER_VALUE_FOR_CAST); } // // Note, row data is linked between these two result sets // public ResultSetInternalMethods copy() throws SQLException { ResultSetInternalMethods rs = ResultSetImpl.getInstance(this.catalog, this.fields, this.rowData, this.connection, this.owningStatement, false); // note, doesn't work for updatable result sets return rs; } public void redefineFieldsForDBMD(Field[] f) { this.fields = f; for (int i = 0; i < this.fields.length; i++) { this.fields[i].setUseOldNameMetadata(true); this.fields[i].setConnection(this.connection);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -