RsltCurs ( DrvConn conn, AdvanStmt stmt, AdvanRSMD rsmd, long stmt_id, String cursor, int preFetch, bool do_preLoad) : base(conn, stmt, rsmd, stmt_id, preFetch) { this.cursor = cursor; tr_id = "Curs[" + inst_id + "]"; /* ** Pre-load row cache if requested. */ if (do_preLoad && preLoad()) { /* ** Close the statement when end-of-data detected. ** ** Note that we don't call our closeCursor() method ** since it expects to handle the connection lock ** state. Our caller is handling the lock state ** during initialization. */ try { base.closeCursor(); } catch (SqlEx) {} } return; } // RsltCurs
RsltSlct ( DrvConn conn, AdvanStmt stmt, AdvanRSMD rsmd, long stmt_id, int preFetch, bool do_preLoad) : base(conn, stmt, rsmd, stmt_id, preFetch) { tr_id = "Slct[" + inst_id + "]"; /* ** Pre-load row cache if requested. */ if (do_preLoad && preLoad()) { /* ** Close the statement when end-of-data detected. ** ** Note that our caller only locks the connection, ** and expects the connection to be unlocked when ** data stream is done. Our closeCursor() method ** will unlock the connection as needed. */ try { closeCursor(); } catch (SqlEx) {} } return; } // RsltSlct
load(DrvConn conn) { MsgConn msg = conn.msg; bool isBlankDateNull = conn.isBlankDateNull; short count = msg.readShort(); AdvanRSMD rsmd = new AdvanRSMD(count, conn.trace); for (short col = 0; col < count; col++) { ProviderType sql_type = (ProviderType) msg.readShort(); short dbms_type = msg.readShort(); short length = msg.readShort(); byte precision = msg.readByte(); byte scale = msg.readByte(); byte flags = msg.readByte(); if (isBlankDateNull && sql_type == ProviderType.DateTime) { flags |= MSG_DSC_NULL; // return empty date as null } String name = msg.readString(); switch (sql_type) { case ProviderType.DateTime: if (dbms_type == 0) { dbms_type = DBMS_TYPE_IDATE; } break; case ProviderType.Interval: /* ** Intervals are not supported directly */ if (dbms_type == DBMS_TYPE_INTDS) { sql_type = ProviderType.IntervalDayToSecond; } else { sql_type = ProviderType.VarChar; } length = (short)((dbms_type == DBMS_TYPE_INTYM) ? 8 : 15); precision = scale = 0; break; } rsmd.desc[col].name = name; rsmd.desc[col].sql_type = sql_type; rsmd.desc[col].dbms_type = dbms_type; rsmd.desc[col].length = length; rsmd.desc[col].precision = precision; rsmd.desc[col].scale = scale; rsmd.desc[col].flags = flags; } return(rsmd); } // load
readDesc() { if (rsmd == null) { rsmd = AdvanRSMD.load(conn); } else { rsmd.reload(conn); } return(rsmd); } // readDesc
RsltByref ( DrvConn conn, AdvanCall stmt, AdvanRSMD rsmd, long stmt_id, bool do_preLoad ) : base(conn, stmt, rsmd, stmt_id, 1, false) /* ** BYREF parameters produce a single result row. ** Even if row may be pre-loaded, we don't want ** the super-class to do the loading. */ { rs_max_rows = 1; tr_id = "Byref[" + inst_id + "]"; /* ** Pre-load the row if available, otherwise disable pre- ** fetching to better handle the single expected row ** (pre-loading requires pre-fetch to be enabled). */ if (do_preLoad) { preLoad(); } else { disablePreFetch(); } /* ** Load the single expected row and close the ** server statement to unlock the connection. */ try { if (!next()) { throw SqlEx.get(ERR_GC4002_PROTOCOL_ERR); } } catch (SqlEx) { throw; } finally { try { closeCursor(); } catch (SqlEx) {} } return; } // RsltByref
readDesc() { if (rsmd == null) { rsmd = AdvanRSMD.load(conn); } else { rsmd.reload(conn); } // TODO: validate descriptor return(rsmd); } // readDesc
RsltUpd ( DrvConn conn, AdvanStmt stmt, AdvanRSMD rsmd, long stmt_id, String cursor ) : base(conn, stmt, rsmd, stmt_id, cursor, 1, false) { /* ** Updatable cursors only permit a single row per fetch, ** so pre-fetching and pre-loading is disabled. */ tr_id = "Upd[" + inst_id + "]"; disablePreFetch(); return; } // RsltUpd
/* ** Name: RsltUpd ** ** Description: ** Class constructor. ** ** Input: ** conn Associated connection. ** stmt Associated statement. ** rsmd ResultSet meta-data. ** stmt_id Statement ID. ** cursor Cursor name. ** ** Output: ** None. ** ** Returns: ** None. ** ** History: ** 4-Aug-03 (gordy) ** Created. ** 6-Oct-03 (gordy) ** Disable pre-loading in super-class. */ public RsltUpd( DrvConn conn, AdvanStmt stmt, AdvanRSMD rsmd, long stmt_id, String cursor ) : base(conn, stmt, rsmd, stmt_id, cursor, 1, false) { /* ** Updatable cursors only permit a single row per fetch, ** so pre-fetching and pre-loading is disabled. */ tr_id = "Upd[" + inst_id + "]"; disablePreFetch(); 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: 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: readDesc ** ** Description: ** Read a data descriptor message. Overrides ** default method in DrvObj. It handles the ** reading of descriptor messages for the method ** readXids (above). ** ** Input: ** None. ** ** Output: ** None. ** ** Returns: ** AdvanRSMD Data descriptor. ** ** History: ** 18-Apr-01 (gordy) ** Created.*/ protected internal override AdvanRSMD readDesc() { if (rsmd == null) rsmd = AdvanRSMD.load(conn); else rsmd.reload(conn); return (rsmd); }
/* ** Name: readDesc ** ** Description: ** Read a query result data descriptor message. Overrides the ** method in AdvanStmt. Maintains a single RSMD. Subsequent ** descriptor messages are loaded into the existing RSMD. ** ** Input: ** None. ** ** Output: ** None. ** ** Returns: ** AdvanRSMD Query result data descriptor. ** ** History: ** 16-Apr-01 (gordy) ** Created. */ protected internal override AdvanRSMD readDesc() { if ( prepRSMD == null ) prepRSMD = AdvanRSMD.load( conn ); else prepRSMD.reload( conn ); return( prepRSMD ); }
/* ** Name: getMetaData ** ** Description: ** Retrieves the ResultSet meta-data describing the ResultSet ** returned by the prepared statement. ** ** Input: ** None. ** ** Output: ** None. ** ** Returns: ** ResultSetMetaData The ResultSet meta-data. ** ** History: ** 1-Nov-00 (gordy) ** Created. ** 16-Apr-01 (gordy) ** Allocate empty RSMD only when needed. */ internal AdvanRSMD getMetaData() { if ( trace.enabled() ) trace.log( title + ".getMetaData(): " + prepRSMD ); if (prepRSMD == null && emptyRSMD == null) emptyRSMD = new AdvanRSMD((short)0, trace); return ((prepRSMD == null) ? emptyRSMD : prepRSMD); }
/* ** Name: RsltSlct ** ** Description: ** Class constructor. ** ** Initial row cache may be pre-loaded, but only if the ** message stream is active and DATA messages available. ** ** Input: ** conn Associated connection. ** stmt Associated statement. ** rsmd ResultSet meta-data. ** stmt_id Statement ID. ** preFetch Pre-fetch row count. ** preLoad Load initial row cache. ** ** Output: ** None. ** ** Returns: ** None. ** ** History: ** 17-May-00 (gordy) ** Created. ** 4-Oct-00 (gordy) ** Create unique ID for standardized internal tracing. ** 27-Oct-00 (gordy) ** New super-class constructor doesn't take cursor name. ** 15-Nov-00 (gordy) ** Changed parameters for 2.0 support. ** 23-Jan-01 (gordy) ** Changed parameter type to AdvanStmt for backward compatibility. ** 31-Oct-02 (gordy) ** Adapted for generic GCF driver. ** 6-Oct-03 (gordy) ** Added preLoad parameter to read initial row cache from server. */ public RsltSlct( DrvConn conn, AdvanStmt stmt, AdvanRSMD rsmd, long stmt_id, int preFetch, bool do_preLoad ) : base(conn, stmt, rsmd, stmt_id, preFetch) { tr_id = "Slct[" + inst_id + "]"; /* ** Pre-load row cache if requested. */ if ( do_preLoad && preLoad() ) { /* ** Close the statement when end-of-data detected. ** ** Note that our caller only locks the connection, ** and expects the connection to be unlocked when ** data stream is done. Our closeCursor() method ** will unlock the connection as needed. */ try { closeCursor(); } catch( SqlEx ) {} } return; }
/* ** Name: load ** ** Description: ** Reads the result-set descriptor (MSG_DESC) from the server ** connection and builds an ResultSet meta-data object. ** ** ** Input: ** conn Database Connection ** ** Output: ** None. ** ** Returns: ** AdvanRSMD Result-set Meta-data. ** ** History: ** 17-May-99 (gordy) ** Created. ** 25-Aug-00 (gordy) ** Nullable byte converted to flags. ** 4-Oct-00 (gordy) ** Create unique ID for standardized internal tracing. ** 28-Mar-01 (gordy) ** Tracing added as a parameter. ** 16-Apr-01 (gordy) ** Converted from constructor to factory method. ** 31-Oct-02 (gordy) ** Adapted for generic GCF driver. ** 16-Jun-06 (gordy) ** ANSI Date/Time data type support. Map intervals to varchar. ** 25-Aug-06 (gordy) ** Save flags to make parameter modes available. */ public static AdvanRSMD load(DrvConn conn) { MsgConn msg = conn.msg; bool isBlankDateNull = conn.isBlankDateNull; short count = msg.readShort(); AdvanRSMD rsmd = new AdvanRSMD(count, conn.trace); for (short col = 0; col < count; col++) { ProviderType sql_type = (ProviderType) msg.readShort(); short dbms_type = msg.readShort(); short length = msg.readShort(); byte precision = msg.readByte(); byte scale = msg.readByte(); byte flags = msg.readByte(); if (isBlankDateNull && sql_type == ProviderType.DateTime) flags |= MSG_DSC_NULL; // return empty date as null String name = msg.readString(); switch (sql_type) { case ProviderType.DateTime: if (dbms_type == 0) dbms_type = DBMS_TYPE_IDATE; break; case ProviderType.Interval: /* ** Intervals are not supported directly */ if (dbms_type == DBMS_TYPE_INTDS) sql_type = ProviderType.IntervalDayToSecond; else sql_type = ProviderType.VarChar; length = (short)((dbms_type == DBMS_TYPE_INTYM) ? 8 : 15); precision = scale = 0; break; } rsmd.desc[col].name = name; rsmd.desc[col].sql_type = sql_type; rsmd.desc[col].dbms_type = dbms_type; rsmd.desc[col].length = length; rsmd.desc[col].precision = precision; rsmd.desc[col].scale = scale; rsmd.desc[col].flags = flags; } return (rsmd); }
/* ** 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 + "]"; }
/* ** Name: exec ** ** Description: ** Execute a prepared statement. ** ** Input: ** param_set Parameters ** ** Output: ** None. ** ** Returns: ** void. ** ** History: ** 19-May-99 (gordy) ** Created. ** 8-Sep-99 (gordy) ** Synchronize on DbConn. ** 29-Sep-99 (gordy) ** Use DbConn lock()/unlock() methods for ** synchronization to support BLOB streams. ** 15-Nov-99 (gordy) ** Pass max row count and column length to result set. ** 16-Nov-99 (gordy) ** Added query timeouts. ** 13-Dec-99 (gordy) ** Added fetch limit. ** 19-Oct-00 (gordy) ** Re-prepare the statement if transaction state changed. ** 8-Jan-01 (gordy) ** Parameter set passed as parameter to support batch processing. ** 3-Mar-01 (gordy) ** Centralize call to clearResults in exec(). ** 16-Apr-01 (gordy) ** RSMD may change between prepare and execute (nasty!). We ** can't do anything about the application seeing the change, ** but we must use the execute RSMD to read the result-set. ** 10-May-01 (gordy) ** Only use execute RSMD if one actually arrives. ** 20-Jun-01 (gordy) ** Pass cursor name to result-set according to spec: ** NULL if READONLY and not provided by application. ** 20-Aug-01 (gordy) ** Send READONLY flag to server. Warn if cursor mode changed ** to READONLY. ** 31-Oct-02 (gordy) ** Adapted for generic GCF driver. ** 25-Feb-03 (gordy) ** Check that all contiguous parameters have been provided ** (we don't know actual dynamic parameter count, so we can't ** tell if sufficient parameters have been provided). ** 4-Aug-03 (gordy) ** Created neew result-set class for updatable cursors. ** 20-Aug-03 (gordy) ** Send AUTO_CLOSE flag for query statements. ** 6-Oct-03 (gordy) ** Fetch first block of rows for read-only cursors. ** 1-Nov-03 (gordy) ** Implemented updatable result-sets. ParamSet now ** builds DESC/DATA messages. */ private void exec( ParamSet param_set ) { int param_cnt; clearResults(); /* ** All dynamic parameters must be set. We check that all ** contiguous parameters have been set, the DBMS will check ** that sufficient parameters have been provided. */ param_cnt = param_set.getCount(); for( int param = 0; param < param_cnt; param++ ) if ( ! param_set.isSet( param ) ) { if ( trace.enabled( 1 ) ) trace.write( tr_id + ": parameter not set: " + (param + 1) ); throw SqlEx.get( ERR_GC4020_NO_PARAM ); } /* ** Is the current driver transaction ID different ** than the ID obtained when the query was prepared? ** If so, the prepared statement was lost with the ** change in transaction state and we need to prepare ** the query again. */ if ( xactID != conn.getXactID() ) prepare(); msg.LockConnection(); try { if ( prepRSMD == null ) { /* ** Non-query statement (execute). */ msg.begin( MSG_QUERY ); msg.write( MSG_QRY_EXS ); msg.write( MSG_QP_STMT_NAME ); msg.write( stmt_name ); msg.done( (param_cnt <= 0) ); if ( param_cnt > 0 ) { param_set.sendDesc(false); param_set.sendData(true); } readResults( timeout, true ); } else { /* ** Select statement (open a cursor). Generate a ** cursor ID if not provided by the application. */ int concurrency = getConcurrency( qry_concur ); short flags = 0; bool needEOG = true; String stmt = stmt_name; String cursor = (crsr_name != null) ? crsr_name : conn.getUniqueID( crsr_prefix ); /* ** Parser removes FOR READONLY clause because it isn't ** a part of Ingres SELECT syntax. Tell server that ** cursor should be READONLY (kludge older protocol ** by appending clause to statement name). */ if ( concurrency == DrvConst.DRV_CRSR_READONLY ) if ( conn.msg_protocol_level < MSG_PROTO_2 ) stmt += " for readonly"; else if ( conn.msg_protocol_level < MSG_PROTO_3 ) flags = (short)(flags | MSG_QF_READONLY); else { flags = (short)(flags | MSG_QF_READONLY | MSG_QF_FETCH_FIRST); needEOG = false; } if ( conn.msg_protocol_level >= MSG_PROTO_3 ) flags = (short)(flags | MSG_QF_AUTO_CLOSE); msg.begin( MSG_QUERY ); msg.write( MSG_QRY_OCS ); if ( flags != 0 ) { msg.write( MSG_QP_FLAGS ); msg.write( (short)2 ); msg.write( flags ); } msg.write( MSG_QP_CRSR_NAME ); msg.write( cursor ); msg.write( MSG_QP_STMT_NAME ); msg.write( stmt ); msg.done( (param_cnt <= 0) ); if ( param_cnt > 0 ) { param_set.sendDesc(false); param_set.sendData(true); } /* ** Check to see if a new result-set descriptor ** has been received. If so, it may be different ** than the previous descriptor and will be more ** accurate (save only if present). */ AdvanRSMD rsmd = readResults( timeout, needEOG ); if ( rsmd != null ) prepRSMD = rsmd; /* ** The cursor name is passed to the result-set ** for updatable cursors or if provided by the ** application (2.1 API spec). */ if ( (rslt_flags & MSG_RF_READ_ONLY) == 0 ) { resultSet = new RsltUpd( conn, this, rsmd, rslt_val_stmt, cursor ); if ( msg.moreMessages() ) readResults( timeout, true ); } else { if ( rs_concur == DrvConst.DRV_CRSR_UPDATE ) warnings.Add( SqlEx.get( ERR_GC4016_RS_CHANGED )); resultSet = new RsltCurs( conn, this, rsmd, rslt_val_stmt, crsr_name, getPreFetchSize(), msg.moreMessages() ); } } } catch( SqlEx ex ) { if ( trace.enabled() ) trace.log( title + ".execute(): error executing query" ); if ( trace.enabled( 1 ) ) ex.trace( trace ); throw ex; } finally { msg.UnlockConnection(); } return; }
/* ** Name: prepare ** ** Description: ** Prepares the query text and assigns a unique statement ** name and transaction ID. If the query is a SELECT, a ** result-set meta-data object is also produced. ** ** Input: ** None. ** ** Output: ** None. ** ** Returns: ** void. ** ** History: ** 19-Oct-00 (gordy) ** Extracted from constructor. ** 5-Feb-01 (gordy) ** Coalesce statement IDs. ** 31-Oct-02 (gordy) ** Adapted for generic GCF driver. */ private void prepare() { xactID = conn.getXactID(); stmt_name = conn.getStmtID( query_text, stmt_prefix ); msg.LockConnection(); try { msg.begin( MSG_QUERY ); msg.write( MSG_QRY_PREP ); msg.write( MSG_QP_STMT_NAME ); msg.write( stmt_name ); msg.write( MSG_QP_QTXT ); msg.write( query_text ); msg.done( true ); prepRSMD = readResults( true ); } catch( SqlEx ex ) { if ( trace.enabled() ) trace.log( title + ": error preparing query" ); if ( trace.enabled( 1 ) ) ex.trace( trace ); throw ex; } finally { msg.UnlockConnection(); } return; }
private bool isNull = false; // Was last column NULL? #endregion Fields #region Constructors /* ** Name: AdvanRslt ** ** Description: ** Class constructor. ** ** Input: ** conn Associated connection. ** rsmd ResultSet meta-data. ** ** Output: ** None. ** ** Returns: ** None. ** ** History: ** 21-Mar-01 (gordy) ** Created. ** 31-Oct-02 (gordy) ** Adapted for generic GCF driver. Replaced init() with constructor. ** 4-Aug-03 (gordy) ** Removal of row cache allowed for simplification in constructors. */ protected AdvanRslt( DrvConn conn, AdvanRSMD rsmd ) : base(conn) { this.rsmd = rsmd; title = trace.getTraceName() + "-ResultSet[" + inst_id + "]"; tr_id = "Rslt[" + inst_id + "]"; return; }
/* ** Name: readResults ** ** Description: ** Read server result messages. Processes messages until ** end-of-group is received or sub-class implementations ** of readData() and readResult() interrupt processing. ** ** MSG_DESC and MSG_DATA messages are processed by methods ** readDesc() and readData() respectively. The default ** implementation of these methods throws an exception. ** Sub-classes must provide their own implementation of ** these methods if these messages are expected as a part ** of the server response. ** ** The readDesc() method returns a Result-set meta-data ** object representing the MSG_DESC message received, ** which is then returned if readResults() completes ** successfully. ** ** MSG_ERROR and MSG_RESULT messages are processed by methods ** readError() and readResult() respectively. The default ** implementation of these methods are described below. ** Sub-classes may provide their own implementation of ** these methods to provide non-default processing. ** ** MSG_ERROR error messages are converted into exceptions ** which get thrown after all messages are processed. ** MSG_ERROR warning and user messages are saved as warnings. ** Multiple exceptions and warnings are chained together. ** ** MSG_RESULT parameter info is saved in result info members. ** The method setProcResult() is also called when a procedure ** return value is received. Sub-classes may override this ** method to provide alternate handling of procedure results. ** ** Input: ** None. ** ** Output: ** None. ** ** Returns: ** void ** ** History: ** 5-May-99 (gordy) ** Created. ** 29-Sep-99 (gordy) ** Permit BLOB data to interrupt message processing. ** 16-Nov-99 (gordy) ** Added query timeouts. ** 16-Dec-99 (gordy) ** Added MSG_RP_FETCH_LIMIT. ** 19-May-00 (gordy) ** Added MSG_RP_EOD. ** 16-Jun-00 (gordy) ** Added procedure return value. ** 31-Oct-00 (gordy) ** Added read-only cursor return value. ** 29-Aug-01 (loera01) SIR 105641 ** Execute setProcReturn if a DB procedure return value is read. ** 21-Apr-06 (gordy) ** Added INFO messages. */ /// <summary> /// Read server result messages. Processes messages until /// end-of-group is received or sub-class implementations /// of readData() and readResult() interrupt processing. /// </summary> /// <returns>A result-set meta-data object representing /// the MSG_DESC message received, or null if no MSG_DESC msg.</returns> protected internal virtual AdvanRSMD readResults() { SqlEx ex = null; // outstanding exception // that hasn't been throw yet AdvanRSMD rsmd = null; byte msg_id; try { do { switch (msg_id = msg.receive()) { case MSG_DESC: rsmd = readDesc(); break; case MSG_DATA: if (readData()) { goto break_msg_process_loop; // if interrupt occurred } break; case MSG_INFO: readInfo(); break; case MSG_ERROR: SqlEx exnew = readError(); if (exnew != null) { if (ex == null) // if first error message { ex = exnew; // then set is as the base ex } else // append new error messages to existing ex { ex.setNextException(exnew); } } break; case MSG_RESULT: if (readResult()) { goto break_msg_process_loop; // interrupt } break; default: if (trace.enabled(1)) { trace.write(tr_id + ": Invalid message ID " + msg_id); } throw SqlEx.get(ERR_GC4002_PROTOCOL_ERR); } // end switch if (msg.moreData()) { if (trace.enabled(1)) { trace.write(tr_id + ": end-of-message not reached"); } throw SqlEx.get(ERR_GC4002_PROTOCOL_ERR); } }while (msg.moreMessages()); } // end try catch (SqlEx exnew) { if (ex == null) // if first error message { ex = exnew; // then set is as the base ex } else // append new error message to existing ex { ex.setNextException(exnew); } } break_msg_process_loop: if (ex != null) // if any pending exceptions, throw now { throw ex; } return(rsmd); } // readResults
/* ** 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 + "]"; } // RsltData
/* ** Name: readDesc ** ** Description: ** Read a data descriptor message. Overrides default method in ** DrvObj. Handles the reading of descriptor messages for the ** method requestDbInfo (above). ** ** Input: ** None. ** ** Output: ** None. ** ** Returns: ** AdvanRSMD Data descriptor. ** ** History: ** 7-Mar-01 (gordy) ** Created. ** 16-Apr-01 (gordy) ** Instead of creating a new RSMD on every invocation, ** use load() and reload() methods of AdvanRSMD for just ** one RSMD. Return the RSMD, caller can ignore or use. */ protected internal override AdvanRSMD readDesc() { if ( rsmd == null ) rsmd = AdvanRSMD.load( conn ); else rsmd.reload( conn ); // TODO: validate descriptor return( rsmd ); }
/* ** 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: readDesc ** ** Description: ** Read a query result DESC message. Overrides the default method ** in DrvObj since descriptors are expected. Disable query timeouts. ** Will reload an existing RSMD or allocate new RSMD if NULL. ** ** Input: ** rsmd ResultSet meta-data to load, may be NULL. ** ** Output: ** None. ** ** Returns: ** JdbcRSMD Query result data descriptor. ** ** History: ** 8-Sep-99 (gordy) ** Created. */ protected internal AdvanRSMD readDesc(AdvanRSMD rsmd) { disableTimer(); if (rsmd == null) rsmd = AdvanRSMD.load(conn); else rsmd.reload(conn); return (rsmd); }
private long stmt_id = 0; // Server statement ID. #endregion Fields #region Constructors /* ** Name: RsltFtch ** ** Description: ** Class constructor. ** ** Input: ** conn Associated connection. ** stmt Associated statement. ** rsmd ResultSet meta-data. ** stmt_id Statement ID. ** preFetch Pre-fetch row count. ** ** Output: ** None. ** ** Returns: ** None. ** ** History: ** 14-May-99 (gordy) ** Created. ** 15-Nov-99 (gordy) ** Added max row count and max column length. ** 13-Dec-99 (gordy) ** Added fetch limit and multi-row data set. ** 4-Oct-00 (gordy) ** Create unique ID for standardized internal tracing. ** 3-Nov-00 (gordy) ** Parameters changed for 2.0 extensions. ** 23-Jan-01 (gordy) ** Changed parameter type to AdvanStmt for backward compatibility. ** 31-Oct-02 (gordy) ** Adapted for generic GCF driver. Statement info maintained here. ** 4-Aug-03 (gordy) ** Pre-fetch handling moved entirely into this class. */ public RsltFtch( DrvConn conn, AdvanStmt stmt, AdvanRSMD rsmd, long stmt_id, int preFetch ) : base(conn, rsmd) { this.stmt = stmt; this.stmt_id = stmt_id; rs_max_len = stmt.rs_max_len; rs_fetch_dir = stmt.rs_fetch_dir; rs_max_rows = stmt.rs_max_rows; rs_fetch_size = (rs_max_rows > 0 && rs_max_rows < preFetch) ? rs_max_rows : preFetch; tr_id = "Ftch[" + inst_id + "]"; /* ** Row pre-fetching must be disabled if there is a BLOB column. */ for( int col = 0; col < rsmd.count; col++ ) if ( ProviderTypeMgr.isLong(rsmd.desc[ col ].sql_type) ) { rowCacheEnabled = false; break; } return; }
/* ** BYREF parameters produce a single result row. ** Even if row may be pre-loaded, we don't want ** the super-class to do the loading. */ /* ** Name: RsltByref ** ** Description: ** Class constructor for Database Procedure BYREF parameters. ** Extends procedure row handling to load the single expected ** result row and release the server side resources. Initial ** row cache may be pre-loaded, but only if the message stream ** is active and DATA message available. ** ** Input: ** conn Associated connection. ** stmt Associated call statement. ** rsmd Result set Meta-Data. ** stmt_id Statement ID. ** preLoad Load initial row cache. ** ** Output: ** None. ** ** Returns: ** None. ** ** History: ** 3-Aug-00 (gordy) ** Created. ** 4-Oct-00 (gordy) ** Create unique ID for standardized internal tracing. ** 3-Nov-00 (gordy) ** Changed parameters for 2.0 extensions. ** 23-Jan-01 (gordy) ** Changed parameter type to AdvanStmt for backward compatibility. ** 31-Oct-02 (gordy) ** Extracted Byref specifics into separate sub-class. ** 4-Aug-03 (gordy) ** Server will handle details of detecting EOD and cleaning ** up the connection, so we disable pre-fetch since only one ** row is expected. ** 6-Oct-03 (gordy) ** Added preLoad parameter to read initial row cache from server. */ public RsltByref( DrvConn conn, AdvanCall stmt, AdvanRSMD rsmd, long stmt_id, bool do_preLoad ) : base(conn, stmt, rsmd, stmt_id, 1, false) { rs_max_rows = 1; tr_id = "Byref[" + inst_id + "]"; /* ** Pre-load the row if available, otherwise disable pre- ** fetching to better handle the single expected row ** (pre-loading requires pre-fetch to be enabled). */ if ( do_preLoad ) preLoad(); else disablePreFetch(); /* ** Load the single expected row and close the ** server statement to unlock the connection. */ try { if ( ! next() ) throw SqlEx.get( ERR_GC4002_PROTOCOL_ERR ); } catch( SqlEx ) { throw; } finally { try { closeCursor(); } catch( SqlEx ) {} } return; }