Skip to content

Fix SQLite/SqlCE validation failure on tables with a schema #1790

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
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by AsyncGenerator.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------


using System;
using NHibernate.Dialect;
using NHibernate.Util;
using NUnit.Framework;

namespace NHibernate.Test.Tools.hbm2ddl.SchemaValidator
{
using System.Threading.Tasks;
[TestFixture]
public class SchemaValidateTableWithSchemaFixtureAsync : TestCase
{
protected override string MappingsAssembly => "NHibernate.Test";

protected override string[] Mappings => new[] { "Tools.hbm2ddl.SchemaValidator.VersionWithSchema.hbm.xml" };

protected override bool AppliesTo(Dialect.Dialect dialect)
{
switch (Dialect)
{
case MsSql2000Dialect _:
case PostgreSQLDialect _:
case SQLiteDialect _:
case MsSqlCeDialect _:
return true;
default:
// Firebird does not support schema. Its current dialect leave table name being schema prefixed,
// which causes SQL parse errors. It has a "create schema" command but instead creates a new
// database.
// MySql does not truly support schema. Its current dialect leave table name being schema prefixed,
// which is interpreted as a database name. It has a "create schema" command but instead creates
// a new database.
// Oracle tightly bounds schema to users.
return false;
}
}

protected override void CreateSchema()
{
switch (Dialect)
{
case MsSql2000Dialect _:
case PostgreSQLDialect _:
// Must handle the schema manually: mapped database-objects are handled too late.
var cnx = Sfi.ConnectionProvider.GetConnection();
try
{
using (var cmd = cnx.CreateCommand())
{
cmd.CommandText = "create schema Test";
cmd.ExecuteNonQuery();
}
}
catch (Exception ex)
{
// Unfortunateley Assert.Warn and Console.WriteLine at this place seems to be ignored in Rider
// viewer.
Assert.Warn("Creating the schema failed, assuming it already exists. {0}", ex);
Console.WriteLine("Creating the schema failed, assuming it already exists.");
Console.WriteLine(ex);
}
finally
{
Sfi.ConnectionProvider.CloseConnection(cnx);
}
break;
}
base.CreateSchema();
}

protected override void DropSchema()
{
// SQL-Server does not need this call, but Postgres does not accept dropping a schema carrying objects.
base.DropSchema();

switch (Dialect)
{
case MsSql2000Dialect _:
case PostgreSQLDialect _:
var cnx = Sfi.ConnectionProvider.GetConnection();
try
{
using (var cmd = cnx.CreateCommand())
{
cmd.CommandText = "drop schema Test";
cmd.ExecuteNonQuery();
}
}
finally
{
Sfi.ConnectionProvider.CloseConnection(cnx);
}
break;
}
}

[Test]
public async Task ShouldVerifyAsync()
{
var validator = new Tool.hbm2ddl.SchemaValidator(cfg);
try
{
await (validator.ValidateAsync());
}
catch (SchemaValidationException sve)
{
Assert.Fail("Validation failed: {0}.\n{1}", StringHelper.CollectionToString(sve.ValidationErrors), sve);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
using System;
using NHibernate.Dialect;
using NHibernate.Util;
using NUnit.Framework;

namespace NHibernate.Test.Tools.hbm2ddl.SchemaValidator
{
[TestFixture]
public class SchemaValidateTableWithSchemaFixture : TestCase
{
protected override string MappingsAssembly => "NHibernate.Test";

protected override string[] Mappings => new[] { "Tools.hbm2ddl.SchemaValidator.VersionWithSchema.hbm.xml" };

protected override bool AppliesTo(Dialect.Dialect dialect)
{
switch (Dialect)
{
case MsSql2000Dialect _:
case PostgreSQLDialect _:
case SQLiteDialect _:
Copy link
Member

Choose a reason for hiding this comment

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

SQL Ce uses the same pattern as SQLiteDialect

Copy link
Member Author

Choose a reason for hiding this comment

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

Indeed, done two years later in e79f47e. Now I have checked Dialect.Qualify overrides, no other database does that, although Firebird and MySql do not support schema either.

(Firebird may be fixed by overriding Qualify for ignoring catalog and schema; I think it is better than introducing the hack in it. MySql should ideally be fixed for ignoring schema; but this may be a breaking change for people "benefiting" of the current behavior handling schema like a catalog (provided catalog is not supplied at the same time). Anyway both cases would have to be handled in another PRs.)

case MsSqlCeDialect _:
return true;
default:
// Firebird does not support schema. Its current dialect leave table name being schema prefixed,
// which causes SQL parse errors. It has a "create schema" command but instead creates a new
// database.
// MySql does not truly support schema. Its current dialect leave table name being schema prefixed,
// which is interpreted as a database name. It has a "create schema" command but instead creates
// a new database.
// Oracle tightly bounds schema to users.
return false;
}
}

protected override void CreateSchema()
{
switch (Dialect)
{
case MsSql2000Dialect _:
case PostgreSQLDialect _:
// Must handle the schema manually: mapped database-objects are handled too late.
var cnx = Sfi.ConnectionProvider.GetConnection();
try
{
using (var cmd = cnx.CreateCommand())
{
cmd.CommandText = "create schema Test";
cmd.ExecuteNonQuery();
}
}
catch (Exception ex)
{
// Unfortunateley Assert.Warn and Console.WriteLine at this place seems to be ignored in Rider
// viewer.
Assert.Warn("Creating the schema failed, assuming it already exists. {0}", ex);
Console.WriteLine("Creating the schema failed, assuming it already exists.");
Console.WriteLine(ex);
}
finally
{
Sfi.ConnectionProvider.CloseConnection(cnx);
}
break;
}
base.CreateSchema();
}

protected override void DropSchema()
{
// SQL-Server does not need this call, but Postgres does not accept dropping a schema carrying objects.
base.DropSchema();

switch (Dialect)
{
case MsSql2000Dialect _:
case PostgreSQLDialect _:
var cnx = Sfi.ConnectionProvider.GetConnection();
try
{
using (var cmd = cnx.CreateCommand())
{
cmd.CommandText = "drop schema Test";
cmd.ExecuteNonQuery();
}
}
finally
{
Sfi.ConnectionProvider.CloseConnection(cnx);
}
break;
}
}

[Test]
public void ShouldVerify()
{
var validator = new Tool.hbm2ddl.SchemaValidator(cfg);
try
{
validator.Validate();
}
catch (SchemaValidationException sve)
{
Assert.Fail("Validation failed: {0}.\n{1}", StringHelper.CollectionToString(sve.ValidationErrors), sve);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="NHibernate.Test.Tools.hbm2ddl.SchemaValidator"
assembly="NHibernate.Test">

<class name="Version" schema="Test">
<id name="Id">
<generator class="NHibernate.Id.TableHiLoGenerator">
<param name="table">uid_table</param>
<param name="column">next_hi_value_column</param>
</generator>
</id>
<property name="Description"/>
<many-to-one name="Previous"/>
</class>
</hibernate-mapping>

2 changes: 1 addition & 1 deletion src/NHibernate/Dialect/MsSqlCeDialect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ public override bool SupportsLimitOffset

public override IDataBaseSchema GetDataBaseSchema(DbConnection connection)
{
return new MsSqlCeDataBaseSchema(connection);
return new MsSqlCeDataBaseSchema(connection, this);
}

public override SqlString GetLimitString(SqlString querySqlString, SqlString offset, SqlString limit)
Expand Down
2 changes: 1 addition & 1 deletion src/NHibernate/Dialect/SQLiteDialect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ protected virtual void RegisterDefaultProperties()

public override Schema.IDataBaseSchema GetDataBaseSchema(DbConnection connection)
{
return new Schema.SQLiteDataBaseMetaData(connection);
return new Schema.SQLiteDataBaseMetaData(connection, this);
}

public override string AddColumnString
Expand Down
Loading