DocSpace-buildtools/common/ASC.Data.Backup.Core/Tasks/Modules/ModuleSpecificsBase.cs

269 lines
8.6 KiB
C#
Raw Normal View History

namespace ASC.Data.Backup.Tasks.Modules;
public abstract class ModuleSpecificsBase : IModuleSpecifics
2020-05-20 15:14:44 +00:00
{
public abstract ModuleName ModuleName { get; }
public abstract IEnumerable<TableInfo> Tables { get; }
public abstract IEnumerable<RelationInfo> TableRelations { get; }
public virtual string ConnectionStringName
=> _connectionStringName ??= ModuleName.ToString().ToLower();
private string _connectionStringName;
private readonly Helpers _helpers;
2022-01-24 09:57:01 +00:00
protected ModuleSpecificsBase(Helpers helpers)
2020-05-20 15:14:44 +00:00
{
_helpers = helpers;
}
public IEnumerable<TableInfo> GetTablesOrdered()
{
var notOrderedTables = new List<TableInfo>(Tables);
2022-02-09 18:33:50 +00:00
var totalTablesCount = notOrderedTables.Count;
var orderedTablesCount = 0;
while (orderedTablesCount < totalTablesCount)
2020-05-20 15:14:44 +00:00
{
var orderedTablesCountBeforeIter = orderedTablesCount; // ensure we not in infinite loop...
2020-05-20 15:14:44 +00:00
var i = 0;
while (i < notOrderedTables.Count)
2020-05-20 15:14:44 +00:00
{
var table = notOrderedTables[i];
2020-05-20 15:14:44 +00:00
var parentTables = TableRelations
.Where(x => x.FitsForTable(table.Name) && !x.IsExternal() && !x.IsSelfRelation() && x.Importance != RelationImportance.Low)
.Select(x => x.ParentTable);
if (parentTables.All(x => notOrderedTables.All(y => !string.Equals(y.Name, x, StringComparison.InvariantCultureIgnoreCase))))
2020-05-20 15:14:44 +00:00
{
notOrderedTables.RemoveAt(i);
orderedTablesCount++;
2020-05-20 15:14:44 +00:00
yield return table;
}
else
2022-02-09 18:33:50 +00:00
{
i++;
2022-02-09 18:33:50 +00:00
}
2020-05-20 15:14:44 +00:00
}
if (orderedTablesCountBeforeIter == orderedTablesCount) // ensure we not in infinite loop...
2022-02-09 16:46:09 +00:00
{
throw ThrowHelper.CantOrderTables(notOrderedTables.Select(x => x.Name));
2022-02-09 16:46:09 +00:00
}
}
}
2020-05-20 15:14:44 +00:00
public DbCommand CreateSelectCommand(DbConnection connection, int tenantId, TableInfo table, int limit, int offset)
{
var command = connection.CreateCommand();
command.CommandText = string.Format("select t.* from {0} as t {1} limit {2},{3};", table.Name, GetSelectCommandConditionText(tenantId, table), offset, limit);
2020-05-20 15:14:44 +00:00
return command;
}
2020-05-20 15:14:44 +00:00
public DbCommand CreateDeleteCommand(DbConnection connection, int tenantId, TableInfo table)
{
var command = connection.CreateCommand();
2022-01-14 13:12:37 +00:00
command.CommandText = $"delete t.* from {table.Name} as t {GetDeleteCommandConditionText(tenantId, table)};";
2022-02-09 18:33:50 +00:00
return command;
}
2022-02-09 18:33:50 +00:00
public DbCommand CreateInsertCommand(bool dump, DbConnection connection, ColumnMapper columnMapper, TableInfo table, DataRowInfo row)
{
if (table.InsertMethod == InsertMethod.None)
{
return null;
2020-05-20 15:14:44 +00:00
}
2022-02-09 18:33:50 +00:00
if (!TryPrepareRow(dump, connection, columnMapper, table, row, out var valuesForInsert))
2020-05-26 08:52:47 +00:00
{
return null;
}
2020-05-20 15:14:44 +00:00
var columns = valuesForInsert.Keys.Intersect(table.Columns).ToArray();
2022-01-14 13:12:37 +00:00
var insert = table.InsertMethod != InsertMethod.Ignore
? table.InsertMethod.ToString().ToLower()
2022-01-14 13:12:37 +00:00
: "insert ignore";
var insertCommantText = $"{insert} into {table.Name}({string.Join(",", columns)}) values({string.Join(",", columns.Select(c => "@" + c))});";
2022-02-09 18:33:50 +00:00
var command = connection.CreateCommand();
command.CommandText = insertCommantText;
foreach (var parameter in valuesForInsert)
{
AddParameter(command, parameter.Key, parameter.Value);
2020-05-26 08:52:47 +00:00
}
return command;
}
public DbCommand AddParameter(DbCommand command, string name, object value)
{
var p = command.CreateParameter();
if (!string.IsNullOrEmpty(name))
2020-05-26 08:52:47 +00:00
{
Merge branch 'feature/backend-refactor' into feature/asc-backup-core-refactor # Conflicts: # common/ASC.Data.Backup.Core/ActionInvoker.cs # common/ASC.Data.Backup.Core/BackupAjaxHandler.cs # common/ASC.Data.Backup.Core/Core/DbBackupProvider.cs # common/ASC.Data.Backup.Core/Core/DbHelper.cs # common/ASC.Data.Backup.Core/Core/FileBackupProvider.cs # common/ASC.Data.Backup.Core/Core/NotifyHelper.cs # common/ASC.Data.Backup.Core/Core/ZipOperator.cs # common/ASC.Data.Backup.Core/Exceptions/ThrowHelper.cs # common/ASC.Data.Backup.Core/Extensions/EnumerableExtensions.cs # common/ASC.Data.Backup.Core/Service/BackupWorker.cs # common/ASC.Data.Backup.Core/Storage/DocumentsBackupStorage.cs # common/ASC.Data.Backup.Core/Tasks/BackupPortalTask.cs # common/ASC.Data.Backup.Core/Tasks/ColumnMapper.cs # common/ASC.Data.Backup.Core/Tasks/Data/DataRowInfo.cs # common/ASC.Data.Backup.Core/Tasks/Data/TableInfo.cs # common/ASC.Data.Backup.Core/Tasks/DeletePortalTask.cs # common/ASC.Data.Backup.Core/Tasks/KeyHelper.cs # common/ASC.Data.Backup.Core/Tasks/Modules/MailModuleSpecifics.cs # common/ASC.Data.Backup.Core/Tasks/Modules/ModuleProvider.cs # common/ASC.Data.Backup.Core/Tasks/Modules/ModuleSpecificsBase.cs # common/ASC.Data.Backup.Core/Tasks/Modules/ProjectsModuleSpecifics.cs # common/ASC.Data.Backup.Core/Tasks/PortalTaskBase.cs # common/ASC.Data.Backup.Core/Tasks/RestoreDbModuleTask.cs # common/ASC.Data.Backup.Core/Tasks/RestorePortalTask.cs # common/ASC.Data.Backup.Core/Tasks/TransferPortalTask.cs
2022-02-15 16:56:43 +00:00
p.ParameterName = name.StartsWith('@') ? name : "@" + name;
}
2020-05-26 08:52:47 +00:00
p.Value = GetParameterValue(value);
2020-05-26 08:52:47 +00:00
command.Parameters.Add(p);
2022-02-09 18:33:50 +00:00
return command;
}
2022-02-09 18:33:50 +00:00
public object GetParameterValue(object value)
{
if (value == null)
2020-05-20 15:14:44 +00:00
{
return DBNull.Value;
2020-05-20 15:14:44 +00:00
}
if (value is Enum @enum)
2022-02-09 18:33:50 +00:00
{
return @enum.ToString("d");
2022-02-09 18:33:50 +00:00
}
if (value is DateTime d)
2022-02-09 18:33:50 +00:00
{
return new DateTime(d.Year, d.Month, d.Day, d.Hour, d.Minute, d.Second, DateTimeKind.Unspecified);
2022-02-09 18:33:50 +00:00
}
return value;
}
2020-05-20 15:14:44 +00:00
public virtual bool TryAdjustFilePath(bool dump, ColumnMapper columnMapper, ref string filePath)
{
return true;
}
public virtual void PrepareData(DataTable data)
{
// nothing to do
}
public virtual Stream PrepareData(string key, Stream stream, ColumnMapper columnMapper)
{
return stream;
}
2020-05-20 15:14:44 +00:00
protected virtual string GetSelectCommandConditionText(int tenantId, TableInfo table)
{
if (!table.HasTenantColumn())
2020-05-20 15:14:44 +00:00
{
throw ThrowHelper.CantDetectTenant(table.Name);
2020-05-20 15:14:44 +00:00
}
return string.Format("where t.{0} = {1}", table.TenantColumn, tenantId);
}
2020-05-20 15:14:44 +00:00
protected virtual string GetDeleteCommandConditionText(int tenantId, TableInfo table)
{
return GetSelectCommandConditionText(tenantId, table);
}
protected virtual bool TryPrepareRow(bool dump, DbConnection connection, ColumnMapper columnMapper, TableInfo table, DataRowInfo row, out Dictionary<string, object> preparedRow)
{
preparedRow = new Dictionary<string, object>();
2020-05-20 15:14:44 +00:00
var parentRelations = TableRelations
.Where(x => x.FitsForRow(row) && x.Importance != RelationImportance.Low)
.GroupBy(x => x.ChildColumn)
.ToDictionary(x => x.Key);
foreach (var columnName in row.ColumnNames)
{
if (table.IdType == IdType.Autoincrement && columnName.Equals(table.IdColumn, StringComparison.OrdinalIgnoreCase))
2020-05-20 15:14:44 +00:00
{
continue;
}
2020-05-20 15:14:44 +00:00
var val = row[columnName];
if (!parentRelations.ContainsKey(columnName))
{
if (!TryPrepareValue(connection, columnMapper, table, columnName, ref val))
2020-05-20 15:14:44 +00:00
{
return false;
2020-05-20 15:14:44 +00:00
}
}
else
{
if (!TryPrepareValue(dump, connection, columnMapper, table, columnName, parentRelations[columnName], ref val))
2020-05-20 15:14:44 +00:00
{
return false;
2020-05-20 15:14:44 +00:00
}
if (!table.HasIdColumn() && !table.HasTenantColumn() && val == row[columnName])
2022-02-09 16:46:09 +00:00
{
2020-05-20 15:14:44 +00:00
return false;
2022-02-09 16:46:09 +00:00
}
}
2022-02-09 16:46:09 +00:00
preparedRow.Add(columnName, val);
}
2022-02-09 18:33:50 +00:00
return true;
}
2020-05-20 15:14:44 +00:00
protected virtual bool TryPrepareValue(DbConnection connection, ColumnMapper columnMapper, TableInfo table, string columnName, ref object value)
{
if (columnName.Equals(table.TenantColumn, StringComparison.OrdinalIgnoreCase))
{
var tenantMapping = columnMapper.GetTenantMapping();
if (tenantMapping < 1)
2020-05-20 15:14:44 +00:00
{
return false;
}
2022-02-09 16:46:09 +00:00
value = tenantMapping;
2022-02-09 18:33:50 +00:00
return true;
}
2020-05-20 15:14:44 +00:00
if (table.UserIDColumns.Any(x => columnName.Equals(x, StringComparison.OrdinalIgnoreCase)))
{
var strVal = Convert.ToString(value);
var userMapping = columnMapper.GetUserMapping(strVal);
if (userMapping == null)
2022-02-09 16:46:09 +00:00
{
return _helpers.IsEmptyOrSystemUser(strVal);
2022-02-09 16:46:09 +00:00
}
2020-05-20 15:14:44 +00:00
value = userMapping;
2020-05-20 15:14:44 +00:00
return true;
}
var mapping = columnMapper.GetMapping(table.Name, columnName, value);
if (mapping != null)
2020-05-20 15:14:44 +00:00
{
value = mapping;
2020-05-20 15:14:44 +00:00
}
return true;
}
2022-02-09 18:33:50 +00:00
protected virtual bool TryPrepareValue(bool dump, DbConnection connection, ColumnMapper columnMapper, TableInfo table, string columnName, IEnumerable<RelationInfo> relations, ref object value)
{
return TryPrepareValue(connection, columnMapper, relations.Single(), ref value);
}
2021-08-31 09:40:28 +00:00
protected virtual bool TryPrepareValue(DbConnection connection, ColumnMapper columnMapper, RelationInfo relation, ref object value)
{
var mappedValue = columnMapper.GetMapping(relation.ParentTable, relation.ParentColumn, value);
if (mappedValue != null)
{
value = mappedValue;
return true;
2020-05-20 15:14:44 +00:00
}
return value == null ||
Guid.TryParse(Convert.ToString(value), out _) ||
int.TryParse(Convert.ToString(value), out _);
2020-05-20 15:14:44 +00:00
}
}