• 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

72.41
/src/FluentCommand/Query/QueryBuilder.cs
1
using System.Text;
2

3
using FluentCommand.Query.Generators;
4

5
namespace FluentCommand.Query;
6

7
/// <summary>
8
/// Provides a high-level builder for constructing and composing multiple SQL query statements.
9
/// </summary>
10
/// <seealso cref="FluentCommand.Query.IStatementBuilder" />
11
public class QueryBuilder : IStatementBuilder
12
{
13
    private readonly Queue<IStatementBuilder> _builderQueue = new();
57✔
14

15
    /// <summary>
16
    /// Initializes a new instance of the <see cref="QueryBuilder"/> class.
17
    /// </summary>
18
    /// <param name="queryGenerator">The <see cref="IQueryGenerator"/> used to generate SQL expressions and statements.</param>
19
    /// <param name="parameters">The initial list of <see cref="QueryParameter"/> objects for the query.</param>
20
    /// <exception cref="System.ArgumentNullException">
21
    /// Thrown if <paramref name="queryGenerator"/> or <paramref name="parameters"/> is <c>null</c>.
22
    /// </exception>
23
    public QueryBuilder(IQueryGenerator queryGenerator, List<QueryParameter> parameters)
57✔
24
    {
25
        QueryGenerator = queryGenerator ?? throw new ArgumentNullException(nameof(queryGenerator));
57!
26
        Parameters = parameters ?? throw new ArgumentNullException(nameof(parameters));
57!
27
    }
57✔
28

29
    /// <summary>
30
    /// Gets the <see cref="IQueryGenerator"/> used to generate SQL expressions and statements.
31
    /// </summary>
32
    /// <value>
33
    /// The <see cref="IQueryGenerator"/> instance.
34
    /// </value>
35
    protected IQueryGenerator QueryGenerator { get; }
60✔
36

37
    /// <summary>
38
    /// Gets the list of <see cref="QueryParameter"/> objects used in the query.
39
    /// </summary>
40
    /// <value>
41
    /// The list of query parameters.
42
    /// </value>
43
    protected List<QueryParameter> Parameters { get; }
62✔
44

45

46
    /// <summary>
47
    /// Starts a new raw SQL statement builder and adds it to the query.
48
    /// </summary>
49
    /// <returns>
50
    /// A new <see cref="StatementBuilder"/> instance for building a raw SQL statement.
51
    /// </returns>
52
    public StatementBuilder Statement()
53
    {
54
        var builder = new StatementBuilder(QueryGenerator, Parameters);
3✔
55

56
        _builderQueue.Enqueue(builder);
3✔
57

58
        return builder;
3✔
59
    }
60

61
    /// <summary>
62
    /// Starts a new SELECT statement builder for a specific entity type and adds it to the query.
63
    /// </summary>
64
    /// <typeparam name="TEntity">The type of the entity to select.</typeparam>
65
    /// <returns>
66
    /// A new <see cref="SelectEntityBuilder{TEntity}"/> instance for building a SELECT statement.
67
    /// </returns>
68
    public SelectEntityBuilder<TEntity> Select<TEntity>()
69
        where TEntity : class
70
    {
71
        var builder = new SelectEntityBuilder<TEntity>(QueryGenerator, Parameters);
39✔
72

73
        _builderQueue.Enqueue(builder);
39✔
74

75
        return builder;
39✔
76
    }
77

78
    /// <summary>
79
    /// Starts a new SELECT statement builder and adds it to the query.
80
    /// </summary>
81
    /// <returns>
82
    /// A new <see cref="SelectBuilder"/> instance for building a SELECT statement.
83
    /// </returns>
84
    public SelectBuilder Select()
85
    {
86
        var builder = new SelectBuilder(QueryGenerator, Parameters);
×
87

88
        _builderQueue.Enqueue(builder);
×
89

90
        return builder;
×
91

92
    }
93

94
    /// <summary>
95
    /// Starts a new INSERT statement builder for a specific entity type and adds it to the query.
96
    /// </summary>
97
    /// <typeparam name="TEntity">The type of the entity to insert.</typeparam>
98
    /// <returns>
99
    /// A new <see cref="InsertEntityBuilder{TEntity}"/> instance for building an INSERT statement.
100
    /// </returns>
101
    public InsertEntityBuilder<TEntity> Insert<TEntity>()
102
        where TEntity : class
103
    {
104
        var builder = new InsertEntityBuilder<TEntity>(QueryGenerator, Parameters);
11✔
105

106
        _builderQueue.Enqueue(builder);
11✔
107

108
        return builder;
11✔
109
    }
110

111
    /// <summary>
112
    /// Starts a new INSERT statement builder and adds it to the query.
113
    /// </summary>
114
    /// <returns>
115
    /// A new <see cref="InsertBuilder"/> instance for building an INSERT statement.
116
    /// </returns>
117
    public InsertBuilder Insert()
118
    {
119
        var builder = new InsertBuilder(QueryGenerator, Parameters);
×
120

121
        _builderQueue.Enqueue(builder);
×
122

123
        return builder;
×
124

125
    }
126

127
    /// <summary>
128
    /// Starts a new UPDATE statement builder for a specific entity type and adds it to the query.
129
    /// </summary>
130
    /// <typeparam name="TEntity">The type of the entity to update.</typeparam>
131
    /// <returns>
132
    /// A new <see cref="UpdateEntityBuilder{TEntity}"/> instance for building an UPDATE statement.
133
    /// </returns>
134
    public UpdateEntityBuilder<TEntity> Update<TEntity>()
135
        where TEntity : class
136
    {
137
        var builder = new UpdateEntityBuilder<TEntity>(QueryGenerator, Parameters);
4✔
138

139
        _builderQueue.Enqueue(builder);
4✔
140

141
        return builder;
4✔
142

143
    }
144

145
    /// <summary>
146
    /// Starts a new UPDATE statement builder and adds it to the query.
147
    /// </summary>
148
    /// <returns>
149
    /// A new <see cref="UpdateBuilder"/> instance for building an UPDATE statement.
150
    /// </returns>
151
    public UpdateBuilder Update()
152
    {
153
        var builder = new UpdateBuilder(QueryGenerator, Parameters);
×
154

155
        _builderQueue.Enqueue(builder);
×
156

157
        return builder;
×
158
    }
159

160
    /// <summary>
161
    /// Starts a new DELETE statement builder for a specific entity type and adds it to the query.
162
    /// </summary>
163
    /// <typeparam name="TEntity">The type of the entity to delete.</typeparam>
164
    /// <returns>
165
    /// A new <see cref="DeleteEntityBuilder{TEntity}"/> instance for building a DELETE statement.
166
    /// </returns>
167
    public DeleteEntityBuilder<TEntity> Delete<TEntity>()
168
        where TEntity : class
169
    {
170
        var builder = new DeleteEntityBuilder<TEntity>(QueryGenerator, Parameters);
3✔
171

172
        _builderQueue.Enqueue(builder);
3✔
173

174
        return builder;
3✔
175

176
    }
177

178
    /// <summary>
179
    /// Starts a new DELETE statement builder and adds it to the query.
180
    /// </summary>
181
    /// <returns>
182
    /// A new <see cref="DeleteBuilder"/> instance for building a DELETE statement.
183
    /// </returns>
184
    public DeleteBuilder Delete()
185
    {
186
        var builder = new DeleteBuilder(QueryGenerator, Parameters);
×
187

188
        _builderQueue.Enqueue(builder);
×
189

190
        return builder;
×
191
    }
192

193
    /// <summary>
194
    /// Builds and returns a <see cref="QueryStatement"/> representing the composed SQL query and its parameters.
195
    /// </summary>
196
    /// <returns>
197
    /// A <see cref="QueryStatement"/> containing the SQL statement and associated <see cref="QueryParameter"/> values,
198
    /// or <c>null</c> if no statement can be built from the current configuration.
199
    /// </returns>
200
    public QueryStatement? BuildStatement()
201
    {
202
        // optimize for when only 1 builder
203
        if (_builderQueue.Count == 1)
57✔
204
        {
205
            var builder = _builderQueue.Dequeue();
55✔
206
            return builder.BuildStatement();
55✔
207
        }
208

209
        // merge all queued builders together
210
        var query = new StringBuilder();
2✔
211

212
        while (_builderQueue.Count > 0)
7✔
213
        {
214
            var builder = _builderQueue.Dequeue();
5✔
215
            var statement = builder.BuildStatement();
5✔
216

217
            if (statement != null)
5✔
218
                query.AppendLine(statement.Statement);
5✔
219
        }
220

221
        if (query.Length == 0)
2!
NEW
222
            return null;
×
223

224
        return new QueryStatement(query.ToString(), Parameters);
2✔
225
    }
226
}
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