You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

186 lines
6.3 KiB

using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace Dapper
{
public class SqlBuilder
{
private readonly Dictionary<string, Clauses> _data = new Dictionary<string, Clauses>();
private int _seq;
class Clause
{
public string Sql { get; set; }
public object Parameters { get; set; }
public bool IsInclusive { get; set; }
}
class Clauses : List<Clause>
{
private readonly string _joiner;
private readonly string _prefix;
private readonly string _postfix;
public Clauses(string joiner, string prefix = "", string postfix = "")
{
_joiner = joiner;
_prefix = prefix;
_postfix = postfix;
}
public string ResolveClauses(DynamicParameters p)
{
foreach (var item in this)
{
p.AddDynamicParams(item.Parameters);
}
return this.Any(a => a.IsInclusive)
? _prefix +
string.Join(_joiner,
this.Where(a => !a.IsInclusive)
.Select(c => c.Sql)
.Union(new[]
{
" ( " +
string.Join(" OR ", this.Where(a => a.IsInclusive).Select(c => c.Sql).ToArray()) +
" ) "
}).ToArray()) + _postfix
: _prefix + string.Join(_joiner, this.Select(c => c.Sql).ToArray()) + _postfix;
}
}
public class Template
{
private readonly string _sql;
private readonly SqlBuilder _builder;
private readonly object _initParams;
private int _dataSeq = -1; // Unresolved
public Template(SqlBuilder builder, string sql, dynamic parameters)
{
_initParams = parameters;
_sql = sql;
_builder = builder;
}
private static readonly Regex _regex = new Regex(@"\/\*\*.+\*\*\/", RegexOptions.Compiled | RegexOptions.Multiline);
void ResolveSql()
{
if (_dataSeq != _builder._seq)
{
DynamicParameters p = new DynamicParameters(_initParams);
rawSql = _sql;
foreach (var pair in _builder._data)
{
rawSql = rawSql.Replace("/**" + pair.Key + "**/", pair.Value.ResolveClauses(p));
}
parameters = p;
// replace all that is left with empty
rawSql = _regex.Replace(rawSql, "");
_dataSeq = _builder._seq;
}
}
string rawSql;
object parameters;
public string RawSql { get { ResolveSql(); return rawSql; } }
public object Parameters { get { ResolveSql(); return parameters; } }
}
public Template AddTemplate(string sql, dynamic parameters = null)
{
return new Template(this, sql, parameters);
}
protected void AddClause(string name, string sql, object parameters, string joiner, string prefix = "", string postfix = "", bool isInclusive = false)
{
Clauses clauses;
if (!_data.TryGetValue(name, out clauses))
{
clauses = new Clauses(joiner, prefix, postfix);
_data[name] = clauses;
}
clauses.Add(new Clause { Sql = sql, Parameters = parameters, IsInclusive = isInclusive });
_seq++;
}
public SqlBuilder Intersect(string sql, dynamic parameters = null)
{
AddClause("intersect", sql, parameters, "\nINTERSECT\n ", "\n ", "\n", false);
return this;
}
public SqlBuilder InnerJoin(string sql, dynamic parameters = null)
{
AddClause("innerjoin", sql, parameters, "\nINNER JOIN ", "\nINNER JOIN ", "\n", false);
return this;
}
public SqlBuilder LeftJoin(string sql, dynamic parameters = null)
{
AddClause("leftjoin", sql, parameters, "\nLEFT JOIN ", "\nLEFT JOIN ", "\n", false);
return this;
}
public SqlBuilder RightJoin(string sql, dynamic parameters = null)
{
AddClause("rightjoin", sql, parameters, "\nRIGHT JOIN ", "\nRIGHT JOIN ", "\n", false);
return this;
}
public SqlBuilder Where(string sql, dynamic parameters = null)
{
AddClause("where", sql, parameters, " AND ", "WHERE ", "\n", false);
return this;
}
public SqlBuilder OrWhere(string sql, dynamic parameters = null)
{
AddClause("where", sql, parameters, " AND ", "WHERE ", "\n", true);
return this;
}
public SqlBuilder OrderBy(string sql, dynamic parameters = null)
{
AddClause("orderby", sql, parameters, " , ", "ORDER BY ", "\n", false);
return this;
}
public SqlBuilder Select(string sql, dynamic parameters = null)
{
AddClause("select", sql, parameters, " , ", "", "\n", false);
return this;
}
public SqlBuilder AddParameters(dynamic parameters)
{
AddClause("--parameters", "", parameters, "", "", "", false);
return this;
}
public SqlBuilder Join(string sql, dynamic parameters = null)
{
AddClause("join", sql, parameters, "\nJOIN ", "\nJOIN ", "\n", false);
return this;
}
public SqlBuilder GroupBy(string sql, dynamic parameters = null)
{
AddClause("groupby", sql, parameters, " , ", "\nGROUP BY ", "\n", false);
return this;
}
public SqlBuilder Having(string sql, dynamic parameters = null)
{
AddClause("having", sql, parameters, "\nAND ", "HAVING ", "\n", false);
return this;
}
}
}