Skip to content

Add multiple arguments support for ISQLFunction #2316

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Apr 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/NHibernate/Criterion/SqlFunctionProjection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ private IType GetReturnType(ICriteria criteria, ICriteriaQuery criteriaQuery)

var resultType = returnType ?? returnTypeProjection?.GetTypes(criteria, criteriaQuery).FirstOrDefault();

return sqlFunction.ReturnType(resultType, criteriaQuery.Factory);
return sqlFunction.GetReturnType(new[] {resultType}, criteriaQuery.Factory, true);
}

public override TypedValue[] GetTypedValues(ICriteria criteria, ICriteriaQuery criteriaQuery)
Expand Down
2 changes: 1 addition & 1 deletion src/NHibernate/Dialect/DB2Dialect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public DB2Dialect()
RegisterFunction("length", new StandardSQLFunction("length", NHibernateUtil.Int32));
RegisterFunction("ltrim", new StandardSQLFunction("ltrim"));

RegisterFunction("mod", new StandardSQLFunction("mod", NHibernateUtil.Int32));
RegisterFunction("mod", new ModulusFunction(true, false));

RegisterFunction("substring", new StandardSQLFunction("substr", NHibernateUtil.String));

Expand Down
2 changes: 1 addition & 1 deletion src/NHibernate/Dialect/Dialect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ protected Dialect()
RegisterFunction("coalesce", new StandardSQLFunction("coalesce"));
RegisterFunction("nullif", new StandardSQLFunction("nullif"));
RegisterFunction("abs", new StandardSQLFunction("abs"));
RegisterFunction("mod", new StandardSQLFunction("mod", NHibernateUtil.Int32));
RegisterFunction("mod", new ModulusFunction(false, false));
RegisterFunction("sqrt", new StandardSQLFunction("sqrt", NHibernateUtil.Double));
RegisterFunction("upper", new StandardSQLFunction("upper"));
RegisterFunction("lower", new StandardSQLFunction("lower"));
Expand Down
29 changes: 24 additions & 5 deletions src/NHibernate/Dialect/FirebirdDialect.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using NHibernate.Dialect.Function;
Expand Down Expand Up @@ -147,7 +148,7 @@ public CastedFunction(string name, IType returnType) : base(name, returnType, fa

public override SqlString Render(IList args, ISessionFactoryImplementor factory)
{
return new SqlString("cast('", Name, "' as ", FunctionReturnType.SqlTypes(factory)[0].ToString(), ")");
return new SqlString("cast('", FunctionName, "' as ", FunctionReturnType.SqlTypes(factory)[0].ToString(), ")");
}
}

Expand All @@ -160,7 +161,7 @@ public CurrentTimeStamp() : base("current_timestamp", NHibernateUtil.LocalDateTi

public override SqlString Render(IList args, ISessionFactoryImplementor factory)
{
return new SqlString(Name);
return new SqlString(FunctionName);
}
}

Expand Down Expand Up @@ -205,7 +206,7 @@ public override string SelectGUIDString
}

