Browse Source

2005-03-22 Sureshkumar T <[email protected]>
Appsamy <[email protected]>

* libodbc.cs (System.Data.Odbc): Added enum FieldIdentifier. Added
library functions SQLPrimaryKeys, SQLBindCol and SQLColAttribute.

* OdbcDataReader.cs: Implemented GetPrimaryKeys to get the primary
keys associated with resultset using SQLPrimaryKeys.


svn path=/trunk/mcs/; revision=42071

Sureshkumar T 21 years ago
parent
commit
fbf1f2c678

+ 9 - 0
mcs/class/System.Data/System.Data.Odbc/ChangeLog

@@ -1,3 +1,12 @@
+2005-03-22  Sureshkumar T  <[email protected]>
+            Appsamy <[email protected]>
+
+	* libodbc.cs (System.Data.Odbc): Added enum FieldIdentifier. Added
+	library functions SQLPrimaryKeys, SQLBindCol and SQLColAttribute.
+
+	* OdbcDataReader.cs: Implemented GetPrimaryKeys to get the primary
+	keys associated with resultset using SQLPrimaryKeys.
+
 2005-03-15  Sureshkumar T  <[email protected]>
 
 	* OdbcConnection.cs: re-throw error on exception in Open method.

+ 105 - 1
mcs/class/System.Data/System.Data.Odbc/OdbcDataReader.cs

@@ -501,6 +501,7 @@ namespace System.Data.Odbc
 			// otherwise, DataTable is null reference
 			if(cols.Length > 0) 
 			{
+                                string [] keys = GetPrimaryKeys ();
 				
 				dataTableSchema = new DataTable ();
 				
@@ -545,8 +546,16 @@ namespace System.Data.Odbc
 					schemaRow["NumericPrecision"] = 0;
 					schemaRow["NumericScale"] = 0;
 					// TODO: need to get KeyInfo
+
 					schemaRow["IsUnique"] = false;
-					schemaRow["IsKey"] = DBNull.Value;					
+					schemaRow["IsKey"] = DBNull.Value;
+                                       
+                                        for (int j=0; j < keys.Length; j++) {
+                                                if (keys [j] == col.ColumnName) {
+                                                        schemaRow ["IsUnique"] = true;
+                                                        schemaRow ["IsKey"] = true;
+                                                }
+                                        }
 
 					schemaRow["BaseCatalogName"] = "";				
 					schemaRow["BaseColumnName"] = col.ColumnName;
@@ -812,6 +821,101 @@ namespace System.Data.Odbc
 			return (ret == OdbcReturn.Success);
 		}
 
+
+                private int GetColumnAttribute (int column, FieldIdentifier fieldId)
+                {
+                        OdbcReturn ret = OdbcReturn.Error;
+                        byte [] buffer = new byte [255];
+                        int outsize = 0;
+                        int val = 0;
+                        ret = libodbc.SQLColAttribute (hstmt, column, fieldId, 
+                                                       buffer, buffer.Length, 
+                                                       ref outsize, ref val);
+                        if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
+                                throw new OdbcException (new OdbcError ("SQLColAttribute",
+                                                                        OdbcHandleType.Stmt,
+                                                                        hstmt)
+                                                         );
+                        return val;
+                        
+                }
+
+                private string GetColumnAttributeStr (int column, FieldIdentifier fieldId)
+                {
+                        OdbcReturn ret = OdbcReturn.Error;
+                        byte [] buffer = new byte [255];
+                        int outsize = 0;
+                        int val = 0;
+                        ret = libodbc.SQLColAttribute (hstmt, column, fieldId, 
+                                                       buffer, buffer.Length, 
+                                                       ref outsize, ref val);
+                        if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
+                                throw new OdbcException (new OdbcError ("SQLColAttribute",
+                                                                        OdbcHandleType.Stmt,
+                                                                        hstmt)
+                                                         );
+                        string value = Encoding.Default.GetString (buffer);
+                        return value;
+                }
+
+                private string [] GetPrimaryKeys ()
+                {
+                        if (cols.Length <= 0)
+                                return new string [0];
+
+                        string [] keys = new string [cols.Length];
+                        IntPtr handle = IntPtr.Zero;
+                        OdbcReturn ret = OdbcReturn.Error;                  
+                        try {
+                                ret=libodbc.SQLAllocHandle(OdbcHandleType.Stmt, 
+                                                           command.Connection.hDbc, ref handle);
+				if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+					throw new OdbcException(new OdbcError("SQLAllocHandle",
+                                                                              OdbcHandleType.Dbc,
+                                                                              command.Connection.hDbc));
+
+                                string tableName   = GetColumnAttributeStr (1, FieldIdentifier.TableName);
+                                string schemaName  = GetColumnAttributeStr (1, FieldIdentifier.SchemaName);
+                                string catalogName = GetColumnAttributeStr (1, FieldIdentifier.CatelogName);
+                                ret = libodbc.SQLPrimaryKeys (handle, catalogName, -3,  
+                                                              schemaName, -3, 
+                                                              tableName, -3);
+                                if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
+                                        throw new OdbcException (new OdbcError ("SQLPrimaryKeys", OdbcHandleType.Stmt, handle));
+                        
+                                int length = 0;
+                                byte [] primaryKey = new byte [255];
+                        
+                                ret = libodbc.SQLBindCol (handle, 4, SQL_C_TYPE.CHAR, primaryKey, primaryKey.Length, ref length);
+                                if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
+                                        throw new OdbcException (new OdbcError ("SQLBindCol", OdbcHandleType.Stmt, handle));
+                        
+                                int i = 0;                              
+                                while (true) {
+                                        ret = libodbc.SQLFetch (handle);
+                                        if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
+                                                break;
+                                        string pkey = Encoding.Default.GetString (primaryKey);
+                                        keys [i++] = pkey;
+                                }
+                        } catch (OdbcException){
+                                // FIXME: Try using SQLStatistics
+                        } finally {
+                                if (handle != IntPtr.Zero) {
+                                        ret = libodbc.SQLFreeStmt (handle, libodbc.SQLFreeStmtOptions.Close);
+                                        if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+                                                throw new OdbcException(new OdbcError("SQLFreeStmt",OdbcHandleType.Stmt,handle));
+                                        
+                                        ret = libodbc.SQLFreeHandle( (ushort) OdbcHandleType.Stmt, handle);
+                                                if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+                                                        throw new OdbcException(new OdbcError("SQLFreeHandle",OdbcHandleType.Stmt,handle));
+                                }                             
+                                        
+                        }
+                        
+                        return keys;
+                }
+
 		public
 #if NET_2_0
                 override

