/* * Copyright (C) 2000 - 2013 TagServlet Ltd * * This file is part of Open BlueDragon (OpenBD) CFML Server Engine. * * OpenBD is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * Free Software Foundation,version 3. * * OpenBD is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenBD. If not, see http://www.gnu.org/licenses/ * * Additional permission under GNU GPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or combining * it with any of the JARS listed in the README.txt (or a modified version of * (that library), containing parts covered by the terms of that JAR, the * licensors of this Program grant you additional permission to convey the * resulting work. * README.txt @ http://www.openbluedragon.org/license/README.txt * * http://openbd.org/ * $Id: cfQueryResultData.java 2408 2013-10-22 12:12:42Z craig $ */ package com.naryx.tagfusion.cfm.engine; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.io.Serializable; import java.math.BigDecimal; import java.sql.Array; import java.sql.Blob; import java.sql.Clob; import java.sql.DatabaseMetaData; import java.sql.NClob; import java.sql.Ref; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.RowId; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.SQLXML; import java.sql.Statement; import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; import java.text.DateFormat; import java.text.ParseException; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Stack; import java.util.Vector; import com.nary.util.FastMap; import com.naryx.tagfusion.cfm.parser.script.userDefinedFunction; import com.naryx.tagfusion.cfm.queryofqueries.orderByCol; import com.naryx.tagfusion.cfm.sql.preparedData; import com.naryx.tagfusion.cfm.tag.cfDUMP; /** * This class handles the Query data structure in ColdFusion. * Please note *all* row/column references are 1 based and not 0 based */ public class cfQueryResultData extends cfJavaObjectData implements cfQueryInterface, ResultSet, Serializable { private static final long serialVersionUID = 1L; private cfQueryResultSetMetaData rsmd; private List<List<cfData>> tableRows; private Vector<cfNullData> nulldatas; // The following item is displayed in a dump so let's serialize it out. private String querySource; public long executeTime; public String queryString; transient protected List<preparedData> preparedDataList; transient protected int maxRows; transient private int LASTROW, CURRENTROW; transient private List<cfData> rowCursor; transient private Stack<Integer> groupColumns = new Stack<Integer>(); transient private Stack<Boolean> groupCaseSensitive = new Stack<Boolean>(); transient private int groupCurrentRow = 0; transient private boolean groupEnabled = true; public cfQueryResultData( String _querySource ){ this(new String[] {}, _querySource); } public cfQueryResultData( String _columnList[], String _querySource ){ this( _columnList, null, _querySource ); } public cfQueryResultData( String _columnList[], int [] _columnTypeList, String _querySource ){ super( "" ); // fudge setInstance( this ); init( _columnList, _columnTypeList, _querySource ); } public cfQueryResultData( ResultSet rs, String querySource, int maxRows ) throws SQLException { super( "" ); // fudge setInstance( this ); this.tableRows = new ArrayList<List<cfData>>(); this.nulldatas = new Vector<cfNullData>(); this.querySource = querySource; LASTROW = 0; CURRENTROW = 0; rowCursor = null; populate( rs, maxRows ); } private cfQueryResultData( cfQueryResultSetMetaData rsmd, String querySource ) { super( "" ); // fudge setInstance( this ); this.tableRows = new ArrayList<List<cfData>>(); this.nulldatas = new Vector<cfNullData>(); this.rsmd = rsmd; this.querySource = querySource; LASTROW = 0; CURRENTROW = 0; rowCursor = null; } protected void init( String [] _columnList, int [] _columnTypeList, String _querySource ){ this.tableRows = new ArrayList<List<cfData>>(); this.nulldatas = new Vector<cfNullData>(); this.rsmd = new cfQueryResultSetMetaData( _columnList, _columnTypeList ); this.querySource = _querySource; LASTROW = 0; CURRENTROW = 0; rowCursor = null; } public void addPreparedData(preparedData _Data) { if (preparedDataList == null) preparedDataList = new ArrayList<preparedData>(); preparedDataList.add(_Data); } public long getExecuteTime() { return executeTime; } public String getQueryString() { return queryString; } public void setMaxRows(int _maxRows) { maxRows = _maxRows; } public void setQueryString(String _queryString) { queryString = _queryString.trim(); } protected void populate( ResultSet rs, int maxRows ) throws SQLException { rsmd = new cfQueryResultSetMetaData( rs.getMetaData() ); for ( int rowCount = 0; rs.next() && ( rowCount != maxRows ); rowCount++ ) setRow( rs ); CURRENTROW = 0; setCursors(); } /* * getRowCursor * * rowCursor is a transient member that isn't serialized therefore we need to make * sure it is initialized before it is used after this object is deserialized. */ public List<cfData> getRowCursor() { if ( (rowCursor == null) && (tableRows.size() > 0) ) { rowCursor = tableRows.get(0); } return rowCursor; } /* * getGroupColumns * * groupColumns is a transient member that isn't serialized therefore we need to make * sure it is initialized before it used after this object is deserialized. */ public Stack<Integer> getGroupColumns() { if ( groupColumns == null ) groupColumns = new Stack<Integer>(); return groupColumns; } /* * getGroupCaseSensitive * * groupCaseSensitive is a transient member that isn't serialized therefore we need to make * sure it is initialized before it used after this object is deserialized. */ public Stack<Boolean> getGroupCaseSensitive() { if ( groupCaseSensitive == null ) groupCaseSensitive = new Stack<Boolean>(); return groupCaseSensitive; } public byte getDataType(){ return cfData.CFQUERYRESULTDATA; } public String getDataTypeName() { return "query"; } public List<List<cfData>> getQueryTableData(){ return this.tableRows; } public void setQuerySource(String _querySource){ querySource = _querySource; } public String getQuerySource(){ return querySource; } public void setQueryData( cfQueryResultData newQuery, String src ){ /* * When we cache data we serialise the original object instance. However upon reloading we simply * set the elements we require internally. This makes life easier as we don't need to rewrite any * object references that maybe pointing to this object instance from inside the core engine. */ tableRows = newQuery.tableRows; nulldatas = newQuery.nulldatas; rsmd = newQuery.rsmd; querySource = src; setCursors(); } public void setQueryData( List<List<cfData>> _queryData ){ // assumes that queryData supplied will work with the set columnList. tableRows = _queryData; setCursors(); } private void setCursors() { LASTROW = tableRows.size(); if (tableRows.size() > 0) { CURRENTROW = 1; rowCursor = tableRows.get(0); } } public List<cfData> getRow( int _index ){ return tableRows.get( _index ); } private void setRow( ResultSet dataRow ) throws SQLException{ int columnCount = getNoColumns(); //--[ Add a new row to the underlying data set addRow(1); for ( int x = 0; x < columnCount; x++ ) { int columnType = rsmd.getColumnType( x + 1 ); // String columnName = rsmd.getColumnName( x + 1 ); // useful when debugging String columnTypeName = null; cfData newData = null; switch ( columnType ) { // NOTE: java.sql.Types.DATE used to be treated separately with a call to getDate() // instead of getTimestamp() but this caused problems with the Oracle 10g JDBC // driver which maps the Oracle DATE data type to java.sql.Types.DATE when it // should map it to java.sql.Types.TIMESTAMP. To work around this we now treat // it as if it was a java.sql.Types.TIMESTAMP. Refer to bug #1433. case java.sql.Types.TIMESTAMP : case java.sql.Types.DATE : try { Timestamp ts = dataRow.getTimestamp( x + 1 ); if ( ts != null ) { newData = new cfDateData( ts ); } } catch ( SQLException e ) { // for MySQL column type YEAR(2) String year = dataRow.getString( x + 1 ); if ( year != null ) { try { String fullDate; if ( year.length() == 2 ) { // MySql JDBC driver 3.1.x fullDate = "01/01/" + ( Integer.parseInt( year ) < 70 ? "20" : "19" ) + year; } else { // MySql JDBC driver 5.0.x fullDate = "01/01/" + year.substring(0,4); } long date = DateFormat.getDateInstance( DateFormat.SHORT ).parse( fullDate ).getTime(); newData = new cfDateData( new java.sql.Date( date ) ); } catch ( ParseException pe ) { newData = new cfStringData( year ); } } } break; case java.sql.Types.TIME : Time time = dataRow.getTime( x + 1 ); if ( time != null ) { newData = new cfDateData( time ); } break; case java.sql.Types.BIT : boolean b = dataRow.getBoolean( x + 1 ); // ODBC requires this for bits instead of getInt() if ( !dataRow.wasNull() ) { newData = new cfNumberData( b ? 1 : 0 ); // CF5/MX treat bits as numbers, not booleans } break; case java.sql.Types.TINYINT : short tiny; if ( rsmd.isSigned( x + 1 ) ) { tiny = dataRow.getByte( x + 1 ); } else { // for MySQL, must get unsigned as short tiny = dataRow.getShort( x + 1 ); } if ( !dataRow.wasNull() ) { newData = new cfNumberData( tiny ); } break; case java.sql.Types.SMALLINT : int s; if ( rsmd.isSigned( x + 1 ) ) { s = dataRow.getShort( x + 1 ); } else { // for MySQL, must get unsigned as int s = dataRow.getInt( x + 1 ); } if ( !dataRow.wasNull() ) { newData = new cfNumberData( s ); } break; case java.sql.Types.INTEGER : long i; if ( rsmd.isSigned( x + 1 ) ) { i = dataRow.getInt( x + 1 ); } else { // for MySQL, must get unsigned as long i = dataRow.getLong( x + 1 ); } if ( !dataRow.wasNull() ) { newData = new cfNumberData( i ); } break; case java.sql.Types.BIGINT : if ( rsmd.isSigned( x + 1 ) ) { long l = dataRow.getLong( x + 1 ); if ( !dataRow.wasNull() ) { newData = new cfNumberData( l ); } break; } // for unsigned (MySQL), fall through and get as double case java.sql.Types.DECIMAL : case java.sql.Types.NUMERIC : case java.sql.Types.DOUBLE : case java.sql.Types.FLOAT : double d = dataRow.getDouble( x + 1 ); if ( !dataRow.wasNull() ) { newData = new cfNumberData( d ); } break; case java.sql.Types.REAL : float f = dataRow.getFloat( x + 1 ); if ( !dataRow.wasNull() ) { // For some reason casting a float to a double doesn't return a double // that exactly matches the original float so we'll use the less efficient // algorithm of converting the float to a string and the string to a double. // If for some reason this fails then we'll revert to casting the float to // a double. double d2; try { d2 = Double.valueOf( Float.toString( f ) ).doubleValue(); } catch ( Exception e ) { d2 = f; } newData = new cfNumberData( d2 ); } break; // this is old code that works, but the code above for DOUBLE // is more efficient // case java.sql.Types.DECIMAL : // case java.sql.Types.NUMERIC : // BigDecimal bd = dataRow.getBigDecimal( x + 1 ); // if ( !dataRow.wasNull() ) { // newData = new cfNumberData( bd.doubleValue() ); // querySizeBytes += 8; // } // break; case java.sql.Types.BINARY : case java.sql.Types.VARBINARY : case java.sql.Types.LONGVARBINARY : case java.sql.Types.BLOB : InputStream in = dataRow.getBinaryStream( x + 1 ); if ( !dataRow.wasNull() ) { newData = new cfBinaryData( in ); try{ in.close(); }catch( IOException ignored ){} } break; case java.sql.Types.LONGVARCHAR : case java.sql.Types.CLOB : newData = getAsCfStringData( dataRow, x+1 ); break; case java.sql.Types.OTHER : // for Microsoft SQL Server via the JDBC-ODBC Bridge, column // types such as UniqueIdentifier, NChar, NText, and NVarChar // get here, but obj is always null Object obj = dataRow.getObject( x + 1 ); if ( dataRow.wasNull() ) { break; } if ( obj != null ) { String className = obj.getClass().getName(); if ( obj.getClass().isArray() ){ if ( className.equals( "[B" ) ) { newData = new cfBinaryData( (byte[]) obj ); break; } } else if ( className.equals( "org.postgresql.util.PGobject" ) ) { // This code will be hit for Postgresql abstime and reltime types. We copy what // happens when the JDBC-ODBC bridge is used and return a cfDateData type for // abstime and a cfStringData type for reltime. try { java.lang.reflect.Method m = obj.getClass().getMethod( "getType", (Class[])null ); String type = (String)m.invoke( obj, (Object[])null ); if ( type.equals( "abstime" ) ) { m = obj.getClass().getMethod( "getValue", (Class[])null ); String value = (String)m.invoke( obj, (Object[])null ); newData = new cfDateData( java.sql.Timestamp.valueOf(value.substring(0,19)) ); break; } } catch ( Exception e ) {} newData = new cfStringData( obj.toString() ); break; } else { newData = new cfJavaObjectData( obj ); break; } } else { columnTypeName = rsmd.getColumnTypeName( x + 1 ).toLowerCase(); if ( columnTypeName.equals( "ntext" ) ) { in = dataRow.getBinaryStream( x + 1 ); try { newData = cfStringData.getString( in ); } catch ( IOException e ) { throw new SQLException( e.toString() ); } break; } else if ( columnTypeName.equals( "uniqueidentifier" ) ) { newData = new cfStringData( getUniqueIdentifier( dataRow.getBytes( x + 1 ) ) ); break; } } // fall through to default case (string) case -8 : // OracleTypes.ROWID case java.sql.Types.CHAR : case java.sql.Types.VARCHAR : // fall through to default case (string) default : // everything else is treated as string data String str = dataRow.getString( x + 1 ); if ( str != null ) { newData = new cfStringData( str ); } break; } //--[ Put this into the Engine now //--[ If it's a null field value then use cfNullData.DBNULL instead of cfNullData.NULL. setCell( LASTROW, x + 1, ( newData == null ? getNull( x + 1 ) : newData ) ); } } public static cfStringData getAsCfStringData( ResultSet _result, int _index ) throws SQLException { Reader inr = _result.getCharacterStream( _index ); if ( !_result.wasNull() ) { try { return cfStringData.getString( inr ); } catch ( IOException e ) { throw new SQLException( e.toString() ); } }else{ return null; } } private static String getUniqueIdentifier( byte[] obj ) { if ( obj == null ) return null; // this code copied from com.newatlanta.jturbo.driver.ResultSet.getObjectUsingType byte[] abyte0 = obj; int k = abyte0.length; if ( k < 8 ) return null; StringBuilder stringbuffer = new StringBuilder(40); for ( int i1 = 3; i1 >= 0; i1-- ) { stringbuffer.append(Integer.toHexString(abyte0[i1] >> 4 & 0xf).toUpperCase()); stringbuffer.append(Integer.toHexString(abyte0[i1] & 0xf).toUpperCase()); } stringbuffer.append('-'); for ( int j1 = 5; j1 >= 4; j1-- ) { stringbuffer.append(Integer.toHexString(abyte0[j1] >> 4 & 0xf).toUpperCase()); stringbuffer.append(Integer.toHexString(abyte0[j1] & 0xf).toUpperCase()); } stringbuffer.append('-'); for ( int k1 = 7; k1 >= 6; k1-- ) { stringbuffer.append(Integer.toHexString(abyte0[k1] >> 4 & 0xf).toUpperCase()); stringbuffer.append(Integer.toHexString(abyte0[k1] & 0xf).toUpperCase()); } for ( int i2 = 8; i2 < abyte0.length; i2++) { if ( i2 == 8 || i2 == 10 ) stringbuffer.append('-'); stringbuffer.append(Integer.toHexString(abyte0[i2] >> 4 & 0xf).toUpperCase()); stringbuffer.append(Integer.toHexString(abyte0[i2] & 0xf).toUpperCase()); } return stringbuffer.toString(); } /** * Returns the row data. Added for union functionality * in query of queries */ public List<List<cfData>> getTableRows(){ return tableRows; } public cfData duplicate(){ List<List<cfData>> copiedTableRows = new ArrayList<List<cfData>>(); cfQueryResultData copiedQuery = new cfQueryResultData( (cfQueryResultSetMetaData)rsmd.clone(), querySource ); for ( int i = 0; i < tableRows.size(); i++ ){ List<cfData> nextRow = tableRows.get( i ); int nextRowLen = nextRow.size(); List<cfData> nextRowCopy = new ArrayList<cfData>(nextRowLen); for ( int j = 0; j < nextRowLen; j++ ){ cfData nextItemCopy = nextRow.get( j ).duplicate(); if ( nextItemCopy == null ){ return null; } nextItemCopy.setQueryTableData( copiedTableRows, j+1 ); nextRowCopy.add( nextItemCopy ); } copiedTableRows.add( nextRowCopy ); } copiedQuery.setQueryData( copiedTableRows ); return copiedQuery; } //----------------------------------------------------- //--[ Interface Operations //----------------------------------------------------- public void reset(){ CURRENTROW = 0; rowCursor = null; } //--[ This is call to actually run the query public void runQuery( cfSession _Session ) throws cfmRunTimeException {} //--[ Called to retrieve each row public boolean nextRow() throws cfmRunTimeException{ CURRENTROW++; if ( CURRENTROW > tableRows.size() ) return false; else if ( isGrouped() ){ return setNextGroupRow(); }else{ rowCursor = tableRows.get( CURRENTROW - 1 ); return true; } } public int getCurrentRow() { return CURRENTROW; } public boolean setCurrentRow( int _row ) { if ( _row > tableRows.size() || _row <= 0 ){ return false; }else{ CURRENTROW = _row; rowCursor = tableRows.get( CURRENTROW - 1 ); return true; } } //--[ Called to allow any clean up of the query public void finishQuery(){ if ( tableRows.size() > 0 ){ CURRENTROW = 1; rowCursor = tableRows.get( CURRENTROW - 1 ); } } //----------------------------------------------------- //--[ GroupBy operators //----------------------------------------------------- private boolean setNextGroupRow() throws cfmRunTimeException { if ( CURRENTROW == 1 ){ //--[ The first row has to be returned rowCursor = tableRows.get( CURRENTROW - 1 ); return true; } else { int groupColumn = getGroupColumn(); boolean caseSensitive = isGroupCaseSensitive(); int previousRow = CURRENTROW - 1; //--[ Lower case if this group is case insensitive String lastColumn = getCell( previousRow, groupColumn ).getString(); if ( !caseSensitive ) lastColumn = lastColumn.toLowerCase(); //--[ check the remaining rows searching for the next row where the // all the group by columns bar the one at the top of the group by // column stack match for ( int RowX=CURRENTROW; RowX <= tableRows.size(); RowX++ ){ String thisColumn = getCell( RowX, groupColumn ).getString(); if ( !caseSensitive ) thisColumn = thisColumn.toLowerCase(); CURRENTROW = RowX; rowCursor = tableRows.get( CURRENTROW - 1 ); if ( lastColumn.compareTo( thisColumn ) != 0 ) { // if previous group columns match return true, otherwise false for ( int i = 0; i < getGroupColumns().size(); i++ ) { int column = getGroupColumns().elementAt( i ).intValue(); if ( column != groupColumn ) { caseSensitive = getGroupCaseSensitive().elementAt( i ).booleanValue(); if ( !isCurrentRowInGroup( previousRow, column, caseSensitive ) ) return false; } } return true; }else if ( getGroupColumns().size() > 1 ){ //--[ we know that the current group column matches but if there // are other group columns then they should match too for ( int i = 0; i < getGroupColumns().size(); i++ ) { int column = getGroupColumns().elementAt( i ).intValue(); caseSensitive = getGroupCaseSensitive().elementAt( i ).booleanValue(); if ( !isCurrentRowInGroup( previousRow, column, caseSensitive ) ){ return false; } } } } return false; } } public void startGroupOutput(){ groupCurrentRow = CURRENTROW; CURRENTROW -= 1; } public void endGroupOutput(){ CURRENTROW = groupCurrentRow; rowCursor = tableRows.get( CURRENTROW - 1 ); } public boolean nextRowInGroup() throws cfmRunTimeException { CURRENTROW++; if ( CURRENTROW > tableRows.size() ) return false; rowCursor = tableRows.get( CURRENTROW - 1 ); //--[ Check the last one to see || (CURRENTROW+1) > tableRows.size() if ( (CURRENTROW-1) == 0 || CURRENTROW == groupCurrentRow ) return true; for( int i=0; i < groupColumns.size(); i++ ){ if (!isCurrentRowInGroup( groupColumns.elementAt(i).intValue(), isGroupCaseSensitive() )) return false; } return true; } private boolean isCurrentRowInGroup( int groupColumn, boolean caseSensitive ) throws cfmRunTimeException { return isCurrentRowInGroup( CURRENTROW-1, groupColumn, caseSensitive ); } private boolean isCurrentRowInGroup( int _row, int groupColumn, boolean caseSensitive ) throws cfmRunTimeException { String thisColumn = getCell( CURRENTROW, groupColumn ).getString(); if ( !caseSensitive ) thisColumn = thisColumn.toLowerCase(); String lastColumn = getCell( _row, groupColumn ).getString(); if ( !caseSensitive ) lastColumn = lastColumn.toLowerCase(); if ( thisColumn.compareTo( lastColumn ) == 0 ) return true; else return false; } public void setGroupedByEnabled( boolean enabled ) { groupEnabled = enabled; } public final boolean isGrouped(){ return ( groupEnabled && !getGroupColumns().empty() ); } private int getGroupColumn() { return getGroupColumns().peek().intValue(); } private boolean isGroupCaseSensitive() { return getGroupCaseSensitive().peek().booleanValue(); } public void setGroupBy( String column, boolean caseSensitive ) throws cfmRunTimeException { int groupColumn = rsmd.getColumnIndex(column); if ( groupColumn == 0 ) { throw new cfmRunTimeException( catchDataFactory.generalException( "errorCode.sqlError", "sql.invalidColumn", new String[]{column} ) ); } getGroupColumns().push( new Integer( groupColumn ) ); getGroupCaseSensitive().push( new Boolean( caseSensitive ) ); groupEnabled = true; } public void removeGroupBy() { getGroupColumns().pop(); getGroupCaseSensitive().pop(); relative( -1 ); } //----------------------------------------------------- //--[ Column Operations //----------------------------------------------------- public String[] getColumnNames(){ return rsmd.getColumnNames(); } // added to fix bug #3009 public String[] getColumnList(){ return rsmd.getColumnNames(); } public String getColumns(){ String[] columnList = rsmd.getColumnNames(); java.util.Arrays.sort( columnList, new ColumnNameComparator() ); String tmp = ""; for ( int r = 0; r < columnList.length; r++ ){ tmp += columnList[r]; if ( r < columnList.length-1 ) tmp += ","; } return tmp; } public int[] getColumnTypes() { return rsmd.getColumnTypes(); } private class ColumnNameComparator implements Comparator<String> { public int compare( String o1, String o2 ) { return o1.compareToIgnoreCase( o2 ); } } private int addColumn( String columnName ){ return rsmd.addColumn( columnName ); } private int addColumn( String columnName, int type ){ return rsmd.addColumn( columnName, type ); } public int getNoColumns(){ return rsmd.getColumnCount(); } public int getNoRows(){ return tableRows.size(); } public int getColumnIndexCF( String columnName ){ return rsmd.getColumnIndex( columnName ); } public void deleteColumn( String columnName ){ int columnIndex = rsmd.getColumnIndex( columnName ); if ( columnIndex == 0 ) return; // Delete the data Iterator<List<cfData>> it = tableRows.iterator(); while ( it.hasNext() ){ List<cfData> row = it.next(); row.remove( columnIndex-1 ); } // Delete the meta data rsmd.deleteColumn(columnName); } //----------------------------------------------------- //--[ Table Adjustment operations //----------------------------------------------------- public void populateQuery( List<Map<String, cfData>> listOfHashMaps ){ tableRows = new ArrayList<List<cfData>>( listOfHashMaps.size() ); List<cfData> rowData; Map<String, cfData> rowHash; String key; int columnIndx; cfData cellData; Iterator<Map<String, cfData>> iter = listOfHashMaps.iterator(); while ( iter.hasNext() ) { rowHash = iter.next(); rowData = new ArrayList<cfData>(); for ( int c=0; c < rsmd.getColumnCount(); c++ ) rowData.add( null ); Iterator<String> iter2 = rowHash.keySet().iterator(); while ( iter2.hasNext() ) { key = iter2.next(); columnIndx = rsmd.getColumnIndex(key); if ( columnIndx == 0 ) continue; Object o = rowHash.get(key); if( o instanceof cfData ) { cellData = getUniqueCellData( (cfData)o ); cellData.setQueryTableData( tableRows, columnIndx ); } else if ( o != null ) { cellData = new cfStringData( o.toString() ); cellData.setQueryTableData( tableRows, columnIndx ); } else { cellData = getNull(columnIndx); } rowData.set( columnIndx - 1, cellData ); } tableRows.add( rowData ); } if ( tableRows.size() > 0 ){ CURRENTROW = 1; rowCursor = tableRows.get( 0 ); } } private static cfData getUniqueCellData( cfData cellData ) { // we need to copy booleans to avoid setQueryTableData() being // called on static cfData instances byte dataType = cellData.getDataType(); if ( dataType == cfData.CFBOOLEANDATA ) { return cellData.duplicate(); } else if ( dataType == cfData.CFNULLDATA ) { return ((cfNullData)cellData).getDbNull(); } return cellData; } // return 1-based column number public int addColumnData( String columnName, cfArrayData colData, Integer _type ) throws cfmRunTimeException { if ( rsmd.getColumnIndex(columnName) > 0 ){ throw new cfmRunTimeException( catchDataFactory.generalException( "errorCode.sqlError", "sql.duplicateColumn", new String[]{columnName} ) ); } if ( colData.size() > tableRows.size() ){ int noToInsert = (colData.size()-tableRows.size()); addRow( noToInsert ); } int columnNo; if ( _type != null ){ columnNo = addColumn( columnName, _type.intValue() ); }else{ columnNo = addColumn( columnName ); } //--[ Run through the list of tableRows List<cfData> rowData; for ( int rows=0; rows < tableRows.size(); rows++ ){ rowData = tableRows.get( rows ); if ( rows < colData.size() ){ cfData nextColData = colData.getElement( rows + 1 ); if ( nextColData == null || nextColData.getDataType() == cfData.CFNULLDATA ){ nextColData = getNull( columnNo ); }else{ nextColData = nextColData.duplicate(); nextColData.setQueryTableData( tableRows, columnNo ); } rowData.add( nextColData ); }else{ rowData.add( getNull( columnNo ) ); } } return columnNo; } public void deleteRow( int rowNo ){ //-- This is used by the QueryDelete() CFML expression //-- The rowNo is 1-based; if ( rowNo > tableRows.size() ) return; tableRows.remove( rowNo - 1 ); //-- Reset the pointers if they are out of sync LASTROW = tableRows.size(); if ( CURRENTROW == 0 || CURRENTROW > tableRows.size() ){ CURRENTROW = 1; if ( LASTROW == 0 ){ rowCursor = null; }else{ rowCursor = tableRows.get( 0 ); } } } public void addRow( int noRows ){ int numCols = rsmd.getColumnCount(); for ( int x=0; x < noRows; x++ ){ List<cfData> rowData = new ArrayList<cfData>( numCols ); for ( int r = 0; r < numCols; r++ ){ cfNullData cellData = new cfNullData(); cellData.setDBNull( true ); cellData.setQueryTableData( tableRows, r+1 ); rowData.add( cellData ); } tableRows.add( rowData ); } //--[ Position some of the cursors LASTROW = tableRows.size(); if (tableRows.size() > 0) { if (CURRENTROW == 0) { CURRENTROW = 1; rowCursor = tableRows.get(0); } } } public cfData getCell( int rowNo, int colNo ) { return getCell( rowNo, colNo, true ); } public cfData getCell( int rowNo, int colNo, boolean _convertNulls ) { if ( rowNo > tableRows.size() || colNo > rsmd.getColumnCount() ) return null; cfData tmp = (cfData)tableRows.get( rowNo-1 ).get( colNo-1 ); return ( ( tmp == null ) || ( tmp.getDataType() == cfData.CFNULLDATA && _convertNulls ) ? new cfStringData( "" ) : tmp ); } public boolean setCell( int rowNo, String columnName, cfData cellData ){ int columnIndex = rsmd.getColumnIndex( columnName ); if ( columnIndex == 0 ) return false; return setCell( rowNo, columnIndex, cellData ); } public boolean setCell( int rowNo, int colNo, cfData _cellData ){ List<cfData> rowData = tableRows.get( rowNo - 1 ); cfData uniqueCellData = getUniqueCellData( _cellData ); rowData.set( colNo - 1, uniqueCellData ); uniqueCellData.setQueryTableData( this.tableRows, colNo ); return true; } /** * Set the cell value for the current row. */ public boolean setCell( String columnName, cfData cellData ) { int columnIndex = rsmd.getColumnIndex( columnName ); if ( columnIndex == 0 ) return false; return setCell( columnIndex, cellData ); } public boolean setCell( int colNo, cfData cellData ) { if ( tableRows.size() == 0 ) { return false; } if ( ( CURRENTROW > 0 ) && ( CURRENTROW <= LASTROW ) ) { return setCell( CURRENTROW, colNo, cellData ); } else { return setCell( 1, colNo, cellData ); } } //----------------------------------------------------- //--[ Methods for dealing with ValueList() and QuotedValueList() //--[ These are marked static, as they placed here as convient methods //--[ to ensure all related functionality remains in this class. //----------------------------------------------------- public static int getNoRows( List<List<cfData>> tableData ){ return tableData.size(); } public static int getNoColumns( List<List<cfData>> tableData ){ List<cfData> rowData = tableData.get(0); if (rowData == null) return -1; return rowData.size(); } public static boolean setCellData(List<List<cfData>> tableData, int rowNo, int colNo, cfData _cellData ){ if ( rowNo > tableData.size() ) return false; //-- Gets the row data List<cfData> rowData = tableData.get(rowNo-1); if ( colNo > rowData.size() ) return false; cfData uniqueCellData = getUniqueCellData( _cellData ); rowData.set( colNo - 1, uniqueCellData ); uniqueCellData.setQueryTableData( tableData, colNo ); return true; } public static cfData getCellData( List<List<cfData>> tableData, int rowNo, int colNo ){ if ( rowNo > tableData.size() ) return null; //-- Gets the row data List<cfData> rowData = tableData.get(rowNo-1); if ( colNo > rowData.size() ) return null; return rowData.get(colNo-1); } /* * Method returns the appropriate cfNullData for the given column ensuring that * there is only one instance of cfNullData created per column */ public cfNullData getNull( int _colno ){ cfNullData nulld = null; if ( nulldatas.size() < _colno ){ nulldatas.setSize( _colno ); }else{ nulld = nulldatas.elementAt( _colno-1 ); } if ( nulld == null ){ nulld = new cfNullData().setDBNull( true ); nulld.setQueryTableData( tableRows, _colno ); nulldatas.setElementAt( nulld, _colno-1 ); } return nulld; } //----------------------------------------------------- //--[ Sorting Methods //----------------------------------------------------- /** * Decides what type of sort to carry out on this cfArrayData. * * @param column the column on which to sort * @param type the kind of sort to carry out, numeric, text or textnocase. * @param direction the order to do the sort, asc or desc. */ public void sort( String _column, String _type, String _direction ) throws cfmRunTimeException{ reset(); if ( _type.equalsIgnoreCase("numeric") ){ if ( _direction.equalsIgnoreCase("asc") ){ Collections.sort( tableRows, new NumericAscComparator( _column ) ); }else{ Collections.sort( tableRows, new NumericDescComparator( _column ) ); } }else if ( _type.equalsIgnoreCase("text") ){ if ( _direction.equalsIgnoreCase("asc") ){ Collections.sort( tableRows, new TextAscComparator( _column ) ); }else{ Collections.sort( tableRows, new TextDescComparator( _column )); } }else if ( _type.equalsIgnoreCase("textnocase") ){ if ( _direction.equalsIgnoreCase("asc") ){ Collections.sort( tableRows, new TextNoCaseAscComparator( _column ) ); }else{ Collections.sort( tableRows, new TextNoCaseDescComparator( _column )); } } // reset the row cursor to the start of the newly ordered query data reset(); nextRow(); } /** * Sorts the query according to a list of columns to sort on. * NB. This is designed to work for the ORDER BY clause in query of queries * * @param _columnToSortBy a list of orderByCols that determine the list of columns to * order the query by. */ public void sort( List<orderByCol> _columnsToSortBy ) throws cfmRunTimeException{ Collections.sort( tableRows, new MultiColumnComparator( _columnsToSortBy ) ); // reset the row cursor to the start of the newly ordered query data reset(); nextRow(); }// sort //*************INNER CLASS COMPARATORS for sorting ************* /** Note this is very bad OO design. It is purely for performance reasons * that it has been implemented this way. */ class NumericDescComparator implements Comparator<List<cfData>> { String colName; NumericDescComparator( String _col ) { colName = _col; } public int compare( List<cfData> o1, List<cfData> o2 ) { try { if ( o1.get( rsmd.getColumnIndex( colName ) - 1 ).getDouble() > o2.get( rsmd.getColumnIndex( colName ) - 1 ).getDouble() ) return -1; else if(o1.get( rsmd.getColumnIndex( colName ) - 1 ).getDouble() < o2.get( rsmd.getColumnIndex( colName ) - 1 ).getDouble() ) return 1; else return 0; } catch ( dataNotSupportedException E ) { return 0; } } }// NumericDescComparator class NumericAscComparator implements Comparator<List<cfData>> { String colName; NumericAscComparator( String _col ) { colName = _col; } public int compare( List<cfData> o1, List<cfData> o2 ) { try { if ( o1.get( rsmd.getColumnIndex( colName ) - 1 ).getDouble() < o2.get( rsmd.getColumnIndex( colName ) - 1 ).getDouble() ) return -1; else if( o1.get( rsmd.getColumnIndex( colName ) - 1 ).getDouble() > o2.get( rsmd.getColumnIndex( colName ) - 1 ).getDouble() ) return 1; else return 0; } catch ( dataNotSupportedException E ) { return 0; } }// compare() }// NumericAscComparator class TextAscComparator implements Comparator<List<cfData>> { String colName; TextAscComparator( String _col ) { colName = _col; }// TextAscComparator() public int compare( List<cfData> o1, List<cfData> o2 ) { try { return o1.get( rsmd.getColumnIndex( colName ) - 1 ).getString().compareTo( o2.get( rsmd.getColumnIndex( colName ) - 1 ).getString() ); } catch ( dataNotSupportedException E ) { return 0; } }// compare() }// TextAscComparator class TextDescComparator implements Comparator<List<cfData>> { String colName; TextDescComparator( String _col ) { colName = _col; }// TextDescComparator() public int compare( List<cfData> o1, List<cfData> o2 ) { try { return ( o2.get( rsmd.getColumnIndex( colName ) - 1 ).getString().compareTo( o1.get( rsmd.getColumnIndex( colName ) - 1 ).getString() ) ); } catch ( dataNotSupportedException E ) { return 0; } }// compare() }// TextDescComparator class TextNoCaseAscComparator implements Comparator<List<cfData>> { String colName; TextNoCaseAscComparator( String _col ) { colName = _col; }// TextNoCaseAscComparator() public int compare( List<cfData> o1, List<cfData> o2 ) { try { return o1.get( rsmd.getColumnIndex( colName ) - 1 ).getString().compareToIgnoreCase( o2.get( rsmd.getColumnIndex( colName ) - 1 ).getString() ); } catch ( dataNotSupportedException E ) { return 0; } }// compare() }// TextNoCaseAscComparator class TextNoCaseDescComparator implements Comparator<List<cfData>> { String colName; TextNoCaseDescComparator( String _col ) { colName = _col; }// TextNoCaseDescComparator() public int compare( List<cfData> o1, List<cfData> o2 ) { try { return o2.get( rsmd.getColumnIndex( colName ) - 1 ).getString().compareToIgnoreCase( o1.get( rsmd.getColumnIndex( colName ) - 1 ).getString() ); } catch ( dataNotSupportedException E ) { return 0; } }// compare() }// TextNoCaseDescComparator class MultiColumnComparator implements Comparator<List<cfData>> { orderByCol[] colList; MultiColumnComparator( List<orderByCol> _cols ) { colList = new orderByCol[ _cols.size() ]; for ( int i = 0; i < colList.length; i++ ) { colList[ i ] = _cols.get( i ); } }// MultiColumnComparator() public int compare( List<cfData> o1, List<cfData> o2 ) { orderByCol obCol; cfData dataItem1, dataItem2; // the components of the 2 rows to compare // loop thru the colList returning if o1 and o2 are not equal on a column for ( int i = 0; i < colList.length; i++ ) { obCol = colList[ i ]; // get columns if ( obCol.isIndex() ) { dataItem1 = o1.get( obCol.getIndex() - 1 ); dataItem2 = o2.get( obCol.getIndex() - 1 ); } else { dataItem1 = o1.get( rsmd.getColumnIndex( obCol.getColName() ) - 1 ); dataItem2 = o2.get( rsmd.getColumnIndex( obCol.getColName() ) - 1 ); } int compResult = cfData.compare( dataItem1, dataItem2 ); if ( compResult != 0 ) { // if items not equal if ( obCol.isAscending() ) { return compResult; } else { return -1 * compResult; // return the reverse of the comparison result } } } return 0; }// compare() }// MultiColumnComparator // ----------------------------------------------------- //--[ Core JTags methods //----------------------------------------------------- private static final FastMap<String, Integer> keyMap = new FastMap<String, Integer>( FastMap.CASE_INSENSITIVE ); static { keyMap.put( "recordcount", new Integer( 0 ) ); keyMap.put( "currentrow", new Integer( 1 ) ); keyMap.put( "columnlist", new Integer( 2 ) ); } /** * WARNING! The performance of this method is critical to overall system * performance. Do not make any changes to this method without doing * before-and-after timing measurements to make sure you have not decreased * performance. */ public cfData getData( String _key ) { if ( getRowCursor() != null ) { int columnIndx = rsmd.getColumnIndex( _key ); if ( columnIndx > 0 ) { cfData cellData = rowCursor.get( columnIndx-1 ); if ( cellData == null ) { cellData = new cfStringData( "" ); cellData.setQueryTableData( tableRows, columnIndx ); } return cellData; } } Integer index = keyMap.get( _key ); if ( index != null ) { switch( index.intValue() ) { case 0 : return new cfNumberData( tableRows.size() ); case 1 : return new cfNumberData( CURRENTROW ); case 2 : return new cfStringData( getColumns() ); default: break; } } if ( ( getSize() == 0 ) && rsmd.getColumnIndex( _key ) > 0 ) return new cfStringData( "" ); return null; } public cfData getData( cfData arrayIndex ) throws cfmRunTimeException { return getData( arrayIndex.getString() ); } public int getSize(){ return tableRows.size(); } public cfStructData getRowAsStruct() { cfStructData sd = new cfStructData(); sd.setData("currentrow", CURRENTROW ); sd.setData("recordcount", tableRows.size() ); List<cfData> rowData = tableRows.get( CURRENTROW-1 ); for ( int cols=0; cols < rsmd.getColumnCount(); cols++ ) { try { sd.setData( rsmd.getColumnName( cols + 1 ), rowData.get(cols) ); } catch (SQLException e) { sd.setData( "Column"+cols, rowData.get(cols-1) ); } } return sd; } //----------------------------------------------------- //--[ Output methods //----------------------------------------------------- public String toString(){ StringBuilder buffer = new StringBuilder( 256 ); buffer.append( "{RESULT: " ); buffer.append( "Records=" + getNoRows() + "," ); buffer.append( "Columns=" ); for ( int cols=1; cols <= rsmd.getColumnCount(); cols++ ) { try { buffer.append( rsmd.getColumnName( cols ) ); } catch ( SQLException e ){ buffer.append( e.getMessage() ); } if ( cols < rsmd.getColumnCount() ) buffer.append( "," ); } buffer.append( "}" ); return buffer.toString(); } public void dump( java.io.PrintWriter out ){ dump( out, "", cfDUMP.TOP_DEFAULT ); } public void dump( java.io.PrintWriter out, String _label, int _top ) { out.write( "<table class='cfdump_table_query'>" ); out.write( "<th class='cfdump_th_query' colspan='2'>" ); if ( _label.length() > 0 ) out.write( _label + " - " ); out.write( "query [short version]</th>" ); out.write( "<tr><td class='cfdump_td_query'>Query Source:</TD><TD class='cfdump_td_value' >"+ querySource +"</td></tr>" ); out.write( getExtraInfo( false ) ); out.write( "<TR><TD class='cfdump_td_query'>Records:</TD>" ); out.write( "<TD class='cfdump_td_value' >"+ getNoRows() +" </TD>"); out.write( "<tr><td class='cfdump_td_query'>Columns:</td>" ); out.write("<td class='cfdump_td_value'>"); for ( int breakCnt=0, cols=1; cols <= rsmd.getColumnCount(); cols++, breakCnt++ ) { try { out.write( rsmd.getColumnName( cols ) ); } catch ( SQLException e ) { out.write( e.getMessage() ); } if(breakCnt == 6 ) { out.write("<br>"); breakCnt=0; } else if(cols<rsmd.getColumnCount() ) out.write( ", " ); } out.write( "</td></tr>" ); out.write( "</table>"); } public void dumpLong( java.io.PrintWriter out ){ dumpLong( out, "", cfDUMP.TOP_DEFAULT ); } public void dumpLong( java.io.PrintWriter out, String _label, int _top ){ out.write( "<table class='cfdump_table_query'>" ); out.write( "<th class='cfdump_th_query' colspan='" + ( rsmd.getColumnCount() + 1 ) + "'>" ); if ( _label.length() > 0 ) out.write( _label + " - " ); out.write( "query [long version]</th>" ); out.write( "<tr>"); out.write( "<td class='cfdump_td_query'> </td>" ); for ( int cols=1; cols <= rsmd.getColumnCount(); cols++ ) { out.write( "<td class='cfdump_td_query'>" ); try { out.write( rsmd.getColumnName( cols ) ); } catch ( SQLException e ) { out.write( e.getMessage() ); } out.write( "</td>" ); } out.write( "</tr>"); // Print out the data part of the table cfData cellData; List<cfData> rowData; int maxRows = ( _top < tableRows.size() ? _top : tableRows.size() ); for ( int rows=0; rows < maxRows; rows++ ) { out.write( "<tr>"); out.write( "<td class='cfdump_td_query'>" + ( rows + 1 ) + "</td>" ); rowData = tableRows.get( rows ); for ( int cols=0; cols < rsmd.getColumnCount(); cols++ ) { out.write( "<td class='cfdump_td_value'>" ); try { cellData = (cfData)rowData.get( cols ); if ( cellData != null ) cellData.dump(out,"",_top); else out.write( " " ); } catch(Exception ignoreIt){out.write( " " );} out.write( "</td>"); } out.write( "</tr>"); } // Print out the footer information out.write( "<tr><td class='cfdump_td_query'>Query Source:</TD><TD class='cfdump_td_value' COLSPAN="+ rsmd.getColumnCount() +">"+ querySource +"</td></tr>" ); out.write( getExtraInfo( true ) ); out.write( "</table>" ); } public void dumpWDDX( int version, java.io.PrintWriter out ){ //--[ Create the header tag if ( version > 10 ) out.write( "<r c='" ); else out.write( "<recordset rowCount='" ); out.write( tableRows.size() + "" ); if ( version > 10 ) out.write( "' n='" ); else out.write( "' fieldNames='" ); int numCols = rsmd.getColumnCount(); for ( int cols=1; cols <= numCols; cols++ ){ try { out.write( rsmd.getColumnName( cols ) ); } catch ( SQLException e ) { out.write( e.getMessage() ); } if( cols < numCols ) out.write( "," ); } out.write( "'>" ); //--[ Generate the body cfData cellData; List<cfData> rowData; for ( int cols=1; cols <= numCols; cols++ ){ if ( version > 10 ) out.write( "<f n='"); else out.write( "<field name='"); try { out.write( rsmd.getColumnName( cols ) ); } catch ( SQLException e ) { out.write( e.getMessage() ); } out.write( "'>" ); for ( int rows=0; rows < tableRows.size(); rows++ ){ rowData = tableRows.get( rows ); cellData = (cfData)rowData.get( cols-1 ); if ( cellData != null ) cellData.dumpWDDX( version, out ); } if ( version > 10 ) out.write( "</f>"); else out.write( "</field>"); } if ( version > 10 ) out.write( "</r>" ); else out.write( "</recordset>" ); } protected String getExtraInfo( boolean _isLong ){ return ""; } /************************************************************************** * * The following methods implement the java.sql.Result interface. They're * here to facility variable sharing with JSP pages. These methods return * "natural" Java objects, not CFML variables. * **************************************************************************/ private boolean wasNull; private cfData getCell( int colNo ) { if ( ( CURRENTROW < 1 ) || ( CURRENTROW > tableRows.size() ) || ( colNo < 1 ) || ( colNo > rsmd.getColumnCount() ) ) { return null; } cfData data = (cfData)tableRows.get( CURRENTROW-1 ).get( colNo-1 ); if ( ( data == null ) || ( data.getDataType() == cfData.CFNULLDATA ) ) { wasNull = true; return null; } wasNull = false; return data; } /** * Moves the cursor down one row from its current position. * A <code>ResultSet</code> cursor is initially positioned * before the first row; the first call to the method * <code>next</code> makes the first row the current row; the * second call makes the second row the current row, and so on. * * <P>If an input stream is open for the current row, a call * to the method <code>next</code> will * implicitly close it. A <code>ResultSet</code> object's * warning chain is cleared when a new row is read. * * @return <code>true</code> if the new current row is valid; * <code>false</code> if there are no more rows * @exception SQLException if a database access error occurs */ public boolean next() throws SQLException { if ( getNoRows() == 0 ) return false; return relative( 1 ); } /** * Releases this <code>ResultSet</code> object's database and * JDBC resources immediately instead of waiting for * this to happen when it is automatically closed. * * <P><B>Note:</B> A <code>ResultSet</code> object * is automatically closed by the * <code>Statement</code> object that generated it when * that <code>Statement</code> object is closed, * re-executed, or is used to retrieve the next result from a * sequence of multiple results. A <code>ResultSet</code> object * is also automatically closed when it is garbage collected. * * @exception SQLException if a database access error occurs */ public void close() throws SQLException { } /** * Reports whether * the last column read had a value of SQL <code>NULL</code>. * Note that you must first call one of the getter methods * on a column to try to read its value and then call * the method <code>wasNull</code> to see if the value read was * SQL <code>NULL</code>. * * @return <code>true</code> if the last column value read was SQL * <code>NULL</code> and <code>false</code> otherwise * @exception SQLException if a database access error occurs */ public boolean wasNull() throws SQLException { return wasNull; } //====================================================================== // Methods for accessing results by column index //====================================================================== /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>String</code> in the Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>null</code> * @exception SQLException if a database access error occurs */ public String getString(int columnIndex) throws SQLException { try { cfData data = getCell( columnIndex ); if ( data == null || data.getDataType() == cfData.CFNULLDATA ) { return null; } return data.getString(); } catch ( dataNotSupportedException e ) { throw new SQLException( "Could not convert value to string" ); } } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>boolean</code> in the Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>false</code> * @exception SQLException if a database access error occurs */ public boolean getBoolean(int columnIndex) throws SQLException { try { cfData data = getCell( columnIndex ); if ( data == null || data.getDataType() == cfData.CFNULLDATA ) { return false; } return data.getBoolean(); } catch ( dataNotSupportedException e ) { throw new SQLException( "Could not convert value to boolean" ); } } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>byte</code> in the Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>0</code> * @exception SQLException if a database access error occurs */ public byte getByte(int columnIndex) throws SQLException { try { cfData data = getCell( columnIndex ); if ( data == null || data.getDataType() == cfData.CFNULLDATA ) { return 0; } return (byte)data.getInt(); } catch ( dataNotSupportedException e ) { throw new SQLException( "Could not convert value to byte" ); } } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>short</code> in the Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>0</code> * @exception SQLException if a database access error occurs */ public short getShort(int columnIndex) throws SQLException { try { cfData data = getCell( columnIndex ); if ( data == null || data.getDataType() == cfData.CFNULLDATA ) { return 0; } return (short)data.getInt(); } catch ( dataNotSupportedException e ) { throw new SQLException( "Could not convert value to short" ); } } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * an <code>int</code> in the Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>0</code> * @exception SQLException if a database access error occurs */ public int getInt(int columnIndex) throws SQLException { try { cfData data = getCell( columnIndex ); if ( data == null || data.getDataType() == cfData.CFNULLDATA ) { return 0; } return data.getInt(); } catch ( dataNotSupportedException e ) { throw new SQLException( "Could not convert value to int" ); } } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>long</code> in the Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>0</code> * @exception SQLException if a database access error occurs */ public long getLong(int columnIndex) throws SQLException { try { cfData data = getCell( columnIndex ); if ( data == null || data.getDataType() == cfData.CFNULLDATA ) { return 0; } return data.getLong(); } catch ( dataNotSupportedException e ) { throw new SQLException( "Could not convert value to long" ); } } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>float</code> in the Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>0</code> * @exception SQLException if a database access error occurs */ public float getFloat(int columnIndex) throws SQLException { try { cfData data = getCell( columnIndex ); if ( data == null || data.getDataType() == cfData.CFNULLDATA ) { return 0; } return (float)data.getDouble(); } catch ( dataNotSupportedException e ) { throw new SQLException( "Could not convert value to float" ); } } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>double</code> in the Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>0</code> * @exception SQLException if a database access error occurs */ public double getDouble(int columnIndex) throws SQLException { try { cfData data = getCell( columnIndex ); if ( data == null || data.getDataType() == cfData.CFNULLDATA ) { return 0; } return data.getDouble(); } catch ( dataNotSupportedException e ) { throw new SQLException( "Could not convert value to double" ); } } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>java.sql.BigDecimal</code> in the Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... * @param scale the number of digits to the right of the decimal point * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>null</code> * @exception SQLException if a database access error occurs * @deprecated */ public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { return getBigDecimal( columnIndex ).setScale( scale, BigDecimal.ROUND_HALF_UP ); } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>byte</code> array in the Java programming language. * The bytes represent the raw values returned by the driver. * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>null</code> * @exception SQLException if a database access error occurs */ public byte[] getBytes(int columnIndex) throws SQLException { try { cfData data = getCell( columnIndex ); if ( data == null || data.getDataType() == cfData.CFNULLDATA ) { return null; } if ( data.getDataType() == cfData.CFBINARYDATA ) { return ((cfBinaryData)data).getByteArray(); } return data.getString().getBytes(); } catch ( dataNotSupportedException e ) { throw new SQLException( "Could not convert value to byte[]" ); } } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>java.sql.Date</code> object in the Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>null</code> * @exception SQLException if a database access error occurs */ public java.sql.Date getDate(int columnIndex) throws SQLException { try { cfData data = getCell( columnIndex ); if ( data == null || data.getDataType() == cfData.CFNULLDATA ) { return null; } return new java.sql.Date( data.getDateData().getLong() ); } catch ( dataNotSupportedException e ) { throw new SQLException( "Could not convert value to java.sql.Date" ); } } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>java.sql.Time</code> object in the Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>null</code> * @exception SQLException if a database access error occurs */ public java.sql.Time getTime(int columnIndex) throws SQLException { try { cfData data = getCell( columnIndex ); if ( data == null || data.getDataType() == cfData.CFNULLDATA ) { return null; } return new java.sql.Time( data.getDateData().getLong() ); } catch ( dataNotSupportedException e ) { throw new SQLException( "Could not convert value to java.sql.Time" ); } } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>java.sql.Timestamp</code> object in the Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>null</code> * @exception SQLException if a database access error occurs */ public java.sql.Timestamp getTimestamp(int columnIndex) throws SQLException { try { cfData data = getCell( columnIndex ); if ( data == null || data.getDataType() == cfData.CFNULLDATA ) { return null; } return new java.sql.Timestamp( data.getDateData().getLong() ); } catch ( dataNotSupportedException e ) { throw new SQLException( "Could not convert value to java.sql.Timestamp" ); } } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a stream of ASCII characters. The value can then be read in chunks from the * stream. This method is particularly * suitable for retrieving large <char>LONGVARCHAR</char> values. * The JDBC driver will * do any necessary conversion from the database format into ASCII. * * <P><B>Note:</B> All the data in the returned stream must be * read prior to getting the value of any other column. The next * call to a getter method implicitly closes the stream. Also, a * stream may return <code>0</code> when the method * <code>InputStream.available</code> * is called whether there is data available or not. * * @param columnIndex the first column is 1, the second is 2, ... * @return a Java input stream that delivers the database column value * as a stream of one-byte ASCII characters; * if the value is SQL <code>NULL</code>, the * value returned is <code>null</code> * @exception SQLException if a database access error occurs */ public InputStream getAsciiStream(int columnIndex) throws SQLException { return null; } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * as a stream of two-byte Unicode characters. The first byte is * the high byte; the second byte is the low byte. * * The value can then be read in chunks from the * stream. This method is particularly * suitable for retrieving large <code>LONGVARCHAR</code>values. The * JDBC driver will do any necessary conversion from the database * format into Unicode. * * <P><B>Note:</B> All the data in the returned stream must be * read prior to getting the value of any other column. The next * call to a getter method implicitly closes the stream. * Also, a stream may return <code>0</code> when the method * <code>InputStream.available</code> * is called, whether there is data available or not. * * @param columnIndex the first column is 1, the second is 2, ... * @return a Java input stream that delivers the database column value * as a stream of two-byte Unicode characters; * if the value is SQL <code>NULL</code>, the value returned is * <code>null</code> * * @exception SQLException if a database access error occurs * @deprecated use <code>getCharacterStream</code> in place of * <code>getUnicodeStream</code> */ public InputStream getUnicodeStream(int columnIndex) throws SQLException { return null; } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as a binary stream of * uninterpreted bytes. The value can then be read in chunks from the * stream. This method is particularly * suitable for retrieving large <code>LONGVARBINARY</code> values. * * <P><B>Note:</B> All the data in the returned stream must be * read prior to getting the value of any other column. The next * call to a getter method implicitly closes the stream. Also, a * stream may return <code>0</code> when the method * <code>InputStream.available</code> * is called whether there is data available or not. * * @param columnIndex the first column is 1, the second is 2, ... * @return a Java input stream that delivers the database column value * as a stream of uninterpreted bytes; * if the value is SQL <code>NULL</code>, the value returned is * <code>null</code> * @exception SQLException if a database access error occurs */ public InputStream getBinaryStream(int columnIndex) throws SQLException { return null; } //====================================================================== // Methods for accessing results by column name //====================================================================== /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>String</code> in the Java programming language. * * @param columnName the SQL name of the column * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>null</code> * @exception SQLException if a database access error occurs */ public String getString( String columnName ) throws SQLException { return getString( findColumn( columnName ) ); } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>boolean</code> in the Java programming language. * * @param columnName the SQL name of the column * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>false</code> * @exception SQLException if a database access error occurs */ public boolean getBoolean( String columnName ) throws SQLException { return getBoolean( findColumn( columnName ) ); } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>byte</code> in the Java programming language. * * @param columnName the SQL name of the column * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>0</code> * @exception SQLException if a database access error occurs */ public byte getByte( String columnName ) throws SQLException { return getByte( findColumn( columnName ) ); } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>short</code> in the Java programming language. * * @param columnName the SQL name of the column * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>0</code> * @exception SQLException if a database access error occurs */ public short getShort( String columnName ) throws SQLException { return getShort( findColumn( columnName ) ); } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * an <code>int</code> in the Java programming language. * * @param columnName the SQL name of the column * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>0</code> * @exception SQLException if a database access error occurs */ public int getInt( String columnName ) throws SQLException { return getInt( findColumn( columnName ) ); } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>long</code> in the Java programming language. * * @param columnName the SQL name of the column * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>0</code> * @exception SQLException if a database access error occurs */ public long getLong( String columnName ) throws SQLException { return getLong( findColumn( columnName ) ); } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>float</code> in the Java programming language. * * @param columnName the SQL name of the column * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>0</code> * @exception SQLException if a database access error occurs */ public float getFloat( String columnName ) throws SQLException { return getFloat( findColumn( columnName ) ); } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>double</code> in the Java programming language. * * @param columnName the SQL name of the column * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>0</code> * @exception SQLException if a database access error occurs */ public double getDouble( String columnName ) throws SQLException { return getDouble( findColumn( columnName ) ); } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>java.math.BigDecimal</code> in the Java programming language. * * @param columnName the SQL name of the column * @param scale the number of digits to the right of the decimal point * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>null</code> * @exception SQLException if a database access error occurs * @deprecated */ public BigDecimal getBigDecimal( String columnName, int scale ) throws SQLException { return getBigDecimal( findColumn( columnName ), scale ); } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>byte</code> array in the Java programming language. * The bytes represent the raw values returned by the driver. * * @param columnName the SQL name of the column * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>null</code> * @exception SQLException if a database access error occurs */ public byte[] getBytes( String columnName ) throws SQLException { return getBytes( findColumn( columnName ) ); } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>java.sql.Date</code> object in the Java programming language. * * @param columnName the SQL name of the column * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>null</code> * @exception SQLException if a database access error occurs */ public java.sql.Date getDate( String columnName ) throws SQLException { return getDate( findColumn( columnName ) ); } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>java.sql.Time</code> object in the Java programming language. * * @param columnName the SQL name of the column * @return the column value; * if the value is SQL <code>NULL</code>, * the value returned is <code>null</code> * @exception SQLException if a database access error occurs */ public java.sql.Time getTime( String columnName ) throws SQLException { return getTime( findColumn( columnName ) ); } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as * a <code>java.sql.Timestamp</code> object. * * @param columnName the SQL name of the column * @return the column value; if the value is SQL <code>NULL</code>, the * value returned is <code>null</code> * @exception SQLException if a database access error occurs */ public java.sql.Timestamp getTimestamp( String columnName ) throws SQLException { return getTimestamp( findColumn( columnName ) ); } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as a stream of * ASCII characters. The value can then be read in chunks from the * stream. This method is particularly * suitable for retrieving large <code>LONGVARCHAR</code> values. * The JDBC driver will * do any necessary conversion from the database format into ASCII. * * <P><B>Note:</B> All the data in the returned stream must be * read prior to getting the value of any other column. The next * call to a getter method implicitly closes the stream. Also, a * stream may return <code>0</code> when the method <code>available</code> * is called whether there is data available or not. * * @param columnName the SQL name of the column * @return a Java input stream that delivers the database column value * as a stream of one-byte ASCII characters. * If the value is SQL <code>NULL</code>, * the value returned is <code>null</code>. * @exception SQLException if a database access error occurs */ public InputStream getAsciiStream( String columnName ) throws SQLException { return getAsciiStream( findColumn( columnName ) ); } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as a stream of two-byte * Unicode characters. The first byte is the high byte; the second * byte is the low byte. * * The value can then be read in chunks from the * stream. This method is particularly * suitable for retrieving large <code>LONGVARCHAR</code> values. * The JDBC technology-enabled driver will * do any necessary conversion from the database format into Unicode. * * <P><B>Note:</B> All the data in the returned stream must be * read prior to getting the value of any other column. The next * call to a getter method implicitly closes the stream. * Also, a stream may return <code>0</code> when the method * <code>InputStream.available</code> is called, whether there * is data available or not. * * @param columnName the SQL name of the column * @return a Java input stream that delivers the database column value * as a stream of two-byte Unicode characters. * If the value is SQL <code>NULL</code>, the value returned * is <code>null</code>. * @exception SQLException if a database access error occurs * @deprecated use <code>getCharacterStream</code> instead */ public InputStream getUnicodeStream( String columnName ) throws SQLException { return getUnicodeStream( findColumn( columnName ) ); } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as a stream of uninterpreted * <code>byte</code>s. * The value can then be read in chunks from the * stream. This method is particularly * suitable for retrieving large <code>LONGVARBINARY</code> * values. * * <P><B>Note:</B> All the data in the returned stream must be * read prior to getting the value of any other column. The next * call to a getter method implicitly closes the stream. Also, a * stream may return <code>0</code> when the method <code>available</code> * is called whether there is data available or not. * * @param columnName the SQL name of the column * @return a Java input stream that delivers the database column value * as a stream of uninterpreted bytes; * if the value is SQL <code>NULL</code>, the result is <code>null</code> * @exception SQLException if a database access error occurs */ public InputStream getBinaryStream( String columnName ) throws SQLException { return getBinaryStream( findColumn( columnName ) ); } //===================================================================== // Advanced features: //===================================================================== /** * Retrieves the first warning reported by calls on this * <code>ResultSet</code> object. * Subsequent warnings on this <code>ResultSet</code> object * will be chained to the <code>SQLWarning</code> object that * this method returns. * * <P>The warning chain is automatically cleared each time a new * row is read. This method may not be called on a <code>ResultSet</code> * object that has been closed; doing so will cause an * <code>SQLException</code> to be thrown. * <P> * <B>Note:</B> This warning chain only covers warnings caused * by <code>ResultSet</code> methods. Any warning caused by * <code>Statement</code> methods * (such as reading OUT parameters) will be chained on the * <code>Statement</code> object. * * @return the first <code>SQLWarning</code> object reported or * <code>null</code> if there are none * @exception SQLException if a database access error occurs or this method is * called on a closed result set */ public SQLWarning getWarnings() throws SQLException { return null; } /** * Clears all warnings reported on this <code>ResultSet</code> object. * After this method is called, the method <code>getWarnings</code> * returns <code>null</code> until a new warning is * reported for this <code>ResultSet</code> object. * * @exception SQLException if a database access error occurs */ public void clearWarnings() throws SQLException { } /** * Retrieves the name of the SQL cursor used by this <code>ResultSet</code> * object. * * <P>In SQL, a result table is retrieved through a cursor that is * named. The current row of a result set can be updated or deleted * using a positioned update/delete statement that references the * cursor name. To insure that the cursor has the proper isolation * level to support update, the cursor's <code>SELECT</code> statement * should be of the form <code>SELECT FOR UPDATE</code>. If * <code>FOR UPDATE</code> is omitted, the positioned updates may fail. * * <P>The JDBC API supports this SQL feature by providing the name of the * SQL cursor used by a <code>ResultSet</code> object. * The current row of a <code>ResultSet</code> object * is also the current row of this SQL cursor. * * <P><B>Note:</B> If positioned update is not supported, a * <code>SQLException</code> is thrown. * * @return the SQL name for this <code>ResultSet</code> object's cursor * @exception SQLException if a database access error occurs */ public String getCursorName() throws SQLException { throw new SQLException( "positioned update not supported" ); } /** * Retrieves the number, types and properties of * this <code>ResultSet</code> object's columns. * * @return the description of this <code>ResultSet</code> object's columns * @exception SQLException if a database access error occurs */ public ResultSetMetaData getMetaData() throws SQLException { return rsmd; } /** * <p>Gets the value of the designated column in the current row * of this <code>ResultSet</code> object as * an <code>Object</code> in the Java programming language. * * <p>This method will return the value of the given column as a * Java object. The type of the Java object will be the default * Java object type corresponding to the column's SQL type, * following the mapping for built-in types specified in the JDBC * specification. If the value is an SQL <code>NULL</code>, * the driver returns a Java <code>null</code>. * * <p>This method may also be used to read database-specific * abstract data types. * * In the JDBC 2.0 API, the behavior of method * <code>getObject</code> is extended to materialize * data of SQL user-defined types. When a column contains * a structured or distinct value, the behavior of this method is as * if it were a call to: <code>getObject(columnIndex, * this.getStatement().getConnection().getTypeMap())</code>. * * @param columnIndex the first column is 1, the second is 2, ... * @return a <code>java.lang.Object</code> holding the column value * @exception SQLException if a database access error occurs */ public Object getObject(int columnIndex) throws SQLException { // Need to check for null first since some getXXX() methods like getLong() will // return 0 when the value is null. In this case we need to return null instead of 0. cfData data = getCell( columnIndex ); if ( data == null || data.getDataType() == cfData.CFNULLDATA ) { return null; } int type = rsmd.getColumnType( columnIndex ); switch ( type ) { case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: return getString( columnIndex ); case Types.NUMERIC: case Types.DECIMAL: return getBigDecimal( columnIndex ); case Types.BIT: return new Boolean( getBoolean( columnIndex ) ); case Types.TINYINT: return new Byte( getByte( columnIndex ) ); case Types.SMALLINT: return new Short( getShort( columnIndex ) ); case Types.INTEGER: return new Integer( getInt( columnIndex ) ); case Types.BIGINT: return new Long( getLong( columnIndex ) ); case Types.REAL: return new Float( getFloat( columnIndex ) ); case Types.FLOAT: case Types.DOUBLE: return new Double( getDouble( columnIndex ) ); case Types.BINARY: case Types.VARBINARY: case Types.LONGVARBINARY: return getBytes( columnIndex ); case Types.DATE: return getDate( columnIndex ); case Types.TIME: return getTime( columnIndex ); case Types.TIMESTAMP: return getTimestamp( columnIndex ); case Types.CLOB : return getClob( columnIndex ); case Types.BLOB : return getBlob( columnIndex ); case Types.ARRAY : return getArray( columnIndex ); case Types.REF : return getRef( columnIndex ); case Types.OTHER: String columnName = rsmd.getColumnTypeName( columnIndex ); if ( columnName != null ) { if ( columnName.equals( "binary" ) ) return getBytes( columnIndex ); if ( columnName.equals( "varbinary" ) ) return getBytes( columnIndex ); } default: throw new SQLException( "getObject() does not support the java.sql.Types value " + type ); } } /** * <p>Gets the value of the designated column in the current row * of this <code>ResultSet</code> object as * an <code>Object</code> in the Java programming language. * * <p>This method will return the value of the given column as a * Java object. The type of the Java object will be the default * Java object type corresponding to the column's SQL type, * following the mapping for built-in types specified in the JDBC * specification. If the value is an SQL <code>NULL</code>, * the driver returns a Java <code>null</code>. * <P> * This method may also be used to read database-specific * abstract data types. * <P> * In the JDBC 2.0 API, the behavior of the method * <code>getObject</code> is extended to materialize * data of SQL user-defined types. When a column contains * a structured or distinct value, the behavior of this method is as * if it were a call to: <code>getObject(columnIndex, * this.getStatement().getConnection().getTypeMap())</code>. * * @param columnName the SQL name of the column * @return a <code>java.lang.Object</code> holding the column value * @exception SQLException if a database access error occurs */ public Object getObject( String columnName ) throws SQLException { return getObject( findColumn( columnName ) ); } //---------------------------------------------------------------- /** * Maps the given <code>ResultSet</code> column name to its * <code>ResultSet</code> column index. * * @param columnName the name of the column * @return the column index of the given column name * @exception SQLException if the <code>ResultSet</code> object * does not contain <code>columnName</code> or a database access error occurs */ public int findColumn( String columnName ) throws SQLException { return rsmd.getColumnIndex( columnName ); } //--------------------------JDBC 2.0----------------------------------- //--------------------------------------------------------------------- // Getters and Setters //--------------------------------------------------------------------- /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as a * <code>java.io.Reader</code> object. * @return a <code>java.io.Reader</code> object that contains the column * value; if the value is SQL <code>NULL</code>, the value returned is * <code>null</code> in the Java programming language. * @param columnIndex the first column is 1, the second is 2, ... * @exception SQLException if a database access error occurs * @since 1.2 */ public Reader getCharacterStream(int columnIndex) throws SQLException { return null; } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as a * <code>java.io.Reader</code> object. * * @param columnName the name of the column * @return a <code>java.io.Reader</code> object that contains the column * value; if the value is SQL <code>NULL</code>, the value returned is * <code>null</code> in the Java programming language * @exception SQLException if a database access error occurs * @since 1.2 */ public Reader getCharacterStream(String columnName) throws SQLException { return null; } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as a * <code>java.math.BigDecimal</code> with full precision. * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value (full precision); * if the value is SQL <code>NULL</code>, the value returned is * <code>null</code> in the Java programming language. * @exception SQLException if a database access error occurs * @since 1.2 */ public BigDecimal getBigDecimal(int columnIndex) throws SQLException { try { cfData data = getCell( columnIndex ); if ( data == null || data.getDataType() == cfData.CFNULLDATA ) { return null; } return new BigDecimal( data.getDouble() ); } catch ( dataNotSupportedException e ) { throw new SQLException( "Could not convert value to BigDecimal" ); } } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as a * <code>java.math.BigDecimal</code> with full precision. * * @param columnName the column name * @return the column value (full precision); * if the value is SQL <code>NULL</code>, the value returned is * <code>null</code> in the Java programming language. * @exception SQLException if a database access error occurs * @since 1.2 * */ public BigDecimal getBigDecimal(String columnName) throws SQLException { return getBigDecimal( findColumn( columnName ) ); } //--------------------------------------------------------------------- // Traversal/Positioning //--------------------------------------------------------------------- /** * Retrieves whether the cursor is before the first row in * this <code>ResultSet</code> object. * * @return <code>true</code> if the cursor is before the first row; * <code>false</code> if the cursor is at any other position or the * result set contains no rows * @exception SQLException if a database access error occurs * @since 1.2 */ public boolean isBeforeFirst() throws SQLException { if ( ( getNoRows() == 0 ) || ( CURRENTROW != 0 ) ) return false; return true; } /** * Retrieves whether the cursor is after the last row in * this <code>ResultSet</code> object. * * @return <code>true</code> if the cursor is after the last row; * <code>false</code> if the cursor is at any other position or the * result set contains no rows * @exception SQLException if a database access error occurs * @since 1.2 */ public boolean isAfterLast() throws SQLException { if ( ( getNoRows() == 0 ) || ( CURRENTROW != ( LASTROW + 1 ) ) ) return false; return true; } /** * Retrieves whether the cursor is on the first row of * this <code>ResultSet</code> object. * * @return <code>true</code> if the cursor is on the first row; * <code>false</code> otherwise * @exception SQLException if a database access error occurs * @since 1.2 */ public boolean isFirst() throws SQLException { if ( getNoRows() == 0 ) return false; return ( CURRENTROW == 1 ); } /** * Retrieves whether the cursor is on the last row of * this <code>ResultSet</code> object. * Note: Calling the method <code>isLast</code> may be expensive * because the JDBC driver * might need to fetch ahead one row in order to determine * whether the current row is the last row in the result set. * * @return <code>true</code> if the cursor is on the last row; * <code>false</code> otherwise * @exception SQLException if a database access error occurs * @since 1.2 */ public boolean isLast() throws SQLException { if ( getNoRows() == 0 ) return false; return ( CURRENTROW == LASTROW ); } /** * Moves the cursor to the front of * this <code>ResultSet</code> object, just before the * first row. This method has no effect if the result set contains no rows. * * @exception SQLException if a database access error * occurs or the result set type is <code>TYPE_FORWARD_ONLY</code> * @since 1.2 */ public void beforeFirst() { reset(); } /** * Moves the cursor to the end of * this <code>ResultSet</code> object, just after the * last row. This method has no effect if the result set contains no rows. * @exception SQLException if a database access error * occurs or the result set type is <code>TYPE_FORWARD_ONLY</code> * @since 1.2 */ public void afterLast() { if ( getNoRows() > 0 ) { CURRENTROW = LASTROW + 1; rowCursor = null; } } /** * Moves the cursor to the first row in * this <code>ResultSet</code> object. * * @return <code>true</code> if the cursor is on a valid row; * <code>false</code> if there are no rows in the result set * @exception SQLException if a database access error * occurs or the result set type is <code>TYPE_FORWARD_ONLY</code> * @since 1.2 */ public boolean first() throws SQLException { if ( getNoRows() == 0 ) return false; return absolute( 1 ); } /** * Moves the cursor to the last row in * this <code>ResultSet</code> object. * * @return <code>true</code> if the cursor is on a valid row; * <code>false</code> if there are no rows in the result set * @exception SQLException if a database access error * occurs or the result set type is <code>TYPE_FORWARD_ONLY</code> * @since 1.2 */ public boolean last() throws SQLException { if ( ( getNoRows() == 0 ) ) return false; return absolute( -1 ); } /** * Retrieves the current row number. The first row is number 1, the * second number 2, and so on. * * @return the current row number; <code>0</code> if there is no current row * @exception SQLException if a database access error occurs * @since 1.2 */ public int getRow() throws SQLException { if ( CURRENTROW > LASTROW ) return 0; return CURRENTROW; } /** * Moves the cursor to the given row number in * this <code>ResultSet</code> object. * * <p>If the row number is positive, the cursor moves to * the given row number with respect to the * beginning of the result set. The first row is row 1, the second * is row 2, and so on. * * <p>If the given row number is negative, the cursor moves to * an absolute row position with respect to * the end of the result set. For example, calling the method * <code>absolute(-1)</code> positions the * cursor on the last row; calling the method <code>absolute(-2)</code> * moves the cursor to the next-to-last row, and so on. * * <p>An attempt to position the cursor beyond the first/last row in * the result set leaves the cursor before the first row or after * the last row. * * <p><B>Note:</B> Calling <code>absolute(1)</code> is the same * as calling <code>first()</code>. Calling <code>absolute(-1)</code> * is the same as calling <code>last()</code>. * * @param row the number of the row to which the cursor should move. * A positive number indicates the row number counting from the * beginning of the result set; a negative number indicates the * row number counting from the end of the result set * @return <code>true</code> if the cursor is on the result set; * <code>false</code> otherwise * @exception SQLException if a database access error * occurs, or the result set type is <code>TYPE_FORWARD_ONLY</code> * @since 1.2 */ public boolean absolute( int row ) { if ( getNoRows() == 0 ) return false; if ( row > 0 ) { if ( row <= tableRows.size() ) { CURRENTROW = row; rowCursor = tableRows.get( CURRENTROW - 1 ); return true; } else { afterLast(); return false; } } else if ( row < 0 ) { CURRENTROW = tableRows.size() + row + 1; // row is negative, so we're subtracting it here if ( CURRENTROW <= tableRows.size() ) { rowCursor = tableRows.get( CURRENTROW - 1 ); return true; } } // ( row == 0 ) or negative row number past first beforeFirst(); return false; } /** * Moves the cursor a relative number of rows, either positive or negative. * Attempting to move beyond the first/last row in the * result set positions the cursor before/after the * the first/last row. Calling <code>relative(0)</code> is valid, but does * not change the cursor position. * * <p>Note: Calling the method <code>relative(1)</code> * is identical to calling the method <code>next()</code> and * calling the method <code>relative(-1)</code> is identical * to calling the method <code>previous()</code>. * * @param rows an <code>int</code> specifying the number of rows to * move from the current row; a positive number moves the cursor * forward; a negative number moves the cursor backward * @return <code>true</code> if the cursor is on a row; * <code>false</code> otherwise * @exception SQLException if a database access error occurs, * there is no current row, or the result set type is * <code>TYPE_FORWARD_ONLY</code> * @since 1.2 */ public boolean relative( int rows ) { if ( getNoRows() == 0 ) return false; return absolute( CURRENTROW + rows ); } /** * Moves the cursor to the previous row in this * <code>ResultSet</code> object. * * @return <code>true</code> if the cursor is on a valid row; * <code>false</code> if it is off the result set * @exception SQLException if a database access error * occurs or the result set type is <code>TYPE_FORWARD_ONLY</code> * @since 1.2 */ public boolean previous() throws SQLException { if ( getNoRows() == 0 ) return false; return relative( -1 ); } /** * Gives a hint as to the direction in which the rows in this * <code>ResultSet</code> object will be processed. * The initial value is determined by the * <code>Statement</code> object * that produced this <code>ResultSet</code> object. * The fetch direction may be changed at any time. * * @param direction an <code>int</code> specifying the suggested * fetch direction; one of <code>ResultSet.FETCH_FORWARD</code>, * <code>ResultSet.FETCH_REVERSE</code>, or * <code>ResultSet.FETCH_UNKNOWN</code> * @exception SQLException if a database access error occurs or * the result set type is <code>TYPE_FORWARD_ONLY</code> and the fetch * direction is not <code>FETCH_FORWARD</code> * @since 1.2 * @see Statement#setFetchDirection * @see #getFetchDirection */ public void setFetchDirection(int direction) throws SQLException { } /** * Retrieves the fetch direction for this * <code>ResultSet</code> object. * * @return the current fetch direction for this <code>ResultSet</code> object * @exception SQLException if a database access error occurs * @since 1.2 * @see #setFetchDirection */ public int getFetchDirection() throws SQLException { return ResultSet.FETCH_FORWARD; } /** * Gives the JDBC driver a hint as to the number of rows that should * be fetched from the database when more rows are needed for this * <code>ResultSet</code> object. * If the fetch size specified is zero, the JDBC driver * ignores the value and is free to make its own best guess as to what * the fetch size should be. The default value is set by the * <code>Statement</code> object * that created the result set. The fetch size may be changed at any time. * * @param rows the number of rows to fetch * @exception SQLException if a database access error occurs or the * condition <code>0 <= rows <= Statement.getMaxRows()</code> is not satisfied * @since 1.2 * @see #getFetchSize */ public void setFetchSize(int rows) throws SQLException { } /** * Retrieves the fetch size for this * <code>ResultSet</code> object. * * @return the current fetch size for this <code>ResultSet</code> object * @exception SQLException if a database access error occurs * @since 1.2 * @see #setFetchSize */ public int getFetchSize() throws SQLException { return 0; } /** * Retrieves the type of this <code>ResultSet</code> object. * The type is determined by the <code>Statement</code> object * that created the result set. * * @return <code>ResultSet.TYPE_FORWARD_ONLY</code>, * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, * or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code> * @exception SQLException if a database access error occurs * @since 1.2 */ public int getType() throws SQLException { return ResultSet.TYPE_SCROLL_INSENSITIVE; } /** * Retrieves the concurrency mode of this <code>ResultSet</code> object. * The concurrency used is determined by the * <code>Statement</code> object that created the result set. * * @return the concurrency type, either * <code>ResultSet.CONCUR_READ_ONLY</code> * or <code>ResultSet.CONCUR_UPDATABLE</code> * @exception SQLException if a database access error occurs * @since 1.2 */ public int getConcurrency() throws SQLException { return ResultSet.CONCUR_READ_ONLY; } //--------------------------------------------------------------------- // Updates //--------------------------------------------------------------------- /** * Retrieves whether the current row has been updated. The value returned * depends on whether or not the result set can detect updates. * * @return <code>true</code> if both (1) the row has been visibly updated * by the owner or another and (2) updates are detected * @exception SQLException if a database access error occurs * @see DatabaseMetaData#updatesAreDetected * @since 1.2 */ public boolean rowUpdated() throws SQLException { return false; } /** * Retrieves whether the current row has had an insertion. * The value returned depends on whether or not this * <code>ResultSet</code> object can detect visible inserts. * * @return <code>true</code> if a row has had an insertion * and insertions are detected; <code>false</code> otherwise * @exception SQLException if a database access error occurs * * @see DatabaseMetaData#insertsAreDetected * @since 1.2 */ public boolean rowInserted() throws SQLException { return false; } /** * Retrieves whether a row has been deleted. A deleted row may leave * a visible "hole" in a result set. This method can be used to * detect holes in a result set. The value returned depends on whether * or not this <code>ResultSet</code> object can detect deletions. * * @return <code>true</code> if a row was deleted and deletions are detected; * <code>false</code> otherwise * @exception SQLException if a database access error occurs * * @see DatabaseMetaData#deletesAreDetected * @since 1.2 */ public boolean rowDeleted() throws SQLException { return false; } /** * Gives a nullable column a null value. * * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> * or <code>insertRow</code> methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateNull(int columnIndex) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>boolean</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateBoolean(int columnIndex, boolean x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>byte</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateByte(int columnIndex, byte x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>short</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateShort(int columnIndex, short x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with an <code>int</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateInt(int columnIndex, int x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>long</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateLong(int columnIndex, long x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>float</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateFloat(int columnIndex, float x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>double</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateDouble(int columnIndex, double x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>java.math.BigDecimal</code> * value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>String</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateString(int columnIndex, String x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>byte</code> array value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateBytes(int columnIndex, byte x[]) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>java.sql.Date</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateDate(int columnIndex, java.sql.Date x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>java.sql.Time</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateTime(int columnIndex, java.sql.Time x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>java.sql.Timestamp</code> * value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateTimestamp(int columnIndex, java.sql.Timestamp x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with an ascii stream value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @param length the length of the stream * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateAsciiStream(int columnIndex, java.io.InputStream x, int length) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a binary stream value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @param length the length of the stream * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateBinaryStream(int columnIndex, java.io.InputStream x, int length) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a character stream value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @param length the length of the stream * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateCharacterStream(int columnIndex, java.io.Reader x, int length) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with an <code>Object</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @param scale for <code>java.sql.Types.DECIMA</code> * or <code>java.sql.Types.NUMERIC</code> types, * this is the number of digits after the decimal point. For all other * types this value will be ignored. * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateObject(int columnIndex, Object x, int scale) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with an <code>Object</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateObject(int columnIndex, Object x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>null</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnName the name of the column * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateNull(String columnName) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>boolean</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateBoolean(String columnName, boolean x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>byte</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateByte(String columnName, byte x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>short</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateShort(String columnName, short x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with an <code>int</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateInt(String columnName, int x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>long</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateLong(String columnName, long x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>float </code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateFloat(String columnName, float x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>double</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateDouble(String columnName, double x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>java.sql.BigDecimal</code> * value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateBigDecimal(String columnName, BigDecimal x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>String</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateString(String columnName, String x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a byte array value. * * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> * or <code>insertRow</code> methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateBytes(String columnName, byte x[]) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>java.sql.Date</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateDate(String columnName, java.sql.Date x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>java.sql.Time</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateTime(String columnName, java.sql.Time x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a <code>java.sql.Timestamp</code> * value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateTimestamp(String columnName, java.sql.Timestamp x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with an ascii stream value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @param length the length of the stream * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateAsciiStream(String columnName, java.io.InputStream x, int length) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a binary stream value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @param length the length of the stream * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateBinaryStream(String columnName, java.io.InputStream x, int length) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with a character stream value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnName the name of the column * @param reader the <code>java.io.Reader</code> object containing * the new column value * @param length the length of the stream * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateCharacterStream(String columnName, java.io.Reader reader, int length) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with an <code>Object</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @param scale for <code>java.sql.Types.DECIMAL</code> * or <code>java.sql.Types.NUMERIC</code> types, * this is the number of digits after the decimal point. For all other * types this value will be ignored. * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateObject(String columnName, Object x, int scale) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Updates the designated column with an <code>Object</code> value. * The updater methods are used to update column values in the * current row or the insert row. The updater methods do not * update the underlying database; instead the <code>updateRow</code> or * <code>insertRow</code> methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database access error occurs * @since 1.2 */ public void updateObject(String columnName, Object x) throws SQLException { throw new SQLException( "updates not supported" ); } /** * Inserts the contents of the insert row into this * <code>ResultSet</code> object and into the database. * The cursor must be on the insert row when this method is called. * * @exception SQLException if a database access error occurs, * if this method is called when the cursor is not on the insert row, * or if not all of non-nullable columns in * the insert row have been given a value * @since 1.2 */ public void insertRow() throws SQLException { throw new SQLException( "insert not supported" ); } /** * Updates the underlying database with the new contents of the * current row of this <code>ResultSet</code> object. * This method cannot be called when the cursor is on the insert row. * * @exception SQLException if a database access error occurs or * if this method is called when the cursor is on the insert row * @since 1.2 */ public void updateRow() throws SQLException { throw new SQLException( "updates not supported" ); } /** * Deletes the current row from this <code>ResultSet</code> object * and from the underlying database. This method cannot be called when * the cursor is on the insert row. * * @exception SQLException if a database access error occurs * or if this method is called when the cursor is on the insert row * @since 1.2 */ public void deleteRow() throws SQLException { throw new SQLException( "delete not supported" ); } /** * Refreshes the current row with its most recent value in * the database. This method cannot be called when * the cursor is on the insert row. * * <P>The <code>refreshRow</code> method provides a way for an * application to * explicitly tell the JDBC driver to refetch a row(s) from the * database. An application may want to call <code>refreshRow</code> when * caching or prefetching is being done by the JDBC driver to * fetch the latest value of a row from the database. The JDBC driver * may actually refresh multiple rows at once if the fetch size is * greater than one. * * <P> All values are refetched subject to the transaction isolation * level and cursor sensitivity. If <code>refreshRow</code> is called after * calling an updater method, but before calling * the method <code>updateRow</code>, then the * updates made to the row are lost. Calling the method * <code>refreshRow</code> frequently will likely slow performance. * * @exception SQLException if a database access error * occurs or if this method is called when the cursor is on the insert row * @since 1.2 */ public void refreshRow() throws SQLException { throw new SQLException( "refresh not supported" ); } /** * Cancels the updates made to the current row in this * <code>ResultSet</code> object. * This method may be called after calling an * updater method(s) and before calling * the method <code>updateRow</code> to roll back * the updates made to a row. If no updates have been made or * <code>updateRow</code> has already been called, this method has no * effect. * * @exception SQLException if a database access error * occurs or if this method is called when the cursor is * on the insert row * @since 1.2 */ public void cancelRowUpdates() throws SQLException { throw new SQLException( "updates not supported" ); } /** * Moves the cursor to the insert row. The current cursor position is * remembered while the cursor is positioned on the insert row. * * The insert row is a special row associated with an updatable * result set. It is essentially a buffer where a new row may * be constructed by calling the updater methods prior to * inserting the row into the result set. * * Only the updater, getter, * and <code>insertRow</code> methods may be * called when the cursor is on the insert row. All of the columns in * a result set must be given a value each time this method is * called before calling <code>insertRow</code>. * An updater method must be called before a * getter method can be called on a column value. * * @exception SQLException if a database access error occurs * or the result set is not updatable * @since 1.2 */ public void moveToInsertRow() throws SQLException { throw new SQLException( "insert not supported" ); } /** * Moves the cursor to the remembered cursor position, usually the * current row. This method has no effect if the cursor is not on * the insert row. * * @exception SQLException if a database access error occurs * or the result set is not updatable * @since 1.2 */ public void moveToCurrentRow() throws SQLException { } /** * Retrieves the <code>Statement</code> object that produced this * <code>ResultSet</code> object. * If the result set was generated some other way, such as by a * <code>DatabaseMetaData</code> method, this method returns * <code>null</code>. * * @return the <code>Statment</code> object that produced * this <code>ResultSet</code> object or <code>null</code> * if the result set was produced some other way * @exception SQLException if a database access error occurs * @since 1.2 */ public Statement getStatement() throws SQLException { return null; } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as an <code>Object</code> * in the Java programming language. * If the value is an SQL <code>NULL</code>, * the driver returns a Java <code>null</code>. * This method uses the given <code>Map</code> object * for the custom mapping of the * SQL structured or distinct type that is being retrieved. * * @param i the first column is 1, the second is 2, ... * @param map a <code>java.util.Map</code> object that contains the mapping * from SQL type names to classes in the Java programming language * @return an <code>Object</code> in the Java programming language * representing the SQL value * @exception SQLException if a database access error occurs * @since 1.2 */ public Object getObject(int i, java.util.Map<String, Class<?>> map) throws SQLException { // NOTE: the map parameter is ignored for now. This parameter is used to map // SQL user-defined types (UDTs) to a Java class. If any of our customers // start to use UDTs then this method will need to be updated. // Refer to Chapter 35 of "JDBC API Tutorial and Reference, Second Edition" return getObject( i ); } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as a <code>Ref</code> object * in the Java programming language. * * @param i the first column is 1, the second is 2, ... * @return a <code>Ref</code> object representing an SQL <code>REF</code> * value * @exception SQLException if a database access error occurs * @since 1.2 */ public Ref getRef(int i) throws SQLException { return null; } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as a <code>Blob</code> object * in the Java programming language. * * @param i the first column is 1, the second is 2, ... * @return a <code>Blob</code> object representing the SQL * <code>BLOB</code> value in the specified column * @exception SQLException if a database access error occurs * @since 1.2 */ public Blob getBlob(int i) throws SQLException { return null; } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as a <code>Clob</code> object * in the Java programming language. * * @param i the first column is 1, the second is 2, ... * @return a <code>Clob</code> object representing the SQL * <code>CLOB</code> value in the specified column * @exception SQLException if a database access error occurs * @since 1.2 */ public Clob getClob(int i) throws SQLException { return null; } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as an <code>Array</code> object * in the Java programming language. * * @param i the first column is 1, the second is 2, ... * @return an <code>Array</code> object representing the SQL * <code>ARRAY</code> value in the specified column * @exception SQLException if a database access error occurs * @since 1.2 */ public Array getArray(int i) throws SQLException { return null; } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as an <code>Object</code> * in the Java programming language. * If the value is an SQL <code>NULL</code>, * the driver returns a Java <code>null</code>. * This method uses the specified <code>Map</code> object for * custom mapping if appropriate. * * @param colName the name of the column from which to retrieve the value * @param map a <code>java.util.Map</code> object that contains the mapping * from SQL type names to classes in the Java programming language * @return an <code>Object</code> representing the SQL value in the * specified column * @exception SQLException if a database access error occurs * @since 1.2 */ public Object getObject(String colName, java.util.Map<String, Class<?>> map) throws SQLException { return getObject( findColumn( colName ), map ); } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as a <code>Ref</code> object * in the Java programming language. * * @param colName the column name * @return a <code>Ref</code> object representing the SQL <code>REF</code> * value in the specified column * @exception SQLException if a database access error occurs * @since 1.2 */ public Ref getRef(String colName) throws SQLException { return null; } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as a <code>Blob</code> object * in the Java programming language. * * @param colName the name of the column from which to retrieve the value * @return a <code>Blob</code> object representing the SQL <code>BLOB</code> * value in the specified column * @exception SQLException if a database access error occurs * @since 1.2 */ public Blob getBlob(String colName) throws SQLException { return null; } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as a <code>Clob</code> object * in the Java programming language. * * @param colName the name of the column from which to retrieve the value * @return a <code>Clob</code> object representing the SQL <code>CLOB</code> * value in the specified column * @exception SQLException if a database access error occurs * @since 1.2 */ public Clob getClob(String colName) throws SQLException { return null; } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as an <code>Array</code> object * in the Java programming language. * * @param colName the name of the column from which to retrieve the value * @return an <code>Array</code> object representing the SQL <code>ARRAY</code> value in * the specified column * @exception SQLException if a database access error occurs * @since 1.2 */ public Array getArray(String colName) throws SQLException { return null; } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as a <code>java.sql.Date</code> object * in the Java programming language. * This method uses the given calendar to construct an appropriate millisecond * value for the date if the underlying database does not store * timezone information. * * @param columnIndex the first column is 1, the second is 2, ... * @param cal the <code>java.util.Calendar</code> object * to use in constructing the date * @return the column value as a <code>java.sql.Date</code> object; * if the value is SQL <code>NULL</code>, * the value returned is <code>null</code> in the Java programming language * @exception SQLException if a database access error occurs * @since 1.2 */ public java.sql.Date getDate(int columnIndex, Calendar cal) throws SQLException { return null; } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as a <code>java.sql.Date</code> object * in the Java programming language. * This method uses the given calendar to construct an appropriate millisecond * value for the date if the underlying database does not store * timezone information. * * @param columnName the SQL name of the column from which to retrieve the value * @param cal the <code>java.util.Calendar</code> object * to use in constructing the date * @return the column value as a <code>java.sql.Date</code> object; * if the value is SQL <code>NULL</code>, * the value returned is <code>null</code> in the Java programming language * @exception SQLException if a database access error occurs * @since 1.2 */ public java.sql.Date getDate(String columnName, Calendar cal) throws SQLException { return null; } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as a <code>java.sql.Time</code> object * in the Java programming language. * This method uses the given calendar to construct an appropriate millisecond * value for the time if the underlying database does not store * timezone information. * * @param columnIndex the first column is 1, the second is 2, ... * @param cal the <code>java.util.Calendar</code> object * to use in constructing the time * @return the column value as a <code>java.sql.Time</code> object; * if the value is SQL <code>NULL</code>, * the value returned is <code>null</code> in the Java programming language * @exception SQLException if a database access error occurs * @since 1.2 */ public java.sql.Time getTime(int columnIndex, Calendar cal) throws SQLException { return null; } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as a <code>java.sql.Time</code> object * in the Java programming language. * This method uses the given calendar to construct an appropriate millisecond * value for the time if the underlying database does not store * timezone information. * * @param columnName the SQL name of the column * @param cal the <code>java.util.Calendar</code> object * to use in constructing the time * @return the column value as a <code>java.sql.Time</code> object; * if the value is SQL <code>NULL</code>, * the value returned is <code>null</code> in the Java programming language * @exception SQLException if a database access error occurs * @since 1.2 */ public java.sql.Time getTime(String columnName, Calendar cal) throws SQLException { return null; } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as a <code>java.sql.Timestamp</code> object * in the Java programming language. * This method uses the given calendar to construct an appropriate millisecond * value for the timestamp if the underlying database does not store * timezone information. * * @param columnIndex the first column is 1, the second is 2, ... * @param cal the <code>java.util.Calendar</code> object * to use in constructing the timestamp * @return the column value as a <code>java.sql.Timestamp</code> object; * if the value is SQL <code>NULL</code>, * the value returned is <code>null</code> in the Java programming language * @exception SQLException if a database access error occurs * @since 1.2 */ public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { return null; } /** * Retrieves the value of the designated column in the current row * of this <code>ResultSet</code> object as a <code>java.sql.Timestamp</code> object * in the Java programming language. * This method uses the given calendar to construct an appropriate millisecond * value for the timestamp if the underlying database does not store * timezone information. * * @param columnName the SQL name of the column * @param cal the <code>java.util.Calendar</code> object * to use in constructing the date * @return the column value as a <code>java.sql.Timestamp</code> object; * if the value is SQL <code>NULL</code>, * the value returned is <code>null</code> in the Java programming language * @exception SQLException if a database access error occurs * @since 1.2 */ public java.sql.Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException { return null; } public java.net.URL getURL(int x) throws SQLException { return null; } public java.net.URL getURL(String x) throws SQLException { return null; } public void updateArray(int x, Array A) throws SQLException { throw new SQLException( "updates not supported" ); } public void updateArray(String x, Array A) throws SQLException { throw new SQLException( "updates not supported" ); } public void updateBlob(String columnName, java.sql.Blob x) throws SQLException { throw new SQLException( "updates not supported" ); } public void updateBlob(int columnName, java.sql.Blob x) throws SQLException { throw new SQLException( "updates not supported" ); } public void updateClob(String columnName, java.sql.Clob x) throws SQLException { throw new SQLException( "updates not supported" ); } public void updateClob(int columnName, java.sql.Clob x) throws SQLException { throw new SQLException( "updates not supported" ); } public void updateRef(int columnName, java.sql.Ref x) throws SQLException { throw new SQLException( "updates not supported" ); } public void updateRef(String columnName, java.sql.Ref x) throws SQLException { throw new SQLException( "updates not supported" ); } /* * Need to override the hashCode() method defined in cfJavaObjectData. If we don't then when * it's called it will go in an infinite loop. */ public int hashCode(){ return tableRows.hashCode(); } public boolean equals( cfData _data ){ if ( _data == this ){ return true; }else if ( _data.getDataType() == cfData.CFQUERYRESULTDATA ){ if ( getSize() == ( (cfQueryResultData)_data).getSize() && this.getColumns().equals( ( (cfQueryResultData)_data).getColumns() ) ){ return this.tableRows.equals( ( (cfQueryResultData)_data).tableRows ); } } return false; } @Override public int getHoldability() throws SQLException { return 0; } @Override public Reader getNCharacterStream( int arg0 ) throws SQLException { return null; } @Override public Reader getNCharacterStream( String arg0 ) throws SQLException { return null; } @Override public NClob getNClob( int arg0 ) throws SQLException { return null; } @Override public NClob getNClob( String arg0 ) throws SQLException { return null; } @Override public String getNString( int arg0 ) throws SQLException { return null; } @Override public String getNString( String arg0 ) throws SQLException { return null; } @Override public RowId getRowId( int arg0 ) throws SQLException { return null; } @Override public RowId getRowId( String arg0 ) throws SQLException { return null; } @Override public SQLXML getSQLXML( int arg0 ) throws SQLException { return null; } @Override public SQLXML getSQLXML( String arg0 ) throws SQLException { return null; } @Override public boolean isClosed() throws SQLException { return true; } @Override public void updateAsciiStream( int arg0, InputStream arg1 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateAsciiStream( String arg0, InputStream arg1 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateAsciiStream( int arg0, InputStream arg1, long arg2 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateAsciiStream( String arg0, InputStream arg1, long arg2 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateBinaryStream( int arg0, InputStream arg1 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateBinaryStream( String arg0, InputStream arg1 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateBinaryStream( int arg0, InputStream arg1, long arg2 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateBinaryStream( String arg0, InputStream arg1, long arg2 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateBlob( int arg0, InputStream arg1 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateBlob( String arg0, InputStream arg1 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateBlob( int arg0, InputStream arg1, long arg2 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateBlob( String arg0, InputStream arg1, long arg2 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateCharacterStream( int arg0, Reader arg1 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateCharacterStream( String arg0, Reader arg1 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateCharacterStream( int arg0, Reader arg1, long arg2 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateCharacterStream( String arg0, Reader arg1, long arg2 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateClob( int arg0, Reader arg1 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateClob( String arg0, Reader arg1 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateClob( int arg0, Reader arg1, long arg2 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateClob( String arg0, Reader arg1, long arg2 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateNCharacterStream( int arg0, Reader arg1 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateNCharacterStream( String arg0, Reader arg1 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateNCharacterStream( int arg0, Reader arg1, long arg2 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateNCharacterStream( String arg0, Reader arg1, long arg2 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateNClob( int arg0, NClob arg1 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateNClob( String arg0, NClob arg1 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateNClob( int arg0, Reader arg1 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateNClob( String arg0, Reader arg1 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateNClob( int arg0, Reader arg1, long arg2 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateNClob( String arg0, Reader arg1, long arg2 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateNString( int arg0, String arg1 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateNString( String arg0, String arg1 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateRowId( int arg0, RowId arg1 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateRowId( String arg0, RowId arg1 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateSQLXML( int arg0, SQLXML arg1 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public void updateSQLXML( String arg0, SQLXML arg1 ) throws SQLException { throw new SQLException( "updates not supported" ); } @Override public boolean isWrapperFor( Class<?> iface ) throws SQLException { throw new SQLException( "method not supported" ); } @Override public <T> T unwrap( Class<T> iface ) throws SQLException { throw new SQLException( "method not supported" ); } public boolean renameColumn(String oldcolumnName, String newcolumnName) { return rsmd.renameColumn( oldcolumnName, newcolumnName ); } /** * Special function for looping around the data with a UserDefinedFunction * * @param SessionData * @param _data * @throws cfmRunTimeException */ public void each( cfDataSession SessionData, cfData _data ) throws cfmRunTimeException { if ( _data.getDataType() != cfData.CFUDFDATA ) throw new cfmRunTimeException( catchDataFactory.generalException("Invalid Attribute", "Must be a user defined function") ); userDefinedFunction udf = (userDefinedFunction)_data; List<cfData> args = new ArrayList<cfData>(1); int resetRow = getCurrentRow(); reset(); while (nextRow()) { cfStructData rowData = getRowAsStruct(); args.clear(); args.add( rowData ); udf.execute( SessionData.Session, args ); } setCurrentRow( resetRow == 0 ? 1 : resetRow ); } public < T > T getObject( int arg0, Class<T> arg1 ) throws SQLException { return null; } public < T > T getObject( String arg0, Class<T> arg1 ) throws SQLException { return null; } }