/// <summary> /// Формирует Sql для удаления данных /// </summary> private string GetDeleteSql(string[] tempTablePath, string[] tablePath, IList <ColumnMap> map) { return($"DELETE FROM {PostgreNamingHelper.Escape(tablePath)} AS rl " + $"USING {PostgreNamingHelper.Escape(tempTablePath)} AS tmp " + $"WHERE tmp.{PostgreNamingHelper.Escape(cRowStateColumnName)} IN ('D') " + $"AND {string.Join(" AND ", map.Where(x => x.IsKey).Select(x => $"rl.{x.EscapedRealColumn} = tmp.{x.EscapedTempColumn}"))} "); }
/// <summary> /// Формирует Sql для команды получения индекса первичного ключа таблицы /// </summary> private string GetTableIndexInfoSql(string[] tablePath) { return($"SELECT indkey, indoption as k " + $"FROM pg_index i " + $"WHERE i.indrelid = \'{PostgreNamingHelper.EscapeString(PostgreNamingHelper.Escape(tablePath))}\'::regclass " + $"AND i.indisprimary = true "); }
/// <summary> /// Формирует Sql для команды импорта данных во временную таблицу /// </summary> private string GetImportDataSql(string[] tempTablePath, DataTable schema) { var columns = new List <string> { cRowStateColumnName }; foreach (var row in schema.Rows.OfType <DataRow>()) { columns.Add($"col{(int)row["ColumnOrdinal"]}"); columns.Add($"col{(int)row["ColumnOrdinal"]}Specified"); if (!(bool)row["IsKey"]) { continue; } columns.Add($"col{(int)row["ColumnOrdinal"]}new"); columns.Add($"col{(int)row["ColumnOrdinal"]}newSpecified"); } return ($"COPY {PostgreNamingHelper.Escape(tempTablePath)}" + $"({string.Join(", ", columns.Select(x=>PostgreNamingHelper.Escape(x)))}) " + $"FROM STDIN BINARY;"); }
/// <summary> /// Проверяет наличие первичного ключа в схеме /// </summary> private void AssertHasPrimaryKey(DataTable schema, string[] tablePath) { if (schema.Rows.OfType <DataRow>().All(x => !(bool)x["IsKey"])) { throw new InvalidOperationException($"Table {PostgreNamingHelper.Escape(tablePath)} does not have primary key."); } }
/// <summary> /// Формирует Sql для вставки данных /// </summary> private string GetInsertSql(string[] tempTablePath, string[] tablePath, IList <ColumnMap> map) { return($"INSERT INTO {PostgreNamingHelper.Escape(tablePath)} " + $"({string.Join(", ", map.Select(x => x.EscapedRealColumn))}) " + $"SELECT " + $"{string.Join(", ", map.Select(x => x.EscapedTempColumn))} " + $"FROM {PostgreNamingHelper.Escape(tempTablePath)} AS tmp " + $"WHERE tmp.{PostgreNamingHelper.Escape(cRowStateColumnName)} IN ('I') "); }
/// <summary> /// Формирует Sql для обновления данных /// </summary> private string GetUpdateSql(string[] tempTablePath, string[] tablePath, IList <ColumnMap> map) { var setBlock = string.Join(", ", map.Select(x => $"{x.EscapedRealColumn} = CASE " + $"WHEN tmp.{(x.IsKey ? x.EscapedTempUpdatedKeySpecifiedColumn : x.EscapedTempSpecifiedColumn)} " + $"THEN tmp.{(x.IsKey ? x.EscapedTempUpdatedKeyColumn : x.EscapedTempColumn)} " + $"ELSE rl.{x.EscapedRealColumn} " + $"END")); return($"UPDATE {PostgreNamingHelper.Escape(tablePath)} AS rl " + $"SET {setBlock} " + $"FROM {PostgreNamingHelper.Escape(tempTablePath)} AS tmp " + $"WHERE tmp.{PostgreNamingHelper.Escape(cRowStateColumnName)} IN ('U') " + $"AND {string.Join(" AND ", map.Where(x => x.IsKey).Select(x => $"rl.{x.EscapedRealColumn} = tmp.{x.EscapedTempColumn}"))} "); }
/// <summary> /// Формирует Sql для команды создания временной таблицы /// </summary> private string GetCreateTempTableSql(DataTable schema, string tempTableName) { var sb = new StringBuilder(); //Создание таблицы sb.Append($"CREATE TEMP TABLE {PostgreNamingHelper.Escape(tempTableName)} ("); sb.Append($"{PostgreNamingHelper.Escape(cRowStateColumnName)} {cRowStateColumnType}"); foreach (var columnInfo in schema.Rows.OfType <DataRow>()) { var columnName = $"col{(int) columnInfo["ColumnOrdinal"]}"; sb.Append($", {PostgreNamingHelper.Escape(columnName)} " + $"{(string)columnInfo["DataTypeName"]}"); sb.Append($", {PostgreNamingHelper.Escape($"{columnName}Specified")} bool "); if (!(bool)columnInfo["IsKey"]) { continue; } columnName = $"{columnName}new"; sb.Append($", {PostgreNamingHelper.Escape(columnName)} " + $"{(string)columnInfo["DataTypeName"]}"); sb.Append($", {PostgreNamingHelper.Escape($"{columnName}Specified")} bool "); } sb.Append("); "); //Создание индекса sb.Append($"CREATE INDEX {PostgreNamingHelper.Escape($"IX_{tempTableName}")} "); sb.Append($"ON {PostgreNamingHelper.Escape(tempTableName)} ("); var indexInfos = new List <string> { $"{PostgreNamingHelper.Escape(cRowStateColumnName)} ASC NULLS LAST" }; indexInfos.AddRange( schema.Rows.OfType <DataRow>() .Where(x => (bool)x["IsKey"]) .OrderBy(x => (int)x["PrimaryKeyIndexOrdinal"]) .Select(x => $"{PostgreNamingHelper.Escape($"col{(int) x["ColumnOrdinal"]}")} " + $"{(string) x["PrimaryKeyIndexOrderBy"]} " + $"{(string) x["PrimaryKeyIndexNulls"]}")); sb.Append(string.Join(", ", indexInfos)); sb.Append("); "); return(sb.ToString()); }
public ColumnMap(string tempColumn, string realColumn, bool isKey) { TempColumn = tempColumn; TempSpecifiedColumn = $"{tempColumn}Specified"; RealColumn = realColumn; EscapedTempColumn = PostgreNamingHelper.Escape(TempColumn); EscapedTempSpecifiedColumn = PostgreNamingHelper.Escape(TempSpecifiedColumn); EscapedRealColumn = PostgreNamingHelper.Escape(RealColumn); IsKey = isKey; if (isKey) { TempUpdatedKeyColumn = $"{tempColumn}new"; TempUpdatedKeySpecifiedColumn = $"{tempColumn}newSpecified"; EscapedTempUpdatedKeyColumn = PostgreNamingHelper.Escape(TempUpdatedKeyColumn); EscapedTempUpdatedKeySpecifiedColumn = PostgreNamingHelper.Escape(TempUpdatedKeySpecifiedColumn); } }
/// <summary> /// Формирует Sql для команды удаления временной таблицы /// </summary> private string GetDropTableSql(string[] tempTablePath) { return($"DROP TABLE IF EXISTS {PostgreNamingHelper.Escape(tempTablePath)}"); }
/// <summary> /// Формирует Sql для команды получения схемы таблицы /// </summary> private string GetSchemaTableSql(string[] tablePath) { return($"SELECT * FROM {PostgreNamingHelper.Escape(tablePath)} LIMIT 0"); }