From a973847d985b61a9808a6446a07caac940f736db Mon Sep 17 00:00:00 2001 From: Invinsiber Date: Wed, 13 Oct 2021 09:23:45 +0200 Subject: [PATCH 1/5] Add postgres extension to add the OVERRIDING SYSTEM VALUE statement in insert expressions --- ...ostgresExtensions.OverridingSystemValue.cs | 52 +++++++++++++++++++ .../Generators/Postgres/PostgresGenerator.cs | 7 ++- 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 src/FluentMigrator.Extensions.Postgres/Postgres/PostgresExtensions.OverridingSystemValue.cs diff --git a/src/FluentMigrator.Extensions.Postgres/Postgres/PostgresExtensions.OverridingSystemValue.cs b/src/FluentMigrator.Extensions.Postgres/Postgres/PostgresExtensions.OverridingSystemValue.cs new file mode 100644 index 000000000..7a9a6f173 --- /dev/null +++ b/src/FluentMigrator.Extensions.Postgres/Postgres/PostgresExtensions.OverridingSystemValue.cs @@ -0,0 +1,52 @@ +#region License +// Copyright (c) 2021, FluentMigrator Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +using System; + +using FluentMigrator.Builders.Insert; +using FluentMigrator.Infrastructure; +using FluentMigrator.Infrastructure.Extensions; + +namespace FluentMigrator.Postgres +{ + public static partial class PostgresExtensions + { + public const string OverridingSystemValue = "PostgresOverridingSystemValue"; + + /// + /// Enables the current insert expression to set explicit values (other than DEFAULT) + /// for identity columns defined as GENERATED ALWAYS + /// + /// The current expression + /// The current expression + /// + public static IInsertDataSyntax WithOverridingSystemValue(this IInsertDataSyntax expression) + { + if (!(expression is ISupportAdditionalFeatures castExpression)) + { + throw new InvalidOperationException( + string.Format( + ErrorMessages.MethodXMustBeCalledOnObjectImplementingY, + "WithOverridingSystemValue", + nameof(ISupportAdditionalFeatures))); + } + + castExpression.SetAdditionalFeature(OverridingSystemValue, value: true); + + return expression; + } + } +} diff --git a/src/FluentMigrator.Runner.Postgres/Generators/Postgres/PostgresGenerator.cs b/src/FluentMigrator.Runner.Postgres/Generators/Postgres/PostgresGenerator.cs index 54b217f4f..c5cc43cc4 100644 --- a/src/FluentMigrator.Runner.Postgres/Generators/Postgres/PostgresGenerator.cs +++ b/src/FluentMigrator.Runner.Postgres/Generators/Postgres/PostgresGenerator.cs @@ -431,6 +431,11 @@ public override string Generate(RenameColumnExpression expression) public override string Generate(InsertDataExpression expression) { + var overridingSystemValue = expression.GetAdditionalFeature(PostgresExtensions.OverridingSystemValue); + var insertSyntax = overridingSystemValue + ? "INSERT INTO {0} ({1}) OVERRIDING SYSTEM VALUE VALUES ({2});" + : "INSERT INTO {0} ({1}) VALUES ({2});"; + var result = new StringBuilder(); foreach (var row in expression.Rows) { @@ -444,7 +449,7 @@ public override string Generate(InsertDataExpression expression) var columns = GetColumnList(columnNames); var data = GetDataList(columnData); - result.AppendFormat("INSERT INTO {0} ({1}) VALUES ({2});", Quoter.QuoteTableName(expression.TableName, expression.SchemaName), columns, data); + result.AppendFormat(insertSyntax, Quoter.QuoteTableName(expression.TableName, expression.SchemaName), columns, data); } return result.ToString(); } From b76b30de24b73e0f419882d011069d5d26d11a17 Mon Sep 17 00:00:00 2001 From: Invinsiber Date: Wed, 13 Oct 2021 11:36:10 +0200 Subject: [PATCH 2/5] Add unit tests for postgres overriding system value extension --- .../InsertDataExpressionBuilderTests.cs | 23 +++++++++++++++++++ .../Generators/Postgres/PostgresDataTests.cs | 14 +++++++++++ 2 files changed, 37 insertions(+) diff --git a/test/FluentMigrator.Tests/Unit/Builders/Insert/InsertDataExpressionBuilderTests.cs b/test/FluentMigrator.Tests/Unit/Builders/Insert/InsertDataExpressionBuilderTests.cs index 5e2d74464..bcb07bf20 100644 --- a/test/FluentMigrator.Tests/Unit/Builders/Insert/InsertDataExpressionBuilderTests.cs +++ b/test/FluentMigrator.Tests/Unit/Builders/Insert/InsertDataExpressionBuilderTests.cs @@ -20,6 +20,7 @@ using FluentMigrator.Builders.Insert; using FluentMigrator.Expressions; +using FluentMigrator.Postgres; using FluentMigrator.SqlServer; using NUnit.Framework; @@ -96,5 +97,27 @@ public void SqlServerIdentityInsertCalledTwiceAddsCorrectAdditionalFeature() expression.AdditionalFeatures.ShouldContain( new KeyValuePair(SqlServerExtensions.IdentityInsert, true)); } + + [Test] + public void PostgresOverridingSystemValueAddsCorrectAdditionalFeature() + { + var expression = new InsertDataExpression(); + var builder = new InsertDataExpressionBuilder(expression); + builder.WithOverridingSystemValue(); + + expression.AdditionalFeatures.ShouldContain( + new KeyValuePair(PostgresExtensions.OverridingSystemValue, value: true)); + } + + [Test] + public void PostgresOverridingSystemValueCalledTwiceAddsCorrectAdditionalFeature() + { + var expression = new InsertDataExpression(); + var builder = new InsertDataExpressionBuilder(expression); + builder.WithOverridingSystemValue().WithOverridingSystemValue(); + + expression.AdditionalFeatures.ShouldContain( + new KeyValuePair(PostgresExtensions.OverridingSystemValue, value: true)); + } } } diff --git a/test/FluentMigrator.Tests/Unit/Generators/Postgres/PostgresDataTests.cs b/test/FluentMigrator.Tests/Unit/Generators/Postgres/PostgresDataTests.cs index 027c0e8ba..64bbcc613 100644 --- a/test/FluentMigrator.Tests/Unit/Generators/Postgres/PostgresDataTests.cs +++ b/test/FluentMigrator.Tests/Unit/Generators/Postgres/PostgresDataTests.cs @@ -1,3 +1,4 @@ +using FluentMigrator.Postgres; using FluentMigrator.Runner.Generators.Postgres; using FluentMigrator.Runner.Processors.Postgres; @@ -128,6 +129,19 @@ public override void CanInsertGuidDataWithDefaultSchema() result.ShouldBe(string.Format("INSERT INTO \"public\".\"TestTable1\" (\"guid\") VALUES ('{0}');", GeneratorTestHelper.TestGuid)); } + [Test] + public void CanInsertWithOverridingSystemValue() + { + var expression = GeneratorTestHelper.GetInsertDataExpression(); + expression.AdditionalFeatures[PostgresExtensions.OverridingSystemValue] = true; + + var expected = "INSERT INTO \"public\".\"TestTable1\" (\"Id\",\"Name\",\"Website\") OVERRIDING SYSTEM VALUE VALUES (1,'Just''in','codethinked.com');"; + expected += "INSERT INTO \"public\".\"TestTable1\" (\"Id\",\"Name\",\"Website\") OVERRIDING SYSTEM VALUE VALUES (2,'Na\\te','kohari.org');"; + + var result = Generator.Generate(expression); + result.ShouldBe(expected); + } + [Test] public override void CanUpdateDataForAllDataWithCustomSchema() { From 94e93264ef9d9534ff92b2335fc0551863f0896e Mon Sep 17 00:00:00 2001 From: Invinsiber Date: Wed, 13 Oct 2021 15:14:02 +0200 Subject: [PATCH 3/5] Add support for postgres OVERRIDING USER VALUE clause --- ...gresExtensions.OverridingIdentityValues.cs | 73 +++++++++++++++++++ ...ostgresExtensions.OverridingSystemValue.cs | 52 ------------- .../PostgresOverridingIdentityValuesType.cs | 33 +++++++++ .../Generators/Postgres/PostgresGenerator.cs | 18 +++-- .../InsertDataExpressionBuilderTests.cs | 58 ++++++++++++++- .../Generators/Postgres/PostgresDataTests.cs | 15 +++- 6 files changed, 189 insertions(+), 60 deletions(-) create mode 100644 src/FluentMigrator.Extensions.Postgres/Postgres/PostgresExtensions.OverridingIdentityValues.cs delete mode 100644 src/FluentMigrator.Extensions.Postgres/Postgres/PostgresExtensions.OverridingSystemValue.cs create mode 100644 src/FluentMigrator.Extensions.Postgres/PostgresOverridingIdentityValuesType.cs diff --git a/src/FluentMigrator.Extensions.Postgres/Postgres/PostgresExtensions.OverridingIdentityValues.cs b/src/FluentMigrator.Extensions.Postgres/Postgres/PostgresExtensions.OverridingIdentityValues.cs new file mode 100644 index 000000000..dbb0847a2 --- /dev/null +++ b/src/FluentMigrator.Extensions.Postgres/Postgres/PostgresExtensions.OverridingIdentityValues.cs @@ -0,0 +1,73 @@ +#region License +// Copyright (c) 2021, FluentMigrator Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +using System; + +using FluentMigrator.Builders.Insert; +using FluentMigrator.Infrastructure; +using FluentMigrator.Infrastructure.Extensions; + +namespace FluentMigrator.Postgres +{ + public static partial class PostgresExtensions + { + public const string OverridingIdentityValues = "PostgresOverridingSystemValue"; + + /// + /// Adds an OVERRIDING SYSTEM VALUE clause in the current expression. + /// This enables the system-generated values to be overriden with the user-specified explicit values (other than DEFAULT) + /// for identity columns defined as GENERATED ALWAYS + /// + /// The current expression + /// The current expression + public static IInsertDataSyntax WithOverridingSystemValue(this IInsertDataSyntax expression) => + SetOverridingIdentityValues(expression, PostgresOverridingIdentityValuesType.System, nameof(WithOverridingSystemValue)); + + /// + /// Adds an OVERRIDING USER VALUE clause in the current expression. + /// Any user-specified values will be ignored and the system-generated values will be applied + /// for identity columns defined as GENERATED BY DEFAULT + /// + /// The current expression + /// The current expression + public static IInsertDataSyntax WithOverridingUserValue(this IInsertDataSyntax expression) => + SetOverridingIdentityValues(expression, PostgresOverridingIdentityValuesType.User, nameof(WithOverridingUserValue)); + + /// + /// Set the additional feature for overriding identity values with the specified + /// on the provided expression + /// + /// + private static IInsertDataSyntax SetOverridingIdentityValues( + IInsertDataSyntax expression, + PostgresOverridingIdentityValuesType overridingType, + string callingMethod) + { + if (!(expression is ISupportAdditionalFeatures castExpression)) + { + throw new InvalidOperationException( + string.Format( + ErrorMessages.MethodXMustBeCalledOnObjectImplementingY, + callingMethod, + nameof(ISupportAdditionalFeatures))); + } + + castExpression.SetAdditionalFeature(OverridingIdentityValues, overridingType); + + return expression; + } + } +} diff --git a/src/FluentMigrator.Extensions.Postgres/Postgres/PostgresExtensions.OverridingSystemValue.cs b/src/FluentMigrator.Extensions.Postgres/Postgres/PostgresExtensions.OverridingSystemValue.cs deleted file mode 100644 index 7a9a6f173..000000000 --- a/src/FluentMigrator.Extensions.Postgres/Postgres/PostgresExtensions.OverridingSystemValue.cs +++ /dev/null @@ -1,52 +0,0 @@ -#region License -// Copyright (c) 2021, FluentMigrator Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; - -using FluentMigrator.Builders.Insert; -using FluentMigrator.Infrastructure; -using FluentMigrator.Infrastructure.Extensions; - -namespace FluentMigrator.Postgres -{ - public static partial class PostgresExtensions - { - public const string OverridingSystemValue = "PostgresOverridingSystemValue"; - - /// - /// Enables the current insert expression to set explicit values (other than DEFAULT) - /// for identity columns defined as GENERATED ALWAYS - /// - /// The current expression - /// The current expression - /// - public static IInsertDataSyntax WithOverridingSystemValue(this IInsertDataSyntax expression) - { - if (!(expression is ISupportAdditionalFeatures castExpression)) - { - throw new InvalidOperationException( - string.Format( - ErrorMessages.MethodXMustBeCalledOnObjectImplementingY, - "WithOverridingSystemValue", - nameof(ISupportAdditionalFeatures))); - } - - castExpression.SetAdditionalFeature(OverridingSystemValue, value: true); - - return expression; - } - } -} diff --git a/src/FluentMigrator.Extensions.Postgres/PostgresOverridingIdentityValuesType.cs b/src/FluentMigrator.Extensions.Postgres/PostgresOverridingIdentityValuesType.cs new file mode 100644 index 000000000..67cae7d0c --- /dev/null +++ b/src/FluentMigrator.Extensions.Postgres/PostgresOverridingIdentityValuesType.cs @@ -0,0 +1,33 @@ +#region License +// Copyright (c) 2021, FluentMigrator Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +namespace FluentMigrator +{ + /// + /// Determines if the system-generated values or the user-supplied values are applied for identity columns + /// + public enum PostgresOverridingIdentityValuesType + { + /// + /// Overrides the system-generated values with user-supplied values for identity columns + /// + System, + /// + /// Ignores the user-supplied values and applies the system-generated values for identity columns + /// + User, + } +} diff --git a/src/FluentMigrator.Runner.Postgres/Generators/Postgres/PostgresGenerator.cs b/src/FluentMigrator.Runner.Postgres/Generators/Postgres/PostgresGenerator.cs index c5cc43cc4..1ccd2333b 100644 --- a/src/FluentMigrator.Runner.Postgres/Generators/Postgres/PostgresGenerator.cs +++ b/src/FluentMigrator.Runner.Postgres/Generators/Postgres/PostgresGenerator.cs @@ -431,10 +431,18 @@ public override string Generate(RenameColumnExpression expression) public override string Generate(InsertDataExpression expression) { - var overridingSystemValue = expression.GetAdditionalFeature(PostgresExtensions.OverridingSystemValue); - var insertSyntax = overridingSystemValue - ? "INSERT INTO {0} ({1}) OVERRIDING SYSTEM VALUE VALUES ({2});" - : "INSERT INTO {0} ({1}) VALUES ({2});"; + var insertSyntaxTemplate = "INSERT INTO {0} ({1}) VALUES ({2});"; + + if (expression.AdditionalFeatures.ContainsKey(PostgresExtensions.OverridingIdentityValues)) + { + var overridingIdentityValues = + expression.GetAdditionalFeature( + PostgresExtensions.OverridingIdentityValues); + var overridingIdentityValuesClause = overridingIdentityValues == PostgresOverridingIdentityValuesType.User + ? "OVERRIDING USER VALUE" + : "OVERRIDING SYSTEM VALUE"; + insertSyntaxTemplate = "INSERT INTO {0} ({1}) " + overridingIdentityValuesClause + " VALUES ({2});"; + } var result = new StringBuilder(); foreach (var row in expression.Rows) @@ -449,7 +457,7 @@ public override string Generate(InsertDataExpression expression) var columns = GetColumnList(columnNames); var data = GetDataList(columnData); - result.AppendFormat(insertSyntax, Quoter.QuoteTableName(expression.TableName, expression.SchemaName), columns, data); + result.AppendFormat(insertSyntaxTemplate, Quoter.QuoteTableName(expression.TableName, expression.SchemaName), columns, data); } return result.ToString(); } diff --git a/test/FluentMigrator.Tests/Unit/Builders/Insert/InsertDataExpressionBuilderTests.cs b/test/FluentMigrator.Tests/Unit/Builders/Insert/InsertDataExpressionBuilderTests.cs index bcb07bf20..11d2c4ffc 100644 --- a/test/FluentMigrator.Tests/Unit/Builders/Insert/InsertDataExpressionBuilderTests.cs +++ b/test/FluentMigrator.Tests/Unit/Builders/Insert/InsertDataExpressionBuilderTests.cs @@ -106,7 +106,9 @@ public void PostgresOverridingSystemValueAddsCorrectAdditionalFeature() builder.WithOverridingSystemValue(); expression.AdditionalFeatures.ShouldContain( - new KeyValuePair(PostgresExtensions.OverridingSystemValue, value: true)); + new KeyValuePair( + PostgresExtensions.OverridingIdentityValues, + PostgresOverridingIdentityValuesType.System)); } [Test] @@ -117,7 +119,59 @@ public void PostgresOverridingSystemValueCalledTwiceAddsCorrectAdditionalFeature builder.WithOverridingSystemValue().WithOverridingSystemValue(); expression.AdditionalFeatures.ShouldContain( - new KeyValuePair(PostgresExtensions.OverridingSystemValue, value: true)); + new KeyValuePair( + PostgresExtensions.OverridingIdentityValues, + PostgresOverridingIdentityValuesType.System)); + } + + [Test] + public void PostgresOverridingUserValueAddsCorrectAdditionalFeature() + { + var expression = new InsertDataExpression(); + var builder = new InsertDataExpressionBuilder(expression); + builder.WithOverridingUserValue(); + + expression.AdditionalFeatures.ShouldContain( + new KeyValuePair( + PostgresExtensions.OverridingIdentityValues, + PostgresOverridingIdentityValuesType.User)); + } + + [Test] + public void PostgresOverridingUserValueCalledTwiceAddsCorrectAdditionalFeature() + { + var expression = new InsertDataExpression(); + var builder = new InsertDataExpressionBuilder(expression); + builder.WithOverridingUserValue().WithOverridingUserValue(); + + expression.AdditionalFeatures.ShouldContain( + new KeyValuePair( + PostgresExtensions.OverridingIdentityValues, + PostgresOverridingIdentityValuesType.User)); + } + + [Test] + public void PostgresOverridingIdentityValuesCalledWithDifferentTypeAddsCorrectAdditionalFeature() + { + // If both WithOverridingSystemValue() and WithOverridingUserValue() are called on the same expression, + // then the latest value should be set in the additional features + + var expressionForUserValue = new InsertDataExpression(); + var builderForUserValue = new InsertDataExpressionBuilder(expressionForUserValue); + builderForUserValue.WithOverridingSystemValue().WithOverridingUserValue(); + + var expressionForSystemValue = new InsertDataExpression(); + var builderForSystemValue = new InsertDataExpressionBuilder(expressionForSystemValue); + builderForSystemValue.WithOverridingUserValue().WithOverridingSystemValue(); + + expressionForUserValue.AdditionalFeatures.ShouldContain( + new KeyValuePair( + PostgresExtensions.OverridingIdentityValues, + PostgresOverridingIdentityValuesType.User)); + expressionForSystemValue.AdditionalFeatures.ShouldContain( + new KeyValuePair( + PostgresExtensions.OverridingIdentityValues, + PostgresOverridingIdentityValuesType.System)); } } } diff --git a/test/FluentMigrator.Tests/Unit/Generators/Postgres/PostgresDataTests.cs b/test/FluentMigrator.Tests/Unit/Generators/Postgres/PostgresDataTests.cs index 64bbcc613..9194efe40 100644 --- a/test/FluentMigrator.Tests/Unit/Generators/Postgres/PostgresDataTests.cs +++ b/test/FluentMigrator.Tests/Unit/Generators/Postgres/PostgresDataTests.cs @@ -133,7 +133,7 @@ public override void CanInsertGuidDataWithDefaultSchema() public void CanInsertWithOverridingSystemValue() { var expression = GeneratorTestHelper.GetInsertDataExpression(); - expression.AdditionalFeatures[PostgresExtensions.OverridingSystemValue] = true; + expression.AdditionalFeatures[PostgresExtensions.OverridingIdentityValues] = PostgresOverridingIdentityValuesType.System; var expected = "INSERT INTO \"public\".\"TestTable1\" (\"Id\",\"Name\",\"Website\") OVERRIDING SYSTEM VALUE VALUES (1,'Just''in','codethinked.com');"; expected += "INSERT INTO \"public\".\"TestTable1\" (\"Id\",\"Name\",\"Website\") OVERRIDING SYSTEM VALUE VALUES (2,'Na\\te','kohari.org');"; @@ -142,6 +142,19 @@ public void CanInsertWithOverridingSystemValue() result.ShouldBe(expected); } + [Test] + public void CanInsertWithOverridingUserValue() + { + var expression = GeneratorTestHelper.GetInsertDataExpression(); + expression.AdditionalFeatures[PostgresExtensions.OverridingIdentityValues] = PostgresOverridingIdentityValuesType.User; + + var expected = "INSERT INTO \"public\".\"TestTable1\" (\"Id\",\"Name\",\"Website\") OVERRIDING USER VALUE VALUES (1,'Just''in','codethinked.com');"; + expected += "INSERT INTO \"public\".\"TestTable1\" (\"Id\",\"Name\",\"Website\") OVERRIDING USER VALUE VALUES (2,'Na\\te','kohari.org');"; + + var result = Generator.Generate(expression); + result.ShouldBe(expected); + } + [Test] public override void CanUpdateDataForAllDataWithCustomSchema() { From c05a654faeee6ebd43dfe28e224662df5d432ec0 Mon Sep 17 00:00:00 2001 From: Invinsiber Date: Wed, 13 Oct 2021 16:19:24 +0200 Subject: [PATCH 4/5] Move postgres extension for Overriding System|User Value to postgres 10+ --- .../Postgres/Postgres10_0Generator.cs | 18 ++++++ .../Generators/Postgres/PostgresGenerator.cs | 29 ++++----- .../Generators/Postgres/PostgresDataTests.cs | 25 ++++---- .../Postgres10_0/Postgres10_0DataTests.cs | 62 +++++++++++++++++++ .../Postgres11_0/Postgres11_0DataTests.cs | 30 +++++++++ 5 files changed, 137 insertions(+), 27 deletions(-) create mode 100644 test/FluentMigrator.Tests/Unit/Generators/Postgres10_0/Postgres10_0DataTests.cs create mode 100644 test/FluentMigrator.Tests/Unit/Generators/Postgres11_0/Postgres11_0DataTests.cs diff --git a/src/FluentMigrator.Runner.Postgres/Generators/Postgres/Postgres10_0Generator.cs b/src/FluentMigrator.Runner.Postgres/Generators/Postgres/Postgres10_0Generator.cs index f85e434f7..908f582ac 100644 --- a/src/FluentMigrator.Runner.Postgres/Generators/Postgres/Postgres10_0Generator.cs +++ b/src/FluentMigrator.Runner.Postgres/Generators/Postgres/Postgres10_0Generator.cs @@ -16,6 +16,8 @@ using System.Collections.Generic; +using FluentMigrator.Expressions; +using FluentMigrator.Infrastructure.Extensions; using FluentMigrator.Postgres; using JetBrains.Annotations; @@ -61,5 +63,21 @@ protected override HashSet GetAllowIndexStorageParameters() return allow; } + + /// + protected override string GetOverridingIdentityValuesString(InsertDataExpression expression) + { + if (!expression.AdditionalFeatures.ContainsKey(PostgresExtensions.OverridingIdentityValues)) + { + return string.Empty; + } + + var overridingIdentityValues = + expression.GetAdditionalFeature( + PostgresExtensions.OverridingIdentityValues); + + return string.Format(" OVERRIDING {0} VALUE", + overridingIdentityValues == PostgresOverridingIdentityValuesType.User ? "USER" : "SYSTEM"); + } } } diff --git a/src/FluentMigrator.Runner.Postgres/Generators/Postgres/PostgresGenerator.cs b/src/FluentMigrator.Runner.Postgres/Generators/Postgres/PostgresGenerator.cs index 1ccd2333b..a021f7049 100644 --- a/src/FluentMigrator.Runner.Postgres/Generators/Postgres/PostgresGenerator.cs +++ b/src/FluentMigrator.Runner.Postgres/Generators/Postgres/PostgresGenerator.cs @@ -431,19 +431,6 @@ public override string Generate(RenameColumnExpression expression) public override string Generate(InsertDataExpression expression) { - var insertSyntaxTemplate = "INSERT INTO {0} ({1}) VALUES ({2});"; - - if (expression.AdditionalFeatures.ContainsKey(PostgresExtensions.OverridingIdentityValues)) - { - var overridingIdentityValues = - expression.GetAdditionalFeature( - PostgresExtensions.OverridingIdentityValues); - var overridingIdentityValuesClause = overridingIdentityValues == PostgresOverridingIdentityValuesType.User - ? "OVERRIDING USER VALUE" - : "OVERRIDING SYSTEM VALUE"; - insertSyntaxTemplate = "INSERT INTO {0} ({1}) " + overridingIdentityValuesClause + " VALUES ({2});"; - } - var result = new StringBuilder(); foreach (var row in expression.Rows) { @@ -457,7 +444,11 @@ public override string Generate(InsertDataExpression expression) var columns = GetColumnList(columnNames); var data = GetDataList(columnData); - result.AppendFormat(insertSyntaxTemplate, Quoter.QuoteTableName(expression.TableName, expression.SchemaName), columns, data); + result.AppendFormat("INSERT INTO {0} ({1}){3} VALUES ({2});", + Quoter.QuoteTableName(expression.TableName, expression.SchemaName), + columns, + data, + GetOverridingIdentityValuesString(expression)); } return result.ToString(); } @@ -642,5 +633,15 @@ public override string Generate(DeleteSequenceExpression expression) { return string.Format("{0};", base.Generate(expression)); } + + protected virtual string GetOverridingIdentityValuesString(InsertDataExpression expression) + { + if (!expression.AdditionalFeatures.ContainsKey(PostgresExtensions.OverridingIdentityValues)) + { + return string.Empty; + } + + throw new NotSupportedException("The current version doesn't support OVERRIDING {SYSTEM|USER} VALUE. Please use Postgres 10+."); + } } } diff --git a/test/FluentMigrator.Tests/Unit/Generators/Postgres/PostgresDataTests.cs b/test/FluentMigrator.Tests/Unit/Generators/Postgres/PostgresDataTests.cs index 9194efe40..cec7b34ba 100644 --- a/test/FluentMigrator.Tests/Unit/Generators/Postgres/PostgresDataTests.cs +++ b/test/FluentMigrator.Tests/Unit/Generators/Postgres/PostgresDataTests.cs @@ -1,3 +1,5 @@ +using System; + using FluentMigrator.Postgres; using FluentMigrator.Runner.Generators.Postgres; using FluentMigrator.Runner.Processors.Postgres; @@ -17,7 +19,7 @@ public class PostgresDataTests : BaseDataTests public void Setup() { var quoter = new PostgresQuoter(new PostgresOptions()); - Generator = new PostgresGenerator(quoter); + Generator = CreateGenerator(quoter); } [Test] @@ -130,29 +132,21 @@ public override void CanInsertGuidDataWithDefaultSchema() } [Test] - public void CanInsertWithOverridingSystemValue() + public virtual void CanInsertWithOverridingSystemValue() { var expression = GeneratorTestHelper.GetInsertDataExpression(); expression.AdditionalFeatures[PostgresExtensions.OverridingIdentityValues] = PostgresOverridingIdentityValuesType.System; - var expected = "INSERT INTO \"public\".\"TestTable1\" (\"Id\",\"Name\",\"Website\") OVERRIDING SYSTEM VALUE VALUES (1,'Just''in','codethinked.com');"; - expected += "INSERT INTO \"public\".\"TestTable1\" (\"Id\",\"Name\",\"Website\") OVERRIDING SYSTEM VALUE VALUES (2,'Na\\te','kohari.org');"; - - var result = Generator.Generate(expression); - result.ShouldBe(expected); + Should.Throw(() => Generator.Generate(expression)); } [Test] - public void CanInsertWithOverridingUserValue() + public virtual void CanInsertWithOverridingUserValue() { var expression = GeneratorTestHelper.GetInsertDataExpression(); expression.AdditionalFeatures[PostgresExtensions.OverridingIdentityValues] = PostgresOverridingIdentityValuesType.User; - var expected = "INSERT INTO \"public\".\"TestTable1\" (\"Id\",\"Name\",\"Website\") OVERRIDING USER VALUE VALUES (1,'Just''in','codethinked.com');"; - expected += "INSERT INTO \"public\".\"TestTable1\" (\"Id\",\"Name\",\"Website\") OVERRIDING USER VALUE VALUES (2,'Na\\te','kohari.org');"; - - var result = Generator.Generate(expression); - result.ShouldBe(expected); + Should.Throw(() => Generator.Generate(expression)); } [Test] @@ -201,5 +195,10 @@ public override void CanUpdateDataWithDbNullCriteria() var result = Generator.Generate(expression); result.ShouldBe("UPDATE \"public\".\"TestTable1\" SET \"Name\" = 'Just''in', \"Age\" = 25 WHERE \"Id\" = 9 AND \"Homepage\" IS NULL;"); } + + protected virtual PostgresGenerator CreateGenerator(PostgresQuoter quoter) + { + return new PostgresGenerator(quoter); + } } } diff --git a/test/FluentMigrator.Tests/Unit/Generators/Postgres10_0/Postgres10_0DataTests.cs b/test/FluentMigrator.Tests/Unit/Generators/Postgres10_0/Postgres10_0DataTests.cs new file mode 100644 index 000000000..26a1dbc5c --- /dev/null +++ b/test/FluentMigrator.Tests/Unit/Generators/Postgres10_0/Postgres10_0DataTests.cs @@ -0,0 +1,62 @@ +#region License +// Copyright (c) 2021, FluentMigrator Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +using FluentMigrator.Postgres; +using FluentMigrator.Runner.Generators.Postgres; +using FluentMigrator.Tests.Unit.Generators.Postgres; + +using NUnit.Framework; + +using Shouldly; + +namespace FluentMigrator.Tests.Unit.Generators.Postgres10_0 +{ + [TestFixture] + public class Postgres10_0DataTests : PostgresDataTests + { + /// + protected override PostgresGenerator CreateGenerator(PostgresQuoter quoter) + { + return new Postgres10_0Generator(quoter); + } + + [Test] + public override void CanInsertWithOverridingSystemValue() + { + var expression = GeneratorTestHelper.GetInsertDataExpression(); + expression.AdditionalFeatures[PostgresExtensions.OverridingIdentityValues] = PostgresOverridingIdentityValuesType.System; + + var expected = "INSERT INTO \"public\".\"TestTable1\" (\"Id\",\"Name\",\"Website\") OVERRIDING SYSTEM VALUE VALUES (1,'Just''in','codethinked.com');"; + expected += "INSERT INTO \"public\".\"TestTable1\" (\"Id\",\"Name\",\"Website\") OVERRIDING SYSTEM VALUE VALUES (2,'Na\\te','kohari.org');"; + + var result = Generator.Generate(expression); + result.ShouldBe(expected); + } + + [Test] + public override void CanInsertWithOverridingUserValue() + { + var expression = GeneratorTestHelper.GetInsertDataExpression(); + expression.AdditionalFeatures[PostgresExtensions.OverridingIdentityValues] = PostgresOverridingIdentityValuesType.User; + + var expected = "INSERT INTO \"public\".\"TestTable1\" (\"Id\",\"Name\",\"Website\") OVERRIDING USER VALUE VALUES (1,'Just''in','codethinked.com');"; + expected += "INSERT INTO \"public\".\"TestTable1\" (\"Id\",\"Name\",\"Website\") OVERRIDING USER VALUE VALUES (2,'Na\\te','kohari.org');"; + + var result = Generator.Generate(expression); + result.ShouldBe(expected); + } + } +} diff --git a/test/FluentMigrator.Tests/Unit/Generators/Postgres11_0/Postgres11_0DataTests.cs b/test/FluentMigrator.Tests/Unit/Generators/Postgres11_0/Postgres11_0DataTests.cs new file mode 100644 index 000000000..109e25249 --- /dev/null +++ b/test/FluentMigrator.Tests/Unit/Generators/Postgres11_0/Postgres11_0DataTests.cs @@ -0,0 +1,30 @@ +#region License +// Copyright (c) 2021, FluentMigrator Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +using FluentMigrator.Runner.Generators.Postgres; +using FluentMigrator.Tests.Unit.Generators.Postgres10_0; + +namespace FluentMigrator.Tests.Unit.Generators.Postgres11_0 +{ + public class Postgres11_0DataTests : Postgres10_0DataTests + { + /// + protected override PostgresGenerator CreateGenerator(PostgresQuoter quoter) + { + return new Postgres11_0Generator(quoter); + } + } +} From 39e3d499e441ff4dd066d1873f33951c5c7b3768 Mon Sep 17 00:00:00 2001 From: Invinsiber Date: Wed, 13 Oct 2021 16:32:22 +0200 Subject: [PATCH 5/5] Fix name of postgres OverridingIdentityValues additional feature --- .../Postgres/PostgresExtensions.OverridingIdentityValues.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FluentMigrator.Extensions.Postgres/Postgres/PostgresExtensions.OverridingIdentityValues.cs b/src/FluentMigrator.Extensions.Postgres/Postgres/PostgresExtensions.OverridingIdentityValues.cs index dbb0847a2..03b2985a5 100644 --- a/src/FluentMigrator.Extensions.Postgres/Postgres/PostgresExtensions.OverridingIdentityValues.cs +++ b/src/FluentMigrator.Extensions.Postgres/Postgres/PostgresExtensions.OverridingIdentityValues.cs @@ -24,7 +24,7 @@ namespace FluentMigrator.Postgres { public static partial class PostgresExtensions { - public const string OverridingIdentityValues = "PostgresOverridingSystemValue"; + public const string OverridingIdentityValues = "PostgresOverridingIdentityValues"; /// /// Adds an OVERRIDING SYSTEM VALUE clause in the current expression.