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);
}