Skip to content
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
62 changes: 7 additions & 55 deletions src/EFCore.PG/Scaffolding/Internal/NpgsqlDatabaseModelFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -400,8 +400,7 @@ ORDER BY attnum
else
{
column.DefaultValueSql = defaultValueSql;
column.DefaultValue = ParseClrDefault(systemTypeName, defaultValueSql);
AdjustDefaults(column, systemTypeName);
column.DefaultValue = ParseDefaultValueSql(systemTypeName, defaultValueSql);
}

// Identify IDENTITY columns, as well as SERIAL ones.
Expand Down Expand Up @@ -503,7 +502,7 @@ ORDER BY attnum
}
}

private static object? ParseClrDefault(string dataTypeName, string? defaultValueSql)
private static object? ParseDefaultValueSql(string systemTypeName, string? defaultValueSql)
{
defaultValueSql = defaultValueSql?.Trim();

Expand All @@ -514,22 +513,23 @@ ORDER BY attnum

while (defaultValueSql.StartsWith('(') && defaultValueSql.EndsWith(')'))
{
defaultValueSql = defaultValueSql.Substring(1, defaultValueSql.Length - 2).Trim();
defaultValueSql = defaultValueSql[1..^1].Trim();
}

return dataTypeName switch
return systemTypeName switch
{
"bool" or "boolean" => defaultValueSql switch
{
"true" or "yes" or "on" or "1" => true,
"false" or "no" or "off" or "0" => false,
_ => null
},

"smallint" or "int2" => short.TryParse(defaultValueSql, CultureInfo.InvariantCulture, out var @short) ? @short : null,
"integer" or "int" or "int4" => int.TryParse(defaultValueSql, CultureInfo.InvariantCulture, out var @int) ? @int : null,
"bigint" or "int8" => long.TryParse(defaultValueSql, CultureInfo.InvariantCulture, out var @long) ? @long : null,

"real" or "float4"=> float.TryParse(defaultValueSql, CultureInfo.InvariantCulture, out var @float) ? @float : null,
"real" or "float4" => float.TryParse(defaultValueSql, CultureInfo.InvariantCulture, out var @float) ? @float : null,
"double precision" or "float8" => double.TryParse(defaultValueSql, CultureInfo.InvariantCulture, out var @double) ? @double : null,
"numeric" or "decimal" => decimal.TryParse(defaultValueSql, CultureInfo.InvariantCulture, out var @decimal) ? @decimal : null,

Expand Down Expand Up @@ -1238,55 +1238,7 @@ nspname NOT IN ({internalSchemas})

#endregion

#region Configure default values

/// <summary>
/// Configures the default value for a column.
/// </summary>
/// <param name="column">The column to configure.</param>
/// <param name="systemTypeName">The type name of the column.</param>
private static void AdjustDefaults(DatabaseColumn column, string systemTypeName)
{
var defaultValue = column.DefaultValueSql;
if (defaultValue is null or "(NULL)")
{
column.DefaultValueSql = null;
return;
}

if (column.IsNullable)
{
return;
}

if (defaultValue == "0")
{
if (systemTypeName is "float4" or "float8" or "int2" or "int4" or "int8" or "money" or "numeric")
{
column.DefaultValueSql = null;
return;
}
}

if (defaultValue is "0.0" or "'0'::numeric")
{
if (systemTypeName is "numeric" or "float4" or "float8" or "money")
{
column.DefaultValueSql = null;
return;
}
}

if (systemTypeName == "bool" && defaultValue == "false"
|| systemTypeName == "date" && defaultValue == "'0001-01-01'::date"
|| systemTypeName == "timestamp" && defaultValue == "'1900-01-01 00:00:00'::timestamp without time zone"
|| systemTypeName == "time" && defaultValue == "'00:00:00'::time without time zone"
|| systemTypeName == "interval" && defaultValue == "'00:00:00'::interval"
|| systemTypeName == "uuid" && defaultValue == "'00000000-0000-0000-0000-000000000000'::uuid")
{
column.DefaultValueSql = null;
}
}
#region SequenceInfo

private static SequenceInfo ReadSequenceInfo(DbDataRecord record, Version postgresVersion)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -934,50 +934,6 @@ public void Computed_values_are_stored()
DROP TABLE "ComputedValues"
""");

[Fact]
public void Default_value_matching_clr_default_is_not_stored()
=> Test(
"""
CREATE DOMAIN "decimalDomain" AS decimal(6);

CREATE TABLE "DefaultValues" (
"IgnoredDefault1" int DEFAULT NULL,
"IgnoredDefault2" int NOT NULL DEFAULT NULL,
"IgnoredDefault9" int NOT NULL DEFAULT 0,
"IgnoredDefault14" smallint NOT NULL DEFAULT 0,
"IgnoredDefault3" bigint NOT NULL DEFAULT 0,
"IgnoredDefault15" decimal NOT NULL DEFAULT 0,
"IgnoredDefault16" decimal NOT NULL DEFAULT 0.0,
"IgnoredDefault17" "decimalDomain" NOT NULL DEFAULT 0,
"IgnoredDefault10" money NOT NULL DEFAULT 0,
"IgnoredDefault19" money NOT NULL DEFAULT 0.0,
"IgnoredDefault21" float4 NOT NULL DEFAULT 0.0,
"IgnoredDefault7" float8 NOT NULL DEFAULT 0,
"IgnoredDefault18" float8 NOT NULL DEFAULT 0.0,
"IgnoredDefault24" float8 NOT NULL DEFAULT 0E0,
"IgnoredDefault4" bool NOT NULL DEFAULT false,
"IgnoredDefault25" date NOT NULL DEFAULT '0001-01-01',
"IgnoredDefault26" timestamp NOT NULL DEFAULT '1900-01-01T00:00:00.000',
"IgnoredDefault27" interval NOT NULL DEFAULT '00:00:00',
"IgnoredDefault32" time NOT NULL DEFAULT '00:00:00',
"IgnoredDefault34" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'
)
""",
[],
[],
dbModel =>
{
var columns = dbModel.Tables.Single().Columns;

Assert.All(
columns,
t => Assert.Null(t.DefaultValueSql));
},
"""
DROP TABLE "DefaultValues";
DROP DOMAIN "decimalDomain";
""");

[Fact]
public void ValueGenerated_is_set_for_default_and_serial_column()
=> Test(
Expand Down