#nullable enable using System; using System.Text; namespace PluralKit.Core { public class QueryBuilder { private readonly string? _conflictField; private readonly string? _condition; private StringBuilder _insertFragment = new StringBuilder(); private StringBuilder _valuesFragment = new StringBuilder(); private StringBuilder _updateFragment = new StringBuilder(); private bool _firstInsert = true; private bool _firstUpdate = true; public QueryType Type { get; } public string Table { get; } private QueryBuilder(QueryType type, string table, string? conflictField, string? condition) { Type = type; Table = table; _conflictField = conflictField; _condition = condition; } public static QueryBuilder Insert(string table) => new QueryBuilder(QueryType.Insert, table, null, null); public static QueryBuilder Update(string table, string condition) => new QueryBuilder(QueryType.Update, table, null, condition); public static QueryBuilder Upsert(string table, string conflictField) => new QueryBuilder(QueryType.Upsert, table, conflictField, null); public QueryBuilder Constant(string fieldName, string paramName) { if (_firstInsert) _firstInsert = false; else { _insertFragment.Append(", "); _valuesFragment.Append(", "); } _insertFragment.Append(fieldName); _valuesFragment.Append(paramName); return this; } public QueryBuilder Variable(string fieldName, string paramName) { Constant(fieldName, paramName); if (_firstUpdate) _firstUpdate = false; else _updateFragment.Append(", "); _updateFragment.Append(fieldName); _updateFragment.Append("="); _updateFragment.Append(paramName); return this; } public string Build(string? suffix = null) { if (_firstInsert) throw new ArgumentException("No fields have been added to the query."); StringBuilder query = new StringBuilder(Type switch { QueryType.Insert => $"insert into {Table} ({_insertFragment}) values ({_valuesFragment})", QueryType.Upsert => $"insert into {Table} ({_insertFragment}) values ({_valuesFragment}) on conflict ({_conflictField}) do update set {_updateFragment}", QueryType.Update => $"update {Table} set {_updateFragment}", _ => throw new ArgumentOutOfRangeException($"Unknown query type {Type}") }); if (Type == QueryType.Update && _condition != null) query.Append($" where {_condition}"); if (suffix != null) query.Append($" {suffix}"); query.Append(";"); return query.ToString(); } public enum QueryType { Insert, Update, Upsert } } }