+ 62 - 4
mcs/class/System.Data/System.Data.Odbc/libodbc.cs

@@ -91,8 +91,41 @@ namespace System.Data.Odbc
                 NoTotal         = -4,
                 NullData        = -1
         }
-
-	[StructLayout(LayoutKind.Sequential)]
+        
+        // Keep this sorted.
+        internal enum FieldIdentifier 
+        {
+                AutoUniqueValue              = 11,    /* SQL_DESC_AUTO_UNIQUE_VALUE */
+                BaseColumnName               = 22,    /* SQL_DESC_BASE_COLUMN_NAME */
+                BaseTableName                = 23,    /* SQL_DESC_BASE_TABLE_NAME */
+                CaseSensitive                = 12,    /* SQL_DESC_CASE_SENSITIVE */
+                CatelogName                  = 17,    /* SQL_DESC_CATALOG_NAME */
+                ConsiseType                  = 2,     /* SQL_DESC_CONCISE_TYPE */
+                Count                        = 1001,  /* SQL_DESC_COUNT */
+                DisplaySize                  = 6,     /* SQL_DESC_DISPLAY_SIZE */
+                FixedPrecScale               = 9,     /* SQL_DESC_FIXED_PREC_SCALE */
+                Label                        = 18,    /* SQL_DESC_LABEL */
+                Length                       = 1003,  /* SQL_DESC_LENGTH */
+                LiteralPrefix                = 27,    /* SQL_DESC_LITERAL_PREFIX */
+                LiteralSuffix                = 28,    /* SQL_DESC_LITERAL_SUFFIX */
+                LocalTypeName                = 29,    /* SQL_DESC_LOCAL_TYPE_NAME */
+                Name                         = 1011,  /* SQL_DESC_NAME */
+                Nullable                     = 1008,  /* SQL_DESC_NULLABLE */
+                NumPrecRadix                 = 32,    /* SQL_DESC_NUM_PREC_RADIX */
+                OctetLength                  = 1013,  /* SQL_DESC_OCTET_LENGTH */
+                Precision                    = 1005,  /* SQL_DESC_PRECISION */
+                Scale                        = 1006,  /* SQL_DESC_SCALE */
+                SchemaName                   = 16,    /* SQL_DESC_SCHEMA_NAME */
+                Searchable                   = 13,    /* SQL_DESC_SEARCHABLE */
+                TableName                    = 15,    /* SQL_DESC_TABLE_NAME */
+                Type                         = 1002,  /* SQL_DESC_TYPE */
+                TypeName                     = 14,    /* SQL_DESC_TYPE_NAME */
+                Unnamed                      = 1012,  /* SQL_DESC_UNNAMED */
+                Unsigned                     = 8,     /* SQL_DESC_UNSIGNED */
+                Updatable                    = 10     /* SQL_DESC_UPDATABLE */                
+        }
+        
+        [StructLayout(LayoutKind.Sequential)]
 	internal struct OdbcTimestamp
 	{
 		internal short year;
@@ -261,7 +294,32 @@ namespace System.Data.Odbc
                                                               byte [] buffer, 
                                                               short buffLength, 
                                                               ref short remainingStrLen);
-
-
+                [DllImport ("odbc32.dll")]
+                internal static extern OdbcReturn SQLColAttribute (IntPtr StmtHandle,
+                                                                   int column,
+                                                                   FieldIdentifier fieldId,
+                                                                   byte [] charAttributePtr, 
+                                                                   int bufferLength,
+                                                                   ref int strLengthPtr,
+                                                                   ref int numericAttributePtr
+                                                                   );
+                [DllImport ("odbc32.dll")]
+                internal static extern OdbcReturn SQLPrimaryKeys (IntPtr StmtHandle,
+                                                                   string catalog,
+                                                                   int catalogLength,
+                                                                   string schema, 
+                                                                   int schemaLength,
+                                                                   string tableName,
+                                                                   int tableLength
+                                                                   );
+
+                [DllImport ("odbc32.dll")]
+                internal static extern OdbcReturn SQLBindCol (IntPtr StmtHandle,
+                                                                   int column,
+                                                                   SQL_C_TYPE targetType,
+                                                                   byte [] buffer, 
+                                                                   int bufferLength,
+                                                                   ref int indicator
+                                                                   );
 	}
 }