Skip to content

Commit 084ca8a

Browse files
committed
Fix validating similar column types
1 parent 502d243 commit 084ca8a

File tree

3 files changed

+195
-1
lines changed

3 files changed

+195
-1
lines changed
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
//------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by AsyncGenerator.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if
6+
// the code is regenerated.
7+
// </auto-generated>
8+
//------------------------------------------------------------------------------
9+
10+
11+
using System;
12+
using NHibernate.Cfg;
13+
using NHibernate.Dialect;
14+
using NHibernate.Mapping.ByCode;
15+
using NHibernate.Tool.hbm2ddl;
16+
using NUnit.Framework;
17+
18+
namespace NHibernate.Test.Tools.hbm2ddl.SchemaValidator
19+
{
20+
using System.Threading.Tasks;
21+
[TestFixture]
22+
public class PostgresSchemaValidateFixtureAsync
23+
{
24+
[Test]
25+
public async Task ShouldBeInvalidIfTimestampTzIsExpectedAndGotTimestampAsync()
26+
{
27+
var actual = BuildConfiguration("timestamp");
28+
Assume.That(Dialect.Dialect.GetDialect(actual.Properties) is PostgreSQLDialect);
29+
30+
var expected = BuildConfiguration("timestamptz");
31+
32+
var export = new SchemaExport(actual);
33+
await (export.CreateAsync(true, true));
34+
35+
try
36+
{
37+
var validator = new Tool.hbm2ddl.SchemaValidator(expected);
38+
39+
var error = Assert.ThrowsAsync<SchemaValidationException>(() => validator.ValidateAsync());
40+
Assert.That(error, Has.Message.EqualTo("Schema validation failed: see list of validation errors"));
41+
Assert.That(
42+
error,
43+
Has.Property("ValidationErrors").Some.Contains("Wrong column type").IgnoreCase
44+
.And.Contains("for column CreatedAt. Found: timestamp, Expected timestamptz").IgnoreCase);
45+
}
46+
finally
47+
{
48+
await (export.DropAsync(true, true));
49+
}
50+
}
51+
52+
[Test]
53+
public async Task ShouldBeInvalidIfTimestampIsExpectedAndGotTimestampTzAsync()
54+
{
55+
var actual = BuildConfiguration("timestamptz");
56+
Assume.That(Dialect.Dialect.GetDialect(actual.Properties) is PostgreSQLDialect);
57+
58+
var expected = BuildConfiguration("timestamp");
59+
60+
var export = new SchemaExport(actual);
61+
await (export.CreateAsync(true, true));
62+
63+
try
64+
{
65+
var validator = new Tool.hbm2ddl.SchemaValidator(expected);
66+
67+
var error = Assert.ThrowsAsync<SchemaValidationException>(() => validator.ValidateAsync());
68+
Assert.That(error, Has.Message.EqualTo("Schema validation failed: see list of validation errors"));
69+
Assert.That(
70+
error,
71+
Has.Property("ValidationErrors").Some.Contains("Wrong column type").IgnoreCase
72+
.And.Contains("for column CreatedAt. Found: timestamptz, Expected timestamp").IgnoreCase);
73+
}
74+
finally
75+
{
76+
await (export.DropAsync(true, true));
77+
}
78+
}
79+
80+
private static Configuration BuildConfiguration(string type)
81+
{
82+
var mapper = new ModelMapper();
83+
mapper.Class<Entity>(c =>
84+
{
85+
c.Table("Entity");
86+
c.Id(x => x.Id);
87+
c.Property(x => x.CreatedAt, p => p.Column(cm => cm.SqlType(type)));
88+
});
89+
90+
var cfg = TestConfigurationHelper.GetDefaultConfiguration();
91+
cfg.AddDeserializedMapping(mapper.CompileMappingForAllExplicitlyAddedEntities(), "Entity");
92+
return cfg;
93+
}
94+
95+
public class Entity
96+
{
97+
public virtual int Id { get; set; }
98+
public virtual DateTime CreatedAt { get; set; }
99+
}
100+
}
101+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using System;
2+
using NHibernate.Cfg;
3+
using NHibernate.Dialect;
4+
using NHibernate.Mapping.ByCode;
5+
using NHibernate.Tool.hbm2ddl;
6+
using NUnit.Framework;
7+
8+
namespace NHibernate.Test.Tools.hbm2ddl.SchemaValidator
9+
{
10+
[TestFixture]
11+
public class PostgresSchemaValidateFixture
12+
{
13+
[Test]
14+
public void ShouldBeInvalidIfTimestampTzIsExpectedAndGotTimestamp()
15+
{
16+
var actual = BuildConfiguration("timestamp");
17+
Assume.That(Dialect.Dialect.GetDialect(actual.Properties) is PostgreSQLDialect);
18+
19+
var expected = BuildConfiguration("timestamptz");
20+
21+
var export = new SchemaExport(actual);
22+
export.Create(true, true);
23+
24+
try
25+
{
26+
var validator = new Tool.hbm2ddl.SchemaValidator(expected);
27+
28+
var error = Assert.Throws<SchemaValidationException>(() => validator.Validate());
29+
Assert.That(error, Has.Message.EqualTo("Schema validation failed: see list of validation errors"));
30+
Assert.That(
31+
error,
32+
Has.Property("ValidationErrors").Some.Contains("Wrong column type").IgnoreCase
33+
.And.Contains("for column CreatedAt. Found: timestamp, Expected timestamptz").IgnoreCase);
34+
}
35+
finally
36+
{
37+
export.Drop(true, true);
38+
}
39+
}
40+
41+
[Test]
42+
public void ShouldBeInvalidIfTimestampIsExpectedAndGotTimestampTz()
43+
{
44+
var actual = BuildConfiguration("timestamptz");
45+
Assume.That(Dialect.Dialect.GetDialect(actual.Properties) is PostgreSQLDialect);
46+
47+
var expected = BuildConfiguration("timestamp");
48+
49+
var export = new SchemaExport(actual);
50+
export.Create(true, true);
51+
52+
try
53+
{
54+
var validator = new Tool.hbm2ddl.SchemaValidator(expected);
55+
56+
var error = Assert.Throws<SchemaValidationException>(() => validator.Validate());
57+
Assert.That(error, Has.Message.EqualTo("Schema validation failed: see list of validation errors"));
58+
Assert.That(
59+
error,
60+
Has.Property("ValidationErrors").Some.Contains("Wrong column type").IgnoreCase
61+
.And.Contains("for column CreatedAt. Found: timestamptz, Expected timestamp").IgnoreCase);
62+
}
63+
finally
64+
{
65+
export.Drop(true, true);
66+
}
67+
}
68+
69+
private static Configuration BuildConfiguration(string type)
70+
{
71+
var mapper = new ModelMapper();
72+
mapper.Class<Entity>(c =>
73+
{
74+
c.Table("Entity");
75+
c.Id(x => x.Id);
76+
c.Property(x => x.CreatedAt, p => p.Column(cm => cm.SqlType(type)));
77+
});
78+
79+
var cfg = TestConfigurationHelper.GetDefaultConfiguration();
80+
cfg.AddDeserializedMapping(mapper.CompileMappingForAllExplicitlyAddedEntities(), "Entity");
81+
return cfg;
82+
}
83+
84+
public class Entity
85+
{
86+
public virtual int Id { get; set; }
87+
public virtual DateTime CreatedAt { get; set; }
88+
}
89+
}
90+
}

src/NHibernate/Mapping/Table.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Collections.Generic;
44
using System.Linq;
55
using System.Text;
6+
using System.Text.RegularExpressions;
67
using NHibernate.Dialect.Schema;
78
using NHibernate.Engine;
89
using NHibernate.Util;
@@ -1035,7 +1036,9 @@ public IEnumerable<string> ValidateColumns(Dialect.Dialect dialect, IMapping map
10351036
}
10361037

10371038
//TODO: Add new method to ColumnMetadata :getTypeCode
1038-
bool typesMatch = column.GetSqlType(dialect, mapping).StartsWith(columnInfo.TypeName, StringComparison.OrdinalIgnoreCase);
1039+
var typesMatch = Regex.IsMatch(
1040+
column.GetSqlType(dialect, mapping),
1041+
$@"^{Regex.Escape(columnInfo.TypeName)}\b");
10391042
//|| columnInfo.get() == column.GetSqlTypeCode(mapping);
10401043
if (!typesMatch)
10411044
{

0 commit comments

Comments
 (0)