2020-05-20 15:14:44 +00:00
/ *
*
* ( c ) Copyright Ascensio System Limited 2010 - 2020
*
* This program is freeware . You can redistribute it and / or modify it under the terms of the GNU
* General Public License ( GPL ) version 3 as published by the Free Software Foundation ( https : //www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7 ( a ) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non - infringement of any third - party rights .
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY ; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE . For more details , see GNU GPL at https : //www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales @onlyoffice . com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices , as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3 ( b ) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software . If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons , you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute .
* Pursuant to Section 7 § 3 ( e ) we decline to grant you any rights under trademark law for use of our trademarks .
*
* /
2022-02-09 18:49:52 +00:00
namespace ASC.Data.Backup.Tasks.Modules ;
public abstract class ModuleSpecificsBase : IModuleSpecifics
2020-05-20 15:14:44 +00:00
{
2022-02-09 18:49:52 +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 ;
public ModuleSpecificsBase ( Helpers helpers )
2020-05-20 15:14:44 +00:00
{
2022-02-09 18:49:52 +00:00
_helpers = helpers ;
}
public IEnumerable < TableInfo > GetTablesOrdered ( )
{
var notOrderedTables = new List < TableInfo > ( Tables ) ;
2022-02-09 18:33:50 +00:00
2022-02-09 18:49:52 +00:00
var totalTablesCount = notOrderedTables . Count ;
var orderedTablesCount = 0 ;
while ( orderedTablesCount < totalTablesCount )
2020-05-20 15:14:44 +00:00
{
2022-02-09 18:49:52 +00:00
var orderedTablesCountBeforeIter = orderedTablesCount ; // ensure we not in infinite loop...
2020-05-20 15:14:44 +00:00
2022-02-09 18:49:52 +00:00
var i = 0 ;
while ( i < notOrderedTables . Count )
2020-05-20 15:14:44 +00:00
{
2022-02-09 18:49:52 +00:00
var table = notOrderedTables [ i ] ;
2020-05-20 15:14:44 +00:00
2022-02-09 18:49:52 +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
{
2022-02-09 18:49:52 +00:00
notOrderedTables . RemoveAt ( i ) ;
orderedTablesCount + + ;
2020-05-20 15:14:44 +00:00
2022-02-09 18:49:52 +00:00
yield return table ;
}
else
2022-02-09 18:33:50 +00:00
{
2022-02-09 18:49:52 +00:00
i + + ;
2022-02-09 18:33:50 +00:00
}
2020-05-20 15:14:44 +00:00
}
2022-02-09 18:49:52 +00:00
if ( orderedTablesCountBeforeIter = = orderedTablesCount ) // ensure we not in infinite loop...
2022-02-09 16:46:09 +00:00
{
2022-02-09 18:49:52 +00:00
throw ThrowHelper . CantOrderTables ( notOrderedTables . Select ( x = > x . Name ) ) ;
2022-02-09 16:46:09 +00:00
}
2022-02-09 18:49:52 +00:00
}
}
2020-05-20 15:14:44 +00:00
2022-02-09 18:49:52 +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
2022-02-09 18:49:52 +00:00
return command ;
}
2020-05-20 15:14:44 +00:00
2022-02-09 18:49:52 +00:00
public DbCommand CreateDeleteCommand ( DbConnection connection , int tenantId , TableInfo table )
{
var command = connection . CreateCommand ( ) ;
command . CommandText = string . Format ( "delete t.* from {0} as t {1};" , table . Name , GetDeleteCommandConditionText ( tenantId , table ) ) ;
2022-02-09 18:33:50 +00:00
2022-02-09 18:49:52 +00:00
return command ;
}
2022-02-09 18:33:50 +00:00
2022-02-09 18:49:52 +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
2022-02-09 18:49:52 +00:00
if ( ! TryPrepareRow ( dump , connection , columnMapper , table , row , out var valuesForInsert ) )
2020-05-26 08:52:47 +00:00
{
2022-02-09 18:49:52 +00:00
return null ;
}
2020-05-20 15:14:44 +00:00
2022-02-09 18:49:52 +00:00
var columns = valuesForInsert . Keys . Intersect ( table . Columns ) . ToArray ( ) ;
2020-05-26 08:52:47 +00:00
2022-02-09 18:49:52 +00:00
var insertCommantText = string . Format ( "{0} into {1}({2}) values({3});" ,
table . InsertMethod ! = InsertMethod . Ignore
? table . InsertMethod . ToString ( ) . ToLower ( )
: "insert ignore" ,
table . Name ,
string . Join ( "," , columns ) ,
string . Join ( "," , columns . Select ( c = > "@" + c ) ) ) ;
2022-02-09 18:33:50 +00:00
2022-02-09 18:49:52 +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
}
2022-02-09 18:49:52 +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
{
2022-02-09 18:49:52 +00:00
p . ParameterName = name . StartsWith ( "@" ) ? name : "@" + name ;
}
2020-05-26 08:52:47 +00:00
2022-02-09 18:49:52 +00:00
p . Value = GetParameterValue ( value ) ;
2020-05-26 08:52:47 +00:00
2022-02-09 18:49:52 +00:00
command . Parameters . Add ( p ) ;
2022-02-09 18:33:50 +00:00
2022-02-09 18:49:52 +00:00
return command ;
}
2022-02-09 18:33:50 +00:00
2022-02-09 18:49:52 +00:00
public object GetParameterValue ( object value )
{
if ( value = = null )
2020-05-20 15:14:44 +00:00
{
2022-02-09 18:49:52 +00:00
return DBNull . Value ;
2020-05-20 15:14:44 +00:00
}
2022-02-09 18:49:52 +00:00
if ( value is Enum @enum )
2022-02-09 18:33:50 +00:00
{
2022-02-09 18:49:52 +00:00
return @enum . ToString ( "d" ) ;
2022-02-09 18:33:50 +00:00
}
2022-02-09 18:49:52 +00:00
if ( value is DateTime d )
2022-02-09 18:33:50 +00:00
{
2022-02-09 18:49:52 +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
}
2022-02-09 18:49:52 +00:00
return value ;
}
2020-05-20 15:14:44 +00:00
2022-02-09 18:49:52 +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
2022-02-09 18:49:52 +00:00
protected virtual string GetSelectCommandConditionText ( int tenantId , TableInfo table )
{
if ( ! table . HasTenantColumn ( ) )
2020-05-20 15:14:44 +00:00
{
2022-02-09 18:49:52 +00:00
throw ThrowHelper . CantDetectTenant ( table . Name ) ;
2020-05-20 15:14:44 +00:00
}
2022-02-09 18:49:52 +00:00
return string . Format ( "where t.{0} = {1}" , table . TenantColumn , tenantId ) ;
}
2020-05-20 15:14:44 +00:00
2022-02-09 18:49:52 +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
2022-02-09 18:49:52 +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
{
2022-02-09 18:49:52 +00:00
continue ;
}
2020-05-20 15:14:44 +00:00
2022-02-09 18:49:52 +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
{
2022-02-09 18:49:52 +00:00
return false ;
2020-05-20 15:14:44 +00:00
}
2022-02-09 18:49:52 +00:00
}
else
{
if ( ! TryPrepareValue ( dump , connection , columnMapper , table , columnName , parentRelations [ columnName ] , ref val ) )
2020-05-20 15:14:44 +00:00
{
2022-02-09 18:49:52 +00:00
return false ;
2020-05-20 15:14:44 +00:00
}
2022-02-09 18:49:52 +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 18:49:52 +00:00
}
2022-02-09 16:46:09 +00:00
2022-02-09 18:49:52 +00:00
preparedRow . Add ( columnName , val ) ;
}
2022-02-09 18:33:50 +00:00
2022-02-09 18:49:52 +00:00
return true ;
}
2020-05-20 15:14:44 +00:00
2022-02-09 18:49:52 +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
{
2022-02-09 18:49:52 +00:00
return false ;
}
2022-02-09 16:46:09 +00:00
2022-02-09 18:49:52 +00:00
value = tenantMapping ;
2022-02-09 18:33:50 +00:00
2022-02-09 18:49:52 +00:00
return true ;
}
2020-05-20 15:14:44 +00:00
2022-02-09 18:49:52 +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
{
2022-02-09 18:49:52 +00:00
return _helpers . IsEmptyOrSystemUser ( strVal ) ;
2022-02-09 16:46:09 +00:00
}
2020-05-20 15:14:44 +00:00
2022-02-09 18:49:52 +00:00
value = userMapping ;
2020-05-20 15:14:44 +00:00
return true ;
}
2022-02-09 18:49:52 +00:00
var mapping = columnMapper . GetMapping ( table . Name , columnName , value ) ;
if ( mapping ! = null )
2020-05-20 15:14:44 +00:00
{
2022-02-09 18:49:52 +00:00
value = mapping ;
2020-05-20 15:14:44 +00:00
}
2022-02-09 18:49:52 +00:00
return true ;
}
2022-02-09 18:33:50 +00:00
2022-02-09 18:49:52 +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
2022-02-09 18:49:52 +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
}
2022-02-09 18:49:52 +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
}
}