7dcbacd5ca
- Filter MERGE SQL columns to only include columns that exist in destination (allColumns and updateColumns were using unfiltered source columns) - Fix schema-qualified table names to use proper [schema].[table] format instead of wrapping entire name in single brackets - Add empty column mapping validation to throw early if no columns intersect - Add JdeDateTransformer output column collision detection in OnInitialize - Add TODO comment for WithCommandTimeout (stored but not yet passed to destinations) - Add tests for FormatQualifiedTableName and output column collision
99 lines
3.3 KiB
C#
99 lines
3.3 KiB
C#
using JdeScoping.DataAccess.Interfaces;
|
|
using JdeScoping.DataSync.Etl.Contracts;
|
|
|
|
namespace JdeScoping.DataSync.Etl.Scripts;
|
|
|
|
public static class CommonScripts
|
|
{
|
|
/// <summary>
|
|
/// Parses a table name, extracting schema if present.
|
|
/// Supports: "Table", "dbo.Table", "[dbo].[Table]"
|
|
/// </summary>
|
|
public static (string Schema, string Table) ParseTableName(string tableName)
|
|
{
|
|
var cleaned = tableName.Replace("[", "").Replace("]", "");
|
|
var parts = cleaned.Split('.', 2);
|
|
return parts.Length == 2
|
|
? (parts[0], parts[1])
|
|
: ("dbo", parts[0]);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Formats a table name as a properly quoted [schema].[table] identifier.
|
|
/// </summary>
|
|
public static string FormatQualifiedTableName(string tableName)
|
|
{
|
|
var (schema, table) = ParseTableName(tableName);
|
|
return $"[{schema}].[{table}]";
|
|
}
|
|
|
|
public static IScriptRunner DisableIndexes(
|
|
IDbConnectionFactory factory,
|
|
string tableName,
|
|
int timeoutSeconds = 300)
|
|
{
|
|
var (schema, table) = ParseTableName(tableName);
|
|
|
|
var sql = @"
|
|
DECLARE @sql NVARCHAR(MAX) = '';
|
|
DECLARE @fullTableName NVARCHAR(256) = QUOTENAME(@schemaName) + '.' + QUOTENAME(@tableName);
|
|
|
|
SELECT @sql = @sql + 'ALTER INDEX ' + QUOTENAME(i.name) + ' ON ' + @fullTableName + ' DISABLE;' + CHAR(13)
|
|
FROM sys.indexes i
|
|
INNER JOIN sys.tables t ON i.object_id = t.object_id
|
|
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
|
|
WHERE t.name = @tableName
|
|
AND s.name = @schemaName
|
|
AND i.type = 2
|
|
AND i.is_disabled = 0;
|
|
|
|
IF LEN(@sql) > 0 EXEC sp_executesql @sql;";
|
|
|
|
return new SqlScriptRunner(factory, sql, $"DisableIndexes:{schema}.{table}",
|
|
parameters: new { tableName = table, schemaName = schema },
|
|
timeoutSeconds: timeoutSeconds);
|
|
}
|
|
|
|
public static IScriptRunner RebuildIndexes(
|
|
IDbConnectionFactory factory,
|
|
string tableName,
|
|
int timeoutSeconds = 3600)
|
|
{
|
|
var (schema, table) = ParseTableName(tableName);
|
|
|
|
var sql = @"
|
|
DECLARE @sql NVARCHAR(256) = 'ALTER INDEX ALL ON ' + QUOTENAME(@schemaName) + '.' + QUOTENAME(@tableName) + ' REBUILD WITH (FILLFACTOR = 95)';
|
|
EXEC sp_executesql @sql;";
|
|
|
|
return new SqlScriptRunner(factory, sql, $"RebuildIndexes:{schema}.{table}",
|
|
parameters: new { tableName = table, schemaName = schema },
|
|
timeoutSeconds: timeoutSeconds);
|
|
}
|
|
|
|
public static IScriptRunner UpdateStatistics(
|
|
IDbConnectionFactory factory,
|
|
string tableName,
|
|
int timeoutSeconds = 600)
|
|
{
|
|
var (schema, table) = ParseTableName(tableName);
|
|
|
|
var sql = @"
|
|
DECLARE @sql NVARCHAR(256) = 'UPDATE STATISTICS ' + QUOTENAME(@schemaName) + '.' + QUOTENAME(@tableName);
|
|
EXEC sp_executesql @sql;";
|
|
|
|
return new SqlScriptRunner(factory, sql, $"UpdateStats:{schema}.{table}",
|
|
parameters: new { tableName = table, schemaName = schema },
|
|
timeoutSeconds: timeoutSeconds);
|
|
}
|
|
|
|
public static IScriptRunner CustomSql(
|
|
IDbConnectionFactory factory,
|
|
string sql,
|
|
string name,
|
|
object? parameters = null,
|
|
int timeoutSeconds = 30)
|
|
{
|
|
return new SqlScriptRunner(factory, sql, name, parameters, timeoutSeconds);
|
|
}
|
|
}
|