• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

loresoft / FluentCommand / 23278216331

19 Mar 2026 03:19AM UTC coverage: 57.398% (+0.7%) from 56.658%
23278216331

push

github

pwelter34
Enable nullable and improve source generators

1403 of 3069 branches covered (45.72%)

Branch coverage included in aggregate %.

527 of 907 new or added lines in 58 files covered. (58.1%)

22 existing lines in 10 files now uncovered.

4288 of 6846 relevant lines covered (62.64%)

330.58 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

50.79
/src/FluentCommand/Query/InsertBuilder.cs
1
using FluentCommand.Query.Generators;
2

3
namespace FluentCommand.Query;
4

5
/// <summary>
6
/// Provides a builder for constructing SQL INSERT statements with fluent, chainable methods.
7
/// </summary>
8
public class InsertBuilder : InsertBuilder<InsertBuilder>
9
{
10
    /// <summary>
11
    /// Initializes a new instance of the <see cref="InsertBuilder"/> class.
12
    /// </summary>
13
    /// <param name="queryGenerator">The <see cref="IQueryGenerator"/> used to generate SQL expressions.</param>
14
    /// <param name="parameters">The list of <see cref="QueryParameter"/> objects for the query.</param>
15
    public InsertBuilder(
16
        IQueryGenerator queryGenerator,
17
        List<QueryParameter> parameters)
18
        : base(queryGenerator, parameters)
×
19
    { }
×
20
}
21

22
/// <summary>
23
/// Provides a generic base class for building SQL INSERT statements with fluent, chainable methods.
24
/// </summary>
25
/// <typeparam name="TBuilder">The type of the builder for fluent chaining.</typeparam>
26
public abstract class InsertBuilder<TBuilder> : StatementBuilder<TBuilder>
27
    where TBuilder : InsertBuilder<TBuilder>
