Last active
August 7, 2025 16:09
-
-
Save davidfowl/07eb4b2b0f0c17c347bc18cae2272458 to your computer and use it in GitHub Desktop.
Revisions
-
davidfowl revised this gist
May 15, 2023 . 1 changed file with 15 additions and 12 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -7,6 +7,10 @@ void GetCatalogItemsSql(int? catalogBrandId, int? before, int? after, int pageSize) { // This looks like it would be susceptible to SQL injection, but it's not. // The interpolated string is converted to a FromSqlInterpolatedStringHandler which will turn those // interpolated values in to parameterized values. SqlQuery($""" SELECT * FROM "Catalog" AS c @@ -33,30 +37,29 @@ void SqlQuery(in FromSqlInterpolatedStringHandler builder) [InterpolatedStringHandler] public ref struct FromSqlInterpolatedStringHandler { StringBuilder _builder; int _paramterCount; DbParameter[]? _parameters; public FromSqlInterpolatedStringHandler(int literalLength, int formattedCount) { _builder = new StringBuilder(literalLength); _parameters = formattedCount > 0 ? new DbParameter[formattedCount] : null; } public void AppendLiteral(string s) { _builder.Append(s); } public void AppendFormatted<T>(T t) { var parameterName = $"@p{_paramterCount}"; _builder.Append(parameterName); _parameters![_paramterCount++] = new NpgsqlParameter<T>(parameterName, t); } internal string GetQueryText() => _builder.ToString(); internal DbParameter[] GetParameters() => _parameters ?? Array.Empty<DbParameter>(); } -
davidfowl revised this gist
May 15, 2023 . 1 changed file with 6 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -19,12 +19,13 @@ ORDER BY c."Id" } void SqlQuery(in FromSqlInterpolatedStringHandler builder) { Console.WriteLine(builder.GetQueryText()); Console.WriteLine(); foreach (var p in builder.GetParameters()) { Console.WriteLine($"{p.ParameterName} = {(p.Value is null ? "NULL" : p.Value.ToString())}"); } } @@ -55,7 +56,7 @@ public void AppendFormatted<T>(T t) parameters![paramterCount++] = new NpgsqlParameter<T>(parameterName, t); } internal string GetQueryText() => builder.ToString(); internal DbParameter[] GetParameters() => parameters ?? Array.Empty<DbParameter>(); } -
davidfowl created this gist
May 14, 2023 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,61 @@ using System.Data.Common; using System.Runtime.CompilerServices; using System.Text; using Npgsql; GetCatalogItemsSql(null, null, null, 10); void GetCatalogItemsSql(int? catalogBrandId, int? before, int? after, int pageSize) { SqlQuery($""" SELECT * FROM "Catalog" AS c WHERE ({catalogBrandId} IS NULL OR c."CatalogBrandId" = {catalogBrandId}) AND ({before} IS NULL OR c."Id" < {before}) AND ({after} IS NULL OR c."Id" >= {after}) ORDER BY c."Id" LIMIT {pageSize + 1} """); } void SqlQuery(FromSqlInterpolatedStringHandler builder) { Console.WriteLine(builder.GetFormattedText()); foreach (var p in builder.GetParameters()) { Console.WriteLine(p); } } [InterpolatedStringHandler] public ref struct FromSqlInterpolatedStringHandler { // Storage for the built-up string StringBuilder builder; int paramterCount; DbParameter[]? parameters; public FromSqlInterpolatedStringHandler(int literalLength, int formattedCount) { builder = new StringBuilder(literalLength); parameters = formattedCount > 0 ? new DbParameter[formattedCount] : null; } public void AppendLiteral(string s) { builder.Append(s); } public void AppendFormatted<T>(T t) { var parameterName = $"@p{paramterCount}"; builder.Append(parameterName); parameters![paramterCount++] = new NpgsqlParameter<T>(parameterName, t); } internal string GetFormattedText() => builder.ToString(); internal DbParameter[] GetParameters() => parameters ?? Array.Empty<DbParameter>(); }