FirebirdSQL / NETProvider

Firebird ADO.NET Data Provider
https://www.firebirdsql.org/en/net-provider/
Other
152 stars 62 forks source link

EntityFrameworkCore Scaffolding: FbDatabaseModelFactory support for data type NUMERIC #1134

Closed bgrauer-atacom closed 10 months ago

bgrauer-atacom commented 10 months ago

The FbDatabaseModelFactory does not support NUMERIC datatype and uses DECIMAL as fallback. This can cause data precision loss.

Adding case

WHEN 1 THEN 'NUMERIC(' || (F.RDB$FIELD_PRECISION) || ',' || ABS(F.RDB$FIELD_SCALE) || ')'

to field type case 7, 8 and 16 should resolve this.


Additional notes:


Sources:

cincuranet commented 10 months ago

Do you care to create PR?

Would it generally not be better to use the explicit case (2) for decimal and return '?' for default cases?

Sure.

Precision and scale of DECIMAL data type are not returned. Intention?

I guess, bug.

bgrauer-atacom commented 10 months ago

I do.

Do you mind if I do a general test case like this:


    [TestCase("SMALLINT", "SMALLINT")]
    [TestCase("INTEGER", "INTEGER")]
    [TestCase("FLOAT", "FLOAT")]
    [TestCase("DATE", "DATE")]
    [TestCase("TIME", "TIME")]
    [TestCase("CHAR(12)", "CHAR_12")]
    [TestCase("BIGINT", "BIGINT")]
    [TestCase("BOOLEAN", "BOOLEAN")]
    [TestCase("DOUBLE PRECISION", "DOUBLE_PRECISION")]
    [TestCase("TIMESTAMP", "TIMESTAMP")]
    [TestCase("VARCHAR(24)", "VARCHAR_24")]
    [TestCase("BLOB SUB_TYPE TEXT", "BLOB_TEXT")]
    [TestCase("BLOB SUB_TYPE BINARY", "BLOB_BINARY")]
    [TestCase("DECIMAL(4,1)", "DECIMAL_4_1")]
    [TestCase("DECIMAL(9,1)", "DECIMAL_9_1")]
    [TestCase("DECIMAL(18,1)", "DECIMAL_18_1")]
    [TestCase("NUMERIC(4,1)", "NUMERIC_4_1")]
    [TestCase("NUMERIC(9,1)", "NUMERIC_9_1")]
    [TestCase("NUMERIC(18,1)", "NUMERIC_18_1")]
    public async Task ReadsCorrectFieldType(string dataType, string tableSuffix)
    {
        // Arrange
        var tableName = $"TEST_READS_CORRECT_FIELD_TYPE_{tableSuffix}";
        var columnName = "FIELD";

        using var commandTable = Connection.CreateCommand();
        commandTable.CommandText = $"create table {tableName} ({columnName} {dataType})";
        await commandTable.ExecuteNonQueryAsync();

        // Act
        var modelFactory = GetModelFactory();
        var model = modelFactory.Create(Connection.ConnectionString, new DatabaseModelFactoryOptions(new string[] { tableName }));
        var table = model.Tables.Single(x => x.Name == tableName);
        var column = table.Columns.Single(x => x.Name == columnName);

        // Assert
        Assert.That(column.StoreType, Is.EqualTo(dataType));
    }
cincuranet commented 10 months ago

Go ahead.