924 lines
40 KiB
C#
924 lines
40 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Data;
|
|
using System.Data.Common;
|
|
using System.Data.Odbc;
|
|
using Microsoft.Data.SqlClient;
|
|
using System.Linq;
|
|
using Sarand.Net.Standard.Base.App;
|
|
using Sarand.Net.Standard.Base.Core;
|
|
using Sarand.Net.Standard.Base.Bus;
|
|
using Sarand.Net.Standard.Base.Dbas;
|
|
using Sarand.Net.Standard.Dbas.Base;
|
|
using Sarand.Net.Standard.Base.Utils;
|
|
using System.Diagnostics;
|
|
|
|
namespace Sarand.Net.Standard.Dbas.Data
|
|
{
|
|
//=======================================================================
|
|
internal class SacsDatabaseOdbc : SacsDatabase
|
|
{
|
|
//-------------------------------------------------------------------
|
|
// Data members.
|
|
private String sqlConnectionString = "";
|
|
private readonly Dictionary<String, DbDfnTable> tableDfns = new Dictionary<String, DbDfnTable>();
|
|
private bool tableDfnsPopulated = false;
|
|
public static readonly String DbCol_CreateOn = "CreateOn";
|
|
public static readonly String DbCol_CreateBy = "CreateBy";
|
|
public static readonly String DbCol_UpdateOn = "UpdateOn";
|
|
public static readonly String DbCol_UpdateBy = "UpdateBy";
|
|
|
|
//-------------------------------------------------------------------
|
|
// Construction.
|
|
public SacsDatabaseOdbc(DbmsType dbms, String databaseName, String connectionString) : base(dbms, databaseName, connectionString)
|
|
{
|
|
if (dbms == DbmsType.MsSql)
|
|
sqlConnectionString = connectionString;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Properties.
|
|
public String SqlConnectionString
|
|
{
|
|
get { return sqlConnectionString; }
|
|
set
|
|
{
|
|
if (sqlConnectionString.Equals(value)) return;
|
|
sqlConnectionString = value;
|
|
OnConnectionChanged();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Connection.
|
|
public override void OnConnectionChanged()
|
|
{
|
|
}
|
|
public override DbConnection CreateConnection(bool forceOdbc = false)
|
|
{
|
|
if (!forceOdbc && DbmsType == DbmsType.MsSql && !StringUtil.IsEmpty(sqlConnectionString))
|
|
return new SqlConnection(sqlConnectionString);
|
|
return new OdbcConnection(ConnectionString);
|
|
}
|
|
public override DbDataAdapter CreateDataAdapter()
|
|
{
|
|
return new OdbcDataAdapter();
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// I d e n t i t y G e n e r a t i o n
|
|
//-------------------------------------------------------------------
|
|
private DbDfnTable nextIdTableDfn = null;
|
|
public override SysId GetNextId(String objectName, DbUpdateInfo dbUpdateInfo, bool databaseTable = true, String idColumn = "Id")
|
|
{
|
|
PopulateNextIdTableDfn();
|
|
|
|
// Next Id database definitions.
|
|
String colObject = NextIdTable + "." + NextIdColumn_Object;
|
|
String colNextId = NextIdTable + "." + NextIdColumn_NextId;
|
|
String colAliasNextId = "NxtId";
|
|
String filter = "(" + colObject + ")='" + objectName + "'";
|
|
bool hasCreateCols = (nextIdTableDfn.HasColumnByName(DbCol_CreateOn) && nextIdTableDfn.HasColumnByName(DbCol_CreateBy));
|
|
bool hasUpdateCols = (nextIdTableDfn.HasColumnByName(DbCol_UpdateOn) && nextIdTableDfn.HasColumnByName(DbCol_UpdateBy));
|
|
|
|
// Query the data.
|
|
int nextIdValue = 1;
|
|
DbQuery qry = new DbQuery(DbmsType);
|
|
qry.Tables.Add(NextIdTable);
|
|
qry.Columns.Add(colNextId, colAliasNextId);
|
|
qry.Filters.Add(filter);
|
|
//SaLogger.Debug($"{SysUtil.Fn} Query: {qry.BuildQuery()}");
|
|
DbResultSet_DataReader resultsSet = DbResultSet_DataReader.ExecuteQuery(this, qry.BuildQuery());
|
|
if (resultsSet != null && resultsSet.NextRecord())
|
|
{
|
|
NamedValue.Map values = resultsSet.GetRecordValues();
|
|
nextIdValue = Math.Max(1, (int)values.GetValue(colAliasNextId).AsLong());
|
|
// Update the record with the next available value.
|
|
List<StringPair> updateColumnValues = new List<StringPair>();
|
|
updateColumnValues.Add(NextIdColumn_NextId, (nextIdValue + 1).ToString());
|
|
if (hasUpdateCols)
|
|
{
|
|
updateColumnValues.Add(DbCol_UpdateOn, DbQuery.FormatDateTimeForCondition(DateTime.Now));
|
|
updateColumnValues.Add(DbCol_UpdateBy, SysId.IsValid(dbUpdateInfo.UserId) ? SysId.ToString(dbUpdateInfo.UserId) : "0");
|
|
}
|
|
String updateQry = "Update " + NextIdTable + " Set " + updateColumnValues.Concat("=").Concat(", ") + " Where " + filter;
|
|
//SaLogger.Debug($"{SysUtil.Fn} Update query: {updateQry}");
|
|
using (var dbConnection = CreateConnection())
|
|
using (var dbCommand = dbConnection.CreateCommand())
|
|
{
|
|
dbConnection.Open();
|
|
dbCommand.CommandType = System.Data.CommandType.Text;
|
|
dbCommand.CommandText = updateQry;
|
|
dbCommand.ExecuteNonQuery();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Object not found on NextId table.
|
|
// If object is a database table, query maximum value.
|
|
if (databaseTable)
|
|
nextIdValue = GetNextIdFromTable(objectName, idColumn);
|
|
|
|
// Construct query to store Next Id value.
|
|
List<StringPair> insertColumnValues = new List<StringPair>();
|
|
insertColumnValues.Add(NextIdColumn_Object, "'" + DbQuery.FormatForCondition(objectName) + "'");
|
|
insertColumnValues.Add(NextIdColumn_NextId, (nextIdValue + 1).ToString());
|
|
if (hasCreateCols)
|
|
{
|
|
insertColumnValues.Add(DbCol_CreateOn, DbQuery.FormatDateTimeForCondition(DateTime.Now));
|
|
insertColumnValues.Add(DbCol_CreateBy, SysId.IsValid(dbUpdateInfo.UserId) ? SysId.ToString(dbUpdateInfo.UserId) : "0");
|
|
}
|
|
if (hasUpdateCols)
|
|
{
|
|
insertColumnValues.Add(DbCol_UpdateOn, DbQuery.FormatDateTimeForCondition(DateTime.Now));
|
|
insertColumnValues.Add(DbCol_UpdateBy, SysId.IsValid(dbUpdateInfo.UserId) ? SysId.ToString(dbUpdateInfo.UserId) : "0");
|
|
}
|
|
String insertQry = "Insert Into " + NextIdTable + " (" + insertColumnValues.GetValues(StringPair.Value.Value1).Concat(",") + ") Values (" + insertColumnValues.GetValues(StringPair.Value.Value2).Concat(",") + ")";
|
|
SaLogger.Debug($"{SysUtil.Fn} Insert query: {insertQry}");
|
|
using (var dbConnection = CreateConnection())
|
|
using (var dbCommand = dbConnection.CreateCommand())
|
|
{
|
|
dbConnection.Open();
|
|
dbCommand.CommandType = System.Data.CommandType.Text;
|
|
dbCommand.CommandText = insertQry;
|
|
dbCommand.ExecuteNonQuery();
|
|
}
|
|
}
|
|
if (resultsSet != null) resultsSet.Dispose();
|
|
return new SysId(nextIdValue);
|
|
}
|
|
public override int GetNextIdFromTable(String objectName, String idColumn = "Id")
|
|
{
|
|
DataValue maxId = GetRowValue(objectName, "Max(" + idColumn + ")", "");
|
|
if (maxId != null && maxId.GetDataType() != DataValue.DataType.Unknown)
|
|
return Math.Max(0, (int)maxId.AsLong()) + 1;
|
|
return 1;
|
|
}
|
|
public override bool SetMinNextId(String objectName, SysId id, DbUpdateInfo dbUpdateInfo, bool databaseTable = true, String idColumn = "Id", bool force = false)
|
|
{
|
|
PopulateNextIdTableDfn();
|
|
|
|
throw new NotSupportedException($"{SysUtil.Fn} Not yet implemented.");
|
|
|
|
//return true;
|
|
}
|
|
private void PopulateNextIdTableDfn()
|
|
{
|
|
if (nextIdTableDfn != null && nextIdTableDfn.Name.Equals(NextIdTable)) return;
|
|
nextIdTableDfn = GetTableDfn(NextIdTable);
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Q u e r y D a t a b a s e
|
|
//-------------------------------------------------------------------
|
|
// Query records.
|
|
public override DbResultSet ExecuteQuery(String query)
|
|
{
|
|
ClearErrorState();
|
|
Log(SysUtil.Fn, "Query: " + query, SaMessageLevel.Debug);
|
|
try
|
|
{
|
|
return DbResultSet_DataReader.ExecuteQuery(this, query);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
SaLogger.Error($"{SysUtil.Fn} {ExceptionUtil.GetLogMessage(exc)}\nQuery:\n\t{String.Join("\n\t", query.ReplaceAll("\n\r", "\n").Split("\n"))}", true);
|
|
SetErrorState(exc.Message);
|
|
}
|
|
return null;
|
|
}
|
|
//-------------------------------------------------------------------
|
|
/// <summary>Execute a non-query statement and return the row count.</summary>
|
|
public override int ExecuteNonQuery(string query)
|
|
{
|
|
ClearErrorState();
|
|
Log(SysUtil.Fn, "Query: " + query, SaMessageLevel.Debug);
|
|
using (var dbConnection = CreateConnection())
|
|
using (var dbCommand = dbConnection.CreateCommand())
|
|
{
|
|
try
|
|
{
|
|
dbConnection.Open();
|
|
dbCommand.CommandType = System.Data.CommandType.Text;
|
|
dbCommand.CommandText = query;
|
|
return dbCommand.ExecuteNonQuery();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
SaLogger.Error($"{SysUtil.Fn} {ExceptionUtil.GetLogMessage(exc)}\nQuery:\n\t{String.Join("\n\t", query.ReplaceAll("\n\r", "\n").Split("\n"))}", true);
|
|
SetErrorState(exc.Message);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
//-------------------------------------------------------------------
|
|
/// <summary>Compile and execute an insert statement and return the row count.</summary>
|
|
public override int ExecuteInsert(String tableName, List<StringPair> columnNameValues)
|
|
{
|
|
ClearErrorState();
|
|
String query =
|
|
"INSERT INTO " + tableName + " " +
|
|
"(" + columnNameValues.GetValues(StringPair.Value.Value1).Concat(", ") + ") " +
|
|
"VALUES (" + columnNameValues.GetValues(StringPair.Value.Value2).Concat(", ") + ")";
|
|
Log(SysUtil.Fn, "Query: " + query, SaMessageLevel.Debug);
|
|
using (var dbConnection = CreateConnection())
|
|
using (var dbCommand = dbConnection.CreateCommand())
|
|
{
|
|
try
|
|
{
|
|
dbConnection.Open();
|
|
dbCommand.CommandType = System.Data.CommandType.Text;
|
|
dbCommand.CommandText = query;
|
|
return dbCommand.ExecuteNonQuery();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
SaLogger.Error($"{SysUtil.Fn} {ExceptionUtil.GetLogMessage(exc)}\nQuery:\n\t{String.Join("\n\t", query.ReplaceAll("\n\r", "\n").Split("\n"))}", true);
|
|
SetErrorState(exc.Message);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
//-------------------------------------------------------------------
|
|
/// <summary>Compile and execute an update statement and return the row count.</summary>
|
|
public override int ExecuteUpdate(String tableName, List<StringPair> columnNameValues, String filter)
|
|
{
|
|
ClearErrorState();
|
|
String query =
|
|
"UPDATE " + tableName + " " +
|
|
"SET " + columnNameValues.Concat("=").Concat(", ");
|
|
if (!StringUtil.IsEmpty(filter))
|
|
query += (String)" WHERE " + filter;
|
|
Log(SysUtil.Fn, "Query: " + query, SaMessageLevel.Debug);
|
|
using (var dbConnection = CreateConnection())
|
|
using (var dbCommand = dbConnection.CreateCommand())
|
|
{
|
|
try
|
|
{
|
|
dbConnection.Open();
|
|
dbCommand.CommandType = System.Data.CommandType.Text;
|
|
dbCommand.CommandText = query;
|
|
return dbCommand.ExecuteNonQuery();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
SaLogger.Error($"{SysUtil.Fn} {ExceptionUtil.GetLogMessage(exc)}\nQuery:\n\t{String.Join("\n\t", query.ReplaceAll("\n\r", "\n").Split("\n"))}", true);
|
|
SetErrorState(exc.Message);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
//-------------------------------------------------------------------
|
|
/// <summary>Compile and execute a delete statement and return the row count.</summary>
|
|
public override int ExecuteDelete(String tableName, String filter)
|
|
{
|
|
ClearErrorState();
|
|
String query = "DELETE FROM " + tableName;
|
|
if (!StringUtil.IsEmpty(filter))
|
|
query += " WHERE " + filter;
|
|
Log(SysUtil.Fn, "Query: " + query, SaMessageLevel.Debug);
|
|
using (var dbConnection = CreateConnection())
|
|
using (var dbCommand = dbConnection.CreateCommand())
|
|
{
|
|
try
|
|
{
|
|
dbConnection.Open();
|
|
dbCommand.CommandType = System.Data.CommandType.Text;
|
|
dbCommand.CommandText = query;
|
|
return dbCommand.ExecuteNonQuery();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
SaLogger.Error($"{SysUtil.Fn} {ExceptionUtil.GetLogMessage(exc)}\nQuery:\n\t{String.Join("\n\t", query.ReplaceAll("\n\r", "\n").Split("\n"))}", true);
|
|
SetErrorState(exc.Message);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
/// <summary>Retrieve specific row value.</summary>
|
|
public override DataValue GetRowValue(String tableName, String columnName, String filter)
|
|
{
|
|
ClearErrorState();
|
|
try
|
|
{
|
|
String colAlias = "DataValue";
|
|
String query = "SELECT " + columnName + " '" + colAlias + "' FROM " + tableName + (!StringUtil.IsEmpty(filter) ? " WHERE " + filter : "");
|
|
using (DbResultSet dbResultSet = DbResultSet_DataReader.ExecuteQuery(this, query))
|
|
{
|
|
if (dbResultSet.NextRecord())
|
|
return dbResultSet.GetRecordValues().GetValue(colAlias);
|
|
else if (dbResultSet.HasErrorState())
|
|
SetErrorState(dbResultSet.ErrorStateMessage);
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
SaLogger.Error($"{SysUtil.Fn} {ExceptionUtil.GetLogMessage(exc)}\n\tTable: {tableName}. Column: {columnName}. Filter: " + (!StringUtil.IsEmpty(filter) ? filter : "<none>"), true);
|
|
SetErrorState(exc.Message);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
/// <summary>Get row count from Table applying optional filter.</summary>
|
|
public override long GetRowCount(String tableName, String filter)
|
|
{
|
|
ClearErrorState();
|
|
DataValue dataValue = GetRowValue(tableName, "Count(*)", filter);
|
|
if (dataValue != null) return dataValue.AsLong();
|
|
return 0;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
/// <summary>Get calculated value from table - Sum, Min or Max.</summary>
|
|
public override DataValue GetRowValue(String tableName, String columnName, String filter, DbGetValueType getValueType)
|
|
{
|
|
ClearErrorState();
|
|
String fn = "";
|
|
if (getValueType == DbGetValueType.eDbValueSum)
|
|
fn = "SUM";
|
|
else if (getValueType == DbGetValueType.eDbValueMin)
|
|
fn = "MIN";
|
|
else if (getValueType == DbGetValueType.eDbValueMax)
|
|
fn = "MAX";
|
|
return GetRowValue(tableName, fn + "(" + columnName + ")", filter);
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// D a t a b a s e S c h e m a
|
|
//-------------------------------------------------------------------
|
|
// NB Always use ODBC connection for querying schema.
|
|
// eg. SQL Connection GetSchema('Indices') doesn't return index columns.
|
|
public override HashSet<String> GetTableNames(bool refresh = false)
|
|
{
|
|
lock (tableDfns)
|
|
{
|
|
// Only populate table names if not previously done.
|
|
if (!tableDfnsPopulated || refresh)
|
|
{
|
|
tableDfns.Clear();
|
|
using (DbConnection dbConnection = CreateConnection(true))
|
|
{
|
|
dbConnection.Open();
|
|
tableDfns.AddRange(GetTableDefinitions(dbConnection).ToDictionary(table => table.Name, table => table));
|
|
}
|
|
}
|
|
return tableDfns.Values.GetNames().ToHashSet(StringComparer.InvariantCultureIgnoreCase);
|
|
}
|
|
}
|
|
public override List<DbDfnTable> GetTableDfns(bool refresh = false)
|
|
{
|
|
lock (tableDfns)
|
|
{
|
|
if (refresh) ClearTableDfns();
|
|
// Only populate table names and/or table schemas where not previously done.
|
|
if (!tableDfnsPopulated || tableDfns.Count < 1 || tableDfns.Values.Any(table => !table.HasColumns()))
|
|
{
|
|
// Use a single connection for table and schema population.
|
|
using (DbConnection dbConnection = CreateConnection(true))
|
|
{
|
|
dbConnection.Open();
|
|
if (!tableDfnsPopulated || tableDfns.Count < 1)
|
|
{
|
|
tableDfns.Clear();
|
|
tableDfns.AddRange(GetTableDefinitions(dbConnection).ToDictionary(table => table.Name, table => table));
|
|
}
|
|
tableDfnsPopulated = true;
|
|
// Populate details for each table.
|
|
foreach (DbDfnTable table in tableDfns.Values)
|
|
{
|
|
if (!table.HasColumns())
|
|
{
|
|
PopulateTableColumns(dbConnection, table);
|
|
PopulateTableIndices(dbConnection, table);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return new List<DbDfnTable>(tableDfns.Values);
|
|
}
|
|
}
|
|
public void ClearTableDfns()
|
|
{
|
|
lock (tableDfns)
|
|
{
|
|
tableDfns.Clear();
|
|
tableDfnsPopulated = false;
|
|
}
|
|
}
|
|
public override DbDfnTable GetTableDfn(String tableName, bool refresh = false)
|
|
{
|
|
lock (tableDfns)
|
|
{
|
|
if (!tableDfns.Keys.Contains(tableName) || refresh)
|
|
{
|
|
// Remove current table definition.
|
|
tableDfns.Remove(tableName);
|
|
}
|
|
// Only populate the specified table if required.
|
|
DbDfnTable table = tableDfns.GetValueOrDefault(tableName);
|
|
if (table == null || !table.HasColumns())
|
|
{
|
|
using (DbConnection dbConnection = CreateConnection(true))
|
|
{
|
|
dbConnection.Open();
|
|
if (!tableDfns.ContainsKey(tableName))
|
|
tableDfns.AddRange(GetTableDefinitions(dbConnection, tableName).ToDictionary(table => table.Name, table => table));
|
|
table = tableDfns.GetValueOrDefault(tableName);
|
|
if (table != null && (!table.HasColumns() || refresh))
|
|
{
|
|
PopulateTableColumns(dbConnection, table);
|
|
PopulateTableIndices(dbConnection, table);
|
|
}
|
|
}
|
|
}
|
|
return tableDfns.GetValueOrDefault(tableName);
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
private static List<DbDfnTable> GetTableDefinitions(DbConnection dbConnection, String tableNameRestriction = null)
|
|
{
|
|
List<DbDfnTable> tables = new List<DbDfnTable>();
|
|
if (SacsSystem.DebugMode) SaLogger.Debug($"{SysUtil.Fn} Database: {dbConnection.Database}." + (!StringUtil.IsEmpty(tableNameRestriction) ? $" Table: {tableNameRestriction}." : ""));
|
|
String[] restrictions = new String[] { null, null, tableNameRestriction }; // database, owner, table name, type
|
|
using (DataTable tableSchema = dbConnection.GetSchema(OdbcMetaDataCollectionNames.Tables, restrictions))
|
|
{
|
|
//DataSet set = tableSchema.DataSet;
|
|
foreach (DataRow row in tableSchema.Rows)
|
|
{
|
|
//-----------------------------------------------------------
|
|
// Columns are: Name Size Data Type Values
|
|
// 1. TABLE_CAT 255 12 VarChar
|
|
// 2. TABLE_SCHEM 128 12 VarChar
|
|
// 3. TABLE_NAME 128 12 VarChar
|
|
// 4. TABLE_TYPE 128 12 VarChar 'SYSTEM TABLE' 'TABLE' 'VIEW'
|
|
// 'GLOBAL TEMPORARY' 'LOCAL TEMPORARY'
|
|
// 'ALIAS' 'SYNONYM'
|
|
// 5. REMARKS 254 12 VarChar
|
|
// TABLE_CATALOG is the SQL alternative to TABLE_CAT
|
|
// TABLE_QUALIFIER is the ODBC 2.0 alternative to TABLE_CAT (ODBC 3.0).
|
|
// TABLE_SCHEMA is the SQL alternative to TABLE_SCHEM
|
|
// TABLE_OWNER is the ODBC 2.0 alternative to TABLE_SCHEM (ODBC 3.0).
|
|
// Variations:
|
|
// Sage Line 50: TABLE_QUALIFIER, TABLE_OWNER, TABLE_NAME, TABLE_TYPE, REMARKS.
|
|
// Sybase Advantage: QUALIFIERNAME, OWNERNAME, TABLENAME, TYPENAME, REMARKS
|
|
//-----------------------------------------------------------
|
|
String database = String.Empty, schema = String.Empty, tableName = String.Empty, type = String.Empty, remarks = String.Empty;
|
|
foreach (DataColumn column in tableSchema.Columns)
|
|
{
|
|
String colName = column.ColumnName;
|
|
String value = row[colName].ToString();
|
|
if (colName.EqualsCI("TABLE_CAT") || colName.EqualsCI("TABLE_CATALOG") || colName.EqualsCI("TABLE_QUALIFIER") || colName.EqualsCI("QualifierName"))
|
|
database = value;
|
|
else if (colName.EqualsCI("TABLE_SCHEM") || colName.EqualsCI("TABLE_SCHEMA") || colName.EqualsCI("TABLE_OWNER") || colName.EqualsCI("OwnerName"))
|
|
schema = value;
|
|
else if (colName.EqualsCI("TABLE_NAME") || colName.EqualsCI("TableName"))
|
|
tableName = value;
|
|
else if (colName.EqualsCI("TABLE_TYPE") || colName.EqualsCI("TypeName"))
|
|
type = value;
|
|
else if (colName.EqualsCI("REMARKS"))
|
|
remarks = value;
|
|
else
|
|
SaLogger.Warn($"{SysUtil.Fn} Unrecognised column name: '{colName}'");
|
|
}
|
|
// TODO Why is Type sometimes "BASE TABLE"?
|
|
if (!StringUtil.IsEmpty(tableName) && (type.EqualsCI("Table") || type.EqualsCI("Base Table")) && (!schema.EqualsCI("sys") || !tableName.StartsWithCI("trace_xe_")))
|
|
{
|
|
#if DEBUG
|
|
//SaLogger.Trace($"{SysUtil.Fn} Database={database}, Schema={schema}, Table={tableName}, Type={type}");
|
|
#endif
|
|
tables.Add(new DbDfnTable(schema, tableName, remarks));
|
|
}
|
|
}
|
|
}
|
|
if (SacsSystem.DebugMode && tables.Exists(item => item == null))
|
|
Debugger.Break();
|
|
return tables.OrderBy(item => item.Name).ToList();
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
private void PopulateTableColumns(DbConnection dbConnection, DbDfnTable table)
|
|
{
|
|
//if (SacsSystem.DebugMode) SaLogger.Debug($"{SysUtil.Fn} Table: {table.Name}");
|
|
short columnPos = 0;
|
|
String[] restrictions = new String[] { null, table.Schema, table.Name, null }; // database, owner, table name, column name
|
|
using (DataTable columnSchema = dbConnection.GetSchema(OdbcMetaDataCollectionNames.Columns, restrictions))
|
|
{
|
|
foreach (DataRow row in columnSchema.Rows)
|
|
{
|
|
//-----------------------------------------------------------
|
|
// Columns are: Name Size Data Type Values
|
|
// 1. TABLE_CAT 255 12 VarChar
|
|
// 2. TABLE_SCHEM 128 12 VarChar
|
|
// 3. TABLE_NAME 128 12 VarChar
|
|
// 4. COLUMN_NAME 128 12 VarChar
|
|
// 5. DATA_TYPE 5 5 SmallInt
|
|
// 6. TYPE_NAME 64 12 VarChar
|
|
// 7. COLUMN_SIZE 10 4 Integer (Counter)
|
|
// 8. BUFFER_LENGTH 10 4 Integer (Counter)
|
|
// 9. DECIMAL_DIGITS 5 5 SmallInt
|
|
// 10. NUM_PREC_RADIX 5 5 SmallInt 10 or 2.
|
|
// 11. NULLABLE 5 5 SmallInt SQL_NO_NULLS,SQL_NULLABLE,SQL_NULLABLE_UNKNOWN
|
|
// 12. REMARKS 254 12 VarChar
|
|
// 13. COLUMN_DEF 128 12 VarChar Default value.
|
|
// 14. SQL_DATA_TYPE 5 5 SmallInt
|
|
// 15. SQL_DATETIME_SUB 5 5 SmallInt
|
|
// 16. CHAR_OCTET_LENGTH 10 4 Integer (Counter)
|
|
// 17. ORDINAL_POSITION 10 4 Integer (Counter)
|
|
// 18. IS_NULLABLE 128 12 VarChar 'YES' or 'NO'
|
|
// 19. ORDINAL 10 4 Integer (Counter)
|
|
// Alternative column names:
|
|
// ODBC 2.0 column ODBC 3.x column
|
|
// TABLE_QUALIFIER TABLE_CAT
|
|
// TABLE_OWNER TABLE_SCHEM
|
|
// PRECISION COLUMN_SIZE
|
|
// LENGTH BUFFER_LENGTH
|
|
// SCALE DECIMAL_DIGITS
|
|
// RADIX NUM_PREC_RADIX
|
|
// SQL Server columns:
|
|
// TABLE_CATALOG, TABLE_SCHEMA, ORDINAL_POSITION, COLUMN_DEFAULT
|
|
// CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH
|
|
// NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE, DATETIME_PRECISION
|
|
// CHARACTER_SET_CATALOG, CHARACTER_SET_SCHEMA, CHARACTER_SET_NAME, COLLATION_CATALOG
|
|
// IS_SPARSE, IS_COLUMN_SET, IS_FILESTREAM
|
|
// SQL Server columns returned by ODBC conection:
|
|
// NUM_PREC_RADIX, COLUMN_DEF, SQL_DATA_TYPE, SQL_DATETIME_SUB, CHAR_OCTET_LENGTH
|
|
// SS_IS_SPARSE, SS_IS_COLUMN_SET, SS_IS_COMPUTED, SS_UDT_CATALOG_NAME, SS_UDT_SCHEMA_NAME
|
|
// SS_UDT_ASSEMBLY_TYPE_NAME, SS_XML_SCHEMACOLLECTION_CATALOG_NAME, SS_XML_SCHEMACOLLECTION_SCHEMA_NAME, SS_XML_SCHEMACOLLECTION_NAME, SS_DATA_TYPE
|
|
// Sage ODBC data sources quote the following columns:
|
|
// TABLE_QUALIFIER,TABLE_OWNER,TABLE_NAME,COLUMN_NAME,DATA_TYPE,
|
|
// TYPE_NAME,PRECISION,LENGTH,SCALE,RADIX,NULLABLE,REMARKS
|
|
// Sybase Advantage data sources quote the following columns:
|
|
// QUALIFIERNAME,OWNERNAME,TABLENAME,colName,TYPE
|
|
// TYPENAME,PRECISION,LENGTH,SCALE,RADIX,NULLABLE
|
|
// REMARKS,DEFAULT,DATATYPE,DATETIME_SUBTYPE
|
|
// OCTET_LENGTH,ORDINAL_POSITION,IS_NULLABLE
|
|
// Notes.
|
|
// - SQL Connection doesn't show if a column is Identity.
|
|
// - Unclear how to deterine column size for datetime values between SQL and ODBC.
|
|
//-----------------------------------------------------------
|
|
String database = String.Empty, schema = String.Empty, tableName = String.Empty, columnName = String.Empty, nativeDataTypeName = String.Empty, remarks = String.Empty;
|
|
short nativeDataType = 0, decimalDigits = 0;
|
|
long columnSize = 0, bufferLen = 0;
|
|
DbColumnNullable nullable = DbColumnNullable.Unknown;
|
|
bool isIdentity = false, isNullable = false;
|
|
foreach (DataColumn column in columnSchema.Columns)
|
|
{
|
|
String colName = column.ColumnName;
|
|
String value = row[colName].ToString();
|
|
//if (columnName.EqualsCI("CreateOn")) SaLogger.Debug(GetType().Name+".PopulateTableColumns Schema column name: " + colName + " [" + value + "]");
|
|
if (colName.EqualsCI("TABLE_CAT") || colName.EqualsCI("TABLE_CATALOG") || colName.EqualsCI("TABLE_QUALIFIER") || colName.EqualsCI("QualifierName"))
|
|
database = value;
|
|
else if (colName.EqualsCI("TABLE_SCHEM") || colName.EqualsCI("TABLE_SCHEMA") || colName.EqualsCI("TABLE_OWNER") || colName.EqualsCI("OwnerName"))
|
|
schema = value;
|
|
else if (colName.EqualsCI("TABLE_NAME") || colName.EqualsCI("TableName"))
|
|
tableName = value;
|
|
else if (colName.EqualsCI("Column_Name") || colName.EqualsCI("ColumnName"))
|
|
columnName = value;
|
|
else if (colName.EqualsCI("Data_Type") || colName.EqualsCI("Type"))
|
|
{
|
|
if (value.IsNumeric(true))
|
|
nativeDataType = value.ToShort();
|
|
else
|
|
{
|
|
// SQL returns data type name (non numeric).
|
|
nativeDataTypeName = value;
|
|
nativeDataType = OdbcUtil.GetSqlNativeDataType(value);
|
|
}
|
|
}
|
|
else if (colName.EqualsCI("Type_Name") || colName.EqualsCI("TypeName"))
|
|
{
|
|
nativeDataTypeName = value;
|
|
if (value.EndsWith(" identity"))
|
|
{
|
|
nativeDataTypeName = value.Left(value.Length - " identity".Length);
|
|
isIdentity = true;
|
|
}
|
|
}
|
|
else if (colName.EqualsCI("Column_Size") || colName.EqualsCI("CHARACTER_MAXIMUM_LENGTH") || colName.EqualsCI("NUMERIC_PRECISION") || colName.EqualsCI("DATETIME_PRECISION") || colName.EqualsCI("Precision"))
|
|
{
|
|
if (!StringUtil.IsEmpty(value)) columnSize = value.ToLong();
|
|
if (colName.EqualsCI("CHARACTER_MAXIMUM_LENGTH") && value.Equals("-1")) columnSize = 0;
|
|
}
|
|
else if (colName.EqualsCI("Buffer_Length") || colName.EqualsCI("Length"))
|
|
{
|
|
if (!StringUtil.IsEmpty(value)) bufferLen = value.ToLong();
|
|
}
|
|
else if (colName.EqualsCI("Decimal_Digits") || colName.EqualsCI("Scale") || colName.EqualsCI("NUMERIC_SCALE"))
|
|
{
|
|
if (!StringUtil.IsEmpty(value)) decimalDigits = value.ToShort();
|
|
}
|
|
else if (colName.EqualsCI("Nullable"))
|
|
{
|
|
if (!StringUtil.IsEmpty(value)) nullable = (DbColumnNullable)value.ToShort();
|
|
}
|
|
else if (colName.EqualsCI("Is_Nullable"))
|
|
isNullable = !value.EqualsCI("No");
|
|
else if (colName.EqualsCI("REMARKS"))
|
|
remarks = value;
|
|
// SqlServer specific.
|
|
else if (colName.EqualsCI("ORDINAL_POSITION")) { }
|
|
else if (colName.EqualsCI("COLUMN_DEFAULT")) { }
|
|
else if (colName.EqualsCI("CHARACTER_OCTET_LENGTH")) { }
|
|
else if (colName.EqualsCI("NUMERIC_PRECISION_RADIX")) { }
|
|
else if (colName.EqualsCI("CHARACTER_SET_CATALOG")) { }
|
|
else if (colName.EqualsCI("CHARACTER_SET_SCHEMA")) { }
|
|
else if (colName.EqualsCI("CHARACTER_SET_NAME")) { }
|
|
else if (colName.EqualsCI("COLLATION_CATALOG")) { }
|
|
else if (colName.EqualsCI("IS_SPARSE")) { }
|
|
else if (colName.EqualsCI("IS_COLUMN_SET")) { }
|
|
else if (colName.EqualsCI("IS_FILESTREAM")) { }
|
|
// SQL Server ODBC.
|
|
else if (colName.EqualsCI("SS_IS_IDENTITY")) isIdentity = value.ToBool();
|
|
else if (colName.EqualsCI("NUM_PREC_RADIX")) { }
|
|
else if (colName.EqualsCI("COLUMN_DEF")) { }
|
|
else if (colName.EqualsCI("SQL_DATA_TYPE")) { }
|
|
else if (colName.EqualsCI("SQL_DATETIME_SUB")) { }
|
|
else if (colName.EqualsCI("CHAR_OCTET_LENGTH")) { }
|
|
else if (colName.EqualsCI("SS_IS_SPARSE")) { }
|
|
else if (colName.EqualsCI("SS_IS_COLUMN_SET")) { }
|
|
else if (colName.EqualsCI("SS_IS_COMPUTED")) { }
|
|
else if (colName.EqualsCI("SS_UDT_CATALOG_NAME")) { }
|
|
else if (colName.EqualsCI("SS_UDT_SCHEMA_NAME")) { }
|
|
else if (colName.EqualsCI("SS_UDT_ASSEMBLY_TYPE_NAME")) { }
|
|
else if (colName.EqualsCI("SS_XML_SCHEMACOLLECTION_CATALOG_NAME")) { }
|
|
else if (colName.EqualsCI("SS_XML_SCHEMACOLLECTION_SCHEMA_NAME")) { }
|
|
else if (colName.EqualsCI("SS_XML_SCHEMACOLLECTION_NAME")) { }
|
|
else if (colName.EqualsCI("SS_DATA_TYPE")) { }
|
|
// Unrecognised columns.
|
|
else SaLogger.Debug($"{SysUtil.Fn} Unrecognised Schema column name: {colName} [{value}]");
|
|
}
|
|
if (!StringUtil.IsEmpty(columnName))
|
|
{
|
|
//SaLogger.Debug(GetType().Name+".PopulateTableColumns Database=" + database + ", Schema=" + schema + ", Table=" + tableName + ", Column=" + columnName);
|
|
DbDfnColumn column = new DbDfnColumn(schema, tableName, ++columnPos, columnName);
|
|
column.DataTypeNative = nativeDataType;
|
|
column.DataTypeNameNative = nativeDataTypeName;
|
|
DbColumnDataType dataType = OdbcUtil.OdbcToDataType(nativeDataType);
|
|
column.DataType = dataType;
|
|
column.IsIdentity = isIdentity;
|
|
column.BufferLen = bufferLen;
|
|
column.Size = columnSize;
|
|
column.DecimalDigits = decimalDigits;
|
|
column.Nullable = nullable;
|
|
column.IsNullable = isNullable;
|
|
column.Remarks = remarks;
|
|
table.AddColumn(column);
|
|
}
|
|
}
|
|
}
|
|
// Additional logic for SQL connections.
|
|
SqlConnection sqlConnection = dbConnection as SqlConnection;
|
|
if (sqlConnection != null)
|
|
{
|
|
// Retrieve additional information via SqlDataReader.
|
|
using (SqlCommand sqlCommand = sqlConnection.CreateCommand())
|
|
{
|
|
sqlCommand.CommandText = "Select Top 1 * From [" + table.Name + "]";
|
|
using (SqlDataReader sqlDataReader = sqlCommand.ExecuteReader(CommandBehavior.SchemaOnly))
|
|
using (DataTable dataTable = sqlDataReader.GetSchemaTable())
|
|
{
|
|
foreach (DataRow row in dataTable.Rows)
|
|
{
|
|
String columnName = "";
|
|
bool isIdentity = false;
|
|
foreach (DataColumn col in dataTable.Columns)
|
|
{
|
|
String value = row[col].ToString();
|
|
if (col.ColumnName.EqualsCI("ColumnName")) columnName = value;
|
|
else if (col.ColumnName.EqualsCI("IsIdentity")) isIdentity = value.ToBool();
|
|
//if (columnName.EqualsCI("CreateOn")) SaLogger.Debug(GetType().Name+".PopulateTableColumns Column name: " + col.ColumnName + " [" + value + "]");
|
|
}
|
|
DbDfnColumn columnDfn = table.Columns.GetColumnByName(columnName);
|
|
if (columnDfn != null)
|
|
{
|
|
if (isIdentity) columnDfn.IsIdentity = isIdentity;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
private void PopulateTableIndices(DbConnection dbConnection, DbDfnTable table)
|
|
{
|
|
String[] restrictions = new String[] { null, table.Schema, table.Name }; // database, owner, table name
|
|
using (DataTable columnSchema = dbConnection.GetSchema(OdbcMetaDataCollectionNames.Indexes, restrictions))
|
|
{
|
|
foreach (DataRow row in columnSchema.Rows)
|
|
{
|
|
//---------------------------------------------------------
|
|
// Columns are: Name Size Data Type Values
|
|
// 1. TABLE_CAT 255 12 VarChar
|
|
// Catalog name of the table to which the statistic or index applies.
|
|
// 2. TABLE_SCHEM 128 12 VarChar
|
|
// Schema name of the table to which the statistic or index applies.
|
|
// 3. TABLE_NAME 128 12 VarChar
|
|
// Table name of the table to which the statistic or index applies.
|
|
// 4. NON_UNIQUE 5 5 SmallInt
|
|
// Indicates whether the index prohibits duplicate values (SQL_TRUE or SQL_FALSE).
|
|
// 5. INDEX_QUALIFIER VarChar
|
|
// The identifier that is used to qualify the index name doing a DROP INDEX.
|
|
// 6. INDEX_NAME VarChar Index name.
|
|
// 7. TYPE SmallInt
|
|
// Type of information being returned:
|
|
// 0 SQL_TABLE_STAT indicates a statistic for the table (in the CARDINALITY or PAGES column).
|
|
// ? SQL_INDEX_BTREE indicates a B-Tree index.
|
|
// 1 SQL_INDEX_CLUSTERED indicates a clustered index.
|
|
// ? SQL_INDEX_CONTENT indicates a content index.
|
|
// 2 SQL_INDEX_HASHED indicates a hashed index.
|
|
// 3 SQL_INDEX_OTHER indicates another type of index.
|
|
// 8. ORDINAL_POSITION SmallInt
|
|
// Column sequence number in index (starting with 1).
|
|
// 9. COLUMN_NAME VarChar
|
|
// Column name. If the column is based on an expression,
|
|
// such as SALARY + BENEFITS, the expression is returned.
|
|
// 10. ASC_OR_DESC Char(1)
|
|
// Sort sequence for the column: "A" for ascending; "D" for descending.
|
|
// 11. CARDINALITY Integer
|
|
// Number of rows in table if TYPE is SQL_TABLE_STAT.
|
|
// Number of unique values in the index if TYPE is not SQL_TABLE_STAT.
|
|
// 12. PAGES Integer
|
|
// Number of pages for the table if TYPE is SQL_TABLE_STAT.
|
|
// Number of pages for the index if TYPE is not SQL_TABLE_STAT.
|
|
// 13. FILTER_CONDITION VarChar
|
|
// If the index is a filtered index, this is the filter condition, such as 'SALARY > 30000'.
|
|
// Alternative column names:
|
|
// ODBC 2.0 column ODBC 3.x column
|
|
// TABLE_QUALIFIER TABLE_CAT
|
|
// TABLE_OWNER TABLE_SCHEM
|
|
// SEQ_IN_INDEX ORDINAL_POSITION
|
|
// COLLATION ASC_OR_DESC
|
|
// Sybase Advantage column names:
|
|
// QUALIFIERNAME,OWNERNAME,TABLENAME,NONUNIQUE
|
|
// INDEXQUALIFIERNAME,INDEXNAME,TYPE,SEQININDEX
|
|
// COLUMNNAME,COLLATION,CARDINALITY,PAGES,FILTER
|
|
//---------------------------------------------------------
|
|
String database = String.Empty, schema = String.Empty, tableName = String.Empty, indexQualifier = String.Empty, indexName = String.Empty, columnName = String.Empty, ascOrDesc = String.Empty, filterCondition = String.Empty;
|
|
bool unique = false, primary = false, clustered = false, nullable = false;
|
|
int indexType = 0;
|
|
short ordinalPos = 0;
|
|
int cardinality = 0, pages = 0;
|
|
foreach (DataColumn column in columnSchema.Columns)
|
|
{
|
|
String colName = column.ColumnName;
|
|
String value = row[colName].ToString();
|
|
if (colName.EqualsCI("TABLE_CAT") || colName.EqualsCI("TABLE_QUALIFIER") || colName.EqualsCI("QualifierName"))
|
|
database = value;
|
|
else if (colName.EqualsCI("TABLE_SCHEM") || colName.EqualsCI("TABLE_OWNER") || colName.EqualsCI("OwnerName"))
|
|
schema = value;
|
|
else if (colName.EqualsCI("TABLE_NAME") || colName.EqualsCI("TableName"))
|
|
tableName = value;
|
|
else if (colName.EqualsCI("NON_UNIQUE") || colName.EqualsCI("NONUNIQUE"))
|
|
unique = (value.ToShort() == 0);
|
|
else if (colName.EqualsCI("INDEX_QUALIFIER") || colName.EqualsCI("INDEXQUALIFIERNAME"))
|
|
indexQualifier = value;
|
|
else if (colName.EqualsCI("INDEX_NAME") || colName.EqualsCI("INDEXNAME"))
|
|
indexName = value;
|
|
else if (colName.EqualsCI("TYPE"))
|
|
indexType = value.ToInt();
|
|
else if (colName.EqualsCI("TYPE_DESC"))
|
|
{
|
|
if (value.EqualsCI("CLUSTERED"))
|
|
clustered = true;
|
|
}
|
|
else if (colName.EqualsCI("ORDINAL_POSITION") || colName.EqualsCI("SEQININDEX"))
|
|
ordinalPos = value.ToShort();
|
|
else if (colName.EqualsCI("Column_Name") || colName.EqualsCI("ColumnName"))
|
|
columnName = value;
|
|
else if (colName.EqualsCI("ASC_OR_DESC"))
|
|
ascOrDesc = value;
|
|
else if (colName.EqualsCI("CARDINALITY"))
|
|
cardinality = value.ToInt();
|
|
else if (colName.EqualsCI("PAGES"))
|
|
pages = value.ToInt();
|
|
else if (colName.EqualsCI("FILTER_CONDITION") || colName.EqualsCI("FILTER"))
|
|
filterCondition = value;
|
|
//else SaLogger.Debug(GetType().Name+".PopulateTableIndices Unrecognised Schema column name: "+colName);
|
|
//SaLogger.Debug(GetType().Name+".PopulateTableIndices Column name: " + colName+", Value="+value);
|
|
}
|
|
|
|
//-------------------------------------------------------
|
|
String debugIndex = "PK_SaAttrUpdate";
|
|
if (indexName.EqualsCI(debugIndex) && false)
|
|
{
|
|
/*
|
|
StockTracker Address table.
|
|
SQL:
|
|
Column: constraint_catalog. Value: SaStockTracker_Solent_STN
|
|
Column: constraint_schema. Value: dbo
|
|
Column: constraint_name. Value: PK_Address
|
|
Column: table_catalog. Value: SaStockTracker_Solent_STN
|
|
Column: table_schema. Value: dbo
|
|
Column: table_name. Value: Address
|
|
Column: index_name. Value: PK_Address
|
|
Column: type_desc. Value: CLUSTERED
|
|
ODBC:
|
|
Column: TABLE_CAT. Value: SaStockTracker_Solent_STN
|
|
Column: TABLE_SCHEM. Value: dbo
|
|
Column: TABLE_NAME. Value: Address
|
|
Column: NON_UNIQUE. Value: 0
|
|
Column: INDEX_QUALIFIER. Value: Address
|
|
Column: INDEX_NAME. Value: PK_Address
|
|
Column: TYPE. Value: 1
|
|
Column: ORDINAL_POSITION. Value: 1
|
|
Column: COLUMN_NAME. Value: Id
|
|
Column: ASC_OR_DESC. Value: A
|
|
Column: CARDINALITY. Value: 6
|
|
Column: PAGES. Value: 1
|
|
Column: FILTER_CONDITION. Value:
|
|
*/
|
|
foreach (DataColumn column in columnSchema.Columns)
|
|
{
|
|
String colName = column.ColumnName;
|
|
String value = row[colName].ToString();
|
|
SaLogger.Debug(debugIndex + " Column: " + colName + ". Value: " + value);
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------
|
|
if (!StringUtil.IsEmpty(indexName))
|
|
{
|
|
//SaLogger.Debug(GetType().Name+".PopulateTableIndices Database=" + database + ", Schema=" + schema + ", Table=" + tableName + ", Index="+indexName+", Column=" + columnName);
|
|
// Retrieve index or populate if not found.
|
|
DbDfnIndex index = table.GetIndexByName(indexName);
|
|
if (index == null)
|
|
{
|
|
index = new DbDfnIndex(schema, tableName, indexName, unique);
|
|
index.IndexType = indexType;
|
|
index.Primary = primary;
|
|
index.Clustered = clustered;
|
|
index.Nullable = nullable;
|
|
index.Pages = pages;
|
|
index.UniqueValues = cardinality;
|
|
table.AddIndex(index);
|
|
}
|
|
// Add column to index:
|
|
if (!StringUtil.IsEmpty(columnName))
|
|
{
|
|
DbDfnIndexColumn indexColumn = new DbDfnIndexColumn(ordinalPos, columnName, (!ascOrDesc.EqualsCI("D")));
|
|
index.AddColumn(indexColumn);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Query to list included columns.
|
|
// Select IndexName = i.Name, ColName = c.Name
|
|
// From sys.indexes i
|
|
// Inner Join sys.index_columns ic On ic.object_id = i.object_id And ic.index_id = i.index_id
|
|
// Inner Join sys.columns c On c.object_id = ic.object_id And c.column_id = ic.column_id
|
|
// Where ic.is_included_column = 1
|
|
// Order By i.Name
|
|
|
|
// Attempt to retrieve included columns (SQL only).
|
|
SqlConnection sqlConnection = dbConnection as SqlConnection;
|
|
if (sqlConnection != null)
|
|
{
|
|
using (DataTable columnSchema = dbConnection.GetSchema("IndexColumns", restrictions))
|
|
{
|
|
foreach (DataRow row in columnSchema.Rows)
|
|
{
|
|
foreach (DataColumn column in columnSchema.Columns)
|
|
{
|
|
String colName = column.ColumnName;
|
|
String value = row[colName].ToString();
|
|
String constraintCatalog, constraintSchema, constraintName, tableCatalog, tableSchema, tableName, columnName, ordinalPosition, keyType, indexName;
|
|
#if DEBUG
|
|
//SaLogger.Trace(fn+" Column name=" + colName);
|
|
#endif
|
|
if (colName.EqualsCI("constraint_catalog"))
|
|
constraintCatalog = value;
|
|
else if (colName.EqualsCI("constraint_schema"))
|
|
constraintSchema = value;
|
|
else if (colName.EqualsCI("constraint_name"))
|
|
constraintName = value;
|
|
else if (colName.EqualsCI("table_catalog"))
|
|
tableCatalog = value;
|
|
else if (colName.EqualsCI("table_schema"))
|
|
tableSchema = value;
|
|
else if (colName.EqualsCI("table_name"))
|
|
tableName = value;
|
|
else if (colName.EqualsCI("column_name"))
|
|
columnName = value;
|
|
else if (colName.EqualsCI("ordinal_position"))
|
|
ordinalPosition = value;
|
|
else if (colName.EqualsCI("KeyType"))
|
|
keyType = value;
|
|
else if (colName.EqualsCI("index_name"))
|
|
indexName = value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
}
|
|
//=======================================================================
|
|
}
|