提交 7408237c 编写于 作者: S Shay Rojansky

Require computed columns to be explicitly specified as stored

Closes #1336
上级 e7357132
......@@ -338,6 +338,7 @@ protected override void Generate(AlterColumnOperation operation, IModel model, M
DefaultValue = operation.DefaultValue,
DefaultValueSql = operation.DefaultValueSql,
ComputedColumnSql = operation.ComputedColumnSql,
ComputedColumnIsStored = operation.ComputedColumnIsStored,
IsFixedLength = operation.IsFixedLength
};
addColumnOperation.AddAnnotations(operation.GetAnnotations());
......@@ -1278,6 +1279,7 @@ protected override void Generate(CreateSequenceOperation operation, IModel model
$"{nameof(NpgsqlAnnotationNames.TsVectorProperties)} is absent or empty");
operation.ComputedColumnSql = ColumnsToTsVector(tsVectorIncludedColumns, tsVectorConfig, model, schema, table);
operation.ComputedColumnIsStored = true;
}
if (operation.ComputedColumnSql != null)
......@@ -1421,6 +1423,11 @@ long Max(Type type)
if (_postgresVersion != null && _postgresVersion < new Version(12, 0))
throw new NotSupportedException("Computed/generated columns aren't supported in PostgreSQL prior to version 12");
if (operation.ComputedColumnIsStored != true)
throw new NotSupportedException(
"Generated columns currently must be stored, specify " +
$"{nameof(RelationalPropertyBuilderExtensions.IsStoredComputedColumn)} in your context's OnModelCreating.");
builder
.Append(DelimitIdentifier(name))
.Append(" ")
......
......@@ -353,7 +353,10 @@ ELSE NULL
// Default values and PostgreSQL 12 generated columns
if (record.GetValueOrDefault<char>("attgenerated") == 's')
{
column.ComputedColumnSql = record.GetValueOrDefault<string>("default");
column.ComputedColumnIsStored = true;
}
else
{
column.DefaultValueSql = record.GetValueOrDefault<string>("default");
......
......@@ -68,11 +68,11 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Entity>()
.Property(e => e.P4)
.HasComputedColumnSql(@"""P1"" + ""P2""");
.HasComputedColumnSql(@"""P1"" + ""P2""", stored: true);
modelBuilder.Entity<Entity>()
.Property(e => e.P5)
.HasComputedColumnSql(@"""P1"" + ""P3""");
.HasComputedColumnSql(@"""P1"" + ""P3""", stored: true);
}
}
......@@ -123,7 +123,7 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
protected override void OnModelCreating(ModelBuilder modelBuilder)
=> modelBuilder.Entity<EnumItem>()
.Property(entity => entity.CalculatedFlagEnum)
.HasComputedColumnSql(@"""FlagEnum"" | ""OptionalFlagEnum""");
.HasComputedColumnSql(@"""FlagEnum"" | ""OptionalFlagEnum""", stored: true);
}
[ConditionalFact]
......
......@@ -478,7 +478,14 @@ public override async Task Add_column_with_computedSql(bool? computedColumnStore
return;
}
await base.Add_column_with_computedSql(computedColumnStored);
if (computedColumnStored != true)
{
// Non-stored generated columns aren't yet supported (PG12)
await Assert.ThrowsAsync<NotSupportedException>(() => base.Add_column_with_computedSql(computedColumnStored));
return;
}
await base.Add_column_with_computedSql(computedColumnStored: true);
AssertSql(
@"ALTER TABLE ""People"" ADD ""Sum"" text GENERATED ALWAYS AS (""X"" + ""Y"") STORED;");
......@@ -550,7 +557,21 @@ public override async Task Add_column_computed_with_collation()
return;
}
await base.Add_column_computed_with_collation();
// Non-stored generated columns aren't yet supported (PG12), so we override to used stored
await Test(
builder => builder.Entity("People").Property<int>("Id"),
builder => { },
builder => builder.Entity("People").Property<string>("Name")
.HasComputedColumnSql("'hello'", stored: true)
.UseCollation(NonDefaultCollation),
model =>
{
var table = Assert.Single(model.Tables);
Assert.Equal(2, table.Columns.Count);
var nameColumn = Assert.Single(table.Columns, c => c.Name == "Name");
Assert.Contains("hello", nameColumn.ComputedColumnSql);
Assert.Equal(NonDefaultCollation, nameColumn.Collation);
});
AssertSql(
@"ALTER TABLE ""People"" ADD ""Name"" text COLLATE ""POSIX"" GENERATED ALWAYS AS ('hello') STORED;");
......@@ -860,6 +881,13 @@ public override async Task Alter_column_make_computed(bool? computedColumnStored
return;
}
if (computedColumnStored != true)
{
// Non-stored generated columns aren't yet supported (PG12)
await Assert.ThrowsAsync<NotSupportedException>(() => base.Add_column_with_computedSql(computedColumnStored));
return;
}
await base.Alter_column_make_computed(computedColumnStored);
AssertSql(
......@@ -876,7 +904,28 @@ public override async Task Alter_column_change_computed()
return;
}
await base.Alter_column_change_computed();
// Non-stored generated columns aren't yet supported (PG12), so we override to used stored
await Test(
builder => builder.Entity(
"People", e =>
{
e.Property<int>("Id");
e.Property<int>("X");
e.Property<int>("Y");
e.Property<int>("Sum");
}),
builder => builder.Entity("People").Property<int>("Sum")
.HasComputedColumnSql($"{DelimitIdentifier("X")} + {DelimitIdentifier("Y")}", stored: true),
builder => builder.Entity("People").Property<int>("Sum")
.HasComputedColumnSql($"{DelimitIdentifier("X")} - {DelimitIdentifier("Y")}", stored: true),
model =>
{
var table = Assert.Single(model.Tables);
var sumColumn = Assert.Single(table.Columns, c => c.Name == "Sum");
Assert.Contains("X", sumColumn.ComputedColumnSql);
Assert.Contains("Y", sumColumn.ComputedColumnSql);
Assert.Contains("-", sumColumn.ComputedColumnSql);
});
AssertSql(
@"ALTER TABLE ""People"" DROP COLUMN ""Sum"";",
......@@ -884,6 +933,9 @@ public override async Task Alter_column_change_computed()
@"ALTER TABLE ""People"" ADD ""Sum"" integer GENERATED ALWAYS AS (""X"" - ""Y"") STORED;");
}
public override Task Alter_column_change_computed_type()
=> Assert.ThrowsAsync<NotSupportedException>(() => base.Alter_column_change_computed());
public override async Task Alter_column_add_comment()
{
await base.Alter_column_add_comment();
......
......@@ -845,8 +845,10 @@ public void Computed_values_are_stored()
var columns = dbModel.Tables.Single().Columns;
// Note that on-the-fly computed columns aren't (yet) supported by PostgreSQL, only stored/persistedcolumns.
Assert.Null(columns.Single(c => c.Name == "SumOfAAndB").DefaultValueSql);
Assert.Equal(@"(""A"" + ""B"")", columns.Single(c => c.Name == "SumOfAAndB").ComputedColumnSql);
var column = columns.Single(c => c.Name == "SumOfAAndB");
Assert.Null(column.DefaultValueSql);
Assert.Equal(@"(""A"" + ""B"")", column.ComputedColumnSql);
Assert.True(column.ComputedColumnIsStored);
},
@"DROP TABLE ""ComputedValues""");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册