2 // System.Data.Odbc.OdbcDataReader
5 // Brian Ritchie (brianlritchie@hotmail.com)
6 // Daniel Morgan <danmorg@sc.rr.com>
7 // Sureshkumar T <tsureshkumar@novell.com> (2004)
9 // Copyright (C) Brian Ritchie, 2002
10 // Copyright (C) Daniel Morgan, 2002
14 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 using System.Collections;
37 using System.ComponentModel;
39 using System.Data.Common;
41 using System.Data.ProviderBase;
45 namespace System.Data.Odbc
48 public sealed class OdbcDataReader : DbDataReaderBase
50 public sealed class OdbcDataReader : MarshalByRefObject, IDataReader, IDisposable, IDataRecord, IEnumerable
55 private OdbcCommand command;
57 private int currentRow;
58 private OdbcColumn[] cols;
60 private int _recordsAffected = -1;
61 bool disposed = false;
62 private DataTable _dataTableSchema;
64 private CommandBehavior behavior;
71 internal OdbcDataReader (OdbcCommand command, CommandBehavior behavior)
76 this.command = command;
78 this.CommandBehavior=behavior;
83 // Init columns array;
85 libodbc.SQLNumResultCols(hstmt, ref colcount);
86 cols=new OdbcColumn[colcount];
90 internal OdbcDataReader (OdbcCommand command, CommandBehavior behavior,
91 int recordAffected) : this (command, behavior)
93 _recordsAffected = recordAffected;
102 private CommandBehavior CommandBehavior
104 get { return behavior; }
105 set { value = behavior; }
111 public override int VisibleFieldCount
113 get { throw new NotImplementedException (); }
117 protected override bool IsValidRow
119 get { throw new NotImplementedException (); }
129 return 0; // no nested selects supported
157 object this[string name] {
161 if (currentRow == -1)
162 throw new InvalidOperationException ();
164 pos = ColIndex(name);
167 throw new IndexOutOfRangeException ();
177 object this[int index] {
179 return (object) GetValue (index);
188 int RecordsAffected {
190 return _recordsAffected;
200 get { throw new NotImplementedException(); }
207 private int ColIndex(string colname)
210 foreach (OdbcColumn col in cols)
213 if (col.ColumnName == colname)
215 if (String.Compare (col.ColumnName, colname, true) == 0)
224 // Dynamically load column descriptions as needed.
225 private OdbcColumn GetColumn(int ordinal)
227 if (cols[ordinal]==null)
230 byte[] colname_buffer=new byte[bufsize];
232 short colname_size=0;
234 short DecDigits=0, Nullable=0, dt=0;
235 OdbcReturn ret=libodbc.SQLDescribeCol(hstmt, Convert.ToUInt16(ordinal+1),
236 colname_buffer, bufsize, ref colname_size, ref dt, ref ColSize,
237 ref DecDigits, ref Nullable);
238 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo))
239 throw new OdbcException(new OdbcError("SQLDescribeCol",OdbcHandleType.Stmt,hstmt));
240 colname=System.Text.Encoding.Default.GetString(colname_buffer);
241 colname=colname.Replace((char) 0,' ').Trim();
242 OdbcColumn c=new OdbcColumn(colname, (SQL_TYPE) dt);
243 c.AllowDBNull=(Nullable!=0);
246 c.MaxLength=(int)ColSize;
249 return cols[ordinal];
258 // FIXME : have to implement output parameter binding
262 this.command.FreeIfNotPrepared ();
264 if ((this.CommandBehavior & CommandBehavior.CloseConnection)==CommandBehavior.CloseConnection) {
265 this.command.Connection.Close();
271 this.Dispose (false);
278 bool GetBoolean (int ordinal)
280 return (bool) GetValue(ordinal);
287 byte GetByte (int ordinal)
289 return (byte) Convert.ToByte(GetValue(ordinal));
296 long GetBytes (int ordinal, long dataIndex, byte[] buffer, int bufferIndex, int length)
298 OdbcReturn ret = OdbcReturn.Error;
299 bool copyBuffer = false;
300 int returnVal = 0, outsize = 0;
301 byte [] tbuff = new byte [length+1];
303 length = buffer == null ? 0 : length;
304 ret=libodbc.SQLGetData (hstmt, (ushort) (ordinal+1), SQL_C_TYPE.BINARY, tbuff, length,
307 if (ret == OdbcReturn.NoData)
310 if ( (ret != OdbcReturn.Success) && (ret != OdbcReturn.SuccessWithInfo))
311 throw new OdbcException (new OdbcError ("SQLGetData", OdbcHandleType.Stmt, hstmt));
313 OdbcError odbcErr = null;
314 if ( (ret == OdbcReturn.SuccessWithInfo))
315 odbcErr = new OdbcError ("SQLGetData", OdbcHandleType.Stmt, hstmt);
318 return outsize; //if buffer is null,return length of the field
320 if (ret == OdbcReturn.SuccessWithInfo) {
321 if (outsize == (int) OdbcLengthIndicator.NoTotal)
323 else if (outsize == (int) OdbcLengthIndicator.NullData) {
327 string sqlstate = odbcErr.SQLState;
328 //SQLState: String Data, Right truncated
329 if (sqlstate != libodbc.SQLSTATE_RIGHT_TRUNC)
330 throw new OdbcException ( odbcErr);
334 copyBuffer = outsize == -1 ? false : true;
340 while (tbuff [i] != libodbc.C_NULL) {
341 buffer [bufferIndex + i] = tbuff [i];
354 char GetChar (int ordinal)
356 throw new NotImplementedException ();
364 long GetChars (int ordinal, long dataIndex, char[] buffer, int bufferIndex, int length)
366 throw new NotImplementedException ();
370 [EditorBrowsableAttribute (EditorBrowsableState.Never)]
375 IDataReader GetData (int ordinal)
377 throw new NotImplementedException ();
384 string GetDataTypeName (int index)
386 return GetColumn(index).OdbcType.ToString();
389 public DateTime GetDate(int ordinal) {
390 return GetDateTime(ordinal);
397 DateTime GetDateTime (int ordinal)
399 return (DateTime) GetValue(ordinal);
407 decimal GetDecimal (int ordinal)
409 throw new NotImplementedException ();
416 double GetDouble (int ordinal)
418 return (double) GetValue(ordinal);
425 Type GetFieldType (int index)
427 return GetColumn(index).DataType;
434 float GetFloat (int ordinal)
436 return (float) GetValue(ordinal);
444 Guid GetGuid (int ordinal)
446 throw new NotImplementedException ();
453 short GetInt16 (int ordinal)
455 return (short) GetValue(ordinal);
462 int GetInt32 (int ordinal)
464 return (int) GetValue(ordinal);
471 long GetInt64 (int ordinal)
473 return (long) GetValue(ordinal);
480 string GetName (int index)
482 return GetColumn(index).ColumnName;
489 int GetOrdinal (string name)
491 int i=ColIndex(name);
494 throw new IndexOutOfRangeException ();
504 DataTable GetSchemaTable()
507 // * Map OdbcType to System.Type and assign to DataType.
508 // This will eliminate the need for IsStringType in
511 if (_dataTableSchema != null)
512 return _dataTableSchema;
514 DataTable dataTableSchema = null;
515 // Only Results from SQL SELECT Queries
516 // get a DataTable for schema of the result
517 // otherwise, DataTable is null reference
520 dataTableSchema = new DataTable ();
522 dataTableSchema.Columns.Add ("ColumnName", typeof (string));
523 dataTableSchema.Columns.Add ("ColumnOrdinal", typeof (int));
524 dataTableSchema.Columns.Add ("ColumnSize", typeof (int));
525 dataTableSchema.Columns.Add ("NumericPrecision", typeof (int));
526 dataTableSchema.Columns.Add ("NumericScale", typeof (int));
527 dataTableSchema.Columns.Add ("IsUnique", typeof (bool));
528 dataTableSchema.Columns.Add ("IsKey", typeof (bool));
529 DataColumn dc = dataTableSchema.Columns["IsKey"];
530 dc.AllowDBNull = true; // IsKey can have a DBNull
531 dataTableSchema.Columns.Add ("BaseCatalogName", typeof (string));
532 dataTableSchema.Columns.Add ("BaseColumnName", typeof (string));
533 dataTableSchema.Columns.Add ("BaseSchemaName", typeof (string));
534 dataTableSchema.Columns.Add ("BaseTableName", typeof (string));
535 dataTableSchema.Columns.Add ("DataType", typeof(Type));
536 dataTableSchema.Columns.Add ("AllowDBNull", typeof (bool));
537 dataTableSchema.Columns.Add ("ProviderType", typeof (int));
538 dataTableSchema.Columns.Add ("IsAliased", typeof (bool));
539 dataTableSchema.Columns.Add ("IsExpression", typeof (bool));
540 dataTableSchema.Columns.Add ("IsIdentity", typeof (bool));
541 dataTableSchema.Columns.Add ("IsAutoIncrement", typeof (bool));
542 dataTableSchema.Columns.Add ("IsRowVersion", typeof (bool));
543 dataTableSchema.Columns.Add ("IsHidden", typeof (bool));
544 dataTableSchema.Columns.Add ("IsLong", typeof (bool));
545 dataTableSchema.Columns.Add ("IsReadOnly", typeof (bool));
549 for (int i = 0; i < cols.Length; i += 1 )
551 string baseTableName = String.Empty;
553 OdbcColumn col=GetColumn(i);
555 schemaRow = dataTableSchema.NewRow ();
556 dataTableSchema.Rows.Add (schemaRow);
558 schemaRow ["ColumnName"] = col.ColumnName;
559 schemaRow ["ColumnOrdinal"] = i;
560 schemaRow ["ColumnSize"] = col.MaxLength;
561 schemaRow ["NumericPrecision"] = GetColumnAttribute (i+1, FieldIdentifier.Precision);
562 schemaRow ["NumericScale"] = GetColumnAttribute (i+1, FieldIdentifier.Scale);
563 schemaRow ["BaseTableName"] = GetColumnAttributeStr (i+1, FieldIdentifier.TableName);
564 schemaRow ["BaseSchemaName"] = GetColumnAttributeStr (i+1, FieldIdentifier.SchemaName);
565 schemaRow ["BaseCatalogName"] = GetColumnAttributeStr (i+1, FieldIdentifier.CatelogName);
566 schemaRow ["BaseColumnName"] = GetColumnAttributeStr (i+1, FieldIdentifier.BaseColumnName);
567 schemaRow ["DataType"] = col.DataType;
568 schemaRow ["IsUnique"] = false;
569 schemaRow ["IsKey"] = DBNull.Value;
570 schemaRow ["AllowDBNull"] = GetColumnAttribute (i+1, FieldIdentifier.Nullable) != libodbc.SQL_NO_NULLS;
571 schemaRow ["ProviderType"] = (int) col.OdbcType;
572 schemaRow ["IsAutoIncrement"] = GetColumnAttribute (i+1, FieldIdentifier.AutoUniqueValue) == libodbc.SQL_TRUE;
573 schemaRow ["IsExpression"] = schemaRow.IsNull ("BaseTableName") || (string) schemaRow ["BaseTableName"] == String.Empty;
574 schemaRow ["IsAliased"] = (string) schemaRow ["BaseColumnName"] != (string) schemaRow ["ColumnName"];
575 schemaRow ["IsReadOnly"] = ((bool) schemaRow ["IsExpression"]
576 || GetColumnAttribute (i+1, FieldIdentifier.Updatable) == libodbc.SQL_ATTR_READONLY);
578 // FIXME: all of these
579 schemaRow ["IsIdentity"] = false;
580 schemaRow ["IsRowVersion"] = false;
581 schemaRow ["IsHidden"] = false;
582 schemaRow ["IsLong"] = false;
585 // FIXME: according to Brian,
586 // this does not work on MS .NET
587 // however, we need it for Mono
589 // schemaRow.AcceptChanges();
594 DataRow [] rows = dataTableSchema.Select ("BaseTableName <> ''",
595 "BaseCatalogName, BaseSchemaName, BaseTableName ASC");
597 string lastTableName = String.Empty,
598 lastSchemaName = String.Empty,
599 lastCatalogName = String.Empty;
600 string [] keys = null; // assumed to be sorted.
601 foreach (DataRow row in rows) {
602 string tableName = (string) row ["BaseTableName"];
603 string schemaName = (string) row ["BaseSchemaName"];
604 string catalogName = (string) row ["BaseCatalogName"];
606 if (tableName != lastTableName || schemaName != lastSchemaName
607 || catalogName != lastCatalogName)
608 keys = GetPrimaryKeys (catalogName, schemaName, tableName);
611 Array.BinarySearch (keys, (string) row ["BaseColumnName"]) >= 0) {
612 row ["IsKey"] = true;
613 row ["IsUnique"] = true;
614 row ["AllowDBNull"] = false;
615 GetColumn ( ColIndex ( (string) row ["ColumnName"])).AllowDBNull = false;
617 lastTableName = tableName;
618 lastSchemaName = schemaName;
619 lastCatalogName = catalogName;
621 dataTableSchema.AcceptChanges();
623 return (_dataTableSchema = dataTableSchema);
630 string GetString (int ordinal)
632 return (string) GetValue(ordinal);
636 public TimeSpan GetTime (int ordinal)
638 throw new NotImplementedException ();
645 object GetValue (int ordinal)
647 if (currentRow == -1)
648 throw new IndexOutOfRangeException ();
650 if (ordinal>cols.Length-1 || ordinal<0)
651 throw new IndexOutOfRangeException ();
654 int outsize=0, bufsize;
656 OdbcColumn col=GetColumn(ordinal);
657 object DataValue=null;
658 ushort ColIndex=Convert.ToUInt16(ordinal+1);
660 // Check cached values
661 if (col.Value==null) {
663 // mk:@MSITStore:C:\program%20files\Microsoft%20Data%20Access%20SDK\Docs\odbc.chm::/htm/odbcc_data_types.htm
664 switch (col.OdbcType) {
667 ret=libodbc.SQLGetData(hstmt, ColIndex, col.SqlCType, ref bit_data, 0, ref outsize);
668 if (outsize != (int) OdbcLengthIndicator.NullData)
669 DataValue = bit_data == 0 ? "False" : "True";
671 case OdbcType.Numeric:
672 case OdbcType.Decimal:
674 buffer=new byte[bufsize]; // According to sqlext.h, use SQL_CHAR for decimal.
675 // FIXME : use Numeric.
676 ret=libodbc.SQLGetData(hstmt, ColIndex, SQL_C_TYPE.CHAR, buffer, bufsize, ref outsize);
678 byte[] temp = new byte[outsize];
679 for (int i=0;i<outsize;i++)
681 DataValue=Decimal.Parse(System.Text.Encoding.Default.GetString(temp));
684 case OdbcType.TinyInt:
686 ret=libodbc.SQLGetData(hstmt, ColIndex, col.SqlCType, ref short_data, 0, ref outsize);
687 DataValue=System.Convert.ToByte(short_data);
691 ret=libodbc.SQLGetData(hstmt, ColIndex, col.SqlCType, ref int_data, 0, ref outsize);
695 case OdbcType.SmallInt:
697 ret=libodbc.SQLGetData(hstmt, ColIndex, col.SqlCType, ref sint_data, 0, ref outsize);
701 case OdbcType.BigInt:
703 ret=libodbc.SQLGetData(hstmt, ColIndex, col.SqlCType, ref long_data, 0, ref outsize);
707 case OdbcType.NVarChar:
708 bufsize=col.MaxLength*2+1; // Unicode is double byte
709 buffer=new byte[bufsize];
710 ret=libodbc.SQLGetData(hstmt, ColIndex, col.SqlCType, buffer, bufsize, ref outsize);
712 DataValue=System.Text.Encoding.Unicode.GetString(buffer,0,outsize);
715 case OdbcType.VarChar:
716 bufsize=col.MaxLength+1;
717 buffer=new byte[bufsize]; // According to sqlext.h, use SQL_CHAR for both char and varchar
718 ret=libodbc.SQLGetData(hstmt, ColIndex, col.SqlCType, buffer, bufsize, ref outsize);
720 DataValue=System.Text.Encoding.Default.GetString(buffer,0,outsize);
724 ret=libodbc.SQLGetData(hstmt, ColIndex, col.SqlCType, ref float_data, 0, ref outsize);
725 DataValue=float_data;
727 case OdbcType.Double:
728 double double_data=0;
729 ret=libodbc.SQLGetData(hstmt, ColIndex, col.SqlCType, ref double_data, 0, ref outsize);
730 DataValue=double_data;
732 case OdbcType.Timestamp:
733 case OdbcType.DateTime:
736 OdbcTimestamp ts_data=new OdbcTimestamp();
737 ret=libodbc.SQLGetData(hstmt, ColIndex, col.SqlCType, ref ts_data, 0, ref outsize);
738 if (outsize!=-1) // This means SQL_NULL_DATA
739 DataValue=new DateTime(ts_data.year,ts_data.month,ts_data.day,ts_data.hour,
740 ts_data.minute,ts_data.second,Convert.ToInt32(ts_data.fraction));
742 case OdbcType.Binary :
743 case OdbcType.Image :
744 bufsize = col.MaxLength + 1;
745 buffer = new byte [bufsize];
746 long read = GetBytes (ordinal, 0, buffer, 0, bufsize);
747 ret = OdbcReturn.Success;
752 buffer=new byte[bufsize];
753 ret=libodbc.SQLGetData(hstmt, ColIndex, SQL_C_TYPE.CHAR, buffer, bufsize, ref outsize);
754 if (outsize != (int) OdbcLengthIndicator.NullData)
755 if (! (ret == OdbcReturn.SuccessWithInfo
756 && outsize == (int) OdbcLengthIndicator.NoTotal))
757 DataValue=System.Text.Encoding.Default.GetString(buffer, 0, outsize);
761 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo))
762 throw new OdbcException(new OdbcError("SQLGetData",OdbcHandleType.Stmt,hstmt));
764 if (outsize==-1) // This means SQL_NULL_DATA
765 col.Value=DBNull.Value;
776 int GetValues (object[] values)
781 for (int i = 0; i < values.Length; i++) {
782 if (i < FieldCount) {
783 values[i] = GetValue(i);
790 // get number of object instances in array
791 if (values.Length < FieldCount)
792 numValues = values.Length;
793 else if (values.Length == FieldCount)
794 numValues = FieldCount;
796 numValues = FieldCount;
804 IDataReader IDataRecord.GetData (int ordinal)
806 throw new NotImplementedException ();
810 void IDisposable.Dispose ()
813 GC.SuppressFinalize (this);
816 public override void Dispose ()
819 GC.SuppressFinalize (this);
822 IEnumerator IEnumerable.GetEnumerator ()
824 return new DbEnumerator (this);
828 private void Dispose (bool disposing)
834 // dispose managed resources
840 _dataTableSchema = null;
848 bool IsDBNull (int ordinal)
850 return (GetValue(ordinal) is DBNull);
854 /// Move to the next result set.
862 OdbcReturn ret = OdbcReturn.Success;
863 ret = libodbc.SQLMoreResults (hstmt);
864 if (ret == OdbcReturn.Success) {
866 libodbc.SQLNumResultCols (hstmt, ref colcount);
867 cols = new OdbcColumn [colcount];
868 _dataTableSchema = null; // force fresh creation
871 return (ret==OdbcReturn.Success);
875 /// Load the next row in the current result set.
877 private bool NextRow ()
879 OdbcReturn ret=libodbc.SQLFetch (hstmt);
880 if (ret != OdbcReturn.Success)
885 // Clear cached values from last record
886 foreach (OdbcColumn col in cols)
891 return (ret == OdbcReturn.Success);
895 private int GetColumnAttribute (int column, FieldIdentifier fieldId)
897 OdbcReturn ret = OdbcReturn.Error;
898 byte [] buffer = new byte [255];
901 ret = libodbc.SQLColAttribute (hstmt, column, fieldId,
902 buffer, buffer.Length,
903 ref outsize, ref val);
904 if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
905 throw new OdbcException (new OdbcError ("SQLColAttribute",
913 private string GetColumnAttributeStr (int column, FieldIdentifier fieldId)
915 OdbcReturn ret = OdbcReturn.Error;
916 byte [] buffer = new byte [255];
919 ret = libodbc.SQLColAttribute (hstmt, column, fieldId,
920 buffer, buffer.Length,
921 ref outsize, ref val);
922 if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
923 throw new OdbcException (new OdbcError ("SQLColAttribute",
929 value = Encoding.Default.GetString (buffer, 0, outsize);
933 private string [] GetPrimaryKeys (string catalog, string schema, string table)
935 if (cols.Length <= 0)
936 return new string [0];
938 ArrayList keys = null;
940 keys = GetPrimaryKeysBySQLPrimaryKey (catalog, schema, table);
941 } catch (OdbcException){
943 keys = GetPrimaryKeysBySQLStatistics (catalog, schema, table);
944 } catch (OdbcException) {
948 return (string []) keys.ToArray (typeof (string));
951 private ArrayList GetPrimaryKeysBySQLPrimaryKey (string catalog, string schema, string table)
953 ArrayList keys = new ArrayList ();
954 IntPtr handle = IntPtr.Zero;
957 ret=libodbc.SQLAllocHandle(OdbcHandleType.Stmt,
958 command.Connection.hDbc, ref handle);
959 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo))
960 throw new OdbcException(new OdbcError("SQLAllocHandle",
962 command.Connection.hDbc));
964 ret = libodbc.SQLPrimaryKeys (handle, catalog, -3,
967 if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
968 throw new OdbcException (new OdbcError ("SQLPrimaryKeys", OdbcHandleType.Stmt, handle));
971 byte [] primaryKey = new byte [255];
973 ret = libodbc.SQLBindCol (handle, 4, SQL_C_TYPE.CHAR, primaryKey, primaryKey.Length, ref length);
974 if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
975 throw new OdbcException (new OdbcError ("SQLBindCol", OdbcHandleType.Stmt, handle));
979 ret = libodbc.SQLFetch (handle);
980 if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
982 string pkey = Encoding.Default.GetString (primaryKey, 0, length);
986 if (handle != IntPtr.Zero) {
987 ret = libodbc.SQLFreeStmt (handle, libodbc.SQLFreeStmtOptions.Close);
988 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo))
989 throw new OdbcException(new OdbcError("SQLFreeStmt",OdbcHandleType.Stmt,handle));
991 ret = libodbc.SQLFreeHandle( (ushort) OdbcHandleType.Stmt, handle);
992 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo))
993 throw new OdbcException(new OdbcError("SQLFreeHandle",OdbcHandleType.Stmt,handle));
999 private unsafe ArrayList GetPrimaryKeysBySQLStatistics (string catalog, string schema, string table)
1001 ArrayList keys = new ArrayList ();
1002 IntPtr handle = IntPtr.Zero;
1005 ret=libodbc.SQLAllocHandle(OdbcHandleType.Stmt,
1006 command.Connection.hDbc, ref handle);
1007 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo))
1008 throw new OdbcException(new OdbcError("SQLAllocHandle",
1010 command.Connection.hDbc));
1012 ret = libodbc.SQLStatistics (handle, catalog, -3,
1015 libodbc.SQL_INDEX_UNIQUE,
1017 if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
1018 throw new OdbcException (new OdbcError ("SQLStatistics", OdbcHandleType.Stmt, handle));
1021 int nonUniqueLength = 0;
1022 short nonUnique = libodbc.SQL_FALSE;
1023 ret = libodbc.SQLBindCol (handle, 4, SQL_C_TYPE.SHORT, ref (short) nonUnique, sizeof (short), ref nonUniqueLength);
1024 if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
1025 throw new OdbcException (new OdbcError ("SQLBindCol", OdbcHandleType.Stmt, handle));
1029 byte [] colName = new byte [255];
1030 ret = libodbc.SQLBindCol (handle, 9, SQL_C_TYPE.CHAR, colName, colName.Length, ref length);
1031 if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
1032 throw new OdbcException (new OdbcError ("SQLBindCol", OdbcHandleType.Stmt, handle));
1036 ret = libodbc.SQLFetch (handle);
1037 if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
1039 if (nonUnique == libodbc.SQL_TRUE) {
1040 string pkey = Encoding.Default.GetString (colName, 0, length);
1046 if (handle != IntPtr.Zero) {
1047 ret = libodbc.SQLFreeStmt (handle, libodbc.SQLFreeStmtOptions.Close);
1048 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo))
1049 throw new OdbcException(new OdbcError("SQLFreeStmt",OdbcHandleType.Stmt,handle));
1051 ret = libodbc.SQLFreeHandle( (ushort) OdbcHandleType.Stmt, handle);
1052 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo))
1053 throw new OdbcException(new OdbcError("SQLFreeHandle",OdbcHandleType.Stmt,handle));
1070 public override object GetProviderSpecificValue (int i)
1072 throw new NotImplementedException ();
1076 public override int GetProviderSpecificValues (object[] values)
1078 throw new NotImplementedException ();
1082 public override Type GetFieldProviderSpecificType (int i)
1084 throw new NotImplementedException ();