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;
42 namespace System.Data.Odbc
45 public sealed class OdbcDataReader : DbDataReader
47 public sealed class OdbcDataReader : MarshalByRefObject, IDataReader, IDisposable, IDataRecord, IEnumerable
52 private OdbcCommand command;
54 private int currentRow;
55 private OdbcColumn[] cols;
57 private int _recordsAffected = -1;
58 bool disposed = false;
59 private DataTable _dataTableSchema;
60 private CommandBehavior behavior;
66 internal OdbcDataReader (OdbcCommand command, CommandBehavior behavior)
68 this.command = command;
69 this.CommandBehavior = behavior;
72 hstmt = command.hStmt;
73 // Init columns array;
75 libodbc.SQLNumResultCols (hstmt, ref colcount);
76 cols = new OdbcColumn [colcount];
80 internal OdbcDataReader (OdbcCommand command, CommandBehavior behavior,
81 int recordAffected) : this (command, behavior)
83 _recordsAffected = recordAffected;
91 private CommandBehavior CommandBehavior
93 get { return behavior; }
94 set { value = behavior; }
103 return 0; // no nested selects supported
131 object this[string name] {
135 if (currentRow == -1)
136 throw new InvalidOperationException ();
138 pos = ColIndex(name);
141 throw new IndexOutOfRangeException ();
151 object this [int index] {
153 return (object) GetValue (index);
161 int RecordsAffected {
163 return _recordsAffected;
173 get { throw new NotImplementedException(); }
180 private int ColIndex (string colname)
183 foreach (OdbcColumn col in cols)
186 if (col.ColumnName == colname)
188 if (String.Compare (col.ColumnName, colname, true) == 0)
197 // Dynamically load column descriptions as needed.
198 private OdbcColumn GetColumn (int ordinal)
200 if (cols [ordinal] == null) {
202 byte [] colname_buffer = new byte [bufsize];
204 short colname_size = 0;
206 short DecDigits = 0, Nullable = 0, dt = 0;
207 OdbcReturn ret = libodbc.SQLDescribeCol (hstmt, Convert.ToUInt16 (ordinal + 1),
208 colname_buffer, bufsize, ref colname_size, ref dt, ref ColSize,
209 ref DecDigits, ref Nullable);
210 if ((ret != OdbcReturn.Success) && (ret != OdbcReturn.SuccessWithInfo))
211 throw new OdbcException (new OdbcError ("SQLDescribeCol", OdbcHandleType.Stmt, hstmt));
212 colname = System.Text.Encoding.Default.GetString (colname_buffer);
213 colname = colname.Replace ((char) 0, ' ').Trim ();
214 OdbcColumn c = new OdbcColumn (colname, (SQL_TYPE) dt);
215 c.AllowDBNull = (Nullable != 0);
216 c.Digits = DecDigits;
217 if (c.IsVariableSizeType)
218 c.MaxLength = (int) ColSize;
221 return cols [ordinal];
230 // FIXME : have to implement output parameter binding
234 this.command.FreeIfNotPrepared ();
236 if ((this.CommandBehavior & CommandBehavior.CloseConnection) == CommandBehavior.CloseConnection) {
237 this.command.Connection.Close ();
243 this.Dispose (false);
250 bool GetBoolean (int ordinal)
252 return (bool) GetValue(ordinal);
259 byte GetByte (int ordinal)
261 return (byte) Convert.ToByte(GetValue(ordinal));
268 long GetBytes (int ordinal, long dataIndex, byte[] buffer, int bufferIndex, int length)
270 OdbcReturn ret = OdbcReturn.Error;
271 bool copyBuffer = false;
272 int returnVal = 0, outsize = 0;
273 byte [] tbuff = new byte [length+1];
275 length = buffer == null ? 0 : length;
276 ret=libodbc.SQLGetData (hstmt, (ushort) (ordinal+1), SQL_C_TYPE.BINARY, tbuff, length,
279 if (ret == OdbcReturn.NoData)
282 if ( (ret != OdbcReturn.Success) && (ret != OdbcReturn.SuccessWithInfo))
283 throw new OdbcException (new OdbcError ("SQLGetData", OdbcHandleType.Stmt, hstmt));
285 OdbcError odbcErr = null;
286 if ( (ret == OdbcReturn.SuccessWithInfo))
287 odbcErr = new OdbcError ("SQLGetData", OdbcHandleType.Stmt, hstmt);
290 return outsize; //if buffer is null,return length of the field
292 if (ret == OdbcReturn.SuccessWithInfo) {
293 if (outsize == (int) OdbcLengthIndicator.NoTotal)
295 else if (outsize == (int) OdbcLengthIndicator.NullData) {
299 string sqlstate = odbcErr.SQLState;
300 //SQLState: String Data, Right truncated
301 if (sqlstate != libodbc.SQLSTATE_RIGHT_TRUNC)
302 throw new OdbcException ( odbcErr);
306 copyBuffer = outsize == -1 ? false : true;
312 while (tbuff [i] != libodbc.C_NULL) {
313 buffer [bufferIndex + i] = tbuff [i];
326 char GetChar (int ordinal)
328 throw new NotImplementedException ();
336 long GetChars (int ordinal, long dataIndex, char[] buffer, int bufferIndex, int length)
338 throw new NotImplementedException ();
342 [EditorBrowsableAttribute (EditorBrowsableState.Never)]
347 IDataReader GetData (int ordinal)
349 throw new NotImplementedException ();
356 string GetDataTypeName (int index)
358 return GetColumn (index).OdbcType.ToString ();
361 public DateTime GetDate (int ordinal) {
362 return GetDateTime (ordinal);
369 DateTime GetDateTime (int ordinal)
371 return (DateTime) GetValue (ordinal);
378 decimal GetDecimal (int ordinal)
380 return (decimal) GetValue (ordinal);
387 double GetDouble (int ordinal)
389 return (double) GetValue (ordinal);
396 Type GetFieldType (int index)
398 return GetColumn(index).DataType;
405 float GetFloat (int ordinal)
407 return (float) GetValue (ordinal);
415 Guid GetGuid (int ordinal)
417 throw new NotImplementedException ();
424 short GetInt16 (int ordinal)
426 return (short) GetValue (ordinal);
433 int GetInt32 (int ordinal)
435 return (int) GetValue (ordinal);
442 long GetInt64 (int ordinal)
444 return (long) GetValue (ordinal);
451 string GetName (int index)
453 return GetColumn(index).ColumnName;
460 int GetOrdinal (string name)
462 int i=ColIndex(name);
465 throw new IndexOutOfRangeException ();
475 DataTable GetSchemaTable()
478 // * Map OdbcType to System.Type and assign to DataType.
479 // This will eliminate the need for IsStringType in
482 if (_dataTableSchema != null)
483 return _dataTableSchema;
485 DataTable dataTableSchema = null;
486 // Only Results from SQL SELECT Queries
487 // get a DataTable for schema of the result
488 // otherwise, DataTable is null reference
491 dataTableSchema = new DataTable ();
493 dataTableSchema.Columns.Add ("ColumnName", typeof (string));
494 dataTableSchema.Columns.Add ("ColumnOrdinal", typeof (int));
495 dataTableSchema.Columns.Add ("ColumnSize", typeof (int));
496 dataTableSchema.Columns.Add ("NumericPrecision", typeof (int));
497 dataTableSchema.Columns.Add ("NumericScale", typeof (int));
498 dataTableSchema.Columns.Add ("IsUnique", typeof (bool));
499 dataTableSchema.Columns.Add ("IsKey", typeof (bool));
500 DataColumn dc = dataTableSchema.Columns["IsKey"];
501 dc.AllowDBNull = true; // IsKey can have a DBNull
502 dataTableSchema.Columns.Add ("BaseCatalogName", typeof (string));
503 dataTableSchema.Columns.Add ("BaseColumnName", typeof (string));
504 dataTableSchema.Columns.Add ("BaseSchemaName", typeof (string));
505 dataTableSchema.Columns.Add ("BaseTableName", typeof (string));
506 dataTableSchema.Columns.Add ("DataType", typeof(Type));
507 dataTableSchema.Columns.Add ("AllowDBNull", typeof (bool));
508 dataTableSchema.Columns.Add ("ProviderType", typeof (int));
509 dataTableSchema.Columns.Add ("IsAliased", typeof (bool));
510 dataTableSchema.Columns.Add ("IsExpression", typeof (bool));
511 dataTableSchema.Columns.Add ("IsIdentity", typeof (bool));
512 dataTableSchema.Columns.Add ("IsAutoIncrement", typeof (bool));
513 dataTableSchema.Columns.Add ("IsRowVersion", typeof (bool));
514 dataTableSchema.Columns.Add ("IsHidden", typeof (bool));
515 dataTableSchema.Columns.Add ("IsLong", typeof (bool));
516 dataTableSchema.Columns.Add ("IsReadOnly", typeof (bool));
520 for (int i = 0; i < cols.Length; i += 1 )
522 string baseTableName = String.Empty;
524 OdbcColumn col=GetColumn(i);
526 schemaRow = dataTableSchema.NewRow ();
527 dataTableSchema.Rows.Add (schemaRow);
529 schemaRow ["ColumnName"] = col.ColumnName;
530 schemaRow ["ColumnOrdinal"] = i;
531 schemaRow ["ColumnSize"] = col.MaxLength;
532 schemaRow ["NumericPrecision"] = GetColumnAttribute (i+1, FieldIdentifier.Precision);
533 schemaRow ["NumericScale"] = GetColumnAttribute (i+1, FieldIdentifier.Scale);
534 schemaRow ["BaseTableName"] = GetColumnAttributeStr (i+1, FieldIdentifier.TableName);
535 schemaRow ["BaseSchemaName"] = GetColumnAttributeStr (i+1, FieldIdentifier.SchemaName);
536 schemaRow ["BaseCatalogName"] = GetColumnAttributeStr (i+1, FieldIdentifier.CatelogName);
537 schemaRow ["BaseColumnName"] = GetColumnAttributeStr (i+1, FieldIdentifier.BaseColumnName);
538 schemaRow ["DataType"] = col.DataType;
539 schemaRow ["IsUnique"] = false;
540 schemaRow ["IsKey"] = DBNull.Value;
541 schemaRow ["AllowDBNull"] = GetColumnAttribute (i+1, FieldIdentifier.Nullable) != libodbc.SQL_NO_NULLS;
542 schemaRow ["ProviderType"] = (int) col.OdbcType;
543 schemaRow ["IsAutoIncrement"] = GetColumnAttribute (i+1, FieldIdentifier.AutoUniqueValue) == libodbc.SQL_TRUE;
544 schemaRow ["IsExpression"] = schemaRow.IsNull ("BaseTableName") || (string) schemaRow ["BaseTableName"] == String.Empty;
545 schemaRow ["IsAliased"] = (string) schemaRow ["BaseColumnName"] != (string) schemaRow ["ColumnName"];
546 schemaRow ["IsReadOnly"] = ((bool) schemaRow ["IsExpression"]
547 || GetColumnAttribute (i+1, FieldIdentifier.Updatable) == libodbc.SQL_ATTR_READONLY);
549 // FIXME: all of these
550 schemaRow ["IsIdentity"] = false;
551 schemaRow ["IsRowVersion"] = false;
552 schemaRow ["IsHidden"] = false;
553 schemaRow ["IsLong"] = false;
556 // FIXME: according to Brian,
557 // this does not work on MS .NET
558 // however, we need it for Mono
560 // schemaRow.AcceptChanges();
565 DataRow [] rows = dataTableSchema.Select ("BaseTableName <> ''",
566 "BaseCatalogName, BaseSchemaName, BaseTableName ASC");
568 string lastTableName = String.Empty,
569 lastSchemaName = String.Empty,
570 lastCatalogName = String.Empty;
571 string [] keys = null; // assumed to be sorted.
572 foreach (DataRow row in rows) {
573 string tableName = (string) row ["BaseTableName"];
574 string schemaName = (string) row ["BaseSchemaName"];
575 string catalogName = (string) row ["BaseCatalogName"];
577 if (tableName != lastTableName || schemaName != lastSchemaName
578 || catalogName != lastCatalogName)
579 keys = GetPrimaryKeys (catalogName, schemaName, tableName);
582 Array.BinarySearch (keys, (string) row ["BaseColumnName"]) >= 0) {
583 row ["IsKey"] = true;
584 row ["IsUnique"] = true;
585 row ["AllowDBNull"] = false;
586 GetColumn ( ColIndex ( (string) row ["ColumnName"])).AllowDBNull = false;
588 lastTableName = tableName;
589 lastSchemaName = schemaName;
590 lastCatalogName = catalogName;
592 dataTableSchema.AcceptChanges();
594 return (_dataTableSchema = dataTableSchema);
601 string GetString (int ordinal)
603 return (string) GetValue (ordinal);
607 public TimeSpan GetTime (int ordinal)
609 throw new NotImplementedException ();
616 object GetValue (int ordinal)
618 if (currentRow == -1)
619 throw new IndexOutOfRangeException ();
621 if (ordinal > cols.Length-1 || ordinal < 0)
622 throw new IndexOutOfRangeException ();
625 int outsize = 0, bufsize;
627 OdbcColumn col = GetColumn (ordinal);
628 object DataValue = null;
629 ushort ColIndex = Convert.ToUInt16 (ordinal+1);
631 // Check cached values
632 if (col.Value == null) {
634 // mk:@MSITStore:C:\program%20files\Microsoft%20Data%20Access%20SDK\Docs\odbc.chm::/htm/odbcc_data_types.htm
635 switch (col.OdbcType) {
638 ret = libodbc.SQLGetData (hstmt, ColIndex, col.SqlCType, ref bit_data, 0, ref outsize);
639 if (outsize != (int) OdbcLengthIndicator.NullData)
640 DataValue = bit_data == 0 ? "False" : "True";
642 case OdbcType.Numeric:
643 case OdbcType.Decimal:
645 buffer = new byte [bufsize]; // According to sqlext.h, use SQL_CHAR for decimal.
646 // FIXME : use Numeric.
647 ret = libodbc.SQLGetData (hstmt, ColIndex, SQL_C_TYPE.CHAR, buffer, bufsize, ref outsize);
649 byte [] temp = new byte [outsize];
650 for (int i = 0;i<outsize;i++)
652 DataValue = Decimal.Parse(System.Text.Encoding.Default.GetString(temp));
655 case OdbcType.TinyInt:
656 short short_data = 0;
657 ret = libodbc.SQLGetData (hstmt, ColIndex, col.SqlCType, ref short_data, 0, ref outsize);
658 DataValue = System.Convert.ToByte(short_data);
662 ret = libodbc.SQLGetData (hstmt, ColIndex, col.SqlCType, ref int_data, 0, ref outsize);
663 DataValue = int_data;
666 case OdbcType.SmallInt:
668 ret = libodbc.SQLGetData (hstmt, ColIndex, col.SqlCType, ref sint_data, 0, ref outsize);
669 DataValue = sint_data;
672 case OdbcType.BigInt:
674 ret = libodbc.SQLGetData (hstmt, ColIndex, col.SqlCType, ref long_data, 0, ref outsize);
675 DataValue = long_data;
678 case OdbcType.NVarChar:
679 bufsize = (col.MaxLength < 127 ? (col.MaxLength*2+1) : 255);
680 buffer = new byte[bufsize]; // According to sqlext.h, use SQL_CHAR for both char and varchar
681 StringBuilder sb = new StringBuilder ();
683 ret = libodbc.SQLGetData (hstmt, ColIndex, col.SqlCType, buffer, bufsize, ref outsize);
684 if (ret == OdbcReturn.Error)
686 if (ret != OdbcReturn.NoData && outsize!=-1) {
687 if (outsize < bufsize)
688 sb.Append (System.Text.Encoding.Unicode.GetString(buffer,0,outsize));
690 sb.Append (System.Text.Encoding.Unicode.GetString(buffer,0,bufsize));
692 } while (ret != OdbcReturn.NoData);
693 DataValue = sb.ToString ();
696 case OdbcType.VarChar:
697 bufsize = (col.MaxLength < 255 ? (col.MaxLength+1) : 255);
698 buffer = new byte[bufsize]; // According to sqlext.h, use SQL_CHAR for both char and varchar
699 StringBuilder sb1 = new StringBuilder ();
701 ret = libodbc.SQLGetData (hstmt, ColIndex, col.SqlCType, buffer, bufsize, ref outsize);
702 if (ret == OdbcReturn.Error)
704 if (ret != OdbcReturn.NoData && outsize!=-1) {
705 if (outsize < bufsize)
706 sb1.Append (System.Text.Encoding.Default.GetString(buffer,0,outsize));
708 sb1.Append (System.Text.Encoding.Default.GetString(buffer,0,bufsize));
710 } while (ret != OdbcReturn.NoData);
711 DataValue = sb1.ToString ();
714 float float_data = 0;
715 ret = libodbc.SQLGetData (hstmt, ColIndex, col.SqlCType, ref float_data, 0, ref outsize);
716 DataValue = float_data;
718 case OdbcType.Double:
719 double double_data = 0;
720 ret = libodbc.SQLGetData (hstmt, ColIndex, col.SqlCType, ref double_data, 0, ref outsize);
721 DataValue = double_data;
723 case OdbcType.Timestamp:
724 case OdbcType.DateTime:
727 OdbcTimestamp ts_data = new OdbcTimestamp();
728 ret = libodbc.SQLGetData (hstmt, ColIndex, col.SqlCType, ref ts_data, 0, ref outsize);
729 if (outsize!=-1) // This means SQL_NULL_DATA
730 DataValue = new DateTime(ts_data.year,ts_data.month,ts_data.day,ts_data.hour,
731 ts_data.minute,ts_data.second,Convert.ToInt32(ts_data.fraction));
733 case OdbcType.VarBinary :
734 case OdbcType.Image :
735 bufsize = (col.MaxLength < 255 ? col.MaxLength : 255);
736 buffer= new byte [bufsize];
737 ArrayList al = new ArrayList ();
739 ret = libodbc.SQLGetData (hstmt, ColIndex, SQL_C_TYPE.BINARY, buffer, bufsize, ref outsize);
740 if (ret == OdbcReturn.Error)
742 if (ret != OdbcReturn.NoData && outsize!=-1) {
743 if (outsize < bufsize) {
744 byte[] tmparr = new byte [outsize];
745 Array.Copy (buffer, 0, tmparr, 0, outsize);
746 al.AddRange (tmparr);
748 al.AddRange (buffer);
750 } while (ret != OdbcReturn.NoData);
751 DataValue = al.ToArray (typeof (byte));
753 case OdbcType.Binary :
754 bufsize = col.MaxLength;
755 buffer = new byte [bufsize];
756 long read = GetBytes (ordinal, 0, buffer, 0, bufsize);
757 ret = OdbcReturn.Success;
762 buffer = new byte[bufsize];
763 ret = libodbc.SQLGetData (hstmt, ColIndex, SQL_C_TYPE.CHAR, buffer, bufsize, ref outsize);
764 if (outsize != (int) OdbcLengthIndicator.NullData)
765 if (! (ret == OdbcReturn.SuccessWithInfo
766 && outsize == (int) OdbcLengthIndicator.NoTotal))
767 DataValue = System.Text.Encoding.Default.GetString(buffer, 0, outsize);
771 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo) && (ret!=OdbcReturn.NoData))
772 throw new OdbcException(new OdbcError("SQLGetData",OdbcHandleType.Stmt,hstmt));
774 if (outsize==-1) // This means SQL_NULL_DATA
775 col.Value = DBNull.Value;
777 col.Value = DataValue;
786 int GetValues (object[] values)
791 for (int i = 0; i < values.Length; i++) {
792 if (i < FieldCount) {
793 values[i] = GetValue (i);
800 // get number of object instances in array
801 if (values.Length < FieldCount)
802 numValues = values.Length;
803 else if (values.Length == FieldCount)
804 numValues = FieldCount;
806 numValues = FieldCount;
813 void IDisposable.Dispose ()
816 GC.SuppressFinalize (this);
819 IEnumerator IEnumerable.GetEnumerator ()
821 return new DbEnumerator (this);
827 public override IEnumerator GetEnumerator ()
829 return new DbEnumerator (this);
836 void Dispose (bool disposing)
842 // dispose managed resources
848 _dataTableSchema = null;
856 bool IsDBNull (int ordinal)
858 return (GetValue (ordinal) is DBNull);
862 /// Move to the next result set.
870 OdbcReturn ret = OdbcReturn.Success;
871 ret = libodbc.SQLMoreResults (hstmt);
872 if (ret == OdbcReturn.Success) {
874 libodbc.SQLNumResultCols (hstmt, ref colcount);
875 cols = new OdbcColumn [colcount];
876 _dataTableSchema = null; // force fresh creation
879 return (ret==OdbcReturn.Success);
883 /// Load the next row in the current result set.
885 private bool NextRow ()
887 OdbcReturn ret=libodbc.SQLFetch (hstmt);
888 if (ret != OdbcReturn.Success)
893 // Clear cached values from last record
894 foreach (OdbcColumn col in cols)
899 return (ret == OdbcReturn.Success);
903 private int GetColumnAttribute (int column, FieldIdentifier fieldId)
905 OdbcReturn ret = OdbcReturn.Error;
906 byte [] buffer = new byte [255];
909 ret = libodbc.SQLColAttribute (hstmt, (short)column, fieldId,
910 buffer, (short)buffer.Length,
911 ref outsize, ref val);
912 if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
913 throw new OdbcException (new OdbcError ("SQLColAttribute",
921 private string GetColumnAttributeStr (int column, FieldIdentifier fieldId)
923 OdbcReturn ret = OdbcReturn.Error;
924 byte [] buffer = new byte [255];
927 ret = libodbc.SQLColAttribute (hstmt, (short)column, fieldId,
928 buffer, (short)buffer.Length,
929 ref outsize, ref val);
930 if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
931 throw new OdbcException (new OdbcError ("SQLColAttribute",
937 value = Encoding.Default.GetString (buffer, 0, outsize);
941 private string [] GetPrimaryKeys (string catalog, string schema, string table)
943 if (cols.Length <= 0)
944 return new string [0];
946 ArrayList keys = null;
948 keys = GetPrimaryKeysBySQLPrimaryKey (catalog, schema, table);
949 } catch (OdbcException){
951 keys = GetPrimaryKeysBySQLStatistics (catalog, schema, table);
952 } catch (OdbcException) {
956 return (string []) keys.ToArray (typeof (string));
959 private ArrayList GetPrimaryKeysBySQLPrimaryKey (string catalog, string schema, string table)
961 ArrayList keys = new ArrayList ();
962 IntPtr handle = IntPtr.Zero;
965 ret=libodbc.SQLAllocHandle(OdbcHandleType.Stmt,
966 command.Connection.hDbc, ref handle);
967 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo))
968 throw new OdbcException(new OdbcError("SQLAllocHandle",
970 command.Connection.hDbc));
972 ret = libodbc.SQLPrimaryKeys (handle, catalog, -3,
975 if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
976 throw new OdbcException (new OdbcError ("SQLPrimaryKeys", OdbcHandleType.Stmt, handle));
979 byte [] primaryKey = new byte [255];
981 ret = libodbc.SQLBindCol (handle, 4, SQL_C_TYPE.CHAR, primaryKey, primaryKey.Length, ref length);
982 if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
983 throw new OdbcException (new OdbcError ("SQLBindCol", OdbcHandleType.Stmt, handle));
987 ret = libodbc.SQLFetch (handle);
988 if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
990 string pkey = Encoding.Default.GetString (primaryKey, 0, length);
994 if (handle != IntPtr.Zero) {
995 ret = libodbc.SQLFreeStmt (handle, libodbc.SQLFreeStmtOptions.Close);
996 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo))
997 throw new OdbcException(new OdbcError("SQLFreeStmt",OdbcHandleType.Stmt,handle));
999 ret = libodbc.SQLFreeHandle( (ushort) OdbcHandleType.Stmt, handle);
1000 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo))
1001 throw new OdbcException(new OdbcError("SQLFreeHandle",OdbcHandleType.Stmt,handle));
1007 private unsafe ArrayList GetPrimaryKeysBySQLStatistics (string catalog, string schema, string table)
1009 ArrayList keys = new ArrayList ();
1010 IntPtr handle = IntPtr.Zero;
1013 ret=libodbc.SQLAllocHandle(OdbcHandleType.Stmt,
1014 command.Connection.hDbc, ref handle);
1015 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo))
1016 throw new OdbcException(new OdbcError("SQLAllocHandle",
1018 command.Connection.hDbc));
1020 ret = libodbc.SQLStatistics (handle, catalog, -3,
1023 libodbc.SQL_INDEX_UNIQUE,
1025 if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
1026 throw new OdbcException (new OdbcError ("SQLStatistics", OdbcHandleType.Stmt, handle));
1029 int nonUniqueLength = 0;
1030 short nonUnique = libodbc.SQL_FALSE;
1031 ret = libodbc.SQLBindCol (handle, 4, SQL_C_TYPE.SHORT, ref (short) nonUnique, sizeof (short), ref nonUniqueLength);
1032 if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
1033 throw new OdbcException (new OdbcError ("SQLBindCol", OdbcHandleType.Stmt, handle));
1037 byte [] colName = new byte [255];
1038 ret = libodbc.SQLBindCol (handle, 9, SQL_C_TYPE.CHAR, colName, colName.Length, ref length);
1039 if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
1040 throw new OdbcException (new OdbcError ("SQLBindCol", OdbcHandleType.Stmt, handle));
1044 ret = libodbc.SQLFetch (handle);
1045 if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
1047 if (nonUnique == libodbc.SQL_TRUE) {
1048 string pkey = Encoding.Default.GetString (colName, 0, length);
1054 if (handle != IntPtr.Zero) {
1055 ret = libodbc.SQLFreeStmt (handle, libodbc.SQLFreeStmtOptions.Close);
1056 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo))
1057 throw new OdbcException(new OdbcError("SQLFreeStmt",OdbcHandleType.Stmt,handle));
1059 ret = libodbc.SQLFreeHandle( (ushort) OdbcHandleType.Stmt, handle);
1060 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo))
1061 throw new OdbcException(new OdbcError("SQLFreeHandle",OdbcHandleType.Stmt,handle));
1078 public override object GetProviderSpecificValue (int i)
1080 throw new NotImplementedException ();
1084 public override int GetProviderSpecificValues (object[] values)
1086 throw new NotImplementedException ();
1090 public override Type GetProviderSpecificFieldType (int i)
1092 throw new NotImplementedException ();