Skip to content

Commit 19ee5db

Browse files
Fix field evaluation in scaffolding (#1133)
1 parent f169563 commit 19ee5db

File tree

2 files changed

+88
-5
lines changed

2 files changed

+88
-5
lines changed

src/FirebirdSql.EntityFrameworkCore.Firebird.Tests/Scaffolding/ScaffoldingTests.cs

+77
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
//$Authors = Jiri Cincura ([email protected])
1717

18+
using System.Linq;
19+
using System.Threading.Tasks;
1820
using FirebirdSql.EntityFrameworkCore.Firebird.Scaffolding.Internal;
1921
using Microsoft.EntityFrameworkCore.Scaffolding;
2022
using NUnit.Framework;
@@ -30,6 +32,81 @@ public void JustCanRun()
3032
Assert.DoesNotThrow(() => modelFactory.Create(Connection, new DatabaseModelFactoryOptions()));
3133
}
3234

35+
[Test]
36+
public async Task ReadsNullableCorrect()
37+
{
38+
var tableName = "TEST_READS_IS_NULL_FROM_DOMAIN";
39+
var columnNameNoDomainNull = "NO_DOMAIN_NULL";
40+
var columnNameNoDomainNotNull = "NO_DOMAIN_NOT_NULL";
41+
var columnNameDomainNull = "DOMAIN_NULL";
42+
var columnNameDomainNotNull = "DOMAIN_NOT_NUL";
43+
44+
using var commandDomainNull = Connection.CreateCommand();
45+
commandDomainNull.CommandText = "create domain DOMAIN_NULL as INTEGER";
46+
await commandDomainNull.ExecuteNonQueryAsync();
47+
48+
using var commandDomainNotNull = Connection.CreateCommand();
49+
commandDomainNotNull.CommandText = "create domain DOMAIN_NOT_NULL as INTEGER NOT NULL";
50+
await commandDomainNotNull.ExecuteNonQueryAsync();
51+
52+
using var commandTable = Connection.CreateCommand();
53+
commandTable.CommandText = $"create table {tableName} ({columnNameNoDomainNull} INTEGER, {columnNameNoDomainNotNull} INTEGER NOT NULL, {columnNameDomainNull} DOMAIN_NULL, {columnNameDomainNotNull} DOMAIN_NOT_NULL)";
54+
await commandTable.ExecuteNonQueryAsync();
55+
56+
var modelFactory = GetModelFactory();
57+
var model = modelFactory.Create(Connection.ConnectionString, new DatabaseModelFactoryOptions(new string[] { tableName }));
58+
var table = model.Tables.Single(x => x.Name == tableName);
59+
var columnNoDomainNull = table.Columns.Single(x => x.Name == columnNameNoDomainNull);
60+
var columnNoDomainNotNull = table.Columns.Single(x => x.Name == columnNameNoDomainNotNull);
61+
var columnDomainNull = table.Columns.Single(x => x.Name == columnNameDomainNull);
62+
var columnDomainNotNull = table.Columns.Single(x => x.Name == columnNameDomainNotNull);
63+
64+
Assert.Multiple(() =>
65+
{
66+
Assert.That(columnNoDomainNull.IsNullable, Is.True);
67+
Assert.That(columnNoDomainNotNull.IsNullable, Is.False);
68+
Assert.That(columnDomainNull.IsNullable, Is.True);
69+
Assert.That(columnDomainNotNull.IsNullable, Is.False);
70+
});
71+
72+
}
73+
74+
[TestCase("SMALLINT")]
75+
[TestCase("INTEGER")]
76+
[TestCase("FLOAT")]
77+
[TestCase("DATE")]
78+
[TestCase("TIME")]
79+
[TestCase("CHAR(12)")]
80+
[TestCase("BIGINT")]
81+
[TestCase("BOOLEAN")]
82+
[TestCase("DOUBLE PRECISION")]
83+
[TestCase("TIMESTAMP")]
84+
[TestCase("VARCHAR(24)")]
85+
[TestCase("BLOB SUB_TYPE TEXT")]
86+
[TestCase("BLOB SUB_TYPE BINARY")]
87+
[TestCase("DECIMAL(4,1)")]
88+
[TestCase("DECIMAL(9,1)")]
89+
[TestCase("DECIMAL(18,1)")]
90+
[TestCase("NUMERIC(4,1)")]
91+
[TestCase("NUMERIC(9,1)")]
92+
[TestCase("NUMERIC(18,1)")]
93+
public async Task ReadsCorrectFieldType(string dataType)
94+
{
95+
var tableName = $"TEST_READS_FIELD_TYPE_CORRECT";
96+
var columnName = "FIELD";
97+
98+
using var commandTable = Connection.CreateCommand();
99+
commandTable.CommandText = $"recreate table {tableName} ({columnName} {dataType})";
100+
await commandTable.ExecuteNonQueryAsync();
101+
102+
var modelFactory = GetModelFactory();
103+
var model = modelFactory.Create(Connection.ConnectionString, new DatabaseModelFactoryOptions(new string[] { tableName }));
104+
var table = model.Tables.Single(x => x.Name == tableName);
105+
var column = table.Columns.Single(x => x.Name == columnName);
106+
107+
Assert.That(column.StoreType, Is.EqualTo(dataType));
108+
}
109+
33110
static IDatabaseModelFactory GetModelFactory()
34111
{
35112
return new FbDatabaseModelFactory();

src/FirebirdSql.EntityFrameworkCore.Firebird/Scaffolding/Internal/FbDatabaseModelFactory.cs

+11-5
Original file line numberDiff line numberDiff line change
@@ -146,27 +146,33 @@ private IEnumerable<DatabaseTable> GetTables(DbConnection connection, Func<Datab
146146
@"SELECT
147147
trim(RF.RDB$FIELD_NAME) as COLUMN_NAME,
148148
COALESCE(RF.RDB$DEFAULT_SOURCE, F.RDB$DEFAULT_SOURCE) as COLUMN_DEFAULT,
149-
COALESCE(RF.RDB$NULL_FLAG, 0) as NOT_NULL,
149+
COALESCE(COALESCE(RF.RDB$NULL_FLAG, F.RDB$NULL_FLAG), 0) as NOT_NULL,
150150
CASE Coalesce(F.RDB$FIELD_TYPE, 0)
151151
WHEN 7 THEN
152152
CASE F.RDB$FIELD_SUB_TYPE
153153
WHEN 0 THEN 'SMALLINT'
154-
ELSE 'DECIMAL'
154+
WHEN 1 THEN 'NUMERIC(' || (F.RDB$FIELD_PRECISION) || ',' || ABS(F.RDB$FIELD_SCALE) || ')'
155+
WHEN 2 THEN 'DECIMAL(' || (F.RDB$FIELD_PRECISION) || ',' || ABS(F.RDB$FIELD_SCALE) || ')'
156+
ELSE '?'
155157
END
156158
WHEN 8 THEN
157159
CASE F.RDB$FIELD_SUB_TYPE
158160
WHEN 0 THEN 'INTEGER'
159-
ELSE 'DECIMAL'
161+
WHEN 1 THEN 'NUMERIC(' || (F.RDB$FIELD_PRECISION) || ',' || ABS(F.RDB$FIELD_SCALE) || ')'
162+
WHEN 2 THEN 'DECIMAL(' || (F.RDB$FIELD_PRECISION) || ',' || ABS(F.RDB$FIELD_SCALE) || ')'
163+
ELSE '?'
160164
END
161165
WHEN 9 THEN 'QUAD'
162166
WHEN 10 THEN 'FLOAT'
163167
WHEN 12 THEN 'DATE'
164168
WHEN 13 THEN 'TIME'
165-
WHEN 14 THEN 'CHAR(' || (TRUNC(F.RDB$FIELD_LENGTH / CH.RDB$BYTES_PER_CHARACTER)) || ') '
169+
WHEN 14 THEN 'CHAR(' || (TRUNC(F.RDB$FIELD_LENGTH / CH.RDB$BYTES_PER_CHARACTER)) || ')'
166170
WHEN 16 THEN
167171
CASE F.RDB$FIELD_SUB_TYPE
168172
WHEN 0 THEN 'BIGINT'
169-
ELSE 'DECIMAL'
173+
WHEN 1 THEN 'NUMERIC(' || (F.RDB$FIELD_PRECISION) || ',' || ABS(F.RDB$FIELD_SCALE) || ')'
174+
WHEN 2 THEN 'DECIMAL(' || (F.RDB$FIELD_PRECISION) || ',' || ABS(F.RDB$FIELD_SCALE) || ')'
175+
ELSE '?'
170176
END
171177
WHEN 23 THEN 'BOOLEAN'
172178
WHEN 27 THEN 'DOUBLE PRECISION'

0 commit comments

Comments
 (0)