using System.Reflection; using System.Text; namespace HermesSocketServer.Store { public class GroupSaveSqlGenerator { private readonly IDictionary columnPropertyRelations; public GroupSaveSqlGenerator(IDictionary columnsToProperties) { columnPropertyRelations = columnsToProperties.ToDictionary(p => p.Key, p => typeof(T).GetProperty(p.Value)); var nullProperties = columnPropertyRelations.Where(p => p.Value == null) .Select(p => columnsToProperties[p.Key]); if (nullProperties.Any()) throw new ArgumentException("Some properties do not exist on the values given: " + string.Join(", ", nullProperties)); } public string GenerateInsertSql(string table, IEnumerable values, IEnumerable columns) { if (string.IsNullOrWhiteSpace(table)) throw new ArgumentException("Value is either null or whitespace-filled.", nameof(table)); if (values == null) throw new ArgumentNullException(nameof(values)); if (!values.Any()) throw new ArgumentException("Empty list given.", nameof(values)); if (columns == null) throw new ArgumentNullException(nameof(columns)); if (!columns.Any()) throw new ArgumentException("Empty list given.", nameof(columns)); var ctp = columns.ToDictionary(c => c, c => columnPropertyRelations[c]); var sb = new StringBuilder(); sb.Append($"INSERT INTO \"{table}\" (\"{string.Join("\", \"", columns)}\") VALUES "); foreach (var value in values) { sb.Append("("); foreach (var column in columns) { var propValue = columnPropertyRelations[column]!.GetValue(value); var propType = columnPropertyRelations[column]!.PropertyType; WriteValue(sb, propValue, propType); sb.Append(","); } sb.Remove(sb.Length - 1, 1) .Append("),"); } sb.Remove(sb.Length - 1, 1) .Append(';'); return sb.ToString(); } public string GenerateUpdateSql(string table, IEnumerable values, IEnumerable keyColumns, IEnumerable updateColumns) { if (string.IsNullOrWhiteSpace(table)) throw new ArgumentException("Value is either null or whitespace-filled.", nameof(table)); if (values == null) throw new ArgumentNullException(nameof(values)); if (!values.Any()) throw new ArgumentException("Empty list given.", nameof(values)); if (keyColumns == null) throw new ArgumentNullException(nameof(keyColumns)); if (!keyColumns.Any()) throw new ArgumentException("Empty list given.", nameof(keyColumns)); if (updateColumns == null) throw new ArgumentNullException(nameof(updateColumns)); if (!updateColumns.Any()) throw new ArgumentException("Empty list given.", nameof(updateColumns)); var columns = keyColumns.Union(updateColumns); var ctp = columns.ToDictionary(c => c, c => columnPropertyRelations[c]); var sb = new StringBuilder(); sb.Append($"UPDATE \"{table}\" as t SET {string.Join(", ", updateColumns.Select(c => "\"" + c + "\" = c.\"" + c + "\""))} FROM (VALUES "); foreach (var value in values) { sb.Append("("); foreach (var column in columns) { var propValue = columnPropertyRelations[column]!.GetValue(value); var propType = columnPropertyRelations[column]!.PropertyType; WriteValue(sb, propValue, propType); sb.Append(","); } sb.Remove(sb.Length - 1, 1) .Append("),"); } sb.Remove(sb.Length - 1, 1) .Append($") AS c(\"{string.Join("\", \"", columns)}\") WHERE id = c.id;"); return sb.ToString(); } public string GenerateDeleteSql(string table, IEnumerable keys, IEnumerable keyColumns) { if (string.IsNullOrWhiteSpace(table)) throw new ArgumentException("Value is either null or whitespace-filled.", nameof(table)); if (keys == null) throw new ArgumentNullException(nameof(keys)); if (!keys.Any()) throw new ArgumentException("Empty list given.", nameof(keys)); if (keyColumns == null) throw new ArgumentNullException(nameof(keyColumns)); if (!keyColumns.Any()) throw new ArgumentException("Empty list given.", nameof(keyColumns)); var ctp = keyColumns.ToDictionary(c => c, c => columnPropertyRelations[c]); var sb = new StringBuilder(); sb.Append($"DELETE FROM \"{table}\" WHERE (\"{string.Join("\", \"", keyColumns)}\") IN ("); foreach (var k in keys) { sb.Append("("); foreach (var column in keyColumns) { var propType = columnPropertyRelations[column]!.PropertyType; WriteValue(sb, k, propType); sb.Append(","); } sb.Remove(sb.Length - 1, 1) .Append("),"); } sb.Remove(sb.Length - 1, 1) .Append(");"); return sb.ToString(); } private void WriteValue(StringBuilder sb, object? value, Type type) { if (type == typeof(string)) sb.Append("'") .Append(value) .Append("'"); else sb.Append(value); } } }