Skip to content

Commit

Permalink
Add RawSql methods (Where, And, Or, OrderBy) and AppendRawSql method (#2
Browse files Browse the repository at this point in the history
)

Change parameter type from LambdaExpression to Expression<Func<T, object>> for strongly-typed expressions
  • Loading branch information
guanghuang authored Nov 29, 2024
1 parent 0171396 commit c778420
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 59 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ builder
- Consider query performance when building complex JOINs

## Limitations
1. Limited support for complex subqueries
1. Limited support for complex subqueries (could use RawSql methods for this)
2. No direct support for GROUP BY and HAVING clauses
3. No NamingConvention support for table and column (e.g. SnakeCase, PascalCase for table and column names)

Expand All @@ -195,6 +195,10 @@ builder
- .NET 7.0+

## Version History
- 1.1.0
- Add RawSql methods (Where, And, Or, OrderBy) and AppendRawSql method
- Change parameter type from LambdaExpression to Expression<Func<T, object>> for strongly-typed expressions

- 1.0.0
- Initial release
- Basic SQL query building
Expand Down
127 changes: 70 additions & 57 deletions src/SqlBuilder/SqlBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,56 +146,45 @@ private string GetTablePrefix(Type type, bool alwaysCreateNew)
tableAliasIndex++;
return newPrefix;
}

/// <summary>
/// Adds a SELECT * clause for a type, with options to exclude specific columns.
/// Adds a SELECT * clause for a type, with options to exclude specific columns and specify a first column.
/// </summary>
/// <typeparam name="T">The entity type</typeparam>
/// <param name="excludeColumns">Columns to exclude from the selection</param>
/// <param name="firstColumn">Column to place first in the selection</param>
/// <param name="prefix">Output parameter for the generated table prefix</param>
/// <param name="prefix">Optional table prefix/alias</param>
/// <returns>The current SqlBuilder instance for method chaining</returns>
public SqlBuilder SelectAll<T>(LambdaExpression[]? excludeColumns, LambdaExpression? firstColumn, out string prefix)
public SqlBuilder SelectAll<T>(Expression<Func<T, object>>[]? excludeColumns, Expression<Func<T, object>>? firstColumn, string? prefix = null)
{
prefix = GetTablePrefix(typeof(T), true);
prefix ??= GetTablePrefix(typeof(T), false);
AppendSelect(Utils.GenerateSelectAllColumns(typeof(T), isSqlServer, excludeColumns, firstColumn, prefix));
return this;
}

/// <summary>
/// Adds a SELECT * clause for a type, excluding specific columns.
/// Adds a SELECT * clause for a type, with options to exclude specific columns.
/// </summary>
/// <typeparam name="T">The entity type</typeparam>
/// <param name="excludeColumns">Columns to exclude from the selection</param>
/// <param name="firstColumn">Column to place first in the selection</param>
/// <param name="prefix">Output parameter for the generated table prefix</param>
/// <returns>The current SqlBuilder instance for method chaining</returns>
public SqlBuilder SelectAll<T>(LambdaExpression[]? excludeColumns, out string prefix)
public SqlBuilder SelectAll<T>(Expression<Func<T, object>>[]? excludeColumns, Expression<Func<T, object>>? firstColumn, out string prefix)
{
return SelectAll<T>(excludeColumns, null, out prefix);
}

/// <summary>
/// Adds a SELECT * clause for a type, with options to exclude specific columns and specify a first column.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="excludeColumns"></param>
/// <param name="firstColumn"></param>
/// <param name="prefix"></param>
/// <returns></returns>
public SqlBuilder SelectAll<T>(Expression<Func<T, object>>[]? excludeColumns, Expression<Func<T, object>>? firstColumn, string? prefix = null)
{
prefix ??= GetTablePrefix(typeof(T), false);
prefix = GetTablePrefix(typeof(T), true);
AppendSelect(Utils.GenerateSelectAllColumns(typeof(T), isSqlServer, excludeColumns, firstColumn, prefix));
return this;
}


/// <summary>
/// Adds a SELECT * clause for a type, excluding specific columns.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="excludeColumns"></param>
/// <param name="prefix"></param>
/// <returns></returns>
/// <typeparam name="T">The entity type</typeparam>
/// <param name="excludeColumns">Columns to exclude from the selection</param>
/// <param name="prefix">Optional table prefix/alias</param>
/// <returns>The current SqlBuilder instance for method chaining</returns>
public SqlBuilder SelectAll<T>(Expression<Func<T, object>>[]? excludeColumns, string? prefix = null)
{
return SelectAll<T>(excludeColumns, null, prefix);
Expand All @@ -204,9 +193,9 @@ public SqlBuilder SelectAll<T>(Expression<Func<T, object>>[]? excludeColumns, st
/// <summary>
/// Adds a SELECT * clause for a type, with options to specify a first column.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="firstColumn"></param>
/// <param name="prefix"></param>
/// <typeparam name="T">The entity type</typeparam>
/// <param name="firstColumn">Column to place first in the selection</param>
/// <param name="prefix">Optional table prefix/alias</param>
/// <returns>The current SqlBuilder instance for method chaining</returns>
public SqlBuilder SelectAll<T>(Expression<Func<T, object>>? firstColumn, out string prefix)
{
Expand Down Expand Up @@ -360,14 +349,16 @@ public SqlBuilder From<T>(string? prefix = null)
}

/// <summary>
/// Adds a WHERE clause to the query.
/// Adds a WHERE clause to the query.
/// </summary>
/// <typeparam name="T">The entity type</typeparam>
/// <typeparam name="TResult">The column type</typeparam>
/// <param name="expression">The column expression</param>
/// <param name="value">The value to compare against</param>
/// <param name="op">The comparison operator (defaults to "=")</param>
/// <param name="prefix">Optional table prefix/alias</param>
/// <returns>The current SqlBuilder instance for method chaining</returns>
public SqlBuilder Where(LambdaExpression expression, string value, string op = "=", string? prefix = null)
public SqlBuilder Where<T, TResult>(Expression<Func<T, TResult>> expression, string value, string op = "=", string? prefix = null)
{
sqlBuilder.Append(" WHERE ");
sqlBuilder.Append(Utils.EncodeColumn(Utils.GetColumnName(expression), isSqlServer, prefix, null, false));
Expand All @@ -376,45 +367,42 @@ public SqlBuilder Where(LambdaExpression expression, string value, string op = "
}

/// <summary>
public SqlBuilder Where<T, TResult>(Expression<Func<T, TResult>> expression, string value, string op = "=", string? prefix = null)
/// Adds a WHERE clause to the query.
/// </summary>
/// <param name="rawSql">The raw SQL string</param>
/// <returns>The current SqlBuilder instance for method chaining</returns>
public SqlBuilder Where(string rawSql)
{
return Where((LambdaExpression)expression, value, op, prefix);
sqlBuilder.Append(" WHERE ").Append(rawSql).AppendLine();
return this;
}

/// <summary>
/// Adds an AND condition to the WHERE clause.
/// </summary>
/// <typeparam name="T">The entity type</typeparam>
/// <typeparam name="TResult">The column type</typeparam>
/// <param name="expression">The column expression</param>
/// <param name="value">The value to compare against</param>
/// <param name="op">The comparison operator (defaults to "=")</param>
/// <param name="prefix">Optional table prefix/alias</param>
/// <returns>The current SqlBuilder instance for method chaining</returns>
public SqlBuilder And(LambdaExpression expression, string value, string op = "=", string? prefix = null)
public SqlBuilder And<T, TResult>(Expression<Func<T, TResult>> expression, string value, string op = "=", string? prefix = null)
{
sqlBuilder.Append(" AND ");
sqlBuilder.Append(Utils.EncodeColumn(Utils.GetColumnName(expression), isSqlServer, prefix, null, false));
sqlBuilder.Append(" ").Append(op).Append(" ").Append(value).AppendLine();
return this;
}

public SqlBuilder And<T, TResult>(Expression<Func<T, TResult>> expression, string value, string op = "=", string? prefix = null)
{
return And((LambdaExpression)expression, value, op, prefix);
}

/// <summary>
/// Adds an OR condition to the WHERE clause.
/// Adds an AND condition to the WHERE clause.
/// </summary>
/// <param name="expression">The column expression</param>
/// <param name="value">The value to compare against</param>
/// <param name="op">The comparison operator (defaults to "=")</param>
/// <param name="prefix">Optional table prefix/alias</param>
/// <param name="rawSql">The raw SQL string</param>
/// <returns>The current SqlBuilder instance for method chaining</returns>
public SqlBuilder Or(LambdaExpression expression, string value, string op = "=", string? prefix = null)
public SqlBuilder And(string rawSql)
{
sqlBuilder.Append(" OR ");
sqlBuilder.Append(Utils.EncodeColumn(Utils.GetColumnName(expression), isSqlServer, prefix, null, false));
sqlBuilder.Append(" ").Append(op).Append(" ").Append(value).AppendLine();
sqlBuilder.Append(" AND ").Append(rawSql).AppendLine();
return this;
}

Expand All @@ -430,24 +418,24 @@ public SqlBuilder Or(LambdaExpression expression, string value, string op = "=",
/// <returns></returns>
public SqlBuilder Or<T, TResult>(Expression<Func<T, TResult>> expression, string value, string op = "=", string? prefix = null)
{
return Or((LambdaExpression)expression, value, op, prefix);
sqlBuilder.Append(" OR ");
sqlBuilder.Append(Utils.EncodeColumn(Utils.GetColumnName(expression), isSqlServer, prefix, null, false));
sqlBuilder.Append(" ").Append(op).Append(" ").Append(value).AppendLine();
return this;
}

/// <summary>
/// Adds an ORDER BY clause to the query.
/// Adds an OR condition to the WHERE clause.
/// </summary>
/// <param name="expression">The column expression to order by</param>
/// <param name="ascOrder">Whether to order ascending (true) or descending (false)</param>
/// <param name="prefix">Optional table prefix/alias</param>
/// <param name="rawSql">The raw SQL string</param>
/// <returns>The current SqlBuilder instance for method chaining</returns>
public SqlBuilder OrderBy(LambdaExpression expression, bool ascOrder = true, string? prefix = null)
public SqlBuilder Or(string rawSql)
{
sqlBuilder.Append(" ORDER BY ");
sqlBuilder.Append(Utils.EncodeColumn(Utils.GetColumnName(expression), isSqlServer, prefix, null, false));
sqlBuilder.Append(" ").Append(ascOrder ? "ASC" : "DESC").AppendLine();
sqlBuilder.Append(" OR ").Append(rawSql).AppendLine();
return this;
}


/// <summary>
/// Adds an ORDER BY clause to the query.
/// </summary>
Expand All @@ -459,7 +447,21 @@ public SqlBuilder OrderBy(LambdaExpression expression, bool ascOrder = true, str
/// <returns></returns>
public SqlBuilder OrderBy<T, TResult>(Expression<Func<T, TResult>> expression, bool ascOrder = true, string? prefix = null)
{
return OrderBy((LambdaExpression)expression, ascOrder, prefix);
sqlBuilder.Append(" ORDER BY ");
sqlBuilder.Append(Utils.EncodeColumn(Utils.GetColumnName(expression), isSqlServer, prefix, null, false));
sqlBuilder.Append(" ").Append(ascOrder ? "ASC" : "DESC").AppendLine();
return this;
}

/// <summary>
/// Adds an ORDER BY clause to the query.
/// </summary>
/// <param name="rawSql">The raw SQL string</param>
/// <returns>The current SqlBuilder instance for method chaining</returns>
public SqlBuilder OrderBy(string rawSql, bool ascOrder = true)
{
sqlBuilder.Append(" ORDER BY ").Append(rawSql).Append(" ").Append(ascOrder ? "ASC" : "DESC").AppendLine();
return this;
}

/// <summary>
Expand Down Expand Up @@ -541,6 +543,17 @@ public SqlBuilder FullJoin<TLeft, TRight, TValue>(Expression<Func<TLeft, TValue>
return BuildJoinClause(left, right, leftPrefix, rightPrefix, op);
}

/// <summary>
/// Appends raw SQL to the query.
/// </summary>
/// <param name="rawSql">The raw SQL string</param>
/// <returns>The current SqlBuilder instance for method chaining</returns>
public SqlBuilder AppendRawSql(string rawSql)
{
sqlBuilder.Append(rawSql);
return this;
}

/// <summary>
/// Builds and returns the complete SQL query string.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/SqlBuilder/SqlBuilder.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<RepositoryUrl>https://github.com/guanghuang/SqlBuilder</RepositoryUrl>
<PackageTags>Query;Sql;SqlBuilder</PackageTags>
<Nullable>enable</Nullable>
<Version>1.0.0</Version>
<Version>1.1.0</Version>
<Copyright>Copyright © 2024 Kvr.SqlBuilder. All rights reserved.</Copyright>
</PropertyGroup>
<ItemGroup>
Expand Down

0 comments on commit c778420

Please sign in to comment.