28
{
29
    /// <summary>
30
    /// Initializes a new instance of the <see cref="InsertBuilder{TBuilder}"/> class.
31
    /// </summary>
32
    /// <param name="queryGenerator">The <see cref="IQueryGenerator"/> used to generate SQL expressions.</param>
33
    /// <param name="parameters">The list of <see cref="QueryParameter"/> objects for the query.</param>
34
    protected InsertBuilder(
35
        IQueryGenerator queryGenerator,
36
        List<QueryParameter> parameters)
37
        : base(queryGenerator, parameters)
12✔
38
    {
39
    }
12✔
40

41
    /// <summary>
42
    /// Gets the collection of column expressions for the INSERT statement.
43
    /// </summary>
44
    /// <value>
45
    /// A <see cref="HashSet{ColumnExpression}"/> containing the column expressions.
46
    /// </value>
47
    protected HashSet<ColumnExpression> ColumnExpressions { get; } = new();
196✔
48

49
    /// <summary>
50
    /// Gets the collection of output column expressions for the INSERT statement.
51
    /// </summary>
52
    /// <value>
53
    /// A <see cref="HashSet{ColumnExpression}"/> containing the output column expressions.
54
    /// </value>
55
    protected HashSet<ColumnExpression> OutputExpressions { get; } = new();
35✔
56

57
    /// <summary>
58
    /// Gets the collection of value expressions for the INSERT statement.
59
    /// </summary>
60
    /// <value>
61
    /// A <see cref="HashSet{String}"/> containing the value expressions (parameter names).
62
    /// </value>
63
    protected HashSet<string> ValueExpressions { get; } = new();
196✔
64

65
    /// <summary>
66
    /// Gets the target table expression for the INSERT statement.
67
    /// </summary>
68
    /// <value>
69
    /// The <see cref="TableExpression"/> representing the target table.
70
    /// </value>
71
    protected TableExpression? TableExpression { get; private set; }
48✔
72

73
    /// <summary>
74
    /// Sets the target table to insert into.
75
    /// </summary>
76
    /// <param name="tableName">The name of the table.</param>
77
    /// <param name="tableSchema">The schema of the table (optional).</param>
78
    /// <param name="tableAlias">The alias for the table (optional).</param>
79
    /// <returns>
80
    /// The same builder instance for method chaining.
81
    /// </returns>
82
    public TBuilder Into(
83
        string tableName,
84
        string? tableSchema = null,
85
        string? tableAlias = null)
86
    {
87
        TableExpression = new TableExpression(tableName, tableSchema, tableAlias);
12✔
88

89
        return (TBuilder)this;
12✔
90
    }
91

92
    /// <summary>
93
    /// Adds a value for the specified column name and value.
94
    /// </summary>
95
    /// <typeparam name="TValue">The type of the value.</typeparam>
96
    /// <param name="columnName">The name of the column.</param>
97
    /// <param name="parameterValue">The value to insert for the column.</param>
98
    /// <returns>
99
    /// The same builder instance for method chaining.
100
    /// </returns>
101
    public TBuilder Value<TValue>(
102
        string columnName,
103
        TValue? parameterValue)
104
    {
105
        return Value(columnName, parameterValue, typeof(TValue));
20✔
106
    }
107

108
    /// <summary>
109
    /// Adds a value for the specified column name, value, and type.
110
    /// </summary>
111
    /// <param name="columnName">The name of the column.</param>
112
    /// <param name="parameterValue">The value to insert for the column.</param>
113
    /// <param name="parameterType">The type of the parameter value.</param>
114
    /// <returns>
115
    /// The same builder instance for method chaining.
116
    /// </returns>
117
    /// <exception cref="ArgumentException">Thrown if <paramref name="columnName"/> is null or empty.</exception>
118
    /// <exception cref="ArgumentNullException">Thrown if <paramref name="parameterType"/> is <c>null</c>.</exception>
119
    public TBuilder Value(
120
        string columnName,
121
        object? parameterValue,
122
        Type parameterType)
123
    {
124
        if (string.IsNullOrWhiteSpace(columnName))
172!
125
            throw new ArgumentException($"'{nameof(columnName)}' cannot be null or empty.", nameof(columnName));
×
126

127
        if (parameterType is null)
172!
128
            throw new ArgumentNullException(nameof(parameterType));
×
129

130
        var paramterName = NextParameter();
172✔
131

132
        var columnExpression = new ColumnExpression(columnName);
172✔
133

134
        ColumnExpressions.Add(columnExpression);
172✔
135
        ValueExpressions.Add(paramterName);
172✔
136

137
        Parameters.Add(new QueryParameter(paramterName, parameterValue, parameterType));
172✔
138

139
        return (TBuilder)this;
172✔
140
    }
141

142
    /// <summary>
143
    /// Conditionally adds a value for the specified column name and value if the condition is met.
144
    /// </summary>
145
    /// <typeparam name="TValue">The type of the value.</typeparam>
146
    /// <param name="columnName">The name of the column.</param>
147
    /// <param name="parameterValue">The value to insert for the column.</param>
148
    /// <param name="condition">A function that determines whether to add the value, based on the column name and value. If <c>null</c>, the value is always added.</param>
149
    /// <returns>
150
    /// The same builder instance for method chaining.
151
    /// </returns>
152
    public TBuilder ValueIf<TValue>(
153
        string columnName,
154
        TValue? parameterValue,
155
        Func<string, TValue?, bool> condition)
156
    {
157
        if (condition != null && !condition(columnName, parameterValue))
×
158
            return (TBuilder)this;
×
159

160
        return Value(columnName, parameterValue);
×
161
    }
162

163
    /// <summary>
164
    /// Adds an OUTPUT clause for the specified column names.
165
    /// </summary>
166
    /// <param name="columnNames">The collection of column names to include in the OUTPUT clause.</param>
167
    /// <param name="tableAlias">The alias for the table (optional).</param>
168
    /// <returns>
169
    /// The same builder instance for method chaining.
170
    /// </returns>
171
    /// <exception cref="ArgumentNullException">Thrown if <paramref name="columnNames"/> is <c>null</c>.</exception>
172
    public TBuilder Output(
173
        IEnumerable<string> columnNames,
174
        string? tableAlias = null)
175
    {
176
        if (columnNames is null)
×
177
            throw new ArgumentNullException(nameof(columnNames));
×
178

179
        foreach (var column in columnNames)
×
180
            Output(column, tableAlias);
×
181

182
        return (TBuilder)this;
×
183
    }
184

185
    /// <summary>
186
    /// Adds an OUTPUT clause for the specified column name.
187
    /// </summary>
188
    /// <param name="columnName">The name of the column to include in the OUTPUT clause.</param>
189
    /// <param name="tableAlias">The alias for the table (optional).</param>
190
    /// <param name="columnAlias">The alias for the output column (optional).</param>
191
    /// <returns>
192
    /// The same builder instance for method chaining.
193
    /// </returns>
194
    public TBuilder Output(
195
        string columnName,
196
        string? tableAlias = null,
197
        string? columnAlias = null)
198
    {
199
        var outputClause = new ColumnExpression(columnName, tableAlias, columnAlias);
11✔
200

201
        OutputExpressions.Add(outputClause);
11✔
202

203
        return (TBuilder)this;
11✔
204
    }
205

206
    /// <summary>
207
    /// Conditionally adds an OUTPUT clause for the specified column name if the condition is met.
208
    /// </summary>
209
    /// <param name="columnName">The name of the column to include in the OUTPUT clause.</param>
210
    /// <param name="tableAlias">The alias for the table (optional).</param>
211
    /// <param name="columnAlias">The alias for the output column (optional).</param>
212
    /// <param name="condition">A function that determines whether to add the OUTPUT clause. If <c>null</c>, the clause is always added.</param>
213
    /// <returns>
214
    /// The same builder instance for method chaining.
215
    /// </returns>
216
    public TBuilder OutputIf(
217
        string columnName,
218
        string? tableAlias = null,
219
        string? columnAlias = null,
220
        Func<string, bool>? condition = null)
221
    {
222
        if (condition != null && !condition(columnName))
×
223
            return (TBuilder)this;
×
224

225
        return Output(columnName, tableAlias, columnAlias);
×
226
    }
227

228
    /// <summary>
229
    /// Builds the SQL INSERT statement using the current configuration.
230
    /// </summary>
231
    /// <returns>
232
    /// A <see cref="QueryStatement"/> containing the SQL INSERT statement and its parameters.
233
    /// </returns>
234
    public override QueryStatement? BuildStatement()
235
    {
236
        if (TableExpression is null)
12!
NEW
237
            throw new InvalidOperationException("Table must be specified before building an insert statement.");
×
238

239
        var insertStatement = new InsertStatement(
12✔
240
            TableExpression,
12✔
241
            ColumnExpressions,
12✔
242
            OutputExpressions,
12✔
243
            ValueExpressions,
12✔
244
            CommentExpressions);
12✔
245

246
        var statement = QueryGenerator.BuildInsert(insertStatement);
12✔
247

248
        return new QueryStatement(statement, Parameters);
12✔
249
    }
250
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc