/* ** Name: allocateRowBuffer ** ** Description: ** Allocate the column data array for a row and populate ** the array with a SqlData object for each column based ** on the column data type. ** ** Input: ** rsmd Row-set Meta-data. ** ** Output: ** None. ** ** Returns: ** SqlData[] Column data array. ** ** History: ** 14-May-99 (gordy) ** Created. ** 10-May-01 (gordy) ** The character datatypes (CHAR, VARCHAR, LONGVARCHAR) may now ** be sent as UCS2 character arrays in addition to the existing ** Ingres Character Set strings. The DBMS datatype is used to ** distinguish the transport format. ** 31-Oct-02 (gordy) ** Adapted for generic GCF driver. ** 4-Aug-03 (gordy) ** Extracted from readData() to separate row and column processing. ** 22-Sep-03 (gordy) ** Changed to use SQL Data objects to hold column values. ** 6-Jan-04 (thoda04) ** Added BigInt support. ** 16-Jun-06 (gordy) ** ANSI Date/Time data type support. ** 7-Dec-09 (gordy, ported by thoda04) ** Support BOOLEAN columns. */ private SqlData[] allocateRowBuffer( AdvanRSMD rsmd ) { SqlData[] row = new SqlData[ rsmd.count ]; for( int col = 0; col < rsmd.count; col++ ) { switch( rsmd.desc[ col ].sql_type ) { case ProviderType.DBNull : row[ col ] = new SqlNull(); break; case ProviderType.TinyInt : row[ col ] = new SqlTinyInt(); break; case ProviderType.SmallInt: row[ col ] = new SqlSmallInt(); break; case ProviderType.Integer : row[ col ] = new SqlInt(); break; case ProviderType.BigInt: row[ col ] = new SqlBigInt(); break; case ProviderType.Single : row[ col ] = new SqlReal(); break; case ProviderType.Double : row[ col ] = new SqlDouble(); break; case ProviderType.Numeric: case ProviderType.Decimal : row[ col ] = new SqlDecimal(); break; case ProviderType.Boolean : row[ col ] = new SqlBool(); break; case ProviderType.Date : row[col] = new SqlDate(); break; case ProviderType.Time: row[col] = new SqlTime(rsmd.desc[col].dbms_type); break; case ProviderType.Interval: case ProviderType.IntervalDayToSecond: case ProviderType.IntervalYearToMonth: row[col] = new SqlInterval(rsmd.desc[col].dbms_type); break; case ProviderType.DateTime: switch (rsmd.desc[col].dbms_type) { case DBMS_TYPE_IDATE: row[col] = new IngresDate(conn.osql_dates, conn.timeValuesInGMT()); break; default: row[col] = new SqlTimestamp(rsmd.desc[col].dbms_type); break; } break; case ProviderType.Binary : row[ col ] = new SqlByte( rsmd.desc[ col ].length ); break; case ProviderType.VarBinary : row[ col ] = new SqlVarByte( rsmd.desc[ col ].length ); break; case ProviderType.Char : if ( rsmd.desc[ col ].dbms_type != DBMS_TYPE_NCHAR ) row[ col ] = new SqlChar( msg.getCharSet(), rsmd.desc[ col ].length ); else row[ col ] = new SqlNChar(rsmd.desc[col].length / 2 ); break; case ProviderType.VarChar : if ( rsmd.desc[ col ].dbms_type != DBMS_TYPE_NVARCHAR ) row[col] = new SqlVarChar(msg.getCharSet(), rsmd.desc[col].length ); else row[col] = new SqlNVarChar( rsmd.desc[col].length / 2 ); break; case ProviderType.LongVarBinary : row[ col ] = new SqlLongByte( (SqlStream.IStreamListener)this ); break; case ProviderType.LongVarChar : if ( rsmd.desc[ col ].dbms_type != DBMS_TYPE_LONG_NCHAR ) row[ col ] = new SqlLongChar( msg.getCharSet(), (SqlStream.IStreamListener)this ); else row[ col ] = new SqlLongNChar( (SqlStream.IStreamListener)this ); break; default : if ( trace.enabled( 1 ) ) trace.write( tr_id + ": unexpected SQL type " + rsmd.desc[ col ].sql_type ); throw SqlEx.get( ERR_GC4002_PROTOCOL_ERR ); } } return( row ); }
/* ** Name: readColumns ** ** Description: ** Read column data from server. Assumes that the column counter, ** column_count, indicates the last column read. Reads the next ** column in the row and continues until message is empty , a BLOB ** column is read or the last column in the row is reached. ** ** Input: ** rsmd Row-set Meta-data ** row Column data array. ** ** Output: ** None. ** ** Returns: ** boolean BLOB column interrupted processing. ** ** History: ** 14-May-99 (gordy) ** Created. ** 29-Sep-99 (gordy) ** Implemented BLOB data support. Changed return type ** to permit BLOB stream to interrupt message processing. ** 12-Nov-99 (gordy) ** Use configured date formatter. ** 23-Nov-99 (gordy) ** Ingres allows for 'empty' dates which format to zero length ** strings. If such a beast is received, create an 'epoch' ** timestamp and generate a data truncation warning. ** 30-May-00 (gordy & rajus01) ** Fixed the behaviour of select date('today') query. ** (Bug #s 101677, 101678). ** 31-Jan-01 (gordy) ** Don't throw protocol exceptions for invalid date formats. ** AdvanRslt now handles these as conversion errors. ** 4-Apr-01 (gordy) ** Can't create a DataTruncation warning for empty dates here ** because row pre-fetching causes warnings for all rows to be ** returned on the first row. Also, a preceding BLOB will ** cause the warning to be generated at some unexpected point. ** 18-Apr-01 (gordy) ** Use readBytes() method which reads length from input message. ** 10-May-01 (gordy) ** The character datatypes (CHAR, VARCHAR, LONGVARCHAR) may now ** be sent as UCS2 character arrays in addition to the existing ** Ingres Character Set strings. The DBMS datatype is used to ** distinguish the transport format. ** 31-Oct-02 (gordy) ** Adapted for generic GCF driver. ** 20-Mar-02 (gordy) ** Added BOOLEAN data type, treated same as BIT. ** 4-Aug-03 (gordy) ** Extracted from readData() to separate row and column processing. ** 22-Sep-03 (gordy) ** Changed to use SQL Data objects to hold column values. ** Extracted column data object allocation to allocateRowBuffer(). ** 6-Jan-04 (thoda04) ** Added BigInt support. ** 16-Jun-06 (gordy) ** ANSI Date/Time data type support. ** 7-Dec-09 (gordy, ported by thoda04) ** Support BOOLEAN columns. */ private bool readColumns( AdvanRSMD rsmd, SqlData[] row ) { /* ** Begin processing columns after last read. ** Processing ends after last column in row ** is read, or if an interrupt is requested. ** Note that the column count (1 based index) ** references the next column to load (0 based ** index). */ for( ; column_count < rsmd.count; column_count++ ) { int col = column_count; /* ** We only require individual column values, with the ** exception of BLOB segments, to not be split across ** messages. If the next column is not available, ** return without interrupt to allow caller to handle ** the partial row. */ if ( ! msg.moreData() ) return( false ); switch( rsmd.desc[ col ].sql_type ) { case ProviderType.DBNull : msg.readSqlData( (SqlNull)row[ col ] ); break; case ProviderType.TinyInt : msg.readSqlData( (SqlTinyInt)row[ col ] ); break; case ProviderType.SmallInt : msg.readSqlData( (SqlSmallInt)row[ col ] ); break; case ProviderType.Integer : msg.readSqlData( (SqlInt)row[ col ] ); break; case ProviderType.BigInt : msg.readSqlData( (SqlBigInt)row[ col ] ); break; case ProviderType.Single : msg.readSqlData( (SqlReal)row[ col ] ); break; case ProviderType.Double : msg.readSqlData( (SqlDouble)row[ col ] ); break; case ProviderType.Decimal : msg.readSqlData( (SqlDecimal)row[ col ] ); // TODO: setWarning( new DataTruncation(col + 1, false, true, -1, 0) ); break; case ProviderType.Boolean: msg.readSqlData((SqlBool)row[col]); break; case ProviderType.Date: msg.readSqlData((SqlDate)row[col]); break; case ProviderType.Time: msg.readSqlData((SqlTime)row[col]); break; case ProviderType.Interval: case ProviderType.IntervalDayToSecond: case ProviderType.IntervalYearToMonth: msg.readSqlData((SqlInterval)row[col]); break; case ProviderType.DateTime: switch (rsmd.desc[col].dbms_type) { case DBMS_TYPE_IDATE: bool isBlankDateNull = (conn != null)?conn.isBlankDateNull : false; msg.readSqlData((IngresDate)row[col], isBlankDateNull); break; default: msg.readSqlData((SqlTimestamp)row[col]); break; } break; case ProviderType.Binary : msg.readSqlData( (SqlByte)row[ col ] ); break; case ProviderType.VarBinary : msg.readSqlData( (SqlVarByte)row[ col ] ); break; case ProviderType.Char : if ( rsmd.desc[ col ].dbms_type != DBMS_TYPE_NCHAR ) msg.readSqlData( (SqlChar)row[ col ] ); else msg.readSqlData( (SqlNChar)row[ col ] ); break; case ProviderType.VarChar : if ( rsmd.desc[ col ].dbms_type != DBMS_TYPE_NVARCHAR ) msg.readSqlData( (SqlVarChar)row[ col ] ); else msg.readSqlData( (SqlNVarChar)row[ col ] ); break; case ProviderType.LongVarBinary : /* ** Initialize BLOB stream. */ msg.readSqlData( (SqlLongByte)row[ col ] ); /* ** NULL BLOBs don't require special handling. ** Non-NULL BLOBs interrupt column processing. */ if ( ! row[ col ].isNull() ) { activeStream = (SqlStream)row[ col ]; // Stream reference column_count++; // Column is done return( true ); // Interrupt. } break; case ProviderType.LongVarChar : /* ** Initialize BLOB stream. */ if ( rsmd.desc[ col ].dbms_type != DBMS_TYPE_LONG_NCHAR ) msg.readSqlData( (SqlLongChar)row[ col ] ); else msg.readSqlData( (SqlLongNChar)row[ col ] ); /* ** NULL BLOBs don't require special handling. ** Non-NULL BLOBs interrupt column processing. */ if ( ! row[ col ].isNull() ) { activeStream = (SqlStream)row[ col ]; // Stream reference column_count++; // Column is done return( true ); // Interrupt. } break; default : if ( trace.enabled( 1 ) ) trace.write( tr_id + ": unexpected SQL type " + rsmd.desc[ col ].sql_type ); throw SqlEx.get( ERR_GC4002_PROTOCOL_ERR ); } } return( false ); }
/* ** Name: writeSqlDataIndicator ** ** Description: ** Writes a single byte (the SQL data/NULL indicator) ** to the current message and returns True if the data ** value is not-NULL. ** ** Input: ** value SQL data value. ** ** Output: ** None. ** ** Returns: ** boolean True if data value is not-NULL. ** ** History: ** 1-Dec-03 (gordy) ** Created. */ private bool writeSqlDataIndicator(SqlData data) { bool isNull = data.isNull(); write((byte)(isNull ? 0 : 1)); return (!isNull); }
/* ** Name: set ** ** Description: ** Set parameter fields. ** ** Input: ** type SQL type. ** value SQL data storage. ** short Flags. ** name Name. ** ** Output: ** None. ** ** Returns: ** void. ** ** History: ** 1-Dec-03 (gordy) ** Created. */ public void set( ProviderType type, SqlData value, ushort flags, String name ) { lock(this) { this.type = type; this.value = value; this.flags = flags; this.name = name; return; } }
/* ** Name: clear ** ** Description: ** Reset parameter fields to initial settings. ** ** Input: ** None. ** ** Output: ** None. ** ** Returns: ** void. ** ** History: ** 15-Nov-00 (gordy) ** Created. ** 1-Dec-03 (gordy) ** OTHER is now the default type. */ public void clear() { type = ProviderType.Other; value = null; flags = 0; name = null; return; }
/* ** Name: getGeneratedKeys ** ** Description: ** Retrieve table and/or object keys ** ** Input: ** None. ** ** Output: ** None. ** ** Returns: ** ResultSet Result-set containing table/object keys ** ** History: ** 21-Feb-03 (gordy) ** Created. ** 3-Jul-03 (gordy) ** Set DBMS types to LOGKEY/TBLKEY. ** 26-Sep-03 (gordy) ** Result-set data now stored as SqlByte SqlData objects. */ public AdvanRslt getGeneratedKeys() { lock(this) { ResultSet rs = rsEmpty; SqlData[][] data; SqlByte bytes; if ( rslt_tblkey ) if ( rslt_objkey ) { if ( rsmdKeys == null ) { rsmdKeys = new AdvanRSMD( (short)2, trace ); rsmdKeys.setColumnInfo( "table_key", 1, (int)Types.BINARY, (short)DBMS_TYPE_TBLKEY, (short)MSG_RPV_TBLKEY_LEN, (byte)0, (byte)0, false ); rsmdKeys.setColumnInfo( "object_key", 2, (int)Types.BINARY, (short)DBMS_TYPE_LOGKEY, (short)MSG_RPV_OBJKEY_LEN, (byte)0, (byte)0, false ); } data = new SqlData[1][]; data[0] = new SqlData[2]; bytes = new SqlByte( MSG_RPV_TBLKEY_LEN ); bytes.put( rslt_val_tblkey ); data[0][0] = bytes; bytes = new SqlByte( MSG_RPV_OBJKEY_LEN ); bytes.put( rslt_val_objkey ); data[0][1] = bytes; rs = new RsltData( conn, rsmdKeys, data ); } else { if ( rsmdTblKey == null ) { rsmdTblKey = new AdvanRSMD( (short)1, trace ); rsmdTblKey.setColumnInfo( "table_key", 1, (int)Types.BINARY, (short)DBMS_TYPE_TBLKEY, (short)MSG_RPV_TBLKEY_LEN, (byte)0, (byte)0, false ); } data = new SqlData[1][]; data[0] = new SqlData[1]; bytes = new SqlByte( MSG_RPV_TBLKEY_LEN ); bytes.put( rslt_val_tblkey ); data[0][0] = bytes; rs = new RsltData( conn, rsmdTblKey, data ); } else if ( rslt_objkey ) { if ( rsmdObjKey == null ) { rsmdObjKey = new AdvanRSMD( (short)1, trace ); rsmdObjKey.setColumnInfo( "object_key", 1, (int)Types.BINARY, (short)DBMS_TYPE_LOGKEY, (short)MSG_RPV_OBJKEY_LEN, (byte)0, (byte)0, false ); } data = new SqlData[1][]; data[0] = new SqlData[1]; bytes = new SqlByte( MSG_RPV_OBJKEY_LEN ); bytes.put( rslt_val_objkey ); data[0][0] = bytes; rs = new RsltData( conn, rsmdObjKey, data ); } else if ( rsEmpty == null ) { if ( rsmdEmpty == null ) { rsmdEmpty = new AdvanRSMD( (short)1, trace ); rsmdEmpty.setColumnInfo( "no_key", 1, (int)Types.BINARY, (short)DBMS_TYPE_TBLKEY, (short)MSG_RPV_TBLKEY_LEN, (byte)0, (byte)0, false ); } rs = rsEmpty = new RsltData( conn, rsmdEmpty, null ); } if ( trace.enabled() ) trace.log( title + ".getGeneratedKeys: " + rs ); return( rs ); } }
/* ** Name: RsltData ** ** Description: ** Class constructor. ** ** Input: ** conn Associated connection. ** rsmd ResultSet meta-data ** dataSet Constant result set, may be null ** ** Output: ** None. ** ** Returns: ** None. ** ** History: ** 12-Nov-99 (rajus01) ** Created. ** 4-Oct-00 (gordy) ** Create unique ID for standardized internal tracing. ** 28-Mar-01 (gordy) ** Tracing added as a parameter. ** 31-Oct-02 (gordy) ** Adapted for generic GCF driver. ** 26-Sep-03 (gordy) ** Column values now stored as SQL data objects. ** 26-Sep-03 (gordy) ** Column data now stored as SqlData objects. */ internal RsltData( DrvConn conn, AdvanRSMD rsmd, SqlData[][] dataSet ) : base(conn, rsmd) { this.dataSet = (dataSet == null) ? empty : dataSet; tr_id = "Data[" + inst_id + "]"; }