Saxonite v1.2.3

This commit is contained in:
2022-02-16 11:18:53 +00:00
parent 51df9e1ff6
commit 966204d643
11 changed files with 478 additions and 197 deletions
+152 -139
View File
@@ -22,14 +22,14 @@ namespace Sarand.Net.Standard.Dbas.Data
// Data members.
private String sqlConnectionString = "";
private readonly List<DbDfnTable> tables = new List<DbDfnTable>();
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";
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)
public SacsDatabaseOdbc(DbmsType dbms, String databaseName, String connectionString) : base(dbms, databaseName, connectionString)
{
if (dbms == DbmsType.MsSql)
sqlConnectionString = connectionString;
@@ -50,16 +50,16 @@ namespace Sarand.Net.Standard.Dbas.Data
//-------------------------------------------------------------------
// Connection.
public override void OnConnectionChanged ()
public override void OnConnectionChanged()
{
}
public override DbConnection CreateConnection (bool forceOdbc = false)
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 ()
public override DbDataAdapter CreateDataAdapter()
{
return new OdbcDataAdapter();
}
@@ -68,17 +68,17 @@ namespace Sarand.Net.Standard.Dbas.Data
// 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")
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 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));
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;
@@ -87,7 +87,7 @@ namespace Sarand.Net.Standard.Dbas.Data
qry.Columns.Add(colNextId, colAliasNextId);
qry.Filters.Add(filter);
//SaLogger.Debug(GetType().Name + ".GetNextId Query: " + qry.BuildQuery());
DbResultSet_DataReader resultsSet = DbResultSet_DataReader.ExecuteQuery(this,qry.BuildQuery());
DbResultSet_DataReader resultsSet = DbResultSet_DataReader.ExecuteQuery(this, qry.BuildQuery());
if (resultsSet != null && resultsSet.NextRecord())
{
NamedValue.Map values = resultsSet.GetRecordValues();
@@ -132,7 +132,7 @@ namespace Sarand.Net.Standard.Dbas.Data
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(",") + ")";
String insertQry = "Insert Into " + NextIdTable + " (" + insertColumnValues.GetValues(StringPair.Value.Value1).Concat(",") + ") Values (" + insertColumnValues.GetValues(StringPair.Value.Value2).Concat(",") + ")";
SaLogger.Debug(GetType().Name + ".GetNextId Insert query: " + insertQry);
using (var dbConnection = CreateConnection())
using (var dbCommand = dbConnection.CreateCommand())
@@ -153,7 +153,7 @@ namespace Sarand.Net.Standard.Dbas.Data
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)
public override bool SetMinNextId(String objectName, SysId id, DbUpdateInfo dbUpdateInfo, bool databaseTable = true, String idColumn = "Id", bool force = false)
{
PopulateNextIdTableDfn();
@@ -161,7 +161,7 @@ namespace Sarand.Net.Standard.Dbas.Data
//return true;
}
private void PopulateNextIdTableDfn ()
private void PopulateNextIdTableDfn()
{
if (nextIdTableDfn != null && nextIdTableDfn.Name.Equals(NextIdTable)) return;
nextIdTableDfn = GetTableDfn(NextIdTable);
@@ -171,7 +171,7 @@ namespace Sarand.Net.Standard.Dbas.Data
// Q u e r y D a t a b a s e
//-------------------------------------------------------------------
// Query records.
public override IDbDataTable ExecuteQuery (String query)
public override IDbDataTable ExecuteQuery(String query)
{
String fn = GetType().Name + ".ExecuteQuery";
ClearErrorState();
@@ -198,7 +198,7 @@ namespace Sarand.Net.Standard.Dbas.Data
}
//-------------------------------------------------------------------
/// <summary>Execute a non-query statement and return the row count.</summary>
public override int ExecuteNonQuery (string query)
public override int ExecuteNonQuery(string query)
{
String fn = GetType().Name + ".ExecuteNonQuery";
ClearErrorState();
@@ -223,7 +223,7 @@ namespace Sarand.Net.Standard.Dbas.Data
}
//-------------------------------------------------------------------
/// <summary>Compile and execute an insert statement and return the row count.</summary>
public override int ExecuteInsert (String tableName, List<StringPair> columnNameValues)
public override int ExecuteInsert(String tableName, List<StringPair> columnNameValues)
{
String fn = GetType().Name + ".ExecuteInsert";
ClearErrorState();
@@ -252,7 +252,7 @@ namespace Sarand.Net.Standard.Dbas.Data
}
//-------------------------------------------------------------------
/// <summary>Compile and execute an update statement and return the row count.</summary>
public override int ExecuteUpdate (String tableName, List<StringPair> columnNameValues, String filter)
public override int ExecuteUpdate(String tableName, List<StringPair> columnNameValues, String filter)
{
String fn = GetType().Name + ".ExecuteUpdate";
ClearErrorState();
@@ -282,7 +282,7 @@ namespace Sarand.Net.Standard.Dbas.Data
}
//-------------------------------------------------------------------
/// <summary>Compile and execute a delete statement and return the row count.</summary>
public override int ExecuteDelete (String tableName, String filter)
public override int ExecuteDelete(String tableName, String filter)
{
String fn = GetType().Name + ".ExecuteDelete";
ClearErrorState();
@@ -311,13 +311,13 @@ namespace Sarand.Net.Standard.Dbas.Data
//-------------------------------------------------------------------
/// <summary>Retrieve specific row value.</summary>
public override DataValue GetRowValue (String tableName, String columnName, String filter)
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:"");
String query = "SELECT " + columnName + " '" + colAlias + "' FROM " + tableName + (!StringUtil.IsEmpty(filter) ? " WHERE " + filter : "");
using (DbResultSet dbResultSet = DbResultSet_DataReader.ExecuteQuery(this, query))
{
if (dbResultSet.NextRecord())
@@ -336,7 +336,7 @@ namespace Sarand.Net.Standard.Dbas.Data
//-------------------------------------------------------------------
/// <summary>Get row count from Table applying optional filter.</summary>
public override long GetRowCount (String tableName, String filter)
public override long GetRowCount(String tableName, String filter)
{
ClearErrorState();
DataValue dataValue = GetRowValue(tableName, "Count(*)", filter);
@@ -346,7 +346,7 @@ namespace Sarand.Net.Standard.Dbas.Data
//-------------------------------------------------------------------
/// <summary>Get calculated value from table - Sum, Min or Max.</summary>
public override DataValue GetRowValue (String tableName, String columnName, String filter, DbGetValueType getValueType)
public override DataValue GetRowValue(String tableName, String columnName, String filter, DbGetValueType getValueType)
{
ClearErrorState();
String fn = "";
@@ -364,143 +364,156 @@ namespace Sarand.Net.Standard.Dbas.Data
//-------------------------------------------------------------------
// NB Always use ODBC connection for querying schema.
// eg. SQL Connection GetSchema('Indices') doesn't return index columns.
public override List<String> GetTableNames (bool refresh = false)
public override List<String> GetTableNames(bool refresh = false)
{
// Only populate table names if not previously done.
if (tables.Count < 1 || refresh)
lock (tables)
{
tables.Clear();
using (DbConnection dbConnection = CreateConnection(true))
// Only populate table names if not previously done.
if (tables.Count < 1 || refresh)
{
dbConnection.Open();
PopulateTableNames(dbConnection);
}
}
return tables.GetNames();
}
public override List<DbDfnTable> GetTableDfns (bool refresh = false)
{
if (refresh) ClearTableDfns();
// Only populate table names and/or table schemas where not previously done.
if (tables.Count < 1 || tables.Exists(item => !item.HasColumns()))
{
// Use a single connection for table and schaema population.
using (DbConnection dbConnection = CreateConnection(true))
{
dbConnection.Open();
if (tables.Count < 1)
PopulateTableNames(dbConnection);
foreach (DbDfnTable table in tables.ToList())
tables.Clear();
using (DbConnection dbConnection = CreateConnection(true))
{
if (!table.HasColumns())
dbConnection.Open();
PopulateTableNames(dbConnection);
}
}
return tables.GetNames();
}
}
public override List<DbDfnTable> GetTableDfns(bool refresh = false)
{
lock (tables)
{
if (refresh) ClearTableDfns();
// Only populate table names and/or table schemas where not previously done.
if (tables.Count < 1 || tables.Exists(item => !item.HasColumns()))
{
// Use a single connection for table and schaema population.
using (DbConnection dbConnection = CreateConnection(true))
{
dbConnection.Open();
if (tables.Count < 1)
PopulateTableNames(dbConnection);
foreach (DbDfnTable table in tables.ToList())
{
if (!table.HasColumns())
{
PopulateTableColumns(dbConnection, table);
PopulateTableIndices(dbConnection, table);
}
}
}
}
return tables.ToList();
}
}
public void ClearTableDfns()
{
lock (tables)
tables.Clear();
}
public override DbDfnTable GetTableDfn(String tableName, bool refresh = false)
{
lock (tables)
{
if (!tables.GetNames().Contains(tableName) || refresh)
{
// Remove current table definition.
tables.RemoveAll(item => item.Name.EqualsCI(tableName));
}
// Only populate the specified table if required.
if (!tables.Exists(item => item.Name.EqualsCI(tableName) && item.Columns.Count > 0))
{
using (DbConnection dbConnection = CreateConnection(true))
{
dbConnection.Open();
if (!tables.Exists(item => item.Name.EqualsCI(tableName)))
PopulateTableNames(dbConnection, tableName);
DbDfnTable table = tables.GetTableByName(tableName);
if (table != null && (!table.HasColumns() || refresh))
{
PopulateTableColumns(dbConnection, table);
PopulateTableIndices(dbConnection, table);
}
}
}
return tables.GetTableByName(tableName);
}
return tables.ToList();
}
public void ClearTableDfns ()
{
tables.Clear();
}
public override DbDfnTable GetTableDfn (String tableName, bool refresh = false)
{
if (!tables.GetNames().Contains(tableName) || refresh)
{
// Remove current table definition.
tables.RemoveAll(item => item.Name.EqualsCI(tableName));
}
// Only populate the specified table if required.
if (!tables.Exists(item => item.Name.EqualsCI(tableName) && item.Columns.Count > 0))
{
using (DbConnection dbConnection = CreateConnection(true))
{
dbConnection.Open();
if (!tables.Exists(item => item.Name.EqualsCI(tableName)))
PopulateTableNames(dbConnection, tableName);
DbDfnTable table = tables.GetTableByName(tableName);
if (table != null && (!table.HasColumns() || refresh))
{
PopulateTableColumns(dbConnection, table);
PopulateTableIndices(dbConnection, table);
}
}
}
return tables.GetTableByName(tableName);
}
//-------------------------------------------------------------------
private void PopulateTableNames (DbConnection dbConnection, String tableNameRestriction = null)
private void PopulateTableNames(DbConnection dbConnection, String tableNameRestriction = null)
{
if (StringUtil.IsEmpty(tableNameRestriction) && tables.Count > 0) return;
if (!StringUtil.IsEmpty(tableNameRestriction) && tables.Exists(item => item.Name.Equals(tableNameRestriction))) return;
String fn = GetType().Name+".PopulateTableNames";
if (SacsSystem.DebugMode) SaLogger.Debug(fn + (!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))
lock (tables)
{
//DataSet set = tableSchema.DataSet;
foreach (DataRow row in tableSchema.Rows)
if (StringUtil.IsEmpty(tableNameRestriction) && tables.Count > 0) return;
if (!StringUtil.IsEmpty(tableNameRestriction) && tables.Exists(item => item.Name.Equals(tableNameRestriction))) return;
String fn = GetType().Name + ".PopulateTableNames";
if (SacsSystem.DebugMode) SaLogger.Debug(fn + (!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))
{
//-----------------------------------------------------------
// 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(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.Left(9).EqualsCI("trace_xe_")))
//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(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.Left(9).EqualsCI("trace_xe_")))
{
#if DEBUG
//SaLogger.Trace(fn+" Database="+database+", Schema="+schema+", Table="+tableName+", Type="+ type);
//SaLogger.Trace(fn+" Database="+database+", Schema="+schema+", Table="+tableName+", Type="+ type);
#endif
tables.Add(new DbDfnTable(schema, tableName, remarks));
tables.Add(new DbDfnTable(schema, tableName, remarks));
}
}
}
List<DbDfnTable> tablesUnsorted = tables.ToList();
if (SacsSystem.DebugMode && tablesUnsorted.Exists(item => item == null))
Debugger.Break();
tables.Clear();
tables.AddRange(tablesUnsorted.OrderBy(item => item.Name).ToList());
}
List<DbDfnTable> tablesUnsorted = tables.ToList();
if (SacsSystem.DebugMode && tablesUnsorted.Exists(item => item == null))
Debugger.Break();
tables.Clear();
tables.AddRange(tablesUnsorted.OrderBy(item => item.Name).ToList());
}
//-------------------------------------------------------------------
private void PopulateTableColumns (DbConnection dbConnection, DbDfnTable table)
private void PopulateTableColumns(DbConnection dbConnection, DbDfnTable table)
{
String fn = GetType().Name+".PopulateTableColumns";
String fn = GetType().Name + ".PopulateTableColumns";
if (SacsSystem.DebugMode) SaLogger.Debug(fn + " Table: " + table.Name);
short columnPos = 0;
String[] restrictions = new String[] { null, table.Schema, table.Name, null }; // database, owner, table name, column name
@@ -703,9 +716,9 @@ namespace Sarand.Net.Standard.Dbas.Data
}
//-------------------------------------------------------------------
private void PopulateTableIndices (DbConnection dbConnection, DbDfnTable table)
private void PopulateTableIndices(DbConnection dbConnection, DbDfnTable table)
{
String fn = GetType().Name+".PopulateTableIndices";
String fn = GetType().Name + ".PopulateTableIndices";
String[] restrictions = new String[] { null, table.Schema, table.Name }; // database, owner, table name
using (DataTable columnSchema = dbConnection.GetSchema(OdbcMetaDataCollectionNames.Indexes, restrictions))
{