-using System;
-using System.Collections;
-using System.Data;
-using System.Runtime.InteropServices;
-using System.Globalization;
-using System.Text;
-
-namespace IBM.Data.DB2
-{
- /// <summary>
- /// Summary description for DB2ClientDataReader.
- /// DB2ClientDataReader.
- /// </summary>
- public sealed class DB2DataReader : MarshalByRefObject, IDataReader
- {
- private struct ColumnInfo
- {
- public string Colname;
- public int Sqltype;
- }
-
- private object[] _resultSet;
- private ColumnInfo[] columnInfo;
- private Hashtable columnsNames;
- private const int internalBufferSize = 100;
- private IntPtr internalBuffer;
- internal DB2Connection db2Conn;
- internal DB2Command db2Comm;
- internal IntPtr hwndStmt;
- private int recordsAffected;
- private bool hasData;
- private int fieldCount = -1;
- private CommandBehavior behavior;
- private bool hasRows;
- private bool skipReadOnce;
-
-
- #region Constructors and destructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="con"></Connection object to Db2>
- /// <param name="com"></Command object>
- internal DB2DataReader(DB2Connection con, DB2Command com, CommandBehavior behavior)
- {
- db2Conn = con;
- db2Comm = com;
- this.behavior = behavior;
- hwndStmt = com.statementHandle; //We have access to the results through the statement handle
-
- _resultSet = null;
-
- GetFieldCountAndAffectedRows();
- internalBuffer = Marshal.AllocHGlobal(internalBufferSize);
-
- isClosed = false;
- }
-
- #endregion
-
- private void GetFieldCountAndAffectedRows()
- {
- short sqlRet;
- recordsAffected = -1;
- if((behavior & CommandBehavior.SchemaOnly) == 0)
- {
- //How many rows affected. numRows will be -1 if we aren't dealing with an Insert, Delete or Update, or if the statement did not execute successfully
- sqlRet = DB2CLIWrapper.SQLRowCount(hwndStmt, out recordsAffected);
- DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "SQLExecDirect error.", db2Conn);
- }
- short colCount;
- sqlRet = DB2CLIWrapper.SQLNumResultCols(hwndStmt, out colCount);
- DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "DB2ClientDataReader - SQLNumResultCols", db2Conn);
- fieldCount = colCount;
- }
-
- #region Properties
-
- #region Depth property
- ///
- ///Depth of nesting for the current row, need to figure out what this translates into
- ///with DB2.
- ///
- private int depth = 0;
- public int Depth
- {
- get
- {
- if(isClosed)
- {
- throw new InvalidOperationException("Reader is closed");
- }
- return depth;
- }
- }
- #endregion
-
- #region IsClosed property
- /// <summary>
- /// True if the reader is closed.
- /// </summary>
- private bool isClosed = true;
- public bool IsClosed
- {
- get
- {
- return isClosed;
- }
- }
- #endregion
-
- #region RecordsAffected property
- ///
- /// Number of records affected by this operation. Will be zero until we close the
- /// reader
- ///
-
- public int RecordsAffected
- {
- get
- {
- return recordsAffected;
- }
- }
- #endregion
-
- #endregion
-
- #region Methods
-
-
-
- #region Close method
-
- public void Close()
- {
- Dispose();
- }
-
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- void Dispose(bool disposing)
- {
- if(!isClosed)
- {
- if(disposing)
- {
- short sqlRet;
- do
- {
- sqlRet = DB2CLIWrapper.SQLMoreResults(this.hwndStmt);
- DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "Db2ClientDataReader - SQLMoreResults", db2Conn);
- } while(sqlRet != DB2Constants.SQL_NO_DATA_FOUND);
-
- _resultSet = null;
- hasData = false;
- isClosed=true;
-
- if(db2Comm != null)
- {
- db2Comm.DataReaderClosed();
- db2Comm = null;
- }
- }
- Marshal.FreeHGlobal(internalBuffer);
- }
- isClosed = true;
- }
-
- ~DB2DataReader()
- {
- Dispose(false);
- }
-
- #endregion
-
- #region GetSchemaTable
-
- public DataTable GetSchemaTable()
- {
- if(isClosed)
- {
- throw new InvalidOperationException("No data exists for the row/column.");
- }
-
- DataTable _schemaTable = BuildNewSchemaTable();
-
- short sqlRet;
- IntPtr ptrCharacterAttribute = IntPtr.Zero;
- InitMem(256, ref ptrCharacterAttribute);
- short buflen = 256;
- short strlen = 256;
- int numericattr = 0;
- int colsize;
- string colname;
- int sqltype;
- int precision;
- int scale;
- int nullable;
- int updatable;
- int isautoincrement;
- string baseschemaname;
- //string basecatalogname;
- string basetablename;
- string basecolumnname;
-
- string previousTableName = null;
- string previousSchemaName = null;
- bool differentTablesUsed = false;
-
- for (short i=1; i<=fieldCount; i++)
- {
- sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)i, (short)DB2Constants.SQL_DESC_COLUMN_NAME, ptrCharacterAttribute, buflen, ref strlen, ref numericattr);
- DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable", db2Conn);
- colname = Marshal.PtrToStringUni(ptrCharacterAttribute);
-
- sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)i, (short)DB2Constants.SQL_DESC_CONCISE_TYPE, ptrCharacterAttribute, buflen, ref strlen, ref numericattr);
- DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable", db2Conn);
- sqltype = numericattr;
-
- sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)i, (short)DB2Constants.SQL_DESC_OCTET_LENGTH, ptrCharacterAttribute, buflen, ref strlen, ref numericattr);
- DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable", db2Conn);
- colsize = numericattr;
-
- sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)i, (short)DB2Constants.SQL_DESC_PRECISION, ptrCharacterAttribute, buflen, ref strlen, ref numericattr);
- DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable", db2Conn);
- precision = numericattr;
-
- sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)i, (short)DB2Constants.SQL_DESC_SCALE, ptrCharacterAttribute, buflen, ref strlen, ref numericattr);
- DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable", db2Conn);
- scale = numericattr;
-
- sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)i, (short)DB2Constants.SQL_DESC_NULLABLE, ptrCharacterAttribute, buflen, ref strlen, ref numericattr);
- DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable", db2Conn);
- nullable = numericattr;
-
- sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)i, (short)DB2Constants.SQL_DESC_UPDATABLE, ptrCharacterAttribute, buflen, ref strlen, ref numericattr);
- DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable", db2Conn);
- updatable = numericattr;
-
- sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)i, (short)DB2Constants.SQL_DESC_AUTO_UNIQUE_VALUE, ptrCharacterAttribute, buflen, ref strlen, ref numericattr);
- DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable", db2Conn);
- isautoincrement = numericattr;
-
- sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)i, (short)DB2Constants.SQL_DESC_BASE_COLUMN_NAME, ptrCharacterAttribute, buflen, ref strlen, ref numericattr);
- DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable", db2Conn);
- basecolumnname = Marshal.PtrToStringUni(ptrCharacterAttribute);
-
- sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)i, (short)DB2Constants.SQL_DESC_BASE_TABLE_NAME, ptrCharacterAttribute, buflen, ref strlen, ref numericattr);
- DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable", db2Conn);
- basetablename = Marshal.PtrToStringUni(ptrCharacterAttribute);
-
- sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)i, (short)DB2Constants.SQL_DESC_SCHEMA_NAME, ptrCharacterAttribute, buflen, ref strlen, ref numericattr);
- DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable", db2Conn);
- baseschemaname = Marshal.PtrToStringUni(ptrCharacterAttribute);
- DataRow r = _schemaTable.NewRow();
-
-
- r["ColumnName"] = colname;
- r["ColumnOrdinal"] = i - 1;
- r["ColumnSize"] = colsize;
- r["NumericPrecision"] = precision;
- r["NumericScale"] = scale;
- r["DataType"] = GetManagedType((short)sqltype);
- r["ProviderType"] = sqltype;
- r["IsLong"] = IsLong((short)sqltype);
- r["AllowDBNull"] = (nullable==0) ? false : true;
- r["IsReadOnly"] = (basecolumnname == null) || (basecolumnname == "");
- r["IsRowVersion"] = false;
- r["IsUnique"] = false;
- r["IsKeyColumn"] = false;
- r["IsAutoIncrement"] = (isautoincrement==0) ? false : true;
- r["BaseSchemaName"] = baseschemaname;
- r["BaseCatalogName"] = "";
- r["BaseTableName"] = basetablename;
- r["BaseColumnName"] = basecolumnname;
-
-
- _schemaTable.Rows.Add(r);
-
-
- if(!differentTablesUsed)
- {
- if(((previousSchemaName == baseschemaname) && (previousTableName == basetablename)) ||
- (previousTableName == null))
- {
- previousTableName = basetablename;
- previousSchemaName = baseschemaname;
- }
- else
- {
- differentTablesUsed = true;
- }
- }
- }
- if(!differentTablesUsed &&
- ((behavior & CommandBehavior.KeyInfo) != 0) &&
- (db2Comm.Transaction == null) &&
- (previousTableName != null) &&
- (previousTableName != ""))
- {
- DB2Command schemaInfoCommand = db2Conn.CreateCommand();
- schemaInfoCommand.CommandText =
- "select concat(concat(INDSCHEMA,'.'),INDNAME), COLNAMES, UNIQUERULE from syscat.INDEXES " +
- "where TABSCHEMA=? and TABNAME=? and uniquerule in ('P','U') order by UNIQUERULE";
- schemaInfoCommand.Parameters.Add("TABSCHEMA", previousSchemaName);
- schemaInfoCommand.Parameters.Add("TABNAME", previousTableName);
- using(DB2DataReader reader = schemaInfoCommand.ExecuteReader())
- {
- bool keyColumnSet = false;
- while(reader.Read())
- {
- string indexName = reader.GetString(0);
- string[] indexColumns = reader.GetString(1).TrimStart('-', '+').Split('-', '+');
- bool primary = reader.GetString(2) == "P";
-
- bool allColumnsFound = true;
- for(int i= 0; i < indexColumns.Length; i++)
- {
- int ordinal = FieldNameLookup(_schemaTable, indexColumns[i]);
- if(ordinal < 0)
- {
- allColumnsFound = false;
- break;
- }
- if(indexColumns.Length == 1)
- _schemaTable.Rows[ordinal]["IsUnique"] = true;
- }
- if(allColumnsFound && !keyColumnSet)
- {
- for(int i= 0; i < indexColumns.Length; i++)
- _schemaTable.Rows[FieldNameLookup(_schemaTable, indexColumns[i])]["IsKeyColumn"] = true;
- keyColumnSet = true;
- }
- }
- }
- if(db2Conn.openConnection.MajorVersion >= 8)
- {
- try
- {
- schemaInfoCommand.CommandText =
- "select COLNAME from SYSCAT.COLIDENTATTRIBUTES where TABSCHEMA=? and TABNAME=?";
- using(DB2DataReader reader = schemaInfoCommand.ExecuteReader())
- {
- while(reader.Read())
- {
- string columnName = reader.GetString(0);
-
- int ordinal = FieldNameLookup(_schemaTable, columnName);
- if(ordinal >= 0)
- _schemaTable.Rows[ordinal]["IsAutoIncrement"] = true;
- }
- }
- }
- catch{}
- }
- }
- return _schemaTable;
- }
- #endregion
-
- #region NextResult
-
- public bool NextResult()
- {
- hasRows = false;
- skipReadOnce = false;
- hasData = false;
- columnInfo = null;
- _resultSet = null;
-
- if((behavior & (CommandBehavior.SchemaOnly | CommandBehavior.SingleResult)) != 0)
- return false;
-
- short sqlRet = DB2CLIWrapper.SQLMoreResults(this.hwndStmt);
- if(sqlRet == DB2Constants.SQL_NO_DATA_FOUND)
- return false;
- DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "Db2ClientDataReader - SQLMoreResults", db2Conn);
- return true;
- }
- #endregion
-
- #region Read
-
-#if !NET_1_0
- public bool HasRows
- {
- get
- {
- if(hasData)
- return true;
-
- hasRows = Read();
- hasData = false;
- skipReadOnce = true;
- return hasRows;
- }
- }
-#endif
-
- public bool Read()
- {
- if (isClosed)
- throw new InvalidOperationException("Reader is closed");
- if((behavior & CommandBehavior.SchemaOnly) != 0)
- return false;
-
- if(skipReadOnce)
- {
- skipReadOnce = false;
- hasData = hasRows;
- return hasRows;
- }
-
- _resultSet = null;
- hasData = false;
-
- short sqlRet = DB2CLIWrapper.SQLFetch(hwndStmt);
- if(sqlRet == DB2Constants.SQL_NO_DATA_FOUND)
- return false;
- DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "DB2ClientDataReader - SQLFetch 1", db2Conn);
-
- hasData = true;
- return true;
- }
- #endregion
-
- #region GetColumnInfo
- private void GetColumnInfo()
- {
- if(isClosed)
- throw new InvalidOperationException("Reader is closed");
- if(fieldCount <= 0)
- throw new InvalidOperationException("No Fields found"); // TODO: check error
- if(columnInfo != null)
- return;
-
- columnInfo = new ColumnInfo[fieldCount];
- columnsNames = new Hashtable(fieldCount);
-
- StringBuilder sb = new StringBuilder(400);
- for(int i = 0; i < columnInfo.Length; i++)
- {
- short sqlRet;
- short strlen;
- int numericAttribute;
-
- sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)(i + 1), (short)DB2Constants.SQL_DESC_BASE_COLUMN_NAME, sb, (short)sb.Capacity, out strlen, out numericAttribute);
- DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable");
- columnInfo[i].Colname = sb.ToString();
- columnsNames[columnInfo[i].Colname.ToUpper()] = i;
-
- sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)(i + 1), (short)DB2Constants.SQL_DESC_CONCISE_TYPE, sb, (short)sb.Capacity, out strlen, out columnInfo[i].Sqltype);
- DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable");
-
-
- }
- }
- #endregion
-
- #region Describe/Bind/Fetch functions
- ///
- ///Broke these out so that we can use different paths for Immediate executions and Prepared executions
- /// <summary>
- /// Does the describe and bind steps for the query result set. Called for both immediate and prepared queries.
- /// </summary>
-
-/// <summary>
-/// FetchResults does what it says.
-/// </summary>
-/// <param name="dbVals"></param>
-/// <param name="sqlLen_or_IndPtr"></param>
-/// <param name="_resultSet"></param>
- private int FieldNameLookup(DataTable _schemaTable, string name)
- {
- for(int i = 0; i < _schemaTable.Rows.Count; i++)
- {
- if(CultureInfo.CurrentCulture.CompareInfo.Compare(name, (string)_schemaTable.Rows[i]["BaseColumnName"],
- CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase) == 0)
- {
- return i;
- }
- }
- return -1;
- }
-
- #endregion
-
- #region IDataRecord Interface
- ///Code for the IDataRecord interface
- ///
- #region FieldCount
- ///
- ///
- public int FieldCount
- {
- get
- {
- if (isClosed)
- throw new InvalidOperationException("Reader is closed");
-
- return fieldCount;
- }
- }
- #endregion
-
- #region Item accessors
- public object this[string name]
- {
- get
- {
- int ordinal = GetOrdinal(name);
- return this[ordinal];
- }
- }
- public object this[int col]
- {
- get
- {
- if(columnInfo == null)
- {
- GetColumnInfo();
- }
- switch(columnInfo[col].Sqltype)
- {
- case DB2Constants.SQL_INTEGER:
- return GetInt32Internal(col);
- case DB2Constants.SQL_SMALLINT:
- return GetInt16Internal(col);
- case DB2Constants.SQL_BIGINT:
- return GetInt64Internal(col);
- case DB2Constants.SQL_DOUBLE:
- return GetDoubleInternal(col);
- case DB2Constants.SQL_REAL:
- return GetFloatInternal(col);
- case DB2Constants.SQL_DECIMAL:
- return GetDecimalInternal(col);
- case DB2Constants.SQL_DATETIME:
- case DB2Constants.SQL_TYPE_TIMESTAMP:
- return GetDateTimeInternal(col);
- case DB2Constants.SQL_TYPE_DATE:
- return GetDateInternal(col);
- case DB2Constants.SQL_TYPE_TIME:
- return GetTimeInternal(col);
- case DB2Constants.SQL_TYPE_CLOB:
- case DB2Constants.SQL_CHAR:
- case DB2Constants.SQL_VARCHAR:
- return GetStringInternal(col);
- case DB2Constants.SQL_TYPE_BLOB:
- case DB2Constants.SQL_TYPE_BINARY:
- case DB2Constants.SQL_LONGVARBINARY:
- case DB2Constants.SQL_VARBINARY:
- return GetBlobDataInternal(col);
- }
- throw new NotImplementedException("Unknown SQL type " + columnInfo[col].Sqltype);
- }
- }
- #endregion
-
- #region GetBytes
- ///
- /// GetBytes, return a stream of bytes
- ///
- public long GetBytes(int col, long fieldOffset, byte[] buffer, int bufferOffset, int length)
- {
- // TODO: need better implementation for big BLOBs
-
- byte[] sourceArray = (byte[])this[col];
-#if NET_1_0
- if(buffer == null)
- {
- Array.Copy(sourceArray, (int)fieldOffset, buffer, bufferOffset, length);
- }
- return sourceArray.Length;
-#else
- if(buffer == null)
- {
- Array.Copy(sourceArray, fieldOffset, buffer, bufferOffset, length);
- }
- return sourceArray.LongLength;
-#endif
- }
- #endregion
-
- #region GetChars
- ///
- ///GetChars, returns char array
- ///
- public long GetChars(int col, long fieldOffset, char[] buffer, int bufferOffset, int length)
- {
- // TODO: need better implementation for big CLOBs
-
- string sourceString = GetString(col);
- if(buffer == null)
- {
- sourceString.CopyTo((int)fieldOffset, buffer, bufferOffset, length);
- }
- return (long)sourceString.Length;
- }
- #endregion
-
- #region GetBoolean method
-
- public Boolean GetBoolean(int col)
- {
- return (Boolean)GetBooleanInternal(col);
- }
- internal object GetBooleanInternal(int col)
- {
- if((col < 0) || (col >= fieldCount))
- {
- throw new IndexOutOfRangeException("col");
- }
- if(!hasData)
- {
- throw new InvalidOperationException("No data");
- }
- if(_resultSet == null)
- {
- _resultSet = new object[fieldCount];
- }
- if(_resultSet[col] == null)
- {
- int len;
- short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_BIT, internalBuffer, internalBufferSize, out len);
- if(len == DB2Constants.SQL_NULL_DATA)
- {
- _resultSet[col] = DBNull.Value;
- }
- else
- {
- _resultSet[col] = Marshal.ReadByte(internalBuffer) != 0;
- }
- }
- return _resultSet[col];
- }
- #endregion
-
- #region GetGuid
- ///
- /// GetDateTime method
- ///
- public Guid GetGuid(int col)
- {
- return (Guid)GetGuidInternal(col);
- }
- internal object GetGuidInternal(int col)
- {
- if((col < 0) || (col >= fieldCount))
- {
- throw new IndexOutOfRangeException("col");
- }
- if(!hasData)
- {
- throw new InvalidOperationException("No data");
- }
- if(_resultSet == null)
- {
- _resultSet = new object[fieldCount];
- }
- if(_resultSet[col] == null)
- {
- int len;
- short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_GUID, internalBuffer, internalBufferSize, out len);
- if(len == DB2Constants.SQL_NULL_DATA)
- {
- _resultSet[col] = DBNull.Value;
- }
- else
- {
- _resultSet[col] = Marshal.PtrToStructure(internalBuffer, typeof(Guid));
- }
- }
- return _resultSet[col];
- }
-
- #endregion
-
- #region GetByte
- ///
- ///GetByte
- ///
- public Byte GetByte(int col)
- {
- return (Byte)GetByteInternal(col);
- }
- internal object GetByteInternal(int col)
- {
- if((col < 0) || (col >= fieldCount))
- {
- throw new IndexOutOfRangeException("col");
- }
- if(!hasData)
- {
- throw new InvalidOperationException("No data");
- }
- if(_resultSet == null)
- {
- _resultSet = new object[fieldCount];
- }
- if(_resultSet[col] == null)
- {
- int len;
- short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_UTINYINT, internalBuffer, 10, out len);
- if(len == DB2Constants.SQL_NULL_DATA)
- {
- _resultSet[col] = DBNull.Value;
- }
- else
- {
- _resultSet[col] = Marshal.ReadByte(internalBuffer);
- }
- }
- return _resultSet[col];
- }
- #endregion
-
- #region GetChar
- ///
- ///GetChar, return column as a char
- ///
- public Char GetChar(int col)
- {
- return (Char)GetCharInternal(col);
- }
- internal object GetCharInternal(int col)
- {
- if((col < 0) || (col >= fieldCount))
- {
- throw new IndexOutOfRangeException("col");
- }
- if(!hasData)
- {
- throw new InvalidOperationException("No data");
- }
- if(_resultSet == null)
- {
- _resultSet = new object[fieldCount];
- }
- if(_resultSet[col] == null)
- {
- int len;
- short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_WCHAR, internalBuffer, 10, out len);
- if(len == DB2Constants.SQL_NULL_DATA)
- {
- _resultSet[col] = DBNull.Value;
- }
- else
- {
- _resultSet[col] = Marshal.PtrToStructure(internalBuffer, typeof(char));
- }
- }
- return _resultSet[col];
- }
- #endregion
-
- #region GetData
- ///
- /// GetData method
- ///
- public IDataReader GetData(int col)
- {
- //Have to research this one, not quite sure what the docs mean
- //DB2 does have some structured data types, is that what this is for?
- throw new NotSupportedException();
- }
- #endregion
-
- #region GetDataTypeName
- ///
- ///GetDataTypeName return the type of data
- ///
- public string GetDataTypeName(int col)
- {
- if(columnInfo == null)
- {
- GetColumnInfo();
- }
- switch(columnInfo[col].Sqltype)
- {
- case DB2Constants.SQL_INTEGER:
- return "INTEGER";
- case DB2Constants.SQL_SMALLINT:
- return "SMALLINT";
- case DB2Constants.SQL_BIGINT:
- return "BIGINT";
- case DB2Constants.SQL_DOUBLE:
- return "DOUBLE";
- case DB2Constants.SQL_REAL:
- return "REAL";
- case DB2Constants.SQL_DECIMAL:
- return "DECIMAL";
- case DB2Constants.SQL_DATETIME:
- return "DATETIME";
- case DB2Constants.SQL_TYPE_TIMESTAMP:
- return "TIMESTAMP";
- case DB2Constants.SQL_TYPE_DATE:
- return "DATE";
- case DB2Constants.SQL_TYPE_TIME:
- return "TIME";
- case DB2Constants.SQL_TYPE_CLOB:
- return "CLOB";
- case DB2Constants.SQL_CHAR:
- return "CHAR";
- case DB2Constants.SQL_VARCHAR:
- return "VARCHAR";
- case DB2Constants.SQL_TYPE_BLOB:
- return "BLOB";
- case DB2Constants.SQL_TYPE_BINARY:
- return "BINARY";
- case DB2Constants.SQL_LONGVARBINARY:
- return "LONGVARBINARY";
- case DB2Constants.SQL_VARBINARY:
- return "VARBINARY";
- }
- throw new NotImplementedException("Unknown SQL type " + columnInfo[col].Sqltype);
- }
- #endregion
-
- #region GetDateTime
- ///
- /// GetDateTime method
- ///
-
- public DateTime GetDateTime(int col)
- {
- return (DateTime)GetDateTimeInternal(col);
- }
- internal object GetDateTimeInternal(int col)
- {
- if((col < 0) || (col >= fieldCount))
- {
- throw new IndexOutOfRangeException("col");
- }
- if(!hasData)
- {
- throw new InvalidOperationException("No data");
- }
- if(_resultSet == null)
- {
- _resultSet = new object[fieldCount];
- }
- if(_resultSet[col] == null)
- {
- int len;
- short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_TYPE_TIMESTAMP, internalBuffer, internalBufferSize, out len);
- if(len == DB2Constants.SQL_NULL_DATA)
- {
- _resultSet[col] = DBNull.Value;
- }
- else
- {
- DateTime ret = new DateTime(
- Marshal.ReadInt16(internalBuffer, 0), // year
- Marshal.ReadInt16(internalBuffer, 2), // month
- Marshal.ReadInt16(internalBuffer, 4), // day
- Marshal.ReadInt16(internalBuffer, 6), // hour
- Marshal.ReadInt16(internalBuffer, 8), // minute
- Marshal.ReadInt16(internalBuffer, 10));// second
- _resultSet[col] = ret.AddTicks(Marshal.ReadInt32(internalBuffer, 12) / 100); // nanoseconds
- }
- }
- return _resultSet[col];
- }
- #endregion
-
- #region GetDate
- ///
- /// GetDate method
- ///
- public DateTime GetDate(int col)
- {
- return (DateTime)GetDateInternal(col);
- }
- internal object GetDateInternal(int col)
- {
- if((col < 0) || (col >= fieldCount))
- {
- throw new IndexOutOfRangeException("col");
- }
- if(!hasData)
- {
- throw new InvalidOperationException("No data");
- }
- if(_resultSet == null)
- {
- _resultSet = new object[fieldCount];
- }
- if(_resultSet[col] == null)
- {
- int len;
- short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_TYPE_DATE, internalBuffer, internalBufferSize, out len);
- if(len == DB2Constants.SQL_NULL_DATA)
- {
- _resultSet[col] = DBNull.Value;
- }
- else
- {
- _resultSet[col] = new DateTime(
- Marshal.ReadInt16(internalBuffer, 0), // year
- Marshal.ReadInt16(internalBuffer, 2), // month
- Marshal.ReadInt16(internalBuffer, 4)); // day
- }
- }
- return _resultSet[col];
- }
-
- #endregion
-
- #region GetTime
- ///
- /// GetTime method
- ///
- public TimeSpan GetTimeSpan(int col)
- {
- return (TimeSpan)GetTimeInternal(col);
- }
- public TimeSpan GetTime(int col)
- {
- return (TimeSpan)GetTimeInternal(col);
- }
- internal object GetTimeInternal(int col)
- {
- if((col < 0) || (col >= fieldCount))
- {
- throw new IndexOutOfRangeException("col");
- }
- if(!hasData)
- {
- throw new InvalidOperationException("No data");
- }
- if(_resultSet == null)
- {
- _resultSet = new object[fieldCount];
- }
- if(_resultSet[col] == null)
- {
- int len;
- short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_TYPE_TIME, internalBuffer, internalBufferSize, out len);
- if(len == DB2Constants.SQL_NULL_DATA)
- {
- _resultSet[col] = DBNull.Value;
- }
- else
- {
- _resultSet[col] = new TimeSpan(
- Marshal.ReadInt16(internalBuffer, 0), // Hour
- Marshal.ReadInt16(internalBuffer, 2), // Minute
- Marshal.ReadInt16(internalBuffer, 4)); // Second
- }
- }
- return _resultSet[col];
- }
-
- #endregion
-
-
- #region GetDecimal
- ///
- ///GetDecimal method
- ///
-
- public Decimal GetDecimal(int col)
- {
- return (Decimal)GetDecimalInternal(col);
- }
- internal object GetDecimalInternal(int col)
- {
- object tmp = GetStringInternal(col);
- if(tmp is string)
- {
- _resultSet[col] = decimal.Parse(((string)_resultSet[col]).Replace(',','.'), // sometimes we get a '.' and sometimes we get a ','
- System.Globalization.CultureInfo.InvariantCulture);
- }
- // if((col < 0) || (col >= fieldCount)) // only works on windows UDB DB2 V8?
- // {
- // throw new IndexOutOfRangeException("col");
- // }
- // if(!hasData)
- // {
- // throw new InvalidOperationException("No data");
- // }
- // if(_resultSet == null)
- // {
- // _resultSet = new object[fieldCount];
- // }
- // if(_resultSet[col] == null)
- // {
- // int len;
- // short sqlRet = Db2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)Db2Constants.SQL_C_DECIMAL_OLEDB, internalBuffer, internalBufferSize, out len);
- // if(len == Db2Constants.SQL_NULL_DATA)
- // {
- // _resultSet[col] = DBNull.Value;
- // }
- // else
- // {
- // _resultSet[col] = Marshal.PtrToStructure(internalBuffer, typeof(decimal));
- // }
- // }
- return _resultSet[col];
- }
- #endregion
-
- #region GetDouble
- ///
- /// GetDouble
- ///
- public Double GetDouble(int col)
- {
- return (Double)GetDoubleInternal(col);
- }
- internal object GetDoubleInternal(int col)
- {
- if((col < 0) || (col >= fieldCount))
- {
- throw new IndexOutOfRangeException("col");
- }
- if(!hasData)
- {
- throw new InvalidOperationException("No data");
- }
- if(_resultSet == null)
- {
- _resultSet = new object[fieldCount];
- }
- if(_resultSet[col] == null)
- {
- int len;
- short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_DOUBLE, internalBuffer, internalBufferSize, out len);
- if(len == DB2Constants.SQL_NULL_DATA)
- {
- _resultSet[col] = DBNull.Value;
- }
- else
- {
- _resultSet[col] = Marshal.PtrToStructure(internalBuffer, typeof(double));
- }
- }
- return _resultSet[col];
- }
- #endregion
-
- #region GetFieldType
- ///
- /// Type GetFieldType
- ///
- public Type GetFieldType(int col)
- {
- if(columnInfo == null)
- {
- GetColumnInfo();
- }
- return GetManagedType(columnInfo[col].Sqltype);
- }
- #endregion
-
- #region GetFloat
- ///
- /// GetFloat
- ///
- public float GetFloat(int col)
- {
- return (float)GetFloatInternal(col);
- }
- internal object GetFloatInternal(int col)
- {
- if((col < 0) || (col >= fieldCount))
- {
- throw new IndexOutOfRangeException("col");
- }
- if(!hasData)
- {
- throw new InvalidOperationException("No data");
- }
- if(_resultSet == null)
- {
- _resultSet = new object[fieldCount];
- }
- if(_resultSet[col] == null)
- {
- int len;
- short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_TYPE_REAL, internalBuffer, internalBufferSize, out len);
- if(len == DB2Constants.SQL_NULL_DATA)
- {
- _resultSet[col] = DBNull.Value;
- }
- else
- {
- _resultSet[col] = Marshal.PtrToStructure(internalBuffer, typeof(float));
- }
- }
- return _resultSet[col];
- }
- #endregion
-
- #region The GetInt?? series
- ///
- ///GetInt16
- ///
- public short GetInt16(int col)
- {
- return (short)GetInt16Internal(col);
- }
-
- internal object GetInt16Internal(int col)
- {
- if((col < 0) || (col >= fieldCount))
- {
- throw new IndexOutOfRangeException("col");
- }
- if(!hasData)
- {
- throw new InvalidOperationException("No data");
- }
- if(_resultSet == null)
- {
- _resultSet = new object[fieldCount];
- }
- if(_resultSet[col] == null)
- {
- int len;
- short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_SSHORT, internalBuffer, internalBufferSize, out len);
- if(len == DB2Constants.SQL_NULL_DATA)
- {
- _resultSet[col] = DBNull.Value;
- }
- else
- {
- _resultSet[col] = Marshal.PtrToStructure(internalBuffer, typeof(short));
- }
- }
- return _resultSet[col];
- }
- ///
- ///GetInt32
- ///
- public int GetInt32(int col)
- {
- return (int)GetInt32Internal(col);
- }
-
- internal object GetInt32Internal(int col)
- {
- if((col < 0) || (col >= fieldCount))
- {
- throw new IndexOutOfRangeException("col");
- }
- if(!hasData)
- {
- throw new InvalidOperationException("No data");
- }
- if(_resultSet == null)
- {
- _resultSet = new object[fieldCount];
- }
- if(_resultSet[col] == null)
- {
- int len;
- short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_SLONG, internalBuffer, internalBufferSize, out len);
- if(len == DB2Constants.SQL_NULL_DATA)
- {
- _resultSet[col] = DBNull.Value;
- }
- else
- {
- _resultSet[col] = Marshal.PtrToStructure(internalBuffer, typeof(int));
- }
- }
- return _resultSet[col];
- }
-
- ///
- ///GetInt64
- ///
- public long GetInt64(int col)
- {
- return (long)GetInt64Internal(col);
- }
-
- internal object GetInt64Internal(int col)
- {
- if((col < 0) || (col >= fieldCount))
- {
- throw new IndexOutOfRangeException("col");
- }
- if(!hasData)
- {
- throw new InvalidOperationException("No data");
- }
- if(_resultSet == null)
- {
- _resultSet = new object[fieldCount];
- }
- if(_resultSet[col] == null)
- {
- int len;
- short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_SBIGINT, internalBuffer, internalBufferSize, out len);
- if(len == DB2Constants.SQL_NULL_DATA)
- {
- _resultSet[col] = DBNull.Value;
- }
- else
- {
- _resultSet[col] = Marshal.PtrToStructure(internalBuffer, typeof(long));
- }
- }
- return _resultSet[col];
- }
-
- #endregion
-
- #region GetName
- ///
- ///GetName, returns the name of the field
- ///
- public string GetName(int col)
- {
- if(columnInfo == null)
- {
- GetColumnInfo();
- }
- return columnInfo[col].Colname;
- }
- #endregion
-
- #region GetOrdinal
- ///
- /// GetOrdinal, return the index of the named column
- ///
- public int GetOrdinal(string name)
- {
- if(columnInfo == null)
- {
- GetColumnInfo();
- }
- object ordinal = columnsNames[name.ToUpper()];
- if(ordinal == null)
- {
- throw new IndexOutOfRangeException("name");
- }
- return (int)ordinal;
- }
- #endregion
-
- #region GetString
- ///
- /// GetString returns a string
- ///
- public string GetString(int col)
- {
- return (string)GetStringInternal(col);
- }
-
- public object GetStringInternal(int col)
- {
- if((col < 0) || (col >= fieldCount))
- {
- throw new IndexOutOfRangeException("col");
- }
- if(!hasData)
- {
- throw new InvalidOperationException("No data");
- }
- if(_resultSet == null)
- {
- _resultSet = new object[fieldCount];
- }
- if(_resultSet[col] == null)
- {
- int length;
- short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_WCHAR, (StringBuilder)null, 0, out length);
- if(length == DB2Constants.SQL_NULL_DATA)
- {
- _resultSet[col] = DBNull.Value;
- }
- else
- {
- IntPtr mem = Marshal.AllocHGlobal(length + 2);
- sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_WCHAR, mem, length + 2, out length);
- _resultSet[col] = Marshal.PtrToStringUni(mem);
- Marshal.FreeHGlobal(mem);
- }
- }
- return _resultSet[col];
- }
- #endregion
-
- #region GetValue
- ///
- /// GetVCalue, returns an object
- ///
- public object GetValue(int col)
- {
- return this[col];
- }
- #endregion
-
- #region GetValues
- ///
- /// GetValues returns all columns in the row through the argument, and the number of columns in the return value
- ///
- public int GetValues(object[] values)
- {
- int count = Math.Min(fieldCount, values.Length);
-
- for (int i = 0; i < count; i++)
- {
- values[i] = this[i];
-
- }
-
- return count;
- }
- #endregion
-
- #region IsDBNull
- ///
- /// IsDBNull Is the column null
- ///
- public bool IsDBNull(int col)
- {
- //Proper implementation once I get the SQLDescribe/SQLBind/SQLFetch stuff in place
- return Convert.IsDBNull(this[col]);
- }
- #endregion
-
- #endregion ///For IDataRecord
-
- #region private methods
-
- private DataTable BuildNewSchemaTable()
- {
- DataTable schemaTable = new DataTable("SchemaTable");
-
- schemaTable.Columns.Add(new DataColumn("ColumnName", typeof(string)));
- schemaTable.Columns.Add(new DataColumn("ColumnOrdinal", typeof(int)));
- schemaTable.Columns.Add(new DataColumn("ColumnSize", typeof(int)));
- schemaTable.Columns.Add(new DataColumn("NumericPrecision", typeof(short)));
- schemaTable.Columns.Add(new DataColumn("NumericScale", typeof(short)));
- schemaTable.Columns.Add(new DataColumn("DataType", typeof(System.Type)));
- schemaTable.Columns.Add(new DataColumn("ProviderType", typeof(int)));
- schemaTable.Columns.Add(new DataColumn("IsLong", typeof(bool)));
- schemaTable.Columns.Add(new DataColumn("AllowDBNull", typeof(bool)));
- schemaTable.Columns.Add(new DataColumn("IsReadOnly", typeof(bool)));
- schemaTable.Columns.Add(new DataColumn("IsRowVersion", typeof(bool)));
- schemaTable.Columns.Add(new DataColumn("IsUnique", typeof(bool)));
- schemaTable.Columns.Add(new DataColumn("IsKey", typeof(bool)));
- schemaTable.Columns.Add(new DataColumn("IsKeyColumn", typeof(bool)));
- schemaTable.Columns.Add(new DataColumn("IsAutoIncrement", typeof(bool)));
- schemaTable.Columns.Add(new DataColumn("BaseSchemaName", typeof(string)));
- schemaTable.Columns.Add(new DataColumn("BaseCatalogName", typeof(string)));
- schemaTable.Columns.Add(new DataColumn("BaseTableName", typeof(string)));
- schemaTable.Columns.Add(new DataColumn("BaseColumnName", typeof(string)));
-
- return schemaTable;
- }
- #endregion
-
- private void InitMem(int memSize, ref IntPtr ptr){
- if (ptr.ToInt32() == 0){
- unsafe{
- fixed(byte* arr = new byte[memSize]){
- ptr = new IntPtr(arr);
- }
- }
- }
- }
-
- private Type GetManagedType(int sql_type)
- {
- switch(sql_type)
- {
- case DB2Constants.SQL_INTEGER:
- return typeof(int);
- case DB2Constants.SQL_SMALLINT:
- return typeof(short);
- case DB2Constants.SQL_BIGINT:
- return typeof(long);
- case DB2Constants.SQL_DOUBLE:
- return typeof(double);
- case DB2Constants.SQL_DECIMAL:
- return typeof(decimal);
- case DB2Constants.SQL_DATETIME:
- case DB2Constants.SQL_TYPE_DATE:
- case DB2Constants.SQL_TYPE_TIMESTAMP:
- return typeof(DateTime);
- case DB2Constants.SQL_TYPE_TIME:
- return typeof(TimeSpan);
- case DB2Constants.SQL_CHAR:
- case DB2Constants.SQL_VARCHAR:
- case DB2Constants.SQL_TYPE_CLOB:
- return typeof(string);
- case DB2Constants.SQL_TYPE_BLOB:
- case DB2Constants.SQL_TYPE_BINARY:
- case DB2Constants.SQL_LONGVARBINARY:
- case DB2Constants.SQL_VARBINARY:
- return typeof(byte[]);
- }
- throw new NotImplementedException("Unknown SQL type " + sql_type);
- }
-
- private bool IsLong(short sql_type)
- {
- switch(sql_type)
- {
- case DB2Constants.SQL_TYPE_CLOB:
- case DB2Constants.SQL_TYPE_BLOB:
- return true;
- }
- return false;
- }
- private object GetBlobDataInternal(int col)
- {
- if((col < 0) || (col >= fieldCount))
- {
- throw new IndexOutOfRangeException("col");
- }
- if(!hasData)
- {
- throw new InvalidOperationException("No data");
- }
- if(_resultSet == null)
- {
- _resultSet = new object[fieldCount];
- }
- if(_resultSet[col] == null)
- {
- int length;
- short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_TYPE_BINARY, (StringBuilder)null, 0, out length);
- if(length == DB2Constants.SQL_NULL_DATA)
- {
- _resultSet[col] = DBNull.Value;
- }
- else
- {
- byte[] result = new byte[length];
- sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_TYPE_BINARY, result, length, out length);
- _resultSet[col] = result;
- }
- }
- return _resultSet[col];
- }
- }
-
-}
-#endregion
+\r
+//\r
+// Permission is hereby granted, free of charge, to any person obtaining\r
+// a copy of this software and associated documentation files (the\r
+// "Software"), to deal in the Software without restriction, including\r
+// without limitation the rights to use, copy, modify, merge, publish,\r
+// distribute, sublicense, and/or sell copies of the Software, and to\r
+// permit persons to whom the Software is furnished to do so, subject to\r
+// the following conditions:\r
+// \r
+// The above copyright notice and this permission notice shall be\r
+// included in all copies or substantial portions of the Software.\r
+// \r
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+//\r
+using System;\r
+using System.Collections;\r
+using System.Data;\r
+using System.Runtime.InteropServices;\r
+using System.Globalization;\r
+using System.Text;\r
+\r
+namespace IBM.Data.DB2\r
+{\r
+ /// <summary>\r
+ /// Summary description for DB2ClientDataReader.\r
+ /// DB2ClientDataReader. \r
+ /// </summary>\r
+ public sealed class DB2DataReader : MarshalByRefObject, IDataReader\r
+ {\r
+ private struct ColumnInfo\r
+ {\r
+ public string Colname;\r
+ public int Sqltype;\r
+ }\r
+\r
+ private object[] _resultSet;\r
+ private ColumnInfo[] columnInfo;\r
+ private Hashtable columnsNames;\r
+ private const int internalBufferSize = 100;\r
+ private IntPtr internalBuffer;\r
+ internal DB2Connection db2Conn; \r
+ internal DB2Command db2Comm; \r
+ internal IntPtr hwndStmt;\r
+ private int recordsAffected;\r
+ private bool hasData = false;\r
+ private int fieldCount = -1;\r
+ private CommandBehavior behavior;\r
+ private bool hasRows;\r
+ private bool skipReadOnce;\r
+ \r
+ \r
+ #region Constructors and destructors\r
+ /// <summary>\r
+ /// \r
+ /// </summary>\r
+ /// <param name="con"></Connection object to Db2>\r
+ /// <param name="com"></Command object>\r
+ internal DB2DataReader(DB2Connection con, DB2Command com, CommandBehavior behavior)\r
+ {\r
+ db2Conn = con;\r
+ db2Comm = com;\r
+ this.behavior = behavior;\r
+ hwndStmt = com.statementHandle; //We have access to the results through the statement handle\r
+ \r
+ _resultSet = null;\r
+ \r
+ GetFieldCountAndAffectedRows();\r
+ internalBuffer = Marshal.AllocHGlobal(internalBufferSize);\r
+\r
+ isClosed = false;\r
+ }\r
+\r
+ #endregion\r
+\r
+ private void GetFieldCountAndAffectedRows()\r
+ {\r
+ short sqlRet;\r
+ recordsAffected = -1;\r
+ if((behavior & CommandBehavior.SchemaOnly) == 0)\r
+ {\r
+ //How many rows affected. numRows will be -1 if we aren't dealing with an Insert, Delete or Update, or if the statement did not execute successfully\r
+ sqlRet = DB2CLIWrapper.SQLRowCount(hwndStmt, out recordsAffected);\r
+ DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "SQLExecDirect error.", db2Conn);\r
+ } \r
+ short colCount;\r
+ sqlRet = DB2CLIWrapper.SQLNumResultCols(hwndStmt, out colCount);\r
+ DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "DB2ClientDataReader - SQLNumResultCols", db2Conn);\r
+ fieldCount = colCount;\r
+ }\r
+\r
+ #region Properties\r
+\r
+ #region Depth property \r
+ ///\r
+ ///Depth of nesting for the current row, need to figure out what this translates into \r
+ ///with DB2.\r
+ ///\r
+ private int depth = 0;\r
+ public int Depth\r
+ {\r
+ get\r
+ {\r
+ if(isClosed)\r
+ {\r
+ throw new InvalidOperationException("Reader is closed");\r
+ }\r
+ return depth;\r
+ }\r
+ }\r
+ #endregion\r
+\r
+ #region IsClosed property\r
+ /// <summary>\r
+ /// True if the reader is closed.\r
+ /// </summary>\r
+ private bool isClosed = true;\r
+ public bool IsClosed\r
+ {\r
+ get\r
+ {\r
+ return isClosed;\r
+ }\r
+ }\r
+ #endregion\r
+\r
+ #region RecordsAffected property\r
+ ///\r
+ /// Number of records affected by this operation. Will be zero until we close the \r
+ /// reader\r
+ /// \r
+ \r
+ public int RecordsAffected\r
+ {\r
+ get\r
+ {\r
+ return recordsAffected;\r
+ }\r
+ }\r
+ #endregion\r
+\r
+ #endregion\r
+\r
+ #region Methods\r
+\r
+\r
+\r
+ #region Close method\r
+\r
+ public void Close()\r
+ {\r
+ Dispose();\r
+ }\r
+\r
+ public void Dispose()\r
+ {\r
+ Dispose(true);\r
+ GC.SuppressFinalize(this);\r
+ }\r
+\r
+ void Dispose(bool disposing)\r
+ {\r
+ if(!isClosed) \r
+ {\r
+ if(disposing)\r
+ {\r
+ short sqlRet;\r
+ do\r
+ {\r
+ sqlRet = DB2CLIWrapper.SQLMoreResults(this.hwndStmt);\r
+ DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "Db2ClientDataReader - SQLMoreResults", db2Conn);\r
+ } while(sqlRet != DB2Constants.SQL_NO_DATA_FOUND);\r
+\r
+ _resultSet = null;\r
+ hasData = false;\r
+ isClosed=true;\r
+\r
+ if(db2Comm != null)\r
+ {\r
+ db2Comm.DataReaderClosed();\r
+ db2Comm = null;\r
+ }\r
+ }\r
+ Marshal.FreeHGlobal(internalBuffer);\r
+ }\r
+ isClosed = true;\r
+ }\r
+\r
+ ~DB2DataReader()\r
+ {\r
+ Dispose(false);\r
+ }\r
+\r
+ #endregion\r
+\r
+ #region GetSchemaTable \r
+\r
+ public DataTable GetSchemaTable()\r
+ {\r
+ if(isClosed)\r
+ {\r
+ throw new InvalidOperationException("No data exists for the row/column.");\r
+ }\r
+\r
+ DataTable _schemaTable = BuildNewSchemaTable();\r
+ \r
+ short sqlRet;\r
+ IntPtr ptrCharacterAttribute = IntPtr.Zero;\r
+ InitMem(256, ref ptrCharacterAttribute);\r
+ short buflen = 256;\r
+ short strlen = 256;\r
+ int numericattr = 0;\r
+ int colsize;\r
+ string colname;\r
+ int sqltype;\r
+ int precision;\r
+ int scale;\r
+ int nullable;\r
+ int updatable;\r
+ int isautoincrement;\r
+ string baseschemaname;\r
+ //string basecatalogname;\r
+ string basetablename;\r
+ string basecolumnname;\r
+\r
+ string previousTableName = null;\r
+ string previousSchemaName = null;\r
+ bool differentTablesUsed = false;\r
+\r
+ for (short i=1; i<=fieldCount; i++) \r
+ {\r
+ sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)i, (short)DB2Constants.SQL_DESC_COLUMN_NAME, ptrCharacterAttribute, buflen, ref strlen, ref numericattr);\r
+ DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable", db2Conn);\r
+ colname = Marshal.PtrToStringUni(ptrCharacterAttribute);\r
+ \r
+ sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)i, (short)DB2Constants.SQL_DESC_CONCISE_TYPE, ptrCharacterAttribute, buflen, ref strlen, ref numericattr);\r
+ DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable", db2Conn);\r
+ sqltype = numericattr;\r
+ \r
+ sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)i, (short)DB2Constants.SQL_DESC_OCTET_LENGTH, ptrCharacterAttribute, buflen, ref strlen, ref numericattr);\r
+ DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable", db2Conn);\r
+ colsize = numericattr;\r
+ \r
+ sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)i, (short)DB2Constants.SQL_DESC_PRECISION, ptrCharacterAttribute, buflen, ref strlen, ref numericattr);\r
+ DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable", db2Conn);\r
+ precision = numericattr;\r
+ \r
+ sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)i, (short)DB2Constants.SQL_DESC_SCALE, ptrCharacterAttribute, buflen, ref strlen, ref numericattr);\r
+ DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable", db2Conn);\r
+ scale = numericattr;\r
+\r
+ sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)i, (short)DB2Constants.SQL_DESC_NULLABLE, ptrCharacterAttribute, buflen, ref strlen, ref numericattr);\r
+ DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable", db2Conn);\r
+ nullable = numericattr;\r
+\r
+ sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)i, (short)DB2Constants.SQL_DESC_UPDATABLE, ptrCharacterAttribute, buflen, ref strlen, ref numericattr);\r
+ DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable", db2Conn);\r
+ updatable = numericattr;\r
+ \r
+ sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)i, (short)DB2Constants.SQL_DESC_AUTO_UNIQUE_VALUE, ptrCharacterAttribute, buflen, ref strlen, ref numericattr);\r
+ DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable", db2Conn);\r
+ isautoincrement = numericattr;\r
+ \r
+ sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)i, (short)DB2Constants.SQL_DESC_BASE_COLUMN_NAME, ptrCharacterAttribute, buflen, ref strlen, ref numericattr);\r
+ DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable", db2Conn);\r
+ basecolumnname = Marshal.PtrToStringUni(ptrCharacterAttribute);\r
+\r
+ sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)i, (short)DB2Constants.SQL_DESC_BASE_TABLE_NAME, ptrCharacterAttribute, buflen, ref strlen, ref numericattr);\r
+ DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable", db2Conn);\r
+ basetablename = Marshal.PtrToStringUni(ptrCharacterAttribute);\r
+ \r
+ sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)i, (short)DB2Constants.SQL_DESC_SCHEMA_NAME, ptrCharacterAttribute, buflen, ref strlen, ref numericattr);\r
+ DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable", db2Conn);\r
+ baseschemaname = Marshal.PtrToStringUni(ptrCharacterAttribute);\r
+ DataRow r = _schemaTable.NewRow();\r
+ \r
+ r["ColumnName"] = colname;\r
+ r["ColumnOrdinal"] = i - 1;\r
+ r["ColumnSize"] = colsize;\r
+ r["NumericPrecision"] = precision;\r
+ r["NumericScale"] = scale;\r
+ r["DataType"] = GetManagedType((short)sqltype);\r
+ r["ProviderType"] = sqltype;\r
+ r["IsLong"] = IsLong((short)sqltype);\r
+ r["AllowDBNull"] = (nullable==0) ? false : true;\r
+ r["IsReadOnly"] = (basecolumnname == null) || (basecolumnname == "");\r
+ r["IsRowVersion"] = false;\r
+ r["IsUnique"] = false;\r
+ r["IsKeyColumn"] = false;\r
+ r["IsAutoIncrement"] = (isautoincrement==0) ? false : true;\r
+ r["BaseSchemaName"] = baseschemaname;\r
+ r["BaseCatalogName"] = "";\r
+ r["BaseTableName"] = basetablename;\r
+ r["BaseColumnName"] = basecolumnname;\r
+ \r
+ _schemaTable.Rows.Add(r);\r
+\r
+ if(!differentTablesUsed)\r
+ {\r
+ if(((previousSchemaName == baseschemaname) && (previousTableName == basetablename)) || \r
+ (previousTableName == null))\r
+ {\r
+ previousTableName = basetablename;\r
+ previousSchemaName = baseschemaname;\r
+ }\r
+ else\r
+ {\r
+ differentTablesUsed = true;\r
+ }\r
+ }\r
+ }\r
+ if(!differentTablesUsed && \r
+ ((behavior & CommandBehavior.KeyInfo) != 0) &&\r
+ (db2Comm.Transaction == null) &&\r
+ (previousTableName != null) &&\r
+ (previousTableName != ""))\r
+ {\r
+ DB2Command schemaInfoCommand = db2Conn.CreateCommand();\r
+ schemaInfoCommand.CommandText = \r
+ "select concat(concat(INDSCHEMA,'.'),INDNAME), COLNAMES, UNIQUERULE from syscat.INDEXES " +\r
+ "where TABSCHEMA=? and TABNAME=? and uniquerule in ('P','U') order by UNIQUERULE";\r
+ schemaInfoCommand.Parameters.Add("TABSCHEMA", previousSchemaName);\r
+ schemaInfoCommand.Parameters.Add("TABNAME", previousTableName);\r
+ using(DB2DataReader reader = schemaInfoCommand.ExecuteReader())\r
+ {\r
+ bool keyColumnSet = false;\r
+ while(reader.Read())\r
+ {\r
+ string indexName = reader.GetString(0);\r
+ string[] indexColumns = reader.GetString(1).TrimStart('-', '+').Split('-', '+');\r
+ bool primary = reader.GetString(2) == "P";\r
+\r
+ bool allColumnsFound = true;\r
+ for(int i= 0; i < indexColumns.Length; i++)\r
+ {\r
+ int ordinal = FieldNameLookup(_schemaTable, indexColumns[i]);\r
+ if(ordinal < 0)\r
+ {\r
+ allColumnsFound = false;\r
+ break;\r
+ }\r
+ if(indexColumns.Length == 1)\r
+ _schemaTable.Rows[ordinal]["IsUnique"] = true;\r
+ }\r
+ if(allColumnsFound && !keyColumnSet)\r
+ {\r
+ for(int i= 0; i < indexColumns.Length; i++)\r
+ _schemaTable.Rows[FieldNameLookup(_schemaTable, indexColumns[i])]["IsKeyColumn"] = true;\r
+ keyColumnSet = true;\r
+ }\r
+ }\r
+ }\r
+ if(db2Conn.openConnection.MajorVersion >= 8)\r
+ {\r
+ try\r
+ {\r
+ schemaInfoCommand.CommandText = \r
+ "select COLNAME from SYSCAT.COLIDENTATTRIBUTES where TABSCHEMA=? and TABNAME=?";\r
+ using(DB2DataReader reader = schemaInfoCommand.ExecuteReader())\r
+ {\r
+ while(reader.Read())\r
+ {\r
+ string columnName = reader.GetString(0);\r
+\r
+ int ordinal = FieldNameLookup(_schemaTable, columnName);\r
+ if(ordinal >= 0)\r
+ _schemaTable.Rows[ordinal]["IsAutoIncrement"] = true;\r
+ }\r
+ }\r
+ }\r
+ catch{}\r
+ }\r
+ }\r
+ return _schemaTable;\r
+ }\r
+ #endregion\r
+\r
+ #region NextResult \r
+\r
+ public bool NextResult()\r
+ {\r
+ hasRows = false;\r
+ skipReadOnce = false;\r
+ hasData = false;\r
+ columnInfo = null;\r
+ _resultSet = null;\r
+ \r
+ if((behavior & (CommandBehavior.SchemaOnly | CommandBehavior.SingleResult)) != 0)\r
+ return false;\r
+\r
+ short sqlRet = DB2CLIWrapper.SQLMoreResults(this.hwndStmt);\r
+ if(sqlRet == DB2Constants.SQL_NO_DATA_FOUND) \r
+ return false;\r
+ DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "Db2ClientDataReader - SQLMoreResults", db2Conn);\r
+ return true;\r
+ }\r
+ #endregion\r
+\r
+ #region Read\r
+\r
+ public bool HasRows\r
+ {\r
+ get\r
+ {\r
+ if(hasData)\r
+ return true;\r
+\r
+ hasRows = Read();\r
+ hasData = false;\r
+ skipReadOnce = true;\r
+ return hasRows;\r
+ }\r
+ }\r
+\r
+ public bool Read()\r
+ {\r
+ if (isClosed)\r
+ throw new InvalidOperationException("Reader is closed");\r
+ if((behavior & CommandBehavior.SchemaOnly) != 0)\r
+ return false;\r
+\r
+ if(skipReadOnce)\r
+ {\r
+ skipReadOnce = false;\r
+ hasData = hasRows;\r
+ return hasRows;\r
+ }\r
+\r
+ _resultSet = null;\r
+ hasData = false;\r
+\r
+ short sqlRet = DB2CLIWrapper.SQLFetch(hwndStmt);\r
+ if(sqlRet == DB2Constants.SQL_NO_DATA_FOUND)\r
+ return false;\r
+ DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "DB2ClientDataReader - SQLFetch 1", db2Conn);\r
+\r
+ hasData = true;\r
+ return true;\r
+ }\r
+ #endregion\r
+\r
+ #region GetColumnInfo\r
+ private void GetColumnInfo()\r
+ {\r
+ if(isClosed)\r
+ throw new InvalidOperationException("Reader is closed");\r
+ if(fieldCount <= 0)\r
+ throw new InvalidOperationException("No Fields found"); // TODO: check error\r
+ if(columnInfo != null)\r
+ return;\r
+ \r
+ columnInfo = new ColumnInfo[fieldCount];\r
+ columnsNames = new Hashtable(fieldCount);\r
+ \r
+ StringBuilder sb = new StringBuilder(400);\r
+ for(int i = 0; i < columnInfo.Length; i++)\r
+ {\r
+ short sqlRet;\r
+ short strlen;\r
+ int numericAttribute;\r
+\r
+ sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)(i + 1), (short)DB2Constants.SQL_DESC_BASE_COLUMN_NAME, sb, (short)sb.Capacity, out strlen, out numericAttribute);\r
+ DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable");\r
+ columnInfo[i].Colname = sb.ToString();\r
+ columnsNames[columnInfo[i].Colname.ToUpper()] = i;\r
+\r
+ sqlRet = DB2CLIWrapper.SQLColAttribute(hwndStmt, (short)(i + 1), (short)DB2Constants.SQL_DESC_CONCISE_TYPE, sb, (short)sb.Capacity, out strlen, out columnInfo[i].Sqltype);\r
+ DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_STMT, hwndStmt, "GetSchemaTable");\r
+\r
+\r
+ }\r
+ }\r
+ #endregion\r
+\r
+ #region Describe/Bind/Fetch functions\r
+ ///\r
+ ///Broke these out so that we can use different paths for Immediate executions and Prepared executions\r
+ /// <summary>\r
+ /// Does the describe and bind steps for the query result set. Called for both immediate and prepared queries. \r
+ /// </summary>\r
+ \r
+/// <summary>\r
+/// FetchResults does what it says.\r
+/// </summary>\r
+/// <param name="dbVals"></param>\r
+/// <param name="sqlLen_or_IndPtr"></param>\r
+/// <param name="_resultSet"></param>\r
+ private int FieldNameLookup(DataTable _schemaTable, string name)\r
+ {\r
+ for(int i = 0; i < _schemaTable.Rows.Count; i++)\r
+ {\r
+ if(CultureInfo.CurrentCulture.CompareInfo.Compare(name, (string)_schemaTable.Rows[i]["BaseColumnName"],\r
+ CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase) == 0)\r
+ {\r
+ return i;\r
+ }\r
+ }\r
+ return -1;\r
+ }\r
+ \r
+ #endregion\r
+\r
+ #region IDataRecord Interface\r
+ ///Code for the IDataRecord interface\r
+ ///\r
+ #region FieldCount\r
+ ///\r
+ ///\r
+ public int FieldCount\r
+ {\r
+ get\r
+ {\r
+ if (isClosed)\r
+ throw new InvalidOperationException("Reader is closed");\r
+\r
+ return fieldCount;\r
+ }\r
+ }\r
+ #endregion\r
+\r
+ #region Item accessors\r
+ public object this[string name]\r
+ {\r
+ get\r
+ {\r
+ int ordinal = GetOrdinal(name);\r
+ return this[ordinal];\r
+ }\r
+ }\r
+ public object this[int col]\r
+ {\r
+ get\r
+ {\r
+ if(columnInfo == null)\r
+ {\r
+ GetColumnInfo();\r
+ }\r
+ switch(columnInfo[col].Sqltype)\r
+ {\r
+ case DB2Constants.SQL_INTEGER:\r
+ return GetInt32Internal(col);\r
+ case DB2Constants.SQL_SMALLINT:\r
+ return GetInt16Internal(col);\r
+ case DB2Constants.SQL_BIGINT:\r
+ return GetInt64Internal(col);\r
+ case DB2Constants.SQL_DOUBLE:\r
+ return GetDoubleInternal(col);\r
+ case DB2Constants.SQL_REAL:\r
+ return GetFloatInternal(col);\r
+ case DB2Constants.SQL_DECIMAL:\r
+ return GetDecimalInternal(col);\r
+ case DB2Constants.SQL_DATETIME:\r
+ case DB2Constants.SQL_TYPE_TIMESTAMP:\r
+ return GetDateTimeInternal(col);\r
+ case DB2Constants.SQL_TYPE_DATE:\r
+ return GetDateInternal(col);\r
+ case DB2Constants.SQL_TYPE_TIME:\r
+ return GetTimeInternal(col);\r
+ case DB2Constants.SQL_TYPE_CLOB:\r
+ case DB2Constants.SQL_CHAR:\r
+ case DB2Constants.SQL_VARCHAR:\r
+ return GetStringInternal(col);\r
+ case DB2Constants.SQL_TYPE_BLOB:\r
+ case DB2Constants.SQL_TYPE_BINARY:\r
+ case DB2Constants.SQL_LONGVARBINARY:\r
+ case DB2Constants.SQL_VARBINARY:\r
+ return GetBlobDataInternal(col);\r
+ }\r
+ throw new NotImplementedException("Unknown SQL type " + columnInfo[col].Sqltype);\r
+ }\r
+ }\r
+ #endregion\r
+\r
+ #region GetBytes\r
+ ///\r
+ /// GetBytes, return a stream of bytes\r
+ ///\r
+ public long GetBytes(int col, long fieldOffset, byte[] buffer, int bufferOffset, int length)\r
+ {\r
+ // TODO: need better implementation for big BLOBs\r
+\r
+ byte[] sourceArray = (byte[])this[col];\r
+ if(buffer == null)\r
+ {\r
+ Array.Copy(sourceArray, fieldOffset, buffer, bufferOffset, length);\r
+ }\r
+ return sourceArray.LongLength;\r
+ }\r
+ #endregion\r
+\r
+ #region GetChars\r
+ ///\r
+ ///GetChars, returns char array\r
+ ///\r
+ public long GetChars(int col, long fieldOffset, char[] buffer, int bufferOffset, int length)\r
+ {\r
+ // TODO: need better implementation for big CLOBs\r
+\r
+ string sourceString = GetString(col);\r
+ if(buffer == null)\r
+ {\r
+ sourceString.CopyTo((int)fieldOffset, buffer, bufferOffset, length);\r
+ }\r
+ return (long)sourceString.Length;\r
+ }\r
+ #endregion\r
+\r
+ #region GetBoolean method\r
+\r
+ public Boolean GetBoolean(int col)\r
+ {\r
+ return (Boolean)GetBooleanInternal(col);\r
+ }\r
+ internal object GetBooleanInternal(int col)\r
+ {\r
+ if((col < 0) || (col >= fieldCount))\r
+ {\r
+ throw new IndexOutOfRangeException("col");\r
+ }\r
+ if(!hasData)\r
+ {\r
+ throw new InvalidOperationException("No data");\r
+ }\r
+ if(_resultSet == null)\r
+ {\r
+ _resultSet = new object[fieldCount];\r
+ }\r
+ if(_resultSet[col] == null)\r
+ {\r
+ int len;\r
+ short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_BIT, internalBuffer, internalBufferSize, out len);\r
+ if(len == DB2Constants.SQL_NULL_DATA)\r
+ {\r
+ _resultSet[col] = DBNull.Value;\r
+ }\r
+ else\r
+ {\r
+ _resultSet[col] = Marshal.ReadByte(internalBuffer) != 0;\r
+ }\r
+ } \r
+ return _resultSet[col];\r
+ }\r
+ #endregion\r
+\r
+ #region GetGuid\r
+ ///\r
+ /// GetDateTime method\r
+ /// \r
+ public Guid GetGuid(int col)\r
+ {\r
+ return (Guid)GetGuidInternal(col);\r
+ }\r
+ internal object GetGuidInternal(int col)\r
+ {\r
+ if((col < 0) || (col >= fieldCount))\r
+ {\r
+ throw new IndexOutOfRangeException("col");\r
+ }\r
+ if(!hasData)\r
+ {\r
+ throw new InvalidOperationException("No data");\r
+ }\r
+ if(_resultSet == null)\r
+ {\r
+ _resultSet = new object[fieldCount];\r
+ }\r
+ if(_resultSet[col] == null)\r
+ {\r
+ int len;\r
+ short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_GUID, internalBuffer, internalBufferSize, out len);\r
+ if(len == DB2Constants.SQL_NULL_DATA)\r
+ {\r
+ _resultSet[col] = DBNull.Value;\r
+ }\r
+ else\r
+ {\r
+ _resultSet[col] = Marshal.PtrToStructure(internalBuffer, typeof(Guid)); \r
+ }\r
+ } \r
+ return _resultSet[col];\r
+ }\r
+\r
+ #endregion\r
+\r
+ #region GetByte\r
+ ///\r
+ ///GetByte\r
+ ///\r
+ public Byte GetByte(int col)\r
+ {\r
+ return (Byte)GetByteInternal(col);\r
+ }\r
+ internal object GetByteInternal(int col)\r
+ {\r
+ if((col < 0) || (col >= fieldCount))\r
+ {\r
+ throw new IndexOutOfRangeException("col");\r
+ }\r
+ if(!hasData)\r
+ {\r
+ throw new InvalidOperationException("No data");\r
+ }\r
+ if(_resultSet == null)\r
+ {\r
+ _resultSet = new object[fieldCount];\r
+ }\r
+ if(_resultSet[col] == null)\r
+ {\r
+ int len;\r
+ short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_UTINYINT, internalBuffer, 10, out len);\r
+ if(len == DB2Constants.SQL_NULL_DATA)\r
+ {\r
+ _resultSet[col] = DBNull.Value;\r
+ }\r
+ else\r
+ {\r
+ _resultSet[col] = Marshal.ReadByte(internalBuffer);\r
+ }\r
+ } \r
+ return _resultSet[col];\r
+ }\r
+ #endregion\r
+\r
+ #region GetChar\r
+ ///\r
+ ///GetChar, return column as a char\r
+ ///\r
+ public Char GetChar(int col)\r
+ {\r
+ return (Char)GetCharInternal(col);\r
+ }\r
+ internal object GetCharInternal(int col)\r
+ {\r
+ if((col < 0) || (col >= fieldCount))\r
+ {\r
+ throw new IndexOutOfRangeException("col");\r
+ }\r
+ if(!hasData)\r
+ {\r
+ throw new InvalidOperationException("No data");\r
+ }\r
+ if(_resultSet == null)\r
+ {\r
+ _resultSet = new object[fieldCount];\r
+ }\r
+ if(_resultSet[col] == null)\r
+ {\r
+ int len;\r
+ short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_WCHAR, internalBuffer, 10, out len);\r
+ if(len == DB2Constants.SQL_NULL_DATA)\r
+ {\r
+ _resultSet[col] = DBNull.Value;\r
+ }\r
+ else\r
+ {\r
+ _resultSet[col] = Marshal.PtrToStructure(internalBuffer, typeof(char));\r
+ }\r
+ } \r
+ return _resultSet[col];\r
+ }\r
+ #endregion\r
+\r
+ #region GetData\r
+ ///\r
+ /// GetData method\r
+ /// \r
+ public IDataReader GetData(int col)\r
+ {\r
+ //Have to research this one, not quite sure what the docs mean\r
+ //DB2 does have some structured data types, is that what this is for?\r
+ throw new NotSupportedException();\r
+ }\r
+ #endregion\r
+\r
+ #region GetDataTypeName\r
+ ///\r
+ ///GetDataTypeName return the type of data\r
+ ///\r
+ public string GetDataTypeName(int col)\r
+ {\r
+ if(columnInfo == null)\r
+ {\r
+ GetColumnInfo();\r
+ }\r
+ switch(columnInfo[col].Sqltype)\r
+ {\r
+ case DB2Constants.SQL_INTEGER:\r
+ return "INTEGER";\r
+ case DB2Constants.SQL_SMALLINT:\r
+ return "SMALLINT";\r
+ case DB2Constants.SQL_BIGINT:\r
+ return "BIGINT";\r
+ case DB2Constants.SQL_DOUBLE:\r
+ return "DOUBLE";\r
+ case DB2Constants.SQL_REAL:\r
+ return "REAL";\r
+ case DB2Constants.SQL_DECIMAL:\r
+ return "DECIMAL";\r
+ case DB2Constants.SQL_DATETIME:\r
+ return "DATETIME";\r
+ case DB2Constants.SQL_TYPE_TIMESTAMP:\r
+ return "TIMESTAMP";\r
+ case DB2Constants.SQL_TYPE_DATE:\r
+ return "DATE";\r
+ case DB2Constants.SQL_TYPE_TIME:\r
+ return "TIME";\r
+ case DB2Constants.SQL_TYPE_CLOB:\r
+ return "CLOB";\r
+ case DB2Constants.SQL_CHAR:\r
+ return "CHAR";\r
+ case DB2Constants.SQL_VARCHAR:\r
+ return "VARCHAR";\r
+ case DB2Constants.SQL_TYPE_BLOB:\r
+ return "BLOB";\r
+ case DB2Constants.SQL_TYPE_BINARY:\r
+ return "BINARY";\r
+ case DB2Constants.SQL_LONGVARBINARY:\r
+ return "LONGVARBINARY";\r
+ case DB2Constants.SQL_VARBINARY:\r
+ return "VARBINARY";\r
+ }\r
+ throw new NotImplementedException("Unknown SQL type " + columnInfo[col].Sqltype);\r
+ }\r
+ #endregion\r
+\r
+ #region GetDateTime\r
+ ///\r
+ /// GetDateTime method\r
+ /// \r
+\r
+ public DateTime GetDateTime(int col)\r
+ {\r
+ return (DateTime)GetDateTimeInternal(col);\r
+ }\r
+ internal object GetDateTimeInternal(int col)\r
+ {\r
+ if((col < 0) || (col >= fieldCount))\r
+ {\r
+ throw new IndexOutOfRangeException("col");\r
+ }\r
+ if(!hasData)\r
+ {\r
+ throw new InvalidOperationException("No data");\r
+ }\r
+ if(_resultSet == null)\r
+ {\r
+ _resultSet = new object[fieldCount];\r
+ }\r
+ if(_resultSet[col] == null)\r
+ {\r
+ int len;\r
+ short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_TYPE_TIMESTAMP, internalBuffer, internalBufferSize, out len);\r
+ if(len == DB2Constants.SQL_NULL_DATA)\r
+ {\r
+ _resultSet[col] = DBNull.Value;\r
+ }\r
+ else\r
+ {\r
+ DateTime ret = new DateTime(\r
+ Marshal.ReadInt16(internalBuffer, 0), // year\r
+ Marshal.ReadInt16(internalBuffer, 2), // month\r
+ Marshal.ReadInt16(internalBuffer, 4), // day\r
+ Marshal.ReadInt16(internalBuffer, 6), // hour\r
+ Marshal.ReadInt16(internalBuffer, 8), // minute\r
+ Marshal.ReadInt16(internalBuffer, 10));// second\r
+ _resultSet[col] = ret.AddTicks(Marshal.ReadInt32(internalBuffer, 12) / 100); // nanoseconds \r
+ }\r
+ } \r
+ return _resultSet[col];\r
+ }\r
+ #endregion\r
+\r
+ #region GetDate\r
+ ///\r
+ /// GetDate method\r
+ /// \r
+ public DateTime GetDate(int col)\r
+ {\r
+ return (DateTime)GetDateInternal(col);\r
+ }\r
+ internal object GetDateInternal(int col)\r
+ {\r
+ if((col < 0) || (col >= fieldCount))\r
+ {\r
+ throw new IndexOutOfRangeException("col");\r
+ }\r
+ if(!hasData)\r
+ {\r
+ throw new InvalidOperationException("No data");\r
+ }\r
+ if(_resultSet == null)\r
+ {\r
+ _resultSet = new object[fieldCount];\r
+ }\r
+ if(_resultSet[col] == null)\r
+ {\r
+ int len;\r
+ short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_TYPE_DATE, internalBuffer, internalBufferSize, out len);\r
+ if(len == DB2Constants.SQL_NULL_DATA)\r
+ {\r
+ _resultSet[col] = DBNull.Value;\r
+ }\r
+ else\r
+ {\r
+ _resultSet[col] = new DateTime(\r
+ Marshal.ReadInt16(internalBuffer, 0), // year\r
+ Marshal.ReadInt16(internalBuffer, 2), // month\r
+ Marshal.ReadInt16(internalBuffer, 4)); // day\r
+ }\r
+ } \r
+ return _resultSet[col];\r
+ }\r
+\r
+ #endregion\r
+\r
+ #region GetTime\r
+ ///\r
+ /// GetTime method\r
+ /// \r
+ public TimeSpan GetTimeSpan(int col)\r
+ {\r
+ return (TimeSpan)GetTimeInternal(col);\r
+ }\r
+ public TimeSpan GetTime(int col)\r
+ {\r
+ return (TimeSpan)GetTimeInternal(col);\r
+ }\r
+ internal object GetTimeInternal(int col)\r
+ {\r
+ if((col < 0) || (col >= fieldCount))\r
+ {\r
+ throw new IndexOutOfRangeException("col");\r
+ }\r
+ if(!hasData)\r
+ {\r
+ throw new InvalidOperationException("No data");\r
+ }\r
+ if(_resultSet == null)\r
+ {\r
+ _resultSet = new object[fieldCount];\r
+ }\r
+ if(_resultSet[col] == null)\r
+ {\r
+ int len;\r
+ short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_TYPE_TIME, internalBuffer, internalBufferSize, out len);\r
+ if(len == DB2Constants.SQL_NULL_DATA)\r
+ {\r
+ _resultSet[col] = DBNull.Value;\r
+ }\r
+ else\r
+ {\r
+ _resultSet[col] = new TimeSpan(\r
+ Marshal.ReadInt16(internalBuffer, 0), // Hour\r
+ Marshal.ReadInt16(internalBuffer, 2), // Minute\r
+ Marshal.ReadInt16(internalBuffer, 4)); // Second\r
+ }\r
+ } \r
+ return _resultSet[col];\r
+ }\r
+\r
+ #endregion\r
+\r
+\r
+ #region GetDecimal\r
+ ///\r
+ ///GetDecimal method\r
+ ///\r
+\r
+ public Decimal GetDecimal(int col)\r
+ {\r
+ return (Decimal)GetDecimalInternal(col);\r
+ }\r
+ internal object GetDecimalInternal(int col)\r
+ {\r
+ object tmp = GetStringInternal(col);\r
+ if(tmp is string)\r
+ {\r
+ _resultSet[col] = decimal.Parse(((string)_resultSet[col]).Replace(',','.'), // sometimes we get a '.' and sometimes we get a ','\r
+ System.Globalization.CultureInfo.InvariantCulture);\r
+ }\r
+ // if((col < 0) || (col >= fieldCount)) // only works on windows UDB DB2 V8?\r
+ // {\r
+ // throw new IndexOutOfRangeException("col");\r
+ // }\r
+ // if(!hasData)\r
+ // {\r
+ // throw new InvalidOperationException("No data");\r
+ // }\r
+ // if(_resultSet == null)\r
+ // {\r
+ // _resultSet = new object[fieldCount];\r
+ // }\r
+ // if(_resultSet[col] == null)\r
+ // {\r
+ // int len;\r
+ // short sqlRet = Db2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)Db2Constants.SQL_C_DECIMAL_OLEDB, internalBuffer, internalBufferSize, out len);\r
+ // if(len == Db2Constants.SQL_NULL_DATA)\r
+ // {\r
+ // _resultSet[col] = DBNull.Value;\r
+ // }\r
+ // else\r
+ // {\r
+ // _resultSet[col] = Marshal.PtrToStructure(internalBuffer, typeof(decimal));\r
+ // }\r
+ // } \r
+ return _resultSet[col];\r
+ }\r
+ #endregion\r
+\r
+ #region GetDouble \r
+ ///\r
+ /// GetDouble \r
+ /// \r
+ public Double GetDouble(int col)\r
+ {\r
+ return (Double)GetDoubleInternal(col);\r
+ }\r
+ internal object GetDoubleInternal(int col)\r
+ {\r
+ if((col < 0) || (col >= fieldCount))\r
+ {\r
+ throw new IndexOutOfRangeException("col");\r
+ }\r
+ if(!hasData)\r
+ {\r
+ throw new InvalidOperationException("No data");\r
+ }\r
+ if(_resultSet == null)\r
+ {\r
+ _resultSet = new object[fieldCount];\r
+ }\r
+ if(_resultSet[col] == null)\r
+ {\r
+ int len;\r
+ short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_DOUBLE, internalBuffer, internalBufferSize, out len);\r
+ if(len == DB2Constants.SQL_NULL_DATA)\r
+ {\r
+ _resultSet[col] = DBNull.Value;\r
+ }\r
+ else\r
+ {\r
+ _resultSet[col] = Marshal.PtrToStructure(internalBuffer, typeof(double));\r
+ }\r
+ } \r
+ return _resultSet[col];\r
+ }\r
+ #endregion\r
+\r
+ #region GetFieldType\r
+ ///\r
+ /// Type GetFieldType\r
+ ///\r
+ public Type GetFieldType(int col)\r
+ {\r
+ if(columnInfo == null)\r
+ {\r
+ GetColumnInfo();\r
+ }\r
+ return GetManagedType(columnInfo[col].Sqltype);\r
+ }\r
+ #endregion\r
+\r
+ #region GetFloat\r
+ ///\r
+ /// GetFloat\r
+ /// \r
+ public float GetFloat(int col)\r
+ {\r
+ return (float)GetFloatInternal(col);\r
+ }\r
+ internal object GetFloatInternal(int col)\r
+ {\r
+ if((col < 0) || (col >= fieldCount))\r
+ {\r
+ throw new IndexOutOfRangeException("col");\r
+ }\r
+ if(!hasData)\r
+ {\r
+ throw new InvalidOperationException("No data");\r
+ }\r
+ if(_resultSet == null)\r
+ {\r
+ _resultSet = new object[fieldCount];\r
+ }\r
+ if(_resultSet[col] == null)\r
+ {\r
+ int len;\r
+ short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_TYPE_REAL, internalBuffer, internalBufferSize, out len);\r
+ if(len == DB2Constants.SQL_NULL_DATA)\r
+ {\r
+ _resultSet[col] = DBNull.Value;\r
+ }\r
+ else\r
+ {\r
+ _resultSet[col] = Marshal.PtrToStructure(internalBuffer, typeof(float));\r
+ }\r
+ } \r
+ return _resultSet[col];\r
+ }\r
+ #endregion\r
+\r
+ #region The GetInt?? series\r
+ ///\r
+ ///GetInt16\r
+ ///\r
+ public short GetInt16(int col)\r
+ {\r
+ return (short)GetInt16Internal(col);\r
+ }\r
+\r
+ internal object GetInt16Internal(int col)\r
+ {\r
+ if((col < 0) || (col >= fieldCount))\r
+ {\r
+ throw new IndexOutOfRangeException("col");\r
+ }\r
+ if(!hasData)\r
+ {\r
+ throw new InvalidOperationException("No data");\r
+ }\r
+ if(_resultSet == null)\r
+ {\r
+ _resultSet = new object[fieldCount];\r
+ }\r
+ if(_resultSet[col] == null)\r
+ {\r
+ int len;\r
+ short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_SSHORT, internalBuffer, internalBufferSize, out len);\r
+ if(len == DB2Constants.SQL_NULL_DATA)\r
+ {\r
+ _resultSet[col] = DBNull.Value;\r
+ }\r
+ else\r
+ {\r
+ _resultSet[col] = Marshal.PtrToStructure(internalBuffer, typeof(short));\r
+ }\r
+ } \r
+ return _resultSet[col];\r
+ }\r
+ ///\r
+ ///GetInt32\r
+ ///\r
+ public int GetInt32(int col)\r
+ {\r
+ return (int)GetInt32Internal(col);\r
+ }\r
+\r
+ internal object GetInt32Internal(int col)\r
+ {\r
+ if((col < 0) || (col >= fieldCount))\r
+ {\r
+ throw new IndexOutOfRangeException("col");\r
+ }\r
+ if(!hasData)\r
+ {\r
+ throw new InvalidOperationException("No data");\r
+ }\r
+ if(_resultSet == null)\r
+ {\r
+ _resultSet = new object[fieldCount];\r
+ }\r
+ if(_resultSet[col] == null)\r
+ {\r
+ int len;\r
+ short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_SLONG, internalBuffer, internalBufferSize, out len);\r
+ if(len == DB2Constants.SQL_NULL_DATA)\r
+ {\r
+ _resultSet[col] = DBNull.Value;\r
+ }\r
+ else\r
+ {\r
+ _resultSet[col] = Marshal.PtrToStructure(internalBuffer, typeof(int));\r
+ }\r
+ } \r
+ return _resultSet[col];\r
+ }\r
+\r
+ ///\r
+ ///GetInt64\r
+ ///\r
+ public long GetInt64(int col)\r
+ {\r
+ return (long)GetInt64Internal(col);\r
+ }\r
+\r
+ internal object GetInt64Internal(int col)\r
+ {\r
+ if((col < 0) || (col >= fieldCount))\r
+ {\r
+ throw new IndexOutOfRangeException("col");\r
+ }\r
+ if(!hasData)\r
+ {\r
+ throw new InvalidOperationException("No data");\r
+ }\r
+ if(_resultSet == null)\r
+ {\r
+ _resultSet = new object[fieldCount];\r
+ }\r
+ if(_resultSet[col] == null)\r
+ {\r
+ int len;\r
+ short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_SBIGINT, internalBuffer, internalBufferSize, out len);\r
+ if(len == DB2Constants.SQL_NULL_DATA)\r
+ {\r
+ _resultSet[col] = DBNull.Value;\r
+ }\r
+ else\r
+ {\r
+ _resultSet[col] = Marshal.PtrToStructure(internalBuffer, typeof(long));\r
+ }\r
+ } \r
+ return _resultSet[col];\r
+ }\r
+\r
+ #endregion\r
+\r
+ #region GetName\r
+ ///\r
+ ///GetName, returns the name of the field\r
+ ///\r
+ public string GetName(int col)\r
+ {\r
+ if(columnInfo == null)\r
+ {\r
+ GetColumnInfo();\r
+ }\r
+ return columnInfo[col].Colname;\r
+ }\r
+ #endregion\r
+\r
+ #region GetOrdinal\r
+ ///\r
+ /// GetOrdinal, return the index of the named column\r
+ /// \r
+ public int GetOrdinal(string name)\r
+ {\r
+ if(columnInfo == null)\r
+ {\r
+ GetColumnInfo();\r
+ }\r
+ object ordinal = columnsNames[name.ToUpper()];\r
+ if(ordinal == null)\r
+ {\r
+ throw new IndexOutOfRangeException("name");\r
+ }\r
+ return (int)ordinal;\r
+ }\r
+ #endregion\r
+\r
+ #region GetString\r
+ ///\r
+ /// GetString returns a string\r
+ /// \r
+ public string GetString(int col)\r
+ {\r
+ return (string)GetStringInternal(col);\r
+ }\r
+\r
+ public object GetStringInternal(int col)\r
+ {\r
+ if((col < 0) || (col >= fieldCount))\r
+ {\r
+ throw new IndexOutOfRangeException("col");\r
+ }\r
+ if(!hasData)\r
+ {\r
+ throw new InvalidOperationException("No data");\r
+ }\r
+ if(_resultSet == null)\r
+ {\r
+ _resultSet = new object[fieldCount];\r
+ }\r
+ if(_resultSet[col] == null)\r
+ {\r
+ int length;\r
+ short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_WCHAR, (StringBuilder)null, 0, out length);\r
+ if(length == DB2Constants.SQL_NULL_DATA)\r
+ {\r
+ _resultSet[col] = DBNull.Value;\r
+ }\r
+ else\r
+ {\r
+ IntPtr mem = Marshal.AllocHGlobal(length + 2);\r
+ sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_WCHAR, mem, length + 2, out length);\r
+ _resultSet[col] = Marshal.PtrToStringUni(mem);\r
+ Marshal.FreeHGlobal(mem);\r
+ }\r
+ } \r
+ return _resultSet[col];\r
+ }\r
+ #endregion\r
+\r
+ #region GetValue\r
+ ///\r
+ /// GetVCalue, returns an object\r
+ /// \r
+ public object GetValue(int col)\r
+ {\r
+ return this[col];\r
+ }\r
+ #endregion\r
+\r
+ #region GetValues\r
+ ///\r
+ /// GetValues returns all columns in the row through the argument, and the number of columns in the return value\r
+ /// \r
+ public int GetValues(object[] values)\r
+ {\r
+ int count = Math.Min(fieldCount, values.Length);\r
+\r
+ for (int i = 0; i < count; i++)\r
+ {\r
+ values[i] = this[i];\r
+ \r
+ }\r
+ \r
+ return count;\r
+ }\r
+ #endregion\r
+\r
+ #region IsDBNull\r
+ ///\r
+ /// IsDBNull Is the column null\r
+ /// \r
+ public bool IsDBNull(int col)\r
+ {\r
+ //Proper implementation once I get the SQLDescribe/SQLBind/SQLFetch stuff in place\r
+ return Convert.IsDBNull(this[col]);\r
+ }\r
+ #endregion\r
+\r
+ #endregion ///For IDataRecord\r
+\r
+ #region private methods\r
+ \r
+ private DataTable BuildNewSchemaTable()\r
+ {\r
+ DataTable schemaTable = new DataTable("SchemaTable");\r
+\r
+ schemaTable.Columns.Add(new DataColumn("ColumnName", typeof(string)));\r
+ schemaTable.Columns.Add(new DataColumn("ColumnOrdinal", typeof(int)));\r
+ schemaTable.Columns.Add(new DataColumn("ColumnSize", typeof(int)));\r
+ schemaTable.Columns.Add(new DataColumn("NumericPrecision", typeof(short)));\r
+ schemaTable.Columns.Add(new DataColumn("NumericScale", typeof(short)));\r
+ schemaTable.Columns.Add(new DataColumn("DataType", typeof(System.Type)));\r
+ schemaTable.Columns.Add(new DataColumn("ProviderType", typeof(int)));\r
+ schemaTable.Columns.Add(new DataColumn("IsLong", typeof(bool)));\r
+ schemaTable.Columns.Add(new DataColumn("AllowDBNull", typeof(bool)));\r
+ schemaTable.Columns.Add(new DataColumn("IsReadOnly", typeof(bool)));\r
+ schemaTable.Columns.Add(new DataColumn("IsRowVersion", typeof(bool)));\r
+ schemaTable.Columns.Add(new DataColumn("IsUnique", typeof(bool)));\r
+ schemaTable.Columns.Add(new DataColumn("IsKey", typeof(bool)));\r
+ schemaTable.Columns.Add(new DataColumn("IsKeyColumn", typeof(bool)));\r
+ schemaTable.Columns.Add(new DataColumn("IsAutoIncrement", typeof(bool)));\r
+ schemaTable.Columns.Add(new DataColumn("BaseSchemaName", typeof(string)));\r
+ schemaTable.Columns.Add(new DataColumn("BaseCatalogName", typeof(string)));\r
+ schemaTable.Columns.Add(new DataColumn("BaseTableName", typeof(string)));\r
+ schemaTable.Columns.Add(new DataColumn("BaseColumnName", typeof(string)));\r
+\r
+ return schemaTable;\r
+ }\r
+ #endregion\r
+ \r
+ private void InitMem(int memSize, ref IntPtr ptr){\r
+ if (ptr.ToInt32() == 0){\r
+ unsafe{\r
+ fixed(byte* arr = new byte[memSize]){\r
+ ptr = new IntPtr(arr); \r
+ }\r
+ }\r
+ } \r
+ }\r
+ \r
+ private Type GetManagedType(int sql_type)\r
+ {\r
+ switch(sql_type)\r
+ {\r
+ case DB2Constants.SQL_INTEGER:\r
+ return typeof(int);\r
+ case DB2Constants.SQL_SMALLINT:\r
+ return typeof(short);\r
+ case DB2Constants.SQL_BIGINT:\r
+ return typeof(long);\r
+ case DB2Constants.SQL_DOUBLE:\r
+ return typeof(double);\r
+ case DB2Constants.SQL_DECIMAL:\r
+ return typeof(decimal);\r
+ case DB2Constants.SQL_DATETIME:\r
+ case DB2Constants.SQL_TYPE_DATE:\r
+ case DB2Constants.SQL_TYPE_TIMESTAMP:\r
+ return typeof(DateTime);\r
+ case DB2Constants.SQL_TYPE_TIME:\r
+ return typeof(TimeSpan);\r
+ case DB2Constants.SQL_CHAR:\r
+ case DB2Constants.SQL_VARCHAR:\r
+ case DB2Constants.SQL_TYPE_CLOB:\r
+ return typeof(string);\r
+ case DB2Constants.SQL_TYPE_BLOB:\r
+ case DB2Constants.SQL_TYPE_BINARY:\r
+ case DB2Constants.SQL_LONGVARBINARY:\r
+ case DB2Constants.SQL_VARBINARY:\r
+ return typeof(byte[]);\r
+ }\r
+ throw new NotImplementedException("Unknown SQL type " + sql_type);\r
+ }\r
+ \r
+ private bool IsLong(short sql_type)\r
+ {\r
+ switch(sql_type)\r
+ {\r
+ case DB2Constants.SQL_TYPE_CLOB:\r
+ case DB2Constants.SQL_TYPE_BLOB:\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+ private object GetBlobDataInternal(int col)\r
+ {\r
+ if((col < 0) || (col >= fieldCount))\r
+ {\r
+ throw new IndexOutOfRangeException("col");\r
+ }\r
+ if(!hasData)\r
+ {\r
+ throw new InvalidOperationException("No data");\r
+ }\r
+ if(_resultSet == null)\r
+ {\r
+ _resultSet = new object[fieldCount];\r
+ }\r
+ if(_resultSet[col] == null)\r
+ {\r
+ int length;\r
+ short sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_TYPE_BINARY, (StringBuilder)null, 0, out length);\r
+ if(length == DB2Constants.SQL_NULL_DATA)\r
+ {\r
+ _resultSet[col] = DBNull.Value;\r
+ }\r
+ else\r
+ {\r
+ byte[] result = new byte[length];\r
+ sqlRet = DB2CLIWrapper.SQLGetData(this.hwndStmt, (short)(col + 1), (short)DB2Constants.SQL_C_TYPE_BINARY, result, length, out length);\r
+ _resultSet[col] = result;\r
+ }\r
+ } \r
+ return _resultSet[col];\r
+ }\r
+ }\r
+\r
+}\r
+#endregion\r