[Serializable]
private class PositionFunction : ISQLFunction
private class PositionFunction : ISQLFunction, ISQLFunctionExtended
{
// The cast is needed, at least in the case that ?3 is a named integer parameter, otherwise firebird will generate an error.
// We have a unit test to cover this potential firebird bug.
Expand All @@ -214,11 +215,28 @@ private class PositionFunction : ISQLFunction
private static readonly ISQLFunction LocateWith3Params = new SQLFunctionTemplate(NHibernateUtil.Int32,
"position(?1, ?2, cast(?3 as int))");

// Since v5.3
[Obsolete("Use GetReturnType method instead.")]
public IType ReturnType(IType columnType, IMapping mapping)
{
return NHibernateUtil.Int32;
}

/// <inheritdoc />
public IType GetReturnType(IEnumerable<IType> argumentTypes, IMapping mapping, bool throwOnError)
{
return NHibernateUtil.Int32;
}

/// <inheritdoc />
public IType GetEffectiveReturnType(IEnumerable<IType> argumentTypes, IMapping mapping, bool throwOnError)
{
return GetReturnType(argumentTypes, mapping, throwOnError);
}

/// <inheritdoc />
public string FunctionName => "position";

public bool HasArguments
{
get { return true; }
Expand Down Expand Up @@ -418,7 +436,8 @@ private void OverrideStandardHQLFunctions()
RegisterFunction("nullif", new StandardSafeSQLFunction("nullif", 2));
RegisterFunction("lower", new StandardSafeSQLFunction("lower", NHibernateUtil.String, 1));
RegisterFunction("upper", new StandardSafeSQLFunction("upper", NHibernateUtil.String, 1));
RegisterFunction("mod", new StandardSafeSQLFunction("mod", NHibernateUtil.Double, 2));
// Modulo does not throw for decimal parameters but they are casted to int by Firebird, which produces unexpected results
RegisterFunction("mod", new ModulusFunction(false, false));
RegisterFunction("str", new SQLFunctionTemplate(NHibernateUtil.String, "cast(?1 as VARCHAR(255))"));
RegisterFunction("strguid", new StandardSQLFunction("uuid_to_char", NHibernateUtil.String));
RegisterFunction("sysdate", new CastedFunction("today", NHibernateUtil.Date));
Expand All @@ -437,7 +456,7 @@ private void RegisterFirebirdServerEmbeddedFunctions()
RegisterFunction("yesterday", new CastedFunction("yesterday", NHibernateUtil.Date));
RegisterFunction("tomorrow", new CastedFunction("tomorrow", NHibernateUtil.Date));
RegisterFunction("now", new CastedFunction("now", NHibernateUtil.DateTime));
RegisterFunction("iif", new StandardSafeSQLFunction("iif", 3));
RegisterFunction("iif", new IifSafeSQLFunction());
// New embedded functions in FB 2.0 (http://www.firebirdsql.org/rlsnotes20/rnfbtwo-str.html#str-string-func)
RegisterFunction("char_length", new StandardSafeSQLFunction("char_length", NHibernateUtil.Int64, 1));
RegisterFunction("bit_length", new StandardSafeSQLFunction("bit_length", NHibernateUtil.Int64, 1));
Expand Down
23 changes: 22 additions & 1 deletion src/NHibernate/Dialect/Function/AnsiSubstringFunction.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate.Engine;
using NHibernate.SqlCommand;
Expand All @@ -22,15 +24,34 @@ namespace NHibernate.Dialect.Function
///]]>
/// </remarks>
[Serializable]
public class AnsiSubstringFunction : ISQLFunction
public class AnsiSubstringFunction : ISQLFunction, ISQLFunctionExtended
{
#region ISQLFunction Members

// Since v5.3
[Obsolete("Use GetReturnType method instead.")]
public IType ReturnType(IType columnType, IMapping mapping)
{
return NHibernateUtil.String;
}

/// <inheritdoc />
public IType GetReturnType(IEnumerable<IType> argumentTypes, IMapping mapping, bool throwOnError)
{
#pragma warning disable 618
return ReturnType(argumentTypes.FirstOrDefault(), mapping);
#pragma warning restore 618
}

/// <inheritdoc />
public IType GetEffectiveReturnType(IEnumerable<IType> argumentTypes, IMapping mapping, bool throwOnError)
{
return GetReturnType(argumentTypes, mapping, throwOnError);
}

/// <inheritdoc />
public string FunctionName => "substring";

public bool HasArguments
{
get { return true; }
Expand Down
23 changes: 21 additions & 2 deletions src/NHibernate/Dialect/Function/AnsiTrimEmulationFunction.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;

using System.Linq;
using NHibernate.Engine;
using NHibernate.SqlCommand;
using NHibernate.Type;
Expand All @@ -17,7 +17,7 @@ namespace NHibernate.Dialect.Function
/// functionality.
/// </summary>
[Serializable]
public class AnsiTrimEmulationFunction : ISQLFunction, IFunctionGrammar
public class AnsiTrimEmulationFunction : ISQLFunction, IFunctionGrammar, ISQLFunctionExtended
{
private static readonly ISQLFunction LeadingSpaceTrim = new SQLFunctionTemplate(NHibernateUtil.String, "ltrim( ?1 )");
private static readonly ISQLFunction TrailingSpaceTrim = new SQLFunctionTemplate(NHibernateUtil.String, "rtrim( ?1 )");
Expand Down Expand Up @@ -76,11 +76,30 @@ public AnsiTrimEmulationFunction(string replaceFunction)

#region ISQLFunction Members

// Since v5.3
[Obsolete("Use GetReturnType method instead.")]
public IType ReturnType(IType columnType, IMapping mapping)
{
return NHibernateUtil.String;
}

/// <inheritdoc />
public IType GetReturnType(IEnumerable<IType> argumentTypes, IMapping mapping, bool throwOnError)
{
#pragma warning disable 618
return ReturnType(argumentTypes.FirstOrDefault(), mapping);
#pragma warning restore 618
}

/// <inheritdoc />
public IType GetEffectiveReturnType(IEnumerable<IType> argumentTypes, IMapping mapping, bool throwOnError)
{
return GetReturnType(argumentTypes, mapping, throwOnError);
}

/// <inheritdoc />
public string FunctionName => null;

public bool HasArguments
{
get { return true; }
Expand Down
29 changes: 12 additions & 17 deletions src/NHibernate/Dialect/Function/AvgQueryFunctionInfo.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using NHibernate.Engine;
using NHibernate.SqlTypes;
using NHibernate.Type;

namespace NHibernate.Dialect.Function
Expand All @@ -10,27 +10,22 @@ class AvgQueryFunctionInfo : ClassicAggregateFunction
{
public AvgQueryFunctionInfo() : base("avg", false) { }

// Since v5.3
[Obsolete("Use GetReturnType method instead.")]
public override IType ReturnType(IType columnType, IMapping mapping)
{
if (columnType == null)
{
throw new ArgumentNullException("columnType");
}
SqlType[] sqlTypes;
try
{
sqlTypes = columnType.SqlTypes(mapping);
}
catch (MappingException me)
{
throw new QueryException(me);
}
return GetReturnType(new[] {columnType}, mapping, true);
}

if (sqlTypes.Length != 1)
/// <inheritdoc />
public override IType GetReturnType(IEnumerable<IType> argumentTypes, IMapping mapping, bool throwOnError)
{
if (!TryGetArgumentType(argumentTypes, mapping, throwOnError, out _, out _))
{
throw new QueryException("multi-column type can not be in avg()");
return null;
}

return NHibernateUtil.Double;
}
}
}
}
24 changes: 23 additions & 1 deletion src/NHibernate/Dialect/Function/BitwiseFunctionOperation.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using NHibernate.Engine;
using NHibernate.SqlCommand;
using NHibernate.Type;
Expand Down Expand Up @@ -27,8 +29,9 @@ namespace NHibernate.Dialect.Function
/// Treats bitwise operations as SQL function calls.
/// </summary>
[Serializable]
public class BitwiseFunctionOperation : ISQLFunction
public class BitwiseFunctionOperation : ISQLFunction, ISQLFunctionExtended
{
// TODO 6.0: convert FunctionName to read-only auto-property
private readonly string _functionName;

/// <summary>
Expand All @@ -45,11 +48,30 @@ public BitwiseFunctionOperation(string functionName)
#region ISQLFunction Members

/// <inheritdoc />
// Since v5.3
[Obsolete("Use GetReturnType method instead.")]
public IType ReturnType(IType columnType, IMapping mapping)
{
return NHibernateUtil.Int64;
}

/// <inheritdoc />
public IType GetReturnType(IEnumerable<IType> argumentTypes, IMapping mapping, bool throwOnError)
{
#pragma warning disable 618
return ReturnType(argumentTypes.FirstOrDefault(), mapping);
#pragma warning restore 618
}

/// <inheritdoc />
public virtual IType GetEffectiveReturnType(IEnumerable<IType> argumentTypes, IMapping mapping, bool throwOnError)
{
return GetReturnType(argumentTypes, mapping, throwOnError);
}

/// <inheritdoc />
public string FunctionName => _functionName;

/// <inheritdoc />
public bool HasArguments => true;

Expand Down
23 changes: 22 additions & 1 deletion src/NHibernate/Dialect/Function/BitwiseNativeOperation.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using NHibernate.Engine;
using NHibernate.SqlCommand;
using NHibernate.Type;
Expand Down Expand Up @@ -32,7 +34,7 @@ namespace NHibernate.Dialect.Function
/// Treats bitwise operations as native operations.
/// </summary>
[Serializable]
public class BitwiseNativeOperation : ISQLFunction
public class BitwiseNativeOperation : ISQLFunction, ISQLFunctionExtended
{
private readonly string _sqlOpToken;
private readonly bool _isUnary;
Expand Down Expand Up @@ -65,11 +67,30 @@ public BitwiseNativeOperation(string sqlOpToken, bool isUnary)
#region ISQLFunction Members

/// <inheritdoc />
// Since v5.3
[Obsolete("Use GetReturnType method instead.")]
public IType ReturnType(IType columnType, IMapping mapping)
{
return NHibernateUtil.Int64;
}

/// <inheritdoc />
public IType GetReturnType(IEnumerable<IType> argumentTypes, IMapping mapping, bool throwOnError)
{
#pragma warning disable 618
return ReturnType(argumentTypes.FirstOrDefault(), mapping);
#pragma warning restore 618
}

/// <inheritdoc />
public virtual IType GetEffectiveReturnType(IEnumerable<IType> argumentTypes, IMapping mapping, bool throwOnError)
{
return GetReturnType(argumentTypes, mapping, throwOnError);
}

/// <inheritdoc />
public string FunctionName => null;

/// <inheritdoc />
public bool HasArguments => true;

Expand Down
23 changes: 22 additions & 1 deletion src/NHibernate/Dialect/Function/CastFunction.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using NHibernate.Engine;
using NHibernate.SqlCommand;
Expand All @@ -12,17 +14,36 @@ namespace NHibernate.Dialect.Function
/// ANSI-SQL style cast(foo as type) where the type is a NHibernate type
/// </summary>
[Serializable]
public class CastFunction : ISQLFunction, IFunctionGrammar
public class CastFunction : ISQLFunction, IFunctionGrammar, ISQLFunctionExtended
{
#region ISQLFunction Members

// Since v5.3
[Obsolete("Use GetReturnType method instead.")]
public IType ReturnType(IType columnType, IMapping mapping)
{
//note there is a weird implementation in the client side
//TODO: cast that use only costant are not supported in SELECT. Ex: cast(5 as string)
return columnType;
}

/// <inheritdoc />
public IType GetReturnType(IEnumerable<IType> argumentTypes, IMapping mapping, bool throwOnError)
{
#pragma warning disable 618
return ReturnType(argumentTypes.FirstOrDefault(), mapping);
#pragma warning restore 618
}

/// <inheritdoc />
public virtual IType GetEffectiveReturnType(IEnumerable<IType> argumentTypes, IMapping mapping, bool throwOnError)
{
return GetReturnType(argumentTypes, mapping, throwOnError);
}

/// <inheritdoc />
public string FunctionName => "cast";

public bool HasArguments
{
get { return true; }
Expand Down
Loading