mirror of
https://github.com/DapperLib/Dapper.git
synced 2026-10-18 22:31:08 +08:00
aecffecae1
* attempt NRT makeover - annotate NRTs on GridReader API - add protected access to some of the GridReader internals - switch GridReader callbacks to be more type-independent docs lib updates; deal with yellow warnings and test failures (SQL server certs and cancellation surfacing differently) fix break simplify proposed GridReader changes to protected OnBeforeGrid and OnAfterGrid[Async] Builds: Bump library versions (#1935) Tests: Upgrade dependencies for Dependabot (#1936) I'll do a pass at all of these later, but getting CVE versions out of the pipe. Resolving 4 alerts here: https://github.com/DapperLib/Dapper/security/dependabot merge and lib updates allow Identity to be constructed on-the-fly inside GridReader fix build warnings include readme rev minor - enable [SkipLocalsInit] everywhere - use NET5_0_OR_GREATER for remoting check # Conflicts: # Dapper/CommandDefinition.cs # Dapper/DefaultTypeMap.cs # Dapper/SqlMapper.Async.cs # Dapper/SqlMapper.IDataReader.cs # Dapper/SqlMapper.Link.cs # Dapper/SqlMapper.cs # Directory.Build.props * shipped, not unshipped * fixup SqlBuilder; use is null / is not null * use central package management (#1949) * Nullable test tweaks * Nuget: let's just remove it! * 2 test fixes from review * fix FindExplicitConstructor * add GetPropertySetterOrThrow * fix NRT on FindConstructor * DapperRow: value is object? * use NotNullWhen * make constructor problem more obvious * test fixes --------- Co-authored-by: Nick Craver <nrcraver@gmail.com>
165 lines
6.4 KiB
C#
165 lines
6.4 KiB
C#
using System.Collections.Generic;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
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;
|
|
|
|
private class Clause
|
|
{
|
|
public Clause(string sql, object? parameters, bool isInclusive)
|
|
{
|
|
Sql = sql;
|
|
Parameters = parameters;
|
|
IsInclusive = isInclusive;
|
|
}
|
|
public string Sql { get; }
|
|
public object? Parameters { get; }
|
|
public bool IsInclusive { get; }
|
|
}
|
|
|
|
private class Clauses : List<Clause>
|
|
{
|
|
private readonly string _joiner, _prefix, _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);
|
|
|
|
private void ResolveSql()
|
|
{
|
|
if (_dataSeq != _builder._seq)
|
|
{
|
|
var 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;
|
|
}
|
|
}
|
|
|
|
private string? rawSql;
|
|
private object? parameters;
|
|
|
|
public string RawSql
|
|
{
|
|
get { ResolveSql(); return rawSql!; }
|
|
}
|
|
|
|
public object? Parameters
|
|
{
|
|
get { ResolveSql(); return parameters; }
|
|
}
|
|
}
|
|
|
|
public Template AddTemplate(string sql, dynamic? parameters = null) =>
|
|
new Template(this, sql, (object?)parameters);
|
|
|
|
protected SqlBuilder AddClause(string name, string sql, object? parameters, string joiner, string prefix = "", string postfix = "", bool isInclusive = false)
|
|
{
|
|
if (!_data.TryGetValue(name, out var clauses))
|
|
{
|
|
clauses = new Clauses(joiner, prefix, postfix);
|
|
_data[name] = clauses;
|
|
}
|
|
clauses.Add(new Clause(sql, parameters, isInclusive));
|
|
_seq++;
|
|
return this;
|
|
}
|
|
|
|
public SqlBuilder Intersect(string sql, dynamic? parameters = null) =>
|
|
AddClause("intersect", sql, (object?)parameters, "\nINTERSECT\n ", "\n ", "\n", false);
|
|
|
|
public SqlBuilder InnerJoin(string sql, dynamic? parameters = null) =>
|
|
AddClause("innerjoin", sql, (object?)parameters, "\nINNER JOIN ", "\nINNER JOIN ", "\n", false);
|
|
|
|
public SqlBuilder LeftJoin(string sql, dynamic? parameters = null) =>
|
|
AddClause("leftjoin", sql, (object?)parameters, "\nLEFT JOIN ", "\nLEFT JOIN ", "\n", false);
|
|
|
|
public SqlBuilder RightJoin(string sql, dynamic? parameters = null) =>
|
|
AddClause("rightjoin", sql, (object?)parameters, "\nRIGHT JOIN ", "\nRIGHT JOIN ", "\n", false);
|
|
|
|
public SqlBuilder Where(string sql, dynamic? parameters = null) =>
|
|
AddClause("where", sql, (object?)parameters, " AND ", "WHERE ", "\n", false);
|
|
|
|
public SqlBuilder OrWhere(string sql, dynamic? parameters = null) =>
|
|
AddClause("where", sql, (object?)parameters, " OR ", "WHERE ", "\n", true);
|
|
|
|
public SqlBuilder OrderBy(string sql, dynamic? parameters = null) =>
|
|
AddClause("orderby", sql, (object?)parameters, " , ", "ORDER BY ", "\n", false);
|
|
|
|
public SqlBuilder Select(string sql, dynamic? parameters = null) =>
|
|
AddClause("select", sql, (object?)parameters, " , ", "", "\n", false);
|
|
|
|
public SqlBuilder AddParameters(dynamic parameters) =>
|
|
AddClause("--parameters", "", (object?)parameters, "", "", "", false);
|
|
|
|
public SqlBuilder Join(string sql, dynamic? parameters = null) =>
|
|
AddClause("join", sql, (object?)parameters, "\nJOIN ", "\nJOIN ", "\n", false);
|
|
|
|
public SqlBuilder GroupBy(string sql, dynamic? parameters = null) =>
|
|
AddClause("groupby", sql, (object?)parameters, " , ", "\nGROUP BY ", "\n", false);
|
|
|
|
public SqlBuilder Having(string sql, dynamic? parameters = null) =>
|
|
AddClause("having", sql, (object?)parameters, "\nAND ", "HAVING ", "\n", false);
|
|
|
|
public SqlBuilder Set(string sql, dynamic? parameters = null) =>
|
|
AddClause("set", sql, (object?)parameters, " , ", "SET ", "\n", false);
|
|
|
|
}
|
|
}
|