Skip to content

Fixes with prepare_sql #710

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
Oct 10, 2017
Merged

Fixes with prepare_sql #710

merged 3 commits into from
Oct 10, 2017

Conversation

hazzik
Copy link
Member

@hazzik hazzik commented Oct 9, 2017

prepare_sql requires all sizes/scales to be specified upfront.

This PR to be dropped if all tests are successful.

@fredericDelaporte
Copy link
Member

It seems to demonstrate older issues, mainly with Time. That is for Odbc that some size specifications were removed. Not for SQL Client driver. Time was never sized.

@hazzik
Copy link
Member Author

hazzik commented Oct 9, 2017

Ok, then we need to add these sizings

@fredericDelaporte
Copy link
Member

Currently testing that, going to add a Jira. Any way good catch. Since this seems a SQL Client specific trouble, do we add this prepare_sql to the 2012 build by example? Testing 2008 without, 2012 with? Or do we duplicate all SQL Server builds, so long for the total build time?

@fredericDelaporte
Copy link
Member

I have overwritten your merge with a rebase + a quick fix to check if there are other issues than time with SQL Server.

@@ -144,6 +145,9 @@ protected static void SetDefaultParameterSize(DbParameter dbParam, SqlType sqlTy
case DbType.DateTimeOffset:
dbParam.Size = MaxDateTimeOffset;
break;
case DbType.Time:
Copy link
Member Author

@hazzik hazzik Oct 9, 2017

Choose a reason for hiding this comment

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

Ideally, this should be in 2008 driver, as 2005 does not support time and reverts it to DateTime. Same for DateTime2.

Copy link
Member

@fredericDelaporte fredericDelaporte Oct 9, 2017

Choose a reason for hiding this comment

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

And same for DateTimeOffset. Defining defaults for those types supported only for 2008+ in the driver for previous versions is not very sound, excepted that the current pattern of sharing that method with SQL Server Ce, causing it to be static, causes it to be hard to be overridden in 2008 driver.

The reverting for DbType.Time and DbType.Date seems to be a specific "feature" of DbParameter interface implementation for SqlParameter, when setting types through DbType property, forcing us to set them through SqlDbType, and only into 2008 driver.

To clean-up that maybe we should cease sharing with SQL Server CE, switch to instance methods and override them. But it would be a breaking change for those using DateTime2 and DateTimeOffset with the old SQL Server driver.

Copy link
Member

Choose a reason for hiding this comment

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

Another option could be to check the dialect in SqlClientDriver for flagging whether we are using 2008+ or not, and if yes port and use corresponding code from SqlClient2008Driver. That way, no need to override anything anymore in SqlClient2008Driver, which would be then set as obsolete.

@fredericDelaporte
Copy link
Member

fredericDelaporte commented Oct 9, 2017

ODBC, Firebird and PostgreSQL are failing due to to four tests, like NormalHqlShouldThrowUserException, which get another failure than the one expected with ODBC when prepare SQL is enabled.

@fredericDelaporte
Copy link
Member

fredericDelaporte commented Oct 9, 2017

SQL Server CE fails with insufficient memory errors on blob types tests. It seems to be yet another issue.

@fredericDelaporte
Copy link
Member

fredericDelaporte commented Oct 9, 2017

SQL Server CE fails with insufficient memory errors on blob types tests. It seems to be yet another issue.

This occurs only with 32 bits version. The 64 bits does not have the trouble. The root of the trouble is the default sizing of binary parameters to 2Gb when prepare_sql is enabled... This wrecks the 32 bits versions, as if it was trying to allocate such a size two or more times, hitting the 4Gb limit for 32 bits processes. The 64 bits surely does same but with my 16Gb setup, it does not get out of memory.
Disabling parameters sizing removes the trouble for SQL Server CE and let all tests work, although according to its documentation sizing parameters is mandatory when preparing SQL.

So we could fix this NH-4091 by ceasing specifying parameter sizes even when prepare_sql is enabled, which would, by the way, allow to switch this sizing method to an instance and override it for Sql 2008. Or we need to change it for not specifying blob sizes when called by SQL Server CE.

// the test SqlConverter to do its job.
return !(Dialect is MsSqlCeDialect);
var prepareSql = PropertiesHelper.GetBoolean(Environment.PrepareSql, cfg.Properties, false);
return !(prepareSql || Dialect is MsSqlCeDialect);
Copy link
Member Author

Choose a reason for hiding this comment

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

Maybe it shall be only for SqlClientDriver?

Copy link
Member

@fredericDelaporte fredericDelaporte Oct 9, 2017

Choose a reason for hiding this comment

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

return !(prepareSql && !(driver is SqlClientDriver) || Dialect is MsSqlCeDialect);? Or just return driver is SqlClientDriver?

Copy link
Member Author

Choose a reason for hiding this comment

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

Second

Copy link
Member

Choose a reason for hiding this comment

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

I do not really get why it should be considered a Sql Server only test. For me it is more like this tests reveal there is some "too wide" catching in place causing the feature to be unavailable for most databases when prepare is enabled. Anyways, that is a quite secondary feature in my mind, and the code lacks indications as to why this "wide" catch is there, so I do not think we should investigate/fix this point, at least not for 5.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.

Ok, leave it as is

Copy link
Member

Choose a reason for hiding this comment

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

Or maybe more accurately, reveals that the test implementation (closing the connection) is not suitable for most databases when prepare is enabled. Maybe should it instead use a trick (like the nullable no null column in some transactions tests for failures) to alter the schema and use that to cause an actual db side failure.

Copy link
Member

Choose a reason for hiding this comment

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

Well, already changed, with comment corresponding to my last comment just above.

Copy link
Member Author

Choose a reason for hiding this comment

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

Need to regen the async

Copy link
Member

Choose a reason for hiding this comment

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

Done. Thanks for the reminder.

if (prepareSql)
{
SqlClientDriver.SetVariableLengthParameterSize(dbParam, sqlType);
}
Copy link
Member

Choose a reason for hiding this comment

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

What do you think of this removal? It works but is in contradiction with documentation:

Before you call Prepare, specify the data type of each parameter in the statement to be prepared. For each parameter that has a variable-length data type, you must set the Size property to the maximum size needed. Prepare returns an error if these conditions are not met.

Copy link
Member Author

Choose a reason for hiding this comment

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

It is strange that it works.

Copy link
Member

Choose a reason for hiding this comment

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

I dislike it quite. But that is the simplest change to get it work... Otherwise I could move the code from SqlClientDriver into Sql CE driver and adjust it to its needs, meaning removing 2008 stuff and not specifying blob sizes, but letting all the other been set, since it will be more compliant with doc and should work too.

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't think that SqlServer CE requires having all parameter sizes to be set when Prepare is used.

Copy link
Member

Choose a reason for hiding this comment

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

So we just keep that change as is. This PR could then be merged after dropping the first commit.


namespace NHibernate.Driver
{
public class Sql2008ClientDriver : SqlClientDriver
{
public const byte MaxTime = 5;
Copy link
Member Author

@hazzik hazzik Oct 10, 2017

Choose a reason for hiding this comment

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

Why is this 5? It shall be either 7 or 8 (same as datetime2). Ok, it is size in bytes, represents the (16,7) precision

Copy link
Member

Choose a reason for hiding this comment

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

Yes, the same for datetime2 and datetimeoffset, where it wants to knows their size instead of their scale.

Copy link
Member

Choose a reason for hiding this comment

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

About those MaxSizes, I have put it public for mimicking what was done for others. But well, I do not think there is need for that. Maybe time to clean-up a bit the driver by switching back to protected those parameter sizing members.

@fredericDelaporte fredericDelaporte force-pushed the prepare_sql branch 2 times, most recently from d566954 to 224f25f Compare October 10, 2017 07:53
@hazzik hazzik changed the title Set prepare_sql = true to test #703 changes Fixes with prepare_sql Oct 10, 2017
 Although specifying parameters size is documented as mandatory when preparing statements, it appears it still works without.
@hazzik
Copy link
Member Author

hazzik commented Oct 10, 2017

The first commit dropped.

@hazzik hazzik added this to the 5.0 milestone Oct 10, 2017
@hazzik hazzik merged commit a33d88e into master Oct 10, 2017
@fredericDelaporte fredericDelaporte deleted the prepare_sql branch October 10, 2017 09:02
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