chore: initial git load of code space
This commit is contained in:
@@ -0,0 +1,238 @@
|
||||
using Strata.SqlTools.SqlBreakdown.Interfaces.Core;
|
||||
|
||||
using Strata.SqlTools.SqlBreakdown.Expressions.Arithmetic;
|
||||
using Strata.SqlTools.SqlBreakdown.Expressions.Conditional.Comparisons;
|
||||
using Strata.SqlTools.SqlBreakdown.Expressions.Literals;
|
||||
|
||||
namespace Strata.SqlTools.SqlBreakdown.Expressions;
|
||||
|
||||
/// <summary>
|
||||
/// Abstract base class for all SQL expression types. Provides operator overloading for
|
||||
/// building complex SQL expressions using C# operators and implicit conversions for
|
||||
/// common value types.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class enables type-safe SQL expression building using familiar C# syntax.
|
||||
/// Supports arithmetic operators (+, -, *, /), comparison operators (==, !=, >, <, >=, <=),
|
||||
/// and implicit conversions from common .NET types. All derived expression classes
|
||||
/// implement the visitor pattern through <see cref="Accept{T}"/> for SQL generation.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <code language="csharp">
|
||||
/// // Build expressions using operators
|
||||
/// var price = new GenericColumnExpression("Price", "Products");
|
||||
/// var discount = new GenericColumnExpression("Discount", "Products");
|
||||
///
|
||||
/// // Arithmetic operations
|
||||
/// var discountedPrice = price * (1.0m - discount);
|
||||
///
|
||||
/// // Comparison operations
|
||||
/// var affordableItems = price <= 100;
|
||||
/// var expensiveItems = price > 1000;
|
||||
///
|
||||
/// // Implicit conversions from literals
|
||||
/// Expression literalNumber = 42.5m;
|
||||
/// Expression literalString = "Sample";
|
||||
/// Expression literalDate = new DateTime(2024, 1, 1);
|
||||
///
|
||||
/// // Factory method for dynamic values
|
||||
/// Expression valueFromObject = Expression.FromObject(someValue);
|
||||
/// </code>
|
||||
/// </example>
|
||||
public abstract class Expression
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines whether the specified object is equal to the current expression.
|
||||
/// Uses reference equality since the == operator is overloaded for SQL expression building.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to compare with the current expression.</param>
|
||||
/// <returns>True if the specified object is the same instance; otherwise, false.</returns>
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return ReferenceEquals(this, obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hash code for this expression instance.
|
||||
/// Uses the base implementation for reference-based hashing.
|
||||
/// </summary>
|
||||
/// <returns>A hash code for the current expression.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Accepts a visitor for the visitor pattern, allowing different SQL generation
|
||||
/// strategies.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The return type of the visitor.</typeparam>
|
||||
/// <param name="visitor">
|
||||
/// The visitor instance that will process this expression.
|
||||
/// </param>
|
||||
/// <returns>The result from the visitor's processing of this expression.</returns>
|
||||
public abstract T Accept<T>(IVisitor<T> visitor);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an appropriate expression from a .NET object value. Automatically converts
|
||||
/// common types to their corresponding literal expressions.
|
||||
/// </summary>
|
||||
/// <param name="value">
|
||||
/// The object to convert. Supported types include numeric types (short, int, long,
|
||||
/// double, decimal), bool, DateTime, DateOnly, DateTimeOffset, and string.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A literal expression representing the value. Returns
|
||||
/// <see cref="NullLiteralExpression"/> for null values.
|
||||
/// </returns>
|
||||
/// <example>
|
||||
/// <code language="csharp">
|
||||
/// // Numeric types become NumberLiteralExpression
|
||||
/// var num = Expression.FromObject(42);
|
||||
///
|
||||
/// // Boolean values become BooleanLiteralExpression
|
||||
/// var flag = Expression.FromObject(true);
|
||||
///
|
||||
/// // DateTime values become DateTimeLiteralExpression
|
||||
/// var date = Expression.FromObject(DateTime.Now);
|
||||
///
|
||||
/// // Strings become StringLiteralExpression
|
||||
/// var text = Expression.FromObject("example");
|
||||
///
|
||||
/// // Null becomes NullLiteralExpression
|
||||
/// var nullValue = Expression.FromObject(null);
|
||||
/// </code>
|
||||
/// </example>
|
||||
public static Expression FromObject(object? value)
|
||||
{
|
||||
return value switch
|
||||
{
|
||||
null => new NullLiteralExpression(),
|
||||
short s => new NumberLiteralExpression(s),
|
||||
int i => new NumberLiteralExpression(i),
|
||||
long l => new NumberLiteralExpression(l),
|
||||
double d => new NumberLiteralExpression((decimal)d),
|
||||
decimal m => new NumberLiteralExpression(m),
|
||||
bool b => new BooleanLiteralExpression(b),
|
||||
DateOnly d => new DateTimeLiteralExpression(d.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc)),
|
||||
DateTime dt => new DateTimeLiteralExpression(dt),
|
||||
DateTimeOffset dto => new DateTimeLiteralExpression(dto.UtcDateTime),
|
||||
string s when DateTime.TryParse(s, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out var dt) => new DateTimeLiteralExpression(dt),
|
||||
_ when value.ToString() == null => new NullLiteralExpression(),
|
||||
_ => new StringLiteralExpression(value.ToString()!)
|
||||
};
|
||||
}
|
||||
|
||||
#region Literal Value Implicit Operators
|
||||
/// <summary>
|
||||
/// Implicitly converts a decimal number to a
|
||||
/// <see cref="NumberLiteralExpression"/>.
|
||||
/// </summary>
|
||||
/// <param name="number">The numeric value.</param>
|
||||
public static implicit operator Expression(decimal number) => new NumberLiteralExpression(number);
|
||||
|
||||
/// <summary>
|
||||
/// Implicitly converts a string to a <see cref="StringLiteralExpression"/>.
|
||||
/// </summary>
|
||||
/// <param name="value">The string value.</param>
|
||||
public static implicit operator Expression(string value) => new StringLiteralExpression(value);
|
||||
|
||||
/// <summary>
|
||||
/// Implicitly converts a DateTime to a <see cref="DateTimeLiteralExpression"/>.
|
||||
/// </summary>
|
||||
/// <param name="dateTime">The DateTime value.</param>
|
||||
public static implicit operator Expression(DateTime dateTime) => new DateTimeLiteralExpression(dateTime);
|
||||
|
||||
/// <summary>
|
||||
/// Implicitly converts a DateOnly to a <see cref="DateTimeLiteralExpression"/>.
|
||||
/// </summary>
|
||||
/// <param name="date">The DateOnly value.</param>
|
||||
public static implicit operator Expression(DateOnly date) => new DateTimeLiteralExpression(date.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc));
|
||||
#endregion
|
||||
|
||||
#region Comparison Operators
|
||||
/// <summary>
|
||||
/// Creates an equality comparison expression (=).
|
||||
/// </summary>
|
||||
/// <param name="a">The left expression.</param>
|
||||
/// <param name="b">The right expression.</param>
|
||||
/// <returns>An <see cref="EqualToExpression"/>.</returns>
|
||||
public static ComparisonOperatorExpression operator ==(Expression a, Expression b) => new EqualToExpression(a, b);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an inequality comparison expression (!=).
|
||||
/// </summary>
|
||||
/// <param name="a">The left expression.</param>
|
||||
/// <param name="b">The right expression.</param>
|
||||
/// <returns>A <see cref="NotEqualToExpression"/>.</returns>
|
||||
public static ComparisonOperatorExpression operator !=(Expression a, Expression b) => new NotEqualToExpression(a, b);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a greater-than comparison expression (>).
|
||||
/// </summary>
|
||||
/// <param name="a">The left expression.</param>
|
||||
/// <param name="b">The right expression.</param>
|
||||
/// <returns>A <see cref="GreaterThanExpression"/>.</returns>
|
||||
public static ComparisonOperatorExpression operator >(Expression a, Expression b) => new GreaterThanExpression(a, b);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a less-than comparison expression (<).
|
||||
/// </summary>
|
||||
/// <param name="a">The left expression.</param>
|
||||
/// <param name="b">The right expression.</param>
|
||||
/// <returns>A <see cref="LessThanExpression"/>.</returns>
|
||||
public static ComparisonOperatorExpression operator <(Expression a, Expression b) => new LessThanExpression(a, b);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a greater-than-or-equal comparison expression (>=).
|
||||
/// </summary>
|
||||
/// <param name="a">The left expression.</param>
|
||||
/// <param name="b">The right expression.</param>
|
||||
/// <returns>A <see cref="GreaterThanOrEqualToExpression"/>.</returns>
|
||||
public static ComparisonOperatorExpression operator >=(Expression a, Expression b) => new GreaterThanOrEqualToExpression(a, b);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a less-than-or-equal comparison expression (<=).
|
||||
/// </summary>
|
||||
/// <param name="a">The left expression.</param>
|
||||
/// <param name="b">The right expression.</param>
|
||||
/// <returns>A <see cref="LessThanOrEqualToExpression"/>.</returns>
|
||||
public static ComparisonOperatorExpression operator <=(Expression a, Expression b) => new LessThanOrEqualToExpression(a, b);
|
||||
#endregion
|
||||
|
||||
#region Arithmetic Operators
|
||||
/// <summary>
|
||||
/// Creates an addition expression (+).
|
||||
/// </summary>
|
||||
/// <param name="a">The left expression.</param>
|
||||
/// <param name="b">The right expression.</param>
|
||||
/// <returns>An <see cref="AdditionExpression"/>.</returns>
|
||||
public static ArithmeticExpression operator +(Expression a, Expression b) => new AdditionExpression(a, b);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a subtraction expression (-).
|
||||
/// </summary>
|
||||
/// <param name="a">The left expression.</param>
|
||||
/// <param name="b">The right expression.</param>
|
||||
/// <returns>A <see cref="SubtractionExpression"/>.</returns>
|
||||
public static ArithmeticExpression operator -(Expression a, Expression b) => new SubtractionExpression(a, b);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a multiplication expression (*).
|
||||
/// </summary>
|
||||
/// <param name="a">The left expression.</param>
|
||||
/// <param name="b">The right expression.</param>
|
||||
/// <returns>A <see cref="MultiplicationExpression"/>.</returns>
|
||||
public static ArithmeticExpression operator *(Expression a, Expression b) => new MultiplicationExpression(a, b);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a division expression (/).
|
||||
/// </summary>
|
||||
/// <param name="a">The left expression.</param>
|
||||
/// <param name="b">The right expression.</param>
|
||||
/// <returns>A <see cref="DivisionExpression"/>.</returns>
|
||||
public static ArithmeticExpression operator /(Expression a, Expression b) => new DivisionExpression(a, b);
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user