Skip to content

Add support for single-argument truncate to dialects that do not support it natively #1597

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 3 commits into from
Mar 9, 2018

Conversation

fredericDelaporte
Copy link
Member

  • Support single parameter truncate, like round.
  • Add PostgreSQL truncate
  • Fix Sybase Anywhere round which was not supporting single parameter calls either.

This is a follow up to #1533, which had made some minimal adjustments on truncate for supporting its specific needs. Its subject was not truncate, so complete fix had to be done in another PR.

 * Support single parameter truncate, like round.
 * Add PostgreSQL truncate
 * Fix Sybase Anywhere round which was not supporting single parameter calls either.
RegisterFunction("round", new RoundFunction());
RegisterFunction("round", new RoundFunction(false));
RegisterFunction("truncate", new RoundFunction(true));
RegisterFunction("trunc", new RoundFunction(true));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As written here, I consider supporting dialect specific names (trunc here) as a bad practice. But since there is some disagreement about this, I will not fight against it and so I am still adding it here.

@@ -140,12 +140,13 @@ protected virtual void RegisterMathFunctions()
RegisterFunction("radians", new StandardSQLFunction("radians", NHibernateUtil.Double));
RegisterFunction("rand", new StandardSQLFunction("rand", NHibernateUtil.Double));
RegisterFunction("remainder", new StandardSQLFunction("remainder"));
RegisterFunction("round", new StandardSQLFunction("round"));
RegisterFunction("round", new RoundEmulatingSingleParameterFunction("round"));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested with an Anywhere 17, using this custom driver.

RegisterFunction("sign", new StandardSQLFunction("sign", NHibernateUtil.Int32));
RegisterFunction("sin", new StandardSQLFunction("sin", NHibernateUtil.Double));
RegisterFunction("sqrt", new StandardSQLFunction("sqrt", NHibernateUtil.Double));
RegisterFunction("tan", new StandardSQLFunction("tan", NHibernateUtil.Double));
RegisterFunction("truncate", new StandardSQLFunction("truncate"));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed, it was an invalid registration.

@@ -343,8 +344,6 @@ protected virtual void RegisterMiscellaneousFunctions()
RegisterFunction("transactsql", new StandardSQLFunction("transactsql", NHibernateUtil.String));
RegisterFunction("varexists", new StandardSQLFunction("varexists", NHibernateUtil.Int32));
RegisterFunction("watcomsql", new StandardSQLFunction("watcomsql", NHibernateUtil.String));
RegisterFunction("truncnum", new StandardSafeSQLFunction("truncnum", 2));
RegisterFunction("truncate", new StandardSafeSQLFunction("truncnum", 2));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to RegisterMathFunctions (and adjusted).

@hazzik
Copy link
Member

hazzik commented Mar 7, 2018

I would not say that this is a bugfix. It's rather an improvement.

/// Constructs a <c>RoundEmulatingSingleParameterFunction</c>.
/// </summary>
/// <param name="name">The SQL name of the round function to call.</param>
public RoundEmulatingSingleParameterFunction(string name)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Class is public, so you need to add a default constructor.

Copy link
Member Author

@fredericDelaporte fredericDelaporte Mar 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For avoiding a breaking change? This class has not yet been released. It was not existing in 5.0.3.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Fine then.

@@ -24,9 +35,9 @@ public class RoundEmulatingSingleParameterFunction : ISQLFunction

public SqlString Render(IList args, ISessionFactoryImplementor factory)
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be much lightweight if we rewrite this function explicitly not using the template functions

Copy link
Member Author

@fredericDelaporte fredericDelaporte Mar 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either I do not get what you are thinking about, or it will be slightly more CPU lightweight but with a lot more code, rewriting a SqlString generation just for this case. For the later I do not think it is worth it.

var buf = new SqlStringBuilder();
buf.Add(_name)
   .Add("(");
for (var i = 0; i < args.Count; i++)
{
	var arg = args[i];
	if (arg is Parameter || arg is SqlString)
	{
		buf.AddObject(arg);
	}
	else
	{
		buf.Add(arg.ToString());
	}
	if (i < (args.Count - 1)) buf.Add(", ");
}

if (args.Count == 1)
	buf.Add(", 0");
return buf.Add(")").ToSqlString();

And this is an almost duplicate of StandardSQLFunction.

Copy link
Member

@hazzik hazzik Mar 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would you need a loop here? You have 2 arguments.

if (args.Count != 1 && args.Count != 2) throw new ... ;
return new SqlString(
  _name,
  "(",
  args[0],
  ", ",
  args.Count > 1 ? args[1] : "0",
  ")"
)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be breaking for dialects supporting more than two arguments (SQL-Server round case).

@hazzik
Copy link
Member

hazzik commented Mar 9, 2018

Sent you a PR fredericDelaporte#3 with another approach.

@hazzik hazzik changed the title Fix truncate registration. Add support for single-argument truncate for dialects which do not support it natively Mar 9, 2018
@hazzik hazzik changed the title Add support for single-argument truncate for dialects which do not support it natively Add support for single-argument truncate to dialects that do not support it natively Mar 9, 2018
@fredericDelaporte fredericDelaporte added this to the 5.1 milestone Mar 9, 2018
@hazzik hazzik merged commit d2e8cc3 into nhibernate:master Mar 9, 2018
@hazzik hazzik added the r: Fixed label Mar 9, 2018
@fredericDelaporte fredericDelaporte deleted the Truncate branch March 9, 2018 12:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants