// Dynamically load column descriptions as needed. private OdbcColumn GetColumn(int ordinal) { if (cols [ordinal] == null) { short bufsize = 255; byte [] colname_buffer = new byte [bufsize]; string colname; short colname_size = 0; uint ColSize = 0; short DecDigits = 0, Nullable = 0, dt = 0; OdbcReturn ret = libodbc.SQLDescribeCol(hstmt, Convert.ToUInt16(ordinal + 1), colname_buffer, bufsize, ref colname_size, ref dt, ref ColSize, ref DecDigits, ref Nullable); if ((ret != OdbcReturn.Success) && (ret != OdbcReturn.SuccessWithInfo)) { throw Connection.CreateOdbcException(OdbcHandleType.Stmt, hstmt); } colname = RemoveTrailingNullChar(Encoding.Unicode.GetString(colname_buffer)); OdbcColumn c = new OdbcColumn(colname, (SQL_TYPE)dt); c.AllowDBNull = (Nullable != 0); c.Digits = DecDigits; if (c.IsVariableSizeType) { c.MaxLength = (int)ColSize; } cols [ordinal] = c; } return(cols [ordinal]); }
// Dynamically load column descriptions as needed. private OdbcColumn GetColumn(int ordinal) { if (cols [ordinal] == null) { short bufsize = 255; byte [] colname_buffer = new byte [bufsize]; string colname; short colname_size = 0; uint ColSize = 0; short DecDigits = 0, Nullable = 0, dt = 0; OdbcReturn ret = libodbc.SQLDescribeCol(hstmt, Convert.ToUInt16(ordinal + 1), colname_buffer, bufsize, ref colname_size, ref dt, ref ColSize, ref DecDigits, ref Nullable); if ((ret != OdbcReturn.Success) && (ret != OdbcReturn.SuccessWithInfo)) { throw new OdbcException(new OdbcError("SQLDescribeCol", OdbcHandleType.Stmt, hstmt)); } colname = System.Text.Encoding.Default.GetString(colname_buffer); colname = colname.Replace((char)0, ' ').Trim(); OdbcColumn c = new OdbcColumn(colname, (SQL_TYPE)dt); c.AllowDBNull = (Nullable != 0); c.Digits = DecDigits; if (c.IsVariableSizeType) { c.MaxLength = (int)ColSize; } cols [ordinal] = c; } return(cols [ordinal]); }
// Dynamically load column descriptions as needed. private OdbcColumn GetColumn (int ordinal) { if (cols [ordinal] == null) { short bufsize = 255; byte [] colname_buffer = new byte [bufsize]; string colname; short colname_size = 0; uint ColSize = 0; short DecDigits = 0, Nullable = 0, dt = 0; OdbcReturn ret = libodbc.SQLDescribeCol (hstmt, Convert.ToUInt16 (ordinal + 1), colname_buffer, bufsize, ref colname_size, ref dt, ref ColSize, ref DecDigits, ref Nullable); if ((ret != OdbcReturn.Success) && (ret != OdbcReturn.SuccessWithInfo)) throw Connection.CreateOdbcException (OdbcHandleType.Stmt, hstmt); colname = RemoveTrailingNullChar (Encoding.Unicode.GetString (colname_buffer)); OdbcColumn c = new OdbcColumn (colname, (SQL_TYPE) dt); c.AllowDBNull = (Nullable != 0); c.Digits = DecDigits; if (c.IsVariableSizeType) c.MaxLength = (int) ColSize; cols [ordinal] = c; } return cols [ordinal]; }
object GetValue(int i) { if (IsClosed) { throw new InvalidOperationException("The reader is closed."); } if (currentRow == -1) { throw new InvalidOperationException("No data available."); } if (i > cols.Length - 1 || i < 0) { throw new IndexOutOfRangeException(); } OdbcReturn ret; int outsize = 0, bufsize; byte[] buffer; OdbcColumn col = GetColumn(i); object DataValue = null; ushort ColIndex = Convert.ToUInt16(i + 1); // Check cached values if (col.Value == null) { // odbc help file // mk:@MSITStore:C:\program%20files\Microsoft%20Data%20Access%20SDK\Docs\odbc.chm::/htm/odbcc_data_types.htm switch (col.OdbcType) { case OdbcType.Bit: short bit_data = 0; ret = libodbc.SQLGetData(hstmt, ColIndex, col.SqlCType, ref bit_data, 0, ref outsize); if (outsize != (int)OdbcLengthIndicator.NullData) { DataValue = bit_data == 0 ? "False" : "True"; } break; case OdbcType.Numeric: case OdbcType.Decimal: bufsize = 50; buffer = new byte [bufsize]; // According to sqlext.h, use SQL_CHAR for decimal. // FIXME : use Numeric. ret = libodbc.SQLGetData(hstmt, ColIndex, SQL_C_TYPE.CHAR, buffer, bufsize, ref outsize); if (outsize != -1) { byte [] temp = new byte [outsize]; for (int j = 0; j < outsize; j++) { temp [j] = buffer [j]; } DataValue = Decimal.Parse(Encoding.Default.GetString(temp), CultureInfo.InvariantCulture); } break; case OdbcType.TinyInt: short short_data = 0; ret = libodbc.SQLGetData(hstmt, ColIndex, col.SqlCType, ref short_data, 0, ref outsize); DataValue = Convert.ToByte(short_data); break; case OdbcType.Int: int int_data = 0; ret = libodbc.SQLGetData(hstmt, ColIndex, col.SqlCType, ref int_data, 0, ref outsize); DataValue = int_data; break; case OdbcType.SmallInt: short sint_data = 0; ret = libodbc.SQLGetData(hstmt, ColIndex, col.SqlCType, ref sint_data, 0, ref outsize); DataValue = sint_data; break; case OdbcType.BigInt: long long_data = 0; ret = libodbc.SQLGetData(hstmt, ColIndex, col.SqlCType, ref long_data, 0, ref outsize); DataValue = long_data; break; case OdbcType.NChar: bufsize = 255; buffer = new byte [bufsize]; ret = libodbc.SQLGetData(hstmt, ColIndex, SQL_C_TYPE.WCHAR, buffer, bufsize, ref outsize); if (outsize != (int)OdbcLengthIndicator.NullData) { if (!(ret == OdbcReturn.SuccessWithInfo && outsize == (int)OdbcLengthIndicator.NoTotal)) { DataValue = Encoding.Unicode.GetString(buffer, 0, outsize); } } break; case OdbcType.NText: case OdbcType.NVarChar: bufsize = (col.MaxLength < 127 ? (col.MaxLength * 2 + 1) : 255); buffer = new byte[bufsize]; // According to sqlext.h, use SQL_CHAR for both char and varchar StringBuilder sb = new StringBuilder(); char[] charBuffer = new char[bufsize]; Decoder unicodeDecoder = Encoding.Unicode.GetDecoder(); do { ret = libodbc.SQLGetData(hstmt, ColIndex, col.SqlCType, buffer, bufsize, ref outsize); if (ret == OdbcReturn.Error) { break; } // Fix for strance ODBC drivers (like psqlODBC) if (ret == OdbcReturn.Success && outsize == -1) { ret = OdbcReturn.NoData; } if (ret == OdbcReturn.Success || ret == OdbcReturn.SuccessWithInfo) { if (outsize >= bufsize || outsize == (int)OdbcLengthIndicator.NoTotal) { outsize = bufsize; } int charCount = unicodeDecoder.GetChars(buffer, 0, outsize, charBuffer, 0); string strValue = new String(charBuffer, 0, charCount); sb.Append(RemoveTrailingNullChar(strValue)); } } while (ret != OdbcReturn.NoData); DataValue = sb.ToString(); charBuffer = null; break; case OdbcType.Text: case OdbcType.VarChar: bufsize = (col.MaxLength < 255 ? (col.MaxLength + 1) : 255); buffer = new byte[bufsize]; // According to sqlext.h, use SQL_CHAR for both char and varchar StringBuilder sb1 = new StringBuilder(); charBuffer = new char[bufsize]; Decoder defaultDecoder = Encoding.Default.GetDecoder(); do { ret = libodbc.SQLGetData(hstmt, ColIndex, col.SqlCType, buffer, bufsize, ref outsize); if (ret == OdbcReturn.Error) { break; } // Fix for strance ODBC drivers (like psqlODBC) if (ret == OdbcReturn.Success && outsize == -1) { ret = OdbcReturn.NoData; } if (ret == OdbcReturn.Success || ret == OdbcReturn.SuccessWithInfo) { if (outsize >= bufsize || outsize == (int)OdbcLengthIndicator.NoTotal) { outsize = bufsize - 1; } int charCount = defaultDecoder.GetChars(buffer, 0, outsize, charBuffer, 0); sb1.Append(charBuffer, 0, charCount); } } while (ret != OdbcReturn.NoData); DataValue = sb1.ToString(); break; case OdbcType.Real: float float_data = 0; ret = libodbc.SQLGetData(hstmt, ColIndex, col.SqlCType, ref float_data, 0, ref outsize); DataValue = float_data; break; case OdbcType.Double: double double_data = 0; ret = libodbc.SQLGetData(hstmt, ColIndex, col.SqlCType, ref double_data, 0, ref outsize); DataValue = double_data; break; case OdbcType.Timestamp: case OdbcType.DateTime: case OdbcType.Date: case OdbcType.Time: OdbcTimestamp ts_data = new OdbcTimestamp(); ret = libodbc.SQLGetData(hstmt, ColIndex, col.SqlCType, ref ts_data, 0, ref outsize); if (outsize != -1) // This means SQL_NULL_DATA { if (col.OdbcType == OdbcType.Time) { // libodbc returns value in first three fields for OdbcType.Time DataValue = new System.TimeSpan(ts_data.year, ts_data.month, ts_data.day); } else { DataValue = new DateTime(ts_data.year, ts_data.month, ts_data.day, ts_data.hour, ts_data.minute, ts_data.second); if (ts_data.fraction != 0) { DataValue = ((DateTime)DataValue).AddTicks((long)ts_data.fraction / 100); } } } break; case OdbcType.VarBinary: case OdbcType.Image: bufsize = (col.MaxLength < 255 && col.MaxLength > 0 ? col.MaxLength : 255); buffer = new byte [bufsize]; ArrayList al = new ArrayList(); //get the size of data to be returned. ret = libodbc.SQLGetData(hstmt, ColIndex, SQL_C_TYPE.BINARY, buffer, 0, ref outsize); if (outsize != (int)OdbcLengthIndicator.NullData) { do { ret = libodbc.SQLGetData(hstmt, ColIndex, SQL_C_TYPE.BINARY, buffer, bufsize, ref outsize); if (ret == OdbcReturn.Error) { break; } if (ret != OdbcReturn.NoData && outsize != -1) { if (outsize < bufsize) { byte [] tmparr = new byte [outsize]; Array.Copy(buffer, 0, tmparr, 0, outsize); al.AddRange(tmparr); } else { al.AddRange(buffer); } } else { break; } } while (ret != OdbcReturn.NoData); } DataValue = al.ToArray(typeof(byte)); break; case OdbcType.Binary: bufsize = col.MaxLength; buffer = new byte [bufsize]; GetBytes(i, 0, buffer, 0, bufsize); ret = OdbcReturn.Success; DataValue = buffer; break; default: bufsize = 255; buffer = new byte[bufsize]; ret = libodbc.SQLGetData(hstmt, ColIndex, SQL_C_TYPE.CHAR, buffer, bufsize, ref outsize); if (outsize != (int)OdbcLengthIndicator.NullData) { if (!(ret == OdbcReturn.SuccessWithInfo && outsize == (int)OdbcLengthIndicator.NoTotal)) { DataValue = Encoding.Default.GetString(buffer, 0, outsize); } } break; } if ((ret != OdbcReturn.Success) && (ret != OdbcReturn.SuccessWithInfo) && (ret != OdbcReturn.NoData)) { throw Connection.CreateOdbcException(OdbcHandleType.Stmt, hstmt); } if (outsize == -1) // This means SQL_NULL_DATA { col.Value = DBNull.Value; } else { col.Value = DataValue; } } return(col.Value); }
DataTable GetSchemaTable() { if (IsClosed) { throw new InvalidOperationException("The reader is closed."); } // FIXME : // * Map OdbcType to System.Type and assign to DataType. // This will eliminate the need for IsStringType in // OdbcColumn if (_dataTableSchema != null) { return(_dataTableSchema); } DataTable dataTableSchema = null; // Only Results from SQL SELECT Queries // get a DataTable for schema of the result // otherwise, DataTable is null reference if (cols.Length > 0) { dataTableSchema = new DataTable(); dataTableSchema.Columns.Add("ColumnName", typeof(string)); dataTableSchema.Columns.Add("ColumnOrdinal", typeof(int)); dataTableSchema.Columns.Add("ColumnSize", typeof(int)); dataTableSchema.Columns.Add("NumericPrecision", typeof(int)); dataTableSchema.Columns.Add("NumericScale", typeof(int)); dataTableSchema.Columns.Add("IsUnique", typeof(bool)); dataTableSchema.Columns.Add("IsKey", typeof(bool)); DataColumn dc = dataTableSchema.Columns["IsKey"]; dc.AllowDBNull = true; // IsKey can have a DBNull dataTableSchema.Columns.Add("BaseCatalogName", typeof(string)); dataTableSchema.Columns.Add("BaseColumnName", typeof(string)); dataTableSchema.Columns.Add("BaseSchemaName", typeof(string)); dataTableSchema.Columns.Add("BaseTableName", typeof(string)); dataTableSchema.Columns.Add("DataType", typeof(Type)); dataTableSchema.Columns.Add("AllowDBNull", typeof(bool)); dataTableSchema.Columns.Add("ProviderType", typeof(int)); dataTableSchema.Columns.Add("IsAliased", typeof(bool)); dataTableSchema.Columns.Add("IsExpression", typeof(bool)); dataTableSchema.Columns.Add("IsIdentity", typeof(bool)); dataTableSchema.Columns.Add("IsAutoIncrement", typeof(bool)); dataTableSchema.Columns.Add("IsRowVersion", typeof(bool)); dataTableSchema.Columns.Add("IsHidden", typeof(bool)); dataTableSchema.Columns.Add("IsLong", typeof(bool)); dataTableSchema.Columns.Add("IsReadOnly", typeof(bool)); DataRow schemaRow; for (int i = 0; i < cols.Length; i += 1) { OdbcColumn col = GetColumn(i); schemaRow = dataTableSchema.NewRow(); dataTableSchema.Rows.Add(schemaRow); schemaRow ["ColumnName"] = col.ColumnName; schemaRow ["ColumnOrdinal"] = i; schemaRow ["ColumnSize"] = col.MaxLength; schemaRow ["NumericPrecision"] = GetColumnAttribute(i + 1, FieldIdentifier.Precision); schemaRow ["NumericScale"] = GetColumnAttribute(i + 1, FieldIdentifier.Scale); schemaRow ["BaseTableName"] = GetColumnAttributeStr(i + 1, FieldIdentifier.TableName); schemaRow ["BaseSchemaName"] = GetColumnAttributeStr(i + 1, FieldIdentifier.SchemaName); schemaRow ["BaseCatalogName"] = GetColumnAttributeStr(i + 1, FieldIdentifier.CatelogName); schemaRow ["BaseColumnName"] = GetColumnAttributeStr(i + 1, FieldIdentifier.BaseColumnName); schemaRow ["DataType"] = col.DataType; schemaRow ["IsUnique"] = false; schemaRow ["IsKey"] = DBNull.Value; schemaRow ["AllowDBNull"] = GetColumnAttribute(i + 1, FieldIdentifier.Nullable) != libodbc.SQL_NO_NULLS; schemaRow ["ProviderType"] = (int)col.OdbcType; schemaRow ["IsAutoIncrement"] = GetColumnAttribute(i + 1, FieldIdentifier.AutoUniqueValue) == libodbc.SQL_TRUE; schemaRow ["IsExpression"] = schemaRow.IsNull("BaseTableName") || (string)schemaRow ["BaseTableName"] == String.Empty; schemaRow ["IsAliased"] = (string)schemaRow ["BaseColumnName"] != (string)schemaRow ["ColumnName"]; schemaRow ["IsReadOnly"] = ((bool)schemaRow ["IsExpression"] || GetColumnAttribute(i + 1, FieldIdentifier.Updatable) == libodbc.SQL_ATTR_READONLY); // FIXME: all of these schemaRow ["IsIdentity"] = false; schemaRow ["IsRowVersion"] = false; schemaRow ["IsHidden"] = false; schemaRow ["IsLong"] = false; // FIXME: according to Brian, // this does not work on MS .NET // however, we need it for Mono // for now // schemaRow.AcceptChanges(); } // set primary keys DataRow [] rows = dataTableSchema.Select("BaseTableName <> ''", "BaseCatalogName, BaseSchemaName, BaseTableName ASC"); string lastTableName = String.Empty, lastSchemaName = String.Empty, lastCatalogName = String.Empty; string [] keys = null; // assumed to be sorted. foreach (DataRow row in rows) { string tableName = (string)row ["BaseTableName"]; string schemaName = (string)row ["BaseSchemaName"]; string catalogName = (string)row ["BaseCatalogName"]; if (tableName != lastTableName || schemaName != lastSchemaName || catalogName != lastCatalogName) { keys = GetPrimaryKeys(catalogName, schemaName, tableName); } if (keys != null && Array.BinarySearch(keys, (string)row ["BaseColumnName"]) >= 0) { row ["IsKey"] = true; row ["IsUnique"] = true; row ["AllowDBNull"] = false; GetColumn(ColIndex((string)row ["ColumnName"])).AllowDBNull = false; } lastTableName = tableName; lastSchemaName = schemaName; lastCatalogName = catalogName; } dataTableSchema.AcceptChanges(); } return(_dataTableSchema = dataTableSchema); }
// Dynamically load column descriptions as needed. private OdbcColumn GetColumn(int ordinal) { if (cols[ordinal]==null) { short bufsize=255; byte[] colname_buffer=new byte[bufsize]; string colname; short colname_size=0; uint ColSize=0; short DecDigits=0, Nullable=0, dt=0; OdbcReturn ret=libodbc.SQLDescribeCol(hstmt, Convert.ToUInt16(ordinal+1), colname_buffer, bufsize, ref colname_size, ref dt, ref ColSize, ref DecDigits, ref Nullable); if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) throw new OdbcException(new OdbcError("SQLDescribeCol",OdbcHandleType.Stmt,hstmt)); colname=System.Text.Encoding.Default.GetString(colname_buffer); colname=colname.Replace((char) 0,' ').Trim(); OdbcColumn c=new OdbcColumn(colname, (SQL_TYPE) dt); c.AllowDBNull=(Nullable!=0); c.Digits=DecDigits; if (c.IsStringType) c.MaxLength=(int)ColSize; cols[ordinal]=c; } return cols[ordinal]; }