/* ** Name: readSqlData ** ** Description: ** Reads a SqlLongByte data value from the current input message. ** Only a single stream data value may be active at a given time. ** Attempting to read another stream data value will result in ** the closure of the preceding stream. ** ** A SqlLongByte data value is composed of a data indicator byte ** which, if not NULL, may be followed by zero or more segments ** which are then followed by and end-of-segments indicator. Each ** segment is composed of a two byte integer length (non-zero) ** followed by a binary byte array of the indicated length. The ** end-of-segments indicator is a two byte integer with value ** zero. ** ** Only the SQL data/NULL indicator is read by this method. If ** the SqlLongByte value is non-NULL, an InputStream is provided ** for reading the segmented data stream. The InputStream also ** implements the SqlStream StreamSource interface for providing ** notification of stream closure events. ** ** Input: ** None. ** ** Output: ** value SQL data value. ** ** Returns: ** void. ** ** History: ** 22-Sep-03 (gordy) ** Created. */ public void readSqlData( SqlLongByte value ) { if ( readSqlDataIndicator() ) // Read data indicator byte. value.set( new ByteSegIS( this, trace, in_msg_id ) ); else value.setNull(); // NULL data value. return; }
/* ** 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: sendData ** ** Description: ** Send a DATA message for current set of parameters. ** ** Input: ** eog Is this message end-of-group? ** ** Output: ** None. ** ** Returns: ** void. ** ** History: ** 19-May-99 (gordy) ** Created. ** 29-Sep-99 (gordy) ** Implemented support for BLOBs. ** 12-Nov-99 (gordy) ** Use configured date formatter. ** 17-Dec-99 (gordy) ** Conversion to BLOB now determined by DBMS max varchar len. ** 2-Feb-00 (gordy) ** Send short streams as VARCHAR or VARBINARY. ** 15-Nov-00 (gordy) ** Extracted Param class to create a stand-alone Paramset class. ** 8-Jan-01 (gordy) ** Parameter set passed as parameter to support batch processing. ** 10-May-01 (gordy) ** Support UCS2 as alternate format for character types. Char ** arrays fully supported as separate BINARY and VARBINARY types. ** 1-Jun-01 (gordy) ** Removed conversion of BLOB to fixed length type for short lengths. ** 20-Feb-02 (gordy) ** Decimal not supported by gateways at proto level 0. Send as float. ** 6-Sep-02 (gordy) ** Use formatted length of CHAR and VARCHAR parameters rather than ** character length. ** 31-Oct-02 (gordy) ** Adapted for generic GCF driver. ** 19-Feb-03 (gordy) ** Replaced BIT with BOOLEAN. Skip unset parameters (default ** procedure parameters). ALT character parameters now stored ** in communication format. ** 26-Jun-03 (gordy) ** Missed an ALT storage class. ** 27-June-03 (wansh01) ** Handle binary type with 0 length as varbinary. ** 1-Dec-03 (gordy) ** Moved to ParamSet to support updatable result sets. ** 23-Jan-04 (gordy) ** Properly handle zero length NCHAR columns using emptyNVarChar. ** Set NULL CHAR/BINARY columns to non-zero length to avoid coercion ** (zero length values were being sent instead of mulls). ** 15-Mar-04 (gordy) ** BIGINT now supported. BOOLEAN should always be in alternate ** storage format (force to alternate until BOOLEAN supported). ** 28-May-04 (gordy) ** Add max column lengths for NCS columns. ** 19-Jun-06 (gordy) ** ANSI Date/Time data type support. Ingres date is now ** the alternate storage for DATE/TIME/TIMESTAMP and ** SqlDate/SqlTime/SqlTimestamp are the primary storage. ** 7-Dec-09 (gordy, ported by thoda04) ** Boolean now fully supported. ** 3-Mar-10 (thoda04) SIR 123368 ** Added support for IngresType.IngresDate parameter data type. */ public void sendData(bool eog) { lock (this) { msg.begin(MSG_DATA); for (int param = 0; param < param_cnt; param++) { if (paramArray[param] == null || (paramArray[param].flags & PS_FLG_SET) == 0) continue; // Skip unset params. SqlData value = paramArray[param].value; ProviderType type = paramArray[param].type; bool alt = ((paramArray[param].flags & PS_FLG_ALT) != 0); int length; switch (type) { case ProviderType.DBNull: msg.write((SqlNull)value); break; case ProviderType.TinyInt: msg.write((SqlTinyInt)value); break; case ProviderType.SmallInt: msg.write((SqlSmallInt)value); break; case ProviderType.Integer: msg.write((SqlInt)value); break; case ProviderType.Real: msg.write((SqlReal)value); break; case ProviderType.Double: msg.write((SqlDouble)value); break; case ProviderType.Date: if (alt) msg.write((IngresDate)value); else msg.write((SqlDate)value); break; case ProviderType.Time: if (alt) msg.write((IngresDate)value); else msg.write((SqlTime)value); break; case ProviderType.IngresDate: case ProviderType.DateTime: if (alt) msg.write((IngresDate)value); else msg.write((SqlTimestamp)value); break; case ProviderType.Boolean: if (alt) msg.write((SqlTinyInt)value); else msg.write((SqlBool)value); break; case ProviderType.BigInt: if (alt) msg.write((SqlDouble)value); else msg.write((SqlBigInt)value); break; case ProviderType.Decimal: if (alt) msg.write((SqlDouble)value); else msg.write((SqlDecimal)value); break; case ProviderType.Char: /* ** Determine length. NULL values assume {n}char(1). */ if (value.isNull()) length = 1; else if (alt) length = ((SqlChar)value).valuelength(); else length = ((SqlNChar)value).valuelength(); /* ** Zero length strings must be sent as VARCHAR. ** Long strings are sent as BLOBs. UCS2 used ** when supported. */ if (alt) { if (length <= 0) msg.write(emptyVarChar); else if (length <= conn.max_char_len) msg.write((SqlChar)value); else { if (tempLongChar == null) tempLongChar = new SqlLongChar(msg.getCharSet()); tempLongChar.set((SqlChar)value); msg.write(tempLongChar); } } else { if (length <= 0) msg.write(emptyNVarChar); else if (length <= conn.max_nchr_len) msg.write((SqlNChar)value); else { if (tempLongNChar == null) tempLongNChar = new SqlLongNChar(); tempLongNChar.set((SqlNChar)value); msg.write(tempLongNChar); } } break; case ProviderType.VarChar: /* ** Determine length. NULL values assume {n}varchar(1). */ if (value.isNull()) length = 1; else if (alt) length = ((SqlVarChar)value).valuelength(); else length = ((SqlNVarChar)value).valuelength(); /* ** Long strings are sent as BLOBs. ** UCS2 used when supported. */ if (alt) { if (length <= conn.max_vchr_len) msg.write((SqlVarChar)value); else { if (tempLongChar == null) tempLongChar = new SqlLongChar(msg.getCharSet()); tempLongChar.set((SqlVarChar)value); msg.write(tempLongChar); } } else { if (length <= conn.max_nvch_len) msg.write((SqlNVarChar)value); else { if (tempLongNChar == null) tempLongNChar = new SqlLongNChar(); tempLongNChar.set((SqlNVarChar)value); msg.write(tempLongNChar); } } break; case ProviderType.LongVarChar: /* ** UCS2 used when supported. */ if (alt) msg.write((SqlLongChar)value); else msg.write((SqlLongNChar)value); break; case ProviderType.Binary: /* ** Determine length. NULL values assume byte(1). */ length = value.isNull() ? 1 : ((SqlByte)value).valuelength(); /* ** Long arrays are sent as BLOBs. Zero length ** arrays must be sent as VARBINARY. ** */ if (length <= 0) msg.write(emptyVarByte); else if (length <= conn.max_byte_len) msg.write((SqlByte)value); else { if (tempLongByte == null) tempLongByte = new SqlLongByte(); tempLongByte.set((SqlByte)value); msg.write(tempLongByte); } break; case ProviderType.VarBinary: /* ** Determine length. NULL values assume varbyte(1). */ length = value.isNull() ? 1 : ((SqlVarByte)value).valuelength(); /* ** Long arrays are sent as BLOBs. */ if (length <= conn.max_vbyt_len) msg.write((SqlVarByte)value); else { if (tempLongByte == null) tempLongByte = new SqlLongByte(); tempLongByte.set((SqlVarByte)value); msg.write(tempLongByte); } break; case ProviderType.LongVarBinary: msg.write((SqlLongByte)value); break; } } msg.done(eog); return; } // lock }
/* ** Name: write ** ** Description: ** Write a SqlLongByte data value to the current input message. ** The binary stream is retrieved and segmented for output by ** an instance of the local inner class ByteSegOS. ** ** A SqlLongByte data value is composed of a data indicator byte ** which, if not NULL, may be followed by zero or more segments ** which are then followed by and end-of-segments indicator. Each ** segment is composed of a two byte integer length (non-zero) ** followed by a binary byte array of the indicated length. The ** end-of-segments indicator is a two byte integer with value ** zero. ** ** Input: ** value SQL data value. ** ** Output: ** None. ** ** Returns: ** void. ** ** History: ** 1-Dec-03 (gordy) ** Created. */ public void write(SqlLongByte value) { if (writeSqlDataIndicator(value)) // Data indicator byte. { if (segOS == null) segOS = new ByteSegOS(this, outBuff, trace); segOS.begin(out_msg_id); // begin a new BLOB. try { value.get(segOS); } // Write stream to output. finally { segOS.end(); } // End-of-segments. } return; }
/* ** Name: getStorage ** ** Description: ** Allocates storage for SQL data values base on the SQL type ** and optional alternate storage format. The class of the ** object returned is defined in the class description. ** ** Input: ** sqlType SQL type. ** alt True for alternate storage format. ** ** Output: ** None. ** ** Returns: ** SqlData SQL data value. ** ** History: ** 1-Dec-03 (gordy) ** Created. ** 19-Jun-06 (gordy) ** ANSI Date/Time data type support. IngresDate is now ** the alternate storage for DATE/TIME/TIMESTAMP and ** SqlDate/SqlTime/SqlTimestamp are the primary storage. ** 3-Mar-10 (thoda04) SIR 123368 ** Added support for IngresType.IngresDate parameter data type. */ /// <summary> /// Allocates storage for SQL data values base on the SQL type /// and optional alternate storage format. The class of the /// object returned is defined in the class description. /// </summary> /// <param name="sqlType">SQL type.</param> /// <param name="alt">True for alternate storage format.</param> /// <returns>SQL data value.</returns> private SqlData getStorage(ProviderType sqlType, bool alt) { SqlData sqlData; switch (sqlType) { case ProviderType.DBNull: sqlData = new SqlNull(); break; case ProviderType.TinyInt: sqlData = new SqlTinyInt(); break; case ProviderType.SmallInt: sqlData = new SqlSmallInt(); break; case ProviderType.Integer: sqlData = new SqlInt(); break; case ProviderType.Real: sqlData = new SqlReal(); break; case ProviderType.Double: sqlData = new SqlDouble(); break; case ProviderType.Binary: sqlData = new SqlByte(); break; case ProviderType.VarBinary: sqlData = new SqlVarByte(); break; case ProviderType.LongVarBinary: sqlData = new SqlLongByte(); break; case ProviderType.Boolean: sqlData = alt ? (SqlData)(new SqlTinyInt()) : (SqlData)(new SqlBool()); break; case ProviderType.BigInt: sqlData = alt ? (SqlData)(new SqlDouble()) : (SqlData)(new SqlBigInt()); break; case ProviderType.Decimal: sqlData = alt ? (SqlData)(new SqlDouble()) : (SqlData)(new SqlDecimal()); break; case ProviderType.Char: sqlData = alt ? (SqlData)(new SqlChar(msg.getCharSet())) : (SqlData)(new SqlNChar()); break; case ProviderType.VarChar: sqlData = alt ? (SqlData)(new SqlVarChar(msg.getCharSet())) : (SqlData)(new SqlNVarChar()); break; case ProviderType.LongVarChar: sqlData = alt ? (SqlData)(new SqlLongChar(msg.getCharSet())) : (SqlData)(new SqlLongNChar()); break; case ProviderType.Date: sqlData = alt ? (SqlData)(new IngresDate(conn.osql_dates, conn.timeValuesInGMT())) : (SqlData)(new SqlDate()); break; case ProviderType.Time: sqlData = alt ? (SqlData)(new IngresDate(conn.osql_dates, conn.timeValuesInGMT())) : (SqlData)(new SqlTime( conn.osql_dates ? DBMS_TYPE_TMWO : DBMS_TYPE_TMTZ)); break; case ProviderType.DateTime: case ProviderType.IngresDate: sqlData = alt ? (SqlData)(new IngresDate(conn.osql_dates, conn.timeValuesInGMT())) : (SqlData)(new SqlTimestamp( conn.osql_dates ? DBMS_TYPE_TSWO : DBMS_TYPE_TSTZ)); break; default: throw SqlEx.get(ERR_GC401A_CONVERSION_ERR); } return (sqlData); }