From 3f8f4b8db9605d457e7cb7f0916ff46d46b6f087 Mon Sep 17 00:00:00 2001 From: jeffovercash Date: Sat, 25 Mar 2023 13:42:48 -0400 Subject: [PATCH] 7.13.6 release Updated EFCore support to EFCore 6.0 and updated to the Fb 9.x driver source. This was done primarily for scaffolding support. Primary driver has a few bug fixes around when connecting to a dialect 1 database but requesting dialect 3. --- NETProvider/DDEX/installer/Install.wxs | 216 +-- .../Demos/EnityCoreExample2/Country.cs | 20 + .../Demos/EnityCoreExample2/Customer.cs | 29 + .../Demos/EnityCoreExample2/Department.cs | 29 + .../Demos/EnityCoreExample2/EFCore101.csproj | 38 + .../Demos/EnityCoreExample2/EFCore101.sln | 25 + .../Demos/EnityCoreExample2/Employee.cs | 38 + .../EmployeeForm.Designer.cs | 112 ++ .../Demos/EnityCoreExample2/EmployeeForm.cs | 43 + .../Demos/EnityCoreExample2/EmployeeForm.resx | 63 + NETProvider/Demos/EnityCoreExample2/Job.cs | 25 + .../MyEmployeeConnectionContext.cs | 527 +++++ .../EnityCoreExample2/MyEmployeeUtils.cs | 18 + .../Demos/EnityCoreExample2/PhoneList.cs | 15 + .../Demos/EnityCoreExample2/Program.cs | 17 + .../Demos/EnityCoreExample2/ProjDeptBudget.cs | 17 + .../Demos/EnityCoreExample2/Project.cs | 25 + .../DataSources/Employee.datasource | 10 + .../Demos/EnityCoreExample2/SalaryHistory.cs | 17 + NETProvider/Demos/EnityCoreExample2/Sale.cs | 25 + NETProvider/Provider/build.ps1 | 7 +- .../docs/ADO Driver documentation.docx | Bin 163586 -> 163449 bytes NETProvider/Provider/installer/Installer.wxs | 37 +- .../Provider/src/Directory.Build.props | 2 +- .../SqlGen/SqlGenerator.cs | 2 +- .../SqlGen/SqlSelectStatement.cs | 14 +- .../ChangeViewTests.cs | 10 + .../Changelog.md | 26 + .../ConnectionStringTests.cs | 7 +- .../GuidTests.cs | 9 + .../IBArrayTests.cs | 113 +- .../IBBlobTests.cs | 12 +- .../IBBooleanSupportTests.cs | 13 +- .../IBCommandBuilderTests.cs | 10 + .../IBCommandTests.cs | 93 +- .../IBConnectionStringBuilderTests.cs | 19 + .../IBConnectionTests.cs | 75 + .../IBDataAdapterTests.cs | 9 + .../IBDataReaderTests.cs | 61 +- .../IBDatabaseInfoTests.cs | 18 + .../IBDatabaseSchemaTests.cs | 8 + .../IBEventTests.cs | 9 + .../IBImplicitTransactionTests.cs | 10 + .../IBParameterCollectionTests.cs | 3 + .../IBParameterTests.cs | 11 + .../IBSchemaTests.cs | 8 + .../IBServicesTests.cs | 9 + .../IBStoredProcCallsTests.cs | 9 + .../IBTransactionTests.cs | 8 + .../TrackerIssuesTests.cs | 8 + .../Changelog.md | 5 + .../Client/Native/Changelog.md | 5 + .../Client/Native/IBArray.cs | 8 +- .../Client/Native/IIBClient.cs | 2 +- .../Common/Changelog.md | 8 + .../Common/ConnectionString.cs | 2 +- .../Common/IscHelper.cs | 4 + .../Common/TypeHelper.cs | 2 +- .../Embarcadero.Data.InterBaseClient.csproj | 9 +- .../InterBaseClient/IBCommand.cs | 69 +- .../InterBaseClient/IBConnection.cs | 26 + .../InterBaseClient/IBConnectionInternal.cs | 3 +- .../InterBaseClient/IBDatabaseInfo.cs | 1 + .../InterBaseClient/IBTransaction.cs | 10 +- .../InterBaseClient/changelog.md | 20 + .../InterBaseSql.Data.TestsBase/Changelog.md | 3 + .../IBTestsBase.cs | 15 +- .../IBTestsSetup.cs | 61 +- .../Changelog.md | 6 +- .../Changelog.txt | 13 - .../Helpers/Changelog.md | 21 + .../Helpers/Changelog.txt | 19 - .../Helpers/ModelHelpers.cs | 71 +- .../Helpers/SkippingAttributes.cs | 96 +- ...eworkCore.InterBase.FunctionalTests.csproj | 10 +- .../MigrationsIBFixture.cs | 31 - .../MigrationsIBTest.cs | 330 +++- .../Query/AsNoTrackingIBTest.cs | 32 - .../Query/AsTrackingIBTest.cs | 32 - .../Query/AsyncFromSqlQueryIBTest.cs | 32 - .../Query/AsyncGearsOfWarQueryIBTest.cs | 44 - .../Query/AsyncSimpleQueryIBTest.cs | 53 - .../Query/ChangeTrackingIBTest.cs | 39 - .../Query/Changelog.md | 27 + .../Query/Changelog.txt | 20 - .../Query/CompiledQueryIBTest.cs | 34 - .../Query/ComplexNavigationsQueryIBFixture.cs | 16 +- .../Query/ComplexNavigationsQueryIBTest.cs | 1696 +++++++---------- .../ComplexNavigationsWeakQueryIBFixture.cs | 39 - .../ComplexNavigationsWeakQueryIBTest.cs | 942 --------- .../Query/DbFunctionsIBTest.cs | 47 - .../Query/FiltersIBTest.cs | 32 - .../Query/FiltersInheritanceIBTest.cs | 31 - .../Query/FromSqlQueryIBTest.cs | 141 +- .../Query/FromSqlSprocQueryIBTest.cs | 353 ++-- .../Query/FunkyDataQueryIBTest.cs | 25 +- .../Query/GearsOfWarFromSqlQueryIBTest.cs | 13 +- .../Query/GearsOfWarQueryIBFixture.cs | 13 +- .../Query/GearsOfWarQueryIBTest.cs | 573 ++++-- .../Query/GroupByQueryIBTest.cs | 52 - .../Query/IncludeAsyncIBTest.cs | 65 - .../Query/IncludeIBTest.cs | 168 -- .../Query/IncludeOneToOneIBTest.cs | 26 +- .../Query/InheritanceIBFixture.cs | 39 - .../Query/InheritanceIBTest.cs | 38 - .../InheritanceRelationshipsQueryIBFixture.cs | 19 +- .../InheritanceRelationshipsQueryIBTest.cs | 376 +++- .../Query/MappingQueryIBTest.cs | 79 +- .../Query/NorthwindQueryIBFixture.cs | 13 +- .../Query/NullKeysIBTest.cs | 19 +- .../Query/NullSemanticsQueryIBFixture.cs | 9 +- .../Query/NullSemanticsQueryIBTest.cs | 29 +- .../Query/OwnedQueryIBTest.cs | 475 +++-- .../Query/QueryFilterFuncletizationIBTest.cs | 51 +- .../Query/QueryNavigationsIBTest.cs | 32 - .../Query/QueryNoClientEvalIBFixture.cs | 9 +- .../Query/QueryNoClientEvalIBTest.cs | 13 +- .../Query/QueryTaggingIBTest.cs | 33 - .../Query/SimpleQueryIBTest.cs | 291 --- .../Query/SqlExecutorIBTest.cs | 81 +- .../Query/UdfDbFunctionIBTests.cs | 284 ++- .../Query/WarningsIBTest.cs | 13 +- .../TestModels/Northwind/Changelog.md | 16 + .../TestModels/Northwind/Changelog.txt | 14 - .../Northwind/NorthwindIBContext.cs | 26 +- .../TestUtilities/IBTestHelpers.cs | 43 + .../TestUtilities/IBTestStore.cs | 269 ++- .../TestUtilities/IBTestStoreFactory.cs | 33 +- .../UpdatesIBFixture.cs | 20 +- .../UpdatesIBTest.cs | 45 +- .../Changelog.md | 2 + .../EndToEnd/DeleteTests.cs | 153 +- .../EndToEnd/InsertTests.cs | 389 ++-- .../EndToEnd/UpdateTests.cs | 401 ++-- .../EntityFrameworkCoreTestsBase.cs | 21 +- .../IBTestDbContext.cs | 143 +- ...EntityFrameworkCore.InterBase.Tests.csproj | 6 +- .../Migrations/MigrationsTests.cs | 1387 +++++++------- .../Query/Changelogs.md | 2 + .../Query/ElementaryTests.cs | 289 ++- .../Scaffolding/ScaffoldingTests.cs | 37 + .../Design/Internal/Changelog.md | 20 + .../Design/Internal/Changelog.txt | 15 - .../Design/Internal/IBDesignTimeServices.cs | 24 +- .../Diagnostics/Internal/Changelog.md | 11 + .../Diagnostics/Internal/Changelog.txt | 11 - .../Internal/IBLoggingDefinitions.cs | 9 +- .../Extensions/Changelog.md | 16 + .../Extensions/IBDatabaseFacadeExtensions.cs | 51 +- .../IBDbContextOptionsBuilderExtensions.cs | 65 +- .../Extensions/IBModelBuilderExtensions.cs | 51 +- .../Extensions/IBModelExtensions.cs | 24 +- .../Extensions/IBPropertyBuilderExtensions.cs | 59 +- .../Extensions/IBPropertyExtensions.cs | 156 +- .../IBServiceCollectionExtensions.cs | 77 +- .../Infrastructure/Changelog.md | 14 + .../Infrastructure/Changelog.txt | 14 - .../IBDbContextOptionsBuilder.cs | 21 +- .../Infrastructure/Internal/Changelog.md | 20 + .../Infrastructure/Internal/Changelog.txt | 15 - .../Internal/IBOptionsExtension.cs | 93 +- .../Infrastructure/Internal/IIBOptions.cs | 11 +- ...seSql.EntityFrameworkCore.InterBase.csproj | 6 +- .../Internal/Changelog.md | 18 + .../Internal/Changelog.txt | 13 - .../Internal/IBOptions.cs | 43 +- .../Metadata/Changelog.md | 13 + .../Metadata/Changelog.txt | 13 - .../Metadata/Conventions/Changelog.md | 3 + .../Conventions/IBConventionSetBuilder.cs | 69 +- .../IBStoreGenerationConvention.cs | 149 +- .../IBValueGenerationConvention.cs | 40 +- .../IBValueGenerationStrategyConvention.cs | 41 +- .../Metadata/IBValueGenerationStrategy.cs | 13 +- .../Metadata/Internal/Changelog.md | 15 + .../Metadata/Internal/Changelog.txt | 15 - .../Metadata/Internal/IBAnnotationNames.cs | 11 +- .../IBRelationalAnnotationProvider.cs} | 36 +- .../Migrations/Changelog.md | 11 + .../IBMigrationSqlGeneratorBehavior.cs | 148 +- .../Migrations/IBMigrationsSqlGenerator.cs | 538 +++--- .../IIBMigrationSqlGeneratorBehavior.cs | 11 +- .../Migrations/Internal/Changelog.md | 19 + .../Migrations/Internal/Changelog.txt | 15 - .../Internal/IBHistoryRepository.cs | 51 +- .../Migrations/Operations/Changelog.txt | 13 - .../Operations/IBCreateDatabaseOperation.cs | 29 - .../Operations/IBDropDatabaseOperation.cs | 29 - .../Internal/Changelog.md | 82 + .../Internal/Changelog.txt | 73 - .../Internal/IBByteArrayMethodTranslator.cs | 58 + .../Internal/IBContainsOptimizedTranslator.cs | 63 - .../Internal/IBConvertTranslator.cs | 82 +- .../Internal/IBDateAddTranslator.cs | 69 +- .../IBDateOnlyPartComponentTranslator.cs | 65 + .../IBDateTimeDateComponentTranslator.cs | 34 +- .../IBDateTimeDatePartComponentTranslator.cs | 66 - .../Internal/IBDateTimeNowTodayTranslator.cs | 35 +- .../IBDateTimePartComponentTranslator.cs | 75 + .../Internal/IBEndsWithOptimizedTranslator.cs | 68 - .../Internal/IBMathTranslator.cs | 202 +- .../Internal/IBMemberTranslatorProvider.cs | 17 +- .../IBMethodCallTranslatorProvider.cs | 17 +- .../Internal/IBNewGuidTranslator.cs | 29 +- .../Internal/IBObjectToStringTranslator.cs | 64 +- .../IBStartsWithOptimizedTranslator.cs | 73 - .../Internal/IBStringContainsTranslator.cs | 62 + .../Internal/IBStringEndsWithTranslator.cs | 69 + .../IBStringFirstOrDefaultTranslator.cs | 54 + .../Internal/IBStringIndexOfTranslator.cs | 36 +- .../IBStringIsNullOrWhiteSpaceTranslator.cs | 49 +- .../IBStringLastOrDefaultTranslator.cs | 54 + .../Internal/IBStringLengthTranslator.cs | 29 +- .../Internal/IBStringReplaceTranslator.cs | 36 +- .../Internal/IBStringStartsWithTranslator.cs | 77 + .../Internal/IBStringSubstringTranslator.cs | 21 +- .../Internal/IBStringToLowerTranslator.cs | 29 +- .../Internal/IBStringToUpperTranslator.cs | 29 +- .../Internal/IBStringTrimTranslator.cs | 47 +- .../IBTimeOnlyPartComponentTranslator.cs | 65 + .../IBTimeSpanPartComponentTranslator.cs | 64 + .../Query/Expressions/Internal/Changelog.md | 23 + .../Query/Expressions/Internal/Changelog.txt | 16 - .../IBDateTimeDateMemberExpression.cs | 77 - .../Internal/IBExtractExpression.cs | 82 - .../Internal/IBSpacedFunctionExpression.cs | 81 + .../Internal/IBSubstringExpression.cs | 92 - .../Expressions/Internal/IBTrimExpression.cs | 90 - .../Query/Internal/Changelog.md | 40 + .../Query/Internal/Changelog.txt | 34 - .../Query/Internal/IBQuerySqlGenerator.cs | 505 ++--- .../Internal/IBQuerySqlGeneratorFactory.cs | 25 +- .../Query/Internal/IBSqlExpressionFactory.cs | 84 +- .../IBSqlTranslatingExpressionVisitor.cs | 42 + ...BSqlTranslatingExpressionVisitorFactory.cs | 33 + .../Scaffolding/Internal/Changelog.md | 27 + .../Scaffolding/Internal/Changelog.txt | 18 - .../Internal/IBDatabaseModelFactory.cs | 459 ++++- ...enerator.cs => IBProviderCodeGenerator.cs} | 37 +- .../Storage/Internal/Changelog.md | 27 + .../Storage/Internal/Changelog.txt | 23 - .../Storage/Internal/IBBoolTypeMapping.cs | 31 +- .../Internal/IBByteArrayTypeMapping.cs | 33 +- .../Storage/Internal/IBDatabaseCreator.cs | 193 +- .../Storage/Internal/IBDateOnlyTypeMapping.cs | 39 + .../Storage/Internal/IBDateTimeTypeMapping.cs | 65 +- .../Storage/Internal/IBGuidTypeMapping.cs | 44 +- .../Internal/IBRelationalConnection.cs | 19 +- .../Internal/IBRelationalTransaction.cs | 32 + .../Storage/Internal/IBSqlGenerationHelper.cs | 66 +- .../Storage/Internal/IBStringTypeMapping.cs | 62 +- .../Storage/Internal/IBTimeOnlyTypeMapping.cs | 39 + .../Storage/Internal/IBTimeSpanTypeMapping.cs | 57 +- .../Storage/Internal/IBTransactionFactory.cs | 38 + .../Storage/Internal/IBTypeMappingSource.cs | 266 +-- .../Internal/IIBSqlGenerationHelper.cs | 14 +- .../Internal/IRelationalIBConnection.cs | 9 +- .../Internal/IRelationalIBTransaction.cs} | 18 +- .../Update/Internal/Changelog.md | 23 + .../Update/Internal/Changelog.txt | 18 - .../IBModificationCommandBatchFactory.cs | 23 +- .../IBServerModificationCommandBatch.cs | 152 +- .../Update/Internal/IBUpdateSqlGenerator.cs | 223 ++- .../Update/Internal/IIBUpdateSqlGenerator.cs | 9 +- .../Utilities/Changelog.md | 8 + .../Utilities/Changelog.txt | 3 - .../Utilities/EnumerableMethods.cs | 728 +++++++ .../Utilities/SharedTypeExtensions.cs | 716 +++++-- .../Utilities/StringBuilderExtensions.cs | 150 +- .../Utilities/TranslatorsHelper.cs | 13 +- NETProvider/Provider/src/Perf/Perf.csproj | 2 +- 271 files changed, 12216 insertions(+), 9247 deletions(-) create mode 100644 NETProvider/Demos/EnityCoreExample2/Country.cs create mode 100644 NETProvider/Demos/EnityCoreExample2/Customer.cs create mode 100644 NETProvider/Demos/EnityCoreExample2/Department.cs create mode 100644 NETProvider/Demos/EnityCoreExample2/EFCore101.csproj create mode 100644 NETProvider/Demos/EnityCoreExample2/EFCore101.sln create mode 100644 NETProvider/Demos/EnityCoreExample2/Employee.cs create mode 100644 NETProvider/Demos/EnityCoreExample2/EmployeeForm.Designer.cs create mode 100644 NETProvider/Demos/EnityCoreExample2/EmployeeForm.cs create mode 100644 NETProvider/Demos/EnityCoreExample2/EmployeeForm.resx create mode 100644 NETProvider/Demos/EnityCoreExample2/Job.cs create mode 100644 NETProvider/Demos/EnityCoreExample2/MyEmployeeConnectionContext.cs create mode 100644 NETProvider/Demos/EnityCoreExample2/MyEmployeeUtils.cs create mode 100644 NETProvider/Demos/EnityCoreExample2/PhoneList.cs create mode 100644 NETProvider/Demos/EnityCoreExample2/Program.cs create mode 100644 NETProvider/Demos/EnityCoreExample2/ProjDeptBudget.cs create mode 100644 NETProvider/Demos/EnityCoreExample2/Project.cs create mode 100644 NETProvider/Demos/EnityCoreExample2/Properties/DataSources/Employee.datasource create mode 100644 NETProvider/Demos/EnityCoreExample2/SalaryHistory.cs create mode 100644 NETProvider/Demos/EnityCoreExample2/Sale.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Changelog.txt create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Helpers/Changelog.md delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Helpers/Changelog.txt delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/MigrationsIBFixture.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/AsNoTrackingIBTest.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/AsTrackingIBTest.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/AsyncFromSqlQueryIBTest.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/AsyncGearsOfWarQueryIBTest.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/AsyncSimpleQueryIBTest.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/ChangeTrackingIBTest.cs create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/Changelog.md delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/Changelog.txt delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/CompiledQueryIBTest.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/ComplexNavigationsWeakQueryIBFixture.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/ComplexNavigationsWeakQueryIBTest.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/DbFunctionsIBTest.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FiltersIBTest.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FiltersInheritanceIBTest.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/GroupByQueryIBTest.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/IncludeAsyncIBTest.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/IncludeIBTest.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/InheritanceIBFixture.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/InheritanceIBTest.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/QueryNavigationsIBTest.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/QueryTaggingIBTest.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/SimpleQueryIBTest.cs create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestModels/Northwind/Changelog.md delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestModels/Northwind/Changelog.txt create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestUtilities/IBTestHelpers.cs create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/Scaffolding/ScaffoldingTests.cs create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Design/Internal/Changelog.md delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Design/Internal/Changelog.txt create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Diagnostics/Internal/Changelog.md delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Diagnostics/Internal/Changelog.txt create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Changelog.md delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Changelog.txt create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Internal/Changelog.md delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Internal/Changelog.txt create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Internal/Changelog.md delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Internal/Changelog.txt create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Changelog.md delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Changelog.txt create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Internal/Changelog.md delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Internal/Changelog.txt rename NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/{Migrations/Internal/IBMigrationsAnnotationProvider.cs => Metadata/Internal/IBRelationalAnnotationProvider.cs} (59%) create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Internal/Changelog.md delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Internal/Changelog.txt delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Operations/Changelog.txt delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Operations/IBCreateDatabaseOperation.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Operations/IBDropDatabaseOperation.cs create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/Changelog.md delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/Changelog.txt create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBByteArrayMethodTranslator.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBContainsOptimizedTranslator.cs create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateOnlyPartComponentTranslator.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateTimeDatePartComponentTranslator.cs create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateTimePartComponentTranslator.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBEndsWithOptimizedTranslator.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStartsWithOptimizedTranslator.cs create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringContainsTranslator.cs create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringEndsWithTranslator.cs create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringFirstOrDefaultTranslator.cs create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringLastOrDefaultTranslator.cs create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringStartsWithTranslator.cs create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBTimeOnlyPartComponentTranslator.cs create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBTimeSpanPartComponentTranslator.cs create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/Changelog.md delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/Changelog.txt delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/IBDateTimeDateMemberExpression.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/IBExtractExpression.cs create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/IBSpacedFunctionExpression.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/IBSubstringExpression.cs delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/IBTrimExpression.cs create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/Changelog.md delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/Changelog.txt create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/IBSqlTranslatingExpressionVisitor.cs create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/IBSqlTranslatingExpressionVisitorFactory.cs create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Scaffolding/Internal/Changelog.md delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Scaffolding/Internal/Changelog.txt rename NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Scaffolding/Internal/{IBProviderConfigurationCodeGenerator.cs => IBProviderCodeGenerator.cs} (51%) create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/Changelog.md delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/Changelog.txt create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBDateOnlyTypeMapping.cs create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBRelationalTransaction.cs create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBTimeOnlyTypeMapping.cs create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBTransactionFactory.cs rename NETProvider/Provider/src/{InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FiltersInheritanceIBFixture.cs => InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IRelationalIBTransaction.cs} (57%) create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/Changelog.md delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/Changelog.txt create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/Changelog.md delete mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/Changelog.txt create mode 100644 NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/EnumerableMethods.cs diff --git a/NETProvider/DDEX/installer/Install.wxs b/NETProvider/DDEX/installer/Install.wxs index 506ff7d..ef04cb6 100644 --- a/NETProvider/DDEX/installer/Install.wxs +++ b/NETProvider/DDEX/installer/Install.wxs @@ -1,116 +1,116 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NETProvider/Demos/EnityCoreExample2/Country.cs b/NETProvider/Demos/EnityCoreExample2/Country.cs new file mode 100644 index 0000000..809f7a0 --- /dev/null +++ b/NETProvider/Demos/EnityCoreExample2/Country.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; + +namespace EFCore101 +{ + public partial class Country + { + public Country() + { + Customers = new HashSet(); + Jobs = new HashSet(); + } + + public string Country1 { get; set; } = null!; + public string Currency { get; set; } = null!; + + public virtual ICollection Customers { get; set; } + public virtual ICollection Jobs { get; set; } + } +} diff --git a/NETProvider/Demos/EnityCoreExample2/Customer.cs b/NETProvider/Demos/EnityCoreExample2/Customer.cs new file mode 100644 index 0000000..b5ae725 --- /dev/null +++ b/NETProvider/Demos/EnityCoreExample2/Customer.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; + +namespace EFCore101 +{ + public partial class Customer + { + public Customer() + { + Sales = new HashSet(); + } + + public int CustNo { get; set; } + public string Customer1 { get; set; } = null!; + public string? ContactFirst { get; set; } + public string? ContactLast { get; set; } + public string? PhoneNo { get; set; } + public string? AddressLine1 { get; set; } + public string? AddressLine2 { get; set; } + public string? City { get; set; } + public string? StateProvince { get; set; } + public string? Country { get; set; } + public string? PostalCode { get; set; } + public string? OnHold { get; set; } + + public virtual Country? CountryNavigation { get; set; } + public virtual ICollection Sales { get; set; } + } +} diff --git a/NETProvider/Demos/EnityCoreExample2/Department.cs b/NETProvider/Demos/EnityCoreExample2/Department.cs new file mode 100644 index 0000000..1b0642e --- /dev/null +++ b/NETProvider/Demos/EnityCoreExample2/Department.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; + +namespace EFCore101 +{ + public partial class Department + { + public Department() + { + Employees = new HashSet(); + InverseHeadDeptNavigation = new HashSet(); + ProjDeptBudgets = new HashSet(); + } + + public string DeptNo { get; set; } = null!; + public string Department1 { get; set; } = null!; + public string? HeadDept { get; set; } + public short? MngrNo { get; set; } + public decimal? Budget { get; set; } + public string? Location { get; set; } + public string? PhoneNo { get; set; } + + public virtual Department? HeadDeptNavigation { get; set; } + public virtual Employee? MngrNoNavigation { get; set; } + public virtual ICollection Employees { get; set; } + public virtual ICollection InverseHeadDeptNavigation { get; set; } + public virtual ICollection ProjDeptBudgets { get; set; } + } +} diff --git a/NETProvider/Demos/EnityCoreExample2/EFCore101.csproj b/NETProvider/Demos/EnityCoreExample2/EFCore101.csproj new file mode 100644 index 0000000..3aecd18 --- /dev/null +++ b/NETProvider/Demos/EnityCoreExample2/EFCore101.csproj @@ -0,0 +1,38 @@ + + + + WinExe + net6.0-windows + enable + true + enable + + + + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + \ No newline at end of file diff --git a/NETProvider/Demos/EnityCoreExample2/EFCore101.sln b/NETProvider/Demos/EnityCoreExample2/EFCore101.sln new file mode 100644 index 0000000..08ec166 --- /dev/null +++ b/NETProvider/Demos/EnityCoreExample2/EFCore101.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33414.496 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore101", "EFCore101.csproj", "{1149F87D-10A0-49F5-9F4E-073F1B151DCC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1149F87D-10A0-49F5-9F4E-073F1B151DCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1149F87D-10A0-49F5-9F4E-073F1B151DCC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1149F87D-10A0-49F5-9F4E-073F1B151DCC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1149F87D-10A0-49F5-9F4E-073F1B151DCC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FF34E2E2-EB0F-4952-A33E-4A1F84E03486} + EndGlobalSection +EndGlobal diff --git a/NETProvider/Demos/EnityCoreExample2/Employee.cs b/NETProvider/Demos/EnityCoreExample2/Employee.cs new file mode 100644 index 0000000..534ba41 --- /dev/null +++ b/NETProvider/Demos/EnityCoreExample2/Employee.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; + +namespace EFCore101 +{ + public partial class Employee + { + public Employee() + { + Departments = new HashSet(); + Projects = new HashSet(); + SalaryHistories = new HashSet(); + Sales = new HashSet(); + Projs = new HashSet(); + } + + public short EmpNo { get; set; } + public string FirstName { get; set; } = null!; + public string LastName { get; set; } = null!; + public string? PhoneExt { get; set; } + public DateTime HireDate { get; set; } + public string DeptNo { get; set; } = null!; + public string JobCode { get; set; } = null!; + public short JobGrade { get; set; } + public string JobCountry { get; set; } = null!; + public decimal Salary { get; set; } + public string? FullName { get; set; } + + public virtual Department DeptNoNavigation { get; set; } = null!; + public virtual Job Job { get; set; } = null!; + public virtual ICollection Departments { get; set; } + public virtual ICollection Projects { get; set; } + public virtual ICollection SalaryHistories { get; set; } + public virtual ICollection Sales { get; set; } + + public virtual ICollection Projs { get; set; } + } +} diff --git a/NETProvider/Demos/EnityCoreExample2/EmployeeForm.Designer.cs b/NETProvider/Demos/EnityCoreExample2/EmployeeForm.Designer.cs new file mode 100644 index 0000000..360d560 --- /dev/null +++ b/NETProvider/Demos/EnityCoreExample2/EmployeeForm.Designer.cs @@ -0,0 +1,112 @@ +namespace EFCore101 +{ + partial class EmployeeForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + components = new System.ComponentModel.Container(); + employeeBindingSource = new BindingSource(components); + panel1 = new Panel(); + button1 = new Button(); + dataGridView1 = new DataGridView(); + ((System.ComponentModel.ISupportInitialize)employeeBindingSource).BeginInit(); + panel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)dataGridView1).BeginInit(); + SuspendLayout(); + // + // panel1 + // + panel1.Controls.Add(button1); + panel1.Dock = DockStyle.Top; + panel1.Location = new Point(0, 0); + panel1.Name = "panel1"; + panel1.Size = new Size(800, 50); + panel1.TabIndex = 5; + // + // button1 + // + button1.Location = new Point(12, 12); + button1.Name = "button1"; + button1.Size = new Size(143, 23); + button1.TabIndex = 1; + button1.Text = "Create Employee"; + button1.UseVisualStyleBackColor = true; + button1.Click += button1_Click; + // + // dataGridView1 + // + dataGridView1.AutoGenerateColumns = false; + dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; + dataGridView1.DataSource = employeeBindingSource; + dataGridView1.Dock = DockStyle.Fill; + dataGridView1.Location = new Point(0, 50); + dataGridView1.Name = "dataGridView1"; + dataGridView1.RowTemplate.Height = 25; + dataGridView1.Size = new Size(800, 400); + dataGridView1.TabIndex = 6; + // + // EmployeeForm + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(800, 450); + Controls.Add(dataGridView1); + Controls.Add(panel1); + Name = "EmployeeForm"; + Text = "EFCore 101"; + Load += Form1_Load; + ((System.ComponentModel.ISupportInitialize)employeeBindingSource).EndInit(); + panel1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)dataGridView1).EndInit(); + ResumeLayout(false); + } + + #endregion + private BindingSource employeeBindingSource; + private Panel panel1; + private Button button1; + private DataGridView dataGridView1; + private DataGridViewTextBoxColumn empNoDataGridViewTextBoxColumn; + private DataGridViewTextBoxColumn firstNameDataGridViewTextBoxColumn; + private DataGridViewTextBoxColumn lastNameDataGridViewTextBoxColumn; + private DataGridViewTextBoxColumn phoneExtDataGridViewTextBoxColumn; + private DataGridViewTextBoxColumn hireDateDataGridViewTextBoxColumn; + private DataGridViewTextBoxColumn deptNoDataGridViewTextBoxColumn; + private DataGridViewTextBoxColumn jobCodeDataGridViewTextBoxColumn; + private DataGridViewTextBoxColumn jobGradeDataGridViewTextBoxColumn; + private DataGridViewTextBoxColumn jobCountryDataGridViewTextBoxColumn; + private DataGridViewTextBoxColumn salaryDataGridViewTextBoxColumn; + private DataGridViewTextBoxColumn fullNameDataGridViewTextBoxColumn; + private DataGridViewTextBoxColumn deptNoNavigationDataGridViewTextBoxColumn; + private DataGridViewTextBoxColumn jobDataGridViewTextBoxColumn; + private DataGridViewTextBoxColumn departmentsDataGridViewTextBoxColumn; + private DataGridViewTextBoxColumn projectsDataGridViewTextBoxColumn; + private DataGridViewTextBoxColumn salaryHistoriesDataGridViewTextBoxColumn; + private DataGridViewTextBoxColumn salesDataGridViewTextBoxColumn; + private DataGridViewTextBoxColumn projsDataGridViewTextBoxColumn; + } +} \ No newline at end of file diff --git a/NETProvider/Demos/EnityCoreExample2/EmployeeForm.cs b/NETProvider/Demos/EnityCoreExample2/EmployeeForm.cs new file mode 100644 index 0000000..64a7db5 --- /dev/null +++ b/NETProvider/Demos/EnityCoreExample2/EmployeeForm.cs @@ -0,0 +1,43 @@ +using Microsoft.EntityFrameworkCore; + +namespace EFCore101 +{ + public partial class EmployeeForm : Form + { + MyEmployeeConnectionContext dbContext = new MyEmployeeConnectionContext(); + + public EmployeeForm() + { + InitializeComponent(); + } + + private void Form1_Load(object sender, EventArgs e) + { + dataGridView1.AutoGenerateColumns = true; + dataGridView1.DataSource = dbContext.Employees.ToList(); + } + + private void button1_Click(object sender, EventArgs e) + { + var rnd = new Random(); + var emp = new Employee() + { + EmpNo = (short)dbContext.GetNextSequenceValue("emp_no_gen"), + FirstName = "Testing " + rnd.Next(10000), + LastName = "EFCore101", + PhoneExt = "123", + HireDate = DateTime.Now, + DeptNo = "600", + JobCode = "VP", + JobGrade = 2, + JobCountry = "USA", + Salary = 80000 + rnd.Next(20000), + }; + + dbContext.Add(emp); + dbContext.SaveChanges(); + Form1_Load(sender, e); + } + } + +} \ No newline at end of file diff --git a/NETProvider/Demos/EnityCoreExample2/EmployeeForm.resx b/NETProvider/Demos/EnityCoreExample2/EmployeeForm.resx new file mode 100644 index 0000000..e638beb --- /dev/null +++ b/NETProvider/Demos/EnityCoreExample2/EmployeeForm.resx @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/NETProvider/Demos/EnityCoreExample2/Job.cs b/NETProvider/Demos/EnityCoreExample2/Job.cs new file mode 100644 index 0000000..4513d69 --- /dev/null +++ b/NETProvider/Demos/EnityCoreExample2/Job.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; + +namespace EFCore101 +{ + public partial class Job + { + public Job() + { + Employees = new HashSet(); + } + + public string JobCode { get; set; } = null!; + public short JobGrade { get; set; } + public string JobCountry { get; set; } = null!; + public string JobTitle { get; set; } = null!; + public decimal MinSalary { get; set; } + public decimal MaxSalary { get; set; } + public string? JobRequirement { get; set; } + public string? LanguageReq { get; set; } + + public virtual Country JobCountryNavigation { get; set; } = null!; + public virtual ICollection Employees { get; set; } + } +} diff --git a/NETProvider/Demos/EnityCoreExample2/MyEmployeeConnectionContext.cs b/NETProvider/Demos/EnityCoreExample2/MyEmployeeConnectionContext.cs new file mode 100644 index 0000000..365bf0f --- /dev/null +++ b/NETProvider/Demos/EnityCoreExample2/MyEmployeeConnectionContext.cs @@ -0,0 +1,527 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata; + +namespace EFCore101 +{ + public partial class MyEmployeeConnectionContext : DbContext + { + public MyEmployeeConnectionContext() + { + } + + public MyEmployeeConnectionContext(DbContextOptions options) + : base(options) + { + } + + public virtual DbSet Countries { get; set; } = null!; + public virtual DbSet Customers { get; set; } = null!; + public virtual DbSet Departments { get; set; } = null!; + public virtual DbSet Employees { get; set; } = null!; + public virtual DbSet Jobs { get; set; } = null!; + public virtual DbSet PhoneLists { get; set; } = null!; + public virtual DbSet ProjDeptBudgets { get; set; } = null!; + public virtual DbSet Projects { get; set; } = null!; + public virtual DbSet SalaryHistories { get; set; } = null!; + public virtual DbSet Sales { get; set; } = null!; + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + if (!optionsBuilder.IsConfigured) + { +#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see http://go.microsoft.com/fwlink/?LinkId=723263. + optionsBuilder.UseInterBase("data source=localhost;initial catalog=Employee;user id=sysdba;password=masterkey"); + } + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Country1) + .HasName("RDB$PRIMARY1"); + + entity.ToTable("COUNTRY"); + + entity.Property(e => e.Country1) + .HasMaxLength(15) + .HasColumnName("COUNTRY"); + + entity.Property(e => e.Currency) + .HasMaxLength(10) + .HasColumnName("CURRENCY"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.CustNo) + .HasName("RDB$PRIMARY22"); + + entity.ToTable("CUSTOMER"); + + entity.HasIndex(e => e.Customer1, "CUSTNAMEX"); + + entity.HasIndex(e => new { e.Country, e.City }, "CUSTREGION"); + + entity.Property(e => e.CustNo).HasColumnName("CUST_NO"); + + entity.Property(e => e.AddressLine1) + .HasMaxLength(30) + .HasColumnName("ADDRESS_LINE1"); + + entity.Property(e => e.AddressLine2) + .HasMaxLength(30) + .HasColumnName("ADDRESS_LINE2"); + + entity.Property(e => e.City) + .HasMaxLength(25) + .HasColumnName("CITY"); + + entity.Property(e => e.ContactFirst) + .HasMaxLength(15) + .HasColumnName("CONTACT_FIRST"); + + entity.Property(e => e.ContactLast) + .HasMaxLength(20) + .HasColumnName("CONTACT_LAST"); + + entity.Property(e => e.Country) + .HasMaxLength(15) + .HasColumnName("COUNTRY"); + + entity.Property(e => e.Customer1) + .HasMaxLength(25) + .HasColumnName("CUSTOMER"); + + entity.Property(e => e.OnHold) + .HasColumnType("CHAR(1)") + .HasColumnName("ON_HOLD") + .HasDefaultValueSql("NULL"); + + entity.Property(e => e.PhoneNo) + .HasMaxLength(20) + .HasColumnName("PHONE_NO"); + + entity.Property(e => e.PostalCode) + .HasMaxLength(12) + .HasColumnName("POSTAL_CODE"); + + entity.Property(e => e.StateProvince) + .HasMaxLength(15) + .HasColumnName("STATE_PROVINCE"); + + entity.HasOne(d => d.CountryNavigation) + .WithMany(p => p.Customers) + .HasForeignKey(d => d.Country) + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("INTEG_61"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.DeptNo) + .HasName("RDB$PRIMARY5"); + + entity.ToTable("DEPARTMENT"); + + entity.HasIndex(e => e.Budget, "BUDGETX"); + + entity.HasIndex(e => e.Department1, "INTEG_15") + .IsUnique(); + + entity.Property(e => e.DeptNo) + .HasColumnType("CHAR(3)") + .HasColumnName("DEPT_NO"); + + entity.Property(e => e.Budget) + .HasColumnType("DECIMAL") + .HasColumnName("BUDGET") + .HasDefaultValueSql("50000"); + + entity.Property(e => e.Department1) + .HasMaxLength(25) + .HasColumnName("DEPARTMENT"); + + entity.Property(e => e.HeadDept) + .HasColumnType("CHAR(3)") + .HasColumnName("HEAD_DEPT"); + + entity.Property(e => e.Location) + .HasMaxLength(15) + .HasColumnName("LOCATION"); + + entity.Property(e => e.MngrNo).HasColumnName("MNGR_NO"); + + entity.Property(e => e.PhoneNo) + .HasMaxLength(20) + .HasColumnName("PHONE_NO") + .HasDefaultValueSql("'555-1234'"); + + entity.HasOne(d => d.HeadDeptNavigation) + .WithMany(p => p.InverseHeadDeptNavigation) + .HasForeignKey(d => d.HeadDept) + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("INTEG_17"); + + entity.HasOne(d => d.MngrNoNavigation) + .WithMany(p => p.Departments) + .HasForeignKey(d => d.MngrNo) + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("INTEG_31"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.EmpNo) + .HasName("RDB$PRIMARY7"); + + entity.ToTable("EMPLOYEE"); + + entity.HasIndex(e => new { e.LastName, e.FirstName }, "NAMEX"); + + entity.Property(e => e.EmpNo).HasColumnName("EMP_NO"); + + entity.Property(e => e.DeptNo) + .HasColumnType("CHAR(3)") + .HasColumnName("DEPT_NO"); + + entity.Property(e => e.FirstName) + .HasMaxLength(15) + .HasColumnName("FIRST_NAME"); + + entity.Property(e => e.FullName) + .HasMaxLength(37) + .ValueGeneratedOnAddOrUpdate() + .HasColumnName("FULL_NAME"); + + entity.Property(e => e.HireDate) + .HasColumnName("HIRE_DATE") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + entity.Property(e => e.JobCode) + .HasMaxLength(5) + .HasColumnName("JOB_CODE"); + + entity.Property(e => e.JobCountry) + .HasMaxLength(15) + .HasColumnName("JOB_COUNTRY"); + + entity.Property(e => e.JobGrade).HasColumnName("JOB_GRADE"); + + entity.Property(e => e.LastName) + .HasMaxLength(20) + .HasColumnName("LAST_NAME"); + + entity.Property(e => e.PhoneExt) + .HasMaxLength(4) + .HasColumnName("PHONE_EXT"); + + entity.Property(e => e.Salary) + .HasColumnType("DECIMAL") + .HasColumnName("SALARY") + .HasDefaultValueSql("0"); + + entity.HasOne(d => d.DeptNoNavigation) + .WithMany(p => p.Employees) + .HasForeignKey(d => d.DeptNo) + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("INTEG_28"); + + entity.HasOne(d => d.Job) + .WithMany(p => p.Employees) + .HasForeignKey(d => new { d.JobCode, d.JobGrade, d.JobCountry }) + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("INTEG_29"); + + entity.HasMany(d => d.Projs) + .WithMany(p => p.EmpNos) + .UsingEntity>( + "EmployeeProject", + l => l.HasOne().WithMany().HasForeignKey("ProjId").OnDelete(DeleteBehavior.Restrict).HasConstraintName("INTEG_41"), + r => r.HasOne().WithMany().HasForeignKey("EmpNo").OnDelete(DeleteBehavior.Restrict).HasConstraintName("INTEG_40"), + j => + { + j.HasKey("EmpNo", "ProjId").HasName("RDB$PRIMARY14"); + + j.ToTable("EMPLOYEE_PROJECT"); + + j.IndexerProperty("EmpNo").HasColumnName("EMP_NO"); + + j.IndexerProperty("ProjId").HasColumnType("CHAR(5)").HasColumnName("PROJ_ID"); + }); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => new { e.JobCode, e.JobGrade, e.JobCountry }) + .HasName("RDB$PRIMARY2"); + + entity.ToTable("JOB"); + + entity.HasIndex(e => new { e.JobCountry, e.MaxSalary }, "MAXSALX"); + + entity.HasIndex(e => new { e.JobCountry, e.MinSalary }, "MINSALX"); + + entity.Property(e => e.JobCode) + .HasMaxLength(5) + .HasColumnName("JOB_CODE"); + + entity.Property(e => e.JobGrade).HasColumnName("JOB_GRADE"); + + entity.Property(e => e.JobCountry) + .HasMaxLength(15) + .HasColumnName("JOB_COUNTRY"); + + entity.Property(e => e.JobRequirement).HasColumnName("JOB_REQUIREMENT"); + + entity.Property(e => e.JobTitle) + .HasMaxLength(25) + .HasColumnName("JOB_TITLE"); + + entity.Property(e => e.LanguageReq) + .HasMaxLength(15) + .HasColumnName("LANGUAGE_REQ"); + + entity.Property(e => e.MaxSalary) + .HasColumnType("DECIMAL") + .HasColumnName("MAX_SALARY") + .HasDefaultValueSql("0"); + + entity.Property(e => e.MinSalary) + .HasColumnType("DECIMAL") + .HasColumnName("MIN_SALARY") + .HasDefaultValueSql("0"); + + entity.HasOne(d => d.JobCountryNavigation) + .WithMany(p => p.Jobs) + .HasForeignKey(d => d.JobCountry) + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("INTEG_11"); + }); + + modelBuilder.Entity(entity => + { + entity.HasNoKey(); + + entity.ToView("PHONE_LIST"); + + entity.Property(e => e.EmpNo).HasColumnName("EMP_NO"); + + entity.Property(e => e.FirstName) + .HasMaxLength(15) + .HasColumnName("FIRST_NAME"); + + entity.Property(e => e.LastName) + .HasMaxLength(20) + .HasColumnName("LAST_NAME"); + + entity.Property(e => e.Location) + .HasMaxLength(15) + .HasColumnName("LOCATION"); + + entity.Property(e => e.PhoneExt) + .HasMaxLength(4) + .HasColumnName("PHONE_EXT"); + + entity.Property(e => e.PhoneNo) + .HasMaxLength(20) + .HasColumnName("PHONE_NO"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => new { e.FiscalYear, e.ProjId, e.DeptNo }) + .HasName("RDB$PRIMARY17"); + + entity.ToTable("PROJ_DEPT_BUDGET"); + + entity.Property(e => e.FiscalYear).HasColumnName("FISCAL_YEAR"); + + entity.Property(e => e.ProjId) + .HasColumnType("CHAR(5)") + .HasColumnName("PROJ_ID"); + + entity.Property(e => e.DeptNo) + .HasColumnType("CHAR(3)") + .HasColumnName("DEPT_NO"); + + entity.Property(e => e.ProjectedBudget) + .HasColumnType("DECIMAL") + .HasColumnName("PROJECTED_BUDGET") + .HasDefaultValueSql("50000"); + + entity.Property(e => e.QuartHeadCnt).HasColumnName("QUART_HEAD_CNT"); + + entity.HasOne(d => d.DeptNoNavigation) + .WithMany(p => p.ProjDeptBudgets) + .HasForeignKey(d => d.DeptNo) + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("INTEG_47"); + + entity.HasOne(d => d.Proj) + .WithMany(p => p.ProjDeptBudgets) + .HasForeignKey(d => d.ProjId) + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("INTEG_48"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.ProjId) + .HasName("RDB$PRIMARY12"); + + entity.ToTable("PROJECT"); + + entity.HasIndex(e => e.ProjName, "INTEG_34") + .IsUnique(); + + entity.HasIndex(e => new { e.Product, e.ProjName }, "PRODTYPEX") + .IsUnique(); + + entity.Property(e => e.ProjId) + .HasColumnType("CHAR(5)") + .HasColumnName("PROJ_ID"); + + entity.Property(e => e.Product) + .HasMaxLength(12) + .HasColumnName("PRODUCT") + .HasDefaultValueSql("'software'"); + + entity.Property(e => e.ProjDesc).HasColumnName("PROJ_DESC"); + + entity.Property(e => e.ProjName) + .HasMaxLength(20) + .HasColumnName("PROJ_NAME"); + + entity.Property(e => e.TeamLeader).HasColumnName("TEAM_LEADER"); + + entity.HasOne(d => d.TeamLeaderNavigation) + .WithMany(p => p.Projects) + .HasForeignKey(d => d.TeamLeader) + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("INTEG_36"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => new { e.EmpNo, e.ChangeDate, e.UpdaterId }) + .HasName("RDB$PRIMARY20"); + + entity.ToTable("SALARY_HISTORY"); + + entity.HasIndex(e => e.ChangeDate, "CHANGEX"); + + entity.HasIndex(e => e.UpdaterId, "UPDATERX"); + + entity.Property(e => e.EmpNo).HasColumnName("EMP_NO"); + + entity.Property(e => e.ChangeDate) + .HasColumnName("CHANGE_DATE") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + entity.Property(e => e.UpdaterId) + .HasMaxLength(20) + .HasColumnName("UPDATER_ID"); + + entity.Property(e => e.NewSalary) + .ValueGeneratedOnAddOrUpdate() + .HasColumnName("NEW_SALARY"); + + entity.Property(e => e.OldSalary) + .HasColumnType("DECIMAL") + .HasColumnName("OLD_SALARY") + .HasDefaultValueSql("0"); + + entity.Property(e => e.PercentChange) + .HasColumnName("PERCENT_CHANGE") + .HasDefaultValueSql("0"); + + entity.HasOne(d => d.EmpNoNavigation) + .WithMany(p => p.SalaryHistories) + .HasForeignKey(d => d.EmpNo) + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("INTEG_56"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.PoNumber) + .HasName("RDB$PRIMARY24"); + + entity.ToTable("SALES"); + + entity.HasIndex(e => e.DateNeeded, "NEEDX"); + + entity.HasIndex(e => new { e.ItemType, e.QtyOrdered }, "QTYX"); + + entity.HasIndex(e => new { e.OrderStatus, e.Paid }, "SALESTATX"); + + entity.Property(e => e.PoNumber) + .HasColumnType("CHAR(8)") + .HasColumnName("PO_NUMBER"); + + entity.Property(e => e.Aged) + .HasColumnType("BIGINT") + .ValueGeneratedOnAddOrUpdate() + .HasColumnName("AGED"); + + entity.Property(e => e.CustNo).HasColumnName("CUST_NO"); + + entity.Property(e => e.DateNeeded).HasColumnName("DATE_NEEDED"); + + entity.Property(e => e.Discount) + .HasColumnName("DISCOUNT") + .HasDefaultValueSql("0"); + + entity.Property(e => e.ItemType) + .HasMaxLength(12) + .HasColumnName("ITEM_TYPE") + .HasDefaultValueSql("'software'"); + + entity.Property(e => e.OrderDate) + .HasColumnName("ORDER_DATE") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + entity.Property(e => e.OrderStatus) + .HasMaxLength(7) + .HasColumnName("ORDER_STATUS") + .HasDefaultValueSql("'new'"); + + entity.Property(e => e.Paid) + .HasColumnType("CHAR(1)") + .HasColumnName("PAID") + .HasDefaultValueSql("'n'"); + + entity.Property(e => e.QtyOrdered) + .HasColumnName("QTY_ORDERED") + .HasDefaultValueSql("1"); + + entity.Property(e => e.SalesRep).HasColumnName("SALES_REP"); + + entity.Property(e => e.ShipDate).HasColumnName("SHIP_DATE"); + + entity.Property(e => e.TotalValue) + .HasColumnType("DECIMAL") + .HasColumnName("TOTAL_VALUE"); + + entity.HasOne(d => d.CustNoNavigation) + .WithMany(p => p.Sales) + .HasForeignKey(d => d.CustNo) + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("INTEG_77"); + + entity.HasOne(d => d.SalesRepNavigation) + .WithMany(p => p.Sales) + .HasForeignKey(d => d.SalesRep) + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("INTEG_78"); + }); + + OnModelCreatingPartial(modelBuilder); + } + + partial void OnModelCreatingPartial(ModelBuilder modelBuilder); + } +} diff --git a/NETProvider/Demos/EnityCoreExample2/MyEmployeeUtils.cs b/NETProvider/Demos/EnityCoreExample2/MyEmployeeUtils.cs new file mode 100644 index 0000000..ce2b509 --- /dev/null +++ b/NETProvider/Demos/EnityCoreExample2/MyEmployeeUtils.cs @@ -0,0 +1,18 @@ +using Microsoft.EntityFrameworkCore; + +namespace EFCore101 +{ + partial class MyEmployeeConnectionContext : DbContext + { + public long GetNextSequenceValue(string genName) + { + using (var cmd = Database.GetDbConnection().CreateCommand()) + { + Database.GetDbConnection().Open(); + cmd.CommandText = "SELECT gen_id(" + genName + ", 1) from rdb$database"; + var obj = cmd.ExecuteScalar(); + return (long)obj; + } + } + } +} \ No newline at end of file diff --git a/NETProvider/Demos/EnityCoreExample2/PhoneList.cs b/NETProvider/Demos/EnityCoreExample2/PhoneList.cs new file mode 100644 index 0000000..b74220e --- /dev/null +++ b/NETProvider/Demos/EnityCoreExample2/PhoneList.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; + +namespace EFCore101 +{ + public partial class PhoneList + { + public short? EmpNo { get; set; } + public string? FirstName { get; set; } + public string? LastName { get; set; } + public string? PhoneExt { get; set; } + public string? Location { get; set; } + public string? PhoneNo { get; set; } + } +} diff --git a/NETProvider/Demos/EnityCoreExample2/Program.cs b/NETProvider/Demos/EnityCoreExample2/Program.cs new file mode 100644 index 0000000..33a3dc7 --- /dev/null +++ b/NETProvider/Demos/EnityCoreExample2/Program.cs @@ -0,0 +1,17 @@ +namespace EFCore101 +{ + internal static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + // To customize application configuration such as set high DPI settings or default font, + // see https://aka.ms/applicationconfiguration. + ApplicationConfiguration.Initialize(); + Application.Run(new EmployeeForm()); + } + } +} \ No newline at end of file diff --git a/NETProvider/Demos/EnityCoreExample2/ProjDeptBudget.cs b/NETProvider/Demos/EnityCoreExample2/ProjDeptBudget.cs new file mode 100644 index 0000000..da6df12 --- /dev/null +++ b/NETProvider/Demos/EnityCoreExample2/ProjDeptBudget.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; + +namespace EFCore101 +{ + public partial class ProjDeptBudget + { + public int FiscalYear { get; set; } + public string ProjId { get; set; } = null!; + public string DeptNo { get; set; } = null!; + public int? QuartHeadCnt { get; set; } + public decimal? ProjectedBudget { get; set; } + + public virtual Department DeptNoNavigation { get; set; } = null!; + public virtual Project Proj { get; set; } = null!; + } +} diff --git a/NETProvider/Demos/EnityCoreExample2/Project.cs b/NETProvider/Demos/EnityCoreExample2/Project.cs new file mode 100644 index 0000000..65f6eb9 --- /dev/null +++ b/NETProvider/Demos/EnityCoreExample2/Project.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; + +namespace EFCore101 +{ + public partial class Project + { + public Project() + { + ProjDeptBudgets = new HashSet(); + EmpNos = new HashSet(); + } + + public string ProjId { get; set; } = null!; + public string ProjName { get; set; } = null!; + public string? ProjDesc { get; set; } + public short? TeamLeader { get; set; } + public string? Product { get; set; } + + public virtual Employee? TeamLeaderNavigation { get; set; } + public virtual ICollection ProjDeptBudgets { get; set; } + + public virtual ICollection EmpNos { get; set; } + } +} diff --git a/NETProvider/Demos/EnityCoreExample2/Properties/DataSources/Employee.datasource b/NETProvider/Demos/EnityCoreExample2/Properties/DataSources/Employee.datasource new file mode 100644 index 0000000..b38ee2e --- /dev/null +++ b/NETProvider/Demos/EnityCoreExample2/Properties/DataSources/Employee.datasource @@ -0,0 +1,10 @@ + + + + EFCore101.Employee, EFCore101, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + \ No newline at end of file diff --git a/NETProvider/Demos/EnityCoreExample2/SalaryHistory.cs b/NETProvider/Demos/EnityCoreExample2/SalaryHistory.cs new file mode 100644 index 0000000..7668457 --- /dev/null +++ b/NETProvider/Demos/EnityCoreExample2/SalaryHistory.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; + +namespace EFCore101 +{ + public partial class SalaryHistory + { + public short EmpNo { get; set; } + public DateTime ChangeDate { get; set; } + public string UpdaterId { get; set; } = null!; + public decimal OldSalary { get; set; } + public double PercentChange { get; set; } + public double? NewSalary { get; set; } + + public virtual Employee EmpNoNavigation { get; set; } = null!; + } +} diff --git a/NETProvider/Demos/EnityCoreExample2/Sale.cs b/NETProvider/Demos/EnityCoreExample2/Sale.cs new file mode 100644 index 0000000..1d71f33 --- /dev/null +++ b/NETProvider/Demos/EnityCoreExample2/Sale.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; + +namespace EFCore101 +{ + public partial class Sale + { + public string PoNumber { get; set; } = null!; + public int CustNo { get; set; } + public short? SalesRep { get; set; } + public string OrderStatus { get; set; } = null!; + public DateTime OrderDate { get; set; } + public DateTime? ShipDate { get; set; } + public DateTime? DateNeeded { get; set; } + public string? Paid { get; set; } + public int QtyOrdered { get; set; } + public decimal TotalValue { get; set; } + public float Discount { get; set; } + public string? ItemType { get; set; } + public long? Aged { get; set; } + + public virtual Customer CustNoNavigation { get; set; } = null!; + public virtual Employee? SalesRepNavigation { get; set; } + } +} diff --git a/NETProvider/Provider/build.ps1 b/NETProvider/Provider/build.ps1 index 2f4ed79..e0aa269 100644 --- a/NETProvider/Provider/build.ps1 +++ b/NETProvider/Provider/build.ps1 @@ -45,14 +45,13 @@ function Build() { function Pack() { 7z a -mx=9 -bsp0 $outDir\InterBaseSql.Data.InterBaseClient-$version-net452.7z $baseDir\src\InterBaseSql.Data.InterBaseClient\bin\$Configuration\net452\InterBaseSql.Data.InterBaseClient.dll $baseDir\src\InterBaseSql.Data.InterBaseClient\bin\$Configuration\net452\InterBaseSql.Data.InterBaseClient.pdb - 7z a -mx=9 -bsp0 $outDir\InterBaseSql.Data.InterBaseClient-$version-netstandard2.0.7z $baseDir\src\InterBaseSql.Data.InterBaseClient\bin\$Configuration\netstandard2.0\InterBaseSql.Data.InterBaseClient.dll $baseDir\src\InterBaseSql.Data.InterBaseClient\bin\$Configuration\netstandard2.0\InterBaseSql.Data.InterBaseClient.pdb 7z a -mx=9 -bsp0 $outDir\InterBaseSql.Data.InterBaseClient-$version-net5.0.7z $baseDir\src\InterBaseSql.Data.InterBaseClient\bin\$Configuration\net5.0\InterBaseSql.Data.InterBaseClient.dll $baseDir\src\InterBaseSql.Data.InterBaseClient\bin\$Configuration\net5.0\InterBaseSql.Data.InterBaseClient.pdb 7z a -mx=9 -bsp0 $outDir\InterBaseSql.Data.InterBaseClient-$version-net6.0.7z $baseDir\src\InterBaseSql.Data.InterBaseClient\bin\$Configuration\net6.0\InterBaseSql.Data.InterBaseClient.dll $baseDir\src\InterBaseSql.Data.InterBaseClient\bin\$Configuration\net6.0\InterBaseSql.Data.InterBaseClient.pdb - 7z a -mx=9 -bsp0 $outDir\EntityFramework.InterBase-$version-net452.7z $baseDir\src\EntityFramework.InterBase\bin\$Configuration\net452\EntityFramework.InterBase.dll $baseDir\src\EntityFramework.InterBase\bin\$Configuration\net452\EntityFramework.InterBase.pdb - 7z a -mx=9 -bsp0 $outDir\EntityFramework.InterBase-$version-netstandard2.1.7z $baseDir\src\EntityFramework.InterBase\bin\$Configuration\netstandard2.1\EntityFramework.InterBase.dll $baseDir\src\EntityFramework.InterBase\bin\$Configuration\netstandard2.1\EntityFramework.InterBase.pdb +# 7z a -mx=9 -bsp0 $outDir\EntityFramework.InterBase-$version-net452.7z $baseDir\src\EntityFramework.InterBase\bin\$Configuration\net452\EntityFramework.InterBase.dll $baseDir\src\EntityFramework.InterBase\bin\$Configuration\net452\EntityFramework.InterBase.pdb +# 7z a -mx=9 -bsp0 $outDir\EntityFramework.InterBase-$version-netstandard2.1.7z $baseDir\src\EntityFramework.InterBase\bin\$Configuration\netstandard2.1\EntityFramework.InterBase.dll $baseDir\src\EntityFramework.InterBase\bin\$Configuration\netstandard2.1\EntityFramework.InterBase.pdb - 7z a -mx=9 -bsp0 $outDir\InterBaseSql.EntityFrameworkCore.InterBase-$version-netstandard2.0.7z $baseDir\src\InterBaseSql.EntityFrameworkCore.InterBase\bin\$Configuration\netstandard2.0\InterBaseSql.EntityFrameworkCore.InterBase.dll $baseDir\src\InterBaseSql.EntityFrameworkCore.InterBase\bin\$Configuration\netstandard2.0\InterBaseSql.EntityFrameworkCore.InterBase.pdb + 7z a -mx=9 -bsp0 $outDir\InterBaseSql.EntityFrameworkCore.InterBase-$version-net6.0.7z $baseDir\src\InterBaseSql.EntityFrameworkCore.InterBase\bin\$Configuration\net6.0\InterBaseSql.EntityFrameworkCore.InterBase.dll $baseDir\src\InterBaseSql.EntityFrameworkCore.InterBase\bin\$Configuration\net6.0\InterBaseSql.EntityFrameworkCore.InterBase.pdb } function NuGets() { diff --git a/NETProvider/Provider/docs/ADO Driver documentation.docx b/NETProvider/Provider/docs/ADO Driver documentation.docx index 7f6bfa0d37bf5c62d23db4803ed315da4f5f902b..00e06ef237877b32b18486cfd2ea6087af08f1ce 100644 GIT binary patch delta 50933 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 X;B=NcCR@h))1B&=4B4JmFagB?D23Bd diff --git a/NETProvider/Provider/installer/Installer.wxs b/NETProvider/Provider/installer/Installer.wxs index 845257e..ace7c86 100644 --- a/NETProvider/Provider/installer/Installer.wxs +++ b/NETProvider/Provider/installer/Installer.wxs @@ -12,11 +12,13 @@ - - - + + + + + @@ -135,6 +137,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/NETProvider/Provider/src/Directory.Build.props b/NETProvider/Provider/src/Directory.Build.props index 776b0a5..12d039f 100644 --- a/NETProvider/Provider/src/Directory.Build.props +++ b/NETProvider/Provider/src/Directory.Build.props @@ -5,7 +5,7 @@ portable - 7.12.1 + 7.13.6 Embarcadero NETProvider diff --git a/NETProvider/Provider/src/EntityFramework.InterBase/SqlGen/SqlGenerator.cs b/NETProvider/Provider/src/EntityFramework.InterBase/SqlGen/SqlGenerator.cs index 9ecabc4..040b90d 100644 --- a/NETProvider/Provider/src/EntityFramework.InterBase/SqlGen/SqlGenerator.cs +++ b/NETProvider/Provider/src/EntityFramework.InterBase/SqlGen/SqlGenerator.cs @@ -1142,7 +1142,7 @@ public override ISqlFragment Visit(DbIsOfExpression e) /// A . public override ISqlFragment Visit(DbCrossJoinExpression e) { - return VisitJoinExpression(e.Inputs, e.ExpressionKind, "CROSS JOIN", null); + return VisitJoinExpression(e.Inputs, e.ExpressionKind, ",", null); } /// diff --git a/NETProvider/Provider/src/EntityFramework.InterBase/SqlGen/SqlSelectStatement.cs b/NETProvider/Provider/src/EntityFramework.InterBase/SqlGen/SqlSelectStatement.cs index 921bb45..9e834c2 100644 --- a/NETProvider/Provider/src/EntityFramework.InterBase/SqlGen/SqlSelectStatement.cs +++ b/NETProvider/Provider/src/EntityFramework.InterBase/SqlGen/SqlSelectStatement.cs @@ -307,14 +307,14 @@ public void WriteSql(SqlWriter writer, SqlGenerator sqlGenerator) } else if (First != null) - { - First.WriteSql(writer, sqlGenerator); - } - else + { + First.WriteSql(writer, sqlGenerator); + } + else if (Skip != null) - { - Skip.WriteSql(writer, sqlGenerator); - } + { + Skip.WriteSql(writer, sqlGenerator); + } --writer.Indent; } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/ChangeViewTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/ChangeViewTests.cs index 4e55e82..5a07f5a 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/ChangeViewTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/ChangeViewTests.cs @@ -670,4 +670,14 @@ public void ChangeAllDataSetSrcNameStartEnd() } #endregion } + + public class ChangeViewTestsDialect1 : ChangeViewTests + { + public ChangeViewTestsDialect1(IBServerType serverType) + : base(serverType) + { + IBTestsSetup.Dialect = 1; + } + } + } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/Changelog.md b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/Changelog.md index 3329f4d..597c65e 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/Changelog.md +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/Changelog.md @@ -1,3 +1,29 @@ +# Changes for 7.13.6 + +## All Files +^ Added support to run the tests also in dialect 1. Old tests only tested against dialect 3. + This includes changes for type > numeric(9,0) where in D3 it is a scaled int64 and in D1 double precision + Also include changes around the DATE data tyoe which is a timestamp in D1 and TIMe not being there in D1. + +## IBArrayTests.cs +^ BigIntArrayTest made virutal so the dialect 1 version of teh test could be overriden +^ TimeArrayTest made virtual because Dialect 1 does not have a time datatype and can be a test basically not run +^ TimeArrayPartialUpdateTest made virtual because Dialect 1 does not have a time datatype and can be a test basically not run + +## IBConnectionStringBuilderTests.cs +^ Added a dialect test to test the connecton peroperly downgrades from 3 to 1. + +## IBConnectionTests.cs +^ added a test around casting to the DATE type and dialect 1 +^ added a test DialectScaleback to test the new dialect downgrade event + +## IBDatabaseInfoTests.cs +^ added test to retrieve the DB dialect + +## IBDataReaderTests.cs +^ added a dialect 1 test that decimals are the right type. + + # Changes for 7.12.1 ## ChangeViewTests.cs diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/ConnectionStringTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/ConnectionStringTests.cs index 0aabbd7..b1dc7d6 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/ConnectionStringTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/ConnectionStringTests.cs @@ -28,14 +28,17 @@ namespace InterBaseSql.Data.InterBaseClient.Tests public class ConnectionStringTests { [Test] - public void ParsingNormalConnectionStringTest() + [TestCase(3)] + [TestCase(1)] + public void ParsingNormalConnectionStringTest(int Dialect) { - const string ConnectionString = "datasource=testserver;database=testdb.ib;user=testuser;password=testpwd"; + string ConnectionString = "datasource=testserver;database=testdb.ib;user=testuser;password=testpwd;dialect=" + Dialect.ToString(); var cs = new ConnectionString(ConnectionString); Assert.AreEqual("testserver", cs.DataSource); Assert.AreEqual("testdb.ib", cs.Database); Assert.AreEqual("testuser", cs.UserID); Assert.AreEqual("testpwd", cs.Password); + Assert.AreEqual(Dialect, cs.Dialect); } [Test] diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/GuidTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/GuidTests.cs index ad1d32b..c67a2e5 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/GuidTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/GuidTests.cs @@ -93,4 +93,13 @@ public void InsertNullGuidTest() #endregion } + public class GuidTestsDialect1 : GuidTests + { + public GuidTestsDialect1(IBServerType serverType) + : base(serverType) + { + IBTestsSetup.Dialect = 1; + } + + } } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBArrayTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBArrayTests.cs index f16fd40..719a3ac 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBArrayTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBArrayTests.cs @@ -121,7 +121,7 @@ public void ShortArrayTest() } [Test] - public void BigIntArrayTest() + public virtual void BigIntArrayTest() { Transaction = Connection.BeginTransaction(); @@ -321,7 +321,7 @@ public void DateArrayTest() } [Test] - public void TimeArrayTest() + public virtual void TimeArrayTest() { Transaction = Connection.BeginTransaction(); @@ -618,7 +618,7 @@ public void DateArrayPartialUpdateTest() } [Test] - public void TimeArrayPartialUpdateTest() + public virtual void TimeArrayPartialUpdateTest() { var updateText = "update TEST set tarray_field = @array_field " + "WHERE int_field = 1"; @@ -787,4 +787,111 @@ public void PartialUpdatesTest() #endregion } + public class IBArrayTestsDialect1 : IBArrayTests + { + public IBArrayTestsDialect1(IBServerType serverType) + : base(serverType) + { + IBTestsSetup.Dialect = 1; + } + + [Test] + public override void TimeArrayPartialUpdateTest() + { + var updateText = "update TEST set tarray_field = @array_field " + + "WHERE int_field = 1"; + + var new_values = new DateTime[2]; + + new_values[0] = new DateTime(1, 1, 1, 11, 13, 14); + new_values[1] = new DateTime(1, 1, 1, 12, 15, 16); + + var update = new IBCommand(updateText, Connection); + + update.Parameters.Add("@array_field", IBDbType.Array).Value = new_values; + + update.ExecuteNonQuery(); + update.Dispose(); + } + + [Test] + public override void TimeArrayTest() + { + Transaction = Connection.BeginTransaction(); + + var id_value = GetId(); + + var selectText = "SELECT tarray_field FROM TEST WHERE int_field = " + id_value.ToString(); + var insertText = "INSERT INTO TEST (int_field, tarray_field) values(@int_field, @array_field)"; + + var insert_values = new DateTime[4]; + + insert_values[0] = new DateTime(1, 1, 1, 3, 9, 10); + insert_values[1] = new DateTime(1, 1, 1, 4, 11, 12); + insert_values[2] = new DateTime(1, 1, 1, 6, 13, 14); + insert_values[3] = new DateTime(1, 1, 1, 8, 15, 16); + + var insert = new IBCommand(insertText, Connection, Transaction); + insert.Parameters.Add("@int_field", IBDbType.Integer).Value = id_value; + insert.Parameters.Add("@array_field", IBDbType.Array).Value = insert_values; + insert.ExecuteNonQuery(); + insert.Dispose(); + + Transaction.Commit(); + + var select = new IBCommand(selectText, Connection); + var reader = select.ExecuteReader(); + if (reader.Read()) + { + if (!reader.IsDBNull(0)) + { + var select_values = new DateTime[insert_values.Length]; + Array.Copy((Array)reader.GetValue(0), select_values, select_values.Length); + CollectionAssert.AreEqual(insert_values, select_values); + } + } + reader.Close(); + select.Dispose(); + } + [Test] + public override void BigIntArrayTest() + { + Transaction = Connection.BeginTransaction(); + + var id_value = GetId(); + + var selectText = "SELECT larray_field FROM TEST WHERE int_field = " + id_value.ToString(); + var insertText = "INSERT INTO TEST (int_field, larray_field) values(@int_field, @array_field)"; + + var insert_values = new double[4]; + + insert_values[0] = 50; + insert_values[1] = 60; + insert_values[2] = 70; + insert_values[3] = 80; + + var insert = new IBCommand(insertText, Connection, Transaction); + insert.Parameters.Add("@int_field", IBDbType.Integer).Value = id_value; + insert.Parameters.Add("@array_field", IBDbType.Array).Value = insert_values; + insert.ExecuteNonQuery(); + insert.Dispose(); + + Transaction.Commit(); + + var select = new IBCommand(selectText, Connection); + var reader = select.ExecuteReader(); + if (reader.Read()) + { + if (!reader.IsDBNull(0)) + { + var select_values = new double[insert_values.Length]; + Array.Copy((Array)reader.GetValue(0), select_values, select_values.Length); + CollectionAssert.AreEqual(insert_values, select_values); + } + } + reader.Close(); + select.Dispose(); + } + } + } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBBlobTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBBlobTests.cs index 0683187..fecef24 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBBlobTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBBlobTests.cs @@ -134,6 +134,16 @@ public void ReaderGetBytes() } } - #endregion +#endregion + } + + public class IBBlobTestsDialect1 : IBBlobTests + { + public IBBlobTestsDialect1(IBServerType serverType) + : base(serverType) + { + IBTestsSetup.Dialect = 1; + } + } } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBBooleanSupportTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBBooleanSupportTests.cs index cec0aaf..538790b 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBBooleanSupportTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBBooleanSupportTests.cs @@ -42,9 +42,6 @@ public override void SetUp() { base.SetUp(); -// if (!EnsureVersion(new Version(3, 0, 0, 0))) -// return; - _shouldTearDown = true; using (var cmd = Connection.CreateCommand()) { @@ -161,4 +158,14 @@ public void ParametrizedInsertTest(int id, bool? value) } } } + + public class IBBooleanSupportTestsDialect1 : IBBooleanSupportTests + { + public IBBooleanSupportTestsDialect1(IBServerType serverType) + : base(serverType) + { + IBTestsSetup.Dialect = 1; + } + } + } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBCommandBuilderTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBCommandBuilderTests.cs index 9571924..9eb5348 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBCommandBuilderTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBCommandBuilderTests.cs @@ -194,4 +194,14 @@ public void TestWithClosedConnection() #endregion } + + public class IBCommandBuilderTestsDialect1 : IBCommandBuilderTests + { + public IBCommandBuilderTestsDialect1(IBServerType serverType) + : base(serverType) + { + IBTestsSetup.Dialect = 1; + } + + } } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBCommandTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBCommandTests.cs index 35f8caf..773570a 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBCommandTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBCommandTests.cs @@ -514,7 +514,10 @@ public void InsertTimeTest() using (var cmd = Connection.CreateCommand()) { cmd.CommandText = "insert into test (int_field, time_field) values (2245, @t)"; - cmd.Parameters.Add("@t", IBDbType.Time).Value = t; + if (IBTestsSetup.Dialect == 3) + cmd.Parameters.Add("@t", IBDbType.Time).Value = t; + else + cmd.Parameters.Add("@t", IBDbType.TimeStamp).Value = t; var ra = cmd.ExecuteNonQuery(); @@ -524,7 +527,11 @@ public void InsertTimeTest() using (var cmd = Connection.CreateCommand()) { cmd.CommandText = "select time_field from test where int_field = 2245"; - var result = (TimeSpan)cmd.ExecuteScalar(); + TimeSpan result; + if (IBTestsSetup.Dialect == 3) + result = (TimeSpan)cmd.ExecuteScalar(); + else + result = ((DateTime)cmd.ExecuteScalar()).TimeOfDay; Assert.AreEqual(t.Hours, result.Hours, "hours are not same"); Assert.AreEqual(t.Minutes, result.Minutes, "minutes are not same"); @@ -545,7 +552,10 @@ public void InsertTimeOldTest() using (var cmd = Connection.CreateCommand()) { cmd.CommandText = "insert into test (int_field, time_field) values (2245, @t)"; - cmd.Parameters.Add("@t", IBDbType.Time).Value = t; + if (IBTestsSetup.Dialect == 3) + cmd.Parameters.Add("@t", IBDbType.Time).Value = t; + else + cmd.Parameters.Add("@t", IBDbType.TimeStamp).Value = t; var ra = cmd.ExecuteNonQuery(); @@ -555,7 +565,13 @@ public void InsertTimeOldTest() using (var cmd = Connection.CreateCommand()) { cmd.CommandText = "select time_field from test where int_field = 2245"; - var result = (TimeSpan)cmd.ExecuteScalar(); + + TimeSpan result; + if (IBTestsSetup.Dialect == 3) + result = (TimeSpan)cmd.ExecuteScalar(); + else + result = ((DateTime)cmd.ExecuteScalar()).TimeOfDay; + Assert.AreEqual(t.Hour, result.Hours, "hours are not same"); Assert.AreEqual(t.Minute, result.Minutes, "minutes are not same"); @@ -660,43 +676,6 @@ public void ReadingCharOctetsTest() } } -// [Test] -// public void CommandCancellationTest() -// { -// if (!EnsureVersion(new Version(2, 5, 0, 0))) -// return; - -// var cancelled = false; - -// using (var cmd = Connection.CreateCommand()) -// { -// cmd.CommandText = -//@"execute block as -//declare variable start_time timestamp; -//begin -// start_time = cast('now' as timestamp); -// while (datediff(second from start_time to cast('now' as timestamp)) <= 10) do -// begin -// end -//end"; -// ThreadPool.QueueUserWorkItem(_ => -// { -// try -// { -// cmd.ExecuteNonQuery(); -// } -// catch (IBException ex) -// { -// cancelled = "HY008" == ex.SQLSTATE; -// } -// }); -// Thread.Sleep(2000); -// cmd.Cancel(); -// Thread.Sleep(2000); -// Assert.IsTrue(cancelled); -// } -// } - [Test] public void CommandPlanTest() { @@ -724,12 +703,15 @@ public void NoCommandPlanTest() } [Test] - public void ReadsTimeWithProperPrecision() + public virtual void ReadsTimeWithProperPrecision() { using (var cmd = Connection.CreateCommand()) { - cmd.CommandText = "select cast('00:00:01.4321' as time) from rdb$database"; - var result = (TimeSpan)cmd.ExecuteScalar(); + cmd.CommandText = "select cast('01/12/2023 00:00:01.4321' as timestamp) from rdb$database"; + + TimeSpan result; + result = ((DateTime)cmd.ExecuteScalar()).TimeOfDay; + Assert.AreEqual(TimeSpan.FromTicks(14321000), result); } } @@ -776,4 +758,27 @@ public void ExecuteNonQueryOnFetch() #endregion } + + public class IBCommandTestsDialect1 : IBCommandTests + { + public IBCommandTestsDialect1(IBServerType serverType) + : base(serverType) + { + IBTestsSetup.Dialect = 1; + } + + [Test] + public override void ReadsTimeWithProperPrecision() + { + using (var cmd = Connection.CreateCommand()) + { + cmd.CommandText = "select cast('01/12/2023 00:00:01.4321' as timestamp) from rdb$database"; + + TimeSpan result; + result = ((DateTime)cmd.ExecuteScalar()).TimeOfDay; + + Assert.AreEqual(TimeSpan.FromTicks(14321000), result); + } + } + } } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBConnectionStringBuilderTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBConnectionStringBuilderTests.cs index 9f0067b..d3b9a3f 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBConnectionStringBuilderTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBConnectionStringBuilderTests.cs @@ -47,5 +47,24 @@ public void CharacterSetDefault() Assert.AreEqual(b.Charset, "None"); } + [Test] + public void Dialect() + { + var connectionString = new IBConnectionStringBuilder() + { + Dialect = IBTestsSetup.Dialect + }; + Assert.AreEqual(true, connectionString.ToString().Contains("dialect=" + IBTestsSetup.Dialect.ToString())); + } + + } + + public class IBConnectionStringBuilderTestsDialect1 : IBConnectionStringBuilderTests + { + public IBConnectionStringBuilderTestsDialect1() + { + IBTestsSetup.Dialect = 1; + } } + } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBConnectionTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBConnectionTests.cs index e371ce6..2f9e91a 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBConnectionTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBConnectionTests.cs @@ -341,6 +341,81 @@ private int GetLogRowsCount(IBConnection conn) } } + [Test] + [TestCase(1)] + [TestCase(3)] + public void DialectAndDATE(int dialect) + { + IBConnectionStringBuilder builder = IBTestsBase.BuildConnectionStringBuilder(IBServerType); + builder.Dialect = dialect; + builder.Charset = "none"; + var cs = builder.ToString(); + using (var connection = new IBConnection(cs)) + { + connection.Open(); + using (var cmd = connection.CreateCommand()) + { + cmd.CommandText = "CREATE PROCEDURE TEST_PROCEDURE (TEST_ARG DATE) AS BEGIN EXIT; END"; + Assert.DoesNotThrow(() => cmd.Prepare()); + } + } + } #endregion } + + public class IBConnectionTestsDialect1 : IBConnectionTests + { + private IBServerType _serverType; + private bool eventFired; + + public IBConnectionTestsDialect1(IBServerType serverType) + : base(serverType) + { + IBTestsSetup.Dialect = 1; + _serverType = serverType; + } + + [Test] + [TestCase(1)] + [TestCase(3)] + public void DialectScaleback(int dialect) + { + IBConnectionStringBuilder builder = IBTestsBase.BuildConnectionStringBuilder(_serverType); + builder.Dialect = dialect; + builder.Charset = "none"; + var cs = builder.ToString(); + using (var connection = new IBConnection(cs)) + { + connection.Open(); + using (var cmd = connection.CreateCommand()) + { + cmd.CommandText = "select cast(int_field as numeric(10,2)) from test"; + Assert.DoesNotThrow(() => cmd.Prepare()); + } + } + } + + + [Test] + public void DialectScalebackEvent() + { + IBConnectionStringBuilder builder = IBTestsBase.BuildConnectionStringBuilder(_serverType); + builder.Dialect = 3; + builder.Charset = "none"; + var cs = builder.ToString(); + using (var connection = new IBConnection(cs)) + { + eventFired = false; + connection.DialectDowngradeWarning += Connection_DialectDowngradeWarning; + connection.Open(); + Assert.AreEqual(true, eventFired); + } + + } + + private void Connection_DialectDowngradeWarning(object sender, int dbDialect) + { + eventFired = true; + } + } } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBDataAdapterTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBDataAdapterTests.cs index 900052e..875774a 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBDataAdapterTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBDataAdapterTests.cs @@ -701,4 +701,13 @@ public void SubsequentDeletes() #endregion } + public class IBDataAdapterTestsDialect1 : IBCommandTests + { + public IBDataAdapterTestsDialect1(IBServerType serverType) + : base(serverType) + { + IBTestsSetup.Dialect = 1; + } + + } } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBDataReaderTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBDataReaderTests.cs index a745c7c..a0a028a 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBDataReaderTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBDataReaderTests.cs @@ -299,7 +299,7 @@ public void TruncateCharTest() } [Test] - public void ValidateDecimalSchema() + public virtual void ValidateDecimalSchema() { var sql = "select decimal_field from test"; @@ -335,7 +335,7 @@ public void DisposeTest() } [Test] - public void GetOrdinalTest() + public virtual void GetOrdinalTest() { var transaction = Connection.BeginTransaction(); @@ -526,7 +526,62 @@ public void DNET749_CommandBehaviorCloseConnectionStackOverflow() } } } - #endregion } + public class IBDataReaderTestsDialect1 : IBDataReaderTests + { + public IBDataReaderTestsDialect1(IBServerType serverType) + : base(serverType) + { + IBTestsSetup.Dialect = 1; + } + + [Test] + public override void GetOrdinalTest() + { + var transaction = Connection.BeginTransaction(); + + var command = new IBCommand("select 0 as fOo, 0 as BAR from rdb$database", Connection, transaction); + + IDataReader reader = command.ExecuteReader(); + while (reader.Read()) + { + var foo = reader.GetOrdinal("foo"); + var FOO = reader.GetOrdinal("FOO"); + var fOo = reader.GetOrdinal("fOo"); + Assert.AreEqual(0, foo); + Assert.AreEqual(0, FOO); + Assert.AreEqual(0, fOo); + + var bar = reader.GetOrdinal("bar"); + var BaR = reader.GetOrdinal("BaR"); + var BAR = reader.GetOrdinal("BAR"); + Assert.AreEqual(1, bar); + Assert.AreEqual(1, BaR); + Assert.AreEqual(1, BAR); + } + + reader.Close(); + transaction.Rollback(); + command.Dispose(); + } + + [Test] + public override void ValidateDecimalSchema() + { + var sql = "select decimal_field from test"; + + var test = new IBCommand(sql, Connection); + var r = test.ExecuteReader(CommandBehavior.SchemaOnly); + + var schema = r.GetSchemaTable(); + + r.Close(); + + // Check schema values + Assert.AreEqual(schema.Rows[0]["ColumnSize"], 8, "Invalid length"); + Assert.AreEqual(schema.Rows[0]["NumericPrecision"], 8, "Invalid precision"); + Assert.AreEqual(schema.Rows[0]["NumericScale"], 2, "Invalid scale"); + } + } } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBDatabaseInfoTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBDatabaseInfoTests.cs index bf09b3b..cd7c2c3 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBDatabaseInfoTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBDatabaseInfoTests.cs @@ -50,6 +50,24 @@ public void DatabaseInfoTest() } } + [Test] + public void DBSQLDialect() + { + var dbInfo = new IBDatabaseInfo(Connection); + Assert.AreEqual(IBTestsSetup.Dialect, dbInfo.DBSQLDialect); + } + #endregion } + + public class IBDatabaseInfoTestsDialect1 : IBDatabaseInfoTests + { + public IBDatabaseInfoTestsDialect1(IBServerType serverType) + : base(serverType) + { + IBTestsSetup.Dialect = 1; + } + + } + } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBDatabaseSchemaTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBDatabaseSchemaTests.cs index 2d91bd0..03bfc29 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBDatabaseSchemaTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBDatabaseSchemaTests.cs @@ -243,4 +243,12 @@ public void ViewPrivileges() #endregion } + public class IBDatabaseSchemaTestsDialect1 : IBDatabaseSchemaTests + { + public IBDatabaseSchemaTestsDialect1(IBServerType serverType) + : base(serverType) + { + IBTestsSetup.Dialect = 1; + } + } } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBEventTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBEventTests.cs index 8ff907f..8678289 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBEventTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBEventTests.cs @@ -32,4 +32,13 @@ public void RegisterEvents() } + public class IBEventTestsDialect1 : IBEventTests + { + public IBEventTestsDialect1(IBServerType serverType) + : base(serverType) + { + IBTestsSetup.Dialect = 1; + } + } + } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBImplicitTransactionTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBImplicitTransactionTests.cs index 8cbdc8e..abbb0ce 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBImplicitTransactionTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBImplicitTransactionTests.cs @@ -123,4 +123,14 @@ public void UpdatedArrayFieldTest() #endregion } + + public class IBImplicitTransactionTestsDialect1 : IBImplicitTransactionTests + { + public IBImplicitTransactionTestsDialect1(IBServerType serverType) + : base(serverType) + { + IBTestsSetup.Dialect = 1; + } + } + } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBParameterCollectionTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBParameterCollectionTests.cs index ace7e24..f6847aa 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBParameterCollectionTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBParameterCollectionTests.cs @@ -129,4 +129,7 @@ public void DNET635_ResetsParentOnClear() Assert.IsNull(parameter.Parent); } } + +// Note this does not need a Dialect 1 vwesion of the tests as no DB is involved. + } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBParameterTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBParameterTests.cs index ef29761..a9aa184 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBParameterTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBParameterTests.cs @@ -109,4 +109,15 @@ public void FbDbTypeFromDBNullAsValueTest() #endregion } + + public class IBParameterTestsDialect1 : IBParameterTests + { + public IBParameterTestsDialect1(IBServerType serverType) + : base(serverType) + { + IBTestsSetup.Dialect = 1; + } + } + + } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBSchemaTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBSchemaTests.cs index ffd1b54..d44226f 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBSchemaTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBSchemaTests.cs @@ -244,4 +244,12 @@ public void ViewPrivileges() #endregion } + public class IBSchemaTestsDialect1 : IBSchemaTests + { + public IBSchemaTestsDialect1(IBServerType serverType) + : base(serverType) + { + IBTestsSetup.Dialect = 1; + } + } } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBServicesTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBServicesTests.cs index 001e194..ccb07d4 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBServicesTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBServicesTests.cs @@ -256,4 +256,13 @@ static void ServiceOutput(object sender, ServiceOutputEventArgs e) #endregion } + + public class IBServicesTestsDialect1 : IBServicesTests + { + public IBServicesTestsDialect1(IBServerType serverType) + : base(serverType) + { + IBTestsSetup.Dialect = 1; + } + } } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBStoredProcCallsTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBStoredProcCallsTests.cs index 17eb4ac..ddb0b4c 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBStoredProcCallsTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBStoredProcCallsTests.cs @@ -144,4 +144,13 @@ public void SqlServerLikeTest02() #endregion } + public class IBStoredProcCallsTestsDialect1 : IBStoredProcCallsTests + { + public IBStoredProcCallsTestsDialect1(IBServerType serverType) + : base(serverType) + { + IBTestsSetup.Dialect = 1; + } + } + } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBTransactionTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBTransactionTests.cs index dd6f63a..21e664a 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBTransactionTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/IBTransactionTests.cs @@ -111,4 +111,12 @@ public void AbortTransaction() #endregion } + public class IBTransactionTestsDialect1 : IBTransactionTests + { + public IBTransactionTestsDialect1(IBServerType serverType) + : base(serverType) + { + IBTestsSetup.Dialect = 1; + } + } } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/TrackerIssuesTests.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/TrackerIssuesTests.cs index 2f765a2..0b9e1f8 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/TrackerIssuesTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient.Tests/TrackerIssuesTests.cs @@ -256,4 +256,12 @@ private static void GetSomething(string connectionString) #endregion } + public class TrackerIssuesTestsDialect1 : TrackerIssuesTests + { + public TrackerIssuesTestsDialect1(IBServerType serverType) + : base(serverType) + { + IBTestsSetup.Dialect = 1; + } + } } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Changelog.md b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Changelog.md index 5dc59e0..e2f6066 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Changelog.md +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Changelog.md @@ -1,3 +1,8 @@ +# Changes for 7.13.6 + +## Embarcadero.Data.InterBaseClient.csproj +^ Removed the NUint reuirement that was accidentally added in 7.12,1 + # Changes for 7.12.1 * Added net60 target for the assembly diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Client/Native/Changelog.md b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Client/Native/Changelog.md index ea619fd..e5270ab 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Client/Native/Changelog.md +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Client/Native/Changelog.md @@ -1,3 +1,8 @@ +# Changes for 7.13.6 + +## IBArray.cs +^ Added support for sql_double + # Changes for 7.12.1 ## IBServiceManager.cs diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Client/Native/IBArray.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Client/Native/IBArray.cs index e0e5952..9d99220 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Client/Native/IBArray.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Client/Native/IBArray.cs @@ -300,7 +300,9 @@ protected override Array DecodeSlice(byte[] slice) case IscCodes.SQL_LONG: evalue = BitConverter.ToInt32(slice, slicePosition); break; - + case IscCodes.SQL_DOUBLE: + evalue = BitConverter.ToDouble(slice, slicePosition); + break; case IscCodes.SQL_QUAD: case IscCodes.SQL_INT64: evalue = BitConverter.ToInt64(slice, slicePosition); @@ -465,7 +467,9 @@ private byte[] EncodeSlice(ArrayDesc desc, Array sourceArray, int length) case IscCodes.SQL_LONG: writer.Write((int)numeric); break; - + case IscCodes.SQL_DOUBLE: + writer.Write(Decimal.ToDouble((decimal) numeric)); + break; case IscCodes.SQL_QUAD: case IscCodes.SQL_INT64: writer.Write((long)numeric); diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Client/Native/IIBClient.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Client/Native/IIBClient.cs index ddf0e16..f443f2c 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Client/Native/IIBClient.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Client/Native/IIBClient.cs @@ -500,7 +500,7 @@ int isc_event_block( ref IntPtr event_buffer, ref IntPtr result_buffer, ushort id_count, - byte[][] event_list); + byte[][] event_list); void isc_event_counts( [In, Out] uint[] status, diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Common/Changelog.md b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Common/Changelog.md index 3c1643e..86bdd5f 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Common/Changelog.md +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Common/Changelog.md @@ -1,3 +1,11 @@ +# Changes for 7.13.6 + +## IscHelper.cs +^ Added support for IscCodes.isc_info_db_sql_dialect + +## TypeHelper.cs +^ Changed BigInt to Numeric(18,0) + # Changes for 7.12.1 ## ConnectionString diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Common/ConnectionString.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Common/ConnectionString.cs index 25fc4c8..78b233c 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Common/ConnectionString.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Common/ConnectionString.cs @@ -312,7 +312,7 @@ public string ComposeDatabase() public void Validate() { - if ((string.IsNullOrEmpty(Database)) || + if ((string.IsNullOrEmpty(Database)) || (string.IsNullOrEmpty(DataSource)) || (string.IsNullOrEmpty(Charset)) || (Port <= 0) || diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Common/IscHelper.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Common/IscHelper.cs index 33870ff..6cb6285 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Common/IscHelper.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Common/IscHelper.cs @@ -147,6 +147,10 @@ public static List ParseDatabaseInfo(byte[] buffer) info.Add(VaxInteger(buffer, pos, length)); break; + case IscCodes.isc_info_db_sql_dialect: + info.Add(VaxInteger(buffer, pos, length)); + break; + case IscCodes.isc_info_page_size: /* Number of bytes per page of the attached database; use with * isc_info_allocation to determine the size of the database diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Common/TypeHelper.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Common/TypeHelper.cs index a3c69b8..fc171db 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Common/TypeHelper.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Common/TypeHelper.cs @@ -300,7 +300,7 @@ public static string GetDataTypeName(DbDataType type) return "DOUBLE PRECISION"; case DbDataType.BigInt: - return "BIGINT"; + return "NUMERIC(18, 0)"; case DbDataType.Numeric: return "NUMERIC"; diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Embarcadero.Data.InterBaseClient.csproj b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Embarcadero.Data.InterBaseClient.csproj index 4d9b398..af3777b 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Embarcadero.Data.InterBaseClient.csproj +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/Embarcadero.Data.InterBaseClient.csproj @@ -22,9 +22,9 @@ Embarcadero Embarcadero - 7.12.1.0 - 7.12.1.0 - 7.12.1 + 7.13.6.0 + 7.13.6.0 + 7.13.6 TRACE @@ -54,8 +54,7 @@ - - + diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/IBCommand.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/IBCommand.cs index 811fce4..616bd19 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/IBCommand.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/IBCommand.cs @@ -1028,6 +1028,44 @@ private void UpdateParameterValues() #region Private Methods + private string ParameterCastFixup() + { + var sql = CommandText; + for (var i = Parameters.Count - 1; i >= 0; i--) + { + IBParameter p = Parameters[i]; + if (sql.Contains("CAST(" + p.InternalParameterName)) + { + switch (p.IBDbType) + { + case IBDbType.BigInt: + case IBDbType.Decimal: + case IBDbType.Double: + case IBDbType.Float: + case IBDbType.Integer: + case IBDbType.Numeric: + case IBDbType.SmallInt: + sql = sql.Replace(p.InternalParameterName, p.InternalValue.ToString()); + break; + case IBDbType.Boolean: + sql = sql.Replace(p.InternalParameterName, (bool)p.InternalValue ? "true" : "false"); + break; + case IBDbType.Char : + case IBDbType.VarChar: + sql = sql.Replace(p.InternalParameterName, "'" + p.InternalValue.ToString() + "'"); + break; + case IBDbType.Guid: + string gstr = ((Guid) p.InternalValue).ToString().ToUpper(); + sql = sql.Replace("CAST(" +p.InternalParameterName + " AS CHAR(16) CHARACTER SET OCTETS)", "EF_CHAR_TO_UUID('" + gstr + "')"); + break; + } + Parameters.Remove(p); + _namedParameters.Remove(p.InternalParameterName); + } + } + return sql; + } + private void Prepare(bool returnsSet) { var innerConn = _connection.InnerConnection; @@ -1078,13 +1116,34 @@ private void Prepare(bool returnsSet) // Try to prepare the command _statement.Prepare(ParseNamedParameters(sql)); } - catch + catch (InterBaseSql.Data.Common.IscException e) { - // Release the statement and rethrow the exception - _statement.Release(); - _statement = null; + // this is an Unknown type error. Interbase can not do casting of parameters so + // Lets massage the SQL to replace the parameter in the cast with the value + if (e.ErrorCode == 335544569) + { + try + { + _statement = innerConn.Database.CreateStatement(_transaction.Transaction); + _statement.Prepare(ParameterCastFixup()); + } + catch + { + // Release the statement and rethrow the exception + _statement.Release(); + _statement = null; - throw; + throw; + } + } + else + { + // Release the statement and rethrow the exception + _statement.Release(); + _statement = null; + + throw; + } } // Add this command to the active command list diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/IBConnection.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/IBConnection.cs index b2facf2..9b0c9b9 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/IBConnection.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/IBConnection.cs @@ -24,6 +24,7 @@ using System.Data.Common; using InterBaseSql.Data.Common; +using InterBaseSql.Data.Services; namespace InterBaseSql.Data.InterBaseClient { @@ -152,6 +153,11 @@ public static void DropDatabase(string connectionString) public event EventHandler InfoMessage; + public delegate void DialectDowngradeWarningHandler(object sender, int dbDialect); + + public event DialectDowngradeWarningHandler DialectDowngradeWarning; + + #endregion #region Fields @@ -161,10 +167,12 @@ public static void DropDatabase(string connectionString) private ConnectionString _options; private bool _disposed; private string _connectionString; + private short _dbSQLDialect; #endregion internal IDatabase IBDatabase => _innerConnection.Database; + public short DBSQLDialect { get { return _dbSQLDialect; } } #region Properties @@ -450,6 +458,22 @@ public override void ChangeDatabase(string db) } } + private short GetDBSQLDialect() + { + var DatabaseInfo = new IBDatabaseInfo(this); + return (short) DatabaseInfo.DBSQLDialect; + } + + void ValidateClientSQLDialect() + { + if (_dbSQLDialect < _innerConnection.Database.Dialect) + { + + _innerConnection.Database.Dialect = _dbSQLDialect; + DialectDowngradeWarning?.Invoke(this, _dbSQLDialect); + } + } + public override void Open() { if (string.IsNullOrEmpty(_connectionString)) @@ -510,6 +534,8 @@ public override void Open() // Update the connection state OnStateChange(_state, ConnectionState.Open); + _dbSQLDialect = GetDBSQLDialect(); + ValidateClientSQLDialect(); } catch (IscException ex) { diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/IBConnectionInternal.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/IBConnectionInternal.cs index 002232f..9edfbf8 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/IBConnectionInternal.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/IBConnectionInternal.cs @@ -388,7 +388,8 @@ private DatabaseParameterBuffer BuildDpb(IDatabase db, ConnectionString options) dpb.Append(IscCodes.isc_dpb_version1); dpb.Append(IscCodes.isc_dpb_dummy_packet_interval, new byte[] { 120, 10, 0, 0 }); dpb.Append(IscCodes.isc_dpb_sql_dialect, new byte[] { options.Dialect, 0, 0, 0 }); - dpb.Append(IscCodes.isc_dpb_lc_ctype, options.Charset); + if (options.Charset.ToLower() != "none") + dpb.Append(IscCodes.isc_dpb_lc_ctype, options.Charset); if (options.DbCachePages > 0) dpb.Append(IscCodes.isc_dpb_num_buffers, options.DbCachePages); if (!string.IsNullOrEmpty(options.UserID)) diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/IBDatabaseInfo.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/IBDatabaseInfo.cs index 4fada42..a7f3ddb 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/IBDatabaseInfo.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/IBDatabaseInfo.cs @@ -62,6 +62,7 @@ public sealed class IBDatabaseInfo public long ReadSeqCount => GetValue(IscCodes.isc_info_read_seq_count); public long UpdateCount => GetValue(IscCodes.isc_info_update_count); public int DatabaseSizeInPages => GetValue(IscCodes.isc_info_db_size_in_pages); + public int DBSQLDialect => GetValue(IscCodes.isc_info_db_sql_dialect); public List ActiveUsers => GetList(IscCodes.isc_info_user_names); #endregion diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/IBTransaction.cs b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/IBTransaction.cs index b2ef7e3..ab0ec94 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/IBTransaction.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/IBTransaction.cs @@ -236,9 +236,9 @@ public void RollbackRetaining() } } - #endregion +#endregion - #region Internal Methods +#region Internal Methods internal void BeginTransaction() { @@ -250,9 +250,9 @@ internal void BeginTransaction(IBTransactionOptions options) _transaction = _connection.InnerConnection.Database.BeginTransaction(BuildTpb(options)); } - #endregion +#endregion - #region Private Methods +#region Private Methods private void CompleteTransaction() { @@ -407,6 +407,6 @@ private static void EnsureSavePointName(string savePointName) } } - #endregion +#endregion } } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/changelog.md b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/changelog.md index 133177a..51a1240 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/changelog.md +++ b/NETProvider/Provider/src/InterBaseSql.Data.InterBaseClient/InterBaseClient/changelog.md @@ -1,3 +1,23 @@ +#Changes for 7.13.6 + +## IBCommand.cs +^ added code for EFCore when it puts a parameter in the where clause ir (cast ? as VarChar(20)) iB cannot handle this. + When that happens and an excetion 335544569 is raised parse te]he SQL and try to replace the ? with the actual string. + +## IBConnection.cs +^ added support for downgrading the dialect when attempting 3 but the DB is actually 1. +^ Added DialectDowngradeWarning event that fires when the Dialect is downgraded. +^ Added new read only property DBSQLDialect to get teh actual Dailect of the DB +^ Added private short GetDBSQLDialect for getting the DB Dialect +^ added void ValidateClientSQLDialect() that checks the requested dialect vs the dialect of the DB. + If the DB dialect is less set the dialect of hte connectino to it and fire the downgrade event. + +## IBConnectionInternal.cs +^ Only add the character set if not 'none'. + +## IBDatabaseInfo.cs +^ Added support for SQLDialect property + # Changes for 7.12.1 ## IBConnection.cs diff --git a/NETProvider/Provider/src/InterBaseSql.Data.TestsBase/Changelog.md b/NETProvider/Provider/src/InterBaseSql.Data.TestsBase/Changelog.md index 703ff71..fdf0c7d 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.TestsBase/Changelog.md +++ b/NETProvider/Provider/src/InterBaseSql.Data.TestsBase/Changelog.md @@ -1,3 +1,6 @@ +# Changes for 7.13.6 +^ added setup support to setup a Dialect 1 DB to test against. + # Changes for 7.12.1 ## IBTestsBase.cs diff --git a/NETProvider/Provider/src/InterBaseSql.Data.TestsBase/IBTestsBase.cs b/NETProvider/Provider/src/InterBaseSql.Data.TestsBase/IBTestsBase.cs index 037099b..abfe2f9 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.TestsBase/IBTestsBase.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.TestsBase/IBTestsBase.cs @@ -19,7 +19,6 @@ //$Authors = Carlos Guzman Alvarez, Jiri Cincura (jiri@cincura.net) using System; -using System.CodeDom; using System.Security.Cryptography; using System.Text; using InterBaseSql.Data.InterBaseClient; @@ -42,6 +41,11 @@ public abstract class IBTestsBase public IBServerType IBServerType { get; } + public static int Dialect { + get { return IBTestsSetup.Dialect; } + set { IBTestsSetup.Dialect = value; } + } + public IBConnection Connection { get { return _connection; } @@ -61,6 +65,7 @@ public IBTestsBase(IBServerType serverType, bool insertTestData = true) { IBServerType = serverType; _insertTestData = insertTestData; + IBTestsSetup.Dialect = 3; } #endregion @@ -114,7 +119,10 @@ insert into test (int_field, char_field, varchar_field, bigint_field, smallint_f command.Parameters.Add("@int_field", IBDbType.Integer); command.Parameters.Add("@char_field", IBDbType.Char); command.Parameters.Add("@varchar_field", IBDbType.VarChar); - command.Parameters.Add("@bigint_field", IBDbType.BigInt); + if (Dialect == 3) + command.Parameters.Add("@bigint_field", IBDbType.BigInt); + else + command.Parameters.Add("@bigint_field", IBDbType.Numeric); command.Parameters.Add("@smallint_field", IBDbType.SmallInt); command.Parameters.Add("@float_field", IBDbType.Double); command.Parameters.Add("@double_field", IBDbType.Double); @@ -294,6 +302,7 @@ public static IBConnectionStringBuilder BuildConnectionStringBuilder(IBServerTyp builder.Charset = IBTestsSetup.Charset; builder.Pooling = IBTestsSetup.Pooling; builder.ServerType = serverType; + builder.Dialect = IBTestsSetup.Dialect; return builder; } @@ -351,6 +360,6 @@ protected static int GetId() return BitConverter.ToInt32(buffer, 0); } - #endregion +#endregion } } diff --git a/NETProvider/Provider/src/InterBaseSql.Data.TestsBase/IBTestsSetup.cs b/NETProvider/Provider/src/InterBaseSql.Data.TestsBase/IBTestsSetup.cs index bf06ec9..35d9e54 100644 --- a/NETProvider/Provider/src/InterBaseSql.Data.TestsBase/IBTestsSetup.cs +++ b/NETProvider/Provider/src/InterBaseSql.Data.TestsBase/IBTestsSetup.cs @@ -26,6 +26,7 @@ using NUnit.Framework; using System.Reflection; using InterBaseSql.Data.Isql; +using InterBaseSql.Data.Services; [SetUpFixture] public class IBTestsSetup @@ -40,11 +41,13 @@ public class IBTestsSetup internal const int PageSize = 4096; internal const bool ForcedWrite = false; - static HashSet> _initalized = new HashSet>(); + public static int Dialect {get; set;} + + static HashSet> _initalized = new HashSet>(); public static void SetUp(IBServerType serverType) { - var item = Tuple.Create(serverType); + var item = Tuple.Create(serverType, Dialect); if (!_initalized.Contains(item)) { var cs = IBTestsBase.BuildConnectionString(serverType); @@ -106,9 +109,11 @@ private static void CreateDomains(string connectionString) public static string Database(IBServerType serverType) { -// var path = System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); var path = AppDomain.CurrentDomain.BaseDirectory; - return $"{path}{DatabaseBase}_{serverType}.ib"; + if (IBTestsSetup.Dialect == 1) + return $"{path}{DatabaseBase}_{serverType}_D1.ib"; + else + return $"{path}{DatabaseBase}_{serverType}.ib"; } [OneTimeTearDown] @@ -328,8 +333,16 @@ private static void CreateTables(string connectionString) commandText.Append("FLOAT_FIELD FLOAT,"); commandText.Append("NUMERIC_FIELD NUMERIC(15,2),"); commandText.Append("DECIMAL_FIELD DECIMAL(15,2),"); - commandText.Append("DATE_FIELD DATE,"); - commandText.Append("TIME_FIELD TIME,"); + if (Dialect == 3) + { + commandText.Append("DATE_FIELD DATE,"); + commandText.Append("TIME_FIELD TIME,"); + } + else + { + commandText.Append("DATE_FIELD TIMESTAMP,"); + commandText.Append("TIME_FIELD TIMESTAMP,"); + } commandText.Append("TIMESTAMP_FIELD TIMESTAMP,"); commandText.Append("CLOB_FIELD BLOB SUB_TYPE 1 SEGMENT SIZE 80,"); commandText.Append("BLOB_FIELD BLOB SUB_TYPE 0 SEGMENT SIZE 80,"); @@ -339,8 +352,16 @@ private static void CreateTables(string connectionString) commandText.Append("FARRAY_FIELD FLOAT [1:4],"); commandText.Append("BARRAY_FIELD DOUBLE PRECISION [1:4],"); commandText.Append("NARRAY_FIELD NUMERIC(10,6) [1:4],"); - commandText.Append("DARRAY_FIELD DATE [1:4],"); - commandText.Append("TARRAY_FIELD TIME [1:4],"); + if (Dialect == 3) + { + commandText.Append("DARRAY_FIELD DATE [1:4],"); + commandText.Append("TARRAY_FIELD TIME [1:4],"); + } + else + { + commandText.Append("DARRAY_FIELD TIMESTAMP [1:4],"); + commandText.Append("TARRAY_FIELD TIMESTAMP [1:4],"); + } commandText.Append("TSARRAY_FIELD TIMESTAMP [1:4],"); commandText.Append("CARRAY_FIELD CHAR(21) [1:4],"); commandText.Append("VARRAY_FIELD VARCHAR(30) [1:4],"); @@ -566,7 +587,9 @@ private static void CreateProcedures(string connectionString) using (var command = new IBCommand("", connection)) { - command.CommandText = @" + if (Dialect == 3) + { + command.CommandText = @" CREATE PROCEDURE TEST_SP ( P01 SMALLINT, P02 INTEGER, P03 INTEGER, P04 FLOAT, P05 INTEGER, P06 INTEGER, P07 DATE, P08 DATE ) RETURNS ( R01 FLOAT, R02 FLOAT, R03 FLOAT, R04 FLOAT, R05 FLOAT, R06 FLOAT, R07 FLOAT, R08 FLOAT, R09 FLOAT, R10 FLOAT, @@ -582,6 +605,26 @@ CREATE PROCEDURE TEST_SP ( SUSPEND; END "; + } + else + { + command.CommandText = @" +CREATE PROCEDURE TEST_SP ( + P01 SMALLINT, P02 INTEGER, P03 INTEGER, P04 FLOAT, P05 INTEGER, P06 INTEGER, P07 TIMESTAMP, P08 TIMESTAMP ) +RETURNS ( R01 FLOAT, R02 FLOAT, R03 FLOAT, R04 FLOAT, R05 FLOAT, R06 FLOAT, R07 FLOAT, R08 FLOAT, R09 FLOAT, R10 FLOAT, + R11 FLOAT, R12 FLOAT, R13 FLOAT, R14 FLOAT, R15 FLOAT, R16 FLOAT, R17 FLOAT, R18 FLOAT, R19 FLOAT, R20 FLOAT, R21 FLOAT, + R22 FLOAT, R23 FLOAT, R24 FLOAT, R25 FLOAT, R26 FLOAT, R27 FLOAT, R28 FLOAT, R29 FLOAT, R30 FLOAT, R31 FLOAT, R32 FLOAT, + R33 FLOAT, R34 FLOAT, R35 FLOAT, R36 FLOAT, R37 FLOAT, R38 FLOAT, R39 FLOAT, R40 FLOAT, R41 FLOAT, R42 FLOAT, R43 FLOAT, + R44 FLOAT, R45 FLOAT, R46 FLOAT, R47 FLOAT, R48 FLOAT, R49 FLOAT, R50 FLOAT, R51 FLOAT, R52 FLOAT, R53 FLOAT, R54 FLOAT, + R55 FLOAT, R56 FLOAT, R57 FLOAT, R58 FLOAT, R59 FLOAT, R60 FLOAT, R61 FLOAT, R62 FLOAT, R63 FLOAT, R64 FLOAT, R65 FLOAT, + R66 FLOAT, R67 FLOAT, R68 FLOAT, R69 FLOAT, R70 FLOAT, R71 FLOAT, R72 FLOAT, R73 FLOAT, R74 FLOAT, R75 FLOAT, R76 FLOAT, + R77 FLOAT, R78 FLOAT, R79 FLOAT, R80 FLOAT, R81 FLOAT, R82 FLOAT, R83 FLOAT, R84 FLOAT, R85 FLOAT, R86 FLOAT, R87 FLOAT, + R88 FLOAT, R89 FLOAT, R90 FLOAT, R91 FLOAT, R92 FLOAT, R93 FLOAT, R94 FLOAT, R95 FLOAT ) AS +BEGIN + SUSPEND; +END +"; + } command.ExecuteNonQuery(); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Changelog.md index e8695eb..4447147 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Changelog.md +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Changelog.md @@ -1,4 +1,8 @@ -#Changes for 7.12.1 +# Changes for 7.13.6 (updated for EFCore 6.0 and to Fb 9.x) + +## removed MigrationsIBFixture.cs + +# Changes for 7.12.1 ## IBTestStore.cs * Added the path to the DB name to place the DB in the same directory as the running test. diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Changelog.txt b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Changelog.txt deleted file mode 100644 index 3eb4245..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Changelog.txt +++ /dev/null @@ -1,13 +0,0 @@ -Changes for 7.10.2 - - General - - All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. - - Common - Namespaces changed from FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests to InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests - Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. - - All files renamed from FbXxxxx to IBXxxxx with the internal class matching that same change. - For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup - - using FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests.TestUtilities now using InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.TestUtilities \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Helpers/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Helpers/Changelog.md new file mode 100644 index 0000000..f43740e --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Helpers/Changelog.md @@ -0,0 +1,21 @@ +#Changes for 7.13.6 (updated for EFCore 6.0 and to Fb 9.x) + +# Changes for 7.10.2 + +## General - +* All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. + +## Common +* Namespaces changed from EntityFramework.Firebird.FunctionalTests.Helpers to EntityFramework.InterBase.FunctionalTests.Helpers +* Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. + +* All files renamed from FbXxxxx to IBXxxxx with the internal class matching that same change. +* For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup + +* using FirebirdSql.EntityFrameworkCore.Firebird.Metadata now using InterBaseSql.EntityFrameworkCore.InterBase.Metadata + +## SkippingAttributes.cs +* "Firebird" string replaced with "InterBase" +* NotSupportedOnFirebirdFactAttribute now NotSupportedOnInterBaseFactAttribute +* NotSupportedOnFirebirdTheoryAttribute now NotSupportedOnInterBaseTheoryAttribute + diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Helpers/Changelog.txt b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Helpers/Changelog.txt deleted file mode 100644 index 34d4b4c..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Helpers/Changelog.txt +++ /dev/null @@ -1,19 +0,0 @@ -Changes for 7.10.2 - - General - - All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. - - Common - Namespaces changed from EntityFramework.Firebird.FunctionalTests.Helpers to EntityFramework.InterBase.FunctionalTests.Helpers - Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. - - All files renamed from FbXxxxx to IBXxxxx with the internal class matching that same change. - For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup - - using FirebirdSql.EntityFrameworkCore.Firebird.Metadata now using InterBaseSql.EntityFrameworkCore.InterBase.Metadata - - SkippingAttributes.cs - "Firebird" string replaced with "InterBase" - NotSupportedOnFirebirdFactAttribute now NotSupportedOnInterBaseFactAttribute - NotSupportedOnFirebirdTheoryAttribute now NotSupportedOnInterBaseTheoryAttribute - \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Helpers/ModelHelpers.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Helpers/ModelHelpers.cs index 90105d9..7e4f93e 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Helpers/ModelHelpers.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Helpers/ModelHelpers.cs @@ -23,58 +23,59 @@ using System.Linq; using InterBaseSql.EntityFrameworkCore.InterBase.Metadata; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Helpers +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Helpers; + +public static class ModelHelpers { - public static class ModelHelpers + public static void SetStringLengths(ModelBuilder modelBuilder) { - public static void SetStringLengths(ModelBuilder modelBuilder) + foreach (var entityType in modelBuilder.Model.GetEntityTypes()) { - foreach (var entityType in modelBuilder.Model.GetEntityTypes()) + foreach (var property in entityType.GetProperties()) { - foreach (var property in entityType.GetProperties()) + if (property.ClrType == typeof(string) && property.GetMaxLength() == null) { - if (property.ClrType == typeof(string) && property.GetMaxLength() == null) - { - property.SetMaxLength(500); - } + property.SetMaxLength(500); } } } + } - public static void SimpleTableNames(ModelBuilder modelBuilder) + public static void SimpleTableNames(ModelBuilder modelBuilder) + { + var names = new HashSet(StringComparer.InvariantCulture); + foreach (var entityType in modelBuilder.Model.GetEntityTypes()) { - var names = new HashSet(StringComparer.InvariantCulture); - foreach (var entityType in modelBuilder.Model.GetEntityTypes()) + if (entityType.BaseType != null) + continue; + var name = new string(entityType.GetTableName().Where(char.IsUpper).ToArray()); + var cnt = 1; + while (names.Contains(name)) { - if (entityType.BaseType != null) - continue; - var name = new string(entityType.GetTableName().Where(char.IsUpper).ToArray()); - var cnt = 1; - while (names.Contains(name)) - { - name += cnt++; - } - names.Add(name); - entityType.SetTableName(name); + name += cnt++; } + names.Add(name); + entityType.SetTableName(name); } + } - public static void SetPrimaryKeyGeneration(ModelBuilder modelBuilder, IBValueGenerationStrategy valueGenerationStrategy = IBValueGenerationStrategy.SequenceTrigger) + public static void SetPrimaryKeyGeneration(ModelBuilder modelBuilder, IBValueGenerationStrategy valueGenerationStrategy = IBValueGenerationStrategy.SequenceTrigger, Func filter = null) + { + filter ??= _ => true; + foreach (var entityType in modelBuilder.Model.GetEntityTypes().Where(filter)) { - foreach (var entityType in modelBuilder.Model.GetEntityTypes()) + var pk = entityType.FindPrimaryKey(); + if (pk == null) + continue; + var properties = pk.Properties; + if (properties.Count() != 1) + continue; + var property = properties[0]; + if (property.GetValueGenerationStrategy() == IBValueGenerationStrategy.None) { - var pk = entityType.FindPrimaryKey(); - if (pk == null) - continue; - var properties = pk.Properties; - if (properties.Count() != 1) - continue; - var property = properties[0]; - if (property.GetValueGenerationStrategy() == IBValueGenerationStrategy.None) - { - property.SetValueGenerationStrategy(valueGenerationStrategy); - } + property.SetValueGenerationStrategy(valueGenerationStrategy); } } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Helpers/SkippingAttributes.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Helpers/SkippingAttributes.cs index 92065b0..6a09bd3 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Helpers/SkippingAttributes.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Helpers/SkippingAttributes.cs @@ -20,66 +20,78 @@ using Xunit; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Helpers +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Helpers; + +public class HasDataInTheSameTransactionAsDDLFactAttribute : FactAttribute { - public class HasDataInTheSameTransactionAsDDLFactAttribute : FactAttribute + public HasDataInTheSameTransactionAsDDLFactAttribute() { - public HasDataInTheSameTransactionAsDDLFactAttribute() - { - Skip = "HasData is called in the same transaction as DDL commands."; - } + Skip = "HasData is called in the same transaction as DDL commands."; } - public class HasDataInTheSameTransactionAsDDLTheoryAttribute : TheoryAttribute +} +public class HasDataInTheSameTransactionAsDDLTheoryAttribute : TheoryAttribute +{ + public HasDataInTheSameTransactionAsDDLTheoryAttribute() { - public HasDataInTheSameTransactionAsDDLTheoryAttribute() - { - Skip = "HasData is called in the same transaction as DDL commands."; - } + Skip = "HasData is called in the same transaction as DDL commands."; } +} -#warning Can I somehow handle it in SQL generation? - public class GeneratedNameTooLongFactAttribute : FactAttribute +public class GeneratedNameTooLongFactAttribute : FactAttribute +{ + public GeneratedNameTooLongFactAttribute() { - public GeneratedNameTooLongFactAttribute() - { - Skip = "Generated name in the query is too long."; - } + Skip = "Generated name in the query is too long."; } - public class GeneratedNameTooLongTheoryAttribute : TheoryAttribute +} +public class GeneratedNameTooLongTheoryAttribute : TheoryAttribute +{ + public GeneratedNameTooLongTheoryAttribute() { - public GeneratedNameTooLongTheoryAttribute() - { - Skip = "Generated name in the query is too long."; - } + Skip = "Generated name in the query is too long."; } +} - public class NotSupportedOnInterBaseFactAttribute : FactAttribute +public class NotSupportedOnInterBaseFactAttribute : FactAttribute +{ + public NotSupportedOnInterBaseFactAttribute() { - public NotSupportedOnInterBaseFactAttribute() - { - Skip = "Not supported on InterBase."; - } + Skip = "Not supported on InterBase."; } - public class NotSupportedOnInterBaseTheoryAttribute : TheoryAttribute +} +public class NotSupportedOnInterBaseTheoryAttribute : TheoryAttribute +{ + public NotSupportedOnInterBaseTheoryAttribute() { - public NotSupportedOnInterBaseTheoryAttribute() - { - Skip = "Not supported on InterBase."; - } + Skip = "Not supported on InterBase."; } +} - public class DoesNotHaveTheDataFactAttribute : FactAttribute +public class DoesNotHaveTheDataFactAttribute : FactAttribute +{ + public DoesNotHaveTheDataFactAttribute() { - public DoesNotHaveTheDataFactAttribute() - { - Skip = "Does not have the data."; - } + Skip = "Does not have the data."; } - public class DoesNotHaveTheDataTheoryAttribute : TheoryAttribute +} +public class DoesNotHaveTheDataTheoryAttribute : TheoryAttribute +{ + public DoesNotHaveTheDataTheoryAttribute() { - public DoesNotHaveTheDataTheoryAttribute() - { - Skip = "Does not have the data."; - } + Skip = "Does not have the data."; } } +public class LongExecutionFactAttribute : FactAttribute +{ + public LongExecutionFactAttribute() + { + Skip = "Long execution."; + } +} +public class LongExecutionTheoryAttribute : TheoryAttribute +{ + public LongExecutionTheoryAttribute() + { + Skip = "Long execution."; + } +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.csproj b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.csproj index 7e3d088..0410fb8 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.csproj +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.csproj @@ -1,6 +1,6 @@  - netcoreapp3.1 + net6.0 false false true @@ -11,10 +11,10 @@ Ib.png - - - - + + + + diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/MigrationsIBFixture.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/MigrationsIBFixture.cs deleted file mode 100644 index 769ed07..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/MigrationsIBFixture.cs +++ /dev/null @@ -1,31 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.TestUtilities; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.TestUtilities; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests -{ - public class MigrationsIBFixture : MigrationsFixtureBase - { - protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/MigrationsIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/MigrationsIBTest.cs index 50838b1..c9e5333 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/MigrationsIBTest.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/MigrationsIBTest.cs @@ -18,51 +18,299 @@ //$Authors = Jiri Cincura (jiri@cincura.net) -using System; using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; +using InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.TestUtilities; +using InterBaseSql.EntityFrameworkCore.InterBase.Scaffolding.Internal; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Scaffolding; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests; + +public class MigrationsIBTest : MigrationsTestBase { - public class MigrationsIBTest : MigrationsTestBase + const string SkipReason = "Assumptions in model differ too much between base tests and InterBase."; + + public MigrationsIBTest(MigrationsIBFixture fixture) + : base(fixture) + { } + + + protected override string NonDefaultCollation => "WIN1250"; + + [Fact(Skip = SkipReason)] + public override Task Create_table() => base.Create_table(); + + [Fact(Skip = SkipReason)] + public override Task Create_table_all_settings() => base.Create_table_all_settings(); + + [Fact(Skip = SkipReason)] + public override Task Create_table_no_key() => base.Create_table_no_key(); + + [Fact(Skip = SkipReason)] + public override Task Create_table_with_comments() => base.Create_table_with_comments(); + + [Fact(Skip = SkipReason)] + public override Task Create_table_with_multiline_comments() => base.Create_table_with_multiline_comments(); + + [Theory(Skip = SkipReason)] + [InlineData(true)] + [InlineData(false)] + [InlineData(null)] + public override Task Create_table_with_computed_column(bool? stored) => base.Create_table_with_computed_column(stored); + + [Fact(Skip = SkipReason)] + public override Task Alter_table_add_comment() => base.Alter_table_add_comment(); + + [Fact(Skip = SkipReason)] + public override Task Alter_table_add_comment_non_default_schema() => base.Alter_table_add_comment_non_default_schema(); + + [Fact(Skip = SkipReason)] + public override Task Alter_table_change_comment() => base.Alter_table_change_comment(); + + [Fact(Skip = SkipReason)] + public override Task Alter_table_remove_comment() => base.Alter_table_remove_comment(); + + [Fact(Skip = SkipReason)] + public override Task Drop_table() => base.Drop_table(); + + [Fact(Skip = SkipReason)] + public override Task Rename_table() => base.Rename_table(); + + [Fact(Skip = SkipReason)] + public override Task Rename_table_with_primary_key() => base.Rename_table_with_primary_key(); + + [Fact(Skip = SkipReason)] + public override Task Move_table() => base.Move_table(); + + [Fact(Skip = SkipReason)] + public override Task Create_schema() => base.Create_schema(); + + [Fact(Skip = SkipReason)] + public override Task Add_column_with_defaultValue_string() => base.Add_column_with_defaultValue_string(); + + [Fact(Skip = SkipReason)] + public override Task Add_column_with_defaultValue_datetime() => base.Add_column_with_defaultValue_datetime(); + + [Fact(Skip = SkipReason)] + public override Task Add_column_with_defaultValueSql() => base.Add_column_with_defaultValueSql(); + + [Fact(Skip = SkipReason)] + public override Task Add_column_with_defaultValueSql_unspecified() => base.Add_column_with_defaultValueSql_unspecified(); + + [Fact(Skip = SkipReason)] + public override Task Add_column_with_defaultValue_unspecified() => base.Add_column_with_defaultValue_unspecified(); + + [Theory(Skip = SkipReason)] + [InlineData(true)] + [InlineData(false)] + [InlineData(null)] + public override Task Add_column_with_computedSql(bool? stored) => base.Add_column_with_computedSql(stored); + + [Fact(Skip = SkipReason)] + public override Task Add_column_with_computedSql_unspecified() => base.Add_column_with_computedSql_unspecified(); + + [Fact(Skip = SkipReason)] + public override Task Add_column_with_required() => base.Add_column_with_required(); + + [Fact(Skip = SkipReason)] + public override Task Add_column_with_ansi() => base.Add_column_with_ansi(); + + [Fact(Skip = SkipReason)] + public override Task Add_column_with_max_length() => base.Add_column_with_max_length(); + + [Fact(Skip = SkipReason)] + public override Task Add_column_with_max_length_on_derived() => base.Add_column_with_max_length_on_derived(); + + [Fact(Skip = SkipReason)] + public override Task Add_column_with_fixed_length() => base.Add_column_with_fixed_length(); + + [Fact(Skip = SkipReason)] + public override Task Add_column_with_comment() => base.Add_column_with_comment(); + + [Fact(Skip = SkipReason)] + public override Task Add_column_with_collation() => base.Add_column_with_collation(); + + [Fact(Skip = SkipReason)] + public override Task Add_column_computed_with_collation() => base.Add_column_computed_with_collation(); + + [Fact(Skip = SkipReason)] + public override Task Add_column_shared() => base.Add_column_shared(); + + [Fact(Skip = SkipReason)] + public override Task Add_column_with_check_constraint() => base.Add_column_with_check_constraint(); + + [Fact(Skip = SkipReason)] + public override Task Alter_column_change_type() => base.Alter_column_change_type(); + + [Fact(Skip = SkipReason)] + public override Task Alter_column_make_required() => base.Alter_column_make_required(); + + [Fact(Skip = SkipReason)] + public override Task Alter_column_make_required_with_index() => base.Alter_column_make_required_with_index(); + + [Fact(Skip = SkipReason)] + public override Task Alter_column_make_required_with_composite_index() => base.Alter_column_make_required_with_composite_index(); + + [Theory(Skip = SkipReason)] + [InlineData(true)] + [InlineData(false)] + [InlineData(null)] + public override Task Alter_column_make_computed(bool? stored) => base.Alter_column_make_computed(stored); + + [Fact(Skip = SkipReason)] + public override Task Alter_column_change_computed() => base.Alter_column_change_computed(); + + [Fact(Skip = SkipReason)] + public override Task Alter_column_change_computed_type() => base.Alter_column_change_computed_type(); + + [Fact(Skip = SkipReason)] + public override Task Alter_column_add_comment() => base.Alter_column_add_comment(); + + [Fact(Skip = SkipReason)] + public override Task Alter_column_change_comment() => base.Alter_column_change_comment(); + + [Fact(Skip = SkipReason)] + public override Task Alter_column_remove_comment() => base.Alter_column_remove_comment(); + + [Fact(Skip = SkipReason)] + public override Task Alter_column_set_collation() => base.Alter_column_set_collation(); + + [Fact(Skip = SkipReason)] + public override Task Alter_column_reset_collation() => base.Alter_column_reset_collation(); + + [Fact(Skip = SkipReason)] + public override Task Drop_column() => base.Drop_column(); + + [Fact(Skip = SkipReason)] + public override Task Drop_column_primary_key() => base.Drop_column_primary_key(); + + [Fact(Skip = SkipReason)] + public override Task Rename_column() => base.Rename_column(); + + [Fact(Skip = SkipReason)] + public override Task Create_index() => base.Create_index(); + + [Fact(Skip = SkipReason)] + public override Task Create_index_unique() => base.Create_index_unique(); + + [Fact(Skip = SkipReason)] + public override Task Create_index_with_filter() => base.Create_index_with_filter(); + + [Fact(Skip = SkipReason)] + public override Task Create_unique_index_with_filter() => base.Create_unique_index_with_filter(); + + [Fact(Skip = SkipReason)] + public override Task Drop_index() => base.Drop_index(); + + [Fact(Skip = SkipReason)] + public override Task Rename_index() => base.Rename_index(); + + [Fact(Skip = SkipReason)] + public override Task Add_primary_key() => base.Add_primary_key(); + + [Fact(Skip = SkipReason)] + public override Task Add_primary_key_with_name() => base.Add_primary_key_with_name(); + + [Fact(Skip = SkipReason)] + public override Task Add_primary_key_composite_with_name() => base.Add_primary_key_composite_with_name(); + + [Fact(Skip = SkipReason)] + public override Task Drop_primary_key() => base.Drop_primary_key(); + + [Fact(Skip = SkipReason)] + public override Task Add_foreign_key() => base.Add_foreign_key(); + + [Fact(Skip = SkipReason)] + public override Task Add_foreign_key_with_name() => base.Add_foreign_key_with_name(); + + [Fact(Skip = SkipReason)] + public override Task Drop_foreign_key() => base.Drop_foreign_key(); + + [Fact(Skip = SkipReason)] + public override Task Add_unique_constraint() => base.Add_unique_constraint(); + + [Fact(Skip = SkipReason)] + public override Task Add_unique_constraint_composite_with_name() => base.Add_unique_constraint_composite_with_name(); + + [Fact(Skip = SkipReason)] + public override Task Drop_unique_constraint() => base.Drop_unique_constraint(); + + [Fact(Skip = SkipReason)] + public override Task Add_check_constraint_with_name() => base.Add_check_constraint_with_name(); + + [Fact(Skip = SkipReason)] + public override Task Alter_check_constraint() => base.Alter_check_constraint(); + + [Fact(Skip = SkipReason)] + public override Task Drop_check_constraint() => base.Drop_check_constraint(); + + [Fact(Skip = SkipReason)] + public override Task Create_sequence() => base.Create_sequence(); + + [Fact(Skip = SkipReason)] + public override Task Create_sequence_all_settings() => base.Create_sequence_all_settings(); + + [Fact(Skip = SkipReason)] + public override Task Alter_sequence_all_settings() => base.Alter_sequence_all_settings(); + + [Fact(Skip = SkipReason)] + public override Task Alter_sequence_increment_by() => base.Alter_sequence_increment_by(); + + [Fact(Skip = SkipReason)] + public override Task Drop_sequence() => base.Drop_sequence(); + + [Fact(Skip = SkipReason)] + public override Task Rename_sequence() => base.Rename_sequence(); + + [Fact(Skip = SkipReason)] + public override Task Move_sequence() => base.Move_sequence(); + + [Fact(Skip = SkipReason)] + public override Task InsertDataOperation() => base.InsertDataOperation(); + + [Fact(Skip = SkipReason)] + public override Task DeleteDataOperation_simple_key() => base.DeleteDataOperation_simple_key(); + + [Fact(Skip = SkipReason)] + public override Task DeleteDataOperation_composite_key() => base.DeleteDataOperation_composite_key(); + + [Fact(Skip = SkipReason)] + public override Task UpdateDataOperation_simple_key() => base.UpdateDataOperation_simple_key(); + + [Fact(Skip = SkipReason)] + public override Task UpdateDataOperation_composite_key() => base.UpdateDataOperation_composite_key(); + + [Fact(Skip = SkipReason)] + public override Task UpdateDataOperation_multiple_columns() => base.UpdateDataOperation_multiple_columns(); + + [Fact(Skip = SkipReason)] + public override Task Alter_column_make_non_computed() => base.Alter_column_make_non_computed(); + + [Fact(Skip = SkipReason)] + public override Task Alter_computed_column_add_comment() => base.Alter_computed_column_add_comment(); + + [Fact(Skip = SkipReason)] + public override Task Drop_column_computed_and_non_computed_with_dependency() => base.Drop_column_computed_and_non_computed_with_dependency(); + + [Fact(Skip = SkipReason)] + public override Task SqlOperation() => base.SqlOperation(); + + public class MigrationsIBFixture : MigrationsFixtureBase { - public MigrationsIBTest(MigrationsIBFixture fixture) - : base(fixture) - { } - - protected override void GiveMeSomeTime(DbContext db) - { } - - protected override Task GiveMeSomeTimeAsync(DbContext db) - => Task.CompletedTask; - - [Fact] - public override void Can_generate_idempotent_up_scripts() - { - Assert.Throws(base.Can_generate_idempotent_up_scripts); - } - - [Fact] - public override void Can_generate_idempotent_down_scripts() - { - Assert.Throws(base.Can_generate_idempotent_down_scripts); - } - - [Fact(Skip = "")] - public override void Can_diff_against_2_2_model() - { } - - [Fact(Skip = "")] - public override void Can_diff_against_3_0_ASP_NET_Identity_model() - { } - - [Fact(Skip = "")] - public override void Can_diff_against_2_2_ASP_NET_Identity_model() - { } - - [Fact(Skip = "")] - public override void Can_diff_against_2_1_ASP_NET_Identity_model() - { } + protected override string StoreName => nameof(MigrationsIBTest); + + protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; + + public override TestHelpers TestHelpers => IBTestHelpers.Instance; + + protected override IServiceCollection AddServices(IServiceCollection serviceCollection) +#pragma warning disable EF1001 + => base.AddServices(serviceCollection) + .AddScoped(); +#pragma warning restore EF1001 } + } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/AsNoTrackingIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/AsNoTrackingIBTest.cs deleted file mode 100644 index 6f350c7..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/AsNoTrackingIBTest.cs +++ /dev/null @@ -1,32 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.TestUtilities; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class AsNoTrackingIBTest : AsNoTrackingTestBase> - { - public AsNoTrackingIBTest(NorthwindQueryIBFixture fixture) - : base(fixture) - { } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/AsTrackingIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/AsTrackingIBTest.cs deleted file mode 100644 index 3bf606d..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/AsTrackingIBTest.cs +++ /dev/null @@ -1,32 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.TestUtilities; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class AsTrackingIBTest : AsTrackingTestBase> - { - public AsTrackingIBTest(NorthwindQueryIBFixture fixture) - : base(fixture) - { } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/AsyncFromSqlQueryIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/AsyncFromSqlQueryIBTest.cs deleted file mode 100644 index 893d47a..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/AsyncFromSqlQueryIBTest.cs +++ /dev/null @@ -1,32 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.TestUtilities; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class AsyncFromSqlQueryIBTest : AsyncFromSqlQueryTestBase> - { - public AsyncFromSqlQueryIBTest(NorthwindQueryIBFixture fixture) - : base(fixture) - { } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/AsyncGearsOfWarQueryIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/AsyncGearsOfWarQueryIBTest.cs deleted file mode 100644 index 5bddf0e..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/AsyncGearsOfWarQueryIBTest.cs +++ /dev/null @@ -1,44 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using System.Linq; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Query; -using Xunit; -using Xunit.Abstractions; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class AsyncGearsOfWarQueryIBTest : AsyncGearsOfWarQueryTestBase - { - public AsyncGearsOfWarQueryIBTest(GearsOfWarQueryIBFixture fixture, ITestOutputHelper testOutputHelper) - : base(fixture) - { } - - // the original implementation has wrong assert - public override async Task GroupBy_Select_sum() - { - using var ctx = CreateContext(); - var result = await ctx.Missions.GroupBy(m => m.CodeName).Select(g => g.Sum(m => m.Rating)).ToListAsync(); - Assert.Equal(6.3, result.Sum() ?? double.NaN, precision: 1); - } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/AsyncSimpleQueryIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/AsyncSimpleQueryIBTest.cs deleted file mode 100644 index 9de222d..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/AsyncSimpleQueryIBTest.cs +++ /dev/null @@ -1,53 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using System.Threading.Tasks; -using InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Helpers; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.TestUtilities; -using Xunit; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class AsyncSimpleQueryIBTest : AsyncSimpleQueryTestBase> - { - public AsyncSimpleQueryIBTest(NorthwindQueryIBFixture fixture) - : base(fixture) - { } - - [Fact(Skip = "Missing view (and tables) for it.")] - public override Task Query_backed_by_database_view() - { - return base.Query_backed_by_database_view(); - } - - [NotSupportedOnInterBaseFact] - public override Task Intersect_non_entity() - { - return base.Intersect_non_entity(); - } - - [NotSupportedOnInterBaseFact] - public override Task Except_non_entity() - { - return base.Except_non_entity(); - } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/ChangeTrackingIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/ChangeTrackingIBTest.cs deleted file mode 100644 index e574fb3..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/ChangeTrackingIBTest.cs +++ /dev/null @@ -1,39 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.TestModels.Northwind; -using Microsoft.EntityFrameworkCore.TestUtilities; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class ChangeTrackingIBTest : ChangeTrackingTestBase> - { - public ChangeTrackingIBTest(NorthwindQueryIBFixture fixture) - : base(fixture) - { } - - protected override NorthwindContext CreateNoTrackingContext() - => new NorthwindRelationalContext( - new DbContextOptionsBuilder(Fixture.CreateOptions()) - .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking).Options); - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/Changelog.md new file mode 100644 index 0000000..13bede8 --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/Changelog.md @@ -0,0 +1,27 @@ +#Changes for 7.13.6 (updated for EFCore 6.0 and to Fb 9.x) + +## removed FiltersIBTest.cs, DbFunctionsIBTest.cs, ComplexNavigationsWeakQueryIBTest.cs, InheritanceIBTest.cs, FiltersInheritanceIBTest.cs, FiltersInheritanceIBFixture.cs, +## CompiledQueryIBTest.cs, ChangeTrackingIBTest.cs, AsNoTrackingIBTest.cs, AsyncSimpleQueryIBTest.cs, AsyncGearsOfWarQueryIBTest.cs, AsyncFromSqlQueryIBTest.cs, +## AsTrackingIBTest.cs, ComplexNavigationsWeakQueryIBFixture.cs, GroupByQueryIBTest.cs, SimpleQueryIBTest.cs, QueryTaggingIBTest.cs, QueryNavigationsIBTest.cs, +## InheritanceIBFixture.cs, IncludeIBTest.cs, IncludeAsyncIBTest.cs + +# Changes for 7.10.2 + +## General - +* All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. + +## Common +* Namespaces changed from FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests.Query to InterBaseSQL.EntityFrameworkCore.InterBase.FunctionalTests.Query +* Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. + +* All files renamed from FbXxxxx to IBXxxxx with the internal class matching that same change. In some cases the Fb occurs inside the name and not as a prefix. +* For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup + +* using FirebirdSql.Data.FirebirdClient now using InterBaseSql.Data.InterBaseClient + +* "Firebird" in strings or test names replaced with "InterBase" + + + + + diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/Changelog.txt b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/Changelog.txt deleted file mode 100644 index 9ae4871..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/Changelog.txt +++ /dev/null @@ -1,20 +0,0 @@ -Changes for 7.10.2 - - General - - All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. - - Common - Namespaces changed from FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests.Query to InterBaseSQL.EntityFrameworkCore.InterBase.FunctionalTests.Query - Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. - - All files renamed from FbXxxxx to IBXxxxx with the internal class matching that same change. In some cases the Fb occurs inside the name and not as a prefix. - For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup - - using FirebirdSql.Data.FirebirdClient now using InterBaseSql.Data.InterBaseClient - - "Firebird" in strings or test names replaced with "InterBase" - - - - - \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/CompiledQueryIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/CompiledQueryIBTest.cs deleted file mode 100644 index 96a742b..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/CompiledQueryIBTest.cs +++ /dev/null @@ -1,34 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.TestUtilities; -using Xunit; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class CompiledQueryIBTest : CompiledQueryTestBase> - { - public CompiledQueryIBTest(NorthwindQueryIBFixture fixture) - : base(fixture) - { } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/ComplexNavigationsQueryIBFixture.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/ComplexNavigationsQueryIBFixture.cs index 39dacbf..232f3d3 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/ComplexNavigationsQueryIBFixture.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/ComplexNavigationsQueryIBFixture.cs @@ -24,16 +24,16 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class ComplexNavigationsQueryIBFixture : ComplexNavigationsQueryRelationalFixtureBase +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query; + +public class ComplexNavigationsQueryIBFixture : ComplexNavigationsQueryRelationalFixtureBase { protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - base.OnModelCreating(modelBuilder, context); - ModelHelpers.SimpleTableNames(modelBuilder); - } + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + base.OnModelCreating(modelBuilder, context); + ModelHelpers.SimpleTableNames(modelBuilder); + ModelHelpers.SetStringLengths(modelBuilder); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/ComplexNavigationsQueryIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/ComplexNavigationsQueryIBTest.cs index 8684e4b..72a3866 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/ComplexNavigationsQueryIBTest.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/ComplexNavigationsQueryIBTest.cs @@ -19,1007 +19,709 @@ //$Authors = Jiri Cincura (jiri@cincura.net) using System.Threading.Tasks; +using System.Linq; using InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Helpers; +using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.TestModels.ComplexNavigationsModel; +using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query; + +public class ComplexNavigationsQueryIBTest : ComplexNavigationsQueryTestBase { - public class ComplexNavigationsQueryIBTest : ComplexNavigationsQueryTestBase - { - public ComplexNavigationsQueryIBTest(ComplexNavigationsQueryIBFixture fixture) - : base(fixture) - { } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Complex_multi_include_with_order_by_and_paging(bool isAsync) - { - return base.Complex_multi_include_with_order_by_and_paging(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Complex_multi_include_with_order_by_and_paging_joins_on_correct_key(bool isAsync) - { - return base.Complex_multi_include_with_order_by_and_paging_joins_on_correct_key(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Complex_multi_include_with_order_by_and_paging_joins_on_correct_key2(bool isAsync) - { - return base.Complex_multi_include_with_order_by_and_paging_joins_on_correct_key2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Complex_navigations_with_predicate_projected_into_anonymous_type(bool isAsync) - { - return base.Complex_navigations_with_predicate_projected_into_anonymous_type(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Complex_navigations_with_predicate_projected_into_anonymous_type2(bool isAsync) - { - return base.Complex_navigations_with_predicate_projected_into_anonymous_type2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Complex_query_with_optional_navigations_and_client_side_evaluation(bool isAsync) - { - return base.Complex_query_with_optional_navigations_and_client_side_evaluation(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Complex_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_with_other_query_operators_composed_on_top(bool isAsync) - { - return base.Complex_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_with_other_query_operators_composed_on_top(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Include_after_multiple_SelectMany_and_reference_navigation(bool isAsync) - { - return base.Include_after_multiple_SelectMany_and_reference_navigation(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Include_after_SelectMany_and_multiple_reference_navigations(bool isAsync) - { - return base.Include_after_SelectMany_and_multiple_reference_navigations(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Include_after_SelectMany_and_reference_navigation(bool isAsync) - { - return base.Include_after_SelectMany_and_reference_navigation(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Include_after_SelectMany_and_reference_navigation_with_another_SelectMany_with_Distinct(bool isAsync) - { - return base.Include_after_SelectMany_and_reference_navigation_with_another_SelectMany_with_Distinct(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Include_nested_with_optional_navigation(bool isAsync) - { - return base.Include_nested_with_optional_navigation(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Include_reference_collection_order_by_reference_navigation(bool isAsync) - { - return base.Include_reference_collection_order_by_reference_navigation(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Join_navigation_in_outer_selector_translated_to_extra_join_nested(bool isAsync) - { - return base.Join_navigation_in_outer_selector_translated_to_extra_join_nested(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Join_navigation_in_outer_selector_translated_to_extra_join_nested2(bool isAsync) - { - return base.Join_navigation_in_outer_selector_translated_to_extra_join_nested2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Level4_Include(bool isAsync) - { - return base.Level4_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Manually_created_left_join_propagates_nullability_to_navigations(bool isAsync) - { - return base.Manually_created_left_join_propagates_nullability_to_navigations(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_complex_includes(bool isAsync) - { - return base.Multiple_complex_includes(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_complex_includes_self_ref(bool isAsync) - { - return base.Multiple_complex_includes_self_ref(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_complex_include_select(bool isAsync) - { - return base.Multiple_complex_include_select(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_include_with_multiple_optional_navigations(bool isAsync) - { - return base.Multiple_include_with_multiple_optional_navigations(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_optional_navigation_with_Include(bool isAsync) - { - return base.Multiple_optional_navigation_with_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_optional_navigation_with_string_based_Include(bool isAsync) - { - return base.Multiple_optional_navigation_with_string_based_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_required_navigations_with_Include(bool isAsync) - { - return base.Multiple_required_navigations_with_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_required_navigation_using_multiple_selects_with_Include(bool isAsync) - { - return base.Multiple_required_navigation_using_multiple_selects_with_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_required_navigation_using_multiple_selects_with_string_based_Include(bool isAsync) - { - return base.Multiple_required_navigation_using_multiple_selects_with_string_based_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_required_navigation_with_string_based_Include(bool isAsync) - { - return base.Multiple_required_navigation_with_string_based_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_SelectMany_calls(bool isAsync) - { - return base.Multiple_SelectMany_calls(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_SelectMany_navigation_property_followed_by_select_collection_navigation(bool isAsync) - { - return base.Multiple_SelectMany_navigation_property_followed_by_select_collection_navigation(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_SelectMany_with_Include(bool isAsync) - { - return base.Multiple_SelectMany_with_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_SelectMany_with_navigation_and_explicit_DefaultIfEmpty(bool isAsync) - { - return base.Multiple_SelectMany_with_navigation_and_explicit_DefaultIfEmpty(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_joined_together(bool isAsync) - { - return base.Multiple_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_joined_together(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_SelectMany_with_string_based_Include(bool isAsync) - { - return base.Multiple_SelectMany_with_string_based_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multi_include_with_groupby_in_subquery(bool isAsync) - { - return base.Multi_include_with_groupby_in_subquery(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multi_level_include_correct_PK_is_chosen_as_the_join_predicate_for_queries_that_join_same_table_multiple_times(bool isAsync) - { - return base.Multi_level_include_correct_PK_is_chosen_as_the_join_predicate_for_queries_that_join_same_table_multiple_times(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multi_level_include_one_to_many_optional_and_one_to_many_optional_produces_valid_sql(bool isAsync) - { - return base.Multi_level_include_one_to_many_optional_and_one_to_many_optional_produces_valid_sql(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multi_level_navigation_with_same_navigation_compared_to_null(bool isAsync) - { - return base.Multi_level_navigation_with_same_navigation_compared_to_null(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigation_filter_navigation_grouping_ordering_by_group_key(bool isAsync) - { - return base.Navigation_filter_navigation_grouping_ordering_by_group_key(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigation_inside_method_call_translated_to_join2(bool isAsync) - { - return base.Navigation_inside_method_call_translated_to_join2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Optional_navigation_take_optional_navigation(bool isAsync) - { - return base.Optional_navigation_take_optional_navigation(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Optional_navigation_with_Include(bool isAsync) - { - return base.Optional_navigation_with_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Optional_navigation_with_Include_and_order(bool isAsync) - { - return base.Optional_navigation_with_Include_and_order(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Optional_navigation_with_Include_ThenInclude(bool isAsync) - { - return base.Optional_navigation_with_Include_ThenInclude(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Optional_navigation_with_order_by_and_Include(bool isAsync) - { - return base.Optional_navigation_with_order_by_and_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Order_by_key_of_anonymous_type_projected_navigation_doesnt_get_optimized_into_FK_access_subquery(bool isAsync) - { - return base.Order_by_key_of_anonymous_type_projected_navigation_doesnt_get_optimized_into_FK_access_subquery(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Order_by_key_of_navigation_similar_to_projected_gets_optimized_into_FK_access(bool isAsync) - { - return base.Order_by_key_of_navigation_similar_to_projected_gets_optimized_into_FK_access(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access1(bool isAsync) - { - return base.Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access1(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access2(bool isAsync) - { - return base.Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access3(bool isAsync) - { - return base.Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access3(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access_subquery(bool isAsync) - { - return base.Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access_subquery(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Projection_select_correct_table_from_subquery_when_materialization_is_not_required(bool isAsync) - { - return base.Projection_select_correct_table_from_subquery_when_materialization_is_not_required(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Project_collection_navigation_nested(bool isAsync) - { - return base.Project_collection_navigation_nested(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Project_collection_navigation_nested_anonymous(bool isAsync) - { - return base.Project_collection_navigation_nested_anonymous(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Project_collection_navigation_using_ef_property(bool isAsync) - { - return base.Project_collection_navigation_using_ef_property(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Project_navigation_and_collection(bool isAsync) - { - return base.Project_navigation_and_collection(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Required_navigation_on_a_subquery_with_complex_projection_and_First(bool isAsync) - { - return base.Required_navigation_on_a_subquery_with_complex_projection_and_First(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Required_navigation_on_a_subquery_with_First_in_predicate(bool isAsync) - { - return base.Required_navigation_on_a_subquery_with_First_in_predicate(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Required_navigation_on_a_subquery_with_First_in_projection(bool isAsync) - { - return base.Required_navigation_on_a_subquery_with_First_in_projection(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Required_navigation_with_Include(bool isAsync) - { - return base.Required_navigation_with_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Required_navigation_with_Include_ThenInclude(bool isAsync) - { - return base.Required_navigation_with_Include_ThenInclude(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_navigation_property_followed_by_select_collection_navigation(bool isAsync) - { - return base.SelectMany_navigation_property_followed_by_select_collection_navigation(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_navigation_property_with_another_navigation_in_subquery(bool isAsync) - { - return base.SelectMany_navigation_property_with_another_navigation_in_subquery(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_navigation_property_with_include_and_followed_by_select_collection_navigation(bool isAsync) - { - return base.SelectMany_navigation_property_with_include_and_followed_by_select_collection_navigation(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_nested_navigation_property_optional_and_projection(bool isAsync) - { - return base.SelectMany_nested_navigation_property_optional_and_projection(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_nested_navigation_property_required(bool isAsync) - { - return base.SelectMany_nested_navigation_property_required(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_Include1(bool isAsync) - { - return base.SelectMany_with_Include1(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_Include2(bool isAsync) - { - return base.SelectMany_with_Include2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_Include_and_order_by(bool isAsync) - { - return base.SelectMany_with_Include_and_order_by(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_Include_ThenInclude(bool isAsync) - { - return base.SelectMany_with_Include_ThenInclude(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_nested_navigations_and_additional_joins_outside_of_SelectMany(bool isAsync) - { - return base.SelectMany_with_nested_navigations_and_additional_joins_outside_of_SelectMany(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_followed_by_Select_required_navigation_using_different_navs(bool isAsync) - { - return base.SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_followed_by_Select_required_navigation_using_different_navs(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_followed_by_Select_required_navigation_using_same_navs(bool isAsync) - { - return base.SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_followed_by_Select_required_navigation_using_same_navs(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany(bool isAsync) - { - return base.SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany2(bool isAsync) - { - return base.SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany3(bool isAsync) - { - return base.SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany3(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany4(bool isAsync) - { - return base.SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany4(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_nested_navigation_and_explicit_DefaultIfEmpty(bool isAsync) - { - return base.SelectMany_with_nested_navigation_and_explicit_DefaultIfEmpty(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_nested_navigation_filter_and_explicit_DefaultIfEmpty(bool isAsync) - { - return base.SelectMany_with_nested_navigation_filter_and_explicit_DefaultIfEmpty(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_nested_required_navigation_filter_and_explicit_DefaultIfEmpty(bool isAsync) - { - return base.SelectMany_with_nested_required_navigation_filter_and_explicit_DefaultIfEmpty(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_order_by_and_Include(bool isAsync) - { - return base.SelectMany_with_order_by_and_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_string_based_Include1(bool isAsync) - { - return base.SelectMany_with_string_based_Include1(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_string_based_Include2(bool isAsync) - { - return base.SelectMany_with_string_based_Include2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Select_multiple_nav_prop_optional_required(bool isAsync) - { - return base.Select_multiple_nav_prop_optional_required(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Select_multiple_nav_prop_reference_optional(bool isAsync) - { - return base.Select_multiple_nav_prop_reference_optional(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Select_multiple_nav_prop_reference_required(bool isAsync) - { - return base.Select_multiple_nav_prop_reference_required(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Select_multiple_nav_prop_reference_required2(bool isAsync) - { - return base.Select_multiple_nav_prop_reference_required2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Select_subquery_with_client_eval_and_navigation1(bool isAsync) - { - return base.Select_subquery_with_client_eval_and_navigation1(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Select_subquery_with_client_eval_and_navigation2(bool isAsync) - { - return base.Select_subquery_with_client_eval_and_navigation2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Simple_level1_level2_GroupBy_Count(bool isAsync) - { - return base.Simple_level1_level2_GroupBy_Count(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Simple_level1_level2_GroupBy_Having_Count(bool isAsync) - { - return base.Simple_level1_level2_GroupBy_Having_Count(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Simple_level1_level2_include(bool isAsync) - { - return base.Simple_level1_level2_include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Simple_level1_level2_level3_include(bool isAsync) - { - return base.Simple_level1_level2_level3_include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task String_include_multiple_derived_collection_navigation_with_same_name_and_different_type_nested_also_includes_partially_matching_navigation_chains(bool isAsync) - { - return base.String_include_multiple_derived_collection_navigation_with_same_name_and_different_type_nested_also_includes_partially_matching_navigation_chains(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task String_include_multiple_derived_navigations_complex(bool isAsync) - { - return base.String_include_multiple_derived_navigations_complex(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task String_include_multiple_derived_navigation_with_same_name_and_different_type_nested_also_includes_partially_matching_navigation_chains(bool isAsync) - { - return base.String_include_multiple_derived_navigation_with_same_name_and_different_type_nested_also_includes_partially_matching_navigation_chains(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_complex_predicate_with_with_nav_prop_and_OrElse1(bool isAsync) - { - return base.Where_complex_predicate_with_with_nav_prop_and_OrElse1(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_complex_predicate_with_with_nav_prop_and_OrElse2(bool isAsync) - { - return base.Where_complex_predicate_with_with_nav_prop_and_OrElse2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_complex_predicate_with_with_nav_prop_and_OrElse3(bool isAsync) - { - return base.Where_complex_predicate_with_with_nav_prop_and_OrElse3(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_complex_predicate_with_with_nav_prop_and_OrElse4(bool isAsync) - { - return base.Where_complex_predicate_with_with_nav_prop_and_OrElse4(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_multiple_nav_prop_optional_required(bool isAsync) - { - return base.Where_multiple_nav_prop_optional_required(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_multiple_nav_prop_reference_optional_compared_to_null1(bool isAsync) - { - return base.Where_multiple_nav_prop_reference_optional_compared_to_null1(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_multiple_nav_prop_reference_optional_compared_to_null2(bool isAsync) - { - return base.Where_multiple_nav_prop_reference_optional_compared_to_null2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_multiple_nav_prop_reference_optional_compared_to_null3(bool isAsync) - { - return base.Where_multiple_nav_prop_reference_optional_compared_to_null3(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_multiple_nav_prop_reference_optional_compared_to_null4(bool isAsync) - { - return base.Where_multiple_nav_prop_reference_optional_compared_to_null4(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_multiple_nav_prop_reference_optional_compared_to_null5(bool isAsync) - { - return base.Where_multiple_nav_prop_reference_optional_compared_to_null5(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_multiple_nav_prop_reference_optional_member_compared_to_null(bool isAsync) - { - return base.Where_multiple_nav_prop_reference_optional_member_compared_to_null(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_multiple_nav_prop_reference_optional_member_compared_to_value(bool isAsync) - { - return base.Where_multiple_nav_prop_reference_optional_member_compared_to_value(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_navigation_property_to_collection2(bool isAsync) - { - return base.Where_navigation_property_to_collection2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_on_multilevel_reference_in_subquery_with_outer_projection(bool isAsync) - { - return base.Where_on_multilevel_reference_in_subquery_with_outer_projection(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Correlated_subquery_doesnt_project_unnecessary_columns_in_top_level_join(bool isAsync) - { - return base.Correlated_subquery_doesnt_project_unnecessary_columns_in_top_level_join(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task GroupJoin_with_complex_subquery_with_joins_does_not_get_flattened(bool isAsync) - { - return base.GroupJoin_with_complex_subquery_with_joins_does_not_get_flattened(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task GroupJoin_with_complex_subquery_with_joins_does_not_get_flattened2(bool isAsync) - { - return base.GroupJoin_with_complex_subquery_with_joins_does_not_get_flattened2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task GroupJoin_with_complex_subquery_with_joins_does_not_get_flattened3(bool isAsync) - { - return base.GroupJoin_with_complex_subquery_with_joins_does_not_get_flattened3(isAsync); - } - - [GeneratedNameTooLongFact] - public override void Include18() - { - base.Include18(); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Include18_1_1(bool isAsync) - { - return base.Include18_1_1(isAsync); - } - - [GeneratedNameTooLongFact] - public override void Include19() - { - base.Include19(); - } - - [GeneratedNameTooLongFact] - public override void IncludeCollection2() - { - base.IncludeCollection2(); - } - - [GeneratedNameTooLongFact] - public override void IncludeCollection5() - { - base.IncludeCollection6(); - } - - [GeneratedNameTooLongFact] - public override void IncludeCollection6() - { - base.IncludeCollection6(); - } - - [GeneratedNameTooLongFact] - public override void IncludeCollection6_1() - { - base.IncludeCollection6_1(); - } - - [GeneratedNameTooLongFact] - public override void IncludeCollection6_2() - { - base.IncludeCollection6_2(); - } - - [GeneratedNameTooLongFact] - public override void IncludeCollection6_3() - { - base.IncludeCollection6_3(); - } - - [GeneratedNameTooLongFact] - public override void IncludeCollection6_4() - { - base.IncludeCollection6_4(); - } - - [GeneratedNameTooLongFact] - public override void IncludeCollection7() - { - base.IncludeCollection7(); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task IncludeCollection8(bool isAsync) - { - return base.IncludeCollection8(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Include_inside_subquery(bool isAsync) - { - return base.Include_inside_subquery(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Join_navigation_deeply_nested_non_key_join(bool isAsync) - { - return base.Join_navigation_deeply_nested_non_key_join(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Join_navigation_deeply_nested_required(bool isAsync) - { - return base.Join_navigation_deeply_nested_required(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Join_navigation_in_inner_selector(bool isAsync) - { - return base.Join_navigation_in_inner_selector(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Join_navigation_key_access_optional(bool isAsync) - { - return base.Join_navigation_key_access_optional(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Join_navigation_key_access_required(bool isAsync) - { - return base.Join_navigation_key_access_required(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Join_navigation_nested(bool isAsync) - { - return base.Join_navigation_nested(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Join_navigation_nested2(bool isAsync) - { - return base.Join_navigation_nested2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Join_navigation_non_key_join(bool isAsync) - { - return base.Join_navigation_non_key_join(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Join_navigation_self_ref(bool isAsync) - { - return base.Join_navigation_self_ref(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Join_navigations_in_inner_selector_translated_without_collision(bool isAsync) - { - return base.Join_navigations_in_inner_selector_translated_without_collision(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Join_with_orderby_on_inner_sequence_navigation_non_key_join(bool isAsync) - { - return base.Join_with_orderby_on_inner_sequence_navigation_non_key_join(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Null_reference_protection_complex(bool isAsync) - { - return base.Null_reference_protection_complex(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Null_reference_protection_complex_client_eval(bool isAsync) - { - return base.Null_reference_protection_complex_client_eval(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Null_reference_protection_complex_materialization(bool isAsync) - { - return base.Null_reference_protection_complex_materialization(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Optional_navigation_propagates_nullability_to_manually_created_left_join2(bool isAsync) - { - return base.Optional_navigation_propagates_nullability_to_manually_created_left_join2(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Project_collection_navigation_nested_with_take(bool isAsync) - { - return base.Project_collection_navigation_nested_with_take(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Union_over_entities_with_different_nullability(bool isAsync) - { - return base.Union_over_entities_with_different_nullability(isAsync); - } + public ComplexNavigationsQueryIBTest(ComplexNavigationsQueryIBFixture fixture) + : base(fixture) + { } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Complex_navigations_with_predicate_projected_into_anonymous_type(bool isAsync) + { + return base.Complex_navigations_with_predicate_projected_into_anonymous_type(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Complex_navigations_with_predicate_projected_into_anonymous_type2(bool isAsync) + { + return base.Complex_navigations_with_predicate_projected_into_anonymous_type2(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Complex_query_with_optional_navigations_and_client_side_evaluation(bool isAsync) + { + return base.Complex_query_with_optional_navigations_and_client_side_evaluation(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Join_navigation_in_outer_selector_translated_to_extra_join_nested(bool isAsync) + { + return base.Join_navigation_in_outer_selector_translated_to_extra_join_nested(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Join_navigation_in_outer_selector_translated_to_extra_join_nested2(bool isAsync) + { + return base.Join_navigation_in_outer_selector_translated_to_extra_join_nested2(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Level4_Include(bool isAsync) + { + return base.Level4_Include(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Manually_created_left_join_propagates_nullability_to_navigations(bool isAsync) + { + return base.Manually_created_left_join_propagates_nullability_to_navigations(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Multiple_required_navigations_with_Include(bool isAsync) + { + return base.Multiple_required_navigations_with_Include(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Multiple_required_navigation_using_multiple_selects_with_Include(bool isAsync) + { + return base.Multiple_required_navigation_using_multiple_selects_with_Include(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Multiple_required_navigation_using_multiple_selects_with_string_based_Include(bool isAsync) + { + return base.Multiple_required_navigation_using_multiple_selects_with_string_based_Include(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Multiple_required_navigation_with_string_based_Include(bool isAsync) + { + return base.Multiple_required_navigation_with_string_based_Include(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Multiple_SelectMany_calls(bool isAsync) + { + return base.Multiple_SelectMany_calls(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Multiple_SelectMany_with_navigation_and_explicit_DefaultIfEmpty(bool isAsync) + { + return base.Multiple_SelectMany_with_navigation_and_explicit_DefaultIfEmpty(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Multiple_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_joined_together(bool isAsync) + { + return base.Multiple_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_joined_together(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Multiple_SelectMany_with_string_based_Include(bool isAsync) + { + return base.Multiple_SelectMany_with_string_based_Include(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Multi_include_with_groupby_in_subquery(bool isAsync) + { + return base.Multi_include_with_groupby_in_subquery(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Multi_level_navigation_with_same_navigation_compared_to_null(bool isAsync) + { + return base.Multi_level_navigation_with_same_navigation_compared_to_null(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Navigation_inside_method_call_translated_to_join2(bool isAsync) + { + return base.Navigation_inside_method_call_translated_to_join2(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Optional_navigation_take_optional_navigation(bool isAsync) + { + return base.Optional_navigation_take_optional_navigation(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Optional_navigation_with_Include(bool isAsync) + { + return base.Optional_navigation_with_Include(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Order_by_key_of_anonymous_type_projected_navigation_doesnt_get_optimized_into_FK_access_subquery(bool isAsync) + { + return base.Order_by_key_of_anonymous_type_projected_navigation_doesnt_get_optimized_into_FK_access_subquery(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Order_by_key_of_navigation_similar_to_projected_gets_optimized_into_FK_access(bool isAsync) + { + return base.Order_by_key_of_navigation_similar_to_projected_gets_optimized_into_FK_access(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access1(bool isAsync) + { + return base.Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access1(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access2(bool isAsync) + { + return base.Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access2(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access3(bool isAsync) + { + return base.Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access3(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access_subquery(bool isAsync) + { + return base.Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access_subquery(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Projection_select_correct_table_from_subquery_when_materialization_is_not_required(bool isAsync) + { + return base.Projection_select_correct_table_from_subquery_when_materialization_is_not_required(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Required_navigation_on_a_subquery_with_complex_projection_and_First(bool isAsync) + { + return base.Required_navigation_on_a_subquery_with_complex_projection_and_First(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Required_navigation_on_a_subquery_with_First_in_predicate(bool isAsync) + { + return base.Required_navigation_on_a_subquery_with_First_in_predicate(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Required_navigation_on_a_subquery_with_First_in_projection(bool isAsync) + { + return base.Required_navigation_on_a_subquery_with_First_in_projection(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task SelectMany_nested_navigation_property_optional_and_projection(bool isAsync) + { + return base.SelectMany_nested_navigation_property_optional_and_projection(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task SelectMany_nested_navigation_property_required(bool isAsync) + { + return base.SelectMany_nested_navigation_property_required(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task SelectMany_with_nested_navigations_and_additional_joins_outside_of_SelectMany(bool isAsync) + { + return base.SelectMany_with_nested_navigations_and_additional_joins_outside_of_SelectMany(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_followed_by_Select_required_navigation_using_different_navs(bool isAsync) + { + return base.SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_followed_by_Select_required_navigation_using_different_navs(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_followed_by_Select_required_navigation_using_same_navs(bool isAsync) + { + return base.SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_followed_by_Select_required_navigation_using_same_navs(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany(bool isAsync) + { + return base.SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany2(bool isAsync) + { + return base.SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany2(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany3(bool isAsync) + { + return base.SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany3(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany4(bool isAsync) + { + return base.SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany4(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task SelectMany_with_nested_navigation_and_explicit_DefaultIfEmpty(bool isAsync) + { + return base.SelectMany_with_nested_navigation_and_explicit_DefaultIfEmpty(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task SelectMany_with_nested_navigation_filter_and_explicit_DefaultIfEmpty(bool isAsync) + { + return base.SelectMany_with_nested_navigation_filter_and_explicit_DefaultIfEmpty(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task SelectMany_with_nested_required_navigation_filter_and_explicit_DefaultIfEmpty(bool isAsync) + { + return base.SelectMany_with_nested_required_navigation_filter_and_explicit_DefaultIfEmpty(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task SelectMany_with_string_based_Include1(bool isAsync) + { + return base.SelectMany_with_string_based_Include1(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task SelectMany_with_string_based_Include2(bool isAsync) + { + return base.SelectMany_with_string_based_Include2(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Select_multiple_nav_prop_optional_required(bool isAsync) + { + return base.Select_multiple_nav_prop_optional_required(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Select_multiple_nav_prop_reference_optional(bool isAsync) + { + return base.Select_multiple_nav_prop_reference_optional(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Select_multiple_nav_prop_reference_required(bool isAsync) + { + return base.Select_multiple_nav_prop_reference_required(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Select_multiple_nav_prop_reference_required2(bool isAsync) + { + return base.Select_multiple_nav_prop_reference_required2(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_with_client_eval_and_navigation1(bool isAsync) + { + return base.Select_subquery_with_client_eval_and_navigation1(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_with_client_eval_and_navigation2(bool isAsync) + { + return base.Select_subquery_with_client_eval_and_navigation2(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Simple_level1_level2_GroupBy_Count(bool isAsync) + { + return base.Simple_level1_level2_GroupBy_Count(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Simple_level1_level2_GroupBy_Having_Count(bool isAsync) + { + return base.Simple_level1_level2_GroupBy_Having_Count(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Simple_level1_level2_include(bool isAsync) + { + return base.Simple_level1_level2_include(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Simple_level1_level2_level3_include(bool isAsync) + { + return base.Simple_level1_level2_level3_include(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task String_include_multiple_derived_collection_navigation_with_same_name_and_different_type_nested_also_includes_partially_matching_navigation_chains(bool isAsync) + { + return base.String_include_multiple_derived_collection_navigation_with_same_name_and_different_type_nested_also_includes_partially_matching_navigation_chains(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task String_include_multiple_derived_navigations_complex(bool isAsync) + { + return base.String_include_multiple_derived_navigations_complex(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task String_include_multiple_derived_navigation_with_same_name_and_different_type_nested_also_includes_partially_matching_navigation_chains(bool isAsync) + { + return base.String_include_multiple_derived_navigation_with_same_name_and_different_type_nested_also_includes_partially_matching_navigation_chains(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_complex_predicate_with_with_nav_prop_and_OrElse1(bool isAsync) + { + return base.Where_complex_predicate_with_with_nav_prop_and_OrElse1(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_complex_predicate_with_with_nav_prop_and_OrElse2(bool isAsync) + { + return base.Where_complex_predicate_with_with_nav_prop_and_OrElse2(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_complex_predicate_with_with_nav_prop_and_OrElse3(bool isAsync) + { + return base.Where_complex_predicate_with_with_nav_prop_and_OrElse3(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_complex_predicate_with_with_nav_prop_and_OrElse4(bool isAsync) + { + return base.Where_complex_predicate_with_with_nav_prop_and_OrElse4(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_multiple_nav_prop_optional_required(bool isAsync) + { + return base.Where_multiple_nav_prop_optional_required(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_multiple_nav_prop_reference_optional_compared_to_null1(bool isAsync) + { + return base.Where_multiple_nav_prop_reference_optional_compared_to_null1(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_multiple_nav_prop_reference_optional_compared_to_null2(bool isAsync) + { + return base.Where_multiple_nav_prop_reference_optional_compared_to_null2(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_multiple_nav_prop_reference_optional_compared_to_null3(bool isAsync) + { + return base.Where_multiple_nav_prop_reference_optional_compared_to_null3(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_multiple_nav_prop_reference_optional_compared_to_null4(bool isAsync) + { + return base.Where_multiple_nav_prop_reference_optional_compared_to_null4(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_multiple_nav_prop_reference_optional_compared_to_null5(bool isAsync) + { + return base.Where_multiple_nav_prop_reference_optional_compared_to_null5(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_multiple_nav_prop_reference_optional_member_compared_to_null(bool isAsync) + { + return base.Where_multiple_nav_prop_reference_optional_member_compared_to_null(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_multiple_nav_prop_reference_optional_member_compared_to_value(bool isAsync) + { + return base.Where_multiple_nav_prop_reference_optional_member_compared_to_value(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_navigation_property_to_collection2(bool isAsync) + { + return base.Where_navigation_property_to_collection2(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_on_multilevel_reference_in_subquery_with_outer_projection(bool isAsync) + { + return base.Where_on_multilevel_reference_in_subquery_with_outer_projection(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Correlated_subquery_doesnt_project_unnecessary_columns_in_top_level_join(bool isAsync) + { + return base.Correlated_subquery_doesnt_project_unnecessary_columns_in_top_level_join(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task GroupJoin_with_complex_subquery_with_joins_does_not_get_flattened(bool isAsync) + { + return base.GroupJoin_with_complex_subquery_with_joins_does_not_get_flattened(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task GroupJoin_with_complex_subquery_with_joins_does_not_get_flattened2(bool isAsync) + { + return base.GroupJoin_with_complex_subquery_with_joins_does_not_get_flattened2(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task GroupJoin_with_complex_subquery_with_joins_does_not_get_flattened3(bool isAsync) + { + return base.GroupJoin_with_complex_subquery_with_joins_does_not_get_flattened3(isAsync); + } + + [GeneratedNameTooLongFact] + public override void Include18() + { + base.Include18(); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include18_1_1(bool isAsync) + { + return base.Include18_1_1(isAsync); + } + + [GeneratedNameTooLongFact] + public override void Include19() + { + base.Include19(); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Join_navigation_deeply_nested_non_key_join(bool isAsync) + { + return base.Join_navigation_deeply_nested_non_key_join(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Join_navigation_deeply_nested_required(bool isAsync) + { + return base.Join_navigation_deeply_nested_required(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Join_navigation_in_inner_selector(bool isAsync) + { + return base.Join_navigation_in_inner_selector(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Join_navigation_key_access_optional(bool isAsync) + { + return base.Join_navigation_key_access_optional(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Join_navigation_key_access_required(bool isAsync) + { + return base.Join_navigation_key_access_required(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Join_navigation_nested(bool isAsync) + { + return base.Join_navigation_nested(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Join_navigation_nested2(bool isAsync) + { + return base.Join_navigation_nested2(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Join_navigation_non_key_join(bool isAsync) + { + return base.Join_navigation_non_key_join(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Join_navigation_self_ref(bool isAsync) + { + return base.Join_navigation_self_ref(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Join_navigations_in_inner_selector_translated_without_collision(bool isAsync) + { + return base.Join_navigations_in_inner_selector_translated_without_collision(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Join_with_orderby_on_inner_sequence_navigation_non_key_join(bool isAsync) + { + return base.Join_with_orderby_on_inner_sequence_navigation_non_key_join(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Null_reference_protection_complex(bool isAsync) + { + return base.Null_reference_protection_complex(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Null_reference_protection_complex_client_eval(bool isAsync) + { + return base.Null_reference_protection_complex_client_eval(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Null_reference_protection_complex_materialization(bool isAsync) + { + return base.Null_reference_protection_complex_materialization(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Optional_navigation_propagates_nullability_to_manually_created_left_join2(bool isAsync) + { + return base.Optional_navigation_propagates_nullability_to_manually_created_left_join2(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Union_over_entities_with_different_nullability(bool isAsync) + { + return base.Union_over_entities_with_different_nullability(isAsync); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_reference_with_groupby_in_subquery(bool async) + { + return base.Include_reference_with_groupby_in_subquery(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Project_shadow_properties(bool async) + { + return base.Project_shadow_properties(async); + } + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task SelectMany_with_outside_reference_to_joined_table_correctly_translated_to_apply(bool isAsync) + { + return base.SelectMany_with_outside_reference_to_joined_table_correctly_translated_to_apply(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Let_let_contains_from_outer_let(bool async) + { + return base.Let_let_contains_from_outer_let(async); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Prune_does_not_throw_null_ref(bool async) + { + return base.Prune_does_not_throw_null_ref(async); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/ComplexNavigationsWeakQueryIBFixture.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/ComplexNavigationsWeakQueryIBFixture.cs deleted file mode 100644 index bca068f..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/ComplexNavigationsWeakQueryIBFixture.cs +++ /dev/null @@ -1,39 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Helpers; -using InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.TestUtilities; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.TestUtilities; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class ComplexNavigationsWeakQueryIBFixture : ComplexNavigationsWeakQueryRelationalFixtureBase - { - protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; - - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - base.OnModelCreating(modelBuilder, context); - ModelHelpers.SimpleTableNames(modelBuilder); - } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/ComplexNavigationsWeakQueryIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/ComplexNavigationsWeakQueryIBTest.cs deleted file mode 100644 index c9ee0ae..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/ComplexNavigationsWeakQueryIBTest.cs +++ /dev/null @@ -1,942 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using System.Threading.Tasks; -using InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Helpers; -using Microsoft.EntityFrameworkCore.Query; -using Xunit; -using Xunit.Abstractions; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class ComplexNavigationsWeakQueryIBTest : ComplexNavigationsWeakQueryTestBase - { - public ComplexNavigationsWeakQueryIBTest(ComplexNavigationsWeakQueryIBFixture fixture, ITestOutputHelper testOutputHelper) - : base(fixture) - { } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Complex_multi_include_with_order_by_and_paging(bool isAsync) - { - return base.Complex_multi_include_with_order_by_and_paging(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Complex_multi_include_with_order_by_and_paging_joins_on_correct_key(bool isAsync) - { - return base.Complex_multi_include_with_order_by_and_paging_joins_on_correct_key(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Complex_multi_include_with_order_by_and_paging_joins_on_correct_key2(bool isAsync) - { - return base.Complex_multi_include_with_order_by_and_paging_joins_on_correct_key2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Complex_navigations_with_predicate_projected_into_anonymous_type(bool isAsync) - { - return base.Complex_navigations_with_predicate_projected_into_anonymous_type(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Complex_navigations_with_predicate_projected_into_anonymous_type2(bool isAsync) - { - return base.Complex_navigations_with_predicate_projected_into_anonymous_type2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Complex_query_with_optional_navigations_and_client_side_evaluation(bool isAsync) - { - return base.Complex_query_with_optional_navigations_and_client_side_evaluation(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Correlated_nested_subquery_doesnt_project_unnecessary_columns_in_top_level(bool isAsync) - { - return base.Correlated_nested_subquery_doesnt_project_unnecessary_columns_in_top_level(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Correlated_nested_two_levels_up_subquery_doesnt_project_unnecessary_columns_in_top_level(bool isAsync) - { - return base.Correlated_nested_two_levels_up_subquery_doesnt_project_unnecessary_columns_in_top_level(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Include_after_SelectMany_and_reference_navigation(bool isAsync) - { - return base.Include_after_SelectMany_and_reference_navigation(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Include_after_SelectMany_and_reference_navigation_with_another_SelectMany_with_Distinct(bool isAsync) - { - return base.Include_after_SelectMany_and_reference_navigation_with_another_SelectMany_with_Distinct(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Include_collection_with_multiple_orderbys_complex(bool isAsync) - { - return base.Include_collection_with_multiple_orderbys_complex(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Include_collection_with_multiple_orderbys_complex_repeated(bool isAsync) - { - return base.Include_collection_with_multiple_orderbys_complex_repeated(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Include_collection_with_multiple_orderbys_member(bool isAsync) - { - return base.Include_collection_with_multiple_orderbys_member(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Include_collection_with_multiple_orderbys_methodcall(bool isAsync) - { - return base.Include_collection_with_multiple_orderbys_methodcall(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Include_collection_with_multiple_orderbys_property(bool isAsync) - { - return base.Include_collection_with_multiple_orderbys_property(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Include_nested_with_optional_navigation(bool isAsync) - { - return base.Include_nested_with_optional_navigation(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Include_reference_collection_order_by_reference_navigation(bool isAsync) - { - return base.Include_reference_collection_order_by_reference_navigation(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Join_navigation_in_outer_selector_translated_to_extra_join_nested(bool isAsync) - { - return base.Join_navigation_in_outer_selector_translated_to_extra_join_nested(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Join_navigation_in_outer_selector_translated_to_extra_join_nested2(bool isAsync) - { - return base.Join_navigation_in_outer_selector_translated_to_extra_join_nested2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Key_equality_navigation_converted_to_FK(bool isAsync) - { - return base.Key_equality_navigation_converted_to_FK(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Key_equality_two_conditions_on_same_navigation2(bool isAsync) - { - return base.Key_equality_two_conditions_on_same_navigation2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Key_equality_using_property_method_and_member_expression3(bool isAsync) - { - return base.Key_equality_using_property_method_and_member_expression3(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Key_equality_using_property_method_nested2(bool isAsync) - { - return base.Key_equality_using_property_method_nested2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Key_equality_using_property_method_required2(bool isAsync) - { - return base.Key_equality_using_property_method_required2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Manually_created_left_join_propagates_nullability_to_navigations(bool isAsync) - { - return base.Manually_created_left_join_propagates_nullability_to_navigations(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Member_doesnt_get_pushed_down_into_subquery_with_result_operator(bool isAsync) - { - return base.Member_doesnt_get_pushed_down_into_subquery_with_result_operator(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_complex_includes(bool isAsync) - { - return base.Multiple_complex_includes(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_complex_include_select(bool isAsync) - { - return base.Multiple_complex_include_select(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_include_with_multiple_optional_navigations(bool isAsync) - { - return base.Multiple_include_with_multiple_optional_navigations(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_optional_navigation_with_Include(bool isAsync) - { - return base.Multiple_optional_navigation_with_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_optional_navigation_with_string_based_Include(bool isAsync) - { - return base.Multiple_optional_navigation_with_string_based_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_required_navigations_with_Include(bool isAsync) - { - return base.Multiple_required_navigations_with_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_required_navigation_using_multiple_selects_with_Include(bool isAsync) - { - return base.Multiple_required_navigation_using_multiple_selects_with_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_required_navigation_using_multiple_selects_with_string_based_Include(bool isAsync) - { - return base.Multiple_required_navigation_using_multiple_selects_with_string_based_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_required_navigation_with_string_based_Include(bool isAsync) - { - return base.Multiple_required_navigation_with_string_based_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_SelectMany_calls(bool isAsync) - { - return base.Multiple_SelectMany_calls(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_SelectMany_navigation_property_followed_by_select_collection_navigation(bool isAsync) - { - return base.Multiple_SelectMany_navigation_property_followed_by_select_collection_navigation(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_SelectMany_with_Include(bool isAsync) - { - return base.Multiple_SelectMany_with_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_SelectMany_with_navigation_and_explicit_DefaultIfEmpty(bool isAsync) - { - return base.Multiple_SelectMany_with_navigation_and_explicit_DefaultIfEmpty(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multiple_SelectMany_with_string_based_Include(bool isAsync) - { - return base.Multiple_SelectMany_with_string_based_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multi_include_with_groupby_in_subquery(bool isAsync) - { - return base.Multi_include_with_groupby_in_subquery(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multi_level_include_correct_PK_is_chosen_as_the_join_predicate_for_queries_that_join_same_table_multiple_times(bool isAsync) - { - return base.Multi_level_include_correct_PK_is_chosen_as_the_join_predicate_for_queries_that_join_same_table_multiple_times(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multi_level_include_one_to_many_optional_and_one_to_many_optional_produces_valid_sql(bool isAsync) - { - return base.Multi_level_include_one_to_many_optional_and_one_to_many_optional_produces_valid_sql(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multi_level_navigation_compared_to_null(bool isAsync) - { - return base.Multi_level_navigation_compared_to_null(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Multi_level_navigation_with_same_navigation_compared_to_null(bool isAsync) - { - return base.Multi_level_navigation_with_same_navigation_compared_to_null(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigations_compared_to_each_other1(bool isAsync) - { - return base.Navigations_compared_to_each_other1(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigations_compared_to_each_other2(bool isAsync) - { - return base.Navigations_compared_to_each_other2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigations_compared_to_each_other4(bool isAsync) - { - return base.Navigations_compared_to_each_other4(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigations_compared_to_each_other5(bool isAsync) - { - return base.Navigations_compared_to_each_other5(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigation_inside_method_call_translated_to_join2(bool isAsync) - { - return base.Navigation_inside_method_call_translated_to_join2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigation_key_access_optional_comparison(bool isAsync) - { - return base.Navigation_key_access_optional_comparison(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigation_key_access_required_comparison(bool isAsync) - { - return base.Navigation_key_access_required_comparison(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigation_with_same_navigation_compared_to_null(bool isAsync) - { - return base.Navigation_with_same_navigation_compared_to_null(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Null_reference_protection_complex(bool isAsync) - { - return base.Null_reference_protection_complex(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Null_reference_protection_complex_client_eval(bool isAsync) - { - return base.Null_reference_protection_complex_client_eval(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Null_reference_protection_complex_materialization(bool isAsync) - { - return base.Null_reference_protection_complex_materialization(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Optional_navigation_propagates_nullability_to_manually_created_left_join2(bool isAsync) - { - return base.Optional_navigation_propagates_nullability_to_manually_created_left_join2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Optional_navigation_take_optional_navigation(bool isAsync) - { - return base.Optional_navigation_take_optional_navigation(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Optional_navigation_with_Include(bool isAsync) - { - return base.Optional_navigation_with_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Optional_navigation_with_Include_and_order(bool isAsync) - { - return base.Optional_navigation_with_Include_and_order(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Optional_navigation_with_Include_ThenInclude(bool isAsync) - { - return base.Optional_navigation_with_Include_ThenInclude(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Optional_navigation_with_order_by_and_Include(bool isAsync) - { - return base.Optional_navigation_with_order_by_and_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Order_by_key_of_anonymous_type_projected_navigation_doesnt_get_optimized_into_FK_access_subquery(bool isAsync) - { - return base.Order_by_key_of_anonymous_type_projected_navigation_doesnt_get_optimized_into_FK_access_subquery(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Order_by_key_of_navigation_similar_to_projected_gets_optimized_into_FK_access(bool isAsync) - { - return base.Order_by_key_of_navigation_similar_to_projected_gets_optimized_into_FK_access(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access1(bool isAsync) - { - return base.Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access1(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access2(bool isAsync) - { - return base.Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access3(bool isAsync) - { - return base.Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access3(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access_subquery(bool isAsync) - { - return base.Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access_subquery(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Projection_select_correct_table_from_subquery_when_materialization_is_not_required(bool isAsync) - { - return base.Projection_select_correct_table_from_subquery_when_materialization_is_not_required(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Projection_select_correct_table_in_subquery_when_materialization_is_not_required_in_multiple_joins(bool isAsync) - { - return base.Projection_select_correct_table_in_subquery_when_materialization_is_not_required_in_multiple_joins(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Projection_select_correct_table_with_anonymous_projection_in_subquery(bool isAsync) - { - return base.Projection_select_correct_table_with_anonymous_projection_in_subquery(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Project_collection_navigation_nested(bool isAsync) - { - return base.Project_collection_navigation_nested(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Project_collection_navigation_nested_anonymous(bool isAsync) - { - return base.Project_collection_navigation_nested_anonymous(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Project_collection_navigation_using_ef_property(bool isAsync) - { - return base.Project_collection_navigation_using_ef_property(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Project_navigation_and_collection(bool isAsync) - { - return base.Project_navigation_and_collection(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Query_source_materialization_bug_4547(bool isAsync) - { - return base.Query_source_materialization_bug_4547(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Required_navigation_on_a_subquery_with_complex_projection_and_First(bool isAsync) - { - return base.Required_navigation_on_a_subquery_with_complex_projection_and_First(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Required_navigation_with_Include(bool isAsync) - { - return base.Required_navigation_with_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Required_navigation_with_Include_ThenInclude(bool isAsync) - { - return base.Required_navigation_with_Include_ThenInclude(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_navigation_comparison2(bool isAsync) - { - return base.SelectMany_navigation_comparison2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_navigation_property_with_another_navigation_in_subquery(bool isAsync) - { - return base.SelectMany_navigation_property_with_another_navigation_in_subquery(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_nested_navigation_property_optional_and_projection(bool isAsync) - { - return base.SelectMany_nested_navigation_property_optional_and_projection(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_nested_navigation_property_required(bool isAsync) - { - return base.SelectMany_nested_navigation_property_required(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_Include1(bool isAsync) - { - return base.SelectMany_with_Include1(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_Include2(bool isAsync) - { - return base.SelectMany_with_Include2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_Include_and_order_by(bool isAsync) - { - return base.SelectMany_with_Include_and_order_by(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_Include_ThenInclude(bool isAsync) - { - return base.SelectMany_with_Include_ThenInclude(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_followed_by_Select_required_navigation_using_different_navs(bool isAsync) - { - return base.SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_followed_by_Select_required_navigation_using_different_navs(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_followed_by_Select_required_navigation_using_same_navs(bool isAsync) - { - return base.SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_followed_by_Select_required_navigation_using_same_navs(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany3(bool isAsync) - { - return base.SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany3(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany4(bool isAsync) - { - return base.SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany4(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_nested_navigation_and_explicit_DefaultIfEmpty(bool isAsync) - { - return base.SelectMany_with_nested_navigation_and_explicit_DefaultIfEmpty(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_nested_navigation_filter_and_explicit_DefaultIfEmpty(bool isAsync) - { - return base.SelectMany_with_nested_navigation_filter_and_explicit_DefaultIfEmpty(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_nested_required_navigation_filter_and_explicit_DefaultIfEmpty(bool isAsync) - { - return base.SelectMany_with_nested_required_navigation_filter_and_explicit_DefaultIfEmpty(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_order_by_and_Include(bool isAsync) - { - return base.SelectMany_with_order_by_and_Include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_string_based_Include1(bool isAsync) - { - return base.SelectMany_with_string_based_Include1(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_string_based_Include2(bool isAsync) - { - return base.SelectMany_with_string_based_Include2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Select_multiple_nav_prop_optional_required(bool isAsync) - { - return base.Select_multiple_nav_prop_optional_required(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Select_multiple_nav_prop_reference_optional(bool isAsync) - { - return base.Select_multiple_nav_prop_reference_optional(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Select_multiple_nav_prop_reference_required(bool isAsync) - { - return base.Select_multiple_nav_prop_reference_required(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Select_multiple_nav_prop_reference_required2(bool isAsync) - { - return base.Select_multiple_nav_prop_reference_required2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Select_nav_prop_reference_optional3(bool isAsync) - { - return base.Select_nav_prop_reference_optional3(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Simple_level1_level2_GroupBy_Count(bool isAsync) - { - return base.Simple_level1_level2_GroupBy_Count(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Simple_level1_level2_GroupBy_Having_Count(bool isAsync) - { - return base.Simple_level1_level2_GroupBy_Having_Count(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Simple_level1_level2_include(bool isAsync) - { - return base.Simple_level1_level2_include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Simple_level1_level2_level3_include(bool isAsync) - { - return base.Simple_level1_level2_level3_include(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task String_include_multiple_derived_collection_navigation_with_same_name_and_different_type_nested_also_includes_partially_matching_navigation_chains(bool isAsync) - { - return base.String_include_multiple_derived_collection_navigation_with_same_name_and_different_type_nested_also_includes_partially_matching_navigation_chains(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task String_include_multiple_derived_navigations_complex(bool isAsync) - { - return base.String_include_multiple_derived_navigations_complex(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task String_include_multiple_derived_navigation_with_same_name_and_different_type_nested_also_includes_partially_matching_navigation_chains(bool isAsync) - { - return base.String_include_multiple_derived_navigation_with_same_name_and_different_type_nested_also_includes_partially_matching_navigation_chains(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_complex_predicate_with_with_nav_prop_and_OrElse1(bool isAsync) - { - return base.Where_complex_predicate_with_with_nav_prop_and_OrElse1(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_complex_predicate_with_with_nav_prop_and_OrElse2(bool isAsync) - { - return base.Where_complex_predicate_with_with_nav_prop_and_OrElse2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_complex_predicate_with_with_nav_prop_and_OrElse3(bool isAsync) - { - return base.Where_complex_predicate_with_with_nav_prop_and_OrElse3(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_complex_predicate_with_with_nav_prop_and_OrElse4(bool isAsync) - { - return base.Where_complex_predicate_with_with_nav_prop_and_OrElse4(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_multiple_nav_prop_optional_required(bool isAsync) - { - return base.Where_multiple_nav_prop_optional_required(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_multiple_nav_prop_reference_optional_compared_to_null1(bool isAsync) - { - return base.Where_multiple_nav_prop_reference_optional_compared_to_null1(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_multiple_nav_prop_reference_optional_compared_to_null2(bool isAsync) - { - return base.Where_multiple_nav_prop_reference_optional_compared_to_null2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_multiple_nav_prop_reference_optional_compared_to_null3(bool isAsync) - { - return base.Where_multiple_nav_prop_reference_optional_compared_to_null3(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_multiple_nav_prop_reference_optional_compared_to_null4(bool isAsync) - { - return base.Where_multiple_nav_prop_reference_optional_compared_to_null4(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_multiple_nav_prop_reference_optional_compared_to_null5(bool isAsync) - { - return base.Where_multiple_nav_prop_reference_optional_compared_to_null5(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_multiple_nav_prop_reference_optional_member_compared_to_null(bool isAsync) - { - return base.Where_multiple_nav_prop_reference_optional_member_compared_to_null(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_multiple_nav_prop_reference_optional_member_compared_to_value(bool isAsync) - { - return base.Where_multiple_nav_prop_reference_optional_member_compared_to_value(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_navigation_property_to_collection2(bool isAsync) - { - return base.Where_navigation_property_to_collection2(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_navigation_property_to_collection_of_original_entity_type(bool isAsync) - { - return base.Where_navigation_property_to_collection_of_original_entity_type(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_on_multilevel_reference_in_subquery_with_outer_projection(bool isAsync) - { - return base.Where_on_multilevel_reference_in_subquery_with_outer_projection(isAsync); - } - - [GeneratedNameTooLongFact] - public override void Include19() - { - base.Include19(); - } - - [GeneratedNameTooLongFact] - public override void IncludeCollection6_2() - { - base.IncludeCollection6_2(); - } - - [GeneratedNameTooLongFact] - public override void IncludeCollection6_3() - { - base.IncludeCollection6_3(); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Join_navigation_deeply_nested_required(bool isAsync) - { - return base.Join_navigation_deeply_nested_required(isAsync); - } - - [GeneratedNameTooLongTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Join_navigations_in_inner_selector_translated_without_collision(bool isAsync) - { - return base.Join_navigations_in_inner_selector_translated_without_collision(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Project_collection_navigation_nested_with_take(bool isAsync) - { - return base.Project_collection_navigation_nested_with_take(isAsync); - } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/DbFunctionsIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/DbFunctionsIBTest.cs deleted file mode 100644 index 753100d..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/DbFunctionsIBTest.cs +++ /dev/null @@ -1,47 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using System.Linq; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.TestUtilities; -using Xunit; -using Xunit.Abstractions; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class DbFunctionsIBTest : DbFunctionsTestBase> - { - public DbFunctionsIBTest(NorthwindQueryIBFixture fixture, ITestOutputHelper testOutputHelper) - : base(fixture) - { } - - public override void Like_literal() - { - // yeah, becase MS SQL and it's default collate - // and nobody in EF Core team cares - using (var context = CreateContext()) - { - var count = context.Customers.Count(c => EF.Functions.Like(c.ContactName, "%M%")); - Assert.Equal(19, count); - } - } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FiltersIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FiltersIBTest.cs deleted file mode 100644 index a8de0f1..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FiltersIBTest.cs +++ /dev/null @@ -1,32 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using Microsoft.EntityFrameworkCore.Query; -using Xunit.Abstractions; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class FiltersIBTest : FiltersTestBase> - { - public FiltersIBTest(NorthwindQueryIBFixture fixture, ITestOutputHelper testOutputHelper) - : base(fixture) - { } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FiltersInheritanceIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FiltersInheritanceIBTest.cs deleted file mode 100644 index a4aaa2c..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FiltersInheritanceIBTest.cs +++ /dev/null @@ -1,31 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using Microsoft.EntityFrameworkCore.Query; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class FiltersInheritanceIBTest : FiltersInheritanceTestBase - { - public FiltersInheritanceIBTest(FiltersInheritanceIBFixture fixture) - : base(fixture) - { } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FromSqlQueryIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FromSqlQueryIBTest.cs index 26fe179..d16ed2f 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FromSqlQueryIBTest.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FromSqlQueryIBTest.cs @@ -18,12 +18,15 @@ //$Authors = Jiri Cincura (jiri@cincura.net) +using System; using System.Data.Common; using System.Linq; +using System.Reflection.Metadata; +using System.Threading.Tasks; using InterBaseSql.Data.InterBaseClient; using InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Helpers; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.TestModels.Northwind; @@ -38,41 +41,133 @@ public FromSqlQueryIBTest(NorthwindQueryIBFixture fixture) : base(fixture) { } - [NotSupportedOnInterBaseFact] - public override void Bad_data_error_handling_invalid_cast_key() + protected override DbParameter CreateDbParameter(string name, object value) + => new IBParameter + { + ParameterName = name, + Value = value + }; + + [Theory] + [MemberData(nameof(IsAsyncData))] + public override async Task FromSql_Count_used_twice_without_parameters(bool async) { - base.Bad_data_error_handling_invalid_cast_key(); + using var context = CreateContext(); + + var query = context.Set() + .FromSqlRaw(NormalizeDelimitersInRawString("SELECT 'ALFKI' AS [CustomerID] FROM RDB$DATABASE")) + .IgnoreQueryFilters(); + + var result1 = async + ? await query.CountAsync() > 0 + : query.Count() > 0; + + var result2 = async + ? await query.CountAsync() > 0 + : query.Count() > 0; } - [NotSupportedOnInterBaseFact] - public override void Bad_data_error_handling_invalid_cast_no_tracking() + [Theory] + [MemberData(nameof(IsAsyncData))] + public override async Task FromSql_Count_used_twice_with_parameters(bool async) { - base.Bad_data_error_handling_invalid_cast_no_tracking(); + using var context = CreateContext(); + + var query = context.Set() + .FromSqlRaw(NormalizeDelimitersInRawString("SELECT CAST({0} AS CHAR(5)) AS [CustomerID] FROM RDB$DATABASE"), "ALFKI") + .IgnoreQueryFilters(); + + var result1 = async + ? await query.CountAsync() > 0 + : query.Count() > 0; + + var result2 = async + ? await query.CountAsync() > 0 + : query.Count() > 0; } - [NotSupportedOnInterBaseFact] - public override void Bad_data_error_handling_invalid_cast_projection() + [Theory] + [MemberData(nameof(IsAsyncData))] + public override async Task FromSql_used_twice_without_parameters(bool async) { - base.Bad_data_error_handling_invalid_cast_projection(); + using var context = CreateContext(); + + var query = context.Set() + .FromSqlRaw(NormalizeDelimitersInRawString("SELECT 'ALFKI' AS [CustomerID] FROM RDB$DATABASE")) + .IgnoreQueryFilters(); + + var result1 = async + ? await query.AnyAsync() + : query.Any(); + + Assert.Equal( + RelationalStrings.QueryFromSqlInsideExists, + async + ? (await Assert.ThrowsAsync(() => query.AnyAsync())).Message + : Assert.Throws(() => query.Any()).Message); } - [NotSupportedOnInterBaseFact] - public override void Bad_data_error_handling_invalid_cast() + [Theory] + [MemberData(nameof(IsAsyncData))] + public override async Task FromSql_used_twice_with_parameters(bool async) { - base.Bad_data_error_handling_invalid_cast(); + using var context = CreateContext(); + + var query = context.Set() + .FromSqlRaw(NormalizeDelimitersInRawString("SELECT CAST({0} AS CHAR(5)) AS [CustomerID] FROM RDB$DATABASE"), "ALFKI") + .IgnoreQueryFilters(); + + var result1 = async + ? await query.AnyAsync() + : query.Any(); + + Assert.Equal( + RelationalStrings.QueryFromSqlInsideExists, + async + ? (await Assert.ThrowsAsync(() => query.AnyAsync())).Message + : Assert.Throws(() => query.Any()).Message); } - [DoesNotHaveTheDataFact] - public override void FromSqlRaw_queryable_simple_projection_composed() + [Theory(Skip = "Provider does the casting.")] + [MemberData(nameof(IsAsyncData))] + public override Task Bad_data_error_handling_invalid_cast(bool async) { - base.FromSqlRaw_queryable_simple_projection_composed(); + return base.Bad_data_error_handling_invalid_cast(async); } - protected override DbParameter CreateDbParameter(string name, object value) - => new IBParameter - { - ParameterName = name, - Value = value - }; + [Theory(Skip = "Provider does the casting.")] + [MemberData(nameof(IsAsyncData))] + public override Task Bad_data_error_handling_invalid_cast_key(bool async) + { + return base.Bad_data_error_handling_invalid_cast_key(async); + } + + [Theory(Skip = "Provider does the casting.")] + [MemberData(nameof(IsAsyncData))] + public override Task Bad_data_error_handling_invalid_cast_no_tracking(bool async) + { + return base.Bad_data_error_handling_invalid_cast_no_tracking(async); + } + + [Theory(Skip = "Provider does the casting.")] + [MemberData(nameof(IsAsyncData))] + public override Task Bad_data_error_handling_invalid_cast_projection(bool async) + { + return base.Bad_data_error_handling_invalid_cast_projection(async); + } + + [Theory(Skip = "Provider does the casting.")] + [MemberData(nameof(IsAsyncData))] + public override Task FromSqlRaw_queryable_simple_projection_composed(bool async) + { + return base.FromSqlRaw_queryable_simple_projection_composed(async); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Multiple_occurrences_of_FromSql_with_db_parameter_adds_parameter_only_once(bool async) + { + return base.Multiple_occurrences_of_FromSql_with_db_parameter_adds_parameter_only_once(async); + } } -} +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FromSqlSprocQueryIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FromSqlSprocQueryIBTest.cs index f8c0609..5e739bb 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FromSqlSprocQueryIBTest.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FromSqlSprocQueryIBTest.cs @@ -25,183 +25,182 @@ using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query; + +public class FromSqlSprocQueryIBTest : FromSqlSprocQueryTestBase> { - public class FromSqlSprocQueryIBTest : FromSqlSprocQueryTestBase> - { - public FromSqlSprocQueryIBTest(NorthwindQueryIBFixture fixture) - : base(fixture) - { } - - protected override string TenMostExpensiveProductsSproc => throw new NotSupportedException(); - protected override string CustomerOrderHistorySproc => throw new NotSupportedException(); - - [DoesNotHaveTheDataTheory] - [InlineData(false)] - [InlineData(true)] - public override Task From_sql_queryable_select_and_stored_procedure(bool async) - { - return base.From_sql_queryable_select_and_stored_procedure(async); - } - - [DoesNotHaveTheDataTheory] - [InlineData(false)] - [InlineData(true)] - public override Task From_sql_queryable_select_and_stored_procedure_on_client(bool async) - { - return base.From_sql_queryable_select_and_stored_procedure_on_client(async); - } - - [DoesNotHaveTheDataTheory] - [InlineData(false)] - [InlineData(true)] - public override Task From_sql_queryable_stored_procedure(bool async) - { - return base.From_sql_queryable_stored_procedure(async); - } - - [DoesNotHaveTheDataTheory] - [InlineData(false)] - [InlineData(true)] - public override Task From_sql_queryable_stored_procedure_and_select(bool async) - { - return base.From_sql_queryable_stored_procedure_and_select(async); - } - - [DoesNotHaveTheDataTheory] - [InlineData(false)] - [InlineData(true)] - public override Task From_sql_queryable_stored_procedure_and_select_on_client(bool async) - { - return base.From_sql_queryable_stored_procedure_and_select_on_client(async); - } - - [DoesNotHaveTheDataTheory] - [InlineData(false)] - [InlineData(true)] - public override Task From_sql_queryable_stored_procedure_composed(bool async) - { - return base.From_sql_queryable_stored_procedure_composed(async); - } - - [DoesNotHaveTheDataTheory] - [InlineData(false)] - [InlineData(true)] - public override Task From_sql_queryable_stored_procedure_composed_on_client(bool async) - { - return base.From_sql_queryable_stored_procedure_composed_on_client(async); - } - - [DoesNotHaveTheDataTheory] - [InlineData(false)] - [InlineData(true)] - public override Task From_sql_queryable_stored_procedure_min(bool async) - { - return base.From_sql_queryable_stored_procedure_min(async); - } - - [DoesNotHaveTheDataTheory] - [InlineData(false)] - [InlineData(true)] - public override Task From_sql_queryable_stored_procedure_min_on_client(bool async) - { - return base.From_sql_queryable_stored_procedure_min_on_client(async); - } - - [DoesNotHaveTheDataTheory] - [InlineData(false)] - [InlineData(true)] - public override Task From_sql_queryable_stored_procedure_projection(bool async) - { - return base.From_sql_queryable_stored_procedure_projection(async); - } - - [DoesNotHaveTheDataTheory] - [InlineData(false)] - [InlineData(true)] - public override Task From_sql_queryable_stored_procedure_re_projection(bool async) - { - return base.From_sql_queryable_stored_procedure_re_projection(async); - } - - [DoesNotHaveTheDataTheory] - [InlineData(false)] - [InlineData(true)] - public override Task From_sql_queryable_stored_procedure_re_projection_on_client(bool async) - { - return base.From_sql_queryable_stored_procedure_re_projection_on_client(async); - } - - [DoesNotHaveTheDataTheory] - [InlineData(false)] - [InlineData(true)] - public override Task From_sql_queryable_stored_procedure_take(bool async) - { - return base.From_sql_queryable_stored_procedure_take(async); - } - - [DoesNotHaveTheDataTheory] - [InlineData(false)] - [InlineData(true)] - public override Task From_sql_queryable_stored_procedure_take_on_client(bool async) - { - return base.From_sql_queryable_stored_procedure_take_on_client(async); - } - - [DoesNotHaveTheDataTheory] - [InlineData(false)] - [InlineData(true)] - public override Task From_sql_queryable_stored_procedure_with_include_throws(bool async) - { - return base.From_sql_queryable_stored_procedure_with_include_throws(async); - } - - [DoesNotHaveTheDataTheory] - [InlineData(false)] - [InlineData(true)] - public override Task From_sql_queryable_stored_procedure_with_parameter(bool async) - { - return base.From_sql_queryable_stored_procedure_with_parameter(async); - } - - [DoesNotHaveTheDataTheory] - [InlineData(false)] - [InlineData(true)] - public override Task From_sql_queryable_stored_procedure_with_parameter_composed(bool async) - { - return base.From_sql_queryable_stored_procedure_with_parameter_composed(async); - } - - [DoesNotHaveTheDataTheory] - [InlineData(false)] - [InlineData(true)] - public override Task From_sql_queryable_stored_procedure_with_parameter_composed_on_client(bool async) - { - return base.From_sql_queryable_stored_procedure_with_parameter_composed_on_client(async); - } - - [DoesNotHaveTheDataTheory] - [InlineData(false)] - [InlineData(true)] - public override Task From_sql_queryable_stored_procedure_with_tag(bool async) - { - return base.From_sql_queryable_stored_procedure_with_tag(async); - } - - [DoesNotHaveTheDataTheory] - [InlineData(false)] - [InlineData(true)] - public override Task From_sql_queryable_with_multiple_stored_procedures(bool async) - { - return base.From_sql_queryable_with_multiple_stored_procedures(async); - } - - [DoesNotHaveTheDataTheory] - [InlineData(false)] - [InlineData(true)] - public override Task From_sql_queryable_with_multiple_stored_procedures_on_client(bool async) - { - return base.From_sql_queryable_with_multiple_stored_procedures_on_client(async); - } + public FromSqlSprocQueryIBTest(NorthwindQueryIBFixture fixture) + : base(fixture) + { } + + protected override string TenMostExpensiveProductsSproc => throw new NotSupportedException(); + protected override string CustomerOrderHistorySproc => throw new NotSupportedException(); + + [DoesNotHaveTheDataTheory] + [InlineData(false)] + [InlineData(true)] + public override Task From_sql_queryable_select_and_stored_procedure(bool async) + { + return base.From_sql_queryable_select_and_stored_procedure(async); + } + + [DoesNotHaveTheDataTheory] + [InlineData(false)] + [InlineData(true)] + public override Task From_sql_queryable_select_and_stored_procedure_on_client(bool async) + { + return base.From_sql_queryable_select_and_stored_procedure_on_client(async); + } + + [DoesNotHaveTheDataTheory] + [InlineData(false)] + [InlineData(true)] + public override Task From_sql_queryable_stored_procedure(bool async) + { + return base.From_sql_queryable_stored_procedure(async); + } + + [DoesNotHaveTheDataTheory] + [InlineData(false)] + [InlineData(true)] + public override Task From_sql_queryable_stored_procedure_and_select(bool async) + { + return base.From_sql_queryable_stored_procedure_and_select(async); + } + + [DoesNotHaveTheDataTheory] + [InlineData(false)] + [InlineData(true)] + public override Task From_sql_queryable_stored_procedure_and_select_on_client(bool async) + { + return base.From_sql_queryable_stored_procedure_and_select_on_client(async); + } + + [DoesNotHaveTheDataTheory] + [InlineData(false)] + [InlineData(true)] + public override Task From_sql_queryable_stored_procedure_composed(bool async) + { + return base.From_sql_queryable_stored_procedure_composed(async); + } + + [DoesNotHaveTheDataTheory] + [InlineData(false)] + [InlineData(true)] + public override Task From_sql_queryable_stored_procedure_composed_on_client(bool async) + { + return base.From_sql_queryable_stored_procedure_composed_on_client(async); + } + + [DoesNotHaveTheDataTheory] + [InlineData(false)] + [InlineData(true)] + public override Task From_sql_queryable_stored_procedure_min(bool async) + { + return base.From_sql_queryable_stored_procedure_min(async); + } + + [DoesNotHaveTheDataTheory] + [InlineData(false)] + [InlineData(true)] + public override Task From_sql_queryable_stored_procedure_min_on_client(bool async) + { + return base.From_sql_queryable_stored_procedure_min_on_client(async); + } + + [DoesNotHaveTheDataTheory] + [InlineData(false)] + [InlineData(true)] + public override Task From_sql_queryable_stored_procedure_projection(bool async) + { + return base.From_sql_queryable_stored_procedure_projection(async); + } + + [DoesNotHaveTheDataTheory] + [InlineData(false)] + [InlineData(true)] + public override Task From_sql_queryable_stored_procedure_re_projection(bool async) + { + return base.From_sql_queryable_stored_procedure_re_projection(async); + } + + [DoesNotHaveTheDataTheory] + [InlineData(false)] + [InlineData(true)] + public override Task From_sql_queryable_stored_procedure_re_projection_on_client(bool async) + { + return base.From_sql_queryable_stored_procedure_re_projection_on_client(async); + } + + [DoesNotHaveTheDataTheory] + [InlineData(false)] + [InlineData(true)] + public override Task From_sql_queryable_stored_procedure_take(bool async) + { + return base.From_sql_queryable_stored_procedure_take(async); + } + + [DoesNotHaveTheDataTheory] + [InlineData(false)] + [InlineData(true)] + public override Task From_sql_queryable_stored_procedure_take_on_client(bool async) + { + return base.From_sql_queryable_stored_procedure_take_on_client(async); + } + + [DoesNotHaveTheDataTheory] + [InlineData(false)] + [InlineData(true)] + public override Task From_sql_queryable_stored_procedure_with_include_throws(bool async) + { + return base.From_sql_queryable_stored_procedure_with_include_throws(async); + } + + [DoesNotHaveTheDataTheory] + [InlineData(false)] + [InlineData(true)] + public override Task From_sql_queryable_stored_procedure_with_parameter(bool async) + { + return base.From_sql_queryable_stored_procedure_with_parameter(async); + } + + [DoesNotHaveTheDataTheory] + [InlineData(false)] + [InlineData(true)] + public override Task From_sql_queryable_stored_procedure_with_parameter_composed(bool async) + { + return base.From_sql_queryable_stored_procedure_with_parameter_composed(async); + } + + [DoesNotHaveTheDataTheory] + [InlineData(false)] + [InlineData(true)] + public override Task From_sql_queryable_stored_procedure_with_parameter_composed_on_client(bool async) + { + return base.From_sql_queryable_stored_procedure_with_parameter_composed_on_client(async); + } + + [DoesNotHaveTheDataTheory] + [InlineData(false)] + [InlineData(true)] + public override Task From_sql_queryable_stored_procedure_with_tag(bool async) + { + return base.From_sql_queryable_stored_procedure_with_tag(async); + } + + [DoesNotHaveTheDataTheory] + [InlineData(false)] + [InlineData(true)] + public override Task From_sql_queryable_with_multiple_stored_procedures(bool async) + { + return base.From_sql_queryable_with_multiple_stored_procedures(async); + } + + [DoesNotHaveTheDataTheory] + [InlineData(false)] + [InlineData(true)] + public override Task From_sql_queryable_with_multiple_stored_procedures_on_client(bool async) + { + return base.From_sql_queryable_with_multiple_stored_procedures_on_client(async); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FunkyDataQueryIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FunkyDataQueryIBTest.cs index d1e88b6..bf05aac 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FunkyDataQueryIBTest.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FunkyDataQueryIBTest.cs @@ -26,23 +26,22 @@ using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query; + +public class FunkyDataQueryIBTest : FunkyDataQueryTestBase { - public class FunkyDataQueryIBTest : FunkyDataQueryTestBase + public FunkyDataQueryIBTest(FunkyDataQueryIBFixture fixture) + : base(fixture) + { } + + public class FunkyDataQueryIBFixture : FunkyDataQueryFixtureBase { - public FunkyDataQueryIBTest(FunkyDataQueryIBFixture fixture) - : base(fixture) - { } + protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; - public class FunkyDataQueryIBFixture : FunkyDataQueryFixtureBase + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) { - protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; - - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - base.OnModelCreating(modelBuilder, context); - ModelHelpers.SetStringLengths(modelBuilder); - } + base.OnModelCreating(modelBuilder, context); + ModelHelpers.SetStringLengths(modelBuilder); } } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/GearsOfWarFromSqlQueryIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/GearsOfWarFromSqlQueryIBTest.cs index ad6354a..2b913af 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/GearsOfWarFromSqlQueryIBTest.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/GearsOfWarFromSqlQueryIBTest.cs @@ -20,12 +20,11 @@ using Microsoft.EntityFrameworkCore.Query; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query; + +public class GearsOfWarFromSqlQueryIBTest : GearsOfWarFromSqlQueryTestBase { - public class GearsOfWarFromSqlQueryIBTest : GearsOfWarFromSqlQueryTestBase - { - public GearsOfWarFromSqlQueryIBTest(GearsOfWarQueryIBFixture fixture) - : base(fixture) - { } - } + public GearsOfWarFromSqlQueryIBTest(GearsOfWarQueryIBFixture fixture) + : base(fixture) + { } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/GearsOfWarQueryIBFixture.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/GearsOfWarQueryIBFixture.cs index 8e02212..bb4a861 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/GearsOfWarQueryIBFixture.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/GearsOfWarQueryIBFixture.cs @@ -24,16 +24,15 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query; + public class GearsOfWarQueryIBFixture : GearsOfWarQueryRelationalFixture { protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - base.OnModelCreating(modelBuilder, context); - ModelHelpers.SetStringLengths(modelBuilder); - } + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + base.OnModelCreating(modelBuilder, context); + ModelHelpers.SetStringLengths(modelBuilder); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/GearsOfWarQueryIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/GearsOfWarQueryIBTest.cs index bc327ce..a438c9d 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/GearsOfWarQueryIBTest.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/GearsOfWarQueryIBTest.cs @@ -18,220 +18,375 @@ //$Authors = Jiri Cincura (jiri@cincura.net) +using System.Linq; using System.Threading.Tasks; using InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Helpers; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.TestModels.GearsOfWarModel; using Xunit; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query; + +public class GearsOfWarQueryIBTest : GearsOfWarQueryRelationalTestBase { - public class GearsOfWarQueryIBTest : GearsOfWarQueryTestBase - { - public GearsOfWarQueryIBTest(GearsOfWarQueryIBFixture fixture) - : base(fixture) - { } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task DateTimeOffset_DateAdd_AddDays(bool isAsync) - { - return base.DateTimeOffset_DateAdd_AddDays(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task DateTimeOffset_DateAdd_AddHours(bool isAsync) - { - return base.DateTimeOffset_DateAdd_AddHours(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task DateTimeOffset_DateAdd_AddMilliseconds(bool isAsync) - { - return base.DateTimeOffset_DateAdd_AddMilliseconds(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task DateTimeOffset_DateAdd_AddMinutes(bool isAsync) - { - return base.DateTimeOffset_DateAdd_AddMinutes(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task DateTimeOffset_DateAdd_AddMonths(bool isAsync) - { - return base.DateTimeOffset_DateAdd_AddMonths(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task DateTimeOffset_DateAdd_AddSeconds(bool isAsync) - { - return base.DateTimeOffset_DateAdd_AddSeconds(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task DateTimeOffset_DateAdd_AddYears(bool isAsync) - { - return base.DateTimeOffset_DateAdd_AddYears(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_datetimeoffset_date_component(bool isAsync) - { - return base.Where_datetimeoffset_date_component(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_datetimeoffset_dayofyear_component(bool isAsync) - { - return base.Where_datetimeoffset_dayofyear_component(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_datetimeoffset_day_component(bool isAsync) - { - return base.Where_datetimeoffset_day_component(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_datetimeoffset_hour_component(bool isAsync) - { - return base.Where_datetimeoffset_hour_component(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_datetimeoffset_millisecond_component(bool isAsync) - { - return base.Where_datetimeoffset_millisecond_component(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_datetimeoffset_minute_component(bool isAsync) - { - return base.Where_datetimeoffset_minute_component(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_datetimeoffset_month_component(bool isAsync) - { - return base.Where_datetimeoffset_month_component(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_datetimeoffset_now(bool isAsync) - { - return base.Where_datetimeoffset_now(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_datetimeoffset_second_component(bool isAsync) - { - return base.Where_datetimeoffset_second_component(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_datetimeoffset_utcnow(bool isAsync) - { - return base.Where_datetimeoffset_utcnow(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_datetimeoffset_year_component(bool isAsync) - { - return base.Where_datetimeoffset_year_component(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Correlated_collections_inner_subquery_predicate_references_outer_qsre(bool isAsync) - { - return base.Correlated_collections_inner_subquery_predicate_references_outer_qsre(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Correlated_collections_inner_subquery_selector_references_outer_qsre(bool isAsync) - { - return base.Correlated_collections_inner_subquery_selector_references_outer_qsre(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Correlated_collections_nested_inner_subquery_references_outer_qsre_one_level_up(bool isAsync) - { - return base.Correlated_collections_nested_inner_subquery_references_outer_qsre_one_level_up(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Correlated_collections_nested_inner_subquery_references_outer_qsre_two_levels_up(bool isAsync) - { - return base.Correlated_collections_nested_inner_subquery_references_outer_qsre_two_levels_up(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task DateTimeOffset_Contains_Less_than_Greater_than(bool isAsync) - { - return base.DateTimeOffset_Contains_Less_than_Greater_than(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Outer_parameter_in_group_join_with_DefaultIfEmpty(bool isAsync) - { - return base.Outer_parameter_in_group_join_with_DefaultIfEmpty(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Outer_parameter_in_join_key(bool isAsync) - { - return base.Outer_parameter_in_join_key(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Outer_parameter_in_join_key_inner_and_outer(bool isAsync) - { - return base.Outer_parameter_in_join_key_inner_and_outer(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Project_collection_navigation_nested_with_take_composite_key(bool isAsync) - { - return base.Project_collection_navigation_nested_with_take_composite_key(isAsync); - } - - [Theory(Skip = "Different implicit ordering on InterBase.")] - [MemberData(nameof(IsAsyncData))] - public override Task Take_without_orderby_followed_by_orderBy_is_pushed_down1(bool isAsync) - { - return base.Take_without_orderby_followed_by_orderBy_is_pushed_down1(isAsync); - } - - [Theory(Skip = "Different implicit ordering on InterBase.")] - [MemberData(nameof(IsAsyncData))] - public override Task Take_without_orderby_followed_by_orderBy_is_pushed_down2(bool isAsync) - { - return base.Take_without_orderby_followed_by_orderBy_is_pushed_down2(isAsync); - } + public GearsOfWarQueryIBTest(GearsOfWarQueryIBFixture fixture) + : base(fixture) + { } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task DateTimeOffset_DateAdd_AddDays(bool isAsync) + { + return base.DateTimeOffset_DateAdd_AddDays(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task DateTimeOffset_DateAdd_AddHours(bool isAsync) + { + return base.DateTimeOffset_DateAdd_AddHours(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task DateTimeOffset_DateAdd_AddMilliseconds(bool isAsync) + { + return base.DateTimeOffset_DateAdd_AddMilliseconds(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task DateTimeOffset_DateAdd_AddMinutes(bool isAsync) + { + return base.DateTimeOffset_DateAdd_AddMinutes(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task DateTimeOffset_DateAdd_AddMonths(bool isAsync) + { + return base.DateTimeOffset_DateAdd_AddMonths(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task DateTimeOffset_DateAdd_AddSeconds(bool isAsync) + { + return base.DateTimeOffset_DateAdd_AddSeconds(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task DateTimeOffset_DateAdd_AddYears(bool isAsync) + { + return base.DateTimeOffset_DateAdd_AddYears(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_datetimeoffset_date_component(bool isAsync) + { + return base.Where_datetimeoffset_date_component(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_datetimeoffset_dayofyear_component(bool isAsync) + { + return base.Where_datetimeoffset_dayofyear_component(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_datetimeoffset_day_component(bool isAsync) + { + return base.Where_datetimeoffset_day_component(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_datetimeoffset_hour_component(bool isAsync) + { + return base.Where_datetimeoffset_hour_component(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_datetimeoffset_millisecond_component(bool isAsync) + { + return base.Where_datetimeoffset_millisecond_component(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_datetimeoffset_minute_component(bool isAsync) + { + return base.Where_datetimeoffset_minute_component(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_datetimeoffset_month_component(bool isAsync) + { + return base.Where_datetimeoffset_month_component(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_datetimeoffset_now(bool isAsync) + { + return base.Where_datetimeoffset_now(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_datetimeoffset_second_component(bool isAsync) + { + return base.Where_datetimeoffset_second_component(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_datetimeoffset_utcnow(bool isAsync) + { + return base.Where_datetimeoffset_utcnow(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_datetimeoffset_year_component(bool isAsync) + { + return base.Where_datetimeoffset_year_component(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Correlated_collections_inner_subquery_predicate_references_outer_qsre(bool isAsync) + { + return base.Correlated_collections_inner_subquery_predicate_references_outer_qsre(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Correlated_collections_inner_subquery_selector_references_outer_qsre(bool isAsync) + { + return base.Correlated_collections_inner_subquery_selector_references_outer_qsre(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Correlated_collections_nested_inner_subquery_references_outer_qsre_one_level_up(bool isAsync) + { + return base.Correlated_collections_nested_inner_subquery_references_outer_qsre_one_level_up(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Correlated_collections_nested_inner_subquery_references_outer_qsre_two_levels_up(bool isAsync) + { + return base.Correlated_collections_nested_inner_subquery_references_outer_qsre_two_levels_up(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task DateTimeOffset_Contains_Less_than_Greater_than(bool isAsync) + { + return base.DateTimeOffset_Contains_Less_than_Greater_than(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Outer_parameter_in_group_join_with_DefaultIfEmpty(bool isAsync) + { + return base.Outer_parameter_in_group_join_with_DefaultIfEmpty(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Outer_parameter_in_join_key(bool isAsync) + { + return base.Outer_parameter_in_join_key(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Outer_parameter_in_join_key_inner_and_outer(bool isAsync) + { + return base.Outer_parameter_in_join_key_inner_and_outer(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Project_collection_navigation_nested_with_take_composite_key(bool isAsync) + { + return base.Project_collection_navigation_nested_with_take_composite_key(isAsync); + } + + [Theory(Skip = "Different implicit ordering on InterBase.")] + [MemberData(nameof(IsAsyncData))] + public override Task Take_without_orderby_followed_by_orderBy_is_pushed_down1(bool isAsync) + { + return base.Take_without_orderby_followed_by_orderBy_is_pushed_down1(isAsync); + } + + [Theory(Skip = "Different implicit ordering on InterBase.")] + [MemberData(nameof(IsAsyncData))] + public override Task Take_without_orderby_followed_by_orderBy_is_pushed_down2(bool isAsync) + { + return base.Take_without_orderby_followed_by_orderBy_is_pushed_down2(isAsync); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Subquery_projecting_non_nullable_scalar_contains_non_nullable_value_doesnt_need_null_expansion(bool async) + { + return base.Subquery_projecting_non_nullable_scalar_contains_non_nullable_value_doesnt_need_null_expansion(async); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Subquery_projecting_non_nullable_scalar_contains_non_nullable_value_doesnt_need_null_expansion_negated(bool async) + { + return base.Subquery_projecting_non_nullable_scalar_contains_non_nullable_value_doesnt_need_null_expansion_negated(async); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Subquery_projecting_nullable_scalar_contains_nullable_value_needs_null_expansion_negated(bool async) + { + return base.Subquery_projecting_nullable_scalar_contains_nullable_value_needs_null_expansion_negated(async); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task SelectMany_predicate_with_non_equality_comparison_with_Take_doesnt_convert_to_join(bool async) + { + return base.SelectMany_predicate_with_non_equality_comparison_with_Take_doesnt_convert_to_join(async); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Subquery_projecting_nullable_scalar_contains_nullable_value_needs_null_expansion(bool async) + { + return base.Subquery_projecting_nullable_scalar_contains_nullable_value_needs_null_expansion(async); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Array_access_on_byte_array(bool async) + { + return base.Array_access_on_byte_array(async); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Correlated_collection_after_distinct_3_levels(bool async) + { + return base.Correlated_collection_after_distinct_3_levels(async); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Correlated_collection_via_SelectMany_with_Distinct_missing_indentifying_columns_in_projection(bool async) + { + return base.Correlated_collection_via_SelectMany_with_Distinct_missing_indentifying_columns_in_projection(async); + } + + [Theory] + [MemberData(nameof(IsAsyncData))] + public override Task ToString_boolean_property_non_nullable(bool async) + { + return AssertQuery(async, ss => ss.Set().Select(w => w.IsAutomatic.ToString()), elementAsserter: (lhs, rhs) => { Assert.True(lhs.Equals(rhs, System.StringComparison.InvariantCultureIgnoreCase)); }); + } + + [Theory] + [MemberData(nameof(IsAsyncData))] + public override Task ToString_boolean_property_nullable(bool async) + { + return AssertQuery(async, ss => ss.Set().Select(lh => lh.Eradicated.ToString()), elementAsserter: (lhs, rhs) => { Assert.True(lhs.Equals(rhs, System.StringComparison.InvariantCultureIgnoreCase)); }); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Correlated_collection_with_inner_collection_references_element_two_levels_up(bool async) + { + return base.Correlated_collection_with_inner_collection_references_element_two_levels_up(async); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Correlated_collection_with_groupby_not_projecting_identifier_column_with_group_aggregate_in_final_projection_multiple_grouping_keys(bool async) + { + return base.Correlated_collection_with_groupby_not_projecting_identifier_column_with_group_aggregate_in_final_projection_multiple_grouping_keys(async); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Correlated_collection_with_groupby_not_projecting_identifier_column_with_group_aggregate_in_final_projection(bool async) + { + return base.Correlated_collection_with_groupby_not_projecting_identifier_column_with_group_aggregate_in_final_projection(async); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Correlated_collection_with_groupby_not_projecting_identifier_column_but_only_grouping_key_in_final_projection(bool async) + { + return base.Correlated_collection_with_groupby_not_projecting_identifier_column_but_only_grouping_key_in_final_projection(async); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Correlated_collection_with_distinct_projecting_identifier_column(bool async) + { + return base.Correlated_collection_with_distinct_projecting_identifier_column(async); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Correlated_collection_with_distinct_not_projecting_identifier_column(bool async) + { + return base.Correlated_collection_with_distinct_not_projecting_identifier_column(async); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Correlated_collections_with_Distinct(bool async) + { + return base.Correlated_collections_with_Distinct(async); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task First_on_byte_array(bool async) + { + return base.First_on_byte_array(async); + } + + [NotSupportedOnInterBaseTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_TimeOnly_subtract_TimeOnly(bool async) + { + return base.Where_TimeOnly_subtract_TimeOnly(async); + } + + [Theory(Skip = "NETProvider#1008")] + [MemberData(nameof(IsAsyncData))] + public override Task Where_TimeOnly_IsBetween(bool async) + { + return base.Where_TimeOnly_IsBetween(async); + } + + [Theory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_TimeOnly_AddMinutes(bool async) + { + return base.Where_TimeOnly_AddMinutes(async); + } + + [Theory(Skip = "NETProvider#1009")] + [MemberData(nameof(IsAsyncData))] + public override Task Where_TimeOnly_Add_TimeSpan(bool async) + { + return base.Where_TimeOnly_Add_TimeSpan(async); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/GroupByQueryIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/GroupByQueryIBTest.cs deleted file mode 100644 index 4df1c82..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/GroupByQueryIBTest.cs +++ /dev/null @@ -1,52 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using System; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.TestUtilities; -using Xunit; -using Xunit.Abstractions; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class GroupByQueryIBTest : GroupByQueryTestBase> - { - public GroupByQueryIBTest(NorthwindQueryIBFixture fixture, ITestOutputHelper testOutputHelper) - : base(fixture) - { } - - [Theory] - [MemberData(nameof(IsAsyncData))] - public override Task GroupBy_Property_Select_Count_with_predicate(bool async) - { - return Assert.ThrowsAsync( - () => base.GroupBy_Property_Select_Count_with_predicate(async)); - } - - [Theory] - [MemberData(nameof(IsAsyncData))] - public override Task GroupBy_Property_Select_LongCount_with_predicate(bool async) - { - return Assert.ThrowsAsync( - () => base.GroupBy_Property_Select_LongCount_with_predicate(async)); - } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/IncludeAsyncIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/IncludeAsyncIBTest.cs deleted file mode 100644 index 337c1c8..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/IncludeAsyncIBTest.cs +++ /dev/null @@ -1,65 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using System.Linq; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.TestModels.Northwind; -using Microsoft.EntityFrameworkCore.TestUtilities; -using Xunit; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class IncludeAsyncIBTest : IncludeAsyncTestBase> - { - public IncludeAsyncIBTest(NorthwindQueryIBFixture fixture) - : base(fixture) - { } - - [Fact] - // See #19363 on EntityFrameworkCore. - public override async Task Include_duplicate_collection_result_operator() - { - using var context = CreateContext(); - var customers - = await (from c1 in context.Set() - .Include(c => c.Orders) - .OrderBy(c => c.CustomerID) - .Take(2) - from c2 in context.Set() - .Include(c => c.Orders) - .OrderBy(c => c.CustomerID) - .Skip(2) - .Take(2) - select new { c1, c2 }) - .OrderBy(x => x.c1.CustomerID).ThenBy(x => x.c2.CustomerID) - .Take(1) - .ToListAsync(); - - Assert.Single(customers); - Assert.Equal(6, customers.SelectMany(c => c.c1.Orders).Count()); - Assert.True(customers.SelectMany(c => c.c1.Orders).All(o => o.Customer != null)); - Assert.Equal(7, customers.SelectMany(c => c.c2.Orders).Count()); - Assert.True(customers.SelectMany(c => c.c2.Orders).All(o => o.Customer != null)); - Assert.Equal(15, context.ChangeTracker.Entries().Count()); - } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/IncludeIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/IncludeIBTest.cs deleted file mode 100644 index 5fbea91..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/IncludeIBTest.cs +++ /dev/null @@ -1,168 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using System.Threading.Tasks; -using System.Linq; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.TestModels.Northwind; -using Xunit; -using Xunit.Abstractions; -using Microsoft.EntityFrameworkCore.TestUtilities; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class IncludeIBTest : IncludeTestBase> - { - public IncludeIBTest(NorthwindQueryIBFixture fixture, ITestOutputHelper testOutputHelper) - : base(fixture) - { } - - [Theory] - [InlineData(false, false)] - [InlineData(true, false)] - [InlineData(false, true)] - [InlineData(true, true)] - // See #19222 on EntityFrameworkCore. - public override async Task Include_is_not_ignored_when_projection_contains_client_method_and_complex_expression( - bool useString, bool async) - { - using (var context = CreateContext()) - { - var query = from e in (useString - ? context.Employees.Include(nameof(Employee.Manager)) - : context.Employees.Include(e => e.Manager)) - where e.EmployeeID == 1 || e.EmployeeID == 2 - orderby e.EmployeeID - select e.Manager != null ? "Employee " + ClientMethod(e) : ""; - - var result = async - ? await query.ToListAsync() - : query.ToList(); - - Assert.Collection( - result, - e => Assert.Equal("Employee Nancy reports to Andrew", e), - e2 => Assert.Equal("", e2)); - } - } - - private static string ClientMethod(Employee e) - => e.FirstName + " reports to " + e.Manager.FirstName + e.Manager.LastName; - - [Theory] - [InlineData(false)] - [InlineData(true)] - // See #19363 on EntityFrameworkCore. - public override void Include_duplicate_collection_result_operator(bool useString) - { - using var context = CreateContext(); - var customers - = useString - ? (from c1 in context.Set() - .Include("Orders") - .OrderBy(c => c.CustomerID) - .Take(2) - from c2 in context.Set() - .Include("Orders") - .OrderBy(c => c.CustomerID) - .Skip(2) - .Take(2) - select new { c1, c2 }) - .OrderBy(x => x.c1.CustomerID).ThenBy(x => x.c2.CustomerID) - .Take(1) - .ToList() - : (from c1 in context.Set() - .Include(c => c.Orders) - .OrderBy(c => c.CustomerID) - .Take(2) - from c2 in context.Set() - .Include(c => c.Orders) - .OrderBy(c => c.CustomerID) - .Skip(2) - .Take(2) - select new { c1, c2 }) - .OrderBy(x => x.c1.CustomerID).ThenBy(x => x.c2.CustomerID) - .Take(1) - .ToList(); - - Assert.Single(customers); - Assert.Equal(6, customers.SelectMany(c => c.c1.Orders).Count()); - Assert.True(customers.SelectMany(c => c.c1.Orders).All(o => o.Customer != null)); - Assert.Equal(7, customers.SelectMany(c => c.c2.Orders).Count()); - Assert.True(customers.SelectMany(c => c.c2.Orders).All(o => o.Customer != null)); - Assert.Equal(15, context.ChangeTracker.Entries().Count()); - - foreach (var customer in customers.Select(e => e.c1)) - { - CheckIsLoaded( - context, - customer, - ordersLoaded: true, - orderDetailsLoaded: false, - productLoaded: false); - } - - foreach (var customer in customers.Select(e => e.c2)) - { - CheckIsLoaded( - context, - customer, - ordersLoaded: true, - orderDetailsLoaded: false, - productLoaded: false); - } - } - - private static void CheckIsLoaded( - NorthwindContext context, - Customer customer, - bool ordersLoaded, - bool orderDetailsLoaded, - bool productLoaded) - { - context.ChangeTracker.AutoDetectChangesEnabled = false; - - Assert.Equal(ordersLoaded, context.Entry(customer).Collection(e => e.Orders).IsLoaded); - if (customer.Orders != null) - { - foreach (var order in customer.Orders) - { - Assert.Equal(ordersLoaded, context.Entry(order).Reference(e => e.Customer).IsLoaded); - - Assert.Equal(orderDetailsLoaded, context.Entry(order).Collection(e => e.OrderDetails).IsLoaded); - if (order.OrderDetails != null) - { - foreach (var orderDetail in order.OrderDetails) - { - Assert.Equal(orderDetailsLoaded, context.Entry(orderDetail).Reference(e => e.Order).IsLoaded); - - Assert.Equal(productLoaded, context.Entry(orderDetail).Reference(e => e.Product).IsLoaded); - if (orderDetail.Product != null) - { - Assert.False(context.Entry(orderDetail.Product).Collection(e => e.OrderDetails).IsLoaded); - } - } - } - } - } - } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/IncludeOneToOneIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/IncludeOneToOneIBTest.cs index 2798dcf..341eb14 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/IncludeOneToOneIBTest.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/IncludeOneToOneIBTest.cs @@ -24,23 +24,23 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query; + + +public class IncludeOneToOneIBTest : IncludeOneToOneTestBase { - public class IncludeOneToOneIBTest : IncludeOneToOneTestBase + public IncludeOneToOneIBTest(OneToOneQueryIBFixture fixture) + : base(fixture) + { } + + public class OneToOneQueryIBFixture : OneToOneQueryFixtureBase { - public IncludeOneToOneIBTest(OneToOneQueryIBFixture fixture) - : base(fixture) - { } + protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; - public class OneToOneQueryIBFixture : OneToOneQueryFixtureBase + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) { - protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; - - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - base.OnModelCreating(modelBuilder, context); - ModelHelpers.SetPrimaryKeyGeneration(modelBuilder); - } + base.OnModelCreating(modelBuilder, context); + ModelHelpers.SetPrimaryKeyGeneration(modelBuilder); } } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/InheritanceIBFixture.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/InheritanceIBFixture.cs deleted file mode 100644 index e586b61..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/InheritanceIBFixture.cs +++ /dev/null @@ -1,39 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.TestUtilities; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.TestModels.Inheritance; -using Microsoft.EntityFrameworkCore.TestUtilities; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class InheritanceIBFixture : InheritanceRelationalFixture - { - protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; - - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - base.OnModelCreating(modelBuilder, context); - modelBuilder.Entity().HasNoKey().ToQuery(() => context.Set().FromSqlRaw(@"SELECT * FROM ""Animal""")); - } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/InheritanceIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/InheritanceIBTest.cs deleted file mode 100644 index 787c6eb..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/InheritanceIBTest.cs +++ /dev/null @@ -1,38 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Storage; -using Xunit.Abstractions; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class InheritanceIBTest : InheritanceRelationalTestBase - { - public InheritanceIBTest(InheritanceIBFixture fixture, ITestOutputHelper testOutputHelper) - : base(fixture) - { } - - protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) - => facade.UseTransaction(transaction.GetDbTransaction()); - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/InheritanceRelationshipsQueryIBFixture.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/InheritanceRelationshipsQueryIBFixture.cs index 41cb077..c39caf0 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/InheritanceRelationshipsQueryIBFixture.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/InheritanceRelationshipsQueryIBFixture.cs @@ -24,17 +24,16 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query; + +public class InheritanceRelationshipsQueryIBFixture : InheritanceRelationshipsQueryRelationalFixture { - public class InheritanceRelationshipsQueryIBFixture : InheritanceRelationshipsQueryRelationalFixture - { - protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; + protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - base.OnModelCreating(modelBuilder, context); - ModelHelpers.SetPrimaryKeyGeneration(modelBuilder); - ModelHelpers.SimpleTableNames(modelBuilder); - } + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + base.OnModelCreating(modelBuilder, context); + ModelHelpers.SetPrimaryKeyGeneration(modelBuilder); + ModelHelpers.SimpleTableNames(modelBuilder); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/InheritanceRelationshipsQueryIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/InheritanceRelationshipsQueryIBTest.cs index 93f79ea..0865cce 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/InheritanceRelationshipsQueryIBTest.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/InheritanceRelationshipsQueryIBTest.cs @@ -20,44 +20,348 @@ using InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Helpers; using Microsoft.EntityFrameworkCore.Query; +using System.Threading.Tasks; using Xunit; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query; + +public class InheritanceRelationshipsQueryIBTest : InheritanceRelationshipsQueryTestBase { - public class InheritanceRelationshipsQueryIBTest : InheritanceRelationshipsQueryTestBase - { - public InheritanceRelationshipsQueryIBTest(InheritanceRelationshipsQueryIBFixture fixture) - : base(fixture) - { } - - [GeneratedNameTooLongFact] - public override void Nested_include_with_inheritance_reference_collection1() - { - base.Nested_include_with_inheritance_reference_collection1(); - } - - [GeneratedNameTooLongFact] - public override void Nested_include_with_inheritance_reference_reference1() - { - base.Nested_include_with_inheritance_reference_reference1(); - } - - [GeneratedNameTooLongFact] - public override void Nested_include_with_inheritance_reference_collection3() - { - base.Nested_include_with_inheritance_reference_collection3(); - } - - [GeneratedNameTooLongFact] - public override void Nested_include_with_inheritance_reference_reference3() - { - base.Nested_include_with_inheritance_reference_reference3(); - } - - [GeneratedNameTooLongFact] - public override void Nested_include_with_inheritance_collection_collection1() - { - base.Nested_include_with_inheritance_collection_collection1(); - } + public InheritanceRelationshipsQueryIBTest(InheritanceRelationshipsQueryIBFixture fixture) + : base(fixture) + { } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_reference_without_inheritance_on_derived1(bool async) + { + return base.Include_reference_without_inheritance_on_derived1(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_collection_without_inheritance_with_filter_reverse(bool async) + { + return base.Include_collection_without_inheritance_with_filter_reverse(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Nested_include_with_inheritance_reference_reference_reverse(bool async) + { + return base.Nested_include_with_inheritance_reference_reference_reverse(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Nested_include_with_inheritance_reference_collection(bool async) + { + return base.Nested_include_with_inheritance_reference_collection(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_reference_with_inheritance_with_filter(bool async) + { + return base.Include_reference_with_inheritance_with_filter(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_reference_with_inheritance_on_derived2(bool async) + { + return base.Include_reference_with_inheritance_on_derived2(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_reference_without_inheritance_on_derived_reverse(bool async) + { + return base.Include_reference_without_inheritance_on_derived_reverse(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_reference_with_inheritance_on_derived_with_filter_reverse(bool async) + { + return base.Include_reference_with_inheritance_on_derived_with_filter_reverse(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_collection_with_inheritance_reverse(bool async) + { + return base.Include_collection_with_inheritance_reverse(async); + } + + [GeneratedNameTooLongFact] + public override void Entity_can_make_separate_relationships_with_base_type_and_derived_type_both() + { + base.Entity_can_make_separate_relationships_with_base_type_and_derived_type_both(); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Nested_include_with_inheritance_collection_reference(bool async) + { + return base.Nested_include_with_inheritance_collection_reference(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_reference_without_inheritance_reverse(bool async) + { + return base.Include_reference_without_inheritance_reverse(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Nested_include_with_inheritance_reference_collection_on_base(bool async) + { + return base.Nested_include_with_inheritance_reference_collection_on_base(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_reference_with_inheritance_reverse(bool async) + { + return base.Include_reference_with_inheritance_reverse(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_collection_with_inheritance_on_derived1(bool async) + { + return base.Include_collection_with_inheritance_on_derived1(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_self_reference_with_inheritance(bool async) + { + return base.Include_self_reference_with_inheritance(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_reference_with_inheritance_on_derived_with_filter1(bool async) + { + return base.Include_reference_with_inheritance_on_derived_with_filter1(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Nested_include_with_inheritance_collection_reference_reverse(bool async) + { + return base.Nested_include_with_inheritance_collection_reference_reverse(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_collection_with_inheritance_on_derived3(bool async) + { + return base.Include_collection_with_inheritance_on_derived3(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_collection_without_inheritance_reverse(bool async) + { + return base.Include_collection_without_inheritance_reverse(async); + } + + [GeneratedNameTooLongFact] + public override void Changes_in_derived_related_entities_are_detected() + { + base.Changes_in_derived_related_entities_are_detected(); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_collection_with_inheritance_with_filter(bool async) + { + return base.Include_collection_with_inheritance_with_filter(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_reference_without_inheritance_on_derived2(bool async) + { + return base.Include_reference_without_inheritance_on_derived2(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_reference_with_inheritance_on_derived4(bool async) + { + return base.Include_reference_with_inheritance_on_derived4(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Nested_include_with_inheritance_reference_reference(bool async) + { + return base.Nested_include_with_inheritance_reference_reference(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_reference_with_inheritance_on_derived_with_filter2(bool async) + { + return base.Include_reference_with_inheritance_on_derived_with_filter2(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_reference_with_inheritance_with_filter_reverse(bool async) + { + return base.Include_reference_with_inheritance_with_filter_reverse(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_reference_with_inheritance_on_derived_reverse(bool async) + { + return base.Include_reference_with_inheritance_on_derived_reverse(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_self_reference_with_inheritance_reverse(bool async) + { + return base.Include_self_reference_with_inheritance_reverse(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_collection_without_inheritance(bool async) + { + return base.Include_collection_without_inheritance(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_reference_without_inheritance_with_filter(bool async) + { + return base.Include_reference_without_inheritance_with_filter(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Nested_include_with_inheritance_collection_collection(bool async) + { + return base.Nested_include_with_inheritance_collection_collection(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Nested_include_with_inheritance_reference_reference_on_base(bool async) + { + return base.Nested_include_with_inheritance_reference_reference_on_base(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_reference_without_inheritance_with_filter_reverse(bool async) + { + return base.Include_reference_without_inheritance_with_filter_reverse(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_collection_with_inheritance(bool async) + { + return base.Include_collection_with_inheritance(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Nested_include_with_inheritance_reference_collection_reverse(bool async) + { + return base.Nested_include_with_inheritance_reference_collection_reverse(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_collection_with_inheritance_on_derived_reverse(bool async) + { + return base.Include_collection_with_inheritance_on_derived_reverse(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_collection_with_inheritance_with_filter_reverse(bool async) + { + return base.Include_collection_with_inheritance_with_filter_reverse(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Collection_projection_on_base_type(bool async) + { + return base.Collection_projection_on_base_type(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_collection_with_inheritance_on_derived2(bool async) + { + return base.Include_collection_with_inheritance_on_derived2(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Nested_include_collection_reference_on_non_entity_base(bool async) + { + return base.Nested_include_collection_reference_on_non_entity_base(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_reference_without_inheritance(bool async) + { + return base.Include_reference_without_inheritance(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_reference_with_inheritance_on_derived_with_filter4(bool async) + { + return base.Include_reference_with_inheritance_on_derived_with_filter4(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_reference_with_inheritance_on_derived1(bool async) + { + return base.Include_reference_with_inheritance_on_derived1(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Nested_include_with_inheritance_collection_collection_reverse(bool async) + { + return base.Nested_include_with_inheritance_collection_collection_reverse(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_reference_with_inheritance(bool async) + { + return base.Include_reference_with_inheritance(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_collection_without_inheritance_with_filter(bool async) + { + return base.Include_collection_without_inheritance_with_filter(async); + } + + [GeneratedNameTooLongTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Include_on_derived_type_with_queryable_Cast(bool async) + { + return base.Include_on_derived_type_with_queryable_Cast(async); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/MappingQueryIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/MappingQueryIBTest.cs index 9c212eb..6d029b4 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/MappingQueryIBTest.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/MappingQueryIBTest.cs @@ -24,55 +24,54 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query; + +public class MappingQueryIBTest : MappingQueryTestBase { - public class MappingQueryIBTest : MappingQueryTestBase - { - public MappingQueryIBTest(MappingQueryFbFixture fixture) - : base(fixture) - { } + public MappingQueryIBTest(MappingQueryFbFixture fixture) + : base(fixture) + { } - [DoesNotHaveTheDataFact] - public override void All_customers() - { - base.All_customers(); - } + [DoesNotHaveTheDataFact] + public override void All_customers() + { + base.All_customers(); + } - [DoesNotHaveTheDataFact] - public override void All_employees() - { - base.All_employees(); - } + [DoesNotHaveTheDataFact] + public override void All_employees() + { + base.All_employees(); + } - [DoesNotHaveTheDataFact] - public override void All_orders() - { - base.All_orders(); - } + [DoesNotHaveTheDataFact] + public override void All_orders() + { + base.All_orders(); + } - [DoesNotHaveTheDataFact] - public override void Project_nullable_enum() - { - base.Project_nullable_enum(); - } + [DoesNotHaveTheDataFact] + public override void Project_nullable_enum() + { + base.Project_nullable_enum(); + } - public class MappingQueryFbFixture : MappingQueryFixtureBase - { - protected override ITestStoreFactory TestStoreFactory => /*FbNorthwindTestStoreFactory*/IBTestStoreFactory.Instance; + public class MappingQueryFbFixture : MappingQueryFixtureBase + { + protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; - protected override string DatabaseSchema { get; } = null; + protected override string DatabaseSchema { get; } = null; - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - base.OnModelCreating(modelBuilder, context); + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + base.OnModelCreating(modelBuilder, context); - modelBuilder.Entity( - e => - { - e.Property(c => c.CompanyName2).Metadata.SetColumnName("CompanyName"); - e.Metadata.SetTableName("Customers"); - }); - } + modelBuilder.Entity( + e => + { + e.Property(c => c.CompanyName2).Metadata.SetColumnName("CompanyName"); + e.Metadata.SetTableName("Customers"); + }); } } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/NorthwindQueryIBFixture.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/NorthwindQueryIBFixture.cs index 5e8c39e..b0098c6 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/NorthwindQueryIBFixture.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/NorthwindQueryIBFixture.cs @@ -25,12 +25,11 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query; + +public class NorthwindQueryIBFixture : NorthwindQueryRelationalFixture + where TModelCustomizer : IModelCustomizer, new() { - public class NorthwindQueryIBFixture : NorthwindQueryRelationalFixture - where TModelCustomizer : IModelCustomizer, new() - { - protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; - protected override Type ContextType => typeof(NorthwindIBContext); - } + protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; + protected override Type ContextType => typeof(NorthwindIBContext); } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/NullKeysIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/NullKeysIBTest.cs index 99eac3b..345b827 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/NullKeysIBTest.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/NullKeysIBTest.cs @@ -22,17 +22,16 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query; + +public class NullKeysIBTest : NullKeysTestBase { - public class NullKeysIBTest : NullKeysTestBase - { - public NullKeysIBTest(NullKeysIBFixture fixture) - : base(fixture) - { } + public NullKeysIBTest(NullKeysIBFixture fixture) + : base(fixture) + { } - public class NullKeysIBFixture : NullKeysFixtureBase - { - protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; - } + public class NullKeysIBFixture : NullKeysFixtureBase + { + protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/NullSemanticsQueryIBFixture.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/NullSemanticsQueryIBFixture.cs index d313a43..c55df3f 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/NullSemanticsQueryIBFixture.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/NullSemanticsQueryIBFixture.cs @@ -22,10 +22,9 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query; + +public class NullSemanticsQueryIBFixture : NullSemanticsQueryFixtureBase { - public class NullSemanticsQueryIBFixture : NullSemanticsQueryRelationalFixture - { - protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; - } + protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/NullSemanticsQueryIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/NullSemanticsQueryIBTest.cs index 2f2acfd..d05d42a 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/NullSemanticsQueryIBTest.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/NullSemanticsQueryIBTest.cs @@ -23,24 +23,23 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestModels.NullSemanticsModel; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query; + +public class NullSemanticsQueryIBTest : NullSemanticsQueryTestBase { - public class NullSemanticsQueryIBTest : NullSemanticsQueryTestBase - { - public NullSemanticsQueryIBTest(NullSemanticsQueryIBFixture fixture) - : base(fixture) - { } + public NullSemanticsQueryIBTest(NullSemanticsQueryIBFixture fixture) + : base(fixture) + { } - protected override NullSemanticsContext CreateContext(bool useRelationalNulls = false) + protected override NullSemanticsContext CreateContext(bool useRelationalNulls = false) + { + var options = new DbContextOptionsBuilder(Fixture.CreateOptions()); + if (useRelationalNulls) { - var options = new DbContextOptionsBuilder(Fixture.CreateOptions()); - if (useRelationalNulls) - { - new IBDbContextOptionsBuilder(options).UseRelationalNulls(); - } - var context = new NullSemanticsContext(options.Options); - context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; - return context; + new IBDbContextOptionsBuilder(options).UseRelationalNulls(); } + var context = new NullSemanticsContext(options.Options); + context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; + return context; } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/OwnedQueryIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/OwnedQueryIBTest.cs index 454536a..b01101b 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/OwnedQueryIBTest.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/OwnedQueryIBTest.cs @@ -25,157 +25,374 @@ using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query; + +public class OwnedQueryIBTest : OwnedQueryRelationalTestBase { - public class OwnedQueryIBTest : RelationalOwnedQueryTestBase - { - public OwnedQueryIBTest(OwnedQueryFbFixture fixture) - : base(fixture) - { } + public OwnedQueryIBTest(OwnedQueryFbFixture fixture) + : base(fixture) + { } + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Navigation_rewrite_on_owned_collection(bool isAsync) => base.Navigation_rewrite_on_owned_collection(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity(bool isAsync) => base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference(bool isAsync) => base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference_and_scalar(bool isAsync) => base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference_and_scalar(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference_in_predicate_and_projection(bool isAsync) => base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference_in_predicate_and_projection(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_collection(bool isAsync) => base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_collection(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_collection_count(bool isAsync) => base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_collection_count(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_property(bool isAsync) => base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_property(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task No_ignored_include_warning_when_implicit_load(bool isAsync) => base.No_ignored_include_warning_when_implicit_load(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Query_for_base_type_loads_all_owned_navs(bool isAsync) => base.Query_for_base_type_loads_all_owned_navs(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Query_for_branch_type_loads_all_owned_navs(bool isAsync) => base.Query_for_branch_type_loads_all_owned_navs(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Query_for_leaf_type_loads_all_owned_navs(bool isAsync) => base.Query_for_leaf_type_loads_all_owned_navs(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Query_when_subquery(bool isAsync) => base.Query_when_subquery(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Query_with_OfType_eagerly_loads_correct_owned_navigations(bool isAsync) => base.Query_with_OfType_eagerly_loads_correct_owned_navigations(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Query_with_owned_entity_equality_method(bool isAsync) => base.Query_with_owned_entity_equality_method(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Query_with_owned_entity_equality_object_method(bool isAsync) => base.Query_with_owned_entity_equality_object_method(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Query_with_owned_entity_equality_operator(bool isAsync) => base.Query_with_owned_entity_equality_operator(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task SelectMany_on_owned_reference_followed_by_regular_entity_and_collection(bool isAsync) => base.SelectMany_on_owned_reference_followed_by_regular_entity_and_collection(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task SelectMany_on_owned_reference_with_entity_in_between_ending_in_owned_collection(bool isAsync) => base.SelectMany_on_owned_reference_with_entity_in_between_ending_in_owned_collection(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Navigation_rewrite_on_owned_collection_with_composition(bool isAsync) => base.Navigation_rewrite_on_owned_collection_with_composition(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Filter_owned_entity_chained_with_regular_entity_followed_by_projecting_owned_collection(bool isAsync) => base.Filter_owned_entity_chained_with_regular_entity_followed_by_projecting_owned_collection(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Navigation_rewrite_on_owned_collection_with_composition_complex(bool isAsync) => base.Navigation_rewrite_on_owned_collection_with_composition_complex(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity_filter(bool isAsync) => base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_filter(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Navigation_rewrite_on_owned_reference_projecting_entity(bool isAsync) => base.Navigation_rewrite_on_owned_reference_projecting_entity(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Navigation_rewrite_on_owned_reference_projecting_scalar(bool isAsync) => base.Navigation_rewrite_on_owned_reference_projecting_scalar(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Preserve_includes_when_applying_skip_take_after_anonymous_type_select(bool isAsync) => base.Preserve_includes_when_applying_skip_take_after_anonymous_type_select(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Project_multiple_owned_navigations(bool isAsync) => base.Project_multiple_owned_navigations(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Project_multiple_owned_navigations_with_expansion_on_owned_collections(bool isAsync) => base.Project_multiple_owned_navigations_with_expansion_on_owned_collections(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Query_for_branch_type_loads_all_owned_navs_tracking(bool isAsync) => base.Query_for_branch_type_loads_all_owned_navs_tracking(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Query_loads_reference_nav_automatically_in_projection(bool isAsync) => base.Query_loads_reference_nav_automatically_in_projection(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task SelectMany_on_owned_collection(bool isAsync) => base.SelectMany_on_owned_collection(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Set_throws_for_owned_type(bool isAsync) => base.Set_throws_for_owned_type(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Throw_for_owned_entities_without_owner_in_tracking_query(bool isAsync) => base.Throw_for_owned_entities_without_owner_in_tracking_query(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Unmapped_property_projection_loads_owned_navigations(bool isAsync) => base.Unmapped_property_projection_loads_owned_navigations(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Client_method_take_loads_owned_navigations_variation_2(bool isAsync) => base.Client_method_take_loads_owned_navigations_variation_2(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Trying_to_access_non_existent_indexer_property_throws_meaningful_exception(bool isAsync) => base.Trying_to_access_non_existent_indexer_property_throws_meaningful_exception(isAsync); - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigation_rewrite_on_owned_collection(bool isAsync) => base.Navigation_rewrite_on_owned_collection(isAsync); + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Client_method_skip_loads_owned_navigations(bool isAsync) => base.Client_method_skip_loads_owned_navigations(isAsync); - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity(bool isAsync) => base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity(isAsync); + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Indexer_property_is_pushdown_into_subquery(bool isAsync) => base.Indexer_property_is_pushdown_into_subquery(isAsync); - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference(bool isAsync) => base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference(isAsync); + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Query_with_OfType_eagerly_loads_correct_owned_navigations_split(bool isAsync) => base.Query_with_OfType_eagerly_loads_correct_owned_navigations_split(isAsync); - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference_and_scalar(bool isAsync) => base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference_and_scalar(isAsync); + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Can_OrderBy_owned_indexer_properties(bool isAsync) => base.Can_OrderBy_owned_indexer_properties(isAsync); - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference_in_predicate_and_projection(bool isAsync) => base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference_in_predicate_and_projection(isAsync); + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Can_query_on_indexer_property_when_property_name_from_closure(bool isAsync) => base.Can_query_on_indexer_property_when_property_name_from_closure(isAsync); - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_collection(bool isAsync) => base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_collection(isAsync); + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Can_group_by_converted_indexer_property(bool isAsync) => base.Can_group_by_converted_indexer_property(isAsync); - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_collection_count(bool isAsync) => base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_collection_count(isAsync); + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_collection_navigation_AsEnumerable_Count(bool isAsync) => base.Where_collection_navigation_AsEnumerable_Count(isAsync); - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_property(bool isAsync) => base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_property(isAsync); + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Can_project_owned_indexer_properties_converted(bool isAsync) => base.Can_project_owned_indexer_properties_converted(isAsync); - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task No_ignored_include_warning_when_implicit_load(bool isAsync) => base.No_ignored_include_warning_when_implicit_load(isAsync); + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Can_group_by_owned_indexer_property(bool isAsync) => base.Can_group_by_owned_indexer_property(isAsync); - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Query_for_base_type_loads_all_owned_navs(bool isAsync) => base.Query_for_base_type_loads_all_owned_navs(isAsync); + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Project_multiple_owned_navigations_split(bool isAsync) => base.Project_multiple_owned_navigations_split(isAsync); - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Query_for_branch_type_loads_all_owned_navs(bool isAsync) => base.Query_for_branch_type_loads_all_owned_navs(isAsync); - - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Query_for_leaf_type_loads_all_owned_navs(bool isAsync) => base.Query_for_leaf_type_loads_all_owned_navs(isAsync); - - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Query_when_group_by(bool isAsync) => base.Query_when_group_by(isAsync); - - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Query_when_subquery(bool isAsync) => base.Query_when_subquery(isAsync); - - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Query_with_OfType_eagerly_loads_correct_owned_navigations(bool isAsync) => base.Query_with_OfType_eagerly_loads_correct_owned_navigations(isAsync); - - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Query_with_owned_entity_equality_method(bool isAsync) => base.Query_with_owned_entity_equality_method(isAsync); - - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Query_with_owned_entity_equality_object_method(bool isAsync) => base.Query_with_owned_entity_equality_object_method(isAsync); - - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Query_with_owned_entity_equality_operator(bool isAsync) => base.Query_with_owned_entity_equality_operator(isAsync); - - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_on_owned_reference_followed_by_regular_entity_and_collection(bool isAsync) => base.SelectMany_on_owned_reference_followed_by_regular_entity_and_collection(isAsync); - - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_on_owned_reference_with_entity_in_between_ending_in_owned_collection(bool isAsync) => base.SelectMany_on_owned_reference_with_entity_in_between_ending_in_owned_collection(isAsync); - - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigation_rewrite_on_owned_collection_with_composition(bool isAsync) => base.Navigation_rewrite_on_owned_collection_with_composition(isAsync); - - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Filter_owned_entity_chained_with_regular_entity_followed_by_projecting_owned_collection(bool isAsync) => base.Filter_owned_entity_chained_with_regular_entity_followed_by_projecting_owned_collection(isAsync); - - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigation_rewrite_on_owned_collection_with_composition_complex(bool isAsync) => base.Navigation_rewrite_on_owned_collection_with_composition_complex(isAsync); - - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity_filter(bool isAsync) => base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_filter(isAsync); - - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigation_rewrite_on_owned_reference_projecting_entity(bool isAsync) => base.Navigation_rewrite_on_owned_reference_projecting_entity(isAsync); + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Can_project_owned_indexer_properties(bool isAsync) => base.Can_project_owned_indexer_properties(isAsync); - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Navigation_rewrite_on_owned_reference_projecting_scalar(bool isAsync) => base.Navigation_rewrite_on_owned_reference_projecting_scalar(isAsync); + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task NoTracking_Include_with_cycles_throws(bool isAsync) => base.NoTracking_Include_with_cycles_throws(isAsync); - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Preserve_includes_when_applying_skip_take_after_anonymous_type_select(bool isAsync) => base.Preserve_includes_when_applying_skip_take_after_anonymous_type_select(isAsync); + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Projecting_indexer_property_ignores_include(bool isAsync) => base.Projecting_indexer_property_ignores_include(isAsync); - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Project_multiple_owned_navigations(bool isAsync) => base.Project_multiple_owned_navigations(isAsync); + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task GroupBy_with_multiple_aggregates_on_owned_navigation_properties(bool isAsync) => base.GroupBy_with_multiple_aggregates_on_owned_navigation_properties(isAsync); - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Project_multiple_owned_navigations_with_expansion_on_owned_collections(bool isAsync) => base.Project_multiple_owned_navigations_with_expansion_on_owned_collections(isAsync); + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Using_from_sql_on_owner_generates_join_with_table_for_owned_shared_dependents(bool isAsync) => base.Using_from_sql_on_owner_generates_join_with_table_for_owned_shared_dependents(isAsync); - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Query_for_branch_type_loads_all_owned_navs_tracking(bool isAsync) => base.Query_for_branch_type_loads_all_owned_navs_tracking(isAsync); + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Query_when_subquery_split(bool isAsync) => base.Query_when_subquery_split(isAsync); - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Query_loads_reference_nav_automatically_in_projection(bool isAsync) => base.Query_loads_reference_nav_automatically_in_projection(isAsync); + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Can_group_by_converted_owned_indexer_property(bool isAsync) => base.Can_group_by_converted_owned_indexer_property(isAsync); - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_on_owned_collection(bool isAsync) => base.SelectMany_on_owned_collection(isAsync); + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Can_project_indexer_properties_converted(bool isAsync) => base.Can_project_indexer_properties_converted(isAsync); - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Set_throws_for_owned_type(bool isAsync) => base.Set_throws_for_owned_type(isAsync); + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Query_for_base_type_loads_all_owned_navs_split(bool isAsync) => base.Query_for_base_type_loads_all_owned_navs_split(isAsync); - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Throw_for_owned_entities_without_owner_in_tracking_query(bool isAsync) => base.Throw_for_owned_entities_without_owner_in_tracking_query(isAsync); + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Can_query_on_indexer_properties(bool isAsync) => base.Can_query_on_indexer_properties(isAsync); - [HasDataInTheSameTransactionAsDDLTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Unmapped_property_projection_loads_owned_navigations(bool isAsync) => base.Unmapped_property_projection_loads_owned_navigations(isAsync); + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Non_nullable_property_through_optional_navigation(bool isAsync) => base.Non_nullable_property_through_optional_navigation(isAsync); - public class OwnedQueryFbFixture : RelationalOwnedQueryFixture - { - protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; - } + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_collection_navigation_ToArray_Count(bool isAsync) => base.Where_collection_navigation_ToArray_Count(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Can_OrderBy_indexer_properties_converted(bool isAsync) => base.Can_OrderBy_indexer_properties_converted(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Can_join_on_indexer_property_on_query(bool isAsync) => base.Can_join_on_indexer_property_on_query(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Can_OrderBy_owened_indexer_properties_converted(bool isAsync) => base.Can_OrderBy_owened_indexer_properties_converted(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_collection_navigation_ToList_Count_member(bool isAsync) => base.Where_collection_navigation_ToList_Count_member(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Can_query_on_owned_indexer_properties(bool isAsync) => base.Can_query_on_owned_indexer_properties(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Projecting_indexer_property_ignores_include_converted(bool isAsync) => base.Projecting_indexer_property_ignores_include_converted(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Client_method_skip_loads_owned_navigations_variation_2(bool isAsync) => base.Client_method_skip_loads_owned_navigations_variation_2(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Client_method_skip_take_loads_owned_navigations_variation_2(bool isAsync) => base.Client_method_skip_take_loads_owned_navigations_variation_2(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Projecting_collection_correlated_with_keyless_entity_after_navigation_works_using_parent_identifiers(bool isAsync) => base.Projecting_collection_correlated_with_keyless_entity_after_navigation_works_using_parent_identifiers(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Can_query_on_indexer_properties_split(bool isAsync) => base.Can_query_on_indexer_properties_split(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_collection_split(bool isAsync) => base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_collection_split(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_collection_navigation_ToArray_Length_member(bool isAsync) => base.Where_collection_navigation_ToArray_Length_member(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Can_OrderBy_indexer_properties(bool isAsync) => base.Can_OrderBy_indexer_properties(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Where_owned_collection_navigation_ToList_Count(bool isAsync) => base.Where_owned_collection_navigation_ToList_Count(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Query_on_collection_entry_works_for_owned_collection(bool isAsync) => base.Query_on_collection_entry_works_for_owned_collection(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Client_method_take_loads_owned_navigations(bool isAsync) => base.Client_method_take_loads_owned_navigations(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Can_group_by_indexer_property(bool isAsync) => base.Can_group_by_indexer_property(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Query_for_branch_type_loads_all_owned_navs_split(bool isAsync) => base.Query_for_branch_type_loads_all_owned_navs_split(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Can_query_indexer_property_on_owned_collection(bool isAsync) => base.Can_query_indexer_property_on_owned_collection(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Client_method_skip_take_loads_owned_navigations(bool isAsync) => base.Client_method_skip_take_loads_owned_navigations(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Unmapped_property_projection_loads_owned_navigations_split(bool isAsync) => base.Unmapped_property_projection_loads_owned_navigations_split(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Can_project_indexer_properties(bool isAsync) => base.Can_project_indexer_properties(isAsync); + + [DoesNotHaveTheDataTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Ordering_by_identifying_projection(bool isAsync) => base.Ordering_by_identifying_projection(isAsync); + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Filter_on_indexer_using_closure(bool async) + { + return base.Filter_on_indexer_using_closure(async); + } + + [HasDataInTheSameTransactionAsDDLTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Filter_on_indexer_using_function_argument(bool async) + { + return base.Filter_on_indexer_using_function_argument(async); + } + + [HasDataInTheSameTransactionAsDDLTheory] + [InlineData(false, false)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(true, true)] + public override Task NoTracking_Include_with_cycles_does_not_throw_when_performing_identity_resolution(bool async, bool useAsTracking) + { + return base.NoTracking_Include_with_cycles_does_not_throw_when_performing_identity_resolution(async, useAsTracking); + } + + [HasDataInTheSameTransactionAsDDLTheory] + [InlineData(false, false)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(true, true)] + public override Task Owned_entity_without_owner_does_not_throw_for_identity_resolution(bool async, bool useAsTracking) + { + return base.Owned_entity_without_owner_does_not_throw_for_identity_resolution(async, useAsTracking); + } + + public class OwnedQueryFbFixture : RelationalOwnedQueryFixture + { + protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/QueryFilterFuncletizationIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/QueryFilterFuncletizationIBTest.cs index bb095ad..42a2d6a 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/QueryFilterFuncletizationIBTest.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/QueryFilterFuncletizationIBTest.cs @@ -24,26 +24,49 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; +using System.Collections.Generic; +using System.Linq; +using System; +using Xunit; using Xunit.Abstractions; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query; + +public class QueryFilterFuncletizationIBTest : QueryFilterFuncletizationTestBase { - public class QueryFilterFuncletizationIBTest : QueryFilterFuncletizationTestBase + public QueryFilterFuncletizationIBTest(QueryFilterFuncletizationIBFixture fixture) + : base(fixture) + { } + + [Fact] + public override void DbContext_list_is_parameterized() + { + using var context = CreateContext(); + // Default value of TenantIds is null InExpression over null values throws + Assert.Throws(() => context.Set().ToList()); + + context.TenantIds = new List(); + var query = context.Set().ToList(); + Assert.Empty(query); + + context.TenantIds = new List { 1 }; + query = context.Set().ToList(); + Assert.Single(query); + + context.TenantIds = new List { 2, 3 }; + query = context.Set().ToList(); + Assert.Equal(2, query.Count); + } + + public class QueryFilterFuncletizationIBFixture : QueryFilterFuncletizationRelationalFixture { - public QueryFilterFuncletizationIBTest(QueryFilterFuncletizationIBFixture fixture, ITestOutputHelper testOutputHelper) - : base(fixture) - { } + protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; - public class QueryFilterFuncletizationIBFixture : QueryFilterFuncletizationRelationalFixture + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) { - protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; - - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - base.OnModelCreating(modelBuilder, context); - ModelHelpers.SimpleTableNames(modelBuilder); - ModelHelpers.SetPrimaryKeyGeneration(modelBuilder, IBValueGenerationStrategy.IdentityColumn); - } + base.OnModelCreating(modelBuilder, context); + ModelHelpers.SimpleTableNames(modelBuilder); + ModelHelpers.SetPrimaryKeyGeneration(modelBuilder, IBValueGenerationStrategy.IdentityColumn); } } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/QueryNavigationsIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/QueryNavigationsIBTest.cs deleted file mode 100644 index 32441cd..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/QueryNavigationsIBTest.cs +++ /dev/null @@ -1,32 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.TestUtilities; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class QueryNavigationsIBTest : QueryNavigationsTestBase> - { - public QueryNavigationsIBTest(NorthwindQueryIBFixture fixture) - : base(fixture) - { } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/QueryNoClientEvalIBFixture.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/QueryNoClientEvalIBFixture.cs index b693c98..776c749 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/QueryNoClientEvalIBFixture.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/QueryNoClientEvalIBFixture.cs @@ -20,8 +20,7 @@ using Microsoft.EntityFrameworkCore.TestUtilities; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class QueryNoClientEvalIBFixture : NorthwindQueryIBFixture - { } -} +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query; + +public class QueryNoClientEvalIBFixture : NorthwindQueryIBFixture +{ } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/QueryNoClientEvalIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/QueryNoClientEvalIBTest.cs index 94e3c67..6f40cf3 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/QueryNoClientEvalIBTest.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/QueryNoClientEvalIBTest.cs @@ -20,12 +20,11 @@ using Microsoft.EntityFrameworkCore.Query; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query; + +public class QueryNoClientEvalIBTest : QueryNoClientEvalTestBase { - public class QueryNoClientEvalIBTest : QueryNoClientEvalTestBase - { - public QueryNoClientEvalIBTest(QueryNoClientEvalIBFixture fixture) - : base(fixture) - { } - } + public QueryNoClientEvalIBTest(QueryNoClientEvalIBFixture fixture) + : base(fixture) + { } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/QueryTaggingIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/QueryTaggingIBTest.cs deleted file mode 100644 index aa1a670..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/QueryTaggingIBTest.cs +++ /dev/null @@ -1,33 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.TestUtilities; -using Xunit.Abstractions; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class QueryTaggingIBTest : QueryTaggingTestBase> - { - public QueryTaggingIBTest(NorthwindQueryIBFixture fixture, ITestOutputHelper testOutputHelper) - : base(fixture) - { } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/SimpleQueryIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/SimpleQueryIBTest.cs deleted file mode 100644 index 27c270f..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/SimpleQueryIBTest.cs +++ /dev/null @@ -1,291 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Helpers; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.TestUtilities; -using Xunit; -using Xunit.Abstractions; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class SimpleQueryIBTest : SimpleQueryTestBase> - { - public SimpleQueryIBTest(NorthwindQueryIBFixture fixture, ITestOutputHelper testOutputHelper) - : base(fixture) - { } - - [Theory(Skip = "Different DECIMAL handling on InterBase.")] - [MemberData(nameof(IsAsyncData))] - public override Task Sum_with_division_on_decimal(bool isAsync) - { - return base.Sum_with_division_on_decimal(isAsync); - } - - [Theory(Skip = "Not handled directly into TimeSpan.")] - [MemberData(nameof(IsAsyncData))] - public override Task Projection_containing_DateTime_subtraction(bool isAsync) - { - return base.Projection_containing_DateTime_subtraction(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Except(bool isAsync) - { - return base.Except(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Except_nested(bool isAsync) - { - return base.Except_nested(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Except_non_entity(bool isAsync) - { - return base.Except_non_entity(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Except_simple_followed_by_projecting_constant(bool isAsync) - { - return base.Except_simple_followed_by_projecting_constant(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Intersect(bool isAsync) - { - return base.Intersect(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Intersect_nested(bool isAsync) - { - return base.Intersect_nested(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Intersect_non_entity(bool isAsync) - { - return base.Intersect_non_entity(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Complex_nested_query_doesnt_try_binding_to_grandparent_when_parent_returns_complex_result(bool isAsync) - { - return base.Complex_nested_query_doesnt_try_binding_to_grandparent_when_parent_returns_complex_result(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task AsQueryable_in_query_server_evals(bool isAsync) - { - return base.AsQueryable_in_query_server_evals(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Project_single_element_from_collection_with_OrderBy_over_navigation_Take_and_FirstOrDefault_2(bool isAsync) - { - return base.Project_single_element_from_collection_with_OrderBy_over_navigation_Take_and_FirstOrDefault_2(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_correlated_subquery_hard(bool isAsync) - { - return base.SelectMany_correlated_subquery_hard(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_correlated_with_outer_1(bool isAsync) - { - return base.SelectMany_correlated_with_outer_1(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_correlated_with_outer_2(bool isAsync) - { - return base.SelectMany_correlated_with_outer_2(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_correlated_with_outer_3(bool isAsync) - { - return base.SelectMany_correlated_with_outer_3(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_correlated_with_outer_4(bool isAsync) - { - return base.SelectMany_correlated_with_outer_4(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_whose_selector_references_outer_source(bool isAsync) - { - return base.SelectMany_whose_selector_references_outer_source(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task SelectMany_with_collection_being_correlated_subquery_which_references_inner_and_outer_entity(bool isAsync) - { - return base.SelectMany_with_collection_being_correlated_subquery_which_references_inner_and_outer_entity(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Select_Except_reference_projection(bool isAsync) - { - return base.Select_Except_reference_projection(isAsync); - } - - [NotSupportedOnInterBaseFact] - public override void Select_nested_collection_multi_level() - { - base.Select_nested_collection_multi_level(); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Trim_with_char_array_argument_in_predicate(bool isAsync) - { - return base.Trim_with_char_array_argument_in_predicate(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task TrimEnd_with_char_array_argument_in_predicate(bool isAsync) - { - return base.TrimEnd_with_char_array_argument_in_predicate(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task TrimStart_with_char_array_argument_in_predicate(bool isAsync) - { - return base.TrimStart_with_char_array_argument_in_predicate(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Union_Intersect(bool isAsync) - { - return base.Union_Intersect(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Union_Select_scalar(bool isAsync) - { - return base.Union_Select_scalar(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_datetimeoffset_now_component(bool isAsync) - { - return base.Where_datetimeoffset_now_component(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_datetimeoffset_utcnow_component(bool isAsync) - { - return base.Where_datetimeoffset_utcnow_component(isAsync); - } - - [NotSupportedOnInterBaseTheory] - [MemberData(nameof(IsAsyncData))] - public override Task Where_datetime_utcnow(bool isAsync) - { - return base.Where_datetime_utcnow(isAsync); - } - - [Theory] - [MemberData(nameof(IsAsyncData))] - // See #19216 on EntityFrameworkCore. - public override Task Projection_of_entity_type_into_object_list(bool isAsync) - { - return AssertQuery( - isAsync, - ss => ss.Set().OrderBy(c => c.CustomerID).Select(c => new List { c }), - entryCount: 91, - assertOrder: true); - } - - [Theory] - [MemberData(nameof(IsAsyncData))] - // See #19220 on EntityFrameworkCore. - public override Task Where_subquery_anon_nested(bool isAsync) - { - return AssertQuery( - isAsync, - ss => - from t in ( - from e in ss.Set().OrderBy(ee => ee.EmployeeID).Take(3).Select( - e => new { e }).Where(e => e.e.City == "Seattle") - from o in ss.Set().OrderBy(oo => oo.OrderID).Take(5).Select( - o => new { o }) - select new { e, o }) - from c in ss.Set().OrderBy(cc => cc.CustomerID).Take(2).Select( - c => new { c }) - select new - { - t.e, - t.o, - c - }, - entryCount: 8); - } - - [Theory] - [MemberData(nameof(IsAsyncData))] - public override Task Member_binding_after_ctor_arguments_fails_with_client_eval(bool isAsync) - { - return AssertTranslationFailed(() => base.Member_binding_after_ctor_arguments_fails_with_client_eval(isAsync)); - } - - [Theory(Skip = "Temp free space")] - [MemberData(nameof(IsAsyncData))] - public override Task Handle_materialization_properly_when_more_than_two_query_sources_are_involved(bool isAsync) - { - return base.Handle_materialization_properly_when_more_than_two_query_sources_are_involved(isAsync); - } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/SqlExecutorIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/SqlExecutorIBTest.cs index eccd0fe..d5fc636 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/SqlExecutorIBTest.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/SqlExecutorIBTest.cs @@ -26,55 +26,54 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query; + +public class SqlExecutorIBTest : SqlExecutorTestBase> { - public class SqlExecutorIBTest : SqlExecutorTestBase> - { - public SqlExecutorIBTest(NorthwindQueryIBFixture fixture) - : base(fixture) - { } + public SqlExecutorIBTest(NorthwindQueryIBFixture fixture) + : base(fixture) + { } - protected override DbParameter CreateDbParameter(string name, object value) - => new IBParameter { ParameterName = name, Value = value }; + protected override DbParameter CreateDbParameter(string name, object value) + => new IBParameter { ParameterName = name, Value = value }; - protected override string TenMostExpensiveProductsSproc => throw new NotSupportedException(); - protected override string CustomerOrderHistorySproc => throw new NotSupportedException(); - protected override string CustomerOrderHistoryWithGeneratedParameterSproc => throw new NotSupportedException(); + protected override string TenMostExpensiveProductsSproc => throw new NotSupportedException(); + protected override string CustomerOrderHistorySproc => throw new NotSupportedException(); + protected override string CustomerOrderHistoryWithGeneratedParameterSproc => throw new NotSupportedException(); - [DoesNotHaveTheDataFact] - public override void Executes_stored_procedure() - { - base.Executes_stored_procedure(); - } + [DoesNotHaveTheDataFact] + public override void Executes_stored_procedure() + { + base.Executes_stored_procedure(); + } - [DoesNotHaveTheDataFact] - public override Task Executes_stored_procedure_async() - { - return base.Executes_stored_procedure_async(); - } + [DoesNotHaveTheDataFact] + public override Task Executes_stored_procedure_async() + { + return base.Executes_stored_procedure_async(); + } - [DoesNotHaveTheDataFact] - public override void Executes_stored_procedure_with_generated_parameter() - { - base.Executes_stored_procedure_with_generated_parameter(); - } + [DoesNotHaveTheDataFact] + public override void Executes_stored_procedure_with_generated_parameter() + { + base.Executes_stored_procedure_with_generated_parameter(); + } - [DoesNotHaveTheDataFact] - public override Task Executes_stored_procedure_with_generated_parameter_async() - { - return base.Executes_stored_procedure_with_generated_parameter_async(); - } + [DoesNotHaveTheDataFact] + public override Task Executes_stored_procedure_with_generated_parameter_async() + { + return base.Executes_stored_procedure_with_generated_parameter_async(); + } - [DoesNotHaveTheDataFact] - public override void Executes_stored_procedure_with_parameter() - { - base.Executes_stored_procedure_with_parameter(); - } + [DoesNotHaveTheDataFact] + public override void Executes_stored_procedure_with_parameter() + { + base.Executes_stored_procedure_with_parameter(); + } - [DoesNotHaveTheDataFact] - public override Task Executes_stored_procedure_with_parameter_async() - { - return base.Executes_stored_procedure_with_parameter_async(); - } + [DoesNotHaveTheDataFact] + public override Task Executes_stored_procedure_with_parameter_async() + { + return base.Executes_stored_procedure_with_parameter_async(); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/UdfDbFunctionIBTests.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/UdfDbFunctionIBTests.cs index eadb722..6fd50d6 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/UdfDbFunctionIBTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/UdfDbFunctionIBTests.cs @@ -19,99 +19,262 @@ //$Authors = Jiri Cincura (jiri@cincura.net) using System; +using InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Helpers; using InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.TestUtilities; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.TestUtilities; +using Xunit; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query; + +public class UdfDbFunctionIBTests : UdfDbFunctionTestBase { - public class UdfDbFunctionIBTests : UdfDbFunctionTestBase + public UdfDbFunctionIBTests(IB fixture) + : base(fixture) + { } + + [NotSupportedOnInterBaseFact] + public override void QF_CrossApply_Correlated_Select_Anonymous() + { + base.QF_CrossApply_Correlated_Select_Anonymous(); + } + + [NotSupportedOnInterBaseFact] + public override void QF_OuterApply_Correlated_Select_QF() + { + base.QF_OuterApply_Correlated_Select_QF(); + } + + [NotSupportedOnInterBaseFact] + public override void Udf_with_argument_being_comparison_of_nullable_columns() + { + base.Udf_with_argument_being_comparison_of_nullable_columns(); + } + + [NotSupportedOnInterBaseFact] + public override void QF_Select_Correlated_Subquery_In_Anonymous_MultipleCollections() + { + base.QF_Select_Correlated_Subquery_In_Anonymous_MultipleCollections(); + } + + [NotSupportedOnInterBaseFact] + public override void QF_CrossApply_Correlated_Select_Result() + { + base.QF_CrossApply_Correlated_Select_Result(); + } + + [NotSupportedOnInterBaseFact] + public override void QF_Select_Correlated_Subquery_In_Anonymous() + { + base.QF_Select_Correlated_Subquery_In_Anonymous(); + } + + [NotSupportedOnInterBaseFact] + public override void QF_Correlated_Func_Call_With_Navigation() + { + base.QF_Correlated_Func_Call_With_Navigation(); + } + + [NotSupportedOnInterBaseFact] + public override void QF_Select_Correlated_Direct_With_Function_Query_Parameter_Correlated_In_Anonymous() { - public UdfDbFunctionIBTests(IB fixture) - : base(fixture) + base.QF_Select_Correlated_Direct_With_Function_Query_Parameter_Correlated_In_Anonymous(); + } + + [NotSupportedOnInterBaseFact] + public override void QF_OuterApply_Correlated_Select_Entity() + { + base.QF_OuterApply_Correlated_Select_Entity(); + } + + [NotSupportedOnInterBaseFact] + public override void QF_Correlated_Nested_Func_Call() + { + base.QF_Correlated_Nested_Func_Call(); + } + + [NotSupportedOnInterBaseFact] + public override void QF_OuterApply_Correlated_Select_Anonymous() + { + base.QF_OuterApply_Correlated_Select_Anonymous(); + } + + [NotSupportedOnInterBaseFact] + public override void QF_Select_Correlated_Subquery_In_Anonymous_Nested_With_QF() + { + base.QF_Select_Correlated_Subquery_In_Anonymous_Nested_With_QF(); + } + + [NotSupportedOnInterBaseFact] + public override void QF_Correlated_Select_In_Anonymous() + { + base.QF_Correlated_Select_In_Anonymous(); + } + + [NotSupportedOnInterBaseFact] + public override void QF_CrossApply_Correlated_Select_QF_Type() + { + base.QF_CrossApply_Correlated_Select_QF_Type(); + } + + [NotSupportedOnInterBaseFact] + public override void Udf_with_argument_being_comparison_to_null_parameter() + { + base.Udf_with_argument_being_comparison_to_null_parameter(); + } + + [DoesNotHaveTheDataFact] + public override void QF_CrossJoin_Not_Correlated() + { + base.QF_CrossJoin_Not_Correlated(); + } + + [DoesNotHaveTheDataFact] + public override void DbSet_mapped_to_function() + { + base.DbSet_mapped_to_function(); + } + + [DoesNotHaveTheDataFact] + public override void QF_LeftJoin_Select_Result() + { + base.QF_LeftJoin_Select_Result(); + } + + [DoesNotHaveTheDataFact] + public override void QF_Join() + { + base.QF_Join(); + } + + [DoesNotHaveTheDataFact] + public override void QF_LeftJoin_Select_Anonymous() + { + base.QF_LeftJoin_Select_Anonymous(); + } + + [DoesNotHaveTheDataFact] + public override void QF_Stand_Alone_Parameter() + { + base.QF_Stand_Alone_Parameter(); + } + + [DoesNotHaveTheDataFact] + public override void QF_Stand_Alone() + { + base.QF_Stand_Alone(); + } + + [DoesNotHaveTheDataFact] + public override void QF_Nested() + { + base.QF_Nested(); + } + + [DoesNotHaveTheDataFact] + public override void QF_CrossJoin_Parameter() + { + base.QF_CrossJoin_Parameter(); + } + + [Fact(Skip = "efcore#24228")] + public override void Nullable_navigation_property_access_preserves_schema_for_sql_function() + { + base.Nullable_navigation_property_access_preserves_schema_for_sql_function(); + } + + [Fact(Skip = "efcore#24228")] + public override void Compare_function_without_null_propagation_to_null() + { + base.Compare_function_without_null_propagation_to_null(); + } + + protected class IBUDFSqlContext : UDFSqlContext + { + public IBUDFSqlContext(DbContextOptions options) + : base(options) { } - protected class IBUDFSqlContext : UDFSqlContext + protected override void OnModelCreating(ModelBuilder modelBuilder) { - public IBUDFSqlContext(DbContextOptions options) - : base(options) - { } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - - var isDateMethodInfo = typeof(UDFSqlContext).GetMethod(nameof(IsDateStatic)); - modelBuilder.HasDbFunction(isDateMethodInfo) - .HasTranslation(args => SqlFunctionExpression.Create((string)null, "IsDate", args, isDateMethodInfo.ReturnType, null)); - var isDateMethodInfo2 = typeof(UDFSqlContext).GetMethod(nameof(IsDateInstance)); - modelBuilder.HasDbFunction(isDateMethodInfo2) - .HasTranslation(args => SqlFunctionExpression.Create((string)null, "IsDate", args, isDateMethodInfo2.ReturnType, null)); - - var methodInfo = typeof(UDFSqlContext).GetMethod(nameof(MyCustomLengthStatic)); - modelBuilder.HasDbFunction(methodInfo) - .HasTranslation(args => SqlFunctionExpression.Create("char_length", args, methodInfo.ReturnType, null)); - var methodInfo2 = typeof(UDFSqlContext).GetMethod(nameof(MyCustomLengthInstance)); - modelBuilder.HasDbFunction(methodInfo2) - .HasTranslation(args => SqlFunctionExpression.Create("char_length", args, methodInfo2.ReturnType, null)); - - modelBuilder.HasDbFunction(typeof(UDFSqlContext).GetMethod(nameof(GetCustomerWithMostOrdersAfterDateStatic))) - .HasName("GetCustWithMostOrdersAfterDate"); - modelBuilder.HasDbFunction(typeof(UDFSqlContext).GetMethod(nameof(GetCustomerWithMostOrdersAfterDateInstance))) - .HasName("GetCustWithMostOrdersAfterDate"); - - modelBuilder.HasDbFunction(typeof(UDFSqlContext).GetMethod(nameof(IdentityString))) - .HasSchema(null); - } + base.OnModelCreating(modelBuilder); + + var isDateMethodInfo = typeof(UDFSqlContext).GetMethod(nameof(IsDateStatic)); + modelBuilder.HasDbFunction(isDateMethodInfo) + .HasTranslation(args => new SqlFunctionExpression(null, "IsDate", args, true, new[] { true }, isDateMethodInfo.ReturnType, null)); + var isDateMethodInfo2 = typeof(UDFSqlContext).GetMethod(nameof(IsDateInstance)); + modelBuilder.HasDbFunction(isDateMethodInfo2) + .HasTranslation(args => new SqlFunctionExpression(null, "IsDate", args, true, new[] { true }, isDateMethodInfo2.ReturnType, null)); + + var methodInfo = typeof(UDFSqlContext).GetMethod(nameof(MyCustomLengthStatic)); + modelBuilder.HasDbFunction(methodInfo) + .HasTranslation(args => new SqlFunctionExpression("char_length", args, true, new[] { true }, methodInfo.ReturnType, null)); + var methodInfo2 = typeof(UDFSqlContext).GetMethod(nameof(MyCustomLengthInstance)); + modelBuilder.HasDbFunction(methodInfo2) + .HasTranslation(args => new SqlFunctionExpression("char_length", args, true, new[] { true }, methodInfo2.ReturnType, null)); + var methodInfo3 = typeof(UDFSqlContext).GetMethod(nameof(StringLength)); + modelBuilder.HasDbFunction(methodInfo3) + .HasTranslation(args => new SqlFunctionExpression("char_length", args, true, new[] { true }, methodInfo3.ReturnType, null)); + + modelBuilder.HasDbFunction(typeof(UDFSqlContext).GetMethod(nameof(GetCustomerWithMostOrdersAfterDateStatic))) + .HasName("GetCustWithMostOrdersAfterDate"); + modelBuilder.HasDbFunction(typeof(UDFSqlContext).GetMethod(nameof(GetCustomerWithMostOrdersAfterDateInstance))) + .HasName("GetCustWithMostOrdersAfterDate"); + + modelBuilder.HasDbFunction(typeof(UDFSqlContext).GetMethod(nameof(IdentityString))) + .HasSchema(null); + + ModelHelpers.SetPrimaryKeyGeneration(modelBuilder); } + } - public class IB : UdfFixtureBase - { - protected override string StoreName { get; } = nameof(UdfDbFunctionIBTests); - protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; - protected override Type ContextType { get; } = typeof(IBUDFSqlContext); + public class IB : UdfFixtureBase + { + protected override string StoreName { get; } = nameof(UdfDbFunctionIBTests); + protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; + protected override Type ContextType { get; } = typeof(IBUDFSqlContext); - protected override void Seed(DbContext context) - { - base.Seed(context); + protected override void Seed(DbContext context) + { + base.Seed(context); - context.Database.ExecuteSqlRaw( - @"create function ""CustomerOrderCount"" (customerId int) + context.Database.ExecuteSqlRaw( + @"create function ""CustomerOrderCount"" (customerId int) returns int as begin return (select count(""Id"") from ""Orders"" where ""CustomerId"" = :customerId); end"); - context.Database.ExecuteSqlRaw( - @"create function ""StarValue"" (starCount int, val varchar(1000)) + context.Database.ExecuteSqlRaw( + @"create function ""StarValue"" (starCount int, val varchar(1000)) returns varchar(1000) as begin return rpad('', :starCount, '*') || :val; end"); - context.Database.ExecuteSqlRaw( - @"create function ""DollarValue"" (starCount int, val varchar(1000)) + context.Database.ExecuteSqlRaw( + @"create function ""DollarValue"" (starCount int, val varchar(1000)) returns varchar(1000) as begin return rpad('', :starCount, '$') || :val; end"); - context.Database.ExecuteSqlRaw( - @"create function ""GetReportingPeriodStartDate"" (period int) + context.Database.ExecuteSqlRaw( + @"create function ""GetReportingPeriodStartDate"" (period int) returns timestamp as begin return cast('1998-01-01' as timestamp); end"); - context.Database.ExecuteSqlRaw( - @"create function ""GetCustWithMostOrdersAfterDate"" (searchDate Date) + context.Database.ExecuteSqlRaw( + @"create function ""GetCustWithMostOrdersAfterDate"" (searchDate Date) returns int as begin @@ -122,8 +285,8 @@ group by ""CustomerId"" order by count(""Id"") desc); end"); - context.Database.ExecuteSqlRaw( - @"create function ""IsTopCustomer"" (customerId int) + context.Database.ExecuteSqlRaw( + @"create function ""IsTopCustomer"" (customerId int) returns boolean as begin @@ -133,16 +296,16 @@ returns boolean return false; end"); - context.Database.ExecuteSqlRaw( - @"create function ""IdentityString"" (customerName varchar(1000)) + context.Database.ExecuteSqlRaw( + @"create function ""IdentityString"" (customerName varchar(1000)) returns varchar(1000) as begin return :customerName; end"); - context.Database.ExecuteSqlRaw( - @"create function ""IsDate"" (val varchar(1000)) + context.Database.ExecuteSqlRaw( + @"create function ""IsDate"" (val varchar(1000)) returns boolean as declare dummy date; @@ -159,8 +322,7 @@ returns boolean return true; end"); - context.SaveChanges(); - } + context.SaveChanges(); } } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/WarningsIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/WarningsIBTest.cs index 4384e6b..f332fd4 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/WarningsIBTest.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/WarningsIBTest.cs @@ -20,12 +20,11 @@ using Microsoft.EntityFrameworkCore.Query; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query; + +public class WarningsIBTest : WarningsTestBase { - public class WarningsIBTest : WarningsTestBase - { - public WarningsIBTest(QueryNoClientEvalIBFixture fixture) - : base(fixture) - { } - } + public WarningsIBTest(QueryNoClientEvalIBFixture fixture) + : base(fixture) + { } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestModels/Northwind/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestModels/Northwind/Changelog.md new file mode 100644 index 0000000..99d3fc6 --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestModels/Northwind/Changelog.md @@ -0,0 +1,16 @@ +#Changes for 7.13.6 (updated for EFCore 6.0 and to Fb 9.x) + +# Changes for 7.10.2 + +## General - +* All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. + +## Common +* Namespaces changed from EntityFramework.Firebird.FunctionalTests.TestModels.Northwind to EntityFramework.InterBase.FunctionalTests.TestModels.Northwind +* Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. + +* All files renamed from FbXxxxx to IBXxxxx with the internal class matching that same change. In some cases the Fb occurs inside the name and not as a prefix. +* For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup + +* using FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests.Helpers now using InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Helpers + diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestModels/Northwind/Changelog.txt b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestModels/Northwind/Changelog.txt deleted file mode 100644 index 815a782..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestModels/Northwind/Changelog.txt +++ /dev/null @@ -1,14 +0,0 @@ -Changes for 7.10.2 - - General - - All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. - - Common - Namespaces changed from EntityFramework.Firebird.FunctionalTests.TestModels.Northwind to EntityFramework.InterBase.FunctionalTests.TestModels.Northwind - Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. - - All files renamed from FbXxxxx to IBXxxxx with the internal class matching that same change. In some cases the Fb occurs inside the name and not as a prefix. - For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup - - using FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests.Helpers now using InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Helpers - \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestModels/Northwind/NorthwindIBContext.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestModels/Northwind/NorthwindIBContext.cs index 0a62ac1..c072555 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestModels/Northwind/NorthwindIBContext.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestModels/Northwind/NorthwindIBContext.cs @@ -22,22 +22,20 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.TestModels.Northwind; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.TestModels.Northwind +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.TestModels.Northwind; + +public class NorthwindIBContext : NorthwindRelationalContext { - public class NorthwindIBContext : NorthwindRelationalContext - { - public NorthwindIBContext(DbContextOptions options) - : base(options) - { } + public NorthwindIBContext(DbContextOptions options) + : base(options) + { } - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - ModelHelpers.SetStringLengths(modelBuilder); + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + ModelHelpers.SetStringLengths(modelBuilder); - modelBuilder.Entity().HasNoKey().ToQuery( - () => CustomerQueries.FromSqlInterpolated($@"SELECT ""c"".""CustomerID"" || {_empty} as ""CustomerID"", ""c"".""Address"", ""c"".""City"", ""c"".""CompanyName"", ""c"".""ContactName"", ""c"".""ContactTitle"", ""c"".""Country"", ""c"".""Fax"", ""c"".""Phone"", ""c"".""PostalCode"", ""c"".""Region"" FROM ""Customers"" AS ""c""" - )); - } + modelBuilder.Entity().ToSqlQuery( + @"SELECT ""c"".""CustomerID"", ""c"".""Address"", ""c"".""City"", ""c"".""CompanyName"", ""c"".""ContactName"", ""c"".""ContactTitle"", ""c"".""Country"", ""c"".""Fax"", ""c"".""Phone"", ""c"".""PostalCode"", ""c"".""Region"" FROM ""Customers"" AS ""c"""); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestUtilities/IBTestHelpers.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestUtilities/IBTestHelpers.cs new file mode 100644 index 0000000..cc07fad --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestUtilities/IBTestHelpers.cs @@ -0,0 +1,43 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt. + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * All Rights Reserved. + */ + +//$Authors = Jiri Cincura (jiri@cincura.net) + +using InterBaseSql.Data.InterBaseClient; +using InterBaseSql.EntityFrameworkCore.InterBase.Diagnostics.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Microsoft.Extensions.DependencyInjection; + +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.TestUtilities; + +public class IBTestHelpers : TestHelpers +{ + protected IBTestHelpers() + { } + + public static IBTestHelpers Instance { get; } = new(); + + public override IServiceCollection AddProviderServices(IServiceCollection services) + => services.AddEntityFrameworkInterBase(); + + public override void UseProviderOptions(DbContextOptionsBuilder optionsBuilder) + => optionsBuilder.UseInterBase(new IBConnection("database=localhost:_.fdb;user=sysdba;password=masterkey;charset=utf8")); + +#pragma warning disable EF1001 + public override LoggingDefinitions LoggingDefinitions { get; } = new IBLoggingDefinitions(); +#pragma warning restore EF1001 +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestUtilities/IBTestStore.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestUtilities/IBTestStore.cs index a58c1db..4e29396 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestUtilities/IBTestStore.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestUtilities/IBTestStore.cs @@ -20,59 +20,252 @@ using System; using InterBaseSql.Data.InterBaseClient; +using InterBaseSql.Data.Isql; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.TestUtilities +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.TestUtilities; + +public class IBTestStore : RelationalTestStore { - public class IBTestStore : RelationalTestStore - { - public static IBTestStore Create(string name) - => new IBTestStore(name, shared: false); + public static IBTestStore Create(string name) + => new IBTestStore(name, shared: false); - public static IBTestStore GetOrCreate(string name) - => new IBTestStore(name, shared: true); + public static IBTestStore GetOrCreate(string name) + => new IBTestStore(name, shared: true); - public IBTestStore(string name, bool shared) - : base(name, shared) - { + public IBTestStore(string name, bool shared) + : base(name, shared) + { var path = AppDomain.CurrentDomain.BaseDirectory; - var csb = new IBConnectionStringBuilder - { - Database = $"{path}EFCore_{name}.ib", - DataSource = "localhost", - UserID = "sysdba", - Password = "masterkey", - Pooling = false, - Charset = "utf8" - }; - ConnectionString = csb.ToString(); - Connection = new IBConnection(ConnectionString); - } + var csb = new IBConnectionStringBuilder + { + Database = $"{path}EFCore_{name}.ib", + DataSource = "localhost", + UserID = "sysdba", + Password = "masterkey", + Pooling = false, + Charset = "utf8" + }; + ConnectionString = csb.ToString(); + Connection = new IBConnection(ConnectionString); + } + + protected override string OpenDelimiter => "\""; + protected override string CloseDelimiter => "\""; - protected override void Initialize(Func createContext, Action seed, Action clean) + + private static void CreateUDF(string connectionString) + { + using (var connection = new IBConnection(connectionString)) { - using (var context = createContext()) + connection.Open(); + const string text = +@"/* Use these 'wrappers' to put functionality into + any of your databases. */ + +/* Date/Time routines */ + +declare external function EF_UTCCurrentTime + returns + timestamp /* free_it */ + entry_point 'UTCCurrentTime' module_name 'EntityFrameworkUDF'; + +declare external function EF_DateAdd + cstring(7), + numeric(18, 0), + timestamp + returns + timestamp /* free_it */ + entry_point 'DateAdd' module_name 'EntityFrameworkUDF'; + +declare external function EF_DateDiff + cstring(12), + timestamp, + timestamp + returns + numeric(18,0) by value /* free_it */ + entry_point 'DateDiff' module_name 'EntityFrameworkUDF'; + +/* Mathematical functions */ + +declare external function EF_Abs + double precision + returns + double precision by value + entry_point 'fn_Abs' module_name 'EntityFrameworkUDF'; + +declare external function EF_Ceiling + double precision + returns + numeric(18,0) by value + entry_point 'fn_Ceiling' module_name 'EntityFrameworkUDF'; + +declare external function EF_Floor + double precision + returns + numeric(18, 0) by value + entry_point 'fn_Floor' module_name 'EntityFrameworkUDF'; + +declare external function EF_Round + double precision, + integer + returns + double precision by value + entry_point 'fn_Round' module_name 'EntityFrameworkUDF'; + +declare external function EF_Power + double precision, + double precision + returns + double precision by value + entry_point 'fn_Power' module_name 'EntityFrameworkUDF'; + +declare external function EF_Trunc + double precision, + integer + returns + double precision by value + entry_point 'fn_Truncate' module_name 'EntityFrameworkUDF'; + +declare external function EF_BitAnd + numeric(18, 0), + numeric(18, 0) + returns + NUMERIC(18, 0) by value + entry_point 'fn_BitAnd' module_name 'EntityFrameworkUDF'; + +declare external function EF_BitNot + numeric(18, 0) + returns + NUMERIC(18, 0) by value + entry_point 'fn_BitNot' module_name 'EntityFrameworkUDF'; + +declare external function EF_BitOr + numeric(18, 0), + numeric(18, 0) + returns + NUMERIC(18, 0) by value + entry_point 'fn_BitOr' module_name 'EntityFrameworkUDF'; + +declare external function EF_BitXor + numeric(18, 0), + numeric(18, 0) + returns + NUMERIC(18, 0) by value + entry_point 'fn_BitXor' module_name 'EntityFrameworkUDF'; + +/* String functions */ + +declare external function EF_Reverse + cstring(2048) + returns cstring(2048) /* free_it */ + entry_point 'Reverse' module_name 'EntityFrameworkUDF'; + +declare external function EF_Position + cstring(2048), + cstring(2048), + integer + returns integer by value /* free_it */ + entry_point 'Position' module_name 'EntityFrameworkUDF'; + +declare external function EF_Length + cstring(2048) + returns integer by value /* free_it */ + entry_point 'StringLength' module_name 'EntityFrameworkUDF'; + +declare external function EF_Lower + cstring(2048) + returns cstring(2048) /* free_it */ + entry_point 'ToLower' module_name 'EntityFrameworkUDF'; + +declare external function EF_Trim + cstring(8), + cstring(2048) + returns cstring(2048) /* free_it */ + entry_point 'Trim' module_name 'EntityFrameworkUDF'; + +declare external function EF_Left + cstring(2048), + integer + returns cstring(2048) /* free_it */ + entry_point 'Left' module_name 'EntityFrameworkUDF'; + +declare external function EF_Right + cstring(2048), + integer + returns cstring(2048) /* free_it */ + entry_point 'Right' module_name 'EntityFrameworkUDF'; + +declare external function EF_Replace + cstring(2048), + cstring(2048), + cstring(2048) + returns cstring(2048) /* free_it */ + entry_point 'Replace' module_name 'EntityFrameworkUDF'; + +declare external function EF_SubStr + cstring(2048), + integer, + integer + returns cstring(2048) /* free_it */ + entry_point 'SubStr' module_name 'EntityFrameworkUDF'; + +declare external function EF_NewGUID + returns cstring(16) character set OCTETS /* free_it */ + entry_point 'NewGuid' module_name 'EntityFrameworkUDF'; + +declare external function EF_UUID_TO_CHAR + cstring(16) character set OCTETS + returns cstring(38) /* free_it */ + entry_point 'UUID_TO_CHAR' module_name 'EntityFrameworkUDF'; + +declare external function EF_CHAR_TO_UUID + cstring(36) + returns cstring(16) character set OCTETS /* free_it */ + entry_point 'CHAR_TO_UUID' module_name 'EntityFrameworkUDF'; + +"; + var script = new IBScript(text); + script.Parse(); + var transaction = connection.BeginTransaction(); + + var command = connection.CreateCommand(); + + command.Transaction = transaction; + foreach (IBStatement element in script.Results) { - // create database explicitly to specify Page Size and Forced Writes - IBConnection.CreateDatabase(ConnectionString, pageSize: 16384, forcedWrites: false, overwrite: true); - context.Database.EnsureCreated(); - clean?.Invoke(context); - Clean(context); - seed?.Invoke(context); + command.CommandText = element.Text; + command.ExecuteNonQuery(); } + transaction.Commit(); } + } - public override void Dispose() + protected override void Initialize(Func createContext, Action seed, Action clean) + { + using (var context = createContext()) { - Connection.Dispose(); - base.Dispose(); + // create database explicitly to specify Page Size and Forced Writes + IBConnection.CreateDatabase(ConnectionString, pageSize: 16384, forcedWrites: false, overwrite: true); + context.Database.EnsureCreated(); + CreateUDF(ConnectionString); + clean?.Invoke(context); + Clean(context); + seed?.Invoke(context); } + } - public override DbContextOptionsBuilder AddProviderOptions(DbContextOptionsBuilder builder) - => builder.UseInterBase(Connection); - - public override void Clean(DbContext context) - { } + public override void Dispose() + { + Connection.Dispose(); + base.Dispose(); } + + public override DbContextOptionsBuilder AddProviderOptions(DbContextOptionsBuilder builder) + => builder.UseInterBase(Connection, + x => x.UseQuerySplittingBehavior(QuerySplittingBehavior.SingleQuery)); + + public override void Clean(DbContext context) + { } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestUtilities/IBTestStoreFactory.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestUtilities/IBTestStoreFactory.cs index aae5e30..1718181 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestUtilities/IBTestStoreFactory.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/TestUtilities/IBTestStoreFactory.cs @@ -24,26 +24,25 @@ using Microsoft.EntityFrameworkCore.TestUtilities; using Microsoft.Extensions.DependencyInjection; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.TestUtilities +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.TestUtilities; + +public class IBTestStoreFactory : RelationalTestStoreFactory { - public class IBTestStoreFactory : RelationalTestStoreFactory - { - public static IBTestStoreFactory Instance { get; } = new IBTestStoreFactory(); + public static IBTestStoreFactory Instance { get; } = new IBTestStoreFactory(); - static IBTestStoreFactory() - { - // See #14847 on EntityFrameworkCore. - CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture; - Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; - } + static IBTestStoreFactory() + { + // See #14847 on EntityFrameworkCore. + CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture; + Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; + } - public override TestStore Create(string storeName) - => IBTestStore.Create(storeName); + public override TestStore Create(string storeName) + => IBTestStore.Create(storeName); - public override TestStore GetOrCreate(string storeName) - => IBTestStore.GetOrCreate(storeName); + public override TestStore GetOrCreate(string storeName) + => IBTestStore.GetOrCreate(storeName); - public override IServiceCollection AddProviderServices(IServiceCollection serviceCollection) - => serviceCollection.AddEntityFrameworkInterBase(); - } + public override IServiceCollection AddProviderServices(IServiceCollection serviceCollection) + => serviceCollection.AddEntityFrameworkInterBase(); } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/UpdatesIBFixture.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/UpdatesIBFixture.cs index 368c7cc..9ace313 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/UpdatesIBFixture.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/UpdatesIBFixture.cs @@ -20,19 +20,21 @@ using InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Helpers; using InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.TestUtilities; +using InterBaseSql.EntityFrameworkCore.InterBase.Metadata; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.TestModels.UpdatesModel; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests; + +public class UpdatesIBFixture : UpdatesRelationalFixture { - public class UpdatesIBFixture : UpdatesRelationalFixture - { - protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; + protected override ITestStoreFactory TestStoreFactory => IBTestStoreFactory.Instance; - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - base.OnModelCreating(modelBuilder, context); - ModelHelpers.SetStringLengths(modelBuilder); - } + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + base.OnModelCreating(modelBuilder, context); + ModelHelpers.SetStringLengths(modelBuilder); + ModelHelpers.SetPrimaryKeyGeneration(modelBuilder, IBValueGenerationStrategy.SequenceTrigger, x => x.ClrType == typeof(Person)); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/UpdatesIBTest.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/UpdatesIBTest.cs index ea18f59..6fed2b0 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/UpdatesIBTest.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/UpdatesIBTest.cs @@ -23,32 +23,31 @@ using Microsoft.EntityFrameworkCore.TestModels.UpdatesModel; using Xunit; -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests +namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests; + +public class UpdatesIBTest : UpdatesRelationalTestBase { - public class UpdatesIBTest : UpdatesRelationalTestBase - { - public UpdatesIBTest(UpdatesIBFixture fixture) - : base(fixture) - { } + public UpdatesIBTest(UpdatesIBFixture fixture) + : base(fixture) + { } - public override void Identifiers_are_generated_correctly() + public override void Identifiers_are_generated_correctly() + { + using (var context = CreateContext()) { - using (var context = CreateContext()) - { - var entityType = context.Model.FindEntityType(typeof(LoginEntityTypeWithAnExtremelyLongAndOverlyConvolutedNameThatIsUsedToVerifyThatTheStoreIdentifierGenerationLengthLimitIsWorkingCorrectly)); - Assert.Equal( - "LoginEntityTypeWithAnExtremely~", - entityType.GetTableName()); - Assert.Equal( - "PK_LoginEntityTypeWithAnExtrem~", - entityType.GetKeys().Single().GetName()); - Assert.Equal( - "FK_LoginEntityTypeWithAnExtrem~", - entityType.GetForeignKeys().Single().GetConstraintName()); - Assert.Equal( - "IX_LoginEntityTypeWithAnExtrem~", - entityType.GetIndexes().Single().GetName()); - } + var entityType = context.Model.FindEntityType(typeof(LoginEntityTypeWithAnExtremelyLongAndOverlyConvolutedNameThatIsUsedToVerifyThatTheStoreIdentifierGenerationLengthLimitIsWorkingCorrectly)); + Assert.Equal( + "LoginEntityTypeWithAnExtremely~", + entityType.GetTableName()); + Assert.Equal( + "PK_LoginEntityTypeWithAnExtrem~", + entityType.GetKeys().Single().GetName()); + Assert.Equal( + "FK_LoginEntityTypeWithAnExtrem~", + entityType.GetForeignKeys().Single().GetConstraintName()); + Assert.Equal( + "IX_LoginEntityTypeWithAnExtrem~", + entityType.GetIndexes().Single().GetDatabaseName()); } } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/Changelog.md index 5c88c8f..80e35d8 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/Changelog.md +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/Changelog.md @@ -1,3 +1,5 @@ +# Changes for 7.13.6 (updated for EFCore 6.0 and to Fb 9.x) + # Changes for 7.12.1 ## InsertTests.cs diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/EndToEnd/DeleteTests.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/EndToEnd/DeleteTests.cs index 05d7ce3..eaf4c50 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/EndToEnd/DeleteTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/EndToEnd/DeleteTests.cs @@ -23,95 +23,94 @@ using Microsoft.EntityFrameworkCore; using NUnit.Framework; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Tests.EndToEnd +namespace InterBaseSql.EntityFrameworkCore.InterBase.Tests.EndToEnd; + +public class DeleteTests : EntityFrameworkCoreTestsBase { - public class DeleteTests : EntityFrameworkCoreTestsBase + class DeleteContext : IBTestDbContext { - class DeleteContext : IBTestDbContext - { - public DeleteContext(string connectionString) - : base(connectionString) - { } - - protected override void OnTestModelCreating(ModelBuilder modelBuilder) - { - base.OnTestModelCreating(modelBuilder); + public DeleteContext(string connectionString) + : base(connectionString) + { } - var insertEntityConf = modelBuilder.Entity(); - insertEntityConf.Property(x => x.Id).HasColumnName("ID"); - insertEntityConf.Property(x => x.Name).HasColumnName("NAME"); - insertEntityConf.ToTable("TEST_DELETE"); - } - } - class DeleteEntity + protected override void OnTestModelCreating(ModelBuilder modelBuilder) { - public int Id { get; set; } - public string Name { get; set; } + base.OnTestModelCreating(modelBuilder); + + var insertEntityConf = modelBuilder.Entity(); + insertEntityConf.Property(x => x.Id).HasColumnName("ID"); + insertEntityConf.Property(x => x.Name).HasColumnName("NAME"); + insertEntityConf.ToTable("TEST_DELETE"); } - [Test] - public void Delete() + } + class DeleteEntity + { + public int Id { get; set; } + public string Name { get; set; } + } + [Test] + public void Delete() + { + using (var db = GetDbContext()) { - using (var db = GetDbContext()) - { - db.Database.ExecuteSqlRaw("create table test_delete (id int not null, name varchar(20), primary key (ID))"); - db.Database.ExecuteSqlRaw("insert into test_delete values (65, 'test')"); - db.Database.ExecuteSqlRaw("insert into test_delete values (66, 'test')"); - db.Database.ExecuteSqlRaw("insert into test_delete values (67, 'test')"); - var entity = new DeleteEntity() { Id = 66 }; - var entry = db.Attach(entity); - entry.State = EntityState.Deleted; - db.SaveChanges(); - var values = db.Set() - .FromSqlRaw("select * from test_delete") - .AsNoTracking() - .OrderBy(x => x.Id) - .ToList(); - Assert.AreEqual(2, values.Count()); - Assert.AreEqual(65, values[0].Id); - Assert.AreEqual(67, values[1].Id); - } + db.Database.ExecuteSqlRaw("create table test_delete (id int not null, name varchar(20), primary key (ID))"); + db.Database.ExecuteSqlRaw("insert into test_delete values (65, 'test')"); + db.Database.ExecuteSqlRaw("insert into test_delete values (66, 'test')"); + db.Database.ExecuteSqlRaw("insert into test_delete values (67, 'test')"); + var entity = new DeleteEntity() { Id = 66 }; + var entry = db.Attach(entity); + entry.State = EntityState.Deleted; + db.SaveChanges(); + var values = db.Set() + .FromSqlRaw("select * from test_delete") + .AsNoTracking() + .OrderBy(x => x.Id) + .ToList(); + Assert.AreEqual(2, values.Count()); + Assert.AreEqual(65, values[0].Id); + Assert.AreEqual(67, values[1].Id); } + } - class ConcurrencyDeleteContext : IBTestDbContext - { - public ConcurrencyDeleteContext(string connectionString) - : base(connectionString) - { } - - protected override void OnTestModelCreating(ModelBuilder modelBuilder) - { - base.OnTestModelCreating(modelBuilder); + class ConcurrencyDeleteContext : IBTestDbContext + { + public ConcurrencyDeleteContext(string connectionString) + : base(connectionString) + { } - var insertEntityConf = modelBuilder.Entity(); - insertEntityConf.Property(x => x.Id).HasColumnName("ID"); - insertEntityConf.Property(x => x.Name).HasColumnName("NAME"); - insertEntityConf.Property(x => x.Stamp).HasColumnName("STAMP") - .ValueGeneratedOnAddOrUpdate() - .IsConcurrencyToken(); - insertEntityConf.ToTable("TEST_DELETE_CONCURRENCY"); - } - } - class ConcurrencyDeleteEntity + protected override void OnTestModelCreating(ModelBuilder modelBuilder) { - public int Id { get; set; } - public string Name { get; set; } - public DateTime Stamp { get; set; } + base.OnTestModelCreating(modelBuilder); + + var insertEntityConf = modelBuilder.Entity(); + insertEntityConf.Property(x => x.Id).HasColumnName("ID"); + insertEntityConf.Property(x => x.Name).HasColumnName("NAME"); + insertEntityConf.Property(x => x.Stamp).HasColumnName("STAMP") + .ValueGeneratedOnAddOrUpdate() + .IsConcurrencyToken(); + insertEntityConf.ToTable("TEST_DELETE_CONCURRENCY"); } - [Test] - public void ConcurrencyDelete() + } + class ConcurrencyDeleteEntity + { + public int Id { get; set; } + public string Name { get; set; } + public DateTime Stamp { get; set; } + } + [Test] + public void ConcurrencyDelete() + { + using (var db = GetDbContext()) { - using (var db = GetDbContext()) - { - - db.Database.ExecuteSqlRaw("create table test_delete_concurrency (id int not null, name varchar(20), stamp timestamp, primary key (id))"); - db.Database.ExecuteSqlRaw("insert into test_delete_concurrency values (65, 'test', current_timestamp)"); - db.Database.ExecuteSqlRaw("insert into test_delete_concurrency values (66, 'test', current_timestamp)"); - db.Database.ExecuteSqlRaw("insert into test_delete_concurrency values (67, 'test', current_timestamp)"); - var entity = new ConcurrencyDeleteEntity() { Id = 66, Stamp = new DateTime(1970, 1, 1) }; - var entry = db.Attach(entity); - entry.State = EntityState.Deleted; - Assert.Throws(() => db.SaveChanges()); - } + + db.Database.ExecuteSqlRaw("create table test_delete_concurrency (id int not null, name varchar(20), stamp timestamp, primary key (id))"); + db.Database.ExecuteSqlRaw("insert into test_delete_concurrency values (65, 'test', current_timestamp)"); + db.Database.ExecuteSqlRaw("insert into test_delete_concurrency values (66, 'test', current_timestamp)"); + db.Database.ExecuteSqlRaw("insert into test_delete_concurrency values (67, 'test', current_timestamp)"); + var entity = new ConcurrencyDeleteEntity() { Id = 66, Stamp = new DateTime(1970, 1, 1) }; + var entry = db.Attach(entity); + entry.State = EntityState.Deleted; + Assert.Throws(() => db.SaveChanges()); } } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/EndToEnd/InsertTests.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/EndToEnd/InsertTests.cs index eaeb99b..d78b0cc 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/EndToEnd/InsertTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/EndToEnd/InsertTests.cs @@ -24,235 +24,234 @@ using NUnit.Framework; using System.Linq; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Tests.EndToEnd +namespace InterBaseSql.EntityFrameworkCore.InterBase.Tests.EndToEnd; + +public class InsertTests : EntityFrameworkCoreTestsBase { - public class InsertTests : EntityFrameworkCoreTestsBase + class InsertContext : IBTestDbContext { - class InsertContext : IBTestDbContext - { - public InsertContext(string connectionString) - : base(connectionString) - { } - - protected override void OnTestModelCreating(ModelBuilder modelBuilder) - { - base.OnTestModelCreating(modelBuilder); + public InsertContext(string connectionString) + : base(connectionString) + { } - var insertEntityConf = modelBuilder.Entity(); - insertEntityConf.Property(x => x.Id).HasColumnName("ID"); - insertEntityConf.Property(x => x.Name).HasColumnName("NAME"); - insertEntityConf.ToTable("TEST_INSERT"); - } - } - class InsertEntity + protected override void OnTestModelCreating(ModelBuilder modelBuilder) { - public int Id { get; set; } - public string Name { get; set; } + base.OnTestModelCreating(modelBuilder); + + var insertEntityConf = modelBuilder.Entity(); + insertEntityConf.Property(x => x.Id).HasColumnName("ID"); + insertEntityConf.Property(x => x.Name).HasColumnName("NAME"); + insertEntityConf.ToTable("TEST_INSERT"); } - [Test] - public void Insert() + } + class InsertEntity + { + public int Id { get; set; } + public string Name { get; set; } + } + [Test] + public void Insert() + { + using (var db = GetDbContext()) { - using (var db = GetDbContext()) - { - db.Database.ExecuteSqlRaw("create table test_insert (id int not null primary key, name varchar(20))"); - var entity = new InsertEntity() { Id = -6, Name = "foobar" }; - db.Add(entity); - db.SaveChanges(); - Assert.AreEqual(-6, entity.Id); - } + db.Database.ExecuteSqlRaw("create table test_insert (id int not null primary key, name varchar(20))"); + var entity = new InsertEntity() { Id = -6, Name = "foobar" }; + db.Add(entity); + db.SaveChanges(); + Assert.AreEqual(-6, entity.Id); } + } - class IdentityInsertContext : IBTestDbContext - { - public IdentityInsertContext(string connectionString) - : base(connectionString) - { } - - protected override void OnTestModelCreating(ModelBuilder modelBuilder) - { - base.OnTestModelCreating(modelBuilder); + class IdentityInsertContext : IBTestDbContext + { + public IdentityInsertContext(string connectionString) + : base(connectionString) + { } - var insertEntityConf = modelBuilder.Entity(); - insertEntityConf.Property(x => x.Id).HasColumnName("ID") - .UseSequenceTrigger(); - insertEntityConf.Property(x => x.Name).HasColumnName("NAME"); - insertEntityConf.ToTable("TEST_INSERT_IDENTITY"); - } - } - class IdentityInsertEntity + protected override void OnTestModelCreating(ModelBuilder modelBuilder) { - public int Id { get; set; } - public string Name { get; set; } + base.OnTestModelCreating(modelBuilder); + + var insertEntityConf = modelBuilder.Entity(); + insertEntityConf.Property(x => x.Id).HasColumnName("ID") + .UseSequenceTrigger(); + insertEntityConf.Property(x => x.Name).HasColumnName("NAME"); + insertEntityConf.ToTable("TEST_INSERT_IDENTITY"); } + } + class IdentityInsertEntity + { + public int Id { get; set; } + public string Name { get; set; } + } // [Test] - //public void IdentityInsert() - //{ - // if (!EnsureVersion(new Version(3, 0, 0, 0))) - // return; + //public void IdentityInsert() + //{ + // if (!EnsureVersion(new Version(3, 0, 0, 0))) + // return; - // using (var db = GetDbContext()) - // { - // db.Database.ExecuteSqlRaw("create table test_insert_identity (id int generated by default as identity (start with 26) primary key, name varchar(20))"); - // var entity = new IdentityInsertEntity() { Name = "foobar" }; - // db.Add(entity); - // db.SaveChanges(); - // Assert.AreEqual(27, entity.Id); - // } - //} + // using (var db = GetDbContext()) + // { + // db.Database.ExecuteSqlRaw("create table test_insert_identity (id int generated by default as identity (start with 26) primary key, name varchar(20))"); + // var entity = new IdentityInsertEntity() { Name = "foobar" }; + // db.Add(entity); + // db.SaveChanges(); + // Assert.AreEqual(27, entity.Id); + // } + //} - class SequenceInsertContext : IBTestDbContext - { - public SequenceInsertContext(string connectionString) - : base(connectionString) - { } - - protected override void OnTestModelCreating(ModelBuilder modelBuilder) - { - base.OnTestModelCreating(modelBuilder); + class SequenceInsertContext : IBTestDbContext + { + public SequenceInsertContext(string connectionString) + : base(connectionString) + { } - var insertEntityConf = modelBuilder.Entity(); - insertEntityConf.Property(x => x.Id).HasColumnName("ID") - .UseSequenceTrigger(); - insertEntityConf.Property(x => x.Name).HasColumnName("NAME"); - insertEntityConf.ToTable("TEST_INSERT_SEQUENCE"); - } - } - class SequenceInsertEntity + protected override void OnTestModelCreating(ModelBuilder modelBuilder) { - public int Id { get; set; } - public string Name { get; set; } + base.OnTestModelCreating(modelBuilder); + var insertEntityConf = modelBuilder.Entity(); + insertEntityConf.Property(x => x.Id).HasColumnName("ID") + .UseSequenceTrigger(); + insertEntityConf.Property(x => x.Name).HasColumnName("NAME"); + insertEntityConf.ToTable("TEST_INSERT_SEQUENCE"); } + } + class SequenceInsertEntity + { + public int Id { get; set; } + public string Name { get; set; } - //[Test] - //public void SequenceInsertNoID() - //{ - // using (var db = GetDbContext()) - // { - // try - // { - // db.Database.ExecuteSqlRaw("drop table test_insert_sequence"); - // db.Database.ExecuteSqlRaw("drop generator seq_test_insert_sequence"); - // } - // catch { } - // db.Database.ExecuteSqlRaw("create table test_insert_sequence (id int not null primary key, name varchar(20))"); - // db.Database.ExecuteSqlRaw("create generator seq_test_insert_sequence"); - // db.Database.ExecuteSqlRaw("set generator seq_test_insert_sequence to 30"); - // db.Database.ExecuteSqlRaw("create trigger test_insert_sequence_id for test_insert_sequence before insert as begin if (new.id is null) then begin new.id = gen_id(seq_test_insert_sequence, 1); end end"); - // var entity = new SequenceInsertEntity() { Name = "foobar" }; - // db.Add(entity); - // db.SaveChanges(); - // var value = db.Set() - // .FromSqlRaw("select * from test_insert_sequence where name = 'foobar'") - // .AsNoTracking() - // .FirstAsync(); - // Assert.AreEqual(31, value.Result.Id); - // Assert.AreEqual("foobar", value.Result.Name); + } - // } - //} + //[Test] + //public void SequenceInsertNoID() + //{ + // using (var db = GetDbContext()) + // { + // try + // { + // db.Database.ExecuteSqlRaw("drop table test_insert_sequence"); + // db.Database.ExecuteSqlRaw("drop generator seq_test_insert_sequence"); + // } + // catch { } + // db.Database.ExecuteSqlRaw("create table test_insert_sequence (id int not null primary key, name varchar(20))"); + // db.Database.ExecuteSqlRaw("create generator seq_test_insert_sequence"); + // db.Database.ExecuteSqlRaw("set generator seq_test_insert_sequence to 30"); + // db.Database.ExecuteSqlRaw("create trigger test_insert_sequence_id for test_insert_sequence before insert as begin if (new.id is null) then begin new.id = gen_id(seq_test_insert_sequence, 1); end end"); + // var entity = new SequenceInsertEntity() { Name = "foobar" }; + // db.Add(entity); + // db.SaveChanges(); + // var value = db.Set() + // .FromSqlRaw("select * from test_insert_sequence where name = 'foobar'") + // .AsNoTracking() + // .FirstAsync(); + // Assert.AreEqual(31, value.Result.Id); + // Assert.AreEqual("foobar", value.Result.Name); - [Test] - public void SequenceInsertID() - { - using (var db = GetDbContext()) - { - db.Database.ExecuteSqlRaw("create table test_insert_sequence (id int not null primary key, name varchar(20))"); - db.Database.ExecuteSqlRaw("create generator seq_test_insert_sequence"); - db.Database.ExecuteSqlRaw("set generator seq_test_insert_sequence to 30"); - db.Database.ExecuteSqlRaw("create trigger test_insert_sequence_id for test_insert_sequence before insert as begin if (new.id is null) then begin new.id = gen_id(seq_test_insert_sequence, 1); end end"); - var entity = new SequenceInsertEntity() { Name = "foobar", Id = (int) db.GetNextSequenceValue("seq_test_insert_sequence") }; - db.Add(entity); - db.SaveChanges(); - Assert.AreEqual(31, entity.Id); - } - } + // } + //} - class DefaultValuesInsertContext : IBTestDbContext + [Test] + public void SequenceInsertID() + { + using (var db = GetDbContext()) { - public DefaultValuesInsertContext(string connectionString) - : base(connectionString) - { } + db.Database.ExecuteSqlRaw("create table test_insert_sequence (id int not null primary key, name varchar(20))"); + db.Database.ExecuteSqlRaw("create generator seq_test_insert_sequence"); + db.Database.ExecuteSqlRaw("set generator seq_test_insert_sequence to 30"); + db.Database.ExecuteSqlRaw("create trigger test_insert_sequence_id for test_insert_sequence before insert as begin if (new.id is null) then begin new.id = gen_id(seq_test_insert_sequence, 1); end end"); + var entity = new SequenceInsertEntity() { Name = "foobar", Id = (int) db.GetNextSequenceValue("seq_test_insert_sequence") }; + db.Add(entity); + db.SaveChanges(); + Assert.AreEqual(31, entity.Id); + } + } - protected override void OnTestModelCreating(ModelBuilder modelBuilder) - { - base.OnTestModelCreating(modelBuilder); + class DefaultValuesInsertContext : IBTestDbContext + { + public DefaultValuesInsertContext(string connectionString) + : base(connectionString) + { } - var insertEntityConf = modelBuilder.Entity(); - insertEntityConf.Property(x => x.Id).HasColumnName("ID") - .ValueGeneratedOnAdd(); - insertEntityConf.Property(x => x.Name).HasColumnName("NAME") - .ValueGeneratedOnAdd(); - insertEntityConf.ToTable("TEST_INSERT_DEVAULTVALUES"); - } - } - class DefaultValuesInsertEntity + protected override void OnTestModelCreating(ModelBuilder modelBuilder) { - public int Id { get; set; } - public string Name { get; set; } - } - //[Test] - //public void DefaultValuesInsert() - //{ - // if (!EnsureVersion(new Version(3, 0, 0, 0))) - // return; + base.OnTestModelCreating(modelBuilder); - // using (var db = GetDbContext()) - // { - // db.Database.ExecuteSqlRaw("create table test_insert_devaultvalues (id int generated by default as identity (start with 26) primary key, name generated always as (id || 'foobar'))"); - // var entity = new DefaultValuesInsertEntity() { }; - // db.Add(entity); - // db.SaveChanges(); - // Assert.AreEqual(27, entity.Id); - // Assert.AreEqual("27foobar", entity.Name); - // } - //} + var insertEntityConf = modelBuilder.Entity(); + insertEntityConf.Property(x => x.Id).HasColumnName("ID") + .ValueGeneratedOnAdd(); + insertEntityConf.Property(x => x.Name).HasColumnName("NAME") + .ValueGeneratedOnAdd(); + insertEntityConf.ToTable("TEST_INSERT_DEVAULTVALUES"); + } + } + class DefaultValuesInsertEntity + { + public int Id { get; set; } + public string Name { get; set; } + } + //[Test] + //public void DefaultValuesInsert() + //{ + // if (!EnsureVersion(new Version(3, 0, 0, 0))) + // return; - class TwoComputedInsertContext : IBTestDbContext - { - public DbSet anEntity { get; set; } + // using (var db = GetDbContext()) + // { + // db.Database.ExecuteSqlRaw("create table test_insert_devaultvalues (id int generated by default as identity (start with 26) primary key, name generated always as (id || 'foobar'))"); + // var entity = new DefaultValuesInsertEntity() { }; + // db.Add(entity); + // db.SaveChanges(); + // Assert.AreEqual(27, entity.Id); + // Assert.AreEqual("27foobar", entity.Name); + // } + //} - public TwoComputedInsertContext(string connectionString) - : base(connectionString) - { } + class TwoComputedInsertContext : IBTestDbContext + { + public DbSet anEntity { get; set; } - protected override void OnTestModelCreating(ModelBuilder modelBuilder) - { - base.OnTestModelCreating(modelBuilder); + public TwoComputedInsertContext(string connectionString) + : base(connectionString) + { } - var insertEntityConf = modelBuilder.Entity(); - insertEntityConf.Property(x => x.Id).HasColumnName("ID") - .UseSequenceTrigger(); - insertEntityConf.Property(x => x.Name).HasColumnName("NAME"); - insertEntityConf.Property(x => x.Computed1).HasColumnName("COMPUTED1") - .ValueGeneratedOnAddOrUpdate(); - insertEntityConf.Property(x => x.Computed2).HasColumnName("COMPUTED2") - .ValueGeneratedOnAddOrUpdate(); - insertEntityConf.ToTable("TEST_INSERT_2COMPUTED"); - } - } - class TwoComputedInsertEntity + protected override void OnTestModelCreating(ModelBuilder modelBuilder) { - public int Id { get; set; } - public string Name { get; set; } - public string Computed1 { get; set; } - public string Computed2 { get; set; } + base.OnTestModelCreating(modelBuilder); + + var insertEntityConf = modelBuilder.Entity(); + insertEntityConf.Property(x => x.Id).HasColumnName("ID") + .UseSequenceTrigger(); + insertEntityConf.Property(x => x.Name).HasColumnName("NAME"); + insertEntityConf.Property(x => x.Computed1).HasColumnName("COMPUTED1") + .ValueGeneratedOnAddOrUpdate(); + insertEntityConf.Property(x => x.Computed2).HasColumnName("COMPUTED2") + .ValueGeneratedOnAddOrUpdate(); + insertEntityConf.ToTable("TEST_INSERT_2COMPUTED"); } - [Test] - public void TwoComputedInsert() + } + class TwoComputedInsertEntity + { + public int Id { get; set; } + public string Name { get; set; } + public string Computed1 { get; set; } + public string Computed2 { get; set; } + } + [Test] + public void TwoComputedInsert() + { + using (var db = GetDbContext()) { - using (var db = GetDbContext()) - { - db.Database.ExecuteSqlRaw("create table test_insert_2computed (id int not null primary key, name varchar(20), computed1 computed by ('1' || name), computed2 computed by ('2' || name))"); - var entity = new TwoComputedInsertEntity() { Name = "foobar", Id = 1 }; - db.Add(entity); - db.SaveChanges(); - var emp = GetDbContext().anEntity - .Where(c => c.Id == 1) - .ToList().ToArray()[0]; - Assert.AreEqual("1foobar", emp.Computed1); - Assert.AreEqual("2foobar", emp.Computed2); - } + db.Database.ExecuteSqlRaw("create table test_insert_2computed (id int not null primary key, name varchar(20), computed1 computed by ('1' || name), computed2 computed by ('2' || name))"); + var entity = new TwoComputedInsertEntity() { Name = "foobar", Id = 1 }; + db.Add(entity); + db.SaveChanges(); + var emp = GetDbContext().anEntity + .Where(c => c.Id == 1) + .ToList().ToArray()[0]; + Assert.AreEqual("1foobar", emp.Computed1); + Assert.AreEqual("2foobar", emp.Computed2); } } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/EndToEnd/UpdateTests.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/EndToEnd/UpdateTests.cs index cc68d49..e4c9c5d 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/EndToEnd/UpdateTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/EndToEnd/UpdateTests.cs @@ -26,246 +26,245 @@ using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Tests.EndToEnd +namespace InterBaseSql.EntityFrameworkCore.InterBase.Tests.EndToEnd; + +public class UpdateTests : EntityFrameworkCoreTestsBase { - public class UpdateTests : EntityFrameworkCoreTestsBase + class UpdateContext : IBTestDbContext { - class UpdateContext : IBTestDbContext + public UpdateContext(string connectionString) + : base(connectionString) { - public UpdateContext(string connectionString) - : base(connectionString) - { - } - - protected override void OnTestModelCreating(ModelBuilder modelBuilder) - { - base.OnTestModelCreating(modelBuilder); - - var insertEntityConf = modelBuilder.Entity(); - insertEntityConf.Property(x => x.Id).HasColumnName("ID"); - insertEntityConf.Property(x => x.Foo).HasColumnName("FOO"); - insertEntityConf.Property(x => x.Bar).HasColumnName("BAR"); - insertEntityConf.ToTable("TEST_UPDATE"); - } } - class UpdateEntity + protected override void OnTestModelCreating(ModelBuilder modelBuilder) { - public int Id { get; set; } - public string Foo { get; set; } - public string Bar { get; set; } - } - [Test] - public void Update() - { - using (var db = GetDbContext()) - { - db.Database.ExecuteSqlRaw("create table test_update (id int not null primary key, foo varchar(20), bar varchar(20))"); - db.Database.ExecuteSqlRaw("INSERT into test_update values (66, 'foo', 'bar')"); - var entity = new UpdateEntity() { Id = 66, Foo = "test", Bar = "test" }; - var entry = db.Attach(entity); - entry.Property(x => x.Foo).IsModified = true; + base.OnTestModelCreating(modelBuilder); - try - { - db.SaveChanges(true); - } - finally - { - var value = db.Set() - .FromSqlRaw("select * from test_update where id = 66") - .AsNoTracking() - .First(); - Assert.AreEqual("test", value.Foo); - Assert.AreNotEqual("test", value.Bar); - } - } + var insertEntityConf = modelBuilder.Entity(); + insertEntityConf.Property(x => x.Id).HasColumnName("ID"); + insertEntityConf.Property(x => x.Foo).HasColumnName("FOO"); + insertEntityConf.Property(x => x.Bar).HasColumnName("BAR"); + insertEntityConf.ToTable("TEST_UPDATE"); } + } - class ComputedUpdateContext : IBTestDbContext + class UpdateEntity + { + public int Id { get; set; } + public string Foo { get; set; } + public string Bar { get; set; } + } + [Test] + public void Update() + { + using (var db = GetDbContext()) { - public ComputedUpdateContext(string connectionString) - : base(connectionString) - { } + db.Database.ExecuteSqlRaw("create table test_update (id int not null primary key, foo varchar(20), bar varchar(20))"); + db.Database.ExecuteSqlRaw("INSERT into test_update values (66, 'foo', 'bar')"); + var entity = new UpdateEntity() { Id = 66, Foo = "test", Bar = "test" }; + var entry = db.Attach(entity); + entry.Property(x => x.Foo).IsModified = true; - protected override void OnTestModelCreating(ModelBuilder modelBuilder) + try { - base.OnTestModelCreating(modelBuilder); - - var insertEntityConf = modelBuilder.Entity(); - insertEntityConf.Property(x => x.Id).HasColumnName("ID"); - insertEntityConf.Property(x => x.Foo).HasColumnName("FOO"); - insertEntityConf.Property(x => x.Bar).HasColumnName("BAR"); - insertEntityConf.Property(x => x.Fullname).HasColumnName("FULLNAME") - .ValueGeneratedOnAddOrUpdate(); - insertEntityConf.ToTable("TEST_UPDATE_COMPUTED"); + db.SaveChanges(true); } - - public DbSet ComputedUpdateEntities { get; set; } - } - class ComputedUpdateEntity - { - public int Id { get; set; } - public string Foo { get; set; } - public string Bar { get; set; } - public string Fullname { get; set; } - } - [Test] - public void ComputedUpdate() - { - using (var db = GetDbContext()) + finally { - db.Database.ExecuteSqlRaw("create table test_update_computed (id int not null primary key, foo varchar(20), bar varchar(20), fullname computed by (foo || bar))"); - db.Database.ExecuteSqlRaw("insert into test_update_computed (id, foo, bar) values (66, 'foo', 'bar')"); - var entity = new ComputedUpdateEntity() { Id = 66, Foo = "test", Bar = "test" }; - var entry = db.Attach(entity); - entry.Property(x => x.Foo).IsModified = true; - db.SaveChanges(); - entry.State = EntityState.Detached; - entity = db.ComputedUpdateEntities.FirstOrDefault(s => s.Id == 66); - Assert.AreEqual("testbar", entity.Fullname); + var value = db.Set() + .FromSqlRaw("select * from test_update where id = 66") + .AsNoTracking() + .First(); + Assert.AreEqual("test", value.Foo); + Assert.AreNotEqual("test", value.Bar); } } + } + + class ComputedUpdateContext : IBTestDbContext + { + public ComputedUpdateContext(string connectionString) + : base(connectionString) + { } - class ConcurrencyUpdateContext : IBTestDbContext + protected override void OnTestModelCreating(ModelBuilder modelBuilder) { - public ConcurrencyUpdateContext(string connectionString) - : base(connectionString) - { } + base.OnTestModelCreating(modelBuilder); - protected override void OnTestModelCreating(ModelBuilder modelBuilder) - { - base.OnTestModelCreating(modelBuilder); + var insertEntityConf = modelBuilder.Entity(); + insertEntityConf.Property(x => x.Id).HasColumnName("ID"); + insertEntityConf.Property(x => x.Foo).HasColumnName("FOO"); + insertEntityConf.Property(x => x.Bar).HasColumnName("BAR"); + insertEntityConf.Property(x => x.Fullname).HasColumnName("FULLNAME") + .ValueGeneratedOnAddOrUpdate(); + insertEntityConf.ToTable("TEST_UPDATE_COMPUTED"); + } - var insertEntityConf = modelBuilder.Entity(); - insertEntityConf.Property(x => x.Id).HasColumnName("ID"); - insertEntityConf.Property(x => x.Foo).HasColumnName("FOO"); - insertEntityConf.Property(x => x.Stamp).HasColumnName("STAMP"); -// .ValueGeneratedOnAddOrUpdate() -// .IsConcurrencyToken(); - insertEntityConf.ToTable("TEST_UPDATE_CONCURRENCY"); - } - public DbSet ConcurrencyUpdateEntities { get; set; } + public DbSet ComputedUpdateEntities { get; set; } + } + class ComputedUpdateEntity + { + public int Id { get; set; } + public string Foo { get; set; } + public string Bar { get; set; } + public string Fullname { get; set; } + } + [Test] + public void ComputedUpdate() + { + using (var db = GetDbContext()) + { + db.Database.ExecuteSqlRaw("create table test_update_computed (id int not null primary key, foo varchar(20), bar varchar(20), fullname computed by (foo || bar))"); + db.Database.ExecuteSqlRaw("insert into test_update_computed (id, foo, bar) values (66, 'foo', 'bar')"); + var entity = new ComputedUpdateEntity() { Id = 66, Foo = "test", Bar = "test" }; + var entry = db.Attach(entity); + entry.Property(x => x.Foo).IsModified = true; + db.SaveChanges(); + entry.State = EntityState.Detached; + entity = db.ComputedUpdateEntities.FirstOrDefault(s => s.Id == 66); + Assert.AreEqual("testbar", entity.Fullname); } - class ConcurrencyUpdateEntity + } + + class ConcurrencyUpdateContext : IBTestDbContext + { + public ConcurrencyUpdateContext(string connectionString) + : base(connectionString) + { } + + protected override void OnTestModelCreating(ModelBuilder modelBuilder) { - public int Id { get; set; } - public string Foo { get; set; } - public DateTime Stamp { get; set; } + base.OnTestModelCreating(modelBuilder); + + var insertEntityConf = modelBuilder.Entity(); + insertEntityConf.Property(x => x.Id).HasColumnName("ID"); + insertEntityConf.Property(x => x.Foo).HasColumnName("FOO"); + insertEntityConf.Property(x => x.Stamp).HasColumnName("STAMP") + .ValueGeneratedOnAddOrUpdate() + .IsConcurrencyToken(); + insertEntityConf.ToTable("TEST_UPDATE_CONCURRENCY"); } - [Test] - public void ConcurrencyUpdate() + public DbSet ConcurrencyUpdateEntities { get; set; } + } + class ConcurrencyUpdateEntity + { + public int Id { get; set; } + public string Foo { get; set; } + public DateTime Stamp { get; set; } + } + [Test] + public void ConcurrencyUpdate() + { + using (var db = GetDbContext()) { - using (var db = GetDbContext()) - { - db.Database.ExecuteSqlRaw("create table test_update_concurrency (id int not null primary key, foo varchar(20), stamp timestamp)"); - db.Database.ExecuteSqlRaw("insert into test_update_concurrency values (66, 'foo', current_timestamp)"); - var entity = new ConcurrencyUpdateEntity() { Id = 66, Foo = "test", Stamp = new DateTime(1970, 1, 1) }; - var entry = db.Attach(entity); - entry.Property(x => x.Foo).IsModified = true; - db.SaveChanges(); - entry.State = EntityState.Detached; - entity = db.ConcurrencyUpdateEntities.FirstOrDefault(s => s.Id == 66); - Assert.AreEqual("test", entity.Foo); - } + db.Database.ExecuteSqlRaw("create table test_update_concurrency (id int not null primary key, foo varchar(20), stamp timestamp)"); + db.Database.ExecuteSqlRaw("insert into test_update_concurrency values (66, 'foo', current_timestamp)"); + var entity = new ConcurrencyUpdateEntity() { Id = 66, Foo = "test", Stamp = new DateTime(1970, 1, 1) }; + var entry = db.Attach(entity); + entry.Property(x => x.Foo).IsModified = true; + db.SaveChanges(); + entry.State = EntityState.Detached; + entity = db.ConcurrencyUpdateEntities.FirstOrDefault(s => s.Id == 66); + Assert.AreEqual("test", entity.Foo); } + } - class ConcurrencyUpdateNoGeneratedContext : IBTestDbContext + class ConcurrencyUpdateNoGeneratedContext : IBTestDbContext + { + public ConcurrencyUpdateNoGeneratedContext(string connectionString) + : base(connectionString) { - public ConcurrencyUpdateNoGeneratedContext(string connectionString) - : base(connectionString) - { - } - protected override void OnTestModelCreating(ModelBuilder modelBuilder) - { - base.OnTestModelCreating(modelBuilder); - - var insertEntityConf = modelBuilder.Entity(); - insertEntityConf.Property(x => x.Id).HasColumnName("ID"); - insertEntityConf.Property(x => x.Foo).HasColumnName("FOO"); - insertEntityConf.Property(x => x.Stamp).HasColumnName("STAMP"); -// .ValueGeneratedOnAddOrUpdate(); -// .IsConcurrencyToken(); - insertEntityConf.ToTable("TEST_UPDATE_CONCURRENCY_NG"); - } - public DbSet Entities { get; set; } - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - base.OnConfiguring(optionsBuilder); - } } - class ConcurrencyUpdateNoGeneratedEntity + protected override void OnTestModelCreating(ModelBuilder modelBuilder) { - public int Id { get; set; } - public string Foo { get; set; } - public DateTime Stamp { get; set; } + base.OnTestModelCreating(modelBuilder); + + var insertEntityConf = modelBuilder.Entity(); + insertEntityConf.Property(x => x.Id).HasColumnName("ID"); + insertEntityConf.Property(x => x.Foo).HasColumnName("FOO"); + insertEntityConf.Property(x => x.Stamp).HasColumnName("STAMP") + .ValueGeneratedOnAddOrUpdate() + .IsConcurrencyToken(); + insertEntityConf.ToTable("TEST_UPDATE_CONCURRENCY_NG"); } - [Test] - public void ConcurrencyUpdateNoGenerated() + public DbSet Entities { get; set; } + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { - using (var db = GetDbContext()) - { - db.Database.ExecuteSqlRaw("create table test_update_concurrency_ng (id int not null primary key, foo varchar(20), stamp timestamp)"); - db.Database.ExecuteSqlRaw("INSERT into test_update_concurrency_ng values (66, 'foo', current_timestamp)"); - var entity = new ConcurrencyUpdateNoGeneratedEntity() { Id = 66, Foo = "test", Stamp = new DateTime(1970, 1, 1) }; - var entry = db.Attach(entity); - entry.Property(x => x.Foo).IsModified = true; - entry.Property(x => x.Stamp).IsModified = true; - db.SaveChanges(); - entry.State = EntityState.Detached; - entity = db.Entities.FirstOrDefault(s => s.Id == 66); - Assert.AreEqual("test", entity.Foo); - Assert.AreEqual(new DateTime(1970, 1, 1), entity.Stamp); - } + base.OnConfiguring(optionsBuilder); } - - class TwoComputedUpdateContext : IBTestDbContext + } + class ConcurrencyUpdateNoGeneratedEntity + { + public int Id { get; set; } + public string Foo { get; set; } + public DateTime Stamp { get; set; } + } + [Test] + public void ConcurrencyUpdateNoGenerated() + { + using (var db = GetDbContext()) { - public DbSet TwoComputedUpdateEntitys { get; set; } + db.Database.ExecuteSqlRaw("create table test_update_concurrency_ng (id int not null primary key, foo varchar(20), stamp timestamp)"); + db.Database.ExecuteSqlRaw("INSERT into test_update_concurrency_ng values (66, 'foo', current_timestamp)"); + var entity = new ConcurrencyUpdateNoGeneratedEntity() { Id = 66, Foo = "test", Stamp = new DateTime(1970, 1, 1) }; + var entry = db.Attach(entity); + entry.Property(x => x.Foo).IsModified = true; + entry.Property(x => x.Stamp).IsModified = true; + db.SaveChanges(); + entry.State = EntityState.Detached; + entity = db.Entities.FirstOrDefault(s => s.Id == 66); + Assert.AreEqual("test", entity.Foo); + Assert.AreEqual(new DateTime(1970, 1, 1), entity.Stamp); + } + } - public TwoComputedUpdateContext(string connectionString) - : base(connectionString) - { } + class TwoComputedUpdateContext : IBTestDbContext + { + public DbSet TwoComputedUpdateEntitys { get; set; } - protected override void OnTestModelCreating(ModelBuilder modelBuilder) - { - base.OnTestModelCreating(modelBuilder); + public TwoComputedUpdateContext(string connectionString) + : base(connectionString) + { } - var insertEntityConf = modelBuilder.Entity(); - insertEntityConf.Property(x => x.Id).HasColumnName("ID"); - insertEntityConf.Property(x => x.Foo).HasColumnName("FOO"); - insertEntityConf.Property(x => x.Bar).HasColumnName("BAR"); - insertEntityConf.Property(x => x.Computed1).HasColumnName("COMPUTED1") - .ValueGeneratedOnAddOrUpdate(); - insertEntityConf.Property(x => x.Computed2).HasColumnName("COMPUTED2") - .ValueGeneratedOnAddOrUpdate(); - insertEntityConf.ToTable("TEST_UPDATE_2COMPUTED"); - } - } - class TwoComputedUpdateEntity + protected override void OnTestModelCreating(ModelBuilder modelBuilder) { - public int Id { get; set; } - public string Foo { get; set; } - public string Bar { get; set; } - public string Computed1 { get; set; } - public string Computed2 { get; set; } + base.OnTestModelCreating(modelBuilder); + + var insertEntityConf = modelBuilder.Entity(); + insertEntityConf.Property(x => x.Id).HasColumnName("ID"); + insertEntityConf.Property(x => x.Foo).HasColumnName("FOO"); + insertEntityConf.Property(x => x.Bar).HasColumnName("BAR"); + insertEntityConf.Property(x => x.Computed1).HasColumnName("COMPUTED1") + .ValueGeneratedOnAddOrUpdate(); + insertEntityConf.Property(x => x.Computed2).HasColumnName("COMPUTED2") + .ValueGeneratedOnAddOrUpdate(); + insertEntityConf.ToTable("TEST_UPDATE_2COMPUTED"); } - [Test] - public void TwoComputedUpdate() + } + class TwoComputedUpdateEntity + { + public int Id { get; set; } + public string Foo { get; set; } + public string Bar { get; set; } + public string Computed1 { get; set; } + public string Computed2 { get; set; } + } + [Test] + public void TwoComputedUpdate() + { + using (var db = GetDbContext()) { - using (var db = GetDbContext()) - { - db.Database.ExecuteSqlRaw("create table test_update_2computed (id int not null primary key, foo varchar(20), bar varchar(20), computed1 computed by (foo || bar), computed2 computed by (bar || bar))"); - db.Database.ExecuteSqlRaw("INSERT into test_update_2computed (id, foo, bar) values (66, 'foo', 'bar')"); - var entity = new TwoComputedUpdateEntity() { Id = 66, Foo = "test", Bar = "test" }; - var entry = db.Attach(entity); - entry.Property(x => x.Foo).IsModified = true; - db.SaveChanges(); - entry.State = EntityState.Detached; - entity = db.TwoComputedUpdateEntitys.FirstOrDefault(s => s.Id == 66); - Assert.AreEqual("testbar", entity.Computed1); - Assert.AreEqual("barbar", entity.Computed2); - } + db.Database.ExecuteSqlRaw("create table test_update_2computed (id int not null primary key, foo varchar(20), bar varchar(20), computed1 computed by (foo || bar), computed2 computed by (bar || bar))"); + db.Database.ExecuteSqlRaw("INSERT into test_update_2computed (id, foo, bar) values (66, 'foo', 'bar')"); + var entity = new TwoComputedUpdateEntity() { Id = 66, Foo = "test", Bar = "test" }; + var entry = db.Attach(entity); + entry.Property(x => x.Foo).IsModified = true; + db.SaveChanges(); + entry.State = EntityState.Detached; + entity = db.TwoComputedUpdateEntitys.FirstOrDefault(s => s.Id == 66); + Assert.AreEqual("testbar", entity.Computed1); + Assert.AreEqual("barbar", entity.Computed2); } } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/EntityFrameworkCoreTestsBase.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/EntityFrameworkCoreTestsBase.cs index 62213cf..dab0b72 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/EntityFrameworkCoreTestsBase.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/EntityFrameworkCoreTestsBase.cs @@ -22,18 +22,17 @@ using InterBaseSql.Data.InterBaseClient; using InterBaseSql.Data.TestsBase; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Tests +namespace InterBaseSql.EntityFrameworkCore.InterBase.Tests; + +public abstract class EntityFrameworkCoreTestsBase : IBTestsBase { - public abstract class EntityFrameworkCoreTestsBase : IBTestsBase - { - public EntityFrameworkCoreTestsBase() - : base(IBServerType.Default, false) - { } + public EntityFrameworkCoreTestsBase() + : base(IBServerType.Default, false) + { } - public TContext GetDbContext() where TContext : IBTestDbContext - { - Connection.Close(); - return (TContext)Activator.CreateInstance(typeof(TContext), Connection.ConnectionString); - } + public TContext GetDbContext() where TContext : IBTestDbContext + { + Connection.Close(); + return (TContext)Activator.CreateInstance(typeof(TContext), Connection.ConnectionString); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/IBTestDbContext.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/IBTestDbContext.cs index 8a88544..a60d37b 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/IBTestDbContext.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/IBTestDbContext.cs @@ -27,100 +27,99 @@ using InterBaseSql.Data.InterBaseClient; using System.Runtime.InteropServices.ComTypes; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Tests +namespace InterBaseSql.EntityFrameworkCore.InterBase.Tests; + +public class IBTestDbContext : DbContext { - public class IBTestDbContext : DbContext + class LastCommandTextCommandInterceptor : DbCommandInterceptor { - class LastCommandTextCommandInterceptor : DbCommandInterceptor - { - public string LastCommandText { get; private set; } - - public override int NonQueryExecuted(DbCommand command, CommandExecutedEventData eventData, int result) - { - LastCommandText = command.CommandText; - return base.NonQueryExecuted(command, eventData, result); - } - - public override Task NonQueryExecutedAsync(DbCommand command, CommandExecutedEventData eventData, int result, CancellationToken cancellationToken = default) - { - LastCommandText = command.CommandText; - return base.NonQueryExecutedAsync(command, eventData, result, cancellationToken); - } - - public override DbDataReader ReaderExecuted(DbCommand command, CommandExecutedEventData eventData, DbDataReader result) - { - LastCommandText = command.CommandText; - return base.ReaderExecuted(command, eventData, result); - } + public string LastCommandText { get; private set; } - public override Task ReaderExecutedAsync(DbCommand command, CommandExecutedEventData eventData, DbDataReader result, CancellationToken cancellationToken = default) - { - LastCommandText = command.CommandText; - return base.ReaderExecutedAsync(command, eventData, result, cancellationToken); - } - - public override object ScalarExecuted(DbCommand command, CommandExecutedEventData eventData, object result) - { - LastCommandText = command.CommandText; - return base.ScalarExecuted(command, eventData, result); - } - - public override Task ScalarExecutedAsync(DbCommand command, CommandExecutedEventData eventData, object result, CancellationToken cancellationToken = default) - { - LastCommandText = command.CommandText; - return base.ScalarExecutedAsync(command, eventData, result, cancellationToken); - } + public override int NonQueryExecuted(DbCommand command, CommandExecutedEventData eventData, int result) + { + LastCommandText = command.CommandText; + return base.NonQueryExecuted(command, eventData, result); } - LastCommandTextCommandInterceptor _lastCommandTextInterceptor; - - readonly string _connectionString; + public override ValueTask NonQueryExecutedAsync(DbCommand command, CommandExecutedEventData eventData, int result, CancellationToken cancellationToken = default) + { + LastCommandText = command.CommandText; + return base.NonQueryExecutedAsync(command, eventData, result, cancellationToken); + } - public IBTestDbContext(string connectionString) - : base() + public override DbDataReader ReaderExecuted(DbCommand command, CommandExecutedEventData eventData, DbDataReader result) { - _connectionString = connectionString; - _lastCommandTextInterceptor = new LastCommandTextCommandInterceptor(); + LastCommandText = command.CommandText; + return base.ReaderExecuted(command, eventData, result); } - public long GetNextSequenceValue(string genName) + public override ValueTask ReaderExecutedAsync(DbCommand command, CommandExecutedEventData eventData, DbDataReader result, CancellationToken cancellationToken = default) { - using (var cmd = Database.GetDbConnection().CreateCommand()) - { - Database.GetDbConnection().Open(); - cmd.CommandText = "SELECT gen_id(" + genName + ", 1) from rdb$database"; - var obj = cmd.ExecuteScalar(); - return (long) obj; - } + LastCommandText = command.CommandText; + return base.ReaderExecutedAsync(command, eventData, result, cancellationToken); } - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + public override object ScalarExecuted(DbCommand command, CommandExecutedEventData eventData, object result) { - base.OnConfiguring(optionsBuilder); + LastCommandText = command.CommandText; + return base.ScalarExecuted(command, eventData, result); + } - optionsBuilder.UseInterBase(_connectionString); - optionsBuilder.AddInterceptors(_lastCommandTextInterceptor); + public override ValueTask ScalarExecutedAsync(DbCommand command, CommandExecutedEventData eventData, object result, CancellationToken cancellationToken = default) + { + LastCommandText = command.CommandText; + return base.ScalarExecutedAsync(command, eventData, result, cancellationToken); } - public string LastCommandText => _lastCommandTextInterceptor.LastCommandText; + } + + LastCommandTextCommandInterceptor _lastCommandTextInterceptor; + + readonly string _connectionString; + + public IBTestDbContext(string connectionString) + : base() + { + _connectionString = connectionString; + _lastCommandTextInterceptor = new LastCommandTextCommandInterceptor(); + } - protected override void OnModelCreating(ModelBuilder modelBuilder) + public long GetNextSequenceValue(string genName) + { + using (var cmd = Database.GetDbConnection().CreateCommand()) { - base.OnModelCreating(modelBuilder); - OnTestModelCreating(modelBuilder); - AfterModelCreated(modelBuilder); + Database.GetDbConnection().Open(); + cmd.CommandText = "SELECT gen_id(" + genName + ", 1) from rdb$database"; + var obj = cmd.ExecuteScalar(); + return (long) obj; } + } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + base.OnConfiguring(optionsBuilder); + + optionsBuilder.UseInterBase(_connectionString); + optionsBuilder.AddInterceptors(_lastCommandTextInterceptor); + } + public string LastCommandText => _lastCommandTextInterceptor.LastCommandText; - protected virtual void OnTestModelCreating(ModelBuilder modelBuilder) - { } + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + OnTestModelCreating(modelBuilder); + AfterModelCreated(modelBuilder); + } - protected virtual void AfterModelCreated(ModelBuilder modelBuilder) + protected virtual void OnTestModelCreating(ModelBuilder modelBuilder) + { } + + protected virtual void AfterModelCreated(ModelBuilder modelBuilder) + { + foreach (var entity in modelBuilder.Model.GetEntityTypes()) { - foreach (var entity in modelBuilder.Model.GetEntityTypes()) + foreach (var property in entity.GetProperties().Where(x => x.ClrType == typeof(string))) { - foreach (var property in entity.GetProperties().Where(x => x.ClrType == typeof(string))) - { - property.SetMaxLength(100); - } + property.SetMaxLength(100); } } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/InterBaseSql.EntityFrameworkCore.InterBase.Tests.csproj b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/InterBaseSql.EntityFrameworkCore.InterBase.Tests.csproj index c1e4a9e..9896492 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/InterBaseSql.EntityFrameworkCore.InterBase.Tests.csproj +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/InterBaseSql.EntityFrameworkCore.InterBase.Tests.csproj @@ -1,6 +1,6 @@  - netcoreapp3.1 + net6.0 false false true @@ -13,8 +13,8 @@ Ib.ico - - + + diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/Migrations/MigrationsTests.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/Migrations/MigrationsTests.cs index 53f304c..5b3ec25 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/Migrations/MigrationsTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/Migrations/MigrationsTests.cs @@ -21,6 +21,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using InterBaseSql.EntityFrameworkCore.InterBase.Metadata; using InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Internal; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -28,99 +29,99 @@ using Microsoft.EntityFrameworkCore.Migrations.Operations; using NUnit.Framework; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Tests.Migrations -{ +namespace InterBaseSql.EntityFrameworkCore.InterBase.Tests.Migrations; + #pragma warning disable EF1001 - public class MigrationsTests : EntityFrameworkCoreTestsBase +public class MigrationsTests : EntityFrameworkCoreTestsBase +{ + [Test] + public void CreateTable() { - [Test] - public void CreateTable() - { - var operation = new CreateTableOperation - { - Name = "People", - Columns = - { - new AddColumnOperation - { - Name = "Id", - Table = "People", - ClrType = typeof(int), - IsNullable = false, - [IBAnnotationNames.ValueGenerationStrategy] = IBValueGenerationStrategy.None, - }, - new AddColumnOperation - { - Name = "Id_Identity", - Table = "People", - ClrType = typeof(int), - IsNullable = false, - [IBAnnotationNames.ValueGenerationStrategy] = IBValueGenerationStrategy.IdentityColumn, - }, - new AddColumnOperation - { - Name = "Id_Sequence", - Table = "People", - ClrType = typeof(int), - IsNullable = false, - [IBAnnotationNames.ValueGenerationStrategy] = IBValueGenerationStrategy.SequenceTrigger, - }, - new AddColumnOperation - { - Name = "EmployerId", - Table = "People", - ClrType = typeof(int), - IsNullable = true, - }, - new AddColumnOperation - { - Name = "SSN", - Table = "People", - ClrType = typeof(string), - ColumnType = "char(11)", - IsNullable = true, - }, - new AddColumnOperation - { - Name = "DEF_O", - Table = "People", - ClrType = typeof(string), - MaxLength = 20, - DefaultValue = "test", - IsNullable = true, - }, - new AddColumnOperation - { - Name = "DEF_S", - Table = "People", - ClrType = typeof(string), - MaxLength = 20, - DefaultValueSql = "'x'", - IsNullable = true, - }, - }, - PrimaryKey = new AddPrimaryKeyOperation - { - Columns = new[] { "Id" }, - }, - UniqueConstraints = - { - new AddUniqueConstraintOperation - { - Columns = new[] { "SSN" }, - }, - }, - ForeignKeys = - { - new AddForeignKeyOperation - { - Columns = new[] { "EmployerId" }, - PrincipalTable = "Companies", - PrincipalColumns = new[] { "Id" }, - }, - }, - }; - var expectedCreateTable = @"CREATE TABLE ""People"" ( + var operation = new CreateTableOperation + { + Name = "People", + Columns = + { + new AddColumnOperation + { + Name = "Id", + Table = "People", + ClrType = typeof(int), + IsNullable = false, + [IBAnnotationNames.ValueGenerationStrategy] = IBValueGenerationStrategy.None, + }, + new AddColumnOperation + { + Name = "Id_Identity", + Table = "People", + ClrType = typeof(int), + IsNullable = false, + [IBAnnotationNames.ValueGenerationStrategy] = IBValueGenerationStrategy.IdentityColumn, + }, + new AddColumnOperation + { + Name = "Id_Sequence", + Table = "People", + ClrType = typeof(int), + IsNullable = false, + [IBAnnotationNames.ValueGenerationStrategy] = IBValueGenerationStrategy.SequenceTrigger, + }, + new AddColumnOperation + { + Name = "EmployerId", + Table = "People", + ClrType = typeof(int), + IsNullable = true, + }, + new AddColumnOperation + { + Name = "SSN", + Table = "People", + ClrType = typeof(string), + ColumnType = "char(11)", + IsNullable = true, + }, + new AddColumnOperation + { + Name = "DEF_O", + Table = "People", + ClrType = typeof(string), + MaxLength = 20, + DefaultValue = "test", + IsNullable = true, + }, + new AddColumnOperation + { + Name = "DEF_S", + Table = "People", + ClrType = typeof(string), + MaxLength = 20, + DefaultValueSql = "'x'", + IsNullable = true, + }, + }, + PrimaryKey = new AddPrimaryKeyOperation + { + Columns = new[] { "Id" }, + }, + UniqueConstraints = + { + new AddUniqueConstraintOperation + { + Columns = new[] { "SSN" }, + }, + }, + ForeignKeys = + { + new AddForeignKeyOperation + { + Columns = new[] { "EmployerId" }, + PrincipalTable = "Companies", + PrincipalColumns = new[] { "Id" }, + }, + }, + }; + var expectedCreateTable = @"CREATE TABLE ""People"" ( ""Id"" INTEGER NOT NULL, ""Id_Identity"" INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, ""Id_Sequence"" INTEGER NOT NULL, @@ -132,679 +133,679 @@ PRIMARY KEY (""Id""), UNIQUE (""SSN""), FOREIGN KEY (""EmployerId"") REFERENCES ""Companies"" (""Id"") ON UPDATE NO ACTION ON DELETE NO ACTION );"; - var batch = Generate(new[] { operation }); - Assert.AreEqual(3, batch.Count()); - Assert.AreEqual(expectedCreateTable, batch[0].CommandText.Trim()); - StringAssert.Contains("create generator ", batch[1].CommandText); - StringAssert.StartsWith("CREATE TRIGGER ", batch[2].CommandText); - } + var batch = Generate(new[] { operation }); + Assert.AreEqual(3, batch.Count()); + Assert.AreEqual(expectedCreateTable, batch[0].CommandText.Trim()); + StringAssert.Contains("create generator ", batch[1].CommandText); + StringAssert.StartsWith("CREATE TRIGGER ", batch[2].CommandText); + } - [Test] - public void DropTable() + [Test] + public void DropTable() + { + var operation = new DropTableOperation() { - var operation = new DropTableOperation() - { - Name = "People", - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"DROP TABLE ""People"";"), batch[0].CommandText); - } + Name = "People", + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"DROP TABLE ""People"";"), batch[0].CommandText); + } - [Test] - public void AddColumn() - { - var operation = new AddColumnOperation() - { - Table = "People", - Name = "NewColumn", - ClrType = typeof(decimal), - Schema = "schema", - IsNullable = false, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""schema"".""People"" ADD ""NewColumn"" DECIMAL(18,2) NOT NULL;"), batch[0].CommandText); - } + [Test] + public void AddColumn() + { + var operation = new AddColumnOperation() + { + Table = "People", + Name = "NewColumn", + ClrType = typeof(decimal), + Schema = "schema", + IsNullable = false, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""schema"".""People"" ADD ""NewColumn"" DECIMAL(18,2) NOT NULL;"), batch[0].CommandText); + } - [Test] - public void DropColumn() - { - var operation = new DropColumnOperation() - { - Table = "People", - Name = "DropMe", - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" DROP ""DropMe"";"), batch[0].CommandText); - } + [Test] + public void DropColumn() + { + var operation = new DropColumnOperation() + { + Table = "People", + Name = "DropMe", + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" DROP ""DropMe"";"), batch[0].CommandText); + } - [Test] - public void AlterColumnLength() + [Test] + public void AlterColumnLength() + { + var operation = new AlterColumnOperation() { - var operation = new AlterColumnOperation() + Table = "People", + Name = "Col", + ClrType = typeof(string), + IsNullable = true, + MaxLength = 200, + OldColumn = new AddColumnOperation() { - Table = "People", - Name = "Col", ClrType = typeof(string), IsNullable = true, - MaxLength = 200, - OldColumn = new ColumnOperation() - { - ClrType = typeof(string), - IsNullable = true, - MaxLength = 100, - }, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(2, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" TYPE VARCHAR(200);"), batch[1].CommandText); - } + MaxLength = 100, + }, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(2, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" TYPE VARCHAR(200);"), batch[1].CommandText); + } - [Test] - public void AlterColumnNullableToNotNull() + [Test] + public void AlterColumnNullableToNotNull() + { + var operation = new AlterColumnOperation() { - var operation = new AlterColumnOperation() + Table = "People", + Name = "Col", + ClrType = typeof(string), + IsNullable = false, + MaxLength = 100, + OldColumn = new AddColumnOperation() { - Table = "People", - Name = "Col", ClrType = typeof(string), - IsNullable = false, + IsNullable = true, MaxLength = 100, - OldColumn = new ColumnOperation() - { - ClrType = typeof(string), - IsNullable = true, - MaxLength = 100, - }, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(2, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" DROP NOT NULL;"), batch[0].CommandText); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" TYPE VARCHAR(100) NOT NULL;"), batch[1].CommandText); - } + }, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(2, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" DROP NOT NULL;"), batch[0].CommandText); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" TYPE VARCHAR(100) NOT NULL;"), batch[1].CommandText); + } - [Test] - public void AlterColumnNotNullToNullable() + [Test] + public void AlterColumnNotNullToNullable() + { + var operation = new AlterColumnOperation() { - var operation = new AlterColumnOperation() + Table = "People", + Name = "Col", + ClrType = typeof(string), + IsNullable = true, + MaxLength = 100, + OldColumn = new AddColumnOperation() { - Table = "People", - Name = "Col", ClrType = typeof(string), - IsNullable = true, + IsNullable = false, MaxLength = 100, - OldColumn = new ColumnOperation() - { - ClrType = typeof(string), - IsNullable = false, - MaxLength = 100, - }, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(2, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" DROP NOT NULL;"), batch[0].CommandText); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" TYPE VARCHAR(100);"), batch[1].CommandText); - } + }, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(2, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" DROP NOT NULL;"), batch[0].CommandText); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" TYPE VARCHAR(100);"), batch[1].CommandText); + } - [Test] - public void AlterColumnType() + [Test] + public void AlterColumnType() + { + var operation = new AlterColumnOperation() { - var operation = new AlterColumnOperation() + Table = "People", + Name = "Col", + ClrType = typeof(long), + IsNullable = false, + OldColumn = new AddColumnOperation() { - Table = "People", - Name = "Col", - ClrType = typeof(long), + ClrType = typeof(int), IsNullable = false, - OldColumn = new ColumnOperation() - { - ClrType = typeof(int), - IsNullable = false, - }, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(2, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" TYPE NUMERIC(18, 0) NOT NULL;"), batch[1].CommandText); - } + }, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(2, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" TYPE NUMERIC(18, 0) NOT NULL;"), batch[1].CommandText); + } - [Test] - public void AlterColumnDefault() + [Test] + public void AlterColumnDefault() + { + var operation = new AlterColumnOperation() { - var operation = new AlterColumnOperation() + Table = "People", + Name = "Col", + ClrType = typeof(int), + DefaultValue = 20, + OldColumn = new AddColumnOperation() { - Table = "People", - Name = "Col", ClrType = typeof(int), - DefaultValue = 20, - OldColumn = new ColumnOperation() - { - ClrType = typeof(int), - DefaultValue = 10, - }, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(4, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" TYPE INTEGER NOT NULL;"), batch[1].CommandText); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" DROP DEFAULT;"), batch[2].CommandText); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" SET DEFAULT 20;"), batch[3].CommandText); - } + DefaultValue = 10, + }, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(4, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" TYPE INTEGER NOT NULL;"), batch[1].CommandText); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" DROP DEFAULT;"), batch[2].CommandText); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" SET DEFAULT 20;"), batch[3].CommandText); + } - [Test] - public void AlterColumnAddIdentityColumn() + [Test] + public void AlterColumnAddIdentityColumn() + { + var operation = new AlterColumnOperation() { - var operation = new AlterColumnOperation() + Table = "People", + Name = "Col", + ClrType = typeof(int), + [IBAnnotationNames.ValueGenerationStrategy] = IBValueGenerationStrategy.IdentityColumn, + OldColumn = new AddColumnOperation() { - Table = "People", - Name = "Col", ClrType = typeof(int), - [IBAnnotationNames.ValueGenerationStrategy] = IBValueGenerationStrategy.IdentityColumn, - OldColumn = new ColumnOperation() - { - ClrType = typeof(int), - }, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(2, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" TYPE INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL;"), batch[1].CommandText); - } + }, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(2, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" TYPE INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL;"), batch[1].CommandText); + } - [Test] - public void AlterColumnAddSequenceTrigger() + [Test] + public void AlterColumnAddSequenceTrigger() + { + var operation = new AlterColumnOperation() { - var operation = new AlterColumnOperation() + Table = "People", + Name = "Col", + ClrType = typeof(int), + [IBAnnotationNames.ValueGenerationStrategy] = IBValueGenerationStrategy.SequenceTrigger, + OldColumn = new AddColumnOperation() { - Table = "People", - Name = "Col", ClrType = typeof(int), - [IBAnnotationNames.ValueGenerationStrategy] = IBValueGenerationStrategy.SequenceTrigger, - OldColumn = new ColumnOperation() - { - ClrType = typeof(int), - }, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(4, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" TYPE INTEGER NOT NULL;"), batch[1].CommandText); - StringAssert.Contains("create generator ", batch[2].CommandText); - StringAssert.StartsWith("CREATE TRIGGER ", batch[3].CommandText); - } + }, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(4, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" TYPE INTEGER NOT NULL;"), batch[1].CommandText); + StringAssert.Contains("create generator ", batch[2].CommandText); + StringAssert.StartsWith("CREATE TRIGGER ", batch[3].CommandText); + } - [Test] - public void AlterColumnRemoveSequenceTrigger() + [Test] + public void AlterColumnRemoveSequenceTrigger() + { + var operation = new AlterColumnOperation() { - var operation = new AlterColumnOperation() + Table = "People", + Name = "Col", + ClrType = typeof(int), + OldColumn = new AddColumnOperation() { - Table = "People", - Name = "Col", ClrType = typeof(int), - OldColumn = new ColumnOperation() - { - ClrType = typeof(int), - [IBAnnotationNames.ValueGenerationStrategy] = IBValueGenerationStrategy.SequenceTrigger, - }, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(3, batch.Count()); - StringAssert.Contains("drop trigger", batch[0].CommandText); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" TYPE INTEGER NOT NULL;"), batch[2].CommandText); - } + [IBAnnotationNames.ValueGenerationStrategy] = IBValueGenerationStrategy.SequenceTrigger, + }, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(3, batch.Count()); + StringAssert.Contains("drop trigger", batch[0].CommandText); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""Col"" TYPE INTEGER NOT NULL;"), batch[2].CommandText); + } - [Test] - public void RenameColumn() - { - var operation = new RenameColumnOperation() - { - Table = "People", - Name = "OldCol", - NewName = "NewCol", - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""OldCol"" TO ""NewCol"";"), batch[0].CommandText); - } + [Test] + public void RenameColumn() + { + var operation = new RenameColumnOperation() + { + Table = "People", + Name = "OldCol", + NewName = "NewCol", + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ALTER COLUMN ""OldCol"" TO ""NewCol"";"), batch[0].CommandText); + } - [Test] - public void CreateIndexOneColumn() - { - var operation = new CreateIndexOperation() - { - Table = "People", - Name = "MyIndex", - Columns = new[] { "Foo" }, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"CREATE INDEX ""MyIndex"" ON ""People"" (""Foo"");"), batch[0].CommandText); - } + [Test] + public void CreateIndexOneColumn() + { + var operation = new CreateIndexOperation() + { + Table = "People", + Name = "MyIndex", + Columns = new[] { "Foo" }, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"CREATE INDEX ""MyIndex"" ON ""People"" (""Foo"");"), batch[0].CommandText); + } - [Test] - public void CreateIndexThreeColumn() - { - var operation = new CreateIndexOperation() - { - Table = "People", - Name = "MyIndex", - Columns = new[] { "Foo", "Bar", "Baz" }, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"CREATE INDEX ""MyIndex"" ON ""People"" (""Foo"", ""Bar"", ""Baz"");"), batch[0].CommandText); - } + [Test] + public void CreateIndexThreeColumn() + { + var operation = new CreateIndexOperation() + { + Table = "People", + Name = "MyIndex", + Columns = new[] { "Foo", "Bar", "Baz" }, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"CREATE INDEX ""MyIndex"" ON ""People"" (""Foo"", ""Bar"", ""Baz"");"), batch[0].CommandText); + } - [Test] - public void CreateIndexUnique() - { - var operation = new CreateIndexOperation() - { - Table = "People", - Name = "MyIndex", - Columns = new[] { "Foo" }, - IsUnique = true, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"CREATE UNIQUE INDEX ""MyIndex"" ON ""People"" (""Foo"");"), batch[0].CommandText); - } + [Test] + public void CreateIndexUnique() + { + var operation = new CreateIndexOperation() + { + Table = "People", + Name = "MyIndex", + Columns = new[] { "Foo" }, + IsUnique = true, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"CREATE UNIQUE INDEX ""MyIndex"" ON ""People"" (""Foo"");"), batch[0].CommandText); + } - [Test] - public void CreateIndexFilter() - { - var operation = new CreateIndexOperation() - { - Table = "People", - Name = "MyIndex", - Filter = "xxx", - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"CREATE INDEX ""MyIndex"" ON ""People"" COMPUTED BY (xxx);"), batch[0].CommandText); - } + [Test] + public void CreateIndexFilter() + { + var operation = new CreateIndexOperation() + { + Table = "People", + Name = "MyIndex", + Filter = "xxx", + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"CREATE INDEX ""MyIndex"" ON ""People"" COMPUTED BY (xxx);"), batch[0].CommandText); + } - [Test] - public void CreateSequence() - { - var operation = new CreateSequenceOperation() - { - Name = "MySequence", - StartValue = 34, - IncrementBy = 56, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"create generator ""MySequence"" START WITH 34 INCREMENT BY 56;"), batch[0].CommandText); - } + [Test] + public void CreateSequence() + { + var operation = new CreateSequenceOperation() + { + Name = "MySequence", + StartValue = 34, + IncrementBy = 56, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"create generator ""MySequence"" START WITH 34 INCREMENT BY 56;"), batch[0].CommandText); + } - [Test] - public void AlterSequence() - { - var operation = new AlterSequenceOperation() - { - Name = "MySequence", - IncrementBy = 12, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"alter generator ""MySequence"" RESTART INCREMENT BY 12;"), batch[0].CommandText); - } + [Test] + public void AlterSequence() + { + var operation = new AlterSequenceOperation() + { + Name = "MySequence", + IncrementBy = 12, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"alter generator ""MySequence"" RESTART INCREMENT BY 12;"), batch[0].CommandText); + } - [Test] - public void RestartSequence() - { - var operation = new RestartSequenceOperation() - { - Name = "MySequence", - StartValue = 23, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"alter generator ""MySequence"" START WITH 23;"), batch[0].CommandText); - } + [Test] + public void RestartSequence() + { + var operation = new RestartSequenceOperation() + { + Name = "MySequence", + StartValue = 23, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"alter generator ""MySequence"" START WITH 23;"), batch[0].CommandText); + } - [Test] - public void DropSequence() + [Test] + public void DropSequence() + { + var operation = new DropSequenceOperation() { - var operation = new DropSequenceOperation() - { - Name = "MySequence", - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"DROP SEQUENCE ""MySequence"";"), batch[0].CommandText); - } + Name = "MySequence", + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"DROP SEQUENCE ""MySequence"";"), batch[0].CommandText); + } - [Test] - public void AddPrimaryKey() - { - var operation = new AddPrimaryKeyOperation() - { - Table = "People", - Name = "PK_People", - Columns = new[] { "Foo" }, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""PK_People"" PRIMARY KEY (""Foo"");"), batch[0].CommandText); - } + [Test] + public void AddPrimaryKey() + { + var operation = new AddPrimaryKeyOperation() + { + Table = "People", + Name = "PK_People", + Columns = new[] { "Foo" }, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""PK_People"" PRIMARY KEY (""Foo"");"), batch[0].CommandText); + } - [Test] - public void AddPrimaryKeyNoName() - { - var operation = new AddPrimaryKeyOperation() - { - Table = "People", - Columns = new[] { "Foo" }, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD PRIMARY KEY (""Foo"");"), batch[0].CommandText); - } + [Test] + public void AddPrimaryKeyNoName() + { + var operation = new AddPrimaryKeyOperation() + { + Table = "People", + Columns = new[] { "Foo" }, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD PRIMARY KEY (""Foo"");"), batch[0].CommandText); + } - [Test] - public void DropPrimaryKey() - { - var operation = new DropPrimaryKeyOperation() - { - Table = "People", - Name = "PK_People", - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" DROP CONSTRAINT ""PK_People"";"), batch[0].CommandText); - } + [Test] + public void DropPrimaryKey() + { + var operation = new DropPrimaryKeyOperation() + { + Table = "People", + Name = "PK_People", + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" DROP CONSTRAINT ""PK_People"";"), batch[0].CommandText); + } - [Test] - public void AddForeignKey() - { - var operation = new AddForeignKeyOperation() - { - Table = "People", - Name = "FK_People_Principal", - Columns = new[] { "Foo" }, - PrincipalTable = "Principal", - PrincipalColumns = new[] { "Bar" }, - OnDelete = ReferentialAction.Restrict, - OnUpdate = ReferentialAction.Restrict, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""FK_People_Principal"" FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"");"), batch[0].CommandText); - } + [Test] + public void AddForeignKey() + { + var operation = new AddForeignKeyOperation() + { + Table = "People", + Name = "FK_People_Principal", + Columns = new[] { "Foo" }, + PrincipalTable = "Principal", + PrincipalColumns = new[] { "Bar" }, + OnDelete = ReferentialAction.Restrict, + OnUpdate = ReferentialAction.Restrict, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""FK_People_Principal"" FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"");"), batch[0].CommandText); + } - [Test] - public void AddForeignKeyNoName() - { - var operation = new AddForeignKeyOperation() - { - Table = "People", - Columns = new[] { "Foo" }, - PrincipalTable = "Principal", - PrincipalColumns = new[] { "Bar" }, - OnDelete = ReferentialAction.Restrict, - OnUpdate = ReferentialAction.Restrict, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"");"), batch[0].CommandText); - } + [Test] + public void AddForeignKeyNoName() + { + var operation = new AddForeignKeyOperation() + { + Table = "People", + Columns = new[] { "Foo" }, + PrincipalTable = "Principal", + PrincipalColumns = new[] { "Bar" }, + OnDelete = ReferentialAction.Restrict, + OnUpdate = ReferentialAction.Restrict, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"");"), batch[0].CommandText); + } - [Test] - public void AddForeignKeyDeleteCascade() - { - var operation = new AddForeignKeyOperation() - { - Table = "People", - Name = "FK_People_Principal", - Columns = new[] { "Foo" }, - PrincipalTable = "Principal", - PrincipalColumns = new[] { "Bar" }, - OnDelete = ReferentialAction.Cascade, - OnUpdate = ReferentialAction.Restrict, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""FK_People_Principal"" FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"") ON DELETE CASCADE;"), batch[0].CommandText); - } + [Test] + public void AddForeignKeyDeleteCascade() + { + var operation = new AddForeignKeyOperation() + { + Table = "People", + Name = "FK_People_Principal", + Columns = new[] { "Foo" }, + PrincipalTable = "Principal", + PrincipalColumns = new[] { "Bar" }, + OnDelete = ReferentialAction.Cascade, + OnUpdate = ReferentialAction.Restrict, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""FK_People_Principal"" FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"") ON DELETE CASCADE;"), batch[0].CommandText); + } - [Test] - public void AddForeignKeyDeleteNoAction() - { - var operation = new AddForeignKeyOperation() - { - Table = "People", - Name = "FK_People_Principal", - Columns = new[] { "Foo" }, - PrincipalTable = "Principal", - PrincipalColumns = new[] { "Bar" }, - OnDelete = ReferentialAction.NoAction, - OnUpdate = ReferentialAction.Restrict, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""FK_People_Principal"" FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"") ON DELETE NO ACTION;"), batch[0].CommandText); - } + [Test] + public void AddForeignKeyDeleteNoAction() + { + var operation = new AddForeignKeyOperation() + { + Table = "People", + Name = "FK_People_Principal", + Columns = new[] { "Foo" }, + PrincipalTable = "Principal", + PrincipalColumns = new[] { "Bar" }, + OnDelete = ReferentialAction.NoAction, + OnUpdate = ReferentialAction.Restrict, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""FK_People_Principal"" FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"") ON DELETE NO ACTION;"), batch[0].CommandText); + } - [Test] - public void AddForeignKeyDeleteRestrict() - { - var operation = new AddForeignKeyOperation() - { - Table = "People", - Name = "FK_People_Principal", - Columns = new[] { "Foo" }, - PrincipalTable = "Principal", - PrincipalColumns = new[] { "Bar" }, - OnDelete = ReferentialAction.Restrict, - OnUpdate = ReferentialAction.Restrict, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""FK_People_Principal"" FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"");"), batch[0].CommandText); - } + [Test] + public void AddForeignKeyDeleteRestrict() + { + var operation = new AddForeignKeyOperation() + { + Table = "People", + Name = "FK_People_Principal", + Columns = new[] { "Foo" }, + PrincipalTable = "Principal", + PrincipalColumns = new[] { "Bar" }, + OnDelete = ReferentialAction.Restrict, + OnUpdate = ReferentialAction.Restrict, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""FK_People_Principal"" FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"");"), batch[0].CommandText); + } - [Test] - public void AddForeignKeyDeleteSetDefault() - { - var operation = new AddForeignKeyOperation() - { - Table = "People", - Name = "FK_People_Principal", - Columns = new[] { "Foo" }, - PrincipalTable = "Principal", - PrincipalColumns = new[] { "Bar" }, - OnDelete = ReferentialAction.SetDefault, - OnUpdate = ReferentialAction.Restrict, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""FK_People_Principal"" FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"") ON DELETE SET DEFAULT;"), batch[0].CommandText); - } + [Test] + public void AddForeignKeyDeleteSetDefault() + { + var operation = new AddForeignKeyOperation() + { + Table = "People", + Name = "FK_People_Principal", + Columns = new[] { "Foo" }, + PrincipalTable = "Principal", + PrincipalColumns = new[] { "Bar" }, + OnDelete = ReferentialAction.SetDefault, + OnUpdate = ReferentialAction.Restrict, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""FK_People_Principal"" FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"") ON DELETE SET DEFAULT;"), batch[0].CommandText); + } - [Test] - public void AddForeignKeyDeleteSetNull() - { - var operation = new AddForeignKeyOperation() - { - Table = "People", - Name = "FK_People_Principal", - Columns = new[] { "Foo" }, - PrincipalTable = "Principal", - PrincipalColumns = new[] { "Bar" }, - OnDelete = ReferentialAction.SetNull, - OnUpdate = ReferentialAction.Restrict, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""FK_People_Principal"" FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"") ON DELETE SET NULL;"), batch[0].CommandText); - } + [Test] + public void AddForeignKeyDeleteSetNull() + { + var operation = new AddForeignKeyOperation() + { + Table = "People", + Name = "FK_People_Principal", + Columns = new[] { "Foo" }, + PrincipalTable = "Principal", + PrincipalColumns = new[] { "Bar" }, + OnDelete = ReferentialAction.SetNull, + OnUpdate = ReferentialAction.Restrict, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""FK_People_Principal"" FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"") ON DELETE SET NULL;"), batch[0].CommandText); + } - [Test] - public void AddForeignKeyUpdateCascade() - { - var operation = new AddForeignKeyOperation() - { - Table = "People", - Name = "FK_People_Principal", - Columns = new[] { "Foo" }, - PrincipalTable = "Principal", - PrincipalColumns = new[] { "Bar" }, - OnDelete = ReferentialAction.Restrict, - OnUpdate = ReferentialAction.Cascade, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""FK_People_Principal"" FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"") ON UPDATE CASCADE;"), batch[0].CommandText); - } + [Test] + public void AddForeignKeyUpdateCascade() + { + var operation = new AddForeignKeyOperation() + { + Table = "People", + Name = "FK_People_Principal", + Columns = new[] { "Foo" }, + PrincipalTable = "Principal", + PrincipalColumns = new[] { "Bar" }, + OnDelete = ReferentialAction.Restrict, + OnUpdate = ReferentialAction.Cascade, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""FK_People_Principal"" FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"") ON UPDATE CASCADE;"), batch[0].CommandText); + } - [Test] - public void AddForeignKeyUpdateNoAction() - { - var operation = new AddForeignKeyOperation() - { - Table = "People", - Name = "FK_People_Principal", - Columns = new[] { "Foo" }, - PrincipalTable = "Principal", - PrincipalColumns = new[] { "Bar" }, - OnDelete = ReferentialAction.Restrict, - OnUpdate = ReferentialAction.NoAction, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""FK_People_Principal"" FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"") ON UPDATE NO ACTION;"), batch[0].CommandText); - } + [Test] + public void AddForeignKeyUpdateNoAction() + { + var operation = new AddForeignKeyOperation() + { + Table = "People", + Name = "FK_People_Principal", + Columns = new[] { "Foo" }, + PrincipalTable = "Principal", + PrincipalColumns = new[] { "Bar" }, + OnDelete = ReferentialAction.Restrict, + OnUpdate = ReferentialAction.NoAction, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""FK_People_Principal"" FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"") ON UPDATE NO ACTION;"), batch[0].CommandText); + } - [Test] - public void AddForeignKeyUpdateRestrict() - { - var operation = new AddForeignKeyOperation() - { - Table = "People", - Name = "FK_People_Principal", - Columns = new[] { "Foo" }, - PrincipalTable = "Principal", - PrincipalColumns = new[] { "Bar" }, - OnDelete = ReferentialAction.Restrict, - OnUpdate = ReferentialAction.Restrict, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""FK_People_Principal"" FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"");"), batch[0].CommandText); - } + [Test] + public void AddForeignKeyUpdateRestrict() + { + var operation = new AddForeignKeyOperation() + { + Table = "People", + Name = "FK_People_Principal", + Columns = new[] { "Foo" }, + PrincipalTable = "Principal", + PrincipalColumns = new[] { "Bar" }, + OnDelete = ReferentialAction.Restrict, + OnUpdate = ReferentialAction.Restrict, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""FK_People_Principal"" FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"");"), batch[0].CommandText); + } - [Test] - public void AddForeignKeyUpdateSetDefault() - { - var operation = new AddForeignKeyOperation() - { - Table = "People", - Name = "FK_People_Principal", - Columns = new[] { "Foo" }, - PrincipalTable = "Principal", - PrincipalColumns = new[] { "Bar" }, - OnDelete = ReferentialAction.Restrict, - OnUpdate = ReferentialAction.SetDefault, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""FK_People_Principal"" FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"") ON UPDATE SET DEFAULT;"), batch[0].CommandText); - } + [Test] + public void AddForeignKeyUpdateSetDefault() + { + var operation = new AddForeignKeyOperation() + { + Table = "People", + Name = "FK_People_Principal", + Columns = new[] { "Foo" }, + PrincipalTable = "Principal", + PrincipalColumns = new[] { "Bar" }, + OnDelete = ReferentialAction.Restrict, + OnUpdate = ReferentialAction.SetDefault, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""FK_People_Principal"" FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"") ON UPDATE SET DEFAULT;"), batch[0].CommandText); + } - [Test] - public void AddForeignKeyUpdateSetNull() - { - var operation = new AddForeignKeyOperation() - { - Table = "People", - Name = "FK_People_Principal", - Columns = new[] { "Foo" }, - PrincipalTable = "Principal", - PrincipalColumns = new[] { "Bar" }, - OnDelete = ReferentialAction.Restrict, - OnUpdate = ReferentialAction.SetNull, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""FK_People_Principal"" FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"") ON UPDATE SET NULL;"), batch[0].CommandText); - } + [Test] + public void AddForeignKeyUpdateSetNull() + { + var operation = new AddForeignKeyOperation() + { + Table = "People", + Name = "FK_People_Principal", + Columns = new[] { "Foo" }, + PrincipalTable = "Principal", + PrincipalColumns = new[] { "Bar" }, + OnDelete = ReferentialAction.Restrict, + OnUpdate = ReferentialAction.SetNull, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""FK_People_Principal"" FOREIGN KEY (""Foo"") REFERENCES ""Principal"" (""Bar"") ON UPDATE SET NULL;"), batch[0].CommandText); + } - [Test] - public void DropForeignKey() - { - var operation = new DropForeignKeyOperation() - { - Table = "People", - Name = "FK_People_Principal", - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" DROP CONSTRAINT ""FK_People_Principal"";"), batch[0].CommandText); - } + [Test] + public void DropForeignKey() + { + var operation = new DropForeignKeyOperation() + { + Table = "People", + Name = "FK_People_Principal", + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" DROP CONSTRAINT ""FK_People_Principal"";"), batch[0].CommandText); + } - [Test] - public void AddUniqueConstraintOneColumn() - { - var operation = new AddUniqueConstraintOperation() - { - Table = "People", - Name = "UNQ_People_Foo", - Columns = new[] { "Foo" }, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""UNQ_People_Foo"" UNIQUE (""Foo"");"), batch[0].CommandText); - } + [Test] + public void AddUniqueConstraintOneColumn() + { + var operation = new AddUniqueConstraintOperation() + { + Table = "People", + Name = "UNQ_People_Foo", + Columns = new[] { "Foo" }, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""UNQ_People_Foo"" UNIQUE (""Foo"");"), batch[0].CommandText); + } - [Test] - public void AddUniqueConstraintTwoColumns() - { - var operation = new AddUniqueConstraintOperation() - { - Table = "People", - Name = "UNQ_People_Foo_Bar", - Columns = new[] { "Foo", "Bar" }, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""UNQ_People_Foo_Bar"" UNIQUE (""Foo"", ""Bar"");"), batch[0].CommandText); - } + [Test] + public void AddUniqueConstraintTwoColumns() + { + var operation = new AddUniqueConstraintOperation() + { + Table = "People", + Name = "UNQ_People_Foo_Bar", + Columns = new[] { "Foo", "Bar" }, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD CONSTRAINT ""UNQ_People_Foo_Bar"" UNIQUE (""Foo"", ""Bar"");"), batch[0].CommandText); + } - [Test] - public void AddUniqueConstraintNoName() - { - var operation = new AddUniqueConstraintOperation() - { - Table = "People", - Columns = new[] { "Foo" }, - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD UNIQUE (""Foo"");"), batch[0].CommandText); - } + [Test] + public void AddUniqueConstraintNoName() + { + var operation = new AddUniqueConstraintOperation() + { + Table = "People", + Columns = new[] { "Foo" }, + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" ADD UNIQUE (""Foo"");"), batch[0].CommandText); + } - [Test] - public void DropUniqueConstraint() - { - var operation = new DropUniqueConstraintOperation() - { - Table = "People", - Name = "UNQ_People_Foo", - }; - var batch = Generate(new[] { operation }); - Assert.AreEqual(1, batch.Count()); - Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" DROP CONSTRAINT ""UNQ_People_Foo"";"), batch[0].CommandText); - } + [Test] + public void DropUniqueConstraint() + { + var operation = new DropUniqueConstraintOperation() + { + Table = "People", + Name = "UNQ_People_Foo", + }; + var batch = Generate(new[] { operation }); + Assert.AreEqual(1, batch.Count()); + Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" DROP CONSTRAINT ""UNQ_People_Foo"";"), batch[0].CommandText); + } - IReadOnlyList Generate(IReadOnlyList operations) + IReadOnlyList Generate(IReadOnlyList operations) + { + using (var db = GetDbContext()) { - using (var db = GetDbContext()) - { - var generator = db.GetService(); - return generator.Generate(operations, db.Model); - } + var generator = db.GetService(); + return generator.Generate(operations, db.Model); } - - static string NewLineEnd(string s) => s + Environment.NewLine; } -#pragma warning restore EF1001 + + static string NewLineEnd(string s) => s + Environment.NewLine; } +#pragma warning restore EF1001 + diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/Query/Changelogs.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/Query/Changelogs.md index 9693dc7..30545b0 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/Query/Changelogs.md +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/Query/Changelogs.md @@ -1,3 +1,5 @@ +# Changes for 7.13.6 (updated for EFCore 6.0 and to Fb 9.x) + # Changes for 7.10.2 ## General diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/Query/ElementaryTests.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/Query/ElementaryTests.cs index c012416..0a9e6d2 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/Query/ElementaryTests.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/Query/ElementaryTests.cs @@ -28,198 +28,197 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using NUnit.Framework; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Tests.Query +namespace InterBaseSql.EntityFrameworkCore.InterBase.Tests.Query; + +public class ElementaryTests : EntityFrameworkCoreTestsBase { - public class ElementaryTests : EntityFrameworkCoreTestsBase + [Test] + public void SimpleSelect() { - [Test] - public void SimpleSelect() + using (var db = GetDbContext()) { - using (var db = GetDbContext()) - { - var data = db.Set().ToList(); - Assert.IsNotEmpty(data); - } + var data = db.Set().ToList(); + Assert.IsNotEmpty(data); } + } - [Test] - public void SelectWithWhere() + [Test] + public void SelectWithWhere() + { + using (var db = GetDbContext()) { - using (var db = GetDbContext()) - { - var query = db.Set() - .Where(x => x.UserName.Trim() != string.Empty); - Assert.DoesNotThrow(() => query.Load()); - var sql = db.LastCommandText; - StringAssert.Contains("TRIM(", sql); - } + var query = db.Set() + .Where(x => x.UserName.Trim() != string.Empty); + Assert.DoesNotThrow(() => query.Load()); + var sql = db.LastCommandText; + StringAssert.Contains("TRIM(", sql); } + } - [Test] - public void SelectWithWhereExtract() + [Test] + public void SelectWithWhereExtract() + { + using (var db = GetDbContext()) { - using (var db = GetDbContext()) - { - var query = db.Set() - .Where(x => x.Timestamp.Second > -1 && x.Timestamp.DayOfYear == 1); - Assert.DoesNotThrow(() => query.Load()); - var sql = db.LastCommandText; - } + var query = db.Set() + .Where(x => x.Timestamp.Second > -1 && x.Timestamp.DayOfYear == 1); + Assert.DoesNotThrow(() => query.Load()); + var sql = db.LastCommandText; } + } - [Test] - public void SelectWithWhereSubstring() + [Test] + public void SelectWithWhereSubstring() + { + using (var db = GetDbContext()) { - using (var db = GetDbContext()) - { - var query = db.Set() - .Where(x => x.UserName.Substring(0, 1) == string.Empty && x.UserName.Substring(0, 1) == string.Empty || x.UserName.Substring(x.AttachmentId, x.AttachmentId) != string.Empty || x.UserName.Substring(x.AttachmentId, x.AttachmentId) != string.Empty); - Assert.DoesNotThrow(() => query.Load()); - var sql = db.LastCommandText; - } + var query = db.Set() + .Where(x => x.UserName.Substring(0, 1) == string.Empty && x.UserName.Substring(0, 1) == string.Empty || x.UserName.Substring(x.AttachmentId, x.AttachmentId) != string.Empty || x.UserName.Substring(x.AttachmentId, x.AttachmentId) != string.Empty); + Assert.DoesNotThrow(() => query.Load()); + var sql = db.LastCommandText; } + } - [Test] - public void SelectWithWhereDateMember() + [Test] + public void SelectWithWhereDateMember() + { + using (var db = GetDbContext()) { - using (var db = GetDbContext()) - { - var query = db.Set() - .Where(x => x.Timestamp.Date == DateTime.Now.Date); - Assert.DoesNotThrow(() => query.Load()); - var sql = db.LastCommandText; - } + var query = db.Set() + .Where(x => x.Timestamp.Date == DateTime.Now.Date); + Assert.DoesNotThrow(() => query.Load()); + var sql = db.LastCommandText; } + } - [Test] - public void SelectTake() + [Test] + public void SelectTake() + { + using (var db = GetDbContext()) { - using (var db = GetDbContext()) - { - var query = db.Set() - .Take(3); - Assert.DoesNotThrow(() => query.Load()); - var sql = db.LastCommandText; - StringAssert.IsMatch(@"ROWS \(.+\)", sql); - StringAssert.DoesNotMatch(@" TO \(", sql); - } + var query = db.Set() + .Take(3); + Assert.DoesNotThrow(() => query.Load()); + var sql = db.LastCommandText; + StringAssert.IsMatch(@"ROWS \(.+\)", sql); + StringAssert.DoesNotMatch(@" TO \(", sql); } + } - [Test] - public void SelectSkipTake() + [Test] + public void SelectSkipTake() + { + using (var db = GetDbContext()) { - using (var db = GetDbContext()) - { - var query = db.Set() - .Skip(2) - .Take(4); - Assert.DoesNotThrow(() => query.Load()); - var sql = db.LastCommandText; - StringAssert.IsMatch(@"ROWS \((.+)\) TO \(.+\)", sql); - } + var query = db.Set() + .Skip(2) + .Take(4); + Assert.DoesNotThrow(() => query.Load()); + var sql = db.LastCommandText; + StringAssert.IsMatch(@"ROWS \((.+)\) TO \(.+\)", sql); } + } - [Test] - public void SelectSkip() + [Test] + public void SelectSkip() + { + using (var db = GetDbContext()) { - using (var db = GetDbContext()) - { - var query = db.Set() - .Skip(2); - Assert.DoesNotThrow(() => query.Load()); - var sql = db.LastCommandText; - StringAssert.IsMatch(@"ROWS \(.+\) TO \(2147483647\)", sql); - } + var query = db.Set() + .Skip(2); + Assert.DoesNotThrow(() => query.Load()); + var sql = db.LastCommandText; + StringAssert.IsMatch(@"ROWS \(.+\) TO \(2147483647\)", sql); } + } - [Test] - public void SelectTopLevelAny() + [Test] + public void SelectTopLevelAny() + { + using (var db = GetDbContext()) { - using (var db = GetDbContext()) - { - Assert.DoesNotThrow(() => db.Set().Any(x => x.AttachmentId != 0)); - } + Assert.DoesNotThrow(() => db.Set().Any(x => x.AttachmentId != 0)); } } +} - class SelectContext : IBTestDbContext +class SelectContext : IBTestDbContext +{ + class LastCommandTextCommandInterceptor : DbCommandInterceptor { - class LastCommandTextCommandInterceptor : DbCommandInterceptor + public string LastCommandText { get; private set; } + + public override int NonQueryExecuted(DbCommand command, CommandExecutedEventData eventData, int result) { - public string LastCommandText { get; private set; } - - public override int NonQueryExecuted(DbCommand command, CommandExecutedEventData eventData, int result) - { - LastCommandText = command.CommandText; - return base.NonQueryExecuted(command, eventData, result); - } - - public override Task NonQueryExecutedAsync(DbCommand command, CommandExecutedEventData eventData, int result, CancellationToken cancellationToken = default) - { - LastCommandText = command.CommandText; - return base.NonQueryExecutedAsync(command, eventData, result, cancellationToken); - } - - public override DbDataReader ReaderExecuted(DbCommand command, CommandExecutedEventData eventData, DbDataReader result) - { - LastCommandText = command.CommandText; - return base.ReaderExecuted(command, eventData, result); - } - - public override Task ReaderExecutedAsync(DbCommand command, CommandExecutedEventData eventData, DbDataReader result, CancellationToken cancellationToken = default) - { - LastCommandText = command.CommandText; - return base.ReaderExecutedAsync(command, eventData, result, cancellationToken); - } - - public override object ScalarExecuted(DbCommand command, CommandExecutedEventData eventData, object result) - { - LastCommandText = command.CommandText; - return base.ScalarExecuted(command, eventData, result); - } - - public override Task ScalarExecutedAsync(DbCommand command, CommandExecutedEventData eventData, object result, CancellationToken cancellationToken = default) - { - LastCommandText = command.CommandText; - return base.ScalarExecutedAsync(command, eventData, result, cancellationToken); - } + LastCommandText = command.CommandText; + return base.NonQueryExecuted(command, eventData, result); } - LastCommandTextCommandInterceptor _lastCommandTextInterceptor; - - public SelectContext(string connectionString) - : base(connectionString) + public override ValueTask NonQueryExecutedAsync(DbCommand command, CommandExecutedEventData eventData, int result, CancellationToken cancellationToken = default) { - _lastCommandTextInterceptor = new LastCommandTextCommandInterceptor(); + LastCommandText = command.CommandText; + return base.NonQueryExecutedAsync(command, eventData, result, cancellationToken); } - protected override void OnTestModelCreating(ModelBuilder modelBuilder) + public override DbDataReader ReaderExecuted(DbCommand command, CommandExecutedEventData eventData, DbDataReader result) { - base.OnTestModelCreating(modelBuilder); - - var monAttachmentConf = modelBuilder.Entity(); - monAttachmentConf.HasKey(x => x.AttachmentId); - monAttachmentConf.Property(x => x.AttachmentId).HasColumnName("TMP$ATTACHMENT_ID"); - monAttachmentConf.Property(x => x.UserName).HasColumnName("TMP$USER"); - monAttachmentConf.Property(x => x.Timestamp).HasColumnName("TMP$TIMESTAMP"); - monAttachmentConf.ToTable("TMP$ATTACHMENTS"); + LastCommandText = command.CommandText; + return base.ReaderExecuted(command, eventData, result); } - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + public override ValueTask ReaderExecutedAsync(DbCommand command, CommandExecutedEventData eventData, DbDataReader result, CancellationToken cancellationToken = default) { - base.OnConfiguring(optionsBuilder); + LastCommandText = command.CommandText; + return base.ReaderExecutedAsync(command, eventData, result, cancellationToken); + } + public override object ScalarExecuted(DbCommand command, CommandExecutedEventData eventData, object result) + { + LastCommandText = command.CommandText; + return base.ScalarExecuted(command, eventData, result); + } - optionsBuilder.AddInterceptors(_lastCommandTextInterceptor); + public override ValueTask ScalarExecutedAsync(DbCommand command, CommandExecutedEventData eventData, object result, CancellationToken cancellationToken = default) + { + LastCommandText = command.CommandText; + return base.ScalarExecutedAsync(command, eventData, result, cancellationToken); } + } + + LastCommandTextCommandInterceptor _lastCommandTextInterceptor; + + public SelectContext(string connectionString) + : base(connectionString) + { + _lastCommandTextInterceptor = new LastCommandTextCommandInterceptor(); + } - public new string LastCommandText => _lastCommandTextInterceptor.LastCommandText; + protected override void OnTestModelCreating(ModelBuilder modelBuilder) + { + base.OnTestModelCreating(modelBuilder); + + var monAttachmentConf = modelBuilder.Entity(); + monAttachmentConf.HasKey(x => x.AttachmentId); + monAttachmentConf.Property(x => x.AttachmentId).HasColumnName("TMP$ATTACHMENT_ID"); + monAttachmentConf.Property(x => x.UserName).HasColumnName("TMP$USER"); + monAttachmentConf.Property(x => x.Timestamp).HasColumnName("TMP$TIMESTAMP"); + monAttachmentConf.ToTable("TMP$ATTACHMENTS"); } - class TMPAttachment + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { - public int AttachmentId { get; set; } - public string UserName { get; set; } - public DateTime Timestamp { get; set; } + base.OnConfiguring(optionsBuilder); + + + optionsBuilder.AddInterceptors(_lastCommandTextInterceptor); } + + public new string LastCommandText => _lastCommandTextInterceptor.LastCommandText; +} + +class TMPAttachment +{ + public int AttachmentId { get; set; } + public string UserName { get; set; } + public DateTime Timestamp { get; set; } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/Scaffolding/ScaffoldingTests.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/Scaffolding/ScaffoldingTests.cs new file mode 100644 index 0000000..97194ce --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/Scaffolding/ScaffoldingTests.cs @@ -0,0 +1,37 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt. + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * All Rights Reserved. + */ + +//$Authors = Jiri Cincura (jiri@cincura.net) + +using InterBaseSql.EntityFrameworkCore.InterBase.Scaffolding.Internal; +using Microsoft.EntityFrameworkCore.Scaffolding; +using NUnit.Framework; + +namespace InterBaseSql.EntityFrameworkCore.InterBase.Tests.Scaffolding; +#pragma warning disable EF1001 +public class ScaffoldingTests : EntityFrameworkCoreTestsBase +{ + [Test] + public void JustCanRun() + { + var modelFactory = GetModelFactory(); + Assert.DoesNotThrow(() => modelFactory.Create(Connection, new DatabaseModelFactoryOptions())); + } + + static IDatabaseModelFactory GetModelFactory() + { + return new IBDatabaseModelFactory(); + } +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Design/Internal/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Design/Internal/Changelog.md new file mode 100644 index 0000000..d616eb0 --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Design/Internal/Changelog.md @@ -0,0 +1,20 @@ +# Changes for 7.13.6 + +## IBDesignTimeServices +* Updated for EFCore 6.0 service integration + +# Changes for 7.10.2 + +## General - +* All class names and name spaces are changed to be IB vs IB or Fes. This was done so that both the IB driver and this driver it is based on will not have any naming conflicts if both used in the same application. + +## Common - +* Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Design.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Design.Internal +* Use the IB named versions of classes and variable names where appropriate moved from IB to ib prefixes. + +* All files renamed from IBXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. +* For example IBBackup.cs becomes IBBackup.cs and the class IBBackup is now IBBackup + +* using FirebirdSql.EntityFrameworkCore.Firebird.Diagnostics.Internal, FirebirdSql.EntityFrameworkCore.Firebird.Scaffolding.Internal and FirebirdSql.EntityFrameworkCore.Firebird.Storage.Internal +* now InterBaseSql.EntityFrameworkCore.InterBase.Diagnostics.Internal, InterBaseSql.EntityFrameworkCore.InterBase.Scaffolding.Internal and InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; + diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Design/Internal/Changelog.txt b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Design/Internal/Changelog.txt deleted file mode 100644 index ea57668..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Design/Internal/Changelog.txt +++ /dev/null @@ -1,15 +0,0 @@ -Changes for 7.10.2 - - General - - All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. - - Common - - Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Design.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Design.Internal - Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. - - All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. - For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup - - using FirebirdSql.EntityFrameworkCore.Firebird.Diagnostics.Internal, FirebirdSql.EntityFrameworkCore.Firebird.Scaffolding.Internal and FirebirdSql.EntityFrameworkCore.Firebird.Storage.Internal - now InterBaseSql.EntityFrameworkCore.InterBase.Diagnostics.Internal, InterBaseSql.EntityFrameworkCore.InterBase.Scaffolding.Internal and InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; - diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Design/Internal/IBDesignTimeServices.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Design/Internal/IBDesignTimeServices.cs index 0ac4659..ebd3f00 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Design/Internal/IBDesignTimeServices.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Design/Internal/IBDesignTimeServices.cs @@ -18,25 +18,23 @@ //$Authors = Jiri Cincura (jiri@cincura.net), Jean Ressouche, Rafael Almeida (ralms@ralms.net) -using InterBaseSql.EntityFrameworkCore.InterBase.Diagnostics.Internal; using InterBaseSql.EntityFrameworkCore.InterBase.Scaffolding.Internal; -using InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; +using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; -using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Scaffolding; -using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.DependencyInjection; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Design.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Design.Internal; + +public class IBDesignTimeServices : IDesignTimeServices { - public class IBDesignTimeServices : IDesignTimeServices + public void ConfigureDesignTimeServices(IServiceCollection serviceCollection) { - public void ConfigureDesignTimeServices(IServiceCollection serviceCollection) - => serviceCollection - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton(); + serviceCollection.AddEntityFrameworkInterBase(); + new EntityFrameworkRelationalDesignServicesBuilder(serviceCollection) + .TryAdd() + .TryAdd() + .TryAdd() + .TryAddCoreServices(); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Diagnostics/Internal/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Diagnostics/Internal/Changelog.md new file mode 100644 index 0000000..eb66d15 --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Diagnostics/Internal/Changelog.md @@ -0,0 +1,11 @@ +# Changes for 7.10.2 + +## General - +* All class names and name spaces are changed to be IB vs IB or Fes. This was done so that both the IB driver and this driver it is based on will not have any naming conflicts if both used in the same application. + +## Common - +* Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Diagnostics.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Diagnostics.Internal +* Use the IB named versions of classes and variable names where appropriate moved from IB to ib prefixes. + +* All files renamed from IBXxxxx to IBXxxxx with the internal class matching that same change. +* For example IBBackup.cs becomes IBBackup.cs and the class IBBackup is now IBBackup diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Diagnostics/Internal/Changelog.txt b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Diagnostics/Internal/Changelog.txt deleted file mode 100644 index 580cfa6..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Diagnostics/Internal/Changelog.txt +++ /dev/null @@ -1,11 +0,0 @@ -Changes for 7.10.2 - - General - - All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. - - Common - - Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Diagnostics.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Diagnostics.Internal - Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. - - All files renamed from FbXxxxx to IBXxxxx with the internal class matching that same change. - For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Diagnostics/Internal/IBLoggingDefinitions.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Diagnostics/Internal/IBLoggingDefinitions.cs index 68f8ad9..2fd54cf 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Diagnostics/Internal/IBLoggingDefinitions.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Diagnostics/Internal/IBLoggingDefinitions.cs @@ -20,8 +20,7 @@ using Microsoft.EntityFrameworkCore.Diagnostics; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Diagnostics.Internal -{ - public class IBLoggingDefinitions : RelationalLoggingDefinitions - { } -} +namespace InterBaseSql.EntityFrameworkCore.InterBase.Diagnostics.Internal; + +public class IBLoggingDefinitions : RelationalLoggingDefinitions +{ } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/Changelog.md index c41c79f..e1537df 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/Changelog.md +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/Changelog.md @@ -1,3 +1,19 @@ +# Changes for 7.13.6 + +## IBModelBuilderExtensions.cs +* Removed IdentityColumn as IB does not support Identity columns + +## IBModelExtensions.cs +* added 2 more GetValueGenerationStrategys + +## IBPropertyExtensions.cs +* Fixed up procedure signature changes to EFCore 6.0 +* additional IdentityColumn removal stuff + +## IBServiceCollectionExtensions.cs +* added AddInterBase function +* UpdatedAddEntityFrameworkInterBase for EFCore 6.0 + # Changes for 7.12.1 * For now IBValueGenerationStrategy.IdentityColumn remains, but is not a language feature supported by InterBase diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBDatabaseFacadeExtensions.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBDatabaseFacadeExtensions.cs index 9952605..175ab4f 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBDatabaseFacadeExtensions.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBDatabaseFacadeExtensions.cs @@ -3,33 +3,32 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Extensions -{ - using System; +namespace InterBaseSql.EntityFrameworkCore.InterBase.Extensions; + +using System; +/// +/// InterBaseSQL specific extension methods for . +/// +public static class IBDatabaseFacadeExtensions +{ /// - /// InterBaseSQL specific extension methods for . + /// + /// Returns true if the database provider currently in use is the InterBaseSQL provider. + /// + /// + /// This method can only be used after the has been configured because + /// it is only then that the provider is known. This means that this method cannot be used + /// in because this is where application code sets the + /// provider to use as part of configuring the context. + /// /// - public static class IBDatabaseFacadeExtensions - { - /// - /// - /// Returns true if the database provider currently in use is the InterBaseSQL provider. - /// - /// - /// This method can only be used after the has been configured because - /// it is only then that the provider is known. This means that this method cannot be used - /// in because this is where application code sets the - /// provider to use as part of configuring the context. - /// - /// - /// - /// The facade from . - /// - /// - /// True if InterBasedSQL is being used; false otherwise. - /// - public static bool IsInterBase(this DatabaseFacade database) - => database.ProviderName.Equals(typeof(IBOptionsExtension).GetTypeInfo().Assembly.GetName().Name, StringComparison.Ordinal); - } + /// + /// The facade from . + /// + /// + /// True if InterBasedSQL is being used; false otherwise. + /// + public static bool IsInterBase(this DatabaseFacade database) + => database.ProviderName.Equals(typeof(IBOptionsExtension).GetTypeInfo().Assembly.GetName().Name, StringComparison.Ordinal); } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBDbContextOptionsBuilderExtensions.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBDbContextOptionsBuilderExtensions.cs index f3d9fec..37f58ee 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBDbContextOptionsBuilderExtensions.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBDbContextOptionsBuilderExtensions.cs @@ -24,40 +24,39 @@ using InterBaseSql.EntityFrameworkCore.InterBase.Infrastructure.Internal; using Microsoft.EntityFrameworkCore.Infrastructure; -namespace Microsoft.EntityFrameworkCore +namespace Microsoft.EntityFrameworkCore; + +public static class IBDbContextOptionsBuilderExtensions { - public static class IBDbContextOptionsBuilderExtensions + public static DbContextOptionsBuilder UseInterBase(this DbContextOptionsBuilder optionsBuilder, string connectionString, Action ibOptionsAction = null) + { + var extension = (IBOptionsExtension)GetOrCreateExtension(optionsBuilder).WithConnectionString(connectionString); + ((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension); + ibOptionsAction?.Invoke(new IBDbContextOptionsBuilder(optionsBuilder)); + return optionsBuilder; + } + + public static DbContextOptionsBuilder UseInterBase(this DbContextOptionsBuilder optionsBuilder, DbConnection connection, Action ibOptionsAction = null) { - public static DbContextOptionsBuilder UseInterBase(this DbContextOptionsBuilder optionsBuilder, string connectionString, Action ibOptionsAction = null) - { - var extension = (IBOptionsExtension)GetOrCreateExtension(optionsBuilder).WithConnectionString(connectionString); - ((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension); - ibOptionsAction?.Invoke(new IBDbContextOptionsBuilder(optionsBuilder)); - return optionsBuilder; - } - - public static DbContextOptionsBuilder UseInterBase(this DbContextOptionsBuilder optionsBuilder, DbConnection connection, Action ibOptionsAction = null) - { - var extension = (IBOptionsExtension)GetOrCreateExtension(optionsBuilder).WithConnection(connection); - ((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension); - ibOptionsAction?.Invoke(new IBDbContextOptionsBuilder(optionsBuilder)); - return optionsBuilder; - } - - public static DbContextOptionsBuilder UseInterBase(this DbContextOptionsBuilder optionsBuilder, string connectionString, Action ibOptionsAction = null) - where TContext : DbContext - { - return (DbContextOptionsBuilder)UseInterBase((DbContextOptionsBuilder)optionsBuilder, connectionString, ibOptionsAction); - } - - public static DbContextOptionsBuilder UseInterBase(this DbContextOptionsBuilder optionsBuilder, DbConnection connection, Action ibOptionsAction = null) - where TContext : DbContext - { - return (DbContextOptionsBuilder)UseInterBase((DbContextOptionsBuilder)optionsBuilder, connection, ibOptionsAction); - } - - static IBOptionsExtension GetOrCreateExtension(DbContextOptionsBuilder optionsBuilder) - => optionsBuilder.Options.FindExtension() - ?? new IBOptionsExtension(); + var extension = (IBOptionsExtension)GetOrCreateExtension(optionsBuilder).WithConnection(connection); + ((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension); + ibOptionsAction?.Invoke(new IBDbContextOptionsBuilder(optionsBuilder)); + return optionsBuilder; } + + public static DbContextOptionsBuilder UseInterBase(this DbContextOptionsBuilder optionsBuilder, string connectionString, Action ibOptionsAction = null) + where TContext : DbContext + { + return (DbContextOptionsBuilder)UseInterBase((DbContextOptionsBuilder)optionsBuilder, connectionString, ibOptionsAction); + } + + public static DbContextOptionsBuilder UseInterBase(this DbContextOptionsBuilder optionsBuilder, DbConnection connection, Action ibOptionsAction = null) + where TContext : DbContext + { + return (DbContextOptionsBuilder)UseInterBase((DbContextOptionsBuilder)optionsBuilder, connection, ibOptionsAction); + } + + static IBOptionsExtension GetOrCreateExtension(DbContextOptionsBuilder optionsBuilder) + => optionsBuilder.Options.FindExtension() + ?? new IBOptionsExtension(); } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBModelBuilderExtensions.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBModelBuilderExtensions.cs index a57ed47..3299b5e 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBModelBuilderExtensions.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBModelBuilderExtensions.cs @@ -22,38 +22,37 @@ using InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Internal; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Microsoft.EntityFrameworkCore +namespace Microsoft.EntityFrameworkCore; + +public static class IBModelBuilderExtensions { - public static class IBModelBuilderExtensions - { - //public static ModelBuilder UseIdentityColumns(this ModelBuilder modelBuilder) - //{ - // var model = modelBuilder.Model; - // model.SetValueGenerationStrategy(IBValueGenerationStrategy.IdentityColumn); - // return modelBuilder; - //} + //public static ModelBuilder UseIdentityColumns(this ModelBuilder modelBuilder) + //{ + // var model = modelBuilder.Model; + // model.SetValueGenerationStrategy(IBValueGenerationStrategy.IdentityColumn); + // return modelBuilder; + //} - public static ModelBuilder UseSequenceTriggers(this ModelBuilder modelBuilder) - { - var model = modelBuilder.Model; - model.SetValueGenerationStrategy(IBValueGenerationStrategy.SequenceTrigger); - return modelBuilder; - } + public static ModelBuilder UseSequenceTriggers(this ModelBuilder modelBuilder) + { + var model = modelBuilder.Model; + model.SetValueGenerationStrategy(IBValueGenerationStrategy.SequenceTrigger); + return modelBuilder; + } - public static IConventionModelBuilder HasValueGenerationStrategy(this IConventionModelBuilder modelBuilder, IBValueGenerationStrategy? valueGenerationStrategy, bool fromDataAnnotation = false) + public static IConventionModelBuilder HasValueGenerationStrategy(this IConventionModelBuilder modelBuilder, IBValueGenerationStrategy? valueGenerationStrategy, bool fromDataAnnotation = false) + { + if (modelBuilder.CanSetAnnotation(IBAnnotationNames.ValueGenerationStrategy, valueGenerationStrategy, fromDataAnnotation)) { - if (modelBuilder.CanSetAnnotation(IBAnnotationNames.ValueGenerationStrategy, valueGenerationStrategy, fromDataAnnotation)) + modelBuilder.Metadata.SetValueGenerationStrategy(valueGenerationStrategy, fromDataAnnotation); + //if (valueGenerationStrategy != IBValueGenerationStrategy.IdentityColumn) + //{ + //} + if (valueGenerationStrategy != IBValueGenerationStrategy.SequenceTrigger) { - modelBuilder.Metadata.SetValueGenerationStrategy(valueGenerationStrategy, fromDataAnnotation); - //if (valueGenerationStrategy != IBValueGenerationStrategy.IdentityColumn) - //{ - //} - if (valueGenerationStrategy != IBValueGenerationStrategy.SequenceTrigger) - { - } - return modelBuilder; } - return null; + return modelBuilder; } + return null; } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBModelExtensions.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBModelExtensions.cs index 498fb60..24323d0 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBModelExtensions.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBModelExtensions.cs @@ -22,17 +22,21 @@ using InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Internal; using Microsoft.EntityFrameworkCore.Metadata; -namespace Microsoft.EntityFrameworkCore +namespace Microsoft.EntityFrameworkCore; + +public static class IBModelExtensions { - public static class FbModelExtensions - { - public static void SetValueGenerationStrategy(this IMutableModel model, IBValueGenerationStrategy? value) - => model.SetOrRemoveAnnotation(IBAnnotationNames.ValueGenerationStrategy, value); + public static void SetValueGenerationStrategy(this IMutableModel model, IBValueGenerationStrategy? value) + => model.SetOrRemoveAnnotation(IBAnnotationNames.ValueGenerationStrategy, value); + + public static void SetValueGenerationStrategy(this IConventionModel model, IBValueGenerationStrategy? value, bool fromDataAnnotation = false) + => model.SetOrRemoveAnnotation(IBAnnotationNames.ValueGenerationStrategy, value, fromDataAnnotation); - public static void SetValueGenerationStrategy(this IConventionModel model, IBValueGenerationStrategy? value, bool fromDataAnnotation = false) - => model.SetOrRemoveAnnotation(IBAnnotationNames.ValueGenerationStrategy, value, fromDataAnnotation); + public static IBValueGenerationStrategy? GetValueGenerationStrategy(this IModel model) + => (IBValueGenerationStrategy?)model[IBAnnotationNames.ValueGenerationStrategy]; + public static IBValueGenerationStrategy? GetValueGenerationStrategy(this IMutableModel model) + => (IBValueGenerationStrategy?)model[IBAnnotationNames.ValueGenerationStrategy]; - public static IBValueGenerationStrategy? GetValueGenerationStrategy(this IModel model) - => (IBValueGenerationStrategy?)model[IBAnnotationNames.ValueGenerationStrategy]; - } + public static IBValueGenerationStrategy? GetValueGenerationStrategy(this IConventionModel model) + => (IBValueGenerationStrategy?)model[IBAnnotationNames.ValueGenerationStrategy]; } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBPropertyBuilderExtensions.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBPropertyBuilderExtensions.cs index e5fff78..544a893 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBPropertyBuilderExtensions.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBPropertyBuilderExtensions.cs @@ -22,44 +22,43 @@ using InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Internal; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Microsoft.EntityFrameworkCore +namespace Microsoft.EntityFrameworkCore; + +public static class IBPropertyBuilderExtensions { - public static class IBPropertyBuilderExtensions - { - //public static PropertyBuilder UseIdentityColumn(this PropertyBuilder propertyBuilder) - //{ - // var property = propertyBuilder.Metadata; - // property.SetValueGenerationStrategy(IBValueGenerationStrategy.IdentityColumn); - // return propertyBuilder; - //} + //public static PropertyBuilder UseIdentityColumn(this PropertyBuilder propertyBuilder) + //{ + // var property = propertyBuilder.Metadata; + // property.SetValueGenerationStrategy(IBValueGenerationStrategy.IdentityColumn); + // return propertyBuilder; + //} - //public static PropertyBuilder UseIdentityColumn(this PropertyBuilder propertyBuilder) - // => (PropertyBuilder)UseIdentityColumn((PropertyBuilder)propertyBuilder); + //public static PropertyBuilder UseIdentityColumn(this PropertyBuilder propertyBuilder) + // => (PropertyBuilder)UseIdentityColumn((PropertyBuilder)propertyBuilder); - public static PropertyBuilder UseSequenceTrigger(this PropertyBuilder propertyBuilder) - { - var property = propertyBuilder.Metadata; - property.SetValueGenerationStrategy(IBValueGenerationStrategy.SequenceTrigger); - return propertyBuilder; - } + public static PropertyBuilder UseSequenceTrigger(this PropertyBuilder propertyBuilder) + { + var property = propertyBuilder.Metadata; + property.SetValueGenerationStrategy(IBValueGenerationStrategy.SequenceTrigger); + return propertyBuilder; + } - public static PropertyBuilder UseSequenceTrigger(this PropertyBuilder propertyBuilder) - => (PropertyBuilder)UseSequenceTrigger((PropertyBuilder)propertyBuilder); + public static PropertyBuilder UseSequenceTrigger(this PropertyBuilder propertyBuilder) + => (PropertyBuilder)UseSequenceTrigger((PropertyBuilder)propertyBuilder); - public static IConventionPropertyBuilder HasValueGenerationStrategy(this IConventionPropertyBuilder propertyBuilder, IBValueGenerationStrategy? valueGenerationStrategy, bool fromDataAnnotation = false) + public static IConventionPropertyBuilder HasValueGenerationStrategy(this IConventionPropertyBuilder propertyBuilder, IBValueGenerationStrategy? valueGenerationStrategy, bool fromDataAnnotation = false) + { + if (propertyBuilder.CanSetAnnotation(IBAnnotationNames.ValueGenerationStrategy, valueGenerationStrategy, fromDataAnnotation)) { - if (propertyBuilder.CanSetAnnotation(IBAnnotationNames.ValueGenerationStrategy, valueGenerationStrategy, fromDataAnnotation)) + propertyBuilder.Metadata.SetValueGenerationStrategy(valueGenerationStrategy, fromDataAnnotation); + //if (valueGenerationStrategy != IBValueGenerationStrategy.IdentityColumn) + //{ + //} + if (valueGenerationStrategy != IBValueGenerationStrategy.SequenceTrigger) { - propertyBuilder.Metadata.SetValueGenerationStrategy(valueGenerationStrategy, fromDataAnnotation); - //if (valueGenerationStrategy != IBValueGenerationStrategy.IdentityColumn) - //{ - //} - if (valueGenerationStrategy != IBValueGenerationStrategy.SequenceTrigger) - { - } - return propertyBuilder; } - return null; + return propertyBuilder; } + return null; } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBPropertyExtensions.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBPropertyExtensions.cs index 9ff8fc9..ba24d2b 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBPropertyExtensions.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBPropertyExtensions.cs @@ -23,74 +23,136 @@ using InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Internal; using Microsoft.EntityFrameworkCore.Metadata; -namespace Microsoft.EntityFrameworkCore +namespace Microsoft.EntityFrameworkCore; + +public static class IBPropertyExtensions { - public static class FbPropertyExtensions + public static IBValueGenerationStrategy GetValueGenerationStrategy(this IProperty property) { - public static IBValueGenerationStrategy GetValueGenerationStrategy(this IProperty property) + var annotation = property[IBAnnotationNames.ValueGenerationStrategy]; + if (annotation != null) { - var annotation = property[IBAnnotationNames.ValueGenerationStrategy]; - if (annotation != null) - { - return (IBValueGenerationStrategy)annotation; - } + return (IBValueGenerationStrategy)annotation; + } - if (property.ValueGenerated != ValueGenerated.OnAdd - || property.GetDefaultValue() != null - || property.GetDefaultValueSql() != null - || property.GetComputedColumnSql() != null) - { - return IBValueGenerationStrategy.None; - } + if (property.ValueGenerated != ValueGenerated.OnAdd + || property.IsForeignKey() + || property.TryGetDefaultValue(out _) + || property.GetDefaultValueSql() != null + || property.GetComputedColumnSql() != null) + { + return IBValueGenerationStrategy.None; + } - var modelStrategy = property.DeclaringEntityType.Model.GetValueGenerationStrategy(); + var modelStrategy = property.DeclaringEntityType.Model.GetValueGenerationStrategy(); - if (modelStrategy == IBValueGenerationStrategy.SequenceTrigger && IsCompatibleSequenceTrigger(property)) - { - return IBValueGenerationStrategy.SequenceTrigger; - } - //if (modelStrategy == IBValueGenerationStrategy.IdentityColumn && IsCompatibleIdentityColumn(property)) - //{ - // return IBValueGenerationStrategy.IdentityColumn; - //} + if (modelStrategy == IBValueGenerationStrategy.SequenceTrigger && IsCompatibleSequenceTrigger(property)) + { + return IBValueGenerationStrategy.SequenceTrigger; + } + if (modelStrategy == IBValueGenerationStrategy.IdentityColumn && IsCompatibleIdentityColumn(property)) + { + throw new ArgumentException("InterBase does not support Identity columns"); + } + + return IBValueGenerationStrategy.None; + } + public static IBValueGenerationStrategy GetValueGenerationStrategy(this IMutableProperty property) + { + var annotation = property[IBAnnotationNames.ValueGenerationStrategy]; + if (annotation != null) + { + return (IBValueGenerationStrategy)annotation; + } + + if (property.ValueGenerated != ValueGenerated.OnAdd + || property.IsForeignKey() + || property.TryGetDefaultValue(out _) + || property.GetDefaultValueSql() != null + || property.GetComputedColumnSql() != null) + { return IBValueGenerationStrategy.None; } - public static ConfigurationSource? GetValueGenerationStrategyConfigurationSource(this IConventionProperty property) - => property.FindAnnotation(IBAnnotationNames.ValueGenerationStrategy)?.GetConfigurationSource(); + var modelStrategy = property.DeclaringEntityType.Model.GetValueGenerationStrategy(); - public static void SetValueGenerationStrategy(this IMutableProperty property, IBValueGenerationStrategy? value) + if (modelStrategy == IBValueGenerationStrategy.SequenceTrigger && IsCompatibleSequenceTrigger(property)) + { + return IBValueGenerationStrategy.SequenceTrigger; + } + if (modelStrategy == IBValueGenerationStrategy.IdentityColumn && IsCompatibleIdentityColumn(property)) { - CheckValueGenerationStrategy(property, value); - property.SetOrRemoveAnnotation(IBAnnotationNames.ValueGenerationStrategy, value); + throw new ArgumentException("InterBase does not support Identity columns"); } - public static void SetValueGenerationStrategy(this IConventionProperty property, IBValueGenerationStrategy? value, bool fromDataAnnotation = false) + return IBValueGenerationStrategy.None; + } + + public static IBValueGenerationStrategy GetValueGenerationStrategy(this IConventionProperty property) + { + var annotation = property[IBAnnotationNames.ValueGenerationStrategy]; + if (annotation != null) { - CheckValueGenerationStrategy(property, value); - property.SetOrRemoveAnnotation(IBAnnotationNames.ValueGenerationStrategy, value, fromDataAnnotation); + return (IBValueGenerationStrategy)annotation; } - static void CheckValueGenerationStrategy(IProperty property, IBValueGenerationStrategy? value) + if (property.ValueGenerated != ValueGenerated.OnAdd + || property.IsForeignKey() + || property.TryGetDefaultValue(out _) + || property.GetDefaultValueSql() != null + || property.GetComputedColumnSql() != null) { - if (value != null) + return IBValueGenerationStrategy.None; + } + + var modelStrategy = property.DeclaringEntityType.Model.GetValueGenerationStrategy(); + + if (modelStrategy == IBValueGenerationStrategy.SequenceTrigger && IsCompatibleSequenceTrigger(property)) + { + return IBValueGenerationStrategy.SequenceTrigger; + } + if (modelStrategy == IBValueGenerationStrategy.IdentityColumn && IsCompatibleIdentityColumn(property)) + { + throw new ArgumentException("InterBase does not support Identity columns"); + } + + return IBValueGenerationStrategy.None; + } + + public static ConfigurationSource? GetValueGenerationStrategyConfigurationSource(this IConventionProperty property) + => property.FindAnnotation(IBAnnotationNames.ValueGenerationStrategy)?.GetConfigurationSource(); + + public static void SetValueGenerationStrategy(this IMutableProperty property, IBValueGenerationStrategy? value) + { + CheckValueGenerationStrategy(property, value); + property.SetOrRemoveAnnotation(IBAnnotationNames.ValueGenerationStrategy, value); + } + + public static void SetValueGenerationStrategy(this IConventionProperty property, IBValueGenerationStrategy? value, bool fromDataAnnotation = false) + { + CheckValueGenerationStrategy(property, value); + property.SetOrRemoveAnnotation(IBAnnotationNames.ValueGenerationStrategy, value, fromDataAnnotation); + } + + static void CheckValueGenerationStrategy(IReadOnlyPropertyBase property, IBValueGenerationStrategy? value) + { + if (value != null) + { + if (value == IBValueGenerationStrategy.IdentityColumn && !IsCompatibleIdentityColumn(property)) + { + throw new ArgumentException("InterBase does not support Identity columns"); + } + if (value == IBValueGenerationStrategy.SequenceTrigger && !IsCompatibleSequenceTrigger(property)) { - //if (value == IBValueGenerationStrategy.IdentityColumn && !IsCompatibleIdentityColumn(property)) - //{ - // throw new ArgumentException($"Incompatible data type for {nameof(IBValueGenerationStrategy.IdentityColumn)} for '{property.Name}'."); - //} - if (value == IBValueGenerationStrategy.SequenceTrigger && !IsCompatibleSequenceTrigger(property)) - { - throw new ArgumentException($"Incompatible data type for {nameof(IBValueGenerationStrategy.SequenceTrigger)} for '{property.Name}'."); - } + throw new ArgumentException($"Incompatible data type for {nameof(IBValueGenerationStrategy.SequenceTrigger)} for '{property.Name}'."); } } + } - static bool IsCompatibleIdentityColumn(IProperty property) - => property.ClrType.IsInteger() || property.ClrType == typeof(decimal); + static bool IsCompatibleIdentityColumn(IReadOnlyPropertyBase property) + => property.ClrType.IsInteger() || property.ClrType == typeof(decimal); - static bool IsCompatibleSequenceTrigger(IProperty property) - => true; - } + static bool IsCompatibleSequenceTrigger(IReadOnlyPropertyBase property) + => true; } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBServiceCollectionExtensions.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBServiceCollectionExtensions.cs index 24062e1..08f2301 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBServiceCollectionExtensions.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Extensions/IBServiceCollectionExtensions.cs @@ -18,11 +18,14 @@ //$Authors = Jiri Cincura (jiri@cincura.net) +using System; using InterBaseSql.EntityFrameworkCore.InterBase; using InterBaseSql.EntityFrameworkCore.InterBase.Diagnostics.Internal; +using InterBaseSql.EntityFrameworkCore.InterBase.Infrastructure; using InterBaseSql.EntityFrameworkCore.InterBase.Infrastructure.Internal; using InterBaseSql.EntityFrameworkCore.InterBase.Internal; using InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Conventions; +using InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Internal; using InterBaseSql.EntityFrameworkCore.InterBase.Migrations; using InterBaseSql.EntityFrameworkCore.InterBase.Migrations.Internal; using InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; @@ -32,45 +35,59 @@ using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Update; using Microsoft.Extensions.DependencyInjection; -namespace Microsoft.EntityFrameworkCore +namespace Microsoft.EntityFrameworkCore; + +public static class IBServiceCollectionExtensions { - public static class IBServiceCollectionExtensions + public static IServiceCollection AddInterBase(this IServiceCollection serviceCollection, string connectionString, Action IBOptionsAction = null, Action optionsAction = null) + where TContext : DbContext + { + return serviceCollection.AddDbContext( + (serviceProvider, options) => + { + optionsAction?.Invoke(options); + options.UseInterBase(connectionString, IBOptionsAction); + }); + } + + public static IServiceCollection AddEntityFrameworkInterBase(this IServiceCollection serviceCollection) { - public static IServiceCollection AddEntityFrameworkInterBase(this IServiceCollection serviceCollection) - { - var builder = new EntityFrameworkRelationalServicesBuilder(serviceCollection) - .TryAdd() - .TryAdd>() - .TryAdd() - .TryAdd() - .TryAdd() - .TryAdd() - .TryAdd() - .TryAdd(p => p.GetService()) - .TryAdd() - .TryAdd(p => p.GetService()) - .TryAdd() - .TryAdd() - .TryAdd() - .TryAdd() - .TryAdd() - .TryAdd() - .TryAdd(p => p.GetService()) - .TryAddProviderSpecificServices(b => b - .TryAddSingleton() - .TryAddSingleton() - .TryAddSingleton() - .TryAddScoped()); + var builder = new EntityFrameworkRelationalServicesBuilder(serviceCollection) + .TryAdd() + .TryAdd>() + .TryAdd() + .TryAdd() + .TryAdd() + .TryAdd() + .TryAdd() + .TryAdd(p => p.GetService()) + .TryAdd() + .TryAdd(p => p.GetService()) + .TryAdd() + .TryAdd() + .TryAdd() + .TryAdd() + .TryAdd() + .TryAdd() + .TryAdd() + .TryAdd(p => p.GetService()) + .TryAdd() + .TryAddProviderSpecificServices(b => b + .TryAddSingleton() + .TryAddSingleton() + .TryAddSingleton() + .TryAddScoped() + .TryAddScoped()); - builder.TryAddCoreServices(); + builder.TryAddCoreServices(); - return serviceCollection; - } + return serviceCollection; } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Changelog.md new file mode 100644 index 0000000..d460fcb --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Changelog.md @@ -0,0 +1,14 @@ +# Changes for 7.10.2 + +## General - +* All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. + +## Common - +* Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Infrastructure to InterBaseSql.EntityFrameworkCore.InterBase.Infrastructure +* Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. + +* All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. +* For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup + +* using FirebirdSql.EntityFrameworkCore.Firebird.Infrastructure.Internal now InterBaseSql.EntityFrameworkCore.InterBase.Infrastructure.Internal + diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Changelog.txt b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Changelog.txt deleted file mode 100644 index 48905c5..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Changelog.txt +++ /dev/null @@ -1,14 +0,0 @@ -Changes for 7.10.2 - - General - - All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. - - Common - - Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Infrastructure to InterBaseSql.EntityFrameworkCore.InterBase.Infrastructure - Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. - - All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. - For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup - - using FirebirdSql.EntityFrameworkCore.Firebird.Infrastructure.Internal now InterBaseSql.EntityFrameworkCore.InterBase.Infrastructure.Internal - diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/IBDbContextOptionsBuilder.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/IBDbContextOptionsBuilder.cs index 18351b8..1719c09 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/IBDbContextOptionsBuilder.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/IBDbContextOptionsBuilder.cs @@ -22,18 +22,17 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Infrastructure +namespace InterBaseSql.EntityFrameworkCore.InterBase.Infrastructure; + +public class IBDbContextOptionsBuilder : RelationalDbContextOptionsBuilder { - public class IBDbContextOptionsBuilder : RelationalDbContextOptionsBuilder - { - public IBDbContextOptionsBuilder(DbContextOptionsBuilder optionsBuilder) - : base(optionsBuilder) - { } + public IBDbContextOptionsBuilder(DbContextOptionsBuilder optionsBuilder) + : base(optionsBuilder) + { } - public virtual IBDbContextOptionsBuilder WithExplicitParameterTypes(bool explicitParameterTypes = true) - => WithOption(e => e.WithExplicitParameterTypes(explicitParameterTypes)); + public virtual IBDbContextOptionsBuilder WithExplicitParameterTypes(bool explicitParameterTypes = true) + => WithOption(e => e.WithExplicitParameterTypes(explicitParameterTypes)); - public virtual IBDbContextOptionsBuilder WithExplicitStringLiteralTypes(bool explicitStringLiteralTypes = true) - => WithOption(e => e.WithExplicitStringLiteralTypes(explicitStringLiteralTypes)); - } + public virtual IBDbContextOptionsBuilder WithExplicitStringLiteralTypes(bool explicitStringLiteralTypes = true) + => WithOption(e => e.WithExplicitStringLiteralTypes(explicitStringLiteralTypes)); } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Internal/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Internal/Changelog.md new file mode 100644 index 0000000..da7986f --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Internal/Changelog.md @@ -0,0 +1,20 @@ +# Changes for 7.13.6 + +## IBOptionsExtension.cs +* GetServiceProviderHashCode return type now int + +# Changes for 7.10.2 + +## General - +* All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. + +## Common - +* Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Design.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Design.Internal +* Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. + +* All files renamed from FbXxxxx to IBXxxxx with the internal class matching that same change. +* For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup + +* FbOptionsExtension.cs renamed to IBOptionsExtension.cs +* FbOptionsExtension now IBOptionsExtension +* ApplyServices now calls AddEntityFrameworkInterBase diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Internal/Changelog.txt b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Internal/Changelog.txt deleted file mode 100644 index 23538e7..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Internal/Changelog.txt +++ /dev/null @@ -1,15 +0,0 @@ -Changes for 7.10.2 - - General - - All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. - - Common - - Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Design.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Design.Internal - Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. - - All files renamed from FbXxxxx to IBXxxxx with the internal class matching that same change. - For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup - - FbOptionsExtension.cs renamed to IBOptionsExtension.cs - FbOptionsExtension now IBOptionsExtension - ApplyServices now calls AddEntityFrameworkInterBase diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Internal/IBOptionsExtension.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Internal/IBOptionsExtension.cs index 3ea36f0..956e213 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Internal/IBOptionsExtension.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Internal/IBOptionsExtension.cs @@ -24,65 +24,64 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Infrastructure.Internal -{ - public class IBOptionsExtension : RelationalOptionsExtension - { - DbContextOptionsExtensionInfo _info; - bool? _explicitParameterTypes; - bool? _explicitStringLiteralTypes; +namespace InterBaseSql.EntityFrameworkCore.InterBase.Infrastructure.Internal; - public IBOptionsExtension() - { } +public class IBOptionsExtension : RelationalOptionsExtension +{ + DbContextOptionsExtensionInfo _info; + bool? _explicitParameterTypes; + bool? _explicitStringLiteralTypes; - public IBOptionsExtension(IBOptionsExtension copyFrom) - : base(copyFrom) - { - _explicitParameterTypes = copyFrom._explicitParameterTypes; - _explicitStringLiteralTypes = copyFrom._explicitStringLiteralTypes; - } + public IBOptionsExtension() + { } - protected override RelationalOptionsExtension Clone() - => new IBOptionsExtension(this); + public IBOptionsExtension(IBOptionsExtension copyFrom) + : base(copyFrom) + { + _explicitParameterTypes = copyFrom._explicitParameterTypes; + _explicitStringLiteralTypes = copyFrom._explicitStringLiteralTypes; + } - public override void ApplyServices(IServiceCollection services) - => services.AddEntityFrameworkInterBase(); + protected override RelationalOptionsExtension Clone() + => new IBOptionsExtension(this); - public override DbContextOptionsExtensionInfo Info => _info ??= new ExtensionInfo(this); - public virtual bool? ExplicitParameterTypes => _explicitParameterTypes; - public virtual bool? ExplicitStringLiteralTypes => _explicitStringLiteralTypes; + public override void ApplyServices(IServiceCollection services) + => services.AddEntityFrameworkInterBase(); - public virtual IBOptionsExtension WithExplicitParameterTypes(bool explicitParameterTypes) - { - var clone = (IBOptionsExtension)Clone(); - clone._explicitParameterTypes = explicitParameterTypes; - return clone; - } + public override DbContextOptionsExtensionInfo Info => _info ??= new ExtensionInfo(this); + public virtual bool? ExplicitParameterTypes => _explicitParameterTypes; + public virtual bool? ExplicitStringLiteralTypes => _explicitStringLiteralTypes; - public virtual IBOptionsExtension WithExplicitStringLiteralTypes(bool explicitStringLiteralTypes) - { - var clone = (IBOptionsExtension)Clone(); - clone._explicitStringLiteralTypes = explicitStringLiteralTypes; - return clone; - } + public virtual IBOptionsExtension WithExplicitParameterTypes(bool explicitParameterTypes) + { + var clone = (IBOptionsExtension)Clone(); + clone._explicitParameterTypes = explicitParameterTypes; + return clone; + } - sealed class ExtensionInfo : RelationalExtensionInfo - { - long? _serviceProviderHash; + public virtual IBOptionsExtension WithExplicitStringLiteralTypes(bool explicitStringLiteralTypes) + { + var clone = (IBOptionsExtension)Clone(); + clone._explicitStringLiteralTypes = explicitStringLiteralTypes; + return clone; + } - public ExtensionInfo(IDbContextOptionsExtension extension) - : base(extension) - { } + sealed class ExtensionInfo : RelationalExtensionInfo + { + int? _serviceProviderHash; - new IBOptionsExtension Extension => (IBOptionsExtension)base.Extension; + public ExtensionInfo(IDbContextOptionsExtension extension) + : base(extension) + { } - public override long GetServiceProviderHashCode() - { - return _serviceProviderHash ??= HashCode.Combine(base.GetServiceProviderHashCode(), Extension._explicitParameterTypes, Extension._explicitStringLiteralTypes); - } + new IBOptionsExtension Extension => (IBOptionsExtension)base.Extension; - public override void PopulateDebugInfo(IDictionary debugInfo) - { } + public override int GetServiceProviderHashCode() + { + return _serviceProviderHash ??= HashCode.Combine(base.GetServiceProviderHashCode(), Extension._explicitParameterTypes, Extension._explicitStringLiteralTypes); } + + public override void PopulateDebugInfo(IDictionary debugInfo) + { } } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Internal/IIBOptions.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Internal/IIBOptions.cs index 9a2bd1d..fd62d9d 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Internal/IIBOptions.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Infrastructure/Internal/IIBOptions.cs @@ -20,11 +20,10 @@ using Microsoft.EntityFrameworkCore.Infrastructure; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Infrastructure.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Infrastructure.Internal; + +public interface IIBOptions : ISingletonOptions { - public interface IIBOptions : ISingletonOptions - { - bool ExplicitParameterTypes { get; } - bool ExplicitStringLiteralTypes { get; } - } + bool ExplicitParameterTypes { get; } + bool ExplicitStringLiteralTypes { get; } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/InterBaseSql.EntityFrameworkCore.InterBase.csproj b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/InterBaseSql.EntityFrameworkCore.InterBase.csproj index 8671f16..35c76d3 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/InterBaseSql.EntityFrameworkCore.InterBase.csproj +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/InterBaseSql.EntityFrameworkCore.InterBase.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + net6.0 InterBaseSql.EntityFrameworkCore.InterBase InterBaseSql.EntityFrameworkCore.InterBase true @@ -42,8 +42,8 @@ - - + + diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Internal/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Internal/Changelog.md new file mode 100644 index 0000000..1871728 --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Internal/Changelog.md @@ -0,0 +1,18 @@ +# Changes for 7.13.6 + +## IBOptions.cs +* Changed all Fb ro IB prefixes. + +# Changes for 7.10.2 + +## General - +* All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. + +## Common - +* Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Internal +* Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. + +* All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. +* For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup + +* using FirebirdSql.EntityFrameworkCore.Firebird.Infrastructure now InterBaseSql.EntityFrameworkCore.InterBase.Infrastructure diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Internal/Changelog.txt b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Internal/Changelog.txt deleted file mode 100644 index 750a81d..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Internal/Changelog.txt +++ /dev/null @@ -1,13 +0,0 @@ -Changes for 7.10.2 - - General - - All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. - - Common - - Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Internal - Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. - - All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. - For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup - - using FirebirdSql.EntityFrameworkCore.Firebird.Infrastructure now InterBaseSql.EntityFrameworkCore.InterBase.Infrastructure diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Internal/IBOptions.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Internal/IBOptions.cs index 538f509..b8ac6f3 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Internal/IBOptions.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Internal/IBOptions.cs @@ -24,33 +24,32 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Internal; + +public class IBOptions : IIBOptions { - public class IBOptions : IIBOptions + public virtual void Initialize(IDbContextOptions options) { - public virtual void Initialize(IDbContextOptions options) - { - var fbOptions = options.FindExtension() ?? new IBOptionsExtension(); + var IBOptions = options.FindExtension() ?? new IBOptionsExtension(); - ExplicitParameterTypes = fbOptions.ExplicitParameterTypes ?? true; - ExplicitStringLiteralTypes = fbOptions.ExplicitStringLiteralTypes ?? true; - } + ExplicitParameterTypes = IBOptions.ExplicitParameterTypes ?? true; + ExplicitStringLiteralTypes = IBOptions.ExplicitStringLiteralTypes ?? true; + } + + public virtual void Validate(IDbContextOptions options) + { + var ibOptions = options.FindExtension() ?? new IBOptionsExtension(); - public virtual void Validate(IDbContextOptions options) + if (ExplicitParameterTypes != (ibOptions.ExplicitParameterTypes ?? true)) { - var fbOptions = options.FindExtension() ?? new IBOptionsExtension(); - - if (ExplicitParameterTypes != (fbOptions.ExplicitParameterTypes ?? true)) - { - throw new InvalidOperationException($"A call was made to '{nameof(IBDbContextOptionsBuilder.WithExplicitParameterTypes)}' that changed an option that must be constant within a service provider, but Entity Framework is not building its own internal service provider. Either allow EF to build the service provider by removing the call to '{nameof(DbContextOptionsBuilder.UseInternalServiceProvider)}', or ensure that the configuration for '{nameof(IBDbContextOptionsBuilder.WithExplicitParameterTypes)}' does not change for all uses of a given service provider passed to '{nameof(DbContextOptionsBuilder.UseInternalServiceProvider)}'."); - } - if (ExplicitStringLiteralTypes != (fbOptions.ExplicitStringLiteralTypes ?? true)) - { - throw new InvalidOperationException($"A call was made to '{nameof(IBDbContextOptionsBuilder.WithExplicitStringLiteralTypes)}' that changed an option that must be constant within a service provider, but Entity Framework is not building its own internal service provider. Either allow EF to build the service provider by removing the call to '{nameof(DbContextOptionsBuilder.UseInternalServiceProvider)}', or ensure that the configuration for '{nameof(IBDbContextOptionsBuilder.WithExplicitStringLiteralTypes)}' does not change for all uses of a given service provider passed to '{nameof(DbContextOptionsBuilder.UseInternalServiceProvider)}'."); - } + throw new InvalidOperationException($"A call was made to '{nameof(IBDbContextOptionsBuilder.WithExplicitParameterTypes)}' that changed an option that must be constant within a service provider, but Entity Framework is not building its own internal service provider. Either allow EF to build the service provider by removing the call to '{nameof(DbContextOptionsBuilder.UseInternalServiceProvider)}', or ensure that the configuration for '{nameof(IBDbContextOptionsBuilder.WithExplicitParameterTypes)}' does not change for all uses of a given service provider passed to '{nameof(DbContextOptionsBuilder.UseInternalServiceProvider)}'."); + } + if (ExplicitStringLiteralTypes != (ibOptions.ExplicitStringLiteralTypes ?? true)) + { + throw new InvalidOperationException($"A call was made to '{nameof(IBDbContextOptionsBuilder.WithExplicitStringLiteralTypes)}' that changed an option that must be constant within a service provider, but Entity Framework is not building its own internal service provider. Either allow EF to build the service provider by removing the call to '{nameof(DbContextOptionsBuilder.UseInternalServiceProvider)}', or ensure that the configuration for '{nameof(IBDbContextOptionsBuilder.WithExplicitStringLiteralTypes)}' does not change for all uses of a given service provider passed to '{nameof(DbContextOptionsBuilder.UseInternalServiceProvider)}'."); } - - public virtual bool ExplicitParameterTypes { get; private set; } - public virtual bool ExplicitStringLiteralTypes { get; private set; } } + + public virtual bool ExplicitParameterTypes { get; private set; } + public virtual bool ExplicitStringLiteralTypes { get; private set; } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Changelog.md new file mode 100644 index 0000000..26b0668 --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Changelog.md @@ -0,0 +1,13 @@ +# Changes for 7.10.2 + +## General - +* All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. + +## Common - +* Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Metadata to InterBaseSql.EntityFrameworkCore.InterBase.Metadata +* Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. + +* All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. +* For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup + + diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Changelog.txt b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Changelog.txt deleted file mode 100644 index 98b6a63..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Changelog.txt +++ /dev/null @@ -1,13 +0,0 @@ -Changes for 7.10.2 - - General - - All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. - - Common - - Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Metadata to InterBaseSql.EntityFrameworkCore.InterBase.Metadata - Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. - - All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. - For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup - - diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Conventions/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Conventions/Changelog.md index 38722c3..6244df7 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Conventions/Changelog.md +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Conventions/Changelog.md @@ -1,3 +1,6 @@ +# Changes for 7.13.6 +* General updates from the Fb 9.x code for EFCore 6.0 support + # Changes for 7.12.1 ## IBValueGenerationStrategyConvention.cs diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Conventions/IBConventionSetBuilder.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Conventions/IBConventionSetBuilder.cs index e7733d5..ae97e5e 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Conventions/IBConventionSetBuilder.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Conventions/IBConventionSetBuilder.cs @@ -23,53 +23,50 @@ using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; using Microsoft.Extensions.DependencyInjection; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Conventions -{ - public class IBConventionSetBuilder : RelationalConventionSetBuilder - { - public IBConventionSetBuilder(ProviderConventionSetBuilderDependencies dependencies, RelationalConventionSetBuilderDependencies relationalDependencies) - : base(dependencies, relationalDependencies) - { } +namespace InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Conventions; - public override ConventionSet CreateConventionSet() - { - var conventionSet = base.CreateConventionSet(); - var valueGenerationStrategyConvention = new IBValueGenerationStrategyConvention(Dependencies, RelationalDependencies); - conventionSet.ModelInitializedConventions.Add(valueGenerationStrategyConvention); - conventionSet.ModelInitializedConventions.Add(new RelationalMaxIdentifierLengthConvention(31, Dependencies, RelationalDependencies)); +public class IBConventionSetBuilder : RelationalConventionSetBuilder +{ + public IBConventionSetBuilder(ProviderConventionSetBuilderDependencies dependencies, RelationalConventionSetBuilderDependencies relationalDependencies) + : base(dependencies, relationalDependencies) + { } - var valueGenerationConvention = new IBValueGenerationConvention(Dependencies, RelationalDependencies); + public override ConventionSet CreateConventionSet() + { + var conventionSet = base.CreateConventionSet(); - ReplaceConvention(conventionSet.EntityTypeBaseTypeChangedConventions, valueGenerationConvention); - ReplaceConvention(conventionSet.EntityTypePrimaryKeyChangedConventions, valueGenerationConvention); - ReplaceConvention(conventionSet.ForeignKeyAddedConventions, valueGenerationConvention); - ReplaceConvention(conventionSet.ForeignKeyRemovedConventions, valueGenerationConvention); + var valueGenerationStrategyConvention = new IBValueGenerationStrategyConvention(Dependencies, RelationalDependencies); + conventionSet.ModelInitializedConventions.Add(valueGenerationStrategyConvention); + conventionSet.ModelInitializedConventions.Add(new RelationalMaxIdentifierLengthConvention(31, Dependencies, RelationalDependencies)); - ConventionSet.AddBefore(conventionSet.ModelFinalizedConventions, valueGenerationStrategyConvention, typeof(ValidatingConvention)); + var valueGenerationConvention = new IBValueGenerationConvention(Dependencies, RelationalDependencies); + ReplaceConvention(conventionSet.EntityTypeBaseTypeChangedConventions, valueGenerationConvention); + ReplaceConvention(conventionSet.EntityTypePrimaryKeyChangedConventions, valueGenerationConvention); + ReplaceConvention(conventionSet.ForeignKeyAddedConventions, valueGenerationConvention); + ReplaceConvention(conventionSet.ForeignKeyRemovedConventions, valueGenerationConvention); - var storeGenerationConvention = new IBStoreGenerationConvention(Dependencies, RelationalDependencies); + var storeGenerationConvention = new IBStoreGenerationConvention(Dependencies, RelationalDependencies); + ReplaceConvention(conventionSet.PropertyAnnotationChangedConventions, storeGenerationConvention); + ReplaceConvention(conventionSet.PropertyAnnotationChangedConventions, (RelationalValueGenerationConvention)valueGenerationConvention); - ReplaceConvention(conventionSet.PropertyAnnotationChangedConventions, storeGenerationConvention); - ReplaceConvention(conventionSet.PropertyAnnotationChangedConventions, (RelationalValueGenerationConvention)valueGenerationConvention); + conventionSet.ModelFinalizingConventions.Add(valueGenerationStrategyConvention); + ReplaceConvention(conventionSet.ModelFinalizingConventions, storeGenerationConvention); - ReplaceConvention(conventionSet.ModelFinalizedConventions, storeGenerationConvention); + return conventionSet; + } - return conventionSet; - } + public static ConventionSet Build() + { + var serviceProvider = new ServiceCollection() + .AddEntityFrameworkInterBase() + .AddDbContext(o => o.UseInterBase("database=localhost:_.ib;user=sysdba;password=masterkey;charset=utf8")) + .BuildServiceProvider(); - public static ConventionSet Build() + using (var serviceScope = serviceProvider.GetRequiredService().CreateScope()) { - var serviceProvider = new ServiceCollection() - .AddEntityFrameworkInterBase() - .AddDbContext(o => o.UseInterBase("database=localhost:_.ib;user=sysdba;password=masterkey;charset=utf8")) - .BuildServiceProvider(); - - using (var serviceScope = serviceProvider.GetRequiredService().CreateScope()) + using (var context = serviceScope.ServiceProvider.GetService()) { - using (var context = serviceScope.ServiceProvider.GetService()) - { - return ConventionSet.CreateConventionSet(context); - } + return ConventionSet.CreateConventionSet(context); } } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Conventions/IBStoreGenerationConvention.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Conventions/IBStoreGenerationConvention.cs index aa45f1d..6e2454e 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Conventions/IBStoreGenerationConvention.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Conventions/IBStoreGenerationConvention.cs @@ -27,97 +27,96 @@ using Microsoft.EntityFrameworkCore.Metadata.Conventions; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Conventions +namespace InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Conventions; + +public class IBStoreGenerationConvention : StoreGenerationConvention { - public class IBStoreGenerationConvention : StoreGenerationConvention - { - public IBStoreGenerationConvention(ProviderConventionSetBuilderDependencies dependencies, RelationalConventionSetBuilderDependencies relationalDependencies) - : base(dependencies, relationalDependencies) - { } + public IBStoreGenerationConvention(ProviderConventionSetBuilderDependencies dependencies, RelationalConventionSetBuilderDependencies relationalDependencies) + : base(dependencies, relationalDependencies) + { } - public override void ProcessPropertyAnnotationChanged(IConventionPropertyBuilder propertyBuilder, string name, IConventionAnnotation annotation, IConventionAnnotation oldAnnotation, IConventionContext context) + public override void ProcessPropertyAnnotationChanged(IConventionPropertyBuilder propertyBuilder, string name, IConventionAnnotation annotation, IConventionAnnotation oldAnnotation, IConventionContext context) + { + if (annotation == null + || oldAnnotation?.Value != null) { - if (annotation == null - || oldAnnotation?.Value != null) - { - return; - } - - var configurationSource = annotation.GetConfigurationSource(); - var fromDataAnnotation = configurationSource != ConfigurationSource.Convention; - switch (name) - { - case RelationalAnnotationNames.DefaultValue: - if (propertyBuilder.HasValueGenerationStrategy(null, fromDataAnnotation) == null - && propertyBuilder.HasDefaultValue(null, fromDataAnnotation) != null) - { - context.StopProcessing(); - return; - } - - break; - case RelationalAnnotationNames.DefaultValueSql: - if (propertyBuilder.HasValueGenerationStrategy(null, fromDataAnnotation) == null - && propertyBuilder.HasDefaultValueSql(null, fromDataAnnotation) != null) - { - context.StopProcessing(); - return; - } - - break; - case RelationalAnnotationNames.ComputedColumnSql: - if (propertyBuilder.HasValueGenerationStrategy(null, fromDataAnnotation) == null - && propertyBuilder.HasComputedColumnSql(null, fromDataAnnotation) != null) - { - context.StopProcessing(); - return; - } - - break; - case IBAnnotationNames.ValueGenerationStrategy: - if ((propertyBuilder.HasDefaultValue(null, fromDataAnnotation) == null - | propertyBuilder.HasDefaultValueSql(null, fromDataAnnotation) == null - | propertyBuilder.HasComputedColumnSql(null, fromDataAnnotation) == null) - && propertyBuilder.HasValueGenerationStrategy(null, fromDataAnnotation) != null) - { - context.StopProcessing(); - return; - } - - break; - } - - base.ProcessPropertyAnnotationChanged(propertyBuilder, name, annotation, oldAnnotation, context); + return; } - protected override void Validate(IConventionProperty property) + var configurationSource = annotation.GetConfigurationSource(); + var fromDataAnnotation = configurationSource != ConfigurationSource.Convention; + switch (name) { - if (property.GetValueGenerationStrategyConfigurationSource() != null - && property.GetValueGenerationStrategy() != IBValueGenerationStrategy.None) - { - if (property.GetDefaultValue() != null) + case RelationalAnnotationNames.DefaultValue: + if (propertyBuilder.HasValueGenerationStrategy(null, fromDataAnnotation) == null + && propertyBuilder.HasDefaultValue(null, fromDataAnnotation) != null) { - throw new InvalidOperationException( - RelationalStrings.ConflictingColumnServerGeneration( - nameof(IBValueGenerationStrategy), property.Name, "DefaultValue")); + context.StopProcessing(); + return; } - if (property.GetDefaultValueSql() != null) + break; + case RelationalAnnotationNames.DefaultValueSql: + if (propertyBuilder.HasValueGenerationStrategy(null, fromDataAnnotation) == null + && propertyBuilder.HasDefaultValueSql(null, fromDataAnnotation) != null) { - throw new InvalidOperationException( - RelationalStrings.ConflictingColumnServerGeneration( - nameof(IBValueGenerationStrategy), property.Name, "DefaultValueSql")); + context.StopProcessing(); + return; } - if (property.GetComputedColumnSql() != null) + break; + case RelationalAnnotationNames.ComputedColumnSql: + if (propertyBuilder.HasValueGenerationStrategy(null, fromDataAnnotation) == null + && propertyBuilder.HasComputedColumnSql(null, fromDataAnnotation) != null) { - throw new InvalidOperationException( - RelationalStrings.ConflictingColumnServerGeneration( - nameof(IBValueGenerationStrategy), property.Name, "ComputedColumnSql")); + context.StopProcessing(); + return; } + + break; + case IBAnnotationNames.ValueGenerationStrategy: + if ((propertyBuilder.HasDefaultValue(null, fromDataAnnotation) == null + | propertyBuilder.HasDefaultValueSql(null, fromDataAnnotation) == null + | propertyBuilder.HasComputedColumnSql(null, fromDataAnnotation) == null) + && propertyBuilder.HasValueGenerationStrategy(null, fromDataAnnotation) != null) + { + context.StopProcessing(); + return; + } + + break; + } + + base.ProcessPropertyAnnotationChanged(propertyBuilder, name, annotation, oldAnnotation, context); + } + + protected override void Validate(IConventionProperty property, in StoreObjectIdentifier storeObject) + { + if (property.GetValueGenerationStrategyConfigurationSource() != null + && property.GetValueGenerationStrategy() != IBValueGenerationStrategy.None) + { + if (property.GetDefaultValue() != null) + { + throw new InvalidOperationException( + RelationalStrings.ConflictingColumnServerGeneration( + nameof(IBValueGenerationStrategy), property.Name, "DefaultValue")); + } + + if (property.GetDefaultValueSql() != null) + { + throw new InvalidOperationException( + RelationalStrings.ConflictingColumnServerGeneration( + nameof(IBValueGenerationStrategy), property.Name, "DefaultValueSql")); } - base.Validate(property); + if (property.GetComputedColumnSql() != null) + { + throw new InvalidOperationException( + RelationalStrings.ConflictingColumnServerGeneration( + nameof(IBValueGenerationStrategy), property.Name, "ComputedColumnSql")); + } } + + base.Validate(property, storeObject); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Conventions/IBValueGenerationConvention.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Conventions/IBValueGenerationConvention.cs index eb6081a..04e3b20 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Conventions/IBValueGenerationConvention.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Conventions/IBValueGenerationConvention.cs @@ -25,31 +25,27 @@ using Microsoft.EntityFrameworkCore.Metadata.Conventions; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Conventions +namespace InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Conventions; + +public class IBValueGenerationConvention : RelationalValueGenerationConvention { - public class IBValueGenerationConvention : RelationalValueGenerationConvention - { - public IBValueGenerationConvention(ProviderConventionSetBuilderDependencies dependencies, RelationalConventionSetBuilderDependencies relationalDependencies) - : base(dependencies, relationalDependencies) - { } + public IBValueGenerationConvention(ProviderConventionSetBuilderDependencies dependencies, RelationalConventionSetBuilderDependencies relationalDependencies) + : base(dependencies, relationalDependencies) + { } - public override void ProcessPropertyAnnotationChanged(IConventionPropertyBuilder propertyBuilder, string name, IConventionAnnotation annotation, IConventionAnnotation oldAnnotation, IConventionContext context) + public override void ProcessPropertyAnnotationChanged(IConventionPropertyBuilder propertyBuilder, string name, IConventionAnnotation annotation, IConventionAnnotation oldAnnotation, IConventionContext context) + { + if (name == IBAnnotationNames.ValueGenerationStrategy) { - if (name == IBAnnotationNames.ValueGenerationStrategy) - { - propertyBuilder.ValueGenerated(GetValueGenerated(propertyBuilder.Metadata)); - return; - } - base.ProcessPropertyAnnotationChanged(propertyBuilder, name, annotation, oldAnnotation, context); + propertyBuilder.ValueGenerated(GetValueGenerated(propertyBuilder.Metadata)); + return; } - - protected override ValueGenerated? GetValueGenerated(IConventionProperty property) - => GetValueGenerated(property); - - public static new ValueGenerated? GetValueGenerated(IProperty property) - => RelationalValueGenerationConvention.GetValueGenerated(property) - ?? (property.GetValueGenerationStrategy() != IBValueGenerationStrategy.None - ? ValueGenerated.OnAdd - : (ValueGenerated?)null); + base.ProcessPropertyAnnotationChanged(propertyBuilder, name, annotation, oldAnnotation, context); } + + protected override ValueGenerated? GetValueGenerated(IConventionProperty property) + => RelationalValueGenerationConvention.GetValueGenerated(property) + ?? (property.GetValueGenerationStrategy() != IBValueGenerationStrategy.None + ? ValueGenerated.OnAdd + : (ValueGenerated?)null); } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Conventions/IBValueGenerationStrategyConvention.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Conventions/IBValueGenerationStrategyConvention.cs index dc4af6f..14bb449 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Conventions/IBValueGenerationStrategyConvention.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Conventions/IBValueGenerationStrategyConvention.cs @@ -23,36 +23,35 @@ using Microsoft.EntityFrameworkCore.Metadata.Conventions; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Conventions +namespace InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Conventions; + +public class IBValueGenerationStrategyConvention : IModelInitializedConvention, IModelFinalizingConvention { - public class IBValueGenerationStrategyConvention : IModelInitializedConvention, IModelFinalizedConvention + public IBValueGenerationStrategyConvention(ProviderConventionSetBuilderDependencies dependencies, RelationalConventionSetBuilderDependencies relationalDependencies) { - public IBValueGenerationStrategyConvention(ProviderConventionSetBuilderDependencies dependencies, RelationalConventionSetBuilderDependencies relationalDependencies) - { - Dependencies = dependencies; - } + Dependencies = dependencies; + } - protected virtual ProviderConventionSetBuilderDependencies Dependencies { get; } + protected virtual ProviderConventionSetBuilderDependencies Dependencies { get; } - public virtual void ProcessModelInitialized(IConventionModelBuilder modelBuilder, IConventionContext context) - { -// modelBuilder.HasValueGenerationStrategy(IBValueGenerationStrategy.IdentityColumn); - } + public virtual void ProcessModelInitialized(IConventionModelBuilder modelBuilder, IConventionContext context) + { +// modelBuilder.HasValueGenerationStrategy(IBValueGenerationStrategy.IdentityColumn); + } - public virtual void ProcessModelFinalized(IConventionModelBuilder modelBuilder, IConventionContext context) + public void ProcessModelFinalizing(IConventionModelBuilder modelBuilder, IConventionContext context) + { + foreach (var entityType in modelBuilder.Metadata.GetEntityTypes()) { - foreach (var entityType in modelBuilder.Metadata.GetEntityTypes()) + foreach (var property in entityType.GetDeclaredProperties()) { - foreach (var property in entityType.GetDeclaredProperties()) + // Needed for the annotation to show up in the model snapshot + var strategy = property.GetValueGenerationStrategy(); + if (strategy != IBValueGenerationStrategy.None) { - // Needed for the annotation to show up in the model snapshot - var strategy = property.GetValueGenerationStrategy(); - if (strategy != IBValueGenerationStrategy.None) - { - property.Builder.HasValueGenerationStrategy(strategy); - } + property.Builder.HasValueGenerationStrategy(strategy); } } } } -} +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/IBValueGenerationStrategy.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/IBValueGenerationStrategy.cs index 65ec99b..124b615 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/IBValueGenerationStrategy.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/IBValueGenerationStrategy.cs @@ -18,12 +18,11 @@ //$Authors = Jiri Cincura (jiri@cincura.net), Jean Ressouche, Rafael Almeida (ralms@ralms.net) -namespace InterBaseSql.EntityFrameworkCore.InterBase.Metadata +namespace InterBaseSql.EntityFrameworkCore.InterBase.Metadata; + +public enum IBValueGenerationStrategy { - public enum IBValueGenerationStrategy - { - None, - SequenceTrigger, - IdentityColumn, - } + None, + SequenceTrigger, + IdentityColumn, } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Internal/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Internal/Changelog.md new file mode 100644 index 0000000..e734a4c --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Internal/Changelog.md @@ -0,0 +1,15 @@ +# Changes for 7.10.2 + +## General - +* All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. + +## Common - +* Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Metadata.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Internal +* Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. + +* All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. +* For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup + +* FbAnnotationNames.cs renamed to IBAnnotationNames.cs +* FbAnnotationNames now IBAnnotationNames +* Prefix changed from "Fb: " to "IB: " diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Internal/Changelog.txt b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Internal/Changelog.txt deleted file mode 100644 index c903b4a..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Internal/Changelog.txt +++ /dev/null @@ -1,15 +0,0 @@ -Changes for 7.10.2 - - General - - All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. - - Common - - Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Metadata.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Internal - Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. - - All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. - For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup - - FbAnnotationNames.cs renamed to IBAnnotationNames.cs - FbAnnotationNames now IBAnnotationNames - Prefix changed from "Fb: " ro "IB: " diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Internal/IBAnnotationNames.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Internal/IBAnnotationNames.cs index 146e28d..6ab5bf0 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Internal/IBAnnotationNames.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Internal/IBAnnotationNames.cs @@ -18,11 +18,10 @@ //$Authors = Jiri Cincura (jiri@cincura.net), Jean Ressouche, Rafael Almeida (ralms@ralms.net) -namespace InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Internal; + +public static class IBAnnotationNames { - public static class IBAnnotationNames - { - public const string Prefix = "IB:"; - public const string ValueGenerationStrategy = Prefix + nameof(ValueGenerationStrategy); - } + public const string Prefix = "IB:"; + public const string ValueGenerationStrategy = Prefix + nameof(ValueGenerationStrategy); } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Internal/IBMigrationsAnnotationProvider.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Internal/IBRelationalAnnotationProvider.cs similarity index 59% rename from NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Internal/IBMigrationsAnnotationProvider.cs rename to NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Internal/IBRelationalAnnotationProvider.cs index da9447e..b55c704 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Internal/IBMigrationsAnnotationProvider.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Metadata/Internal/IBRelationalAnnotationProvider.cs @@ -3,38 +3,46 @@ * Developer's Public License Version 1.0 (the "License"); * you may not use this file except in compliance with the * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. + * https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt. * * Software distributed under the License is distributed on * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either * express or implied. See the License for the specific * language governing rights and limitations under the License. * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * * All Rights Reserved. */ -//$Authors = Jiri Cincura (jiri@cincura.net), Jean Ressouche, Rafael Almeida (ralms@ralms.net) +//$Authors = Jiri Cincura (jiri@cincura.net) using System.Collections.Generic; -using InterBaseSql.EntityFrameworkCore.InterBase.Metadata; +using System.Linq; using InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Internal; +using InterBaseSql.EntityFrameworkCore.InterBase.Metadata; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Migrations.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Internal; + +public class IBRelationalAnnotationProvider : RelationalAnnotationProvider { - public class IBMigrationsAnnotationProvider : MigrationsAnnotationProvider - { - public IBMigrationsAnnotationProvider(MigrationsAnnotationProviderDependencies dependencies) +#pragma warning disable EF1001 + public IBRelationalAnnotationProvider(RelationalAnnotationProviderDependencies dependencies) +#pragma warning restore EF1001 : base(dependencies) - { } + { } + + public override IEnumerable For(IColumn column, bool designTime) + { + if (!designTime) + { + yield break; + } - public override IEnumerable For(IProperty property) + var property = column.PropertyMappings.Select(x => x.Property) + .FirstOrDefault(x => x.GetValueGenerationStrategy() != IBValueGenerationStrategy.None); + if (property != null) { var valueGenerationStrategy = property.GetValueGenerationStrategy(); if (valueGenerationStrategy != IBValueGenerationStrategy.None) @@ -43,4 +51,4 @@ public override IEnumerable For(IProperty property) } } } -} +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Changelog.md index 9c6069b..66f4ec1 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Changelog.md +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Changelog.md @@ -1,3 +1,14 @@ +# Changes to 7.13.6 + +## Removed Operations folder + +## IBMigrationSqlGeneratorBehavior.cs +* Fixed code around IB not supporting returning values on inserts and deletes + +## IBMigrationsSqlGenerator.cs +* Fixed bug around changing an column's nullability +* added COLLATE meta generation when a collate is indicated + # Changes 7.12.1 ## IBMigrationsSqlGenerator.cs diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/IBMigrationSqlGeneratorBehavior.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/IBMigrationSqlGeneratorBehavior.cs index 8b54e72..5c75d86 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/IBMigrationSqlGeneratorBehavior.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/IBMigrationSqlGeneratorBehavior.cs @@ -18,80 +18,128 @@ //$Authors = Jiri Cincura (jiri@cincura.net) +using InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.Extensions.Options; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Migrations +namespace InterBaseSql.EntityFrameworkCore.InterBase.Migrations; + +public class IBMigrationSqlGeneratorBehavior : IIBMigrationSqlGeneratorBehavior { - public class IBMigrationSqlGeneratorBehavior : IIBMigrationSqlGeneratorBehavior + readonly ISqlGenerationHelper _sqlGenerationHelper; + + public IBMigrationSqlGeneratorBehavior(ISqlGenerationHelper sqlGenerationHelper) + { + _sqlGenerationHelper = sqlGenerationHelper; + } + + public virtual void CreateSequenceTriggerForColumn(string columnName, string tableName, string schemaName, MigrationsSqlGenerationOptions options, MigrationCommandListBuilder builder) { - readonly ISqlGenerationHelper _sqlGenerationHelper; + var identitySequenceName = CreateSequenceTriggerSequenceName(columnName, tableName, schemaName); - public IBMigrationSqlGeneratorBehavior(ISqlGenerationHelper sqlGenerationHelper) + builder.Append("create generator "); + builder.Append(identitySequenceName); + builder.AppendLine(_sqlGenerationHelper.StatementTerminator); + if (options.HasFlag(MigrationsSqlGenerationOptions.Script)) { - _sqlGenerationHelper = sqlGenerationHelper; + builder.AppendLine(((IIBSqlGenerationHelper)_sqlGenerationHelper).AlternativeStatementTerminator); } - - public virtual void CreateSequenceTriggerForColumn(string columnName, string tableName, string schemaName, MigrationCommandListBuilder builder) + else { - var identitySequenceName = CreateSequenceTriggerSequenceName(columnName, tableName, schemaName); + builder.AppendLine(_sqlGenerationHelper.StatementTerminator); + } + builder.EndCommand(); - builder.Append("create generator "); - builder.Append(identitySequenceName); + builder.Append("CREATE TRIGGER "); + builder.Append(_sqlGenerationHelper.DelimitIdentifier(CreateSequenceTriggerName(columnName, tableName, schemaName))); + builder.Append(" ACTIVE BEFORE INSERT ON "); + builder.Append(_sqlGenerationHelper.DelimitIdentifier(tableName, schemaName)); + builder.AppendLine(); + builder.AppendLine("AS"); + builder.AppendLine("BEGIN"); + builder.IncrementIndent(); + builder.Append("if (new."); + builder.Append(_sqlGenerationHelper.DelimitIdentifier(columnName)); + builder.Append(" is null) then"); + builder.AppendLine(); + builder.AppendLine("begin"); + builder.IncrementIndent(); + builder.Append("new."); + builder.Append(_sqlGenerationHelper.DelimitIdentifier(columnName)); + builder.Append(" = next value for "); + builder.Append(identitySequenceName); + builder.Append(_sqlGenerationHelper.StatementTerminator); + builder.AppendLine(); + builder.DecrementIndent(); + builder.AppendLine("end"); + builder.DecrementIndent(); + builder.Append("END"); + builder.AppendLine(); + if (options.HasFlag(MigrationsSqlGenerationOptions.Script)) + { + builder.AppendLine(((IIBSqlGenerationHelper)_sqlGenerationHelper).AlternativeStatementTerminator); + } + else + { builder.AppendLine(_sqlGenerationHelper.StatementTerminator); - builder.EndCommand(); + } + builder.EndCommand(); - builder.Append("CREATE TRIGGER "); - builder.Append(_sqlGenerationHelper.DelimitIdentifier(CreateSequenceTriggerName(columnName, tableName, schemaName))); - builder.Append(" ACTIVE BEFORE INSERT ON "); - builder.Append(_sqlGenerationHelper.DelimitIdentifier(tableName, schemaName)); - builder.AppendLine(); - builder.AppendLine("AS"); - builder.AppendLine("BEGIN"); - builder.IncrementIndent(); - builder.Append("if (new."); - builder.Append(_sqlGenerationHelper.DelimitIdentifier(columnName)); - builder.Append(" is null) then"); - builder.AppendLine(); - builder.AppendLine("begin"); - builder.IncrementIndent(); - builder.Append("new."); - builder.Append(_sqlGenerationHelper.DelimitIdentifier(columnName)); - builder.Append(" = next value for "); - builder.Append(identitySequenceName); + if (options.HasFlag(MigrationsSqlGenerationOptions.Script)) + { + builder.Append("SET TERM "); builder.Append(_sqlGenerationHelper.StatementTerminator); - builder.AppendLine(); - builder.DecrementIndent(); - builder.AppendLine("end"); - builder.DecrementIndent(); - builder.Append("END"); - builder.AppendLine(); - builder.AppendLine(_sqlGenerationHelper.StatementTerminator); + builder.AppendLine(((IIBSqlGenerationHelper)_sqlGenerationHelper).AlternativeStatementTerminator); builder.EndCommand(); } + } - public virtual void DropSequenceTriggerForColumn(string columnName, string tableName, string schemaName, MigrationCommandListBuilder builder) - { - var triggerName = CreateSequenceTriggerName(columnName, tableName, schemaName); + public virtual void DropSequenceTriggerForColumn(string columnName, string tableName, string schemaName, MigrationsSqlGenerationOptions options, MigrationCommandListBuilder builder) + { + var triggerName = CreateSequenceTriggerName(columnName, tableName, schemaName); - builder.Append("execute statement 'drop trigger "); - builder.Append(_sqlGenerationHelper.DelimitIdentifier(triggerName)); - builder.Append("'"); - builder.Append(_sqlGenerationHelper.StatementTerminator); - builder.AppendLine(); + if (options.HasFlag(MigrationsSqlGenerationOptions.Script)) + { + builder.Append("SET TERM "); + builder.Append(((IIBSqlGenerationHelper)_sqlGenerationHelper).AlternativeStatementTerminator); + builder.AppendLine(_sqlGenerationHelper.StatementTerminator); builder.EndCommand(); } - protected virtual string CreateSequenceTriggerName(string columnName, string tableName, string schemaName) + builder.Append("execute statement 'drop trigger "); + builder.Append(_sqlGenerationHelper.DelimitIdentifier(triggerName)); + builder.Append("'"); + builder.Append(_sqlGenerationHelper.StatementTerminator); + builder.AppendLine(); + if (options.HasFlag(MigrationsSqlGenerationOptions.Script)) + { + builder.AppendLine(((IIBSqlGenerationHelper)_sqlGenerationHelper).AlternativeStatementTerminator); + } + else { - return !string.IsNullOrEmpty(schemaName) - ? $"ID_{schemaName}_{tableName}_{columnName}" - : $"ID_{tableName}_{columnName}"; + builder.AppendLine(_sqlGenerationHelper.StatementTerminator); } + builder.EndCommand(); - protected virtual string CreateSequenceTriggerSequenceName(string columnName, string tableName, string schemaName) + if (options.HasFlag(MigrationsSqlGenerationOptions.Script)) { - return "GEN_IDENTITY"; + builder.Append("SET TERM "); + builder.Append(_sqlGenerationHelper.StatementTerminator); + builder.AppendLine(((IIBSqlGenerationHelper)_sqlGenerationHelper).AlternativeStatementTerminator); + builder.EndCommand(); } } + + protected virtual string CreateSequenceTriggerName(string columnName, string tableName, string schemaName) + { + return !string.IsNullOrEmpty(schemaName) + ? $"ID_{schemaName}_{tableName}_{columnName}" + : $"ID_{tableName}_{columnName}"; + } + + protected virtual string CreateSequenceTriggerSequenceName(string columnName, string tableName, string schemaName) + { + return "GEN_IDENTITY"; + } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/IBMigrationsSqlGenerator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/IBMigrationsSqlGenerator.cs index 46ba6f8..e772bca 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/IBMigrationsSqlGenerator.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/IBMigrationsSqlGenerator.cs @@ -19,369 +19,365 @@ //$Authors = Jiri Cincura (jiri@cincura.net) using System; +using System.Collections.Generic; +using System.Globalization; using System.Linq; using InterBaseSql.Data.InterBaseClient; using InterBaseSql.EntityFrameworkCore.InterBase.Infrastructure.Internal; using InterBaseSql.EntityFrameworkCore.InterBase.Metadata; using InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Internal; -using InterBaseSql.EntityFrameworkCore.InterBase.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Storage; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Migrations +namespace InterBaseSql.EntityFrameworkCore.InterBase.Migrations; + +public class IBMigrationsSqlGenerator : MigrationsSqlGenerator { - public class IBMigrationsSqlGenerator : MigrationsSqlGenerator + readonly IIBMigrationSqlGeneratorBehavior _behavior; + readonly IIBOptions _options; + + public IBMigrationsSqlGenerator(MigrationsSqlGeneratorDependencies dependencies, IIBMigrationSqlGeneratorBehavior behavior, IIBOptions options) + : base(dependencies) { - readonly IIBMigrationSqlGeneratorBehavior _behavior; - readonly IIBOptions _options; + _behavior = behavior; + _options = options; + } - public IBMigrationsSqlGenerator(MigrationsSqlGeneratorDependencies dependencies, IIBMigrationSqlGeneratorBehavior behavior, IIBOptions options) - : base(dependencies) + protected override void Generate(MigrationOperation operation, IModel model, MigrationCommandListBuilder builder) + { + switch (operation) { - _behavior = behavior; - _options = options; + default: + base.Generate(operation, model, builder); + break; } + } - protected override void Generate(MigrationOperation operation, IModel model, MigrationCommandListBuilder builder) - { - switch (operation) - { - case IBCreateDatabaseOperation createDatabaseOperation: - Generate(createDatabaseOperation, model, builder); - break; - case IBDropDatabaseOperation dropDatabaseOperation: - Generate(dropDatabaseOperation, model, builder); - break; - default: - base.Generate(operation, model, builder); - break; - } - } + protected override void Generate(CreateTableOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate = true) + { + base.Generate(operation, model, builder, true); - protected override void Generate(CreateTableOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate = true) + var columns = operation.Columns.Where(p => !p.IsNullable && string.IsNullOrWhiteSpace(p.DefaultValueSql) && p.DefaultValue == null); + foreach (var column in columns) { - base.Generate(operation, model, builder, true); - - var columns = operation.Columns.Where(p => !p.IsNullable && string.IsNullOrWhiteSpace(p.DefaultValueSql) && p.DefaultValue == null); - foreach (var column in columns) + var valueGenerationStrategy = column[IBAnnotationNames.ValueGenerationStrategy] as IBValueGenerationStrategy?; + if (valueGenerationStrategy == IBValueGenerationStrategy.SequenceTrigger) { - var valueGenerationStrategy = column[IBAnnotationNames.ValueGenerationStrategy] as IBValueGenerationStrategy?; - if (valueGenerationStrategy == IBValueGenerationStrategy.SequenceTrigger) - { - _behavior.CreateSequenceTriggerForColumn(column.Name, column.Table, column.Schema, builder); - } + _behavior.CreateSequenceTriggerForColumn(column.Name, column.Table, column.Schema, Options, builder); } } + } - protected override void Generate(RenameTableOperation operation, IModel model, MigrationCommandListBuilder builder) - => throw new NotSupportedException("Renaming table is not supported by InterBase."); + protected override void Generate(RenameTableOperation operation, IModel model, MigrationCommandListBuilder builder) + => throw new NotSupportedException("Renaming table is not supported by InterBase."); - protected override void Generate(DropTableOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate = true) - => base.Generate(operation, model, builder, terminate); + protected override void Generate(DropTableOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate = true) + => base.Generate(operation, model, builder, terminate); - protected override void Generate(AlterTableOperation operation, IModel model, MigrationCommandListBuilder builder) - => base.Generate(operation, model, builder); + protected override void Generate(AlterTableOperation operation, IModel model, MigrationCommandListBuilder builder) + => base.Generate(operation, model, builder); - protected override void Generate(AlterColumnOperation operation, IModel model, MigrationCommandListBuilder builder) + protected override void Generate(AlterColumnOperation operation, IModel model, MigrationCommandListBuilder builder) + { + var valueGenerationStrategy = operation[IBAnnotationNames.ValueGenerationStrategy] as IBValueGenerationStrategy?; + var oldValueGenerationStrategy = operation.OldColumn[IBAnnotationNames.ValueGenerationStrategy] as IBValueGenerationStrategy?; + //if (oldValueGenerationStrategy == IBValueGenerationStrategy.IdentityColumn && valueGenerationStrategy != IBValueGenerationStrategy.IdentityColumn) + //{ + // throw new InvalidOperationException("Cannot remove identity from column."); + //} + if (oldValueGenerationStrategy == IBValueGenerationStrategy.SequenceTrigger && valueGenerationStrategy != IBValueGenerationStrategy.SequenceTrigger) { - var valueGenerationStrategy = operation[IBAnnotationNames.ValueGenerationStrategy] as IBValueGenerationStrategy?; - var oldValueGenerationStrategy = operation.OldColumn[IBAnnotationNames.ValueGenerationStrategy] as IBValueGenerationStrategy?; - //if (oldValueGenerationStrategy == IBValueGenerationStrategy.IdentityColumn && valueGenerationStrategy != IBValueGenerationStrategy.IdentityColumn) - //{ - // throw new InvalidOperationException("Cannot remove identity from column."); - //} - if (oldValueGenerationStrategy == IBValueGenerationStrategy.SequenceTrigger && valueGenerationStrategy != IBValueGenerationStrategy.SequenceTrigger) - { - _behavior.DropSequenceTriggerForColumn(operation.Name, operation.Table, operation.Schema, builder); - } + _behavior.DropSequenceTriggerForColumn(operation.Name, operation.Table, operation.Schema, Options, builder); + } - // will be recreated, if needed, by next statement + // will be recreated, if needed, by next statement + if (operation.IsNullable) + { + builder.Append("UPDATE RDB$RELATION_FIELDS SET RDB$NULL_FLAG = 0 WHERE RDB$FIELD_NAME = '" + operation.Name + "'"); + builder.Append(" AND RDB$RELATION_NAME = '" + operation.Table + "'"); + TerminateStatement(builder); + } + + builder.Append("ALTER TABLE "); + builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Table, operation.Schema)); + builder.Append(" ALTER COLUMN "); + builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name)); + builder.Append(" TYPE "); + if (operation.ColumnType != null) + { + builder.Append(operation.ColumnType); + } + else + { + var type = GetColumnType(operation.Schema, operation.Table, operation.Name, operation, model); + builder.Append(type); + } + if (operation.Collation != null) + { + builder.Append(" COLLATE "); + builder.Append(operation.Collation); + } + //if (valueGenerationStrategy == IBValueGenerationStrategy.IdentityColumn) + //{ + // builder.Append(" GENERATED BY DEFAULT AS IDENTITY"); + //} + builder.Append(operation.IsNullable ? string.Empty : " NOT NULL"); + TerminateStatement(builder); + + if (operation.DefaultValue != null || !string.IsNullOrWhiteSpace(operation.DefaultValueSql)) + { builder.Append("ALTER TABLE "); builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Table, operation.Schema)); builder.Append(" ALTER COLUMN "); builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name)); - builder.Append(" DROP NOT NULL"); + builder.Append(" DROP DEFAULT"); TerminateStatement(builder); builder.Append("ALTER TABLE "); builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Table, operation.Schema)); builder.Append(" ALTER COLUMN "); builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name)); - builder.Append(" TYPE "); - if (operation.ColumnType != null) - { - builder.Append(operation.ColumnType); - } - else - { - var type = GetColumnType(operation.Schema, operation.Table, operation.Name, operation, model); - builder.Append(type); - } - //if (valueGenerationStrategy == IBValueGenerationStrategy.IdentityColumn) - //{ - // builder.Append(" GENERATED BY DEFAULT AS IDENTITY"); - //} - builder.Append(operation.IsNullable ? string.Empty : " NOT NULL"); + builder.Append(" SET"); + DefaultValue(operation.DefaultValue, operation.DefaultValueSql, operation.ColumnType, builder); TerminateStatement(builder); - - if (operation.DefaultValue != null || !string.IsNullOrWhiteSpace(operation.DefaultValueSql)) - { - builder.Append("ALTER TABLE "); - builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Table, operation.Schema)); - builder.Append(" ALTER COLUMN "); - builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name)); - builder.Append(" DROP DEFAULT"); - TerminateStatement(builder); - - builder.Append("ALTER TABLE "); - builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Table, operation.Schema)); - builder.Append(" ALTER COLUMN "); - builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name)); - builder.Append(" SET"); - DefaultValue(operation.DefaultValue, operation.DefaultValueSql, operation.ColumnType, builder); - TerminateStatement(builder); - } - - if (valueGenerationStrategy == IBValueGenerationStrategy.SequenceTrigger) - { - _behavior.CreateSequenceTriggerForColumn(operation.Name, operation.Table, operation.Schema, builder); - } } - protected override void Generate(AddColumnOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate = true) - => base.Generate(operation, model, builder, terminate); - - protected override void Generate(DropColumnOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate = true) + if (valueGenerationStrategy == IBValueGenerationStrategy.SequenceTrigger) { - builder.Append("ALTER TABLE "); - builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Table, operation.Schema)); - builder.Append(" DROP "); - builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name)); - if (terminate) - TerminateStatement(builder); + _behavior.CreateSequenceTriggerForColumn(operation.Name, operation.Table, operation.Schema, Options, builder); } + } - protected override void Generate(RenameColumnOperation operation, IModel model, MigrationCommandListBuilder builder) - { - builder.Append("ALTER TABLE "); - builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Table, operation.Schema)); - builder.Append(" ALTER COLUMN "); - builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name)); - builder.Append(" TO "); - builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.NewName)); + protected override void Generate(AddColumnOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate = true) + => base.Generate(operation, model, builder, terminate); + + protected override void Generate(DropColumnOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate = true) + { + builder.Append("ALTER TABLE "); + builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Table, operation.Schema)); + builder.Append(" DROP "); + builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name)); + if (terminate) TerminateStatement(builder); - } + } + protected override void Generate(RenameColumnOperation operation, IModel model, MigrationCommandListBuilder builder) + { + builder.Append("ALTER TABLE "); + builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Table, operation.Schema)); + builder.Append(" ALTER COLUMN "); + builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name)); + builder.Append(" TO "); + builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.NewName)); + TerminateStatement(builder); + } - protected override void Generate(CreateIndexOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate = true) - { - builder.Append("CREATE "); - if (operation.IsUnique) - { - builder.Append("UNIQUE "); - } - IndexTraits(operation, model, builder); - builder.Append("INDEX "); - builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name)); - builder.Append(" ON "); - builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Table, operation.Schema)); - if (!string.IsNullOrEmpty(operation.Filter)) - { - builder.Append(" COMPUTED BY ("); - builder.Append(operation.Filter); - builder.Append(")"); - } - else - { - builder.Append(" ("); - builder.Append(ColumnList(operation.Columns)); - builder.Append(")"); - } - if (terminate) - TerminateStatement(builder); - } - protected override void Generate(DropIndexOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate = true) + protected override void Generate(CreateIndexOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate = true) + { + builder.Append("CREATE "); + if (operation.IsUnique) { - builder.Append("DROP "); - IndexTraits(operation, model, builder); - builder.Append("INDEX "); - builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name)); - if (terminate) - TerminateStatement(builder); + builder.Append("UNIQUE "); } - - protected override void Generate(RenameIndexOperation operation, IModel model, MigrationCommandListBuilder builder) - => throw new NotSupportedException("Renaming index is not supported by InterBase."); - - - protected override void Generate(CreateSequenceOperation operation, IModel model, MigrationCommandListBuilder builder) + IndexTraits(operation, model, builder); + builder.Append("INDEX "); + builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name)); + builder.Append(" ON "); + builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Table, operation.Schema)); + if (!string.IsNullOrEmpty(operation.Filter)) { - builder.Append("create generator "); - builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name, operation.Schema)); - builder.Append(" START WITH "); - builder.Append(operation.StartValue); - builder.Append(" INCREMENT BY "); - builder.Append(operation.IncrementBy); - TerminateStatement(builder); + builder.Append(" COMPUTED BY ("); + builder.Append(operation.Filter); + builder.Append(")"); } - - protected override void Generate(AlterSequenceOperation operation, IModel model, MigrationCommandListBuilder builder) + else { - builder.Append("alter generator "); - builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name, operation.Schema)); - builder.Append(" RESTART INCREMENT BY "); - builder.Append(operation.IncrementBy); - TerminateStatement(builder); + builder.Append(" ("); + builder.Append(ColumnList(operation.Columns)); + builder.Append(")"); } + if (terminate) + TerminateStatement(builder); + } - protected override void Generate(RestartSequenceOperation operation, IModel model, MigrationCommandListBuilder builder) - { - builder.Append("alter generator "); - builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name, operation.Schema)); - builder.Append(" START WITH "); - builder.Append(operation.StartValue); + protected override void Generate(DropIndexOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate = true) + { + builder.Append("DROP "); + IndexTraits(operation, model, builder); + builder.Append("INDEX "); + builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name)); + if (terminate) TerminateStatement(builder); - } + } + + protected override void Generate(RenameIndexOperation operation, IModel model, MigrationCommandListBuilder builder) + => throw new NotSupportedException("Renaming index is not supported by InterBase."); - protected override void Generate(RenameSequenceOperation operation, IModel model, MigrationCommandListBuilder builder) - => throw new NotSupportedException("Renaming sequence is not supported by InterBase."); - protected override void Generate(DropSequenceOperation operation, IModel model, MigrationCommandListBuilder builder) - => base.Generate(operation, model, builder); + protected override void Generate(CreateSequenceOperation operation, IModel model, MigrationCommandListBuilder builder) + { + builder.Append("create generator "); + builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name, operation.Schema)); + builder.Append(" START WITH "); + builder.Append(operation.StartValue.ToString(CultureInfo.InvariantCulture)); + builder.Append(" INCREMENT BY "); + builder.Append(operation.IncrementBy.ToString(CultureInfo.InvariantCulture)); + TerminateStatement(builder); + } - protected override void Generate(AddPrimaryKeyOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate = true) - => base.Generate(operation, model, builder, terminate); + protected override void Generate(AlterSequenceOperation operation, IModel model, MigrationCommandListBuilder builder) + { + builder.Append("alter generator "); + builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name, operation.Schema)); + builder.Append(" RESTART INCREMENT BY "); + builder.Append(operation.IncrementBy.ToString(CultureInfo.InvariantCulture)); + TerminateStatement(builder); + } - protected override void Generate(DropPrimaryKeyOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate = true) - => base.Generate(operation, model, builder, terminate); + protected override void Generate(RestartSequenceOperation operation, IModel model, MigrationCommandListBuilder builder) + { + builder.Append("alter generator "); + builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name, operation.Schema)); + builder.Append(" START WITH "); + builder.Append(operation.StartValue.ToString(CultureInfo.InvariantCulture)); + TerminateStatement(builder); + } + protected override void Generate(RenameSequenceOperation operation, IModel model, MigrationCommandListBuilder builder) + => throw new NotSupportedException("Renaming sequence is not supported by InterBase."); - protected override void Generate(AddForeignKeyOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate = true) - => base.Generate(operation, model, builder, terminate); + protected override void Generate(DropSequenceOperation operation, IModel model, MigrationCommandListBuilder builder) + => base.Generate(operation, model, builder); - protected override void Generate(DropForeignKeyOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate = true) - => base.Generate(operation, model, builder, terminate); + protected override void Generate(AddPrimaryKeyOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate = true) + => base.Generate(operation, model, builder, terminate); + protected override void Generate(DropPrimaryKeyOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate = true) + => base.Generate(operation, model, builder, terminate); - protected override void Generate(AddUniqueConstraintOperation operation, IModel model, MigrationCommandListBuilder builder) - => base.Generate(operation, model, builder); - protected override void Generate(DropUniqueConstraintOperation operation, IModel model, MigrationCommandListBuilder builder) - => base.Generate(operation, model, builder); + protected override void Generate(AddForeignKeyOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate = true) + => base.Generate(operation, model, builder, terminate); + protected override void Generate(DropForeignKeyOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate = true) + => base.Generate(operation, model, builder, terminate); - protected override void Generate(AlterDatabaseOperation operation, IModel model, MigrationCommandListBuilder builder) - => base.Generate(operation, model, builder); + protected override void Generate(AddUniqueConstraintOperation operation, IModel model, MigrationCommandListBuilder builder) + => base.Generate(operation, model, builder); - protected override void Generate(SqlOperation operation, IModel model, MigrationCommandListBuilder builder) - => base.Generate(operation, model, builder); + protected override void Generate(DropUniqueConstraintOperation operation, IModel model, MigrationCommandListBuilder builder) + => base.Generate(operation, model, builder); - protected override void Generate(DropSchemaOperation operation, IModel model, MigrationCommandListBuilder builder) - => throw new NotSupportedException("Schemas are not supported by InterBase."); + protected override void Generate(AlterDatabaseOperation operation, IModel model, MigrationCommandListBuilder builder) + => base.Generate(operation, model, builder); - protected override void Generate(EnsureSchemaOperation operation, IModel model, MigrationCommandListBuilder builder) - => throw new NotSupportedException("Schemas are not supported by InterBase."); + protected override void Generate(SqlOperation operation, IModel model, MigrationCommandListBuilder builder) + => base.Generate(operation, model, builder); - public virtual void Generate(IBCreateDatabaseOperation operation, IModel model, MigrationCommandListBuilder builder) - { - IBConnection.CreateDatabase(operation.ConnectionString); - } - public virtual void Generate(IBDropDatabaseOperation operation, IModel model, MigrationCommandListBuilder builder) - { - IBConnection.ClearPool(operation.ConnectionString); - IBConnection.DropDatabase(operation.ConnectionString); - } + protected override void Generate(DropSchemaOperation operation, IModel model, MigrationCommandListBuilder builder) + => throw new NotSupportedException("Schemas are not supported by InterBase."); - protected override void ColumnDefinition(string schema, string table, string name, ColumnOperation operation, IModel model, MigrationCommandListBuilder builder) - { - builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(name)) - .Append(" ") - .Append(operation.ColumnType ?? GetColumnType(schema, table, name, operation, model)); + protected override void Generate(EnsureSchemaOperation operation, IModel model, MigrationCommandListBuilder builder) + => throw new NotSupportedException("Schemas are not supported by InterBase."); - var valueGenerationStrategy = operation[IBAnnotationNames.ValueGenerationStrategy] as IBValueGenerationStrategy?; - //if (valueGenerationStrategy == IBValueGenerationStrategy.IdentityColumn) - //{ - // builder.Append(" GENERATED BY DEFAULT AS IDENTITY"); - //} - DefaultValue(operation.DefaultValue, operation.DefaultValueSql, operation.ColumnType, builder); + protected override void ColumnDefinition(string schema, string table, string name, ColumnOperation operation, IModel model, MigrationCommandListBuilder builder) + { + builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(name)); + builder.Append(" "); + builder.Append(operation.ColumnType ?? GetColumnType(schema, table, name, operation, model)); - if (!operation.IsNullable) - { - builder.Append(" NOT NULL"); - } + if (operation.Collation != null) + { + builder.Append(" COLLATE "); + builder.Append(operation.Collation); } - protected override void DefaultValue(object defaultValue, string defaultValueSql, string columnType, MigrationCommandListBuilder builder) + var valueGenerationStrategy = operation[IBAnnotationNames.ValueGenerationStrategy] as IBValueGenerationStrategy?; + //if (valueGenerationStrategy == IBValueGenerationStrategy.IdentityColumn) + //{ + // builder.Append(" GENERATED BY DEFAULT AS IDENTITY"); + //} + + DefaultValue(operation.DefaultValue, operation.DefaultValueSql, operation.ColumnType, builder); + + if (!operation.IsNullable) { - if (defaultValueSql != null) - { - builder.Append(" DEFAULT "); - builder.Append(defaultValueSql); - } - else if (defaultValue != null) - { - builder.Append(" DEFAULT "); - var typeMapping = Dependencies.TypeMappingSource.GetMappingForValue(defaultValue); - builder.Append(typeMapping.GenerateSqlLiteral(defaultValue)); - } + builder.Append(" NOT NULL"); } + } + - protected override void ForeignKeyConstraint(AddForeignKeyOperation operation, IModel model, MigrationCommandListBuilder builder) + protected override void DefaultValue(object defaultValue, string defaultValueSql, string columnType, MigrationCommandListBuilder builder) + { + if (defaultValueSql != null) { - if (operation.Name != null) - { - builder.Append("CONSTRAINT "); - builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name)); - builder.Append(" "); - } - builder.Append("FOREIGN KEY ("); - builder.Append(ColumnList(operation.Columns)); - builder.Append(") REFERENCES "); - builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.PrincipalTable, operation.PrincipalSchema)); - if (operation.PrincipalColumns != null) - { - builder.Append(" ("); - builder.Append(ColumnList(operation.PrincipalColumns)); - builder.Append(")"); - } - if (operation.OnUpdate != ReferentialAction.Restrict) - { - builder.Append(" ON UPDATE "); - ForeignKeyAction(operation.OnUpdate, builder); - } - if (operation.OnDelete != ReferentialAction.Restrict) - { - builder.Append(" ON DELETE "); - ForeignKeyAction(operation.OnDelete, builder); - } + builder.Append(" DEFAULT "); + builder.Append(defaultValueSql); + } + else if (defaultValue != null) + { + builder.Append(" DEFAULT "); + var typeMapping = Dependencies.TypeMappingSource.GetMappingForValue(defaultValue); + builder.Append(typeMapping.GenerateSqlLiteral(defaultValue)); } + } - protected override void ForeignKeyAction(ReferentialAction referentialAction, MigrationCommandListBuilder builder) + protected override void ForeignKeyConstraint(AddForeignKeyOperation operation, IModel model, MigrationCommandListBuilder builder) + { + if (operation.Name != null) { - switch (referentialAction) - { - case ReferentialAction.NoAction: - builder.Append("NO ACTION"); - break; - default: - base.ForeignKeyAction(referentialAction, builder); - break; - } + builder.Append("CONSTRAINT "); + builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name)); + builder.Append(" "); + } + builder.Append("FOREIGN KEY ("); + builder.Append(ColumnList(operation.Columns)); + builder.Append(") REFERENCES "); + builder.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.PrincipalTable, operation.PrincipalSchema)); + if (operation.PrincipalColumns != null) + { + builder.Append(" ("); + builder.Append(ColumnList(operation.PrincipalColumns)); + builder.Append(")"); + } + if (operation.OnUpdate != ReferentialAction.Restrict) + { + builder.Append(" ON UPDATE "); + ForeignKeyAction(operation.OnUpdate, builder); + } + if (operation.OnDelete != ReferentialAction.Restrict) + { + builder.Append(" ON DELETE "); + ForeignKeyAction(operation.OnDelete, builder); } + } - protected virtual void TerminateStatement(MigrationCommandListBuilder builder) + protected override void ForeignKeyAction(ReferentialAction referentialAction, MigrationCommandListBuilder builder) + { + switch (referentialAction) { - builder.AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator); - EndStatement(builder); + case ReferentialAction.NoAction: + builder.Append("NO ACTION"); + break; + default: + base.ForeignKeyAction(referentialAction, builder); + break; } } + + protected virtual void TerminateStatement(MigrationCommandListBuilder builder) + { + builder.AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator); + EndStatement(builder); + } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/IIBMigrationSqlGeneratorBehavior.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/IIBMigrationSqlGeneratorBehavior.cs index ba422df..bcf4186 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/IIBMigrationSqlGeneratorBehavior.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/IIBMigrationSqlGeneratorBehavior.cs @@ -20,11 +20,10 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace InterBaseSql.EntityFrameworkCore.InterBase +namespace InterBaseSql.EntityFrameworkCore.InterBase; + +public interface IIBMigrationSqlGeneratorBehavior { - public interface IIBMigrationSqlGeneratorBehavior - { - void CreateSequenceTriggerForColumn(string columnName, string tableName, string schemaName, MigrationCommandListBuilder builder); - void DropSequenceTriggerForColumn(string columnName, string tableName, string schemaName, MigrationCommandListBuilder builder); - } + void CreateSequenceTriggerForColumn(string columnName, string tableName, string schemaName, MigrationsSqlGenerationOptions options, MigrationCommandListBuilder builder); + void DropSequenceTriggerForColumn(string columnName, string tableName, string schemaName, MigrationsSqlGenerationOptions options, MigrationCommandListBuilder builder); } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Internal/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Internal/Changelog.md new file mode 100644 index 0000000..9dc93ff --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Internal/Changelog.md @@ -0,0 +1,19 @@ +# Changes for 7.13.6 + +## Removed IBMigrationsAnnotationProvider.cs + +# Changes for 7.10.2 + +## General - +* All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. + +## Common - +* Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Migrations.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Migrations.Internal +* Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. + +* All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. +* For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup + +* using FirebirdSql.EntityFrameworkCore.Firebird.Metadata.Internal, FirebirdSql.EntityFrameworkCore.Firebird.Metadata +* now InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Internal, InterBaseSql.EntityFrameworkCore.InterBase.Metadata + diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Internal/Changelog.txt b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Internal/Changelog.txt deleted file mode 100644 index ef5f238..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Internal/Changelog.txt +++ /dev/null @@ -1,15 +0,0 @@ -Changes for 7.10.2 - - General - - All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. - - Common - - Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Migrations.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Migrations.Internal - Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. - - All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. - For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup - - using FirebirdSql.EntityFrameworkCore.Firebird.Metadata.Internal, FirebirdSql.EntityFrameworkCore.Firebird.Metadata - now InterBaseSql.EntityFrameworkCore.InterBase.Metadata.Internal, InterBaseSql.EntityFrameworkCore.InterBase.Metadata - diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Internal/IBHistoryRepository.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Internal/IBHistoryRepository.cs index 667af61..d6f74b2 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Internal/IBHistoryRepository.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Internal/IBHistoryRepository.cs @@ -22,40 +22,39 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Migrations.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Migrations.Internal; + +public class IBHistoryRepository : HistoryRepository { - public class IBHistoryRepository : HistoryRepository - { - public IBHistoryRepository(HistoryRepositoryDependencies dependencies) - : base(dependencies) - { } + public IBHistoryRepository(HistoryRepositoryDependencies dependencies) + : base(dependencies) + { } - protected override string ExistsSql + protected override string ExistsSql + { + get { - get - { - var escapedTableName = Dependencies.TypeMappingSource.GetMapping(typeof(string)).GenerateSqlLiteral(TableName); - return $@"SELECT COUNT(*) FROM rdb$relations WHERE COALESCE(rdb$system_flag, 0) = 0 AND rdb$view_blr IS NULL AND rdb$relation_name = {escapedTableName}"; - } + var escapedTableName = Dependencies.TypeMappingSource.GetMapping(typeof(string)).GenerateSqlLiteral(TableName); + return $@"SELECT COUNT(*) FROM rdb$relations WHERE COALESCE(rdb$system_flag, 0) = 0 AND rdb$view_blr IS NULL AND rdb$relation_name = {escapedTableName}"; } + } - protected override bool InterpretExistsResult(object value) => Convert.ToInt64(value) != 0; + protected override bool InterpretExistsResult(object value) => Convert.ToInt64(value) != 0; - public override string GetCreateIfNotExistsScript() => GetCreateScript(); + public override string GetCreateIfNotExistsScript() => GetCreateScript(); - public override string GetBeginIfExistsScript(string migrationId) - { - throw new NotSupportedException("Generating idempotent scripts is currently not supported."); - } + public override string GetBeginIfExistsScript(string migrationId) + { + throw new NotSupportedException("Generating idempotent scripts is currently not supported."); + } - public override string GetBeginIfNotExistsScript(string migrationId) - { - throw new NotSupportedException("Generating idempotent scripts is currently not supported."); - } + public override string GetBeginIfNotExistsScript(string migrationId) + { + throw new NotSupportedException("Generating idempotent scripts is currently not supported."); + } - public override string GetEndIfScript() - { - throw new NotSupportedException("Generating idempotent scripts is currently not supported."); - } + public override string GetEndIfScript() + { + throw new NotSupportedException("Generating idempotent scripts is currently not supported."); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Operations/Changelog.txt b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Operations/Changelog.txt deleted file mode 100644 index be96261..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Operations/Changelog.txt +++ /dev/null @@ -1,13 +0,0 @@ -Changes for 7.10.2 - - General - - All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. - - Common - - Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Migrations.Operations to InterBaseSql.EntityFrameworkCore.InterBase.Migrations.Operations - Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. - - All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. - For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup - - diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Operations/IBCreateDatabaseOperation.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Operations/IBCreateDatabaseOperation.cs deleted file mode 100644 index 850eb3b..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Operations/IBCreateDatabaseOperation.cs +++ /dev/null @@ -1,29 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using Microsoft.EntityFrameworkCore.Migrations.Operations; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.Migrations.Operations -{ - public class IBCreateDatabaseOperation : MigrationOperation - { - public virtual string ConnectionString { get; set; } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Operations/IBDropDatabaseOperation.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Operations/IBDropDatabaseOperation.cs deleted file mode 100644 index 6a15197..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Migrations/Operations/IBDropDatabaseOperation.cs +++ /dev/null @@ -1,29 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using Microsoft.EntityFrameworkCore.Migrations.Operations; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.Migrations.Operations -{ - public class IBDropDatabaseOperation : MigrationOperation - { - public virtual string ConnectionString { get; set; } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/Changelog.md new file mode 100644 index 0000000..b9fc3d0 --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/Changelog.md @@ -0,0 +1,82 @@ +# Changes for 7.13.6 (mostly update to EFCore 6.0 and Fb 9.x driver) + +## removed IBStartsWithOptimizedTranslator.cs, IBEndsWithOptimizedTranslator.cs, IBDateTimeDatePartComponentTranslator.cs and IBContainsOptimizedTranslator.cs + +## Added IBByteArrayMethodTranslator.cs, IBDateOnlyPartComponentnTranslator.cs, IBDateTimePartComponentTranslator.cs, IBStringContainsTranslator.cs, +## IBStringEndsWithTranslator.cs, IBStringFirstOrDefaultTranslator.cs, IBStringLastOrDefaultTranslator.cs, IBStringStartsWithTranslator.cs, +## IBTimeOnlyPartComponentTranslator.cs and IBTimeSpanPartComponentTranslator.cs + + +# Changes for 7.10.2 + +## General - +* All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. + +## Common - +* Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Query.ExpressionTranslators.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal +* Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. + +* All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. +* For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup + +* using FirebirdSql.EntityFrameworkCore.Firebird.Query.Internal now InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal + +## FbConvertTranslator.cs renamed to IBConvertTranslator.cs +* FbConvertTranslator now IBConvertTranslator +* internal dictionary now maps int64 to Numeric(18, 0) + +## FbDateAddTranslator.cs now IBDateAddTranslator.cs +* FbDateAddTranslator now IBDateAddTranslator +* Translate now uses the UDF EF_DATEADD + +## FbEndsWithOptimizedTranslator.cs renamed to IBEndsWithOptimizedTranslator.cs +* FbEndsWithOptimizedTranslator now IBEndsWithOptimizedTranslator +* Translate now used the IDF EF_LENGTH + +## FbMathTranslator.cs renamed to IBMathTranslator.cs +* FbMathTranslator now IBMathTranslator +* The internal Fb function ABS replaced with the UDF EF_ABS +* The internal Fb function CEILING replaced with EF_CEILING +* The internal Fb function FLOOR replaced with the UDF EF_FLOOR +* The internal Fb function POWER replaced with the UDF EF_POWER +* The internal Fb function EXP replaced with the UDF EF_EXP + +## FbNewGuidTranslator.cs renamed to IBNewGuidTranslator.cs +* FbNewGuidTranslator now IBNewGuidTranslator +* Translate now calls the UDF EF_NEWGUID + +## FbObjectToStringTranslator.cs renamed to IBObjectToStringTranslator.cs +* FbObjectToStringTranslator now IBObjectToStringTranslator +* Translate now calls the UDF EF_UUID_TO_CHAR + +## FbStartsWithOptimizedTranslator.cs renamed to IBStartsWithOptimizedTranslator.cs +* FbStartsWithOptimizedTranslator now IBStartsWithOptimizedTranslator +* Translate now calls the UDF EF_LENGTH + +## FbStringIndexOfTranslator.cs renamed to IBStringIndexOfTranslator.cs +* FbStringIndexOfTranslator now IBStringIndexOfTranslator +* Translate now calls the UDF EF_POSITION + +## FbStringIsNullOrWhiteSpaceTranslator.cs renamed to IBStringIsNullOrWhiteSpaceTranslator.cs +* FbStringIsNullOrWhiteSpaceTranslator now IBStringIsNullOrWhiteSpaceTranslator +* Translate now calls the UDF EF_TRIM + +## FbStringLengthTranslator.cs renamed to IBStringLengthTranslator.cs +* FbStringLengthTranslator now IBStringLengthTranslator +* Translate now calls the UDF EF_LENGTH + +## FbStringReplaceTranslator.cs renamed to IBStringReplaceTranslator.cs +* FbStringReplaceTranslator now IBStringReplaceTranslator +* Translate now calls the UDF EF_REPLACE + +## FbStringToLowerTranslator.cs renamed to IBStringToLowerTranslator.cs +* FbStringToLowerTranslator now IBStringToLowerTranslator +* Translate now calls the UDF EF_LOWER + +## FbStringToLowerTranslator.cs renamed to IBStringToLowerTranslator.cs +* FbStringToLowerTranslator now IBStringToLowerTranslator +* Translate now single quotes "'BOTH'", "'LEADING'" and "'TRAILING'" to be passed to EF_TRIM UDF + + + + diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/Changelog.txt b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/Changelog.txt deleted file mode 100644 index 800a610..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/Changelog.txt +++ /dev/null @@ -1,73 +0,0 @@ -Changes for 7.10.2 - - General - - All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. - - Common - - Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Query.ExpressionTranslators.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal - Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. - - All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. - For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup - - using FirebirdSql.EntityFrameworkCore.Firebird.Query.Internal now InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal - - FbConvertTranslator.cs renamed to IBConvertTranslator.cs - FbConvertTranslator now IBConvertTranslator - internal dictionary now maps int64 to Numeric(18, 0) - - FbDateAddTranslator.cs now IBDateAddTranslator.cs - FbDateAddTranslator now IBDateAddTranslator - Translate now uses the UDF EF_DATEADD - - FbEndsWithOptimizedTranslator.cs renamed to IBEndsWithOptimizedTranslator.cs - FbEndsWithOptimizedTranslator now IBEndsWithOptimizedTranslator - Translate now used the IDF EF_LENGTH - - FbMathTranslator.cs renamed to IBMathTranslator.cs - FbMathTranslator now IBMathTranslator - The internal Fb function ABS replaced with the UDF EF_ABS - The internal Fb function CEILING replaced with EF_CEILING - The internal Fb function FLOOR replaced with the UDF EF_FLOOR - The internal Fb function POWER replaced with the UDF EF_POWER - The internal Fb function EXP replaced with the UDF EF_EXP - - FbNewGuidTranslator.cs renamed to IBNewGuidTranslator.cs - FbNewGuidTranslator now IBNewGuidTranslator - Translate now calls the UDF EF_NEWGUID - - FbObjectToStringTranslator.cs renamed to IBObjectToStringTranslator.cs - FbObjectToStringTranslator now IBObjectToStringTranslator - Translate now calls the UDF EF_UUID_TO_CHAR - - FbStartsWithOptimizedTranslator.cs renamed to IBStartsWithOptimizedTranslator.cs - FbStartsWithOptimizedTranslator now IBStartsWithOptimizedTranslator - Translate now calls the UDF EF_LENGTH - - FbStringIndexOfTranslator.cs renamed to IBStringIndexOfTranslator.cs - FbStringIndexOfTranslator now IBStringIndexOfTranslator - Translate now calls the UDF EF_POSITION - - FbStringIsNullOrWhiteSpaceTranslator.cs renamed to IBStringIsNullOrWhiteSpaceTranslator.cs - FbStringIsNullOrWhiteSpaceTranslator now IBStringIsNullOrWhiteSpaceTranslator - Translate now calls the UDF EF_TRIM - - FbStringLengthTranslator.cs renamed to IBStringLengthTranslator.cs - FbStringLengthTranslator now IBStringLengthTranslator - Translate now calls the UDF EF_LENGTH - - FbStringReplaceTranslator.cs renamed to IBStringReplaceTranslator.cs - FbStringReplaceTranslator now IBStringReplaceTranslator - Translate now calls the UDF EF_REPLACE - - FbStringToLowerTranslator.cs renamed to IBStringToLowerTranslator.cs - FbStringToLowerTranslator now IBStringToLowerTranslator - Translate now calls the UDF EF_LOWER - - FbStringToLowerTranslator.cs renamed to IBStringToLowerTranslator.cs - FbStringToLowerTranslator now IBStringToLowerTranslator - Translate now single quotes "'BOTH'", "'LEADING'" and "'TRAILING'" to be passed to EF_TRIM UDF - - - - \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBByteArrayMethodTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBByteArrayMethodTranslator.cs new file mode 100644 index 0000000..380c30d --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBByteArrayMethodTranslator.cs @@ -0,0 +1,58 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt. + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * All Rights Reserved. + */ + +//$Authors = Jiri Cincura (jiri@cincura.net) + +using System.Collections.Generic; +using System.Reflection; +using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; + +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBByteArrayMethodTranslator : IMethodCallTranslator +{ + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + + public IBByteArrayMethodTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) + { + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } + + public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) + { + if (method.IsGenericMethod + && method.GetGenericMethodDefinition().Equals(EnumerableMethods.Contains) + && arguments[0].Type == typeof(byte[])) + { + var value = arguments[1] is SqlConstantExpression constantValue + ? _ibSqlExpressionFactory.Function("ASCII_CHAR", new[] { _ibSqlExpressionFactory.Constant((byte)constantValue.Value) }, false, new[] { false }, typeof(string)) + : _ibSqlExpressionFactory.Function("ASCII_CHAR", new[] { _ibSqlExpressionFactory.Convert(_ibSqlExpressionFactory.ApplyDefaultTypeMapping(arguments[1]), typeof(byte)) }, true, new[] { true }, typeof(string)); + + return _ibSqlExpressionFactory.GreaterThan( + _ibSqlExpressionFactory.Function( + "POSITION", + new[] { value, _ibSqlExpressionFactory.ApplyDefaultTypeMapping(arguments[0]) }, + true, + new[] { true, true }, + typeof(int)), + _ibSqlExpressionFactory.Constant(0)); + } + return null; + } +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBContainsOptimizedTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBContainsOptimizedTranslator.cs deleted file mode 100644 index 0ea5f9f..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBContainsOptimizedTranslator.cs +++ /dev/null @@ -1,63 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using System.Collections.Generic; -using System.Reflection; -using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.SqlExpressions; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal -{ - public class IBContainsOptimizedTranslator : IMethodCallTranslator - { - static readonly MethodInfo MethodInfo = typeof(string).GetRuntimeMethod(nameof(string.Contains), new[] { typeof(string) }); - - readonly IBSqlExpressionFactory _ibSqlExpressionFactory; - - public IBContainsOptimizedTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) - { - _ibSqlExpressionFactory = ibSqlExpressionFactory; - } - - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) - { - if (!method.Equals(MethodInfo)) - return null; - - var patternExpression = arguments[0]; - var positionExpression = _ibSqlExpressionFactory.GreaterThan( - _ibSqlExpressionFactory.Function( - "POSITION", - new[] { patternExpression, instance }, - typeof(int)), - _ibSqlExpressionFactory.Constant(0)); - return patternExpression is SqlConstantExpression sqlConstantExpression - ? ((string)sqlConstantExpression.Value)?.Length == 0 - ? (SqlExpression)_ibSqlExpressionFactory.Constant(true) - : positionExpression - : _ibSqlExpressionFactory.OrElse( - positionExpression, - _ibSqlExpressionFactory.Equal( - patternExpression, - _ibSqlExpressionFactory.Constant(string.Empty))); - } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBConvertTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBConvertTranslator.cs index 792fe6d..493c2bd 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBConvertTranslator.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBConvertTranslator.cs @@ -24,56 +24,58 @@ using System.Reflection; using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; using InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBConvertTranslator : IMethodCallTranslator { - public class IBConvertTranslator : IMethodCallTranslator + static readonly List Mappings = new List { - static readonly Dictionary TypeMappings = new Dictionary - { - [nameof(Convert.ToByte)] = "SMALLINT", - [nameof(Convert.ToDecimal)] = $"DECIMAL({IBTypeMappingSource.DefaultDecimalPrecision},{IBTypeMappingSource.DefaultDecimalScale})", - [nameof(Convert.ToDouble)] = "DOUBLE PRECISION", - [nameof(Convert.ToInt16)] = "SMALLINT", - [nameof(Convert.ToInt32)] = "INTEGER", - [nameof(Convert.ToInt64)] = "NUMERIC(18, 0)", - [nameof(Convert.ToString)] = $"VARCHAR({IBTypeMappingSource.VarcharMaxSize})" - }; + nameof(Convert.ToByte), + nameof(Convert.ToDecimal), + nameof(Convert.ToDouble), + nameof(Convert.ToInt16), + nameof(Convert.ToInt32), + nameof(Convert.ToInt64), + nameof(Convert.ToString), + }; - static readonly HashSet SupportedTypes = new HashSet - { - typeof(bool), - typeof(byte), - typeof(decimal), - typeof(double), - typeof(float), - typeof(int), - typeof(long), - typeof(short), - typeof(string), - typeof(DateTime), - }; + static readonly HashSet SupportedTypes = new HashSet + { + typeof(bool), + typeof(byte), + typeof(decimal), + typeof(double), + typeof(float), + typeof(int), + typeof(long), + typeof(short), + typeof(string), + typeof(DateTime), + }; - static readonly IEnumerable SupportedMethods - = TypeMappings.Keys - .SelectMany(t => typeof(Convert).GetTypeInfo().GetDeclaredMethods(t) - .Where(m => m.GetParameters().Length == 1 && SupportedTypes.Contains(m.GetParameters().First().ParameterType))); + static readonly IEnumerable SupportedMethods + = Mappings + .SelectMany(t => typeof(Convert).GetTypeInfo().GetDeclaredMethods(t) + .Where(m => m.GetParameters().Length == 1 && SupportedTypes.Contains(m.GetParameters().First().ParameterType))); - readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; - public IBConvertTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) - { - _ibSqlExpressionFactory = ibSqlExpressionFactory; - } + public IBConvertTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) + { + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) - { - if (!SupportedMethods.Contains(method)) - return null; + public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) + { + if (!SupportedMethods.Contains(method)) + return null; - return _ibSqlExpressionFactory.Convert(arguments[0], method.ReturnType); - } + return _ibSqlExpressionFactory.ApplyDefaultTypeMapping( + _ibSqlExpressionFactory.Convert(_ibSqlExpressionFactory.ApplyDefaultTypeMapping(arguments[0]), method.ReturnType)); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateAddTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateAddTranslator.cs index b05af9f..46a74de 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateAddTranslator.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateAddTranslator.cs @@ -22,40 +22,49 @@ using System.Collections.Generic; using System.Reflection; using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBDateAddTranslator : IMethodCallTranslator { - public class IBDateAddTranslator : IMethodCallTranslator + static readonly Dictionary MethodInfoDatePartMapping = new Dictionary + { + { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddYears), new[] { typeof(int) }), "YEAR" }, + { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddMonths), new[] { typeof(int) }), "MONTH" }, + { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddDays), new[] { typeof(double) }), "DAY" }, + { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddHours), new[] { typeof(double) }), "HOUR" }, + { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddMinutes), new[] { typeof(double) }), "MINUTE" }, + { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddSeconds), new[] { typeof(double) }), "SECOND" }, + { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddMilliseconds), new[] { typeof(double) }), "MILLISECOND" }, + + { typeof(DateOnly).GetRuntimeMethod(nameof(DateOnly.AddYears), new[] { typeof(int) }), "YEAR" }, + { typeof(DateOnly).GetRuntimeMethod(nameof(DateOnly.AddMonths), new[] { typeof(int) }), "MONTH" }, + { typeof(DateOnly).GetRuntimeMethod(nameof(DateOnly.AddDays), new[] { typeof(int) }), "DAY" }, + { typeof(TimeOnly).GetRuntimeMethod(nameof(TimeOnly.AddHours), new[] { typeof(double) }), "HOUR" }, + { typeof(TimeOnly).GetRuntimeMethod(nameof(TimeOnly.AddMinutes), new[] { typeof(double) }), "MINUTE" }, + }; + + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + + public IBDateAddTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) { - static readonly Dictionary MethodInfoDatePartMapping = new Dictionary - { - { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddYears), new[] { typeof(int) }), "YEAR" }, - { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddMonths), new[] { typeof(int) }), "MONTH" }, - { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddDays), new[] { typeof(double) }), "DAY" }, - { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddHours), new[] { typeof(double) }), "HOUR" }, - { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddMinutes), new[] { typeof(double) }), "MINUTE" }, - { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddSeconds), new[] { typeof(double) }), "SECOND" }, - { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddMilliseconds), new[] { typeof(double) }), "MILLISECOND" }, - }; - - readonly IBSqlExpressionFactory _ibSqlExpressionFactory; - - public IBDateAddTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) - { - _ibSqlExpressionFactory = ibSqlExpressionFactory; - } - - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) - { - if (!MethodInfoDatePartMapping.TryGetValue(method, out var part)) - return null; - - return _ibSqlExpressionFactory.Function( - "EF_DATEADD", - new[] { _ibSqlExpressionFactory.Fragment(part), arguments[0], instance }, - instance.Type); - } + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } + + public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) + { + if (!MethodInfoDatePartMapping.TryGetValue(method, out var part)) + return null; + + return _ibSqlExpressionFactory.ApplyDefaultTypeMapping(_ibSqlExpressionFactory.Function( + "EF_DATEADD", + new[] { _ibSqlExpressionFactory.Fragment(part), _ibSqlExpressionFactory.ApplyDefaultTypeMapping(arguments[0]), instance }, + true, + new[] { false, true, true }, + instance.Type)); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateOnlyPartComponentTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateOnlyPartComponentTranslator.cs new file mode 100644 index 0000000..94c0a0c --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateOnlyPartComponentTranslator.cs @@ -0,0 +1,65 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt. + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * All Rights Reserved. + */ + +//$Authors = Jiri Cincura (jiri@cincura.net) + +using System; +using System.Collections.Generic; +using System.Reflection; +using InterBaseSql.EntityFrameworkCore.InterBase.Query.Expressions.Internal; +using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; + +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBDateOnlyPartComponentTranslator : IMemberTranslator +{ + const string YearDayPart = "YEARDAY"; + static readonly Dictionary MemberMapping = new Dictionary + { + { typeof(DateOnly).GetProperty(nameof(DateOnly.Year)), "YEAR" }, + { typeof(DateOnly).GetProperty(nameof(DateOnly.Month)), "MONTH" }, + { typeof(DateOnly).GetProperty(nameof(DateOnly.Day)), "DAY" }, + { typeof(DateOnly).GetProperty(nameof(DateOnly.DayOfYear)), YearDayPart }, + { typeof(DateOnly).GetProperty(nameof(DateOnly.DayOfWeek)), "WEEKDAY" }, + }; + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + + public IBDateOnlyPartComponentTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) + { + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } + + public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) + { + if (!MemberMapping.TryGetValue(member, out var part)) + return null; + + var result = (SqlExpression)_ibSqlExpressionFactory.SpacedFunction( + "EXTRACT", + new[] { _ibSqlExpressionFactory.Fragment(part), _ibSqlExpressionFactory.Fragment("FROM"), instance }, + true, + new[] { false, false, true }, + typeof(int)); + if (part == YearDayPart) + { + result = _ibSqlExpressionFactory.Add(result, _ibSqlExpressionFactory.Constant(1)); + } + return result; + } +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateTimeDateComponentTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateTimeDateComponentTranslator.cs index 6bd94b8..853348d 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateTimeDateComponentTranslator.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateTimeDateComponentTranslator.cs @@ -21,27 +21,33 @@ using System; using System.Reflection; using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBDateTimeDateComponentTranslator : IMemberTranslator { - public class IBDateTimeDateComponentTranslator : IMemberTranslator - { - readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; - public IBDateTimeDateComponentTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) - { - _ibSqlExpressionFactory = ibSqlExpressionFactory; - } + public IBDateTimeDateComponentTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) + { + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } - public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) + public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) + { + if (member.DeclaringType == typeof(DateTime) && member.Name == nameof(DateTime.Date)) { - if (member.DeclaringType == typeof(DateTime) && member.Name == nameof(DateTime.Date)) - { - return _ibSqlExpressionFactory.DateTimeDateMember(instance); - } - return null; + return _ibSqlExpressionFactory.SpacedFunction( + "CAST", + new[] { instance, _ibSqlExpressionFactory.Fragment("AS"), _ibSqlExpressionFactory.Fragment("DATE") }, + true, + new[] { true, false, false }, + typeof(DateTime)); } + return null; } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateTimeDatePartComponentTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateTimeDatePartComponentTranslator.cs deleted file mode 100644 index 4f144ad..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateTimeDatePartComponentTranslator.cs +++ /dev/null @@ -1,66 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using System; -using System.Collections.Generic; -using System.Reflection; -using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.SqlExpressions; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal -{ - public class IBDateTimeDatePartComponentTranslator : IMemberTranslator - { - const string YearDayPart = "YEARDAY"; - static readonly Dictionary MemberDatePartMapping = new Dictionary - { - { typeof(DateTime).GetProperty(nameof(DateTime.Year)), "YEAR" }, - { typeof(DateTime).GetProperty(nameof(DateTime.Month)), "MONTH" }, - { typeof(DateTime).GetProperty(nameof(DateTime.Day)), "DAY" }, - { typeof(DateTime).GetProperty(nameof(DateTime.Hour)), "HOUR" }, - { typeof(DateTime).GetProperty(nameof(DateTime.Minute)), "MINUTE" }, - { typeof(DateTime).GetProperty(nameof(DateTime.Second)), "SECOND" }, - { typeof(DateTime).GetProperty(nameof(DateTime.Millisecond)), "MILLISECOND" }, - { typeof(DateTime).GetProperty(nameof(DateTime.DayOfYear)), YearDayPart }, - { typeof(DateTime).GetProperty(nameof(DateTime.DayOfWeek)), "WEEKDAY" }, - }; - - readonly IBSqlExpressionFactory _ibSqlExpressionFactory; - - public IBDateTimeDatePartComponentTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) - { - _ibSqlExpressionFactory = ibSqlExpressionFactory; - } - - public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) - { - if (!MemberDatePartMapping.TryGetValue(member, out var part)) - return null; - - var result = (SqlExpression)_ibSqlExpressionFactory.Extract(part, instance); - if (part == YearDayPart) - { - result = _ibSqlExpressionFactory.Add(result, _ibSqlExpressionFactory.Constant(1)); - } - return result; - } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateTimeNowTodayTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateTimeNowTodayTranslator.cs index a4f2752..82f3a46 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateTimeNowTodayTranslator.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateTimeNowTodayTranslator.cs @@ -21,32 +21,33 @@ using System; using System.Reflection; using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBDateTimeNowTodayTranslator : IMemberTranslator { - public class IBDateTimeNowTodayTranslator : IMemberTranslator + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + + public IBDateTimeNowTodayTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) { - readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } - public IBDateTimeNowTodayTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) + public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) + { + if (member.DeclaringType == typeof(DateTime) && member.Name == nameof(DateTime.Now)) { - _ibSqlExpressionFactory = ibSqlExpressionFactory; + // CURRENT_TIMESTAMP + return _ibSqlExpressionFactory.ApplyDefaultTypeMapping(_ibSqlExpressionFactory.NiladicFunction("CURRENT_TIMESTAMP", false, typeof(DateTime))); } - - public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) + if (member.DeclaringType == typeof(DateTime) && member.Name == nameof(DateTime.Today)) { - if (member.DeclaringType == typeof(DateTime) && member.Name == nameof(DateTime.Now)) - { - // LOCALTIMESTAMP - return _ibSqlExpressionFactory.Function("CURRENT_TIMESTAMP", typeof(DateTime)); - } - if (member.DeclaringType == typeof(DateTime) && member.Name == nameof(DateTime.Today)) - { - return _ibSqlExpressionFactory.Function("CURRENT_DATE", typeof(DateTime)); - } - return null; + return _ibSqlExpressionFactory.ApplyDefaultTypeMapping(_ibSqlExpressionFactory.NiladicFunction("CURRENT_DATE", false, typeof(DateTime))); } + return null; } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateTimePartComponentTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateTimePartComponentTranslator.cs new file mode 100644 index 0000000..e1fbc41 --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBDateTimePartComponentTranslator.cs @@ -0,0 +1,75 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt. + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * All Rights Reserved. + */ + +//$Authors = Jiri Cincura (jiri@cincura.net) + +using System; +using System.Collections.Generic; +using System.Reflection; +using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; + +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBDateTimePartComponentTranslator : IMemberTranslator +{ + const string YearDayPart = "YEARDAY"; + const string SecondPart = "SECOND"; + const string MillisecondPart = "MILLISECOND"; + static readonly Dictionary MemberMapping = new Dictionary + { + { typeof(DateTime).GetProperty(nameof(DateTime.Year)), "YEAR" }, + { typeof(DateTime).GetProperty(nameof(DateTime.Month)), "MONTH" }, + { typeof(DateTime).GetProperty(nameof(DateTime.Day)), "DAY" }, + { typeof(DateTime).GetProperty(nameof(DateTime.Hour)), "HOUR" }, + { typeof(DateTime).GetProperty(nameof(DateTime.Minute)), "MINUTE" }, + { typeof(DateTime).GetProperty(nameof(DateTime.Second)), SecondPart }, + { typeof(DateTime).GetProperty(nameof(DateTime.Millisecond)), MillisecondPart }, + { typeof(DateTime).GetProperty(nameof(DateTime.DayOfYear)), YearDayPart }, + { typeof(DateTime).GetProperty(nameof(DateTime.DayOfWeek)), "WEEKDAY" }, + }; + + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + + public IBDateTimePartComponentTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) + { + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } + + public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) + { + if (!MemberMapping.TryGetValue(member, out var part)) + return null; + + var result = (SqlExpression)_ibSqlExpressionFactory.SpacedFunction( + "EXTRACT", + new[] { _ibSqlExpressionFactory.Fragment(part), _ibSqlExpressionFactory.Fragment("FROM"), instance }, + true, + new[] { false, false, true }, + typeof(int)); + if (part == YearDayPart) + { + result = _ibSqlExpressionFactory.Add(result, _ibSqlExpressionFactory.Constant(1)); + } + else if (part == SecondPart || part == MillisecondPart) + { + result = _ibSqlExpressionFactory.Function("TRUNC", new[] { result }, true, new[] { true }, typeof(int)); + } + return result; + } +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBEndsWithOptimizedTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBEndsWithOptimizedTranslator.cs deleted file mode 100644 index 3ad0823..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBEndsWithOptimizedTranslator.cs +++ /dev/null @@ -1,68 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using System.Collections.Generic; -using System.Reflection; -using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.SqlExpressions; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal -{ - class IBEndsWithOptimizedTranslator : IMethodCallTranslator - { - static readonly MethodInfo MethodInfo = typeof(string).GetRuntimeMethod(nameof(string.EndsWith), new[] { typeof(string) }); - - readonly IBSqlExpressionFactory _ibSqlExpressionFactory; - - public IBEndsWithOptimizedTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) - { - _ibSqlExpressionFactory = ibSqlExpressionFactory; - } - - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) - { - if (!method.Equals(MethodInfo)) - return null; - - var patternExpression = arguments[0]; - var endsWithExpression = _ibSqlExpressionFactory.Equal( - _ibSqlExpressionFactory.Function( - "RIGHT", - new[] { - instance, - _ibSqlExpressionFactory.Function( - "EF_LENGTH", - new[] { patternExpression }, - typeof(int)) }, - instance.Type), - patternExpression); - return patternExpression is SqlConstantExpression sqlConstantExpression - ? (string)sqlConstantExpression.Value == string.Empty - ? (SqlExpression)_ibSqlExpressionFactory.Constant(true) - : endsWithExpression - : _ibSqlExpressionFactory.OrElse( - endsWithExpression, - _ibSqlExpressionFactory.Equal( - patternExpression, - _ibSqlExpressionFactory.Constant(string.Empty))); - } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBMathTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBMathTranslator.cs index 674a8f9..afc5219 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBMathTranslator.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBMathTranslator.cs @@ -20,133 +20,143 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBMathTranslator : IMethodCallTranslator { - public class IBMathTranslator : IMethodCallTranslator + static readonly Dictionary SupportedMethodTranslations = new Dictionary { - static readonly Dictionary SupportedMethodTranslations = new Dictionary - { - { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(decimal) }), "EF_ABS" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(double) }), "EF_ABS" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(short) }), "EF_ABS" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(int) }), "EF_ABS" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(long) }), "EF_ABS" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(sbyte) }), "EF_ABS" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(float) }), "EF_ABS" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(decimal) }), "EF_ABS" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(double) }), "EF_ABS" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(short) }), "EF_ABS" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(int) }), "EF_ABS" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(long) }), "EF_ABS" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(sbyte) }), "EF_ABS" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(float) }), "EF_ABS" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Ceiling), new[] { typeof(double) }), "EF_CEILING" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Ceiling), new[] { typeof(decimal) }), "EF_CEILING" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Ceiling), new[] { typeof(double) }), "EF_CEILING" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Ceiling), new[] { typeof(decimal) }), "EF_CEILING" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Floor), new[] { typeof(double) }), "EF_FLOOR" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Floor), new[] { typeof(decimal) }), "EF_FLOOR" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Floor), new[] { typeof(double) }), "EF_FLOOR" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Floor), new[] { typeof(decimal) }), "EF_FLOOR" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Pow), new[] { typeof(double), typeof(double) }), "EF_POWER" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Pow), new[] { typeof(double), typeof(double) }), "EF_POWER" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Exp), new[] { typeof(double) }), "EF_EXP" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Exp), new[] { typeof(double) }), "EF_EXP" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Log10), new[] { typeof(double) }), "LOG10" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Log10), new[] { typeof(double) }), "LOG10" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Log), new[] { typeof(double) }), "LN" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Log), new[] { typeof(double), typeof(double) }), "LOG" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Log), new[] { typeof(double) }), "LN" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Log), new[] { typeof(double), typeof(double) }), "LOG" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Sqrt), new[] { typeof(double) }), "SQRT" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Sqrt), new[] { typeof(double) }), "SQRT" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Acos), new[] { typeof(double) }), "ACOS" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Acos), new[] { typeof(double) }), "ACOS" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Asin), new[] { typeof(double) }), "ASIN" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Asin), new[] { typeof(double) }), "ASIN" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Atan), new[] { typeof(double) }), "ATAN" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Atan), new[] { typeof(double) }), "ATAN" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Atan2), new[] { typeof(double), typeof(double) }), "ATAN2" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Atan2), new[] { typeof(double), typeof(double) }), "ATAN2" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Cos), new[] { typeof(double) }), "COS" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Cos), new[] { typeof(double) }), "COS" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Sin), new[] { typeof(double) }), "SIN" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Sin), new[] { typeof(double) }), "SIN" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Tan), new[] { typeof(double) }), "TAN" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Tan), new[] { typeof(double) }), "TAN" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(float) }), "SIGN" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(long) }), "SIGN" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(int) }), "SIGN" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(sbyte) }), "SIGN" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(double) }), "SIGN" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(decimal) }), "SIGN" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(short) }), "SIGN" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(float) }), "SIGN" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(long) }), "SIGN" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(int) }), "SIGN" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(sbyte) }), "SIGN" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(double) }), "SIGN" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(decimal) }), "SIGN" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(short) }), "SIGN" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(float), typeof(float) }), "MAXVALUE" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(sbyte), typeof(sbyte) }), "MAXVALUE" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(ulong), typeof(ulong) }), "MAXVALUE" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(uint), typeof(uint) }), "MAXVALUE" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(long), typeof(long) }), "MAXVALUE" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(ushort), typeof(ushort) }), "MAXVALUE" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(short), typeof(short) }), "MAXVALUE" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(double), typeof(double) }), "MAXVALUE" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(decimal), typeof(decimal) }), "MAXVALUE" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(byte), typeof(byte) }), "MAXVALUE" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(int), typeof(int) }), "MAXVALUE" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(float), typeof(float) }), "MAXVALUE" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(sbyte), typeof(sbyte) }), "MAXVALUE" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(ulong), typeof(ulong) }), "MAXVALUE" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(uint), typeof(uint) }), "MAXVALUE" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(long), typeof(long) }), "MAXVALUE" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(ushort), typeof(ushort) }), "MAXVALUE" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(short), typeof(short) }), "MAXVALUE" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(double), typeof(double) }), "MAXVALUE" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(decimal), typeof(decimal) }), "MAXVALUE" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(byte), typeof(byte) }), "MAXVALUE" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(int), typeof(int) }), "MAXVALUE" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(float), typeof(float) }), "MINVALUE" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(sbyte), typeof(sbyte) }), "MINVALUE" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(ulong), typeof(ulong) }), "MINVALUE" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(uint), typeof(uint) }), "MINVALUE" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(long), typeof(long) }), "MINVALUE" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(ushort), typeof(ushort) }), "MINVALUE" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(short), typeof(short) }), "MINVALUE" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(double), typeof(double) }), "MINVALUE" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(decimal), typeof(decimal) }), "MINVALUE" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(byte), typeof(byte) }), "MINVALUE" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(int), typeof(int) }), "MINVALUE" }, - }; + { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(float), typeof(float) }), "MINVALUE" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(sbyte), typeof(sbyte) }), "MINVALUE" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(ulong), typeof(ulong) }), "MINVALUE" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(uint), typeof(uint) }), "MINVALUE" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(long), typeof(long) }), "MINVALUE" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(ushort), typeof(ushort) }), "MINVALUE" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(short), typeof(short) }), "MINVALUE" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(double), typeof(double) }), "MINVALUE" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(decimal), typeof(decimal) }), "MINVALUE" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(byte), typeof(byte) }), "MINVALUE" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(int), typeof(int) }), "MINVALUE" }, + }; - static readonly HashSet TruncateMethodInfos = new HashSet - { - typeof(Math).GetRuntimeMethod(nameof(Math.Truncate), new[] { typeof(decimal) }), - typeof(Math).GetRuntimeMethod(nameof(Math.Truncate), new[] { typeof(double) }) - }; + static readonly HashSet TruncateMethodInfos = new HashSet + { + typeof(Math).GetRuntimeMethod(nameof(Math.Truncate), new[] { typeof(decimal) }), + typeof(Math).GetRuntimeMethod(nameof(Math.Truncate), new[] { typeof(double) }) + }; - static readonly HashSet RoundMethodInfos = new HashSet - { - typeof(Math).GetRuntimeMethod(nameof(Math.Round), new[] { typeof(decimal) }), - typeof(Math).GetRuntimeMethod(nameof(Math.Round), new[] { typeof(double) }), - typeof(Math).GetRuntimeMethod(nameof(Math.Round), new[] { typeof(decimal), typeof(int) }), - typeof(Math).GetRuntimeMethod(nameof(Math.Round), new[] { typeof(double), typeof(int) }) - }; + static readonly HashSet RoundMethodInfos = new HashSet + { + typeof(Math).GetRuntimeMethod(nameof(Math.Round), new[] { typeof(decimal) }), + typeof(Math).GetRuntimeMethod(nameof(Math.Round), new[] { typeof(double) }), + typeof(Math).GetRuntimeMethod(nameof(Math.Round), new[] { typeof(decimal), typeof(int) }), + typeof(Math).GetRuntimeMethod(nameof(Math.Round), new[] { typeof(double), typeof(int) }) + }; - readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; - public IBMathTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) + public IBMathTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) + { + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } + + public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) + { + if (SupportedMethodTranslations.TryGetValue(method, out var sqlFunctionName)) { - _ibSqlExpressionFactory = ibSqlExpressionFactory; + return _ibSqlExpressionFactory.Function(sqlFunctionName, arguments, true, arguments.Select(_ => true), method.ReturnType); } - - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) + if (TruncateMethodInfos.Contains(method)) + { + return _ibSqlExpressionFactory.ApplyDefaultTypeMapping(_ibSqlExpressionFactory.Function( + "TRUNC", + new[] { _ibSqlExpressionFactory.ApplyDefaultTypeMapping(arguments[0]), _ibSqlExpressionFactory.Constant(0) }, + true, + new[] { true, false }, + method.ReturnType)); + } + if (RoundMethodInfos.Contains(method)) { - if (SupportedMethodTranslations.TryGetValue(method, out var sqlFunctionName)) - { - return _ibSqlExpressionFactory.Function(sqlFunctionName, arguments, method.ReturnType); - } - if (TruncateMethodInfos.Contains(method)) - { - return _ibSqlExpressionFactory.Function( - "TRUNC", - new[] { arguments[0], _ibSqlExpressionFactory.Constant(0) }, - method.ReturnType); - } - if (RoundMethodInfos.Contains(method)) - { - return _ibSqlExpressionFactory.Function( - "EF_ROUND", - arguments.Count == 1 - ? new[] { arguments[0], _ibSqlExpressionFactory.Constant(0) } - : new[] { arguments[0], arguments[1] }, - method.ReturnType); - } - return null; + var roundArguments = arguments.Count == 1 + ? new[] { _ibSqlExpressionFactory.ApplyDefaultTypeMapping(arguments[0]), _ibSqlExpressionFactory.Constant(0) } + : new[] { _ibSqlExpressionFactory.ApplyDefaultTypeMapping(arguments[0]), _ibSqlExpressionFactory.ApplyDefaultTypeMapping(arguments[1]) }; + var nullability = arguments.Count == 1 + ? new[] { true, false } + : new[] { true, true }; + return _ibSqlExpressionFactory.ApplyDefaultTypeMapping(_ibSqlExpressionFactory.Function( + "EF_ROUND", + roundArguments, + true, + nullability, + method.ReturnType)); } + return null; } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBMemberTranslatorProvider.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBMemberTranslatorProvider.cs index f8b2181..a3b9b34 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBMemberTranslatorProvider.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBMemberTranslatorProvider.cs @@ -24,16 +24,15 @@ using InterBaseSql.EntityFrameworkCore.InterBase.Utilities; using Microsoft.EntityFrameworkCore.Query; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBMemberTranslatorProvider : RelationalMemberTranslatorProvider { - public class IBMemberTranslatorProvider : RelationalMemberTranslatorProvider - { - static readonly List Translators = TranslatorsHelper.GetTranslators().ToList(); + static readonly List Translators = TranslatorsHelper.GetTranslators().ToList(); - public IBMemberTranslatorProvider(RelationalMemberTranslatorProviderDependencies dependencies) - : base(dependencies) - { - AddTranslators(Translators.Select(t => (IMemberTranslator)Activator.CreateInstance(t, dependencies.SqlExpressionFactory))); - } + public IBMemberTranslatorProvider(RelationalMemberTranslatorProviderDependencies dependencies) + : base(dependencies) + { + AddTranslators(Translators.Select(t => (IMemberTranslator)Activator.CreateInstance(t, dependencies.SqlExpressionFactory))); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBMethodCallTranslatorProvider.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBMethodCallTranslatorProvider.cs index 997608d..680b3e4 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBMethodCallTranslatorProvider.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBMethodCallTranslatorProvider.cs @@ -24,16 +24,15 @@ using InterBaseSql.EntityFrameworkCore.InterBase.Utilities; using Microsoft.EntityFrameworkCore.Query; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBMethodCallTranslatorProvider : RelationalMethodCallTranslatorProvider { - public class IBMethodCallTranslatorProvider : RelationalMethodCallTranslatorProvider - { - static readonly List Translators = TranslatorsHelper.GetTranslators().ToList(); + static readonly List Translators = TranslatorsHelper.GetTranslators().ToList(); - public IBMethodCallTranslatorProvider(RelationalMethodCallTranslatorProviderDependencies dependencies) - : base(dependencies) - { - AddTranslators(Translators.Select(t => (IMethodCallTranslator)Activator.CreateInstance(t, dependencies.SqlExpressionFactory))); - } + public IBMethodCallTranslatorProvider(RelationalMethodCallTranslatorProviderDependencies dependencies) + : base(dependencies) + { + AddTranslators(Translators.Select(t => (IMethodCallTranslator)Activator.CreateInstance(t, dependencies.SqlExpressionFactory))); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBNewGuidTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBNewGuidTranslator.cs index ae1f8ca..ab11660 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBNewGuidTranslator.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBNewGuidTranslator.cs @@ -22,27 +22,28 @@ using System.Collections.Generic; using System.Reflection; using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBNewGuidTranslator : IMethodCallTranslator { - public class IBNewGuidTranslator : IMethodCallTranslator - { - readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; - public IBNewGuidTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) - { - _ibSqlExpressionFactory = ibSqlExpressionFactory; - } + public IBNewGuidTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) + { + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) + public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) + { + if (method.DeclaringType == typeof(Guid) && method.Name == nameof(Guid.NewGuid)) { - if (method.DeclaringType == typeof(Guid) && method.Name == nameof(Guid.NewGuid)) - { - return _ibSqlExpressionFactory.Function("EF_NEWGUID", new[] { instance }, typeof(Guid)); - } - return null; + return _ibSqlExpressionFactory.Function("EF_NEWGUID", Array.Empty(), false, Array.Empty(), typeof(Guid)); } + return null; } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBObjectToStringTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBObjectToStringTranslator.cs index 5539dcb..4a3462f 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBObjectToStringTranslator.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBObjectToStringTranslator.cs @@ -22,41 +22,47 @@ using System.Collections.Generic; using System.Reflection; using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBObjectToStringTranslator : IMethodCallTranslator { - public class IBObjectToStringTranslator : IMethodCallTranslator + static readonly HashSet SupportedTypes = new HashSet { - static readonly HashSet SupportedTypes = new HashSet - { - typeof(int), - typeof(long), - typeof(DateTime), - typeof(bool), - typeof(byte), - typeof(byte[]), - typeof(double), - typeof(char), - typeof(short), - typeof(float), - typeof(decimal), - typeof(TimeSpan), - typeof(uint), - typeof(ushort), - typeof(ulong), - typeof(sbyte), - }; + typeof(int), + typeof(long), + typeof(DateTime), + typeof(bool), + typeof(byte), + typeof(byte[]), + typeof(double), + typeof(char), + typeof(short), + typeof(float), + typeof(decimal), + typeof(TimeSpan), + typeof(uint), + typeof(ushort), + typeof(ulong), + typeof(sbyte), + typeof(DateOnly), + typeof(TimeOnly), + }; - readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; - public IBObjectToStringTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) - { - _ibSqlExpressionFactory = ibSqlExpressionFactory; - } + public IBObjectToStringTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) + { + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) + public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) + { + if (method.Name == nameof(ToString) && method.GetParameters().Length == 0) { if (method.Name == nameof(ToString) && method.GetParameters().Length == 0) { @@ -67,10 +73,10 @@ public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadO } else if (type == typeof(Guid)) { - return _ibSqlExpressionFactory.Function("EF_UUID_TO_CHAR", new[] { instance }, typeof(string)); + return _ibSqlExpressionFactory.Function("EF_UUID_TO_CHAR", new[] { instance }, true, new[] { true }, typeof(string)); } } - return null; } + return null; } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStartsWithOptimizedTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStartsWithOptimizedTranslator.cs deleted file mode 100644 index 827b39e..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStartsWithOptimizedTranslator.cs +++ /dev/null @@ -1,73 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using System.Collections.Generic; -using System.Reflection; -using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.SqlExpressions; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal -{ - public class IBStartsWithOptimizedTranslator : IMethodCallTranslator - { - static readonly MethodInfo StartsWithMethod = typeof(string).GetRuntimeMethod(nameof(string.StartsWith), new[] { typeof(string) }); - - readonly IBSqlExpressionFactory _ibSqlExpressionFactory; - - public IBStartsWithOptimizedTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) - { - _ibSqlExpressionFactory = ibSqlExpressionFactory; - } - - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) - { - if (!method.Equals(StartsWithMethod)) - return null; - - var patternExpression = arguments[0]; - - var startsWithExpression = _ibSqlExpressionFactory.AndAlso( - _ibSqlExpressionFactory.Like( - instance, - _ibSqlExpressionFactory.Add(patternExpression, _ibSqlExpressionFactory.Constant("%"))), - _ibSqlExpressionFactory.Equal( - _ibSqlExpressionFactory.Function( - "LEFT", - new[] { - instance, - _ibSqlExpressionFactory.Function( - "EF_LENGTH", - new[] { patternExpression }, - typeof(int)) }, - instance.Type), - patternExpression)); - return patternExpression is SqlConstantExpression sqlConstantExpression - ? (string)sqlConstantExpression.Value == string.Empty - ? (SqlExpression)_ibSqlExpressionFactory.Constant(true) - : startsWithExpression - : _ibSqlExpressionFactory.OrElse( - startsWithExpression, - _ibSqlExpressionFactory.Equal( - patternExpression, - _ibSqlExpressionFactory.Constant(string.Empty))); - } - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringContainsTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringContainsTranslator.cs new file mode 100644 index 0000000..e891198 --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringContainsTranslator.cs @@ -0,0 +1,62 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt. + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * All Rights Reserved. + */ + +//$Authors = Jiri Cincura (jiri@cincura.net) + +using System.Collections.Generic; +using System.Reflection; +using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; + +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBStringContainsTranslator : IMethodCallTranslator +{ + static readonly MethodInfo MethodInfo = typeof(string).GetRuntimeMethod(nameof(string.Contains), new[] { typeof(string) }); + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + + public IBStringContainsTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) + { + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } + + public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) + { + if (!method.Equals(MethodInfo)) + return null; + + var patternExpression = _ibSqlExpressionFactory.ApplyDefaultTypeMapping(arguments[0]); + var positionExpression = _ibSqlExpressionFactory.GreaterThan( + _ibSqlExpressionFactory.Function( + "POSITION", + new[] { patternExpression, instance }, + true, + new[] { true, true }, + typeof(int)), + _ibSqlExpressionFactory.Constant(0)); + return patternExpression is SqlConstantExpression sqlConstantExpression + ? ((string)sqlConstantExpression.Value)?.Length == 0 + ? (SqlExpression)_ibSqlExpressionFactory.Constant(true) + : positionExpression + : _ibSqlExpressionFactory.OrElse( + positionExpression, + _ibSqlExpressionFactory.Equal( + patternExpression, + _ibSqlExpressionFactory.Constant(string.Empty))); + } +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringEndsWithTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringEndsWithTranslator.cs new file mode 100644 index 0000000..710fb62 --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringEndsWithTranslator.cs @@ -0,0 +1,69 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt. + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * All Rights Reserved. + */ + +//$Authors = Jiri Cincura (jiri@cincura.net) + +using System.Collections.Generic; +using System.Reflection; +using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; + +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +class IBStringEndsWithTranslator : IMethodCallTranslator +{ + static readonly MethodInfo MethodInfo = typeof(string).GetRuntimeMethod(nameof(string.EndsWith), new[] { typeof(string) }); + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + + public IBStringEndsWithTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) + { + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } + + public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) + { + if (!method.Equals(MethodInfo)) + return null; + + var patternExpression = _ibSqlExpressionFactory.ApplyDefaultTypeMapping(arguments[0]); + var endsWithExpression = _ibSqlExpressionFactory.Equal( + _ibSqlExpressionFactory.ApplyDefaultTypeMapping(_ibSqlExpressionFactory.Function( + "RIGHT", + new[] { + instance, + _ibSqlExpressionFactory.Function( + "CHAR_LENGTH", + new[] { patternExpression }, + true, + new[] { true }, + typeof(int)) }, + true, + new[] { true, true }, + instance.Type)), + patternExpression); + return patternExpression is SqlConstantExpression sqlConstantExpression + ? (string)sqlConstantExpression.Value == string.Empty + ? (SqlExpression)_ibSqlExpressionFactory.Constant(true) + : endsWithExpression + : _ibSqlExpressionFactory.OrElse( + endsWithExpression, + _ibSqlExpressionFactory.Equal( + patternExpression, + _ibSqlExpressionFactory.Constant(string.Empty))); + } +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringFirstOrDefaultTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringFirstOrDefaultTranslator.cs new file mode 100644 index 0000000..21dde1e --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringFirstOrDefaultTranslator.cs @@ -0,0 +1,54 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt. + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * All Rights Reserved. + */ + +//$Authors = Jiri Cincura (jiri@cincura.net) + +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; + +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBStringFirstOrDefaultTranslator : IMethodCallTranslator +{ + static readonly MethodInfo MethodInfo = typeof(Enumerable).GetRuntimeMethods() + .Single(m => m.Name == nameof(Enumerable.FirstOrDefault) && m.GetParameters().Length == 1) + .MakeGenericMethod(typeof(char)); + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + + public IBStringFirstOrDefaultTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) + { + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } + + public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) + { + if (!method.Equals(MethodInfo)) + return null; + + var argument = _ibSqlExpressionFactory.ApplyDefaultTypeMapping(arguments[0]); + return _ibSqlExpressionFactory.Function( + "LEFT", + new[] { argument, _ibSqlExpressionFactory.Constant(1) }, + true, + new[] { true, false }, + typeof(string)); + } +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringIndexOfTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringIndexOfTranslator.cs index c4777af..9814ac7 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringIndexOfTranslator.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringIndexOfTranslator.cs @@ -22,29 +22,37 @@ using System.Linq; using System.Reflection; using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBStringIndexOfTranslator : IMethodCallTranslator { - public class IBStringIndexOfTranslator : IMethodCallTranslator - { - readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; - public IBStringIndexOfTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) - { - _ibSqlExpressionFactory = ibSqlExpressionFactory; - } + public IBStringIndexOfTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) + { + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) + public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) + { + if (method.DeclaringType == typeof(string) && method.Name == nameof(string.IndexOf)) { - if (method.DeclaringType == typeof(string) && method.Name == nameof(string.IndexOf)) + var args = new List(); + args.Add(_ibSqlExpressionFactory.ApplyDefaultTypeMapping(arguments[0])); + args.Add(instance); + foreach (var a in arguments.Skip(1)) { - return _ibSqlExpressionFactory.Subtract( - _ibSqlExpressionFactory.Function("EF_POSITION", new[] { arguments[0], instance }.Concat(arguments.Skip(1)), typeof(int)), - _ibSqlExpressionFactory.Constant(1)); + args.Add(_ibSqlExpressionFactory.ApplyDefaultTypeMapping(a)); } - return null; + return _ibSqlExpressionFactory.Subtract( + _ibSqlExpressionFactory.Function("EF_POSITION", args, true, Enumerable.Repeat(true, args.Count), typeof(int)), + _ibSqlExpressionFactory.Constant(1)); } + return null; } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringIsNullOrWhiteSpaceTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringIsNullOrWhiteSpaceTranslator.cs index 499ba94..9d3d0d5 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringIsNullOrWhiteSpaceTranslator.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringIsNullOrWhiteSpaceTranslator.cs @@ -21,34 +21,35 @@ using System.Collections.Generic; using System.Reflection; using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBStringIsNullOrWhiteSpaceTranslator : IMethodCallTranslator { - public class IBStringIsNullOrWhiteSpaceTranslator : IMethodCallTranslator + static readonly MethodInfo IsNullOrWhiteSpaceMethod = typeof(string).GetRuntimeMethod(nameof(string.IsNullOrWhiteSpace), new[] { typeof(string) }); + + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + + public IBStringIsNullOrWhiteSpaceTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) { - static readonly MethodInfo IsNullOrWhiteSpaceMethod = typeof(string).GetRuntimeMethod(nameof(string.IsNullOrWhiteSpace), new[] { typeof(string) }); - - readonly IBSqlExpressionFactory _ibSqlExpressionFactory; - - public IBStringIsNullOrWhiteSpaceTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) - { - _ibSqlExpressionFactory = ibSqlExpressionFactory; - } - - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) - { - if (!method.Equals(IsNullOrWhiteSpaceMethod)) - return null; - - var argument = arguments[0]; - return _ibSqlExpressionFactory.OrElse( - _ibSqlExpressionFactory.IsNull(argument), - _ibSqlExpressionFactory.Equal( - _ibSqlExpressionFactory.Function("EF_TRIM", new[] { argument }, typeof(string)), - _ibSqlExpressionFactory.Constant(string.Empty)) - ); - } + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } + + public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) + { + if (!method.Equals(IsNullOrWhiteSpaceMethod)) + return null; + + var argument = _ibSqlExpressionFactory.ApplyDefaultTypeMapping(arguments[0]); + return _ibSqlExpressionFactory.OrElse( + _ibSqlExpressionFactory.IsNull(argument), + _ibSqlExpressionFactory.Equal( + _ibSqlExpressionFactory.Function("EF_TRIM", new[] { argument }, true, new[] { true }, typeof(string)), + _ibSqlExpressionFactory.Constant(string.Empty)) + ); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringLastOrDefaultTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringLastOrDefaultTranslator.cs new file mode 100644 index 0000000..9b664fe --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringLastOrDefaultTranslator.cs @@ -0,0 +1,54 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt. + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * All Rights Reserved. + */ + +//$Authors = Jiri Cincura (jiri@cincura.net) + +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; + +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBStringLastOrDefaultTranslator : IMethodCallTranslator +{ + static readonly MethodInfo MethodInfo = typeof(Enumerable).GetRuntimeMethods() + .Single(m => m.Name == nameof(Enumerable.LastOrDefault) && m.GetParameters().Length == 1) + .MakeGenericMethod(typeof(char)); + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + + public IBStringLastOrDefaultTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) + { + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } + + public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) + { + if (!method.Equals(MethodInfo)) + return null; + + var argument = _ibSqlExpressionFactory.ApplyDefaultTypeMapping(arguments[0]); + return _ibSqlExpressionFactory.Function( + "RIGHT", + new[] { argument, _ibSqlExpressionFactory.Constant(1) }, + true, + new[] { true, false }, + typeof(string)); + } +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringLengthTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringLengthTranslator.cs index 645b730..8736dfd 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringLengthTranslator.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringLengthTranslator.cs @@ -21,27 +21,28 @@ using System; using System.Reflection; using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBStringLengthTranslator : IMemberTranslator { - public class IBStringLengthTranslator : IMemberTranslator - { - readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; - public IBStringLengthTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) - { - _ibSqlExpressionFactory = ibSqlExpressionFactory; - } + public IBStringLengthTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) + { + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } - public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) + public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) + { + if (member.DeclaringType == typeof(string) && member.Name == nameof(string.Length)) { - if (member.DeclaringType == typeof(string) && member.Name == nameof(string.Length)) - { - return _ibSqlExpressionFactory.Function("EF_LENGTH", new[] { instance }, typeof(int)); - } - return null; + return _ibSqlExpressionFactory.Function("EF_LENGTH", new[] { instance }, true, new[] { true }, typeof(int)); } + return null; } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringReplaceTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringReplaceTranslator.cs index 157dc2d..efe57cd 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringReplaceTranslator.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringReplaceTranslator.cs @@ -22,28 +22,36 @@ using System.Linq; using System.Reflection; using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBStringReplaceTranslator : IMethodCallTranslator { - public class IBStringReplaceTranslator : IMethodCallTranslator - { - static readonly MethodInfo ReplaceMethod = typeof(string).GetRuntimeMethod(nameof(string.Replace), new[] { typeof(string), typeof(string) }); + static readonly MethodInfo ReplaceMethod = typeof(string).GetRuntimeMethod(nameof(string.Replace), new[] { typeof(string), typeof(string) }); - readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; - public IBStringReplaceTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) - { - _ibSqlExpressionFactory = ibSqlExpressionFactory; - } + public IBStringReplaceTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) + { + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) - { - if (!method.Equals(ReplaceMethod)) - return null; + public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) + { + if (!method.Equals(ReplaceMethod)) + return null; - return _ibSqlExpressionFactory.Function("EF_REPLACE", new[] { instance }.Concat(arguments), instance.Type); + var args = new List(); + args.Add(instance); + foreach (var a in arguments) + { + args.Add(_ibSqlExpressionFactory.ApplyDefaultTypeMapping(a)); } + return _ibSqlExpressionFactory.ApplyDefaultTypeMapping( + _ibSqlExpressionFactory.Function("EF_REPLACE", args, true, Enumerable.Repeat(true, args.Count), instance.Type)); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringStartsWithTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringStartsWithTranslator.cs new file mode 100644 index 0000000..598f6d8 --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringStartsWithTranslator.cs @@ -0,0 +1,77 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt. + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * All Rights Reserved. + */ + +//$Authors = Jiri Cincura (jiri@cincura.net) + +using System.Collections.Generic; +using System.Reflection; +using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; + +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class FbStringStartsWithTranslator : IMethodCallTranslator +{ + static readonly MethodInfo StartsWithMethod = typeof(string).GetRuntimeMethod(nameof(string.StartsWith), new[] { typeof(string) }); + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + + public FbStringStartsWithTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) + { + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } + + public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) + { + if (!method.Equals(StartsWithMethod)) + return null; + + var patternExpression = _ibSqlExpressionFactory.ApplyDefaultTypeMapping(arguments[0]); + var patternConstantExpression = patternExpression as SqlConstantExpression; + var likePatternExpression = patternConstantExpression != null + ? (SqlExpression)_ibSqlExpressionFactory.Constant(((string)patternConstantExpression.Value) + "%") + : (SqlExpression)_ibSqlExpressionFactory.Add(patternExpression, _ibSqlExpressionFactory.Constant("%")); + var startsWithExpression = _ibSqlExpressionFactory.AndAlso( + _ibSqlExpressionFactory.Like( + instance, + likePatternExpression), + _ibSqlExpressionFactory.Equal( + _ibSqlExpressionFactory.ApplyDefaultTypeMapping(_ibSqlExpressionFactory.Function( + "LEFT", + new[] { + instance, + _ibSqlExpressionFactory.Function( + "CHAR_LENGTH", + new[] { patternExpression }, + true, + new[] { true }, + typeof(int)) }, + true, + new[] { true, true }, + instance.Type)), + patternExpression)); + return patternConstantExpression != null + ? (string)patternConstantExpression.Value == string.Empty + ? _ibSqlExpressionFactory.Constant(true) + : startsWithExpression + : _ibSqlExpressionFactory.OrElse( + startsWithExpression, + _ibSqlExpressionFactory.Equal( + patternExpression, + _ibSqlExpressionFactory.Constant(string.Empty))); + } +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringSubstringTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringSubstringTranslator.cs index 56b8923..7636ecd 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringSubstringTranslator.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringSubstringTranslator.cs @@ -21,6 +21,8 @@ using System.Collections.Generic; using System.Reflection; using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; @@ -38,14 +40,25 @@ public IBStringSubstringTranslator(IBSqlExpressionFactory ibSqlExpressionFactory _ibSqlExpressionFactory = ibSqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) + public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) { if (!(method.Equals(SubstringOnlyStartMethod) || method.Equals(SubstringStartAndLengthMethod))) return null; - var fromExpression = _ibSqlExpressionFactory.Add(arguments[0], _ibSqlExpressionFactory.Constant(1)); - var forExpression = arguments.Count == 2 ? arguments[1] : null; - return _ibSqlExpressionFactory.Substring(instance, fromExpression, forExpression); + var fromExpression = _ibSqlExpressionFactory.ApplyDefaultTypeMapping(_ibSqlExpressionFactory.Add(arguments[0], _ibSqlExpressionFactory.Constant(1))); + var forExpression = arguments.Count == 2 ? _ibSqlExpressionFactory.ApplyDefaultTypeMapping(arguments[1]) : null; + var substringArguments = forExpression != null + ? new[] { instance, _ibSqlExpressionFactory.Fragment("FROM"), fromExpression, _ibSqlExpressionFactory.Fragment("FOR"), forExpression } + : new[] { instance, _ibSqlExpressionFactory.Fragment("FROM"), fromExpression }; + var nullability = forExpression != null + ? new[] { true, false, true, false, true } + : new[] { true, false, true }; + return _ibSqlExpressionFactory.SpacedFunction( + "EF_SUBSTR", + substringArguments, + true, + nullability, + typeof(string)); } } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringToLowerTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringToLowerTranslator.cs index 2893f0e..1c84b1c 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringToLowerTranslator.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringToLowerTranslator.cs @@ -21,27 +21,28 @@ using System.Collections.Generic; using System.Reflection; using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBStringToLowerTranslator : IMethodCallTranslator { - public class IBStringToLowerTranslator : IMethodCallTranslator - { - readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; - public IBStringToLowerTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) - { - _ibSqlExpressionFactory = ibSqlExpressionFactory; - } + public IBStringToLowerTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) + { + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) + public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) + { + if (method.DeclaringType == typeof(string) && method.Name == nameof(string.ToLower)) { - if (method.DeclaringType == typeof(string) && method.Name == nameof(string.ToLower)) - { - return _ibSqlExpressionFactory.Function("EF_LOWER", new[] { instance }, typeof(string)); - } - return null; + return _ibSqlExpressionFactory.Function("EF_LOWER", new[] { instance }, true, new[] { true }, typeof(string)); } + return null; } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringToUpperTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringToUpperTranslator.cs index 3a83d75..ac8a58d 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringToUpperTranslator.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringToUpperTranslator.cs @@ -21,27 +21,28 @@ using System.Collections.Generic; using System.Reflection; using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBStringToUpperTranslator : IMethodCallTranslator { - public class IBStringToUpperTranslator : IMethodCallTranslator - { - readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; - public IBStringToUpperTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) - { - _ibSqlExpressionFactory = ibSqlExpressionFactory; - } + public IBStringToUpperTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) + { + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) + public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) + { + if (method.DeclaringType == typeof(string) && method.Name == nameof(string.ToUpper)) { - if (method.DeclaringType == typeof(string) && method.Name == nameof(string.ToUpper)) - { - return _ibSqlExpressionFactory.Function("UPPER", new[] { instance }, typeof(string)); - } - return null; + return _ibSqlExpressionFactory.Function("UPPER", new[] { instance }, true, new[] { true }, typeof(string)); } + return null; } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringTrimTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringTrimTranslator.cs index 5f4c151..b29a3ba 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringTrimTranslator.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBStringTrimTranslator.cs @@ -22,10 +22,12 @@ using System.Collections.Generic; using System.Reflection; using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internall { public class IBStringTrimTranslator : IMethodCallTranslator { @@ -43,33 +45,60 @@ public IBStringTrimTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) _ibSqlExpressionFactory = ibSqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) + public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) + { + if (!TryGetTrimDefinition(instance, method, arguments, out var trimArguments, out var nullability)) + { + return null; + } + return _ibSqlExpressionFactory.SpacedFunction( + "EF_TRIM", + trimArguments, + true, + nullability, + typeof(string)); + } + bool TryGetTrimDefinition(SqlExpression instance, MethodInfo method, IReadOnlyList arguments, out IEnumerable trimArguments, out IEnumerable nullability) { if (method.Equals(TrimWithoutArgsMethod)) { - return _ibSqlExpressionFactory.Trim("'BOTH'", null, instance); + trimArguments = new[] { _ibSqlExpressionFactory.Fragment("BOTH"), _ibSqlExpressionFactory.Fragment("FROM"), instance }; + nullability = new[] { false, false, true }; + return true; } if (method.Equals(TrimWithCharArgMethod)) { - return _ibSqlExpressionFactory.Trim("'BOTH'", arguments[0], instance); + trimArguments = new[] { _ibSqlExpressionFactory.Fragment("BOTH"), _ibSqlExpressionFactory.ApplyDefaultTypeMapping(arguments[0]), _ibSqlExpressionFactory.Fragment("FROM"), instance }; + nullability = new[] { false, true, false, true }; + return true; } if (method.Equals(TrimEndWithoutArgsMethod)) { - return _ibSqlExpressionFactory.Trim("'TRAILING'", null, instance); + trimArguments = new[] { _ibSqlExpressionFactory.Fragment("TRAILING"), _ibSqlExpressionFactory.Fragment("FROM"), instance }; + nullability = new[] { false, false, true }; + return true; } if (method.Equals(TrimEndWithCharArgMethod)) { - return _ibSqlExpressionFactory.Trim("'TRAILING'", arguments[0], instance); + trimArguments = new[] { _ibSqlExpressionFactory.Fragment("TRAILING"), _ibSqlExpressionFactory.ApplyDefaultTypeMapping(arguments[0]), _ibSqlExpressionFactory.Fragment("FROM"), instance }; + nullability = new[] { false, true, false, true }; + return true; } if (method.Equals(TrimStartWithoutArgsMethod)) { - return _ibSqlExpressionFactory.Trim("'LEADING'", null, instance); + trimArguments = new[] { _ibSqlExpressionFactory.Fragment("LEADING"), _ibSqlExpressionFactory.Fragment("FROM"), instance }; + nullability = new[] { false, false, true }; + return true; } if (method.Equals(TrimStartWithCharArgMethod)) { - return _ibSqlExpressionFactory.Trim("'LEADING'", arguments[0], instance); + trimArguments = new[] { _ibSqlExpressionFactory.Fragment("LEADING"), _ibSqlExpressionFactory.ApplyDefaultTypeMapping(arguments[0]), _ibSqlExpressionFactory.Fragment("FROM"), instance }; + nullability = new[] { false, true, false, true }; + return true; } - return null; + trimArguments = default; + nullability = default; + return false; } } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBTimeOnlyPartComponentTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBTimeOnlyPartComponentTranslator.cs new file mode 100644 index 0000000..5066de4 --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBTimeOnlyPartComponentTranslator.cs @@ -0,0 +1,65 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt. + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * All Rights Reserved. + */ + +//$Authors = Jiri Cincura (jiri@cincura.net) + +using System; +using System.Collections.Generic; +using System.Reflection; +using InterBaseSql.EntityFrameworkCore.InterBase.Query.Expressions.Internal; +using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; + +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBTimeOnlyPartComponentTranslator : IMemberTranslator +{ + const string SecondPart = "SECOND"; + const string MillisecondPart = "MILLISECOND"; + private static readonly Dictionary MemberMapping = new Dictionary + { + { typeof(TimeOnly).GetProperty(nameof(TimeOnly.Hour)), "HOUR" }, + { typeof(TimeOnly).GetProperty(nameof(TimeOnly.Minute)), "MINUTE" }, + { typeof(TimeOnly).GetProperty(nameof(TimeOnly.Second)), SecondPart }, + { typeof(TimeOnly).GetProperty(nameof(TimeOnly.Millisecond)), MillisecondPart }, + }; + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + + public IBTimeOnlyPartComponentTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) + { + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } + + public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) + { + if (!MemberMapping.TryGetValue(member, out var part)) + return null; + + var result = (SqlExpression)_ibSqlExpressionFactory.SpacedFunction( + "EXTRACT", + new[] { _ibSqlExpressionFactory.Fragment(part), _ibSqlExpressionFactory.Fragment("FROM"), instance }, + true, + new[] { false, false, true }, + typeof(int)); + if (part == SecondPart || part == MillisecondPart) + { + result = _ibSqlExpressionFactory.Function("TRUNC", new[] { result }, true, new[] { true }, typeof(int)); + } + return result; + } +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBTimeSpanPartComponentTranslator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBTimeSpanPartComponentTranslator.cs new file mode 100644 index 0000000..d6b3623 --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/ExpressionTranslators/Internal/IBTimeSpanPartComponentTranslator.cs @@ -0,0 +1,64 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt. + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * All Rights Reserved. + */ + +//$Authors = Jiri Cincura (jiri@cincura.net) + +using System; +using System.Collections.Generic; +using System.Reflection; +using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; + +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.ExpressionTranslators.Internal; + +public class IBTimeSpanPartComponentTranslator : IMemberTranslator +{ + const string SecondPart = "SECOND"; + const string MillisecondPart = "MILLISECOND"; + private static readonly Dictionary MemberMapping = new Dictionary + { + { typeof(TimeSpan).GetProperty(nameof(TimeSpan.Hours)), "HOUR" }, + { typeof(TimeSpan).GetProperty(nameof(TimeSpan.Minutes)), "MINUTE" }, + { typeof(TimeSpan).GetProperty(nameof(TimeSpan.Seconds)), SecondPart }, + { typeof(TimeSpan).GetProperty(nameof(TimeSpan.Milliseconds)), MillisecondPart }, + }; + readonly IBSqlExpressionFactory _ibSqlExpressionFactory; + + public IBTimeSpanPartComponentTranslator(IBSqlExpressionFactory ibSqlExpressionFactory) + { + _ibSqlExpressionFactory = ibSqlExpressionFactory; + } + + public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) + { + if (!MemberMapping.TryGetValue(member, out var part)) + return null; + + var result = (SqlExpression)_ibSqlExpressionFactory.SpacedFunction( + "EXTRACT", + new[] { _ibSqlExpressionFactory.Fragment(part), _ibSqlExpressionFactory.Fragment("FROM"), instance }, + true, + new[] { false, false, true }, + typeof(int)); + if (part == SecondPart || part == MillisecondPart) + { + result = _ibSqlExpressionFactory.Function("TRUNC", new[] { result }, true, new[] { true }, typeof(int)); + } + return result; + } +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/Changelog.md new file mode 100644 index 0000000..10c5658 --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/Changelog.md @@ -0,0 +1,23 @@ +# Changes for 7.13.6 +* Updates for EFCore 6.0 and sync with Fb 9.x + +## Removed IBTrimExpression.cs, IBSubstringExpression.cs, IBExtractExpression.cs and IBDateTimeDateMemberExpression.cs + +## Added IBSpacedFunctionExpression.cs + +# Changes for 7.10.2 + +## General - +* All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. + +## Common - +* Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Query.Expressions.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Query.Expressions.Internal +* Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. + +* All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. +* For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup + +* using FirebirdSql.EntityFrameworkCore.Firebird.Query.Internal now InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal + + + diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/Changelog.txt b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/Changelog.txt deleted file mode 100644 index 1cbae5b..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/Changelog.txt +++ /dev/null @@ -1,16 +0,0 @@ -Changes for 7.10.2 - - General - - All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. - - Common - - Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Query.Expressions.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Query.Expressions.Internal - Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. - - All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. - For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup - - using FirebirdSql.EntityFrameworkCore.Firebird.Query.Internal now InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal - - - diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/IBDateTimeDateMemberExpression.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/IBDateTimeDateMemberExpression.cs deleted file mode 100644 index edd8a5b..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/IBDateTimeDateMemberExpression.cs +++ /dev/null @@ -1,77 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using System; -using System.Linq.Expressions; -using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -using Microsoft.EntityFrameworkCore.Storage; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.Expressions.Internal -{ - public class IBDateTimeDateMemberExpression : SqlFunctionExpression, IEquatable - { - public virtual SqlExpression ValueExpression { get; } - - public IBDateTimeDateMemberExpression(SqlExpression valueExpression, RelationalTypeMapping typeMapping) - : base(default, default, default, default, default, default, typeof(DateTime), typeMapping) - { - ValueExpression = valueExpression; - } - - protected override Expression Accept(ExpressionVisitor visitor) - => visitor is IBQuerySqlGenerator fbQuerySqlGenerator - ? fbQuerySqlGenerator.VisitDateTimeDateMember(this) - : base.Accept(visitor); - - protected override Expression VisitChildren(ExpressionVisitor visitor) - { - var newValueExpression = (SqlExpression)visitor.Visit(ValueExpression); - - return newValueExpression != ValueExpression - ? new IBDateTimeDateMemberExpression(newValueExpression, TypeMapping) - : this; - } - - public override void Print(ExpressionPrinter expressionPrinter) - { - expressionPrinter.Append("CAST("); - expressionPrinter.Visit(ValueExpression); - expressionPrinter.Append(" AS DATE)"); - } - - public override bool Equals(object obj) - { - return obj != null - && (ReferenceEquals(this, obj) - || obj is IBDateTimeDateMemberExpression fbDateTimeDateMemberExpression - && Equals(fbDateTimeDateMemberExpression)); - } - - public bool Equals(IBDateTimeDateMemberExpression other) - { - return base.Equals(other) - && ValueExpression.Equals(other.ValueExpression); - } - - public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), ValueExpression); - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/IBExtractExpression.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/IBExtractExpression.cs deleted file mode 100644 index 5c6f9bf..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/IBExtractExpression.cs +++ /dev/null @@ -1,82 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using System; -using System.Linq.Expressions; -using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -using Microsoft.EntityFrameworkCore.Storage; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.Expressions.Internal -{ - public class IBExtractExpression : SqlFunctionExpression, IEquatable - { - public virtual string Part { get; } - public virtual SqlExpression ValueExpression { get; } - - public IBExtractExpression(string part, SqlExpression valueExpression, RelationalTypeMapping typeMapping) - : base(default, default, default, default, default, default, typeof(int), typeMapping) - { - Part = part; - ValueExpression = valueExpression; - } - - protected override Expression Accept(ExpressionVisitor visitor) - => visitor is IBQuerySqlGenerator fbQuerySqlGenerator - ? fbQuerySqlGenerator.VisitExtract(this) - : base.Accept(visitor); - - protected override Expression VisitChildren(ExpressionVisitor visitor) - { - var newValueExpression = (SqlExpression)visitor.Visit(ValueExpression); - - return newValueExpression != ValueExpression - ? new IBExtractExpression(Part, newValueExpression, TypeMapping) - : this; - } - - public override void Print(ExpressionPrinter expressionPrinter) - { - expressionPrinter.Append("EXTRACT("); - expressionPrinter.Append(Part); - expressionPrinter.Append(" FROM "); - expressionPrinter.Visit(ValueExpression); - expressionPrinter.Append(")"); - } - - public override bool Equals(object obj) - { - return obj != null - && (ReferenceEquals(this, obj) - || obj is IBExtractExpression fbExtractExpression - && Equals(fbExtractExpression)); - } - - public bool Equals(IBExtractExpression other) - { - return base.Equals(other) - && ValueExpression.Equals(other.ValueExpression) - && Part.Equals(other.Part); - } - - public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), Part, ValueExpression); - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/IBSpacedFunctionExpression.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/IBSpacedFunctionExpression.cs new file mode 100644 index 0000000..b7ab525 --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/IBSpacedFunctionExpression.cs @@ -0,0 +1,81 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt. + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * All Rights Reserved. + */ + +//$Authors = Jiri Cincura (jiri@cincura.net) + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Storage; + +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.Expressions.Internal; + +public class IBSpacedFunctionExpression : SqlFunctionExpression, IEquatable +{ + public IBSpacedFunctionExpression(string name, IEnumerable arguments, bool nullable, IEnumerable argumentsPropagateNullability, Type type, RelationalTypeMapping typeMapping) + : base(name, arguments, nullable, argumentsPropagateNullability, type, typeMapping) + { } + + public override SqlFunctionExpression ApplyTypeMapping(RelationalTypeMapping typeMapping) + { + return new IBSpacedFunctionExpression(Name, Arguments, IsNullable, ArgumentsPropagateNullability, Type, typeMapping ?? TypeMapping); + } + + protected override Expression VisitChildren(ExpressionVisitor visitor) + { + var changed = false; + + var arguments = new SqlExpression[Arguments.Count]; + for (var i = 0; i < arguments.Length; i++) + { + arguments[i] = (SqlExpression)visitor.Visit(Arguments[i]); + changed |= arguments[i] != Arguments[i]; + } + + return changed + ? new IBSpacedFunctionExpression(Name, arguments, IsNullable, ArgumentsPropagateNullability, Type, TypeMapping) + : this; + } + + public override SqlFunctionExpression Update(SqlExpression instance, IReadOnlyList arguments) + { + if (instance != null) + throw new ArgumentException("Instance must be null.", nameof(instance)); + + return !arguments.SequenceEqual(Arguments) + ? new IBSpacedFunctionExpression(Name, arguments, IsNullable, ArgumentsPropagateNullability, Type, TypeMapping) + : this; + } + + public override bool Equals(object obj) + { + return obj != null + && (ReferenceEquals(this, obj) + || obj is IBSpacedFunctionExpression ibExtraFunctionExpression + && Equals(ibExtraFunctionExpression)); + } + + public virtual bool Equals(IBSpacedFunctionExpression other) + { + return base.Equals(other); + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } +} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/IBSubstringExpression.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/IBSubstringExpression.cs deleted file mode 100644 index 51d4c27..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/IBSubstringExpression.cs +++ /dev/null @@ -1,92 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using System; -using System.Linq.Expressions; -using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -using Microsoft.EntityFrameworkCore.Storage; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.Expressions.Internal -{ - public class IBSubstringExpression : SqlFunctionExpression, IEquatable - { - public virtual SqlExpression ValueExpression { get; } - public virtual SqlExpression FromExpression { get; } - public virtual SqlExpression ForExpression { get; } - - public IBSubstringExpression(SqlExpression valueExpression, SqlExpression fromExpression, SqlExpression forExpression, RelationalTypeMapping typeMapping) - : base(default, default, default, default, default, default, typeof(string), typeMapping) - { - ValueExpression = valueExpression; - FromExpression = fromExpression; - ForExpression = forExpression; - } - - protected override Expression Accept(ExpressionVisitor visitor) - => visitor is IBQuerySqlGenerator fbQuerySqlGenerator - ? fbQuerySqlGenerator.VisitSubstring(this) - : base.Accept(visitor); - - protected override Expression VisitChildren(ExpressionVisitor visitor) - { - var newValueExpression = (SqlExpression)visitor.Visit(ValueExpression); - var newFromExpression = (SqlExpression)visitor.Visit(FromExpression); - var newForExpression = (SqlExpression)visitor.Visit(ForExpression); - - return newValueExpression != ValueExpression || newFromExpression != FromExpression || newForExpression != ForExpression - ? new IBSubstringExpression(newValueExpression, newFromExpression, newForExpression, TypeMapping) - : this; - } - - public override void Print(ExpressionPrinter expressionPrinter) - { - expressionPrinter.Append("SUBSTRING("); - expressionPrinter.Visit(ValueExpression); - expressionPrinter.Append(" FROM "); - expressionPrinter.Visit(FromExpression); - if (ForExpression != null) - { - expressionPrinter.Append(" FOR "); - expressionPrinter.Visit(ForExpression); - } - expressionPrinter.Append(")"); - } - - public override bool Equals(object obj) - { - return obj != null - && (ReferenceEquals(this, obj) - || obj is IBSubstringExpression fbSubstringExpression - && Equals(fbSubstringExpression)); - } - - public bool Equals(IBSubstringExpression other) - { - return base.Equals(other) - && ValueExpression.Equals(other.ValueExpression) - && FromExpression.Equals(other.FromExpression) - && (ForExpression == null ? other.ForExpression == null : ForExpression.Equals(other.ForExpression)); - } - - public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), ValueExpression, FromExpression, ForExpression); - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/IBTrimExpression.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/IBTrimExpression.cs deleted file mode 100644 index 29fc800..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Expressions/Internal/IBTrimExpression.cs +++ /dev/null @@ -1,90 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. - * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * - * All Rights Reserved. - */ - -//$Authors = Jiri Cincura (jiri@cincura.net) - -using System; -using System.Linq.Expressions; -using InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -using Microsoft.EntityFrameworkCore.Storage; - -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.Expressions.Internal -{ - public class IBTrimExpression : SqlFunctionExpression, IEquatable - { - public virtual string Where { get; } - public virtual SqlExpression WhatExpression { get; } - public virtual SqlExpression ValueExpression { get; } - - public IBTrimExpression(string where, SqlExpression whatExpression, SqlExpression valueExpression, RelationalTypeMapping typeMapping) - : base(default, default, default, default, default, default, typeof(string), typeMapping) - { - Where = where; - WhatExpression = whatExpression; - ValueExpression = valueExpression; - } - - protected override Expression Accept(ExpressionVisitor visitor) - => visitor is IBQuerySqlGenerator fbQuerySqlGenerator - ? fbQuerySqlGenerator.VisitTrim(this) - : base.Accept(visitor); - - protected override Expression VisitChildren(ExpressionVisitor visitor) - { - var newValueExpression = (SqlExpression)visitor.Visit(ValueExpression); - - return newValueExpression != ValueExpression - ? new IBTrimExpression(Where, WhatExpression, newValueExpression, TypeMapping) - : this; - } - - public override void Print(ExpressionPrinter expressionPrinter) - { - expressionPrinter.Append("TRIM("); - expressionPrinter.Append(Where); - if (WhatExpression != null) - { - expressionPrinter.Append(" "); - expressionPrinter.Visit(WhatExpression); - } - expressionPrinter.Append(" FROM "); - expressionPrinter.Visit(ValueExpression); - expressionPrinter.Append(")"); - } - - public override bool Equals(object obj) - { - return obj != null - && (ReferenceEquals(this, obj) - || obj is IBTrimExpression fbTrimExpression - && Equals(fbTrimExpression)); - } - - public bool Equals(IBTrimExpression other) - { - return base.Equals(other) - && Where.Equals(other.Where) - && WhatExpression.Equals(other.WhatExpression) - && ValueExpression.Equals(other.ValueExpression); - } - - public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), Where, WhatExpression, ValueExpression); - } -} diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/Changelog.md new file mode 100644 index 0000000..29db00f --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/Changelog.md @@ -0,0 +1,40 @@ +# Changes for 7.13.6 (Primarily matching Fb 9.x driver changes for EFCore 6.0) + +## Added IBSQLTranslatingExpressionVisitor.cs and IBSQLTranslatingExpressionVisitorFactory.cs + + + +# Changes for 7.10.2 + +## General - +* All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. + +## Common - +* Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Query.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal +* Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. + +* All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. +* For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup + +* using FirebirdSql.EntityFrameworkCore.Firebird.Infrastructure.Internal, FirebirdSql.EntityFrameworkCore.Firebird.Query.Expressions.Internal and FirebirdSql.EntityFrameworkCore.Firebird.Storage.Internal +* now InterBaseSql.EntityFrameworkCore.InterBase.Infrastructure.Internal, InterBaseSql.EntityFrameworkCore.InterBase.Query.Expressions.Internal and InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal + +## FbQuerySqlGenerator.cs now IBQuerySqlGenerator.cs +* FbQuerySqlGenerator now IBQuerySqlGenerator +* Added private GeneratingLimits boolean used to impliment Rows without a cast on the parameters at the end vs Top in the SELECT section. +* VisitSqlBinary "MOD" now "EF_MOD" +* VisitSqlBinary "BIN_AND" now "EF_BINAND" +* VisitSqlBinary "BIN_OR" now "EF_BINOR" +* VisitSqlBinary "BINXOR" now "EF_BIN_XOR" +* VisitSqlBinary "BIN_SHL" now "EF_BINSHL" +* VisitSqlBinary "BIN_SHR" now "EF_BINSHR" +* VisitSqlParameter no longer casts the parameter for rows ever when GeneratingLimits is true +* VisitSqlConstant no longer casts the parameter when GeneratingLimits is true +* GenerateLimitOffset +* sets the GeneratingLimits to true to stop casts beign generated regardless of the sqlConstantExpression value +* Uses the integer max as a end limit vs long max value (IB only supports rows to maxint) +* GeneratingLimits set to false before exiting +* VisitSubstring now uses EF_SUBSTR and no longer uses the FB specific FROM..FOR form +* VisitTrim calls EF_TRIM instead of the internal function for Fb TRIM + + diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/Changelog.txt b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/Changelog.txt deleted file mode 100644 index f7c66bf..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/Changelog.txt +++ /dev/null @@ -1,34 +0,0 @@ -Changes for 7.10.2 - - General - - All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. - - Common - - Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Query.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal - Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. - - All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. - For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup - - using FirebirdSql.EntityFrameworkCore.Firebird.Infrastructure.Internal, FirebirdSql.EntityFrameworkCore.Firebird.Query.Expressions.Internal and FirebirdSql.EntityFrameworkCore.Firebird.Storage.Internal - now InterBaseSql.EntityFrameworkCore.InterBase.Infrastructure.Internal, InterBaseSql.EntityFrameworkCore.InterBase.Query.Expressions.Internal and InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal - - FbQuerySqlGenerator.cs now IBQuerySqlGenerator.cs - FbQuerySqlGenerator now IBQuerySqlGenerator - Added private GeneratingLimits boolean used to impliment Rows without a cast on the parameters at the end vs Top in the SELECT section. - VisitSqlBinary "MOD" now "EF_MOD" - VisitSqlBinary "BIN_AND" now "EF_BINAND" - VisitSqlBinary "BIN_OR" now "EF_BINOR" - VisitSqlBinary "BINXOR" now "EF_BIN_XOR" - VisitSqlBinary "BIN_SHL" now "EF_BINSHL" - VisitSqlBinary "BIN_SHR" now "EF_BINSHR" - VisitSqlParameter no longer casts the parameter for rows ever when GeneratingLimits is true - VisitSqlConstant no longer casts the parameter when GeneratingLimits is true - GenerateLimitOffset - sets the GeneratingLimits to true to stop casts beign generated regardless of the sqlConstantExpression value - Uses the integer max as a end limit vs long max value (IB only supports rows to maxint) - GeneratingLimits set to false before exiting - VisitSubstring now uses EF_SUBSTR and no longer uses the FB specific FROM..FOR form - VisitTrim calls EF_TRIM instead of the internal function for Fb TRIM - - diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/IBQuerySqlGenerator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/IBQuerySqlGenerator.cs index 3eed0f1..2327ed4 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/IBQuerySqlGenerator.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/IBQuerySqlGenerator.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Linq.Expressions; using InterBaseSql.EntityFrameworkCore.InterBase.Infrastructure.Internal; @@ -29,363 +30,279 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; + +public class IBQuerySqlGenerator : QuerySqlGenerator { - public class IBQuerySqlGenerator : QuerySqlGenerator + readonly IIBOptions _ibOptions; + bool GeneratingLimits = false; + + public IBQuerySqlGenerator(QuerySqlGeneratorDependencies dependencies, IIBOptions ibOptions) + : base(dependencies) { - readonly IIBOptions _ibOptions; - bool GeneratingLimits = false; + _ibOptions = ibOptions; + } - public IBQuerySqlGenerator(QuerySqlGeneratorDependencies dependencies, IIBOptions ibOptions) - : base(dependencies) + protected override Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpression) + { + if (sqlBinaryExpression.OperatorType == ExpressionType.Modulo) { - _ibOptions = ibOptions; + Sql.Append("EF_MOD("); + Visit(sqlBinaryExpression.Left); + Sql.Append(", "); + Visit(sqlBinaryExpression.Right); + Sql.Append(")"); + return sqlBinaryExpression; } - - protected override Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpression) + else if (sqlBinaryExpression.OperatorType == ExpressionType.And && sqlBinaryExpression.TypeMapping.ClrType != typeof(bool)) { - if (sqlBinaryExpression.OperatorType == ExpressionType.Modulo) - { - Sql.Append("EF_MOD("); - Visit(sqlBinaryExpression.Left); - Sql.Append(", "); - Visit(sqlBinaryExpression.Right); - Sql.Append(")"); - return sqlBinaryExpression; - } - else if (sqlBinaryExpression.OperatorType == ExpressionType.And && sqlBinaryExpression.TypeMapping.ClrType != typeof(bool)) - { - Sql.Append("EF_BINAND("); - Visit(sqlBinaryExpression.Left); - Sql.Append(", "); - Visit(sqlBinaryExpression.Right); - Sql.Append(")"); - return sqlBinaryExpression; - } - else if (sqlBinaryExpression.OperatorType == ExpressionType.Or && sqlBinaryExpression.TypeMapping.ClrType != typeof(bool)) - { - Sql.Append("EF_BINOR("); - Visit(sqlBinaryExpression.Left); - Sql.Append(", "); - Visit(sqlBinaryExpression.Right); - Sql.Append(")"); - return sqlBinaryExpression; - } - else if (sqlBinaryExpression.OperatorType == ExpressionType.ExclusiveOr) - { - Sql.Append("EF_BINXOR("); - Visit(sqlBinaryExpression.Left); - Sql.Append(", "); - Visit(sqlBinaryExpression.Right); - Sql.Append(")"); - return sqlBinaryExpression; - } - else if (sqlBinaryExpression.OperatorType == ExpressionType.LeftShift) - { - Sql.Append("EF_BINSHL("); - Visit(sqlBinaryExpression.Left); - Sql.Append(", "); - Visit(sqlBinaryExpression.Right); - Sql.Append(")"); - return sqlBinaryExpression; - } - else if (sqlBinaryExpression.OperatorType == ExpressionType.RightShift) - { - Sql.Append("EF_BINSHR("); - Visit(sqlBinaryExpression.Left); - Sql.Append(", "); - Visit(sqlBinaryExpression.Right); - Sql.Append(")"); - return sqlBinaryExpression; - } - else - { - return base.VisitSqlBinary(sqlBinaryExpression); - } + Sql.Append("EF_BINAND("); + Visit(sqlBinaryExpression.Left); + Sql.Append(", "); + Visit(sqlBinaryExpression.Right); + Sql.Append(")"); + return sqlBinaryExpression; } - - protected override Expression VisitSqlParameter(SqlParameterExpression sqlParameterExpression) + else if (sqlBinaryExpression.OperatorType == ExpressionType.Or && sqlBinaryExpression.TypeMapping.ClrType != typeof(bool)) { - var shouldExplicitParameterTypes = _ibOptions.ExplicitParameterTypes && (GeneratingLimits != true); - if (shouldExplicitParameterTypes) - { - Sql.Append("CAST("); - } - base.VisitSqlParameter(sqlParameterExpression); - if (shouldExplicitParameterTypes) - { - Sql.Append(" AS "); - if (sqlParameterExpression.Type == typeof(string)) - { - Sql.Append((Dependencies.SqlGenerationHelper as IIBSqlGenerationHelper).StringParameterQueryType()); - } - else - { - Sql.Append(sqlParameterExpression.TypeMapping.StoreType); - } - Sql.Append(")"); - } - return sqlParameterExpression; + Sql.Append("EF_BINOR("); + Visit(sqlBinaryExpression.Left); + Sql.Append(", "); + Visit(sqlBinaryExpression.Right); + Sql.Append(")"); + return sqlBinaryExpression; } - - protected override Expression VisitSqlConstant(SqlConstantExpression sqlConstantExpression) + else if (sqlBinaryExpression.OperatorType == ExpressionType.ExclusiveOr) { - var shouldExplicitStringLiteralTypes = (_ibOptions.ExplicitStringLiteralTypes && sqlConstantExpression.Type == typeof(string)) && (GeneratingLimits != true); - if (shouldExplicitStringLiteralTypes) - { - Sql.Append("CAST("); - } - base.VisitSqlConstant(sqlConstantExpression); - if (shouldExplicitStringLiteralTypes) - { - Sql.Append(" AS "); - Sql.Append((Dependencies.SqlGenerationHelper as IIBSqlGenerationHelper).StringLiteralQueryType(sqlConstantExpression.Value as string)); - Sql.Append(")"); - } - return sqlConstantExpression; + Sql.Append("EF_BINXOR("); + Visit(sqlBinaryExpression.Left); + Sql.Append(", "); + Visit(sqlBinaryExpression.Right); + Sql.Append(")"); + return sqlBinaryExpression; } - - protected override void GenerateTop(SelectExpression selectExpression) + else if (sqlBinaryExpression.OperatorType == ExpressionType.LeftShift) + { + Sql.Append("EF_BINSHL("); + Visit(sqlBinaryExpression.Left); + Sql.Append(", "); + Visit(sqlBinaryExpression.Right); + Sql.Append(")"); + return sqlBinaryExpression; + } + else if (sqlBinaryExpression.OperatorType == ExpressionType.RightShift) { - // handled by GenerateLimitOffset + Sql.Append("EF_BINSHR("); + Visit(sqlBinaryExpression.Left); + Sql.Append(", "); + Visit(sqlBinaryExpression.Right); + Sql.Append(")"); + return sqlBinaryExpression; } - - protected override void GenerateLimitOffset(SelectExpression selectExpression) + else { - GeneratingLimits = true; -// var p = GetCommand(selectExpression).Parameters; - if (selectExpression.Limit != null && selectExpression.Offset != null) - { - Sql.AppendLine(); - Sql.Append("ROWS ("); - Visit(selectExpression.Offset); - Sql.Append(") TO ("); -// Sql.Append(" + 1) TO ("); -// Visit(selectExpression.Offset); -// Sql.Append(" + "); - Visit(selectExpression.Limit); - Sql.Append(")"); - } - else if (selectExpression.Limit != null && selectExpression.Offset == null) - { - Sql.AppendLine(); - Sql.Append("ROWS ("); - Visit(selectExpression.Limit); - Sql.Append(")"); - } - else if (selectExpression.Limit == null && selectExpression.Offset != null) - { - Sql.AppendLine(); - Sql.Append("ROWS ("); - Visit(selectExpression.Offset); - Sql.Append(") TO ("); - Sql.Append(int.MaxValue); - Sql.Append(")"); - } - GeneratingLimits = false; + return base.VisitSqlBinary(sqlBinaryExpression); } + } - protected override string GenerateOperator(SqlBinaryExpression binaryExpression) + protected override Expression VisitSqlParameter(SqlParameterExpression sqlParameterExpression) + { + var shouldExplicitParameterTypes = _ibOptions.ExplicitParameterTypes && (GeneratingLimits != true); + if (shouldExplicitParameterTypes) { - if (binaryExpression.OperatorType == ExpressionType.Add && binaryExpression.TypeMapping.ClrType == typeof(string)) - { - return " || "; - } - else if (binaryExpression.OperatorType == ExpressionType.AndAlso || binaryExpression.OperatorType == ExpressionType.And) + Sql.Append("CAST("); + } + base.VisitSqlParameter(sqlParameterExpression); + if (shouldExplicitParameterTypes) + { + Sql.Append(" AS "); + if (sqlParameterExpression.Type == typeof(string)) { - return " AND "; + var isUnicode = IBTypeMappingSource.IsUnicode(sqlParameterExpression.TypeMapping); + Sql.Append(((IIBSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringParameterQueryType(isUnicode)); } - else if (binaryExpression.OperatorType == ExpressionType.OrElse || binaryExpression.OperatorType == ExpressionType.Or) + else { - return " OR "; + Sql.Append(sqlParameterExpression.TypeMapping.StoreType); } - return base.GenerateOperator(binaryExpression); + Sql.Append(")"); } + return sqlParameterExpression; + } - // https://github.com/aspnet/EntityFrameworkCore/issues/19031 - protected override void GenerateOrderings(SelectExpression selectExpression) + protected override Expression VisitSqlConstant(SqlConstantExpression sqlConstantExpression) + { + var shouldExplicitStringLiteralTypes = (_ibOptions.ExplicitStringLiteralTypes && sqlConstantExpression.Type == typeof(string)) && (GeneratingLimits != true); + if (shouldExplicitStringLiteralTypes) { - if (selectExpression.Orderings.Any()) - { - var orderings = selectExpression.Orderings.ToList(); - - if (selectExpression.Limit == null - && selectExpression.Offset == null) - { - orderings.RemoveAll(oe => oe.Expression is SqlConstantExpression || oe.Expression is SqlParameterExpression); - } + Sql.Append("CAST("); + } + base.VisitSqlConstant(sqlConstantExpression); + if (shouldExplicitStringLiteralTypes) + { + Sql.Append(" AS "); + Sql.Append(((IIBSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringLiteralQueryType(sqlConstantExpression.Value as string)); + Sql.Append(")"); + } + return sqlConstantExpression; + } - if (orderings.Count > 0) - { - Sql.AppendLine() - .Append("ORDER BY "); + protected override void GenerateTop(SelectExpression selectExpression) + { + // handled by GenerateLimitOffset + } - GenerateList(orderings, e => Visit(e)); - } - } + protected override void GenerateLimitOffset(SelectExpression selectExpression) + { + if (selectExpression.Limit != null && selectExpression.Offset != null) + { + Sql.AppendLine(); + Sql.Append("ROWS ("); + Visit(selectExpression.Offset); + Sql.Append(" + 1) TO ("); + Visit(selectExpression.Offset); + Sql.Append(" + "); + Visit(selectExpression.Limit); + Sql.Append(")"); } - - protected /*override*/ void GeneratePseudoFromClause() + else if (selectExpression.Limit != null && selectExpression.Offset == null) { - Sql.Append(" FROM RDB$DATABASE"); + Sql.AppendLine(); + Sql.Append("ROWS ("); + Visit(selectExpression.Limit); + Sql.Append(")"); } - - // GeneratePseudoFromClause workaround - protected override Expression VisitSelect(SelectExpression selectExpression) + else if (selectExpression.Limit == null && selectExpression.Offset != null) { - if (selectExpression.Alias != null) - { - Sql.AppendLine("("); - Sql.IncrementIndent(); - } - - Sql.Append("SELECT "); - - if (selectExpression.IsDistinct) - { - Sql.Append("DISTINCT "); - } - - GenerateTop(selectExpression); - - if (selectExpression.Projection.Any()) - { - GenerateList(selectExpression.Projection, e => Visit(e)); - } - else - { - Sql.Append("1"); - } - - if (selectExpression.Tables.Any()) - { - Sql.AppendLine().Append("FROM "); - - GenerateList(selectExpression.Tables, e => Visit(e), sql => sql.AppendLine()); - } - else - { - GeneratePseudoFromClause(); - } + Sql.AppendLine(); + Sql.Append("ROWS ("); + Visit(selectExpression.Offset); + Sql.Append(") TO ("); + Sql.Append(long.MaxValue.ToString(CultureInfo.InvariantCulture)); + Sql.Append(")"); + } + GeneratingLimits = false; + } - if (selectExpression.Predicate != null) - { - Sql.AppendLine().Append("WHERE "); + protected override string GetOperator(SqlBinaryExpression binaryExpression) + { + if (binaryExpression.OperatorType == ExpressionType.Add && binaryExpression.TypeMapping.ClrType == typeof(string)) + { + return " || "; + } + else if (binaryExpression.OperatorType == ExpressionType.AndAlso || binaryExpression.OperatorType == ExpressionType.And) + { + return " AND "; + } + else if (binaryExpression.OperatorType == ExpressionType.OrElse || binaryExpression.OperatorType == ExpressionType.Or) + { + return " OR "; + } + return base.GetOperator(binaryExpression); + } - Visit(selectExpression.Predicate); - } + // https://github.com/aspnet/EntityFrameworkCore/issues/19031 + protected override void GenerateOrderings(SelectExpression selectExpression) + { + if (selectExpression.Orderings.Any()) + { + var orderings = selectExpression.Orderings.ToList(); - if (selectExpression.GroupBy.Count > 0) + if (selectExpression.Limit == null + && selectExpression.Offset == null) { - Sql.AppendLine().Append("GROUP BY "); - - GenerateList(selectExpression.GroupBy, e => Visit(e)); + orderings.RemoveAll(oe => oe.Expression is SqlConstantExpression || oe.Expression is SqlParameterExpression); } - if (selectExpression.Having != null) + if (orderings.Count > 0) { - Sql.AppendLine().Append("HAVING "); + Sql.AppendLine() + .Append("ORDER BY "); - Visit(selectExpression.Having); + GenerateList(orderings, e => Visit(e)); } + } + } - GenerateOrderings(selectExpression); - GenerateLimitOffset(selectExpression); - - if (selectExpression.Alias != null) - { - Sql.DecrementIndent(); - - Sql.AppendLine() - .Append(")" + AliasSeparator + Dependencies.SqlGenerationHelper.DelimitIdentifier(selectExpression.Alias)); - } + protected override void GeneratePseudoFromClause() + { + Sql.Append(" FROM RDB$DATABASE"); + } - return selectExpression; + // GeneratePseudoFromClause workaround + protected override Expression VisitOrdering(OrderingExpression orderingExpression) + { + if (orderingExpression.Expression is SqlConstantExpression + || orderingExpression.Expression is SqlParameterExpression + || (orderingExpression.Expression is SqlFragmentExpression sqlFragment && sqlFragment.Sql.Equals("(SELECT 1)", StringComparison.Ordinal))) + { + Sql.Append("(SELECT 1"); + GeneratePseudoFromClause(); + Sql.Append(")"); } - - protected override Expression VisitOrdering(OrderingExpression orderingExpression) + else { - if (orderingExpression.Expression is SqlConstantExpression - || orderingExpression.Expression is SqlParameterExpression) - { - Sql.Append("(SELECT 1"); - GeneratePseudoFromClause(); - Sql.Append(")"); - } - else - { - Visit(orderingExpression.Expression); - } - - if (!orderingExpression.IsAscending) - { - Sql.Append(" DESC"); - } - - return orderingExpression; + Visit(orderingExpression.Expression); } - public virtual Expression VisitSubstring(IBSubstringExpression substringExpression) + if (!orderingExpression.IsAscending) { - Sql.Append("EF_SUBSTR("); - Visit(substringExpression.ValueExpression); - Sql.Append(", "); - Visit(substringExpression.FromExpression); - if (substringExpression.ForExpression != null) - { - Sql.Append(", "); - Visit(substringExpression.ForExpression); - } - Sql.Append(")"); - return substringExpression; + Sql.Append(" DESC"); } - public virtual Expression VisitExtract(IBExtractExpression extractExpression) + return orderingExpression; + } + + protected override Expression VisitTableValuedFunction(TableValuedFunctionExpression tableValuedFunctionExpression) + { + Sql.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(tableValuedFunctionExpression.StoreFunction.Name)); + if (tableValuedFunctionExpression.Arguments.Any()) { - Sql.Append("EXTRACT("); - Sql.Append(extractExpression.Part); - Sql.Append(" FROM "); - Visit(extractExpression.ValueExpression); + Sql.Append("("); + GenerateList(tableValuedFunctionExpression.Arguments, e => Visit(e)); Sql.Append(")"); - return extractExpression; } + Sql.Append(AliasSeparator); + Sql.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(tableValuedFunctionExpression.Alias)); + return tableValuedFunctionExpression; + } - public virtual Expression VisitDateTimeDateMember(IBDateTimeDateMemberExpression dateTimeDateMemberExpression) + protected override Expression VisitExtension(Expression extensionExpression) + { + return extensionExpression switch { - Sql.Append("CAST("); - Visit(dateTimeDateMemberExpression.ValueExpression); - Sql.Append(" AS DATE)"); - return dateTimeDateMemberExpression; - } + IBSpacedFunctionExpression spacedFunctionExpression => VisitSpacedFunction(spacedFunctionExpression), + _ => base.VisitExtension(extensionExpression), + }; + } - public virtual Expression VisitTrim(IBTrimExpression trimExpression) + public virtual Expression VisitSpacedFunction(IBSpacedFunctionExpression spacedFunctionExpression) + { + Sql.Append(spacedFunctionExpression.Name); + Sql.Append("("); + for (var i = 0; i < spacedFunctionExpression.Arguments.Count; i++) { - Sql.Append("EF_TRIM("); - Sql.Append(trimExpression.Where); - if (trimExpression.WhatExpression != null) + Visit(spacedFunctionExpression.Arguments[i]); + if (i < spacedFunctionExpression.Arguments.Count - 1) { Sql.Append(" "); - Visit(trimExpression.WhatExpression); } - Sql.Append(", "); - Visit(trimExpression.ValueExpression); - Sql.Append(")"); - return trimExpression; } + Sql.Append(")"); + return spacedFunctionExpression; + } + void GenerateList(IReadOnlyList items, Action generationAction, Action joinAction = null) + { + joinAction ??= (isb => isb.Append(", ")); - void GenerateList(IReadOnlyList items, Action generationAction, Action joinAction = null) + for (var i = 0; i < items.Count; i++) { - joinAction ??= (isb => isb.Append(", ")); - - for (var i = 0; i < items.Count; i++) + if (i > 0) { - if (i > 0) - { - joinAction(Sql); - } - - generationAction(items[i]); + joinAction(Sql); } + + generationAction(items[i]); } } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/IBQuerySqlGeneratorFactory.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/IBQuerySqlGeneratorFactory.cs index 0ec667e..fc46f30 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/IBQuerySqlGeneratorFactory.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/IBQuerySqlGeneratorFactory.cs @@ -21,20 +21,19 @@ using InterBaseSql.EntityFrameworkCore.InterBase.Infrastructure.Internal; using Microsoft.EntityFrameworkCore.Query; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal -{ - public class IBQuerySqlGeneratorFactory : IQuerySqlGeneratorFactory - { - readonly QuerySqlGeneratorDependencies _dependencies; - readonly IIBOptions _ibOptions; +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; - public IBQuerySqlGeneratorFactory(QuerySqlGeneratorDependencies dependencies, IIBOptions ibOptions) - { - _dependencies = dependencies; - _ibOptions = ibOptions; - } +public class IBQuerySqlGeneratorFactory : IQuerySqlGeneratorFactory +{ + readonly QuerySqlGeneratorDependencies _dependencies; + readonly IIBOptions _ibOptions; - public QuerySqlGenerator Create() - => new IBQuerySqlGenerator(_dependencies, _ibOptions); + public IBQuerySqlGeneratorFactory(QuerySqlGeneratorDependencies dependencies, IIBOptions ibOptions) + { + _dependencies = dependencies; + _ibOptions = ibOptions; } + + public QuerySqlGenerator Create() + => new IBQuerySqlGenerator(_dependencies, _ibOptions); } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/IBSqlExpressionFactory.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/IBSqlExpressionFactory.cs index 9a9d90b..0f89231 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/IBSqlExpressionFactory.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/IBSqlExpressionFactory.cs @@ -18,74 +18,30 @@ //$Authors = Jiri Cincura (jiri@cincura.net) +using System; +using System.Collections.Generic; using InterBaseSql.EntityFrameworkCore.InterBase.Query.Expressions.Internal; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal -{ - public class IBSqlExpressionFactory : SqlExpressionFactory - { - public IBSqlExpressionFactory(SqlExpressionFactoryDependencies dependencies) - : base(dependencies) - { } - - public IBSubstringExpression Substring(SqlExpression valueExpression, SqlExpression fromExpression, SqlExpression forExpression) - => (IBSubstringExpression)ApplyDefaultTypeMapping(new IBSubstringExpression(valueExpression, fromExpression, forExpression, null)); - - public IBExtractExpression Extract(string part, SqlExpression valueExpression) - => (IBExtractExpression)ApplyDefaultTypeMapping(new IBExtractExpression(part, valueExpression, null)); - - public IBDateTimeDateMemberExpression DateTimeDateMember(SqlExpression valueExpression) - => (IBDateTimeDateMemberExpression)ApplyDefaultTypeMapping(new IBDateTimeDateMemberExpression(valueExpression, null)); - - public IBTrimExpression Trim(string where, SqlExpression whatExpression, SqlExpression valueExpression) - => (IBTrimExpression)ApplyDefaultTypeMapping(new IBTrimExpression(where, whatExpression, valueExpression, null)); +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; - public override SqlExpression ApplyTypeMapping(SqlExpression sqlExpression, RelationalTypeMapping typeMapping) - => sqlExpression == null || sqlExpression.TypeMapping != null - ? sqlExpression - : sqlExpression switch - { - IBSubstringExpression e => ApplyTypeMappingOnSubstring(e), - IBExtractExpression e => ApplyTypeMappingOnExtract(e), - IBDateTimeDateMemberExpression e => ApplyTypeMappingOnDateTimeDateMember(e), - IBTrimExpression e => ApplyTypeMappingOnTrim(e), - _ => base.ApplyTypeMapping(sqlExpression, typeMapping) - }; - - SqlExpression ApplyTypeMappingOnSubstring(IBSubstringExpression expression) - { - return new IBSubstringExpression( - ApplyDefaultTypeMapping(expression.ValueExpression), - ApplyDefaultTypeMapping(expression.FromExpression), - ApplyDefaultTypeMapping(expression.ForExpression), - expression.TypeMapping ?? FindMapping(expression.Type)); - } - - SqlExpression ApplyTypeMappingOnExtract(IBExtractExpression expression) - { - return new IBExtractExpression( - expression.Part, - ApplyDefaultTypeMapping(expression.ValueExpression), - expression.TypeMapping ?? FindMapping(expression.Type)); - } - - SqlExpression ApplyTypeMappingOnDateTimeDateMember(IBDateTimeDateMemberExpression expression) - { - return new IBDateTimeDateMemberExpression( - ApplyDefaultTypeMapping(expression.ValueExpression), - expression.TypeMapping ?? FindMapping(expression.Type)); - } - - SqlExpression ApplyTypeMappingOnTrim(IBTrimExpression expression) - { - return new IBTrimExpression( - expression.Where, - ApplyDefaultTypeMapping(expression.WhatExpression), - ApplyDefaultTypeMapping(expression.ValueExpression), - expression.TypeMapping ?? FindMapping(expression.Type)); - } - } +public class IBSqlExpressionFactory : SqlExpressionFactory +{ + public IBSqlExpressionFactory(SqlExpressionFactoryDependencies dependencies) + : base(dependencies) + { } + + public IBSpacedFunctionExpression SpacedFunction(string name, IEnumerable arguments, bool nullable, IEnumerable argumentsPropagateNullability, Type type, RelationalTypeMapping typeMapping = null) + => (IBSpacedFunctionExpression)ApplyDefaultTypeMapping(new IBSpacedFunctionExpression(name, arguments, nullable, argumentsPropagateNullability, type, typeMapping)); + + public override SqlExpression ApplyTypeMapping(SqlExpression sqlExpression, RelationalTypeMapping typeMapping) + => sqlExpression == null || sqlExpression.TypeMapping != null + ? sqlExpression + : sqlExpression switch + { + IBSpacedFunctionExpression e => e.ApplyTypeMapping(typeMapping), + _ => base.ApplyTypeMapping(sqlExpression, typeMapping) + }; } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/IBSqlTranslatingExpressionVisitor.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/IBSqlTranslatingExpressionVisitor.cs new file mode 100644 index 0000000..1b9c7e3 --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/IBSqlTranslatingExpressionVisitor.cs @@ -0,0 +1,42 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt. + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * All Rights Reserved. + */ + +//$Authors = Jiri Cincura (jiri@cincura.net) + +using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; + +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; + +public class IBSqlTranslatingExpressionVisitor : RelationalSqlTranslatingExpressionVisitor +{ + public IBSqlTranslatingExpressionVisitor(RelationalSqlTranslatingExpressionVisitorDependencies dependencies, QueryCompilationContext queryCompilationContext, QueryableMethodTranslatingExpressionVisitor queryableMethodTranslatingExpressionVisitor) + : base(dependencies, queryCompilationContext, queryableMethodTranslatingExpressionVisitor) + { } + + protected override Expression VisitUnary(UnaryExpression unaryExpression) + { + if (unaryExpression.NodeType == ExpressionType.ArrayLength && unaryExpression.Operand.Type == typeof(byte[])) + { + if (!(base.Visit(unaryExpression.Operand) is SqlExpression sqlExpression)) + { + return null; + } + return Dependencies.SqlExpressionFactory.Function("OCTET_LENGTH", new[] { sqlExpression }, true, new[] { true }, typeof(int)); + } + return base.VisitUnary(unaryExpression); + } +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/IBSqlTranslatingExpressionVisitorFactory.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/IBSqlTranslatingExpressionVisitorFactory.cs new file mode 100644 index 0000000..faa02c5 --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Query/Internal/IBSqlTranslatingExpressionVisitorFactory.cs @@ -0,0 +1,33 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt. + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * All Rights Reserved. + */ + +//$Authors = Jiri Cincura (jiri@cincura.net) + +using Microsoft.EntityFrameworkCore.Query; + +namespace InterBaseSql.EntityFrameworkCore.InterBase.Query.Internal; + +public class IBSqlTranslatingExpressionVisitorFactory : IRelationalSqlTranslatingExpressionVisitorFactory +{ + readonly RelationalSqlTranslatingExpressionVisitorDependencies _dependencies; + + public IBSqlTranslatingExpressionVisitorFactory(RelationalSqlTranslatingExpressionVisitorDependencies dependencies) + { + _dependencies = dependencies; + } + + public virtual RelationalSqlTranslatingExpressionVisitor Create(QueryCompilationContext queryCompilationContext, QueryableMethodTranslatingExpressionVisitor queryableMethodTranslatingExpressionVisitor) + => new IBSqlTranslatingExpressionVisitor(_dependencies, queryCompilationContext, queryableMethodTranslatingExpressionVisitor); +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Scaffolding/Internal/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Scaffolding/Internal/Changelog.md new file mode 100644 index 0000000..738d4a1 --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Scaffolding/Internal/Changelog.md @@ -0,0 +1,27 @@ +#Changes for 7.13.6 (updated for EFCore 6.0 and to Fb 9.x) + +## removed IBProviderConfigurationCodeGenerator.cs + +## added IBProviderCodeGenerator.cs + +## IBDatabaseModleFactory +* fixed Fb specific SQL to be IB compliant + +# Changes for 7.10.2 + +## General - +* All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. + +## Common - +* Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Scaffolding.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Scaffolding.Internal +* Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. + +* All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. +* For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup + +* using FirebirdSql.Data.FirebirdClient now InterBaseSql.Data.InterBaseClient + +## FbProviderConfigurationCodeGenerator.cs now IBProviderConfigurationCodeGenerator.cs +* FbProviderConfigurationCodeGenerator now IBProviderConfigurationCodeGenerator +* MethodCallCodeFragment now uses IBDbContextOptionsBuilderExtensions.UseInterBase in the MethodCallCodeFragment call + diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Scaffolding/Internal/Changelog.txt b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Scaffolding/Internal/Changelog.txt deleted file mode 100644 index 1a85bc2..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Scaffolding/Internal/Changelog.txt +++ /dev/null @@ -1,18 +0,0 @@ -Changes for 7.10.2 - - General - - All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. - - Common - - Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Scaffolding.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Scaffolding.Internal - Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. - - All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. - For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup - - using FirebirdSql.Data.FirebirdClient now InterBaseSql.Data.InterBaseClient - - FbProviderConfigurationCodeGenerator.cs now IBProviderConfigurationCodeGenerator.cs - FbProviderConfigurationCodeGenerator now IBProviderConfigurationCodeGenerator - MethodCallCodeFragment now uses IBDbContextOptionsBuilderExtensions.UseInterBase in the MethodCallCodeFragment call - diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Scaffolding/Internal/IBDatabaseModelFactory.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Scaffolding/Internal/IBDatabaseModelFactory.cs index 4abd4e9..f67fbb6 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Scaffolding/Internal/IBDatabaseModelFactory.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Scaffolding/Internal/IBDatabaseModelFactory.cs @@ -19,60 +19,467 @@ //$Authors = Jiri Cincura (jiri@cincura.net) using System; +using System.Collections.Generic; using System.Data; using System.Data.Common; +using System.Linq; using InterBaseSql.Data.InterBaseClient; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Scaffolding; using Microsoft.EntityFrameworkCore.Scaffolding.Metadata; +using Microsoft.Extensions.Logging; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Scaffolding.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Scaffolding.Internal; + +public class IBDatabaseModelFactory : DatabaseModelFactory { - public class IBDatabaseModelFactory : IDatabaseModelFactory + + public override DatabaseModel Create(string connectionString, DatabaseModelFactoryOptions options) + { + using (var connection = new IBConnection(connectionString)) + { + return Create(connection, options); + } + } + + public override DatabaseModel Create(DbConnection connection, DatabaseModelFactoryOptions options) { - DatabaseModel _databaseModel; - IBConnection _connection; - Version _serverVersion; + var databaseModel = new DatabaseModel(); - public DatabaseModel Create(string connectionString, DatabaseModelFactoryOptions options) + var connectionStartedOpen = connection.State == ConnectionState.Open; + if (!connectionStartedOpen) { - using (var connection = new IBConnection(connectionString)) + connection.Open(); + } + try + { + databaseModel.DatabaseName = connection.Database; + databaseModel.DefaultSchema = GetDefaultSchema(connection); + + var schemaList = new List(); + var tableList = options.Tables.ToList(); + var tableFilter = GenerateTableFilter(tableList, schemaList); + + var tables = GetTables(connection, tableFilter); + foreach (var table in tables) { - return Create(connection, options); + table.Database = databaseModel; + if (tableFilter.Invoke(table)) + { + databaseModel.Tables.Add(table); + } + } + + return databaseModel; + } + finally + { + if (!connectionStartedOpen) + { + connection.Close(); } } + } + + private static string GetDefaultSchema(DbConnection connection) + { + return null; + } - public DatabaseModel Create(DbConnection connection, DatabaseModelFactoryOptions options) + private static Func GenerateTableFilter(IReadOnlyList tables, IReadOnlyList schemas) + { + return tables.Any() ? x => tables.Contains(x.Name) : _ => true; + } + + private const string GetTablesQuery = + @"SELECT + r.RDB$RELATION_NAME, + r.RDB$DESCRIPTION, + r.RDB$RELATION_TYPE + FROM + RDB$RELATIONS r + WHERE + COALESCE(r.RDB$SYSTEM_FLAG, 0) <> 1 + ORDER BY + r.RDB$RELATION_NAME"; + + private IEnumerable GetTables(DbConnection connection, Func filter) + { + using (var command = connection.CreateCommand()) { - ResetState(); + var tables = new List(); + command.CommandText = GetTablesQuery; + using (var reader = command.ExecuteReader()) + { + while (reader.Read()) + { + var name = reader.GetString(0).Trim(); + var comment = reader.GetString(1); + var type = reader.GetString(2).Trim(); - _connection = (IBConnection)connection; + var table = type == "VIEW" + ? new DatabaseView() + : new DatabaseTable(); - var connectionStartedOpen = _connection.State == ConnectionState.Open; - if (!connectionStartedOpen) + table.Schema = null; + table.Name = name; + table.Comment = string.IsNullOrEmpty(comment) ? null : comment; + + tables.Add(table); + } + } + + GetColumns(connection, tables, filter); + GetPrimaryKeys(connection, tables); + GetIndexes(connection, tables, filter); + GetConstraints(connection, tables); + + return tables; + } + } + + private string GetStoreType(int field_type, int size, int sub_type) + { + string result = ""; + switch (field_type) + { + case 7: + result = sub_type == 0 ? "SMALLINT" : "DECIMAL"; + break; + case 8: + result = sub_type == 0 ? "INTEGER" : "DECIMAL"; + break; + case 9: + result = "QUAD"; + break; + case 10: + result = "FLOAT"; + break; + case 12: + result = "DATE"; + break; + case 13: + result = "TIME"; + break; + case 14: + result = "CHAR(" + size.ToString() + ")"; + break; + case 16: + result = sub_type == 0 ? "BIGINT" : "DECIMAL"; + break; + case 17: + result = "BOOLEAN"; + break; + case 27: + result = "DOUBLE PRECISION"; + break; + case 35: + result = "TIMESTAMP"; + break; + case 37: + result = "VARCHAR(" + size.ToString() + ")"; + break; + case 40: + result = "CSTRING(" + size.ToString() + ")"; + break; + case 45: + result = "BLOB_ID"; + break; + case 261: + result = "BLOB SUB_TYPE "; + switch (sub_type) + { + case 0: + result += "BINARY"; + break; + case 1: + result += "TEXT"; + break; + default: + result += sub_type.ToString(); + break; + } + break; + default: + result = ""; + break; + } + return result; + } + + private const string GetColumnsQuery = + @"SELECT RF.RDB$FIELD_NAME as COLUMN_NAME, + COALESCE(RF.RDB$DEFAULT_SOURCE, F.RDB$DEFAULT_SOURCE) as COLUMN_DEFAULT, + COALESCE(RF.RDB$NULL_FLAG, 0) as NOT_NULL, + F.rdb$description as COLUMN_COMMENT, 0 as AUTO_GENERATED, + ch.RDB$CHARACTER_SET_NAME as CHARACTER_SET_NAME, + Coalesce(F.RDB$FIELD_TYPE, 0) FIELD_TYPE, + case Coalesce(F.RDB$FIELD_TYPE, 0) + when 14 then cast((F.RDB$FIELD_LENGTH / CH.RDB$BYTES_PER_CHARACTER) as smallint) + when 37 then cast((F.RDB$FIELD_LENGTH / CH.RDB$BYTES_PER_CHARACTER) as smallint) + when 40 then cast((F.RDB$FIELD_LENGTH / CH.RDB$BYTES_PER_CHARACTER) as smallint) + else 0 + end as FIELD_SIZE, coalesce(F.RDB$FIELD_SUB_TYPE, 0) as FIELD_SUB_TYPE, + F.RDB$COMPUTED_SOURCE COMPUTED_SOURCE + FROM RDB$RELATION_FIELDS RF JOIN RDB$FIELDS F ON + F.RDB$FIELD_NAME = RF.RDB$FIELD_SOURCE LEFT OUTER JOIN RDB$CHARACTER_SETS CH ON + CH.RDB$CHARACTER_SET_ID = F.RDB$CHARACTER_SET_ID + WHERE RF.RDB$RELATION_NAME = '{0}' + AND COALESCE(RF.RDB$SYSTEM_FLAG, 0) = 0 + ORDER BY + RF.RDB$FIELD_POSITION"; + + private void GetColumns(DbConnection connection, IReadOnlyList tables, Func tableFilter) + { + foreach (var table in tables) + { + using (var command = connection.CreateCommand()) { - _connection.Open(); + command.CommandText = string.Format(GetColumnsQuery, table.Name); + using (var reader = command.ExecuteReader()) + { + while (reader.Read()) + { + var name = reader["COLUMN_NAME"].ToString().Trim(); + var defaultValue = reader["COLUMN_DEFAULT"].ToString().Trim(); + var nullable = !Convert.ToBoolean(reader["NOT_NULL"]); + var storeType = GetStoreType(Convert.ToInt32(reader["FIELD_TYPE"]), + Convert.ToInt32(reader["FIELD_SIZE"]), + Convert.ToInt32(reader["FIELD_SUB_TYPE"])); + var charset = reader["CHARACTER_SET_NAME"].ToString().Trim(); + var comment = reader["COLUMN_COMMENT"].ToString().Trim(); + + var is_computed = string.IsNullOrEmpty(reader["COMPUTED_SOURCE"].ToString().Trim()) ? false : true; + + var valueGenerated = ValueGenerated.Never; + + if (is_computed) + + { + valueGenerated = ValueGenerated.OnAddOrUpdate; + } + + var column = new DatabaseColumn + { + Table = table, + Name = name, + StoreType = storeType, + IsNullable = nullable, + DefaultValueSql = CreateDefaultValueString(defaultValue), + ValueGenerated = valueGenerated, + Comment = string.IsNullOrEmpty(comment) ? null : comment, + }; + + table.Columns.Add(column); + } + } } - try + } + } + + private string CreateDefaultValueString(string defaultValue) + { + if (defaultValue == null) + { + return null; + } + if (defaultValue.ToLowerInvariant().StartsWith("default ")) + { + return defaultValue.Remove(0, 8); + } + else + { + return null; + } + } + + private const string GetPrimaryQuery = + @"SELECT + i.rdb$index_name as INDEX_NAME, + sg.rdb$field_name as FIELD_NAME + FROM + RDB$INDICES i + LEFT JOIN rdb$index_segments sg on i.rdb$index_name = sg.rdb$index_name + LEFT JOIN rdb$relation_constraints rc on rc.rdb$index_name = I.rdb$index_name + WHERE + rc.rdb$constraint_type = 'PRIMARY KEY' + AND i.rdb$relation_name = '{0}' + ORDER BY sg.RDB$FIELD_POSITION"; + + private void GetPrimaryKeys(DbConnection connection, IReadOnlyList tables) + { + foreach (var x in tables) + { + using (var command = connection.CreateCommand()) { - _databaseModel.DatabaseName = _connection.Database; - _serverVersion = Data.Services.IBServerProperties.ParseServerVersion(_connection.ServerVersion); -#warning Finish - return _databaseModel; + command.CommandText = string.Format(GetPrimaryQuery, x.Name); + + using (var reader = command.ExecuteReader()) + { + DatabasePrimaryKey index = null; + while (reader.Read()) + { + if (index == null) + { + index = new DatabasePrimaryKey + { + Table = x, + Name = reader.GetString(0).Trim() + }; + } + index.Columns.Add(x.Columns.Single(y => y.Name == reader.GetString(1).Trim())); + x.PrimaryKey = index; + } + } } - finally + } + } + + private const string GetIndexesQuery = + @"SELECT DISTINCT I.rdb$index_name as INDEX_NAME, + COALESCE(I.rdb$unique_flag, 0) as IS_UNIQUE + FROM RDB$INDICES i LEFT JOIN rdb$index_segments sg on + i.rdb$index_name = sg.rdb$index_name LEFT JOIN rdb$relation_constraints rc on + rc.rdb$index_name = I.rdb$index_name + WHERE i.rdb$relation_name = '{0}' and + rc.rdb$constraint_type is null + ORDER BY INDEX_NAME, IS_UNIQUE"; + + // rdb$index_name maps to INDEX_NAME from above + private const string GetIndexFields = + @"SELECT rc.RDB$FIELD_NAME as COLUMNS + FROM rdb$INDEX_SEGMENTS rc + WHERE rc.rdb$index_name = '{0}'"; + + /// + /// Primary keys are handled as in , not here + /// + private void GetIndexes(DbConnection connection, IReadOnlyList tables, Func tableFilter) + { + foreach (var table in tables) + { + using (var command = connection.CreateCommand()) { - if (!connectionStartedOpen) + command.CommandText = string.Format(GetIndexesQuery, table.Name); + using (var reader = command.ExecuteReader()) { - _connection.Close(); + while (reader.Read()) + { + var index = new DatabaseIndex + { + Table = table, + Name = reader.GetString(0).Trim(), + IsUnique = reader.GetBoolean(1), + }; + using (var cCommand = connection.CreateCommand()) + { + cCommand.CommandText = string.Format(GetIndexFields, index.Name); + using (var fReader = cCommand.ExecuteReader()) + { + while (fReader.Read()) + { + index.Columns.Add(table.Columns.Single(y => y.Name == fReader.GetString(0).Trim())); + } + } + } + table.Indexes.Add(index); + } } } } + } + + private const string GetConstraintsQuery = + @"SELECT drs.rdb$constraint_name as CONSTRAINT_NAME, drs.RDB$RELATION_NAME as TABLE_NAME, + mrc.rdb$relation_name AS REFERENCED_TABLE_NAME, rc.RDB$DELETE_RULE as DELETE_RULE, + mrc.rdb$index_name mrc_index_name, drs.rdb$index_name drs_index_name, + drs.rdb$constraint_type CONSTRAINT_TYPE + FROM rdb$relation_constraints drs left JOIN rdb$ref_constraints rc ON + drs.rdb$constraint_name = rc.rdb$constraint_name left JOIN rdb$relation_constraints mrc ON + rc.rdb$const_name_uq = mrc.rdb$constraint_name + WHERE (drs.rdb$constraint_type = 'FOREIGN KEY' or + drs.rdb$constraint_type = 'UNIQUE') AND + drs.RDB$RELATION_NAME = '{0}' "; + + // mi maps to mrc_index_name and di maps to drs_index_name + private const string GetIndexSegments = + @"select di.rdb$field_name || '|' || mi.rdb$field_name as PAIRED_COLUMNS + from rdb$index_segments di join rdb$index_segments mi on + mi.RDB$FIELD_POSITION = di.RDB$FIELD_POSITION + where (mi.rdb$index_name = '{0}' or mi.rdb$index_name is null) and + di.rdb$index_name = '{1}'"; - void ResetState() + private const string GetUniqueSegments = + @"select di.rdb$field_name + from rdb$index_segments di + where di.rdb$index_name = '{0}'"; + + private void GetConstraints(DbConnection connection, IReadOnlyList tables) + { + foreach (var table in tables) { - _databaseModel = new DatabaseModel(); - _connection = null; - _serverVersion = null; + using (var command = connection.CreateCommand()) + { + command.CommandText = string.Format(GetConstraintsQuery, table.Name); + using (var reader = command.ExecuteReader()) + { + while (reader.Read()) + { + if (reader["CONSTRAINT_TYPE"].ToString().Trim() == "FOREIGN KEY") + { + var referencedTableName = reader.GetString(2).Trim(); + var referencedTable = tables.First(t => t.Name == referencedTableName); + var fkInfo = new DatabaseForeignKey { Name = reader.GetString(0).Trim(), OnDelete = ConvertToReferentialAction(reader.GetString(3).Trim()), Table = table, PrincipalTable = referencedTable }; + + using (var cCommand = connection.CreateCommand()) + { + cCommand.CommandText = string.Format(GetIndexSegments, reader.GetString(4).Trim(), reader.GetString(5).Trim()); + using (var fReader = cCommand.ExecuteReader()) + { + while (fReader.Read()) + { + fkInfo.Columns.Add(table.Columns.Single(y => + string.Equals(y.Name, fReader.GetString(0).Split('|')[0].Trim(), StringComparison.OrdinalIgnoreCase))); + fkInfo.PrincipalColumns.Add(fkInfo.PrincipalTable.Columns.Single(y => + string.Equals(y.Name, fReader.GetString(0).Split('|')[1].Trim(), StringComparison.OrdinalIgnoreCase))); + } + } + } + table.ForeignKeys.Add(fkInfo); + } + else + { + var unInfo = new DatabaseUniqueConstraint { Name = reader.GetString(0).Trim(), Table = table }; + + using (var cCommand = connection.CreateCommand()) + { + cCommand.CommandText = string.Format(GetUniqueSegments, reader.GetString(5).Trim()); + using (var fReader = cCommand.ExecuteReader()) + { + while (fReader.Read()) + { + unInfo.Columns.Add(table.Columns.Single(y => y.Name == fReader.GetString(0).Trim())); + } + } + } + table.UniqueConstraints.Add(unInfo); + } + } + } + } } } + + private static ReferentialAction? ConvertToReferentialAction(string onDeleteAction) + { + return onDeleteAction.ToUpperInvariant() switch + { + "RESTRICT" => ReferentialAction.Restrict, + "CASCADE" => ReferentialAction.Cascade, + "SET NULL" => ReferentialAction.SetNull, + "NO ACTION" => ReferentialAction.NoAction, + _ => null, + }; + } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Scaffolding/Internal/IBProviderConfigurationCodeGenerator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Scaffolding/Internal/IBProviderCodeGenerator.cs similarity index 51% rename from NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Scaffolding/Internal/IBProviderConfigurationCodeGenerator.cs rename to NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Scaffolding/Internal/IBProviderCodeGenerator.cs index eb94d36..7597a48 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Scaffolding/Internal/IBProviderConfigurationCodeGenerator.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Scaffolding/Internal/IBProviderCodeGenerator.cs @@ -18,25 +18,34 @@ //$Authors = Jiri Cincura (jiri@cincura.net) +using System; +using System.Reflection; +using InterBaseSql.EntityFrameworkCore.InterBase.Infrastructure; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; using Microsoft.EntityFrameworkCore.Scaffolding; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Scaffolding.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Scaffolding.Internal; + +public class IBProviderCodeGenerator : ProviderCodeGenerator { - public class IBProviderConfigurationCodeGenerator : ProviderCodeGenerator - { - public IBProviderConfigurationCodeGenerator(ProviderCodeGeneratorDependencies dependencies) - : base(dependencies) - { } + static readonly MethodInfo UseInterBaseMethodInfo + = typeof(IBDbContextOptionsBuilderExtensions).GetRequiredRuntimeMethod( + nameof(IBDbContextOptionsBuilderExtensions.UseInterBase), + typeof(DbContextOptionsBuilder), + typeof(string), + typeof(Action)); - public override MethodCallCodeFragment GenerateUseProvider(string connectionString, MethodCallCodeFragment providerOptions) - { - return new MethodCallCodeFragment( - nameof(IBDbContextOptionsBuilderExtensions.UseInterBase), - providerOptions == null - ? new object[] { connectionString } - : new object[] { connectionString, new NestedClosureCodeFragment("x", providerOptions) }); - } + public IBProviderCodeGenerator(ProviderCodeGeneratorDependencies dependencies) + : base(dependencies) + { } + + public override MethodCallCodeFragment GenerateUseProvider(string connectionString, MethodCallCodeFragment providerOptions) + { + return new MethodCallCodeFragment( + UseInterBaseMethodInfo, + providerOptions == null + ? new object[] { connectionString } + : new object[] { connectionString, new NestedClosureCodeFragment("x", providerOptions) }); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/Changelog.md new file mode 100644 index 0000000..8b76b0c --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/Changelog.md @@ -0,0 +1,27 @@ +#Changes for 7.13.6 (updated for EFCore 6.0 and to Fb 9.x) + +## added IBDateOnlyTypeMapping.cs, IBRelationalTransaction.cs, IBTimeOnlyTypeMapping.cs, IBTransactionFactory.cs, and IRelationalIBTransaction.cs + +# Changes for 7.10.2 + +## General - +* All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. + +## Common - +* Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Storage.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal +* Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. + +* All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. +* For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup + +## FbGuidTypeMapping.cs renamed to IBGuidTypeMapping.cs +* FbGuidTypeMapping now IBGuidTypeMapping +* GenerateNonNullSqlLiteral now calls EF_CHAR_TO_UUID + +## FbTypeMappingSource.cs renamed to IBTypeMappingSource.cs +* FbTypeMappingSource now IBTypeMappingSource +* IBTypeMappingsSource LongTypeMapping now maps to NUMERIC(18, 0) + +## NotSupportedInInterBase.cs added +* Special exception for unsupported features + diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/Changelog.txt b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/Changelog.txt deleted file mode 100644 index 991ef5c..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/Changelog.txt +++ /dev/null @@ -1,23 +0,0 @@ -Changes for 7.10.2 - - General - - All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. - - Common - - Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Storage.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal - Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. - - All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. - For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup - - FbGuidTypeMapping.cs renamed to IBGuidTypeMapping.cs - FbGuidTypeMapping now IBGuidTypeMapping - GenerateNonNullSqlLiteral now calls EF_CHAR_TO_UUID - - FbTypeMappingSource.cs renamed to IBTypeMappingSource.cs - FbTypeMappingSource now IBTypeMappingSource - IBTypeMappingsSource LongTypeMapping now maps to NUMERIC(18, 0) - - NotSupportedInInterBase.cs added - Sepecial execption for unsupported features - \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBBoolTypeMapping.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBBoolTypeMapping.cs index fcfa287..55d2039 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBBoolTypeMapping.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBBoolTypeMapping.cs @@ -20,24 +20,23 @@ using Microsoft.EntityFrameworkCore.Storage; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal -{ - public class IBBoolTypeMapping : BoolTypeMapping - { - public IBBoolTypeMapping() - : base("BOOLEAN", System.Data.DbType.Boolean) - { } +namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; - protected IBBoolTypeMapping(RelationalTypeMappingParameters parameters) - : base(parameters) - { } +public class IBBoolTypeMapping : BoolTypeMapping +{ + public IBBoolTypeMapping() + : base("BOOLEAN", System.Data.DbType.Boolean) + { } - protected override string GenerateNonNullSqlLiteral(object value) - { - return (bool)value ? "TRUE" : "FALSE"; - } + protected IBBoolTypeMapping(RelationalTypeMappingParameters parameters) + : base(parameters) + { } - protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters) - => new IBBoolTypeMapping(parameters); + protected override string GenerateNonNullSqlLiteral(object value) + { + return (bool)value ? "TRUE" : "FALSE"; } + + protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters) + => new IBBoolTypeMapping(parameters); } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBByteArrayTypeMapping.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBByteArrayTypeMapping.cs index fcca6a4..a8aa746 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBByteArrayTypeMapping.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBByteArrayTypeMapping.cs @@ -21,25 +21,24 @@ using InterBaseSql.Data.Common; using Microsoft.EntityFrameworkCore.Storage; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal -{ - public class IBByteArrayTypeMapping : ByteArrayTypeMapping - { - public IBByteArrayTypeMapping() - : base("BLOB SUB_TYPE BINARY", System.Data.DbType.Binary) - { } +namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; - protected IBByteArrayTypeMapping(RelationalTypeMappingParameters parameters) - : base(parameters) - { } +public class IBByteArrayTypeMapping : ByteArrayTypeMapping +{ + public IBByteArrayTypeMapping() + : base("BLOB SUB_TYPE 0", System.Data.DbType.Binary) + { } - protected override string GenerateNonNullSqlLiteral(object value) - { - var hex = ((byte[])value).ToHexString(); - return $"x'{hex}'"; - } + protected IBByteArrayTypeMapping(RelationalTypeMappingParameters parameters) + : base(parameters) + { } - protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters) - => new IBByteArrayTypeMapping(parameters); + protected override string GenerateNonNullSqlLiteral(object value) + { + var hex = ((byte[])value).ToHexString(); + return $"x'{hex}'"; } + + protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters) + => new IBByteArrayTypeMapping(parameters); } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBDatabaseCreator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBDatabaseCreator.cs index 1e7d3a9..ba22158 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBDatabaseCreator.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBDatabaseCreator.cs @@ -21,80 +21,161 @@ using System; using System.Threading; using System.Threading.Tasks; +using InterBaseSql.Data.Common; using InterBaseSql.Data.InterBaseClient; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; + +public class IBDatabaseCreator : RelationalDatabaseCreator { - public class IBDatabaseCreator : RelationalDatabaseCreator + readonly IIBRelationalConnection _connection; + readonly IRawSqlCommandBuilder _rawSqlCommandBuilder; + + public IBDatabaseCreator(RelationalDatabaseCreatorDependencies dependencies, IIBRelationalConnection connection, IRawSqlCommandBuilder rawSqlCommandBuilder) + : base(dependencies) { - readonly IIBRelationalConnection _connection; - readonly IRawSqlCommandBuilder _rawSqlCommandBuilder; + _connection = connection; + _rawSqlCommandBuilder = rawSqlCommandBuilder; + } - public IBDatabaseCreator(RelationalDatabaseCreatorDependencies dependencies, IIBRelationalConnection connection, IRawSqlCommandBuilder rawSqlCommandBuilder) - : base(dependencies) + public override void Create() + { + IBConnection.CreateDatabase(_connection.ConnectionString, pageSize: 16384); + + var designTimeModel = Dependencies.CurrentContext.Context.GetService().Model; + + var collation = designTimeModel.GetCollation(); + if (collation != null) { - _connection = connection; - _rawSqlCommandBuilder = rawSqlCommandBuilder; + Dependencies.ExecutionStrategy.Execute( + _connection, + connection => CreateAlterCollationCommand(collation).ExecuteNonQuery( + new RelationalCommandParameterObject( + connection, + null, + null, + Dependencies.CurrentContext.Context, + Dependencies.CommandLogger))); } + } - public override void Create() + //public override async Task CreateAsync(CancellationToken cancellationToken = default) + //{ + // await IBConnection.CreateDatabaseAsync(_connection.ConnectionString, pageSize: 16384, cancellationToken: cancellationToken).ConfigureAwait(false); + + // var designTimeModel = Dependencies.CurrentContext.Context.GetService().Model; + + // var collation = designTimeModel.GetCollation(); + // if (collation != null) + // { + // await Dependencies.ExecutionStrategy.ExecuteAsync( + // _connection, + // connection => CreateAlterCollationCommand(collation).ExecuteNonQueryAsync( + // new RelationalCommandParameterObject( + // connection, + // null, + // null, + // Dependencies.CurrentContext.Context, + // Dependencies.CommandLogger))).ConfigureAwait(false); + // } + //} + + public override void Delete() + { + IBConnection.ClearPool((IBConnection)_connection.DbConnection); + IBConnection.DropDatabase(_connection.ConnectionString); + } + + //public override Task DeleteAsync(CancellationToken cancellationToken = default) + //{ + // IBConnection.ClearPool((IBConnection)_connection.DbConnection); + // return IBConnection.DropDatabaseAsync(_connection.ConnectionString, cancellationToken); + //} + + public override bool Exists() + { + try { - IBConnection.CreateDatabase(_connection.ConnectionString); + _connection.Open(); + return true; } - - public override void Delete() + catch (IBException) { - IBConnection.ClearPool((IBConnection)_connection.DbConnection); - IBConnection.DropDatabase(_connection.ConnectionString); + return false; } + finally + { + _connection.Close(); + } + } - public override bool Exists() + //public override async Task ExistsAsync(CancellationToken cancellationToken = default) + //{ + // try + // { + // await _connection.OpenAsync(cancellationToken).ConfigureAwait(false); + // return true; + // } + // catch (IBException) + // { + // return false; + // } + // finally + // { + // await _connection.CloseAsync().ConfigureAwait(false); + // } + //} + + public override bool HasTables() + { + return Dependencies.ExecutionStrategy.Execute( + _connection, + connection => Convert.ToInt64(CreateHasTablesCommand().ExecuteScalar( + new RelationalCommandParameterObject( + connection, + null, + null, + Dependencies.CurrentContext.Context, + Dependencies.CommandLogger))) + != 0); + } + + //public override Task HasTablesAsync(CancellationToken cancellationToken = default) + //{ + // return Dependencies.ExecutionStrategy.ExecuteAsync( + // _connection, + // async (connection, ct) => Convert.ToInt64(await CreateHasTablesCommand().ExecuteScalarAsync( + // new RelationalCommandParameterObject( + // connection, + // null, + // null, + // Dependencies.CurrentContext.Context, + // Dependencies.CommandLogger), + // ct).ConfigureAwait(false)) + // != 0, + // cancellationToken); + //} + + IRelationalCommand CreateHasTablesCommand() + => _rawSqlCommandBuilder + .Build("SELECT COUNT(*) FROM rdb$relations WHERE COALESCE(rdb$system_flag, 0) = 0 AND rdb$view_blr IS NULL"); + + IRelationalCommand CreateAlterCollationCommand(string collation) + { + var command = _connection.DbConnection.CreateCommand(); + command.CommandText = "select coalesce(rdb$character_set_name, 'NONE') from rdb$database"; + string charSet = ""; + using (var reader = command.ExecuteReader()) { - try + while (reader.Read()) { - _connection.Open(); - return true; - } - catch (IBException) - { - return false; - } - finally - { - _connection.Close(); + charSet = reader.GetString(0); } } - - public override bool HasTables() - => Dependencies.ExecutionStrategyFactory.Create().Execute( - _connection, - connection => Convert.ToInt64(CreateHasTablesCommand().ExecuteScalar( - new RelationalCommandParameterObject( - connection, - null, - null, - Dependencies.CurrentContext.Context, - Dependencies.CommandLogger))) - != 0); - - public override Task HasTablesAsync(CancellationToken cancellationToken = default) - => Dependencies.ExecutionStrategyFactory.Create().ExecuteAsync( - _connection, - async (connection, ct) => Convert.ToInt64(await CreateHasTablesCommand().ExecuteScalarAsync( - new RelationalCommandParameterObject( - connection, - null, - null, - Dependencies.CurrentContext.Context, - Dependencies.CommandLogger), - ct)) - != 0, - cancellationToken); - - IRelationalCommand CreateHasTablesCommand() - => _rawSqlCommandBuilder - .Build("SELECT COUNT(*) FROM rdb$relations WHERE COALESCE(rdb$system_flag, 0) = 0 AND rdb$view_blr IS NULL"); + return _rawSqlCommandBuilder.Build($@"execute statement 'alter character set {charSet} set default collation {collation}'"); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBDateOnlyTypeMapping.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBDateOnlyTypeMapping.cs new file mode 100644 index 0000000..6dd0a17 --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBDateOnlyTypeMapping.cs @@ -0,0 +1,39 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt. + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * All Rights Reserved. + */ + +//$Authors = Jiri Cincura (jiri@cincura.net) + +using Microsoft.EntityFrameworkCore.Storage; + +namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; + +public class IBDateOnlyTypeMapping : DateOnlyTypeMapping +{ + public IBDateOnlyTypeMapping(string storeType) + : base(storeType) + { } + + protected IBDateOnlyTypeMapping(RelationalTypeMappingParameters parameters) + : base(parameters) + { } + + protected override string GenerateNonNullSqlLiteral(object value) + { + return $"CAST('{value:yyyy-MM-dd}' AS DATE)"; + } + + protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters) + => new IBDateOnlyTypeMapping(parameters); +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBDateTimeTypeMapping.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBDateTimeTypeMapping.cs index b291464..78d2d43 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBDateTimeTypeMapping.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBDateTimeTypeMapping.cs @@ -23,45 +23,44 @@ using InterBaseSql.Data.InterBaseClient; using Microsoft.EntityFrameworkCore.Storage; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; + +public class IBDateTimeTypeMapping : DateTimeTypeMapping { - public class IBDateTimeTypeMapping : DateTimeTypeMapping - { - readonly IBDbType _ibDbType; + readonly IBDbType _ibDbType; - public IBDateTimeTypeMapping(string storeType, IBDbType IBDbType) - : base(storeType) - { - _ibDbType = IBDbType; - } + public IBDateTimeTypeMapping(string storeType, IBDbType IBDbType) + : base(storeType) + { + _ibDbType = IBDbType; + } - protected IBDateTimeTypeMapping(RelationalTypeMappingParameters parameters, IBDbType IBDbType) - : base(parameters) - { - _ibDbType = IBDbType; - } + protected IBDateTimeTypeMapping(RelationalTypeMappingParameters parameters, IBDbType IBDbType) + : base(parameters) + { + _ibDbType = IBDbType; + } - protected override void ConfigureParameter(DbParameter parameter) - { - ((IBParameter)parameter).IBDbType = _ibDbType; - } + protected override void ConfigureParameter(DbParameter parameter) + { + ((IBParameter)parameter).IBDbType = _ibDbType; + } - protected override string GenerateNonNullSqlLiteral(object value) + protected override string GenerateNonNullSqlLiteral(object value) + { + switch (_ibDbType) { - switch (_ibDbType) - { - case IBDbType.TimeStamp: - return $"CAST('{value:yyyy-MM-dd HH:mm:ss}' AS TIMESTAMP)"; - case IBDbType.Date: - return $"CAST('{value:yyyy-MM-dd}' AS DATE)"; - case IBDbType.Time: - return $"CAST('{value:HH:mm:ss}' AS TIME)"; - default: - throw new ArgumentOutOfRangeException(nameof(_ibDbType), $"{nameof(_ibDbType)}={_ibDbType}"); - } + case IBDbType.TimeStamp: + return $"CAST('{value:yyyy-MM-dd HH:mm:ss.ffff}' AS TIMESTAMP)"; + case IBDbType.Date: + return $"CAST('{value:yyyy-MM-dd}' AS DATE)"; + case IBDbType.Time: + return $"CAST('{value:HH:mm:ss.ffff}' AS TIME)"; + default: + throw new ArgumentOutOfRangeException(nameof(_ibDbType), $"{nameof(_ibDbType)}={_ibDbType}"); } - - protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters) - => new IBDateTimeTypeMapping(parameters, _ibDbType); } + + protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters) + => new IBDateTimeTypeMapping(parameters, _ibDbType); } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBGuidTypeMapping.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBGuidTypeMapping.cs index b3adc6a..014a999 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBGuidTypeMapping.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBGuidTypeMapping.cs @@ -22,29 +22,29 @@ using InterBaseSql.Data.InterBaseClient; using Microsoft.EntityFrameworkCore.Storage; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; + +public class IBGuidTypeMapping : GuidTypeMapping { - public class IBGuidTypeMapping : GuidTypeMapping + public IBGuidTypeMapping() + : base("CHAR(16) CHARACTER SET OCTETS") + { } + + protected IBGuidTypeMapping(RelationalTypeMappingParameters parameters) + : base(parameters) + { } + + protected override void ConfigureParameter(DbParameter parameter) + { + ((IBParameter)parameter).IBDbType = IBDbType.Guid; + } + + protected override string GenerateNonNullSqlLiteral(object value) { - public IBGuidTypeMapping() - : base("CHAR(16) CHARACTER SET OCTETS") - { } - - protected IBGuidTypeMapping(RelationalTypeMappingParameters parameters) - : base(parameters) - { } - - protected override void ConfigureParameter(DbParameter parameter) - { - ((IBParameter)parameter).IBDbType = IBDbType.Guid; - } - - protected override string GenerateNonNullSqlLiteral(object value) - { - return $"EF_CHAR_TO_UUID('{value}')"; - } - - protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters) - => new IBGuidTypeMapping(parameters); + return $"EF_CHAR_TO_UUID('{value}')"; } + + protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters) + => new IBGuidTypeMapping(parameters); } + diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBRelationalConnection.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBRelationalConnection.cs index b457183..432dcbb 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBRelationalConnection.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBRelationalConnection.cs @@ -22,17 +22,14 @@ using InterBaseSql.Data.InterBaseClient; using Microsoft.EntityFrameworkCore.Storage; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal -{ - public class IBRelationalConnection : RelationalConnection, IIBRelationalConnection - { - public IBRelationalConnection(RelationalConnectionDependencies dependencies) - : base(dependencies) - { } +namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; - public override bool IsMultipleActiveResultSetsEnabled => true; +public class IBRelationalConnection : RelationalConnection, IIBRelationalConnection +{ + public IBRelationalConnection(RelationalConnectionDependencies dependencies) + : base(dependencies) + { } - protected override DbConnection CreateDbConnection() - => new IBConnection(ConnectionString); - } + protected override DbConnection CreateDbConnection() + => new IBConnection(ConnectionString); } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBRelationalTransaction.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBRelationalTransaction.cs new file mode 100644 index 0000000..f621de8 --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBRelationalTransaction.cs @@ -0,0 +1,32 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt. + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * All Rights Reserved. + */ + +//$Authors = Jiri Cincura (jiri@cincura.net) + +using System; +using System.Data.Common; +using InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Storage; + +namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; + +public class IBRelationalTransaction : RelationalTransaction, IIBRelationalTransaction +{ + public IBRelationalTransaction(IRelationalConnection connection, DbTransaction transaction, Guid transactionId, IDiagnosticsLogger logger, bool transactionOwned, ISqlGenerationHelper sqlGenerationHelper) + : base(connection, transaction, transactionId, logger, transactionOwned, sqlGenerationHelper) + { } +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBSqlGenerationHelper.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBSqlGenerationHelper.cs index efee4c9..c054cfe 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBSqlGenerationHelper.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBSqlGenerationHelper.cs @@ -22,45 +22,47 @@ using System.Text; using Microsoft.EntityFrameworkCore.Storage; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; + +public class IBSqlGenerationHelper : RelationalSqlGenerationHelper, IIBSqlGenerationHelper { - public class IBSqlGenerationHelper : RelationalSqlGenerationHelper, IIBSqlGenerationHelper + + public IBSqlGenerationHelper(RelationalSqlGenerationHelperDependencies dependencies) + : base(dependencies) { + } - public IBSqlGenerationHelper(RelationalSqlGenerationHelperDependencies dependencies) - : base(dependencies) - { - } + public virtual string StringLiteralQueryType(string s) + { + var length = MinimumStringQueryTypeLength(s); + EnsureStringLiteralQueryTypeLength(length); + return $"VARCHAR({length})"; + } - public virtual string StringLiteralQueryType(string s) - { - var length = MinimumStringQueryTypeLength(s); - EnsureStringQueryTypeLength(length); - return $"VARCHAR({length}) CHARACTER SET UTF8"; - } + public virtual string StringParameterQueryType(bool isUnicode) + { + var size = isUnicode ? IBTypeMappingSource.UnicodeVarcharMaxSize : IBTypeMappingSource.VarcharMaxSize; + return $"VARCHAR({size})"; + } - public virtual string StringParameterQueryType() - { - return $"VARCHAR({IBTypeMappingSource.VarcharMaxSize})"; - } + public virtual void GenerateBlockParameterName(StringBuilder builder, string name) + { + builder.Append(":").Append(name); + } - public virtual void GenerateBlockParameterName(StringBuilder builder, string name) - { - builder.Append(":").Append(name); - } + public string AlternativeStatementTerminator => "~"; - static int MinimumStringQueryTypeLength(string s) - { - var length = s?.Length ?? 0; - if (length == 0) - length = 1; - return length; - } + static int MinimumStringQueryTypeLength(string s) + { + var length = s?.Length ?? 0; + if (length == 0) + length = 1; + return length; + } - static void EnsureStringQueryTypeLength(int length) - { - if (length > IBTypeMappingSource.VarcharMaxSize) - throw new ArgumentOutOfRangeException(nameof(length)); - } + static void EnsureStringLiteralQueryTypeLength(int length) + { + if (length > IBTypeMappingSource.UnicodeVarcharMaxSize) + throw new ArgumentOutOfRangeException(nameof(length)); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBStringTypeMapping.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBStringTypeMapping.cs index a5cbe32..d4dd9a7 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBStringTypeMapping.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBStringTypeMapping.cs @@ -18,42 +18,42 @@ //$Authors = Jiri Cincura (jiri@cincura.net) +using System.Data; using System.Data.Common; using InterBaseSql.Data.InterBaseClient; using Microsoft.EntityFrameworkCore.Storage; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; + +public class IBStringTypeMapping : StringTypeMapping { - public class IBStringTypeMapping : StringTypeMapping + readonly IBDbType _ibDbType; + + public IBStringTypeMapping(string storeType, DbType dbType, IBDbType ibDbType, int? size = null, bool unicode = true) + : base(storeType, dbType, unicode: unicode, size: size) + { + _ibDbType = ibDbType; + } + + protected IBStringTypeMapping(RelationalTypeMappingParameters parameters, IBDbType IBDbType) + : base(parameters) + { + _ibDbType = IBDbType; + } + + protected override void ConfigureParameter(DbParameter parameter) + { + ((IBParameter)parameter).IBDbType = _ibDbType; + } + + protected override string GenerateNonNullSqlLiteral(object value) { - readonly IBDbType _ibDbType; - - public IBStringTypeMapping(string storeType, IBDbType IBDbType, int? size = null) - : base(storeType, unicode: true, size: size) - { - _ibDbType = IBDbType; - } - - protected IBStringTypeMapping(RelationalTypeMappingParameters parameters, IBDbType IBDbType) - : base(parameters) - { - _ibDbType = IBDbType; - } - - protected override void ConfigureParameter(DbParameter parameter) - { - ((IBParameter)parameter).IBDbType = _ibDbType; - } - - protected override string GenerateNonNullSqlLiteral(object value) - { - var svalue = value.ToString(); - return IsUnicode - ? $"_UTF8'{EscapeSqlLiteral(svalue)}'" - : $"'{EscapeSqlLiteral(svalue)}'"; - } - - protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters) - => new IBStringTypeMapping(parameters, _ibDbType); + var svalue = value.ToString(); + return IsUnicode + ? $"'{EscapeSqlLiteral(svalue)}'" + : $"'{EscapeSqlLiteral(svalue)}'"; } + + protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters) + => new IBStringTypeMapping(parameters, _ibDbType); } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBTimeOnlyTypeMapping.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBTimeOnlyTypeMapping.cs new file mode 100644 index 0000000..d74cafb --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBTimeOnlyTypeMapping.cs @@ -0,0 +1,39 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt. + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * All Rights Reserved. + */ + +//$Authors = Jiri Cincura (jiri@cincura.net) + +using Microsoft.EntityFrameworkCore.Storage; + +namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; + +public class IBTimeOnlyTypeMapping : TimeOnlyTypeMapping +{ + public IBTimeOnlyTypeMapping(string storeType) + : base(storeType) + { } + + protected IBTimeOnlyTypeMapping(RelationalTypeMappingParameters parameters) + : base(parameters) + { } + + protected override string GenerateNonNullSqlLiteral(object value) + { + return $"CAST('{value:HH:mm:ss.ffff}' AS TIME)"; + } + + protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters) + => new IBTimeOnlyTypeMapping(parameters); +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBTimeSpanTypeMapping.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBTimeSpanTypeMapping.cs index 7eadf57..57c818f 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBTimeSpanTypeMapping.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBTimeSpanTypeMapping.cs @@ -23,41 +23,40 @@ using InterBaseSql.Data.InterBaseClient; using Microsoft.EntityFrameworkCore.Storage; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; + +public class IBTimeSpanTypeMapping : TimeSpanTypeMapping { - public class IBTimeSpanTypeMapping : TimeSpanTypeMapping - { - readonly IBDbType _ibDbType; + readonly IBDbType _ibDbType; - public IBTimeSpanTypeMapping(string storeType, IBDbType IBDbType) - : base(storeType) - { - _ibDbType = IBDbType; - } + public IBTimeSpanTypeMapping(string storeType, IBDbType IBDbType) + : base(storeType) + { + _ibDbType = IBDbType; + } - protected IBTimeSpanTypeMapping(RelationalTypeMappingParameters parameters, IBDbType IBDbType) - : base(parameters) - { - _ibDbType = IBDbType; - } + protected IBTimeSpanTypeMapping(RelationalTypeMappingParameters parameters, IBDbType IBDbType) + : base(parameters) + { + _ibDbType = IBDbType; + } - protected override void ConfigureParameter(DbParameter parameter) - { - ((IBParameter)parameter).IBDbType = _ibDbType; - } + protected override void ConfigureParameter(DbParameter parameter) + { + ((IBParameter)parameter).IBDbType = _ibDbType; + } - protected override string GenerateNonNullSqlLiteral(object value) + protected override string GenerateNonNullSqlLiteral(object value) + { + switch (_ibDbType) { - switch (_ibDbType) - { - case IBDbType.Time: - return $"CAST('{value:HH:mm:ss}' AS TIME)"; - default: - throw new ArgumentOutOfRangeException(nameof(_ibDbType), $"{nameof(_ibDbType)}={_ibDbType}"); - } + case IBDbType.Time: + return $"CAST('{value:hh\\:mm\\:ss\\.ffff}' AS TIME)"; + default: + throw new ArgumentOutOfRangeException(nameof(_ibDbType), $"{nameof(_ibDbType)}={_ibDbType}"); } - - protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters) - => new IBTimeSpanTypeMapping(parameters, _ibDbType); } + + protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters) + => new IBTimeSpanTypeMapping(parameters, _ibDbType); } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBTransactionFactory.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBTransactionFactory.cs new file mode 100644 index 0000000..73d98a4 --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBTransactionFactory.cs @@ -0,0 +1,38 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt. + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * All Rights Reserved. + */ + +//$Authors = Jiri Cincura (jiri@cincura.net) + +using System; +using System.Data.Common; +using InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Storage; + +namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; + +class IBTransactionFactory : IRelationalTransactionFactory +{ + public IBTransactionFactory(RelationalTransactionFactoryDependencies dependencies) + { + Dependencies = dependencies; + } + + protected virtual RelationalTransactionFactoryDependencies Dependencies { get; } + + public RelationalTransaction Create(IRelationalConnection connection, DbTransaction transaction, Guid transactionId, IDiagnosticsLogger logger, bool transactionOwned) + => new IBRelationalTransaction(connection, transaction, transactionId, logger, transactionOwned, Dependencies.SqlGenerationHelper); +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBTypeMappingSource.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBTypeMappingSource.cs index 4ace8bb..8f69501 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBTypeMappingSource.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IBTypeMappingSource.cs @@ -25,174 +25,184 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; + +public class IBTypeMappingSource : RelationalTypeMappingSource { - public class IBTypeMappingSource : RelationalTypeMappingSource - { - public const int BinaryMaxSize = Int32.MaxValue; - public const int VarcharMaxSize = 32765 / 4; - public const int DefaultDecimalPrecision = 18; - public const int DefaultDecimalScale = 2; + public const int BinaryMaxSize = Int32.MaxValue; + public const int UnicodeVarcharMaxSize = VarcharMaxSize / 4; + public const int VarcharMaxSize = 32765; + public const int DefaultDecimalPrecision = 18; + public const int DefaultDecimalScale = 2; + + readonly IBBoolTypeMapping _boolean = new IBBoolTypeMapping(); - readonly IBBoolTypeMapping _boolean = new IBBoolTypeMapping(); + readonly ShortTypeMapping _smallint = new ShortTypeMapping("SMALLINT", DbType.Int16); + readonly IntTypeMapping _integer = new IntTypeMapping("INTEGER", DbType.Int32); + readonly LongTypeMapping _bigint = new LongTypeMapping("NUMERIC(18, 0)", DbType.Int64); - readonly ShortTypeMapping _smallint = new ShortTypeMapping("SMALLINT", DbType.Int16); - readonly IntTypeMapping _integer = new IntTypeMapping("INTEGER", DbType.Int32); - readonly LongTypeMapping _bigint = new LongTypeMapping("NUMERIC(18, 0)", DbType.Int64); + readonly IBStringTypeMapping _char = new IBStringTypeMapping("CHAR", DbType.StringFixedLength, IBDbType.Char); + readonly IBStringTypeMapping _varchar = new IBStringTypeMapping("VARCHAR", DbType.String, IBDbType.VarChar); + readonly IBStringTypeMapping _clob = new IBStringTypeMapping("BLOB SUB_TYPE TEXT", DbType.String, IBDbType.Text); - readonly IBStringTypeMapping _char = new IBStringTypeMapping("CHAR", IBDbType.Char); - readonly IBStringTypeMapping _varchar = new IBStringTypeMapping("VARCHAR", IBDbType.VarChar); - readonly IBStringTypeMapping _clob = new IBStringTypeMapping("BLOB SUB_TYPE TEXT", IBDbType.Text); + readonly IBByteArrayTypeMapping _binary = new IBByteArrayTypeMapping(); - readonly IBByteArrayTypeMapping _binary = new IBByteArrayTypeMapping(); + readonly FloatTypeMapping _float = new FloatTypeMapping("FLOAT"); + readonly DoubleTypeMapping _double = new DoubleTypeMapping("DOUBLE PRECISION"); + readonly DecimalTypeMapping _decimal = new DecimalTypeMapping($"DECIMAL({DefaultDecimalPrecision},{DefaultDecimalScale})"); - readonly FloatTypeMapping _float = new FloatTypeMapping("FLOAT"); - readonly DoubleTypeMapping _double = new DoubleTypeMapping("DOUBLE PRECISION"); - readonly DecimalTypeMapping _decimal = new DecimalTypeMapping($"DECIMAL({DefaultDecimalPrecision},{DefaultDecimalScale})"); + readonly IBDateTimeTypeMapping _timestamp = new IBDateTimeTypeMapping("TIMESTAMP", IBDbType.TimeStamp); + readonly IBDateTimeTypeMapping _date = new IBDateTimeTypeMapping("DATE", IBDbType.Date); + readonly IBDateOnlyTypeMapping _dateOnly = new IBDateOnlyTypeMapping("DATE"); - readonly IBDateTimeTypeMapping _timestamp = new IBDateTimeTypeMapping("TIMESTAMP", IBDbType.TimeStamp); - readonly IBDateTimeTypeMapping _date = new IBDateTimeTypeMapping("DATE", IBDbType.Date); + readonly IBTimeSpanTypeMapping _timeSpan = new IBTimeSpanTypeMapping("TIME", IBDbType.Time); + readonly IBTimeOnlyTypeMapping _timeOnly = new IBTimeOnlyTypeMapping("TIME"); - readonly IBTimeSpanTypeMapping _time = new IBTimeSpanTypeMapping("TIME", IBDbType.Time); - readonly IBGuidTypeMapping _guid = new IBGuidTypeMapping(); + readonly IBGuidTypeMapping _guid = new IBGuidTypeMapping(); - readonly Dictionary _storeTypeMappings; - readonly Dictionary _clrTypeMappings; - readonly HashSet _disallowedMappings; + readonly Dictionary _storeTypeMappings; + readonly Dictionary _clrTypeMappings; + readonly HashSet _disallowedMappings; - public IBTypeMappingSource(TypeMappingSourceDependencies dependencies, RelationalTypeMappingSourceDependencies relationalDependencies) - : base(dependencies, relationalDependencies) + public IBTypeMappingSource(TypeMappingSourceDependencies dependencies, RelationalTypeMappingSourceDependencies relationalDependencies) + : base(dependencies, relationalDependencies) + { + _storeTypeMappings = new Dictionary(StringComparer.OrdinalIgnoreCase) { - _storeTypeMappings = new Dictionary(StringComparer.OrdinalIgnoreCase) - { - { "BOOLEAN", _boolean }, - { "SMALLINT", _smallint }, - { "INTEGER", _integer }, - { "BIGINT", _bigint }, - { "CHAR", _char }, - { "VARCHAR", _varchar }, - { "BLOB SUB_TYPE TEXT", _clob }, - { "BLOB SUB_TYPE BINARY", _binary }, - { "FLOAT", _float }, - { "DOUBLE PRECISION", _double }, - { "DECIMAL", _decimal }, - { "TIMESTAMP", _timestamp }, - { "DATE", _date }, - { "TIME", _time }, - { "CHAR(16) CHARACTER SET OCTETS", _guid }, - }; - - _clrTypeMappings = new Dictionary() - { - { typeof(bool), _boolean }, - { typeof(short), _smallint }, - { typeof(int), _integer }, - { typeof(long), _bigint }, - { typeof(float), _float }, - { typeof(double), _double}, - { typeof(decimal), _decimal }, - { typeof(DateTime), _timestamp }, - { typeof(TimeSpan), _time }, - { typeof(Guid), _guid }, - }; - - _disallowedMappings = new HashSet(StringComparer.OrdinalIgnoreCase) - { - "CHARACTER", - "CHAR", - "VARCHAR", - "CHARACTER VARYING", - "CHAR VARYING", - }; - } + { "BOOLEAN", _boolean }, + { "SMALLINT", _smallint }, + { "INTEGER", _integer }, + { "BIGINT", _bigint }, + { "CHAR", _char }, + { "VARCHAR", _varchar }, + { "BLOB SUB_TYPE TEXT", _clob }, + { "BLOB SUB_TYPE BINARY", _binary }, + { "FLOAT", _float }, + { "DOUBLE PRECISION", _double }, + { "DECIMAL", _decimal }, + { "TIMESTAMP", _timestamp }, + { "DATE", _date }, + { "TIME", _timeSpan }, + { "CHAR(16) CHARACTER SET OCTETS", _guid }, + }; + + _clrTypeMappings = new Dictionary() + { + { typeof(bool), _boolean }, + { typeof(short), _smallint }, + { typeof(int), _integer }, + { typeof(long), _bigint }, + { typeof(float), _float }, + { typeof(double), _double}, + { typeof(decimal), _decimal }, + { typeof(DateTime), _timestamp }, + { typeof(TimeSpan), _timeSpan }, + { typeof(Guid), _guid }, + { typeof(DateOnly), _dateOnly }, + { typeof(TimeOnly), _timeOnly }, + }; + + _disallowedMappings = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "CHARACTER", + "CHAR", + "VARCHAR", + "CHARACTER VARYING", + "CHAR VARYING", + }; + } - protected override RelationalTypeMapping FindMapping(in RelationalTypeMappingInfo mappingInfo) + protected override RelationalTypeMapping FindMapping(in RelationalTypeMappingInfo mappingInfo) + { + return FindRawMapping(mappingInfo)?.Clone(mappingInfo) ?? base.FindMapping(mappingInfo); + } + + protected override void ValidateMapping(CoreTypeMapping mapping, IProperty property) + { + var relationalMapping = mapping as RelationalTypeMapping; + + if (_disallowedMappings.Contains(relationalMapping?.StoreType)) { - return FindRawMapping(mappingInfo)?.Clone(mappingInfo) ?? base.FindMapping(mappingInfo); + if (property == null) + { + throw new ArgumentException($"Data type '{relationalMapping.StoreType}' is not supported in this form. Either specify the length explicitly in the type name or remove the data type and use APIs such as HasMaxLength."); + } + + throw new ArgumentException($"Data type '{relationalMapping.StoreType}' for property '{property}' is not supported in this form. Either specify the length explicitly in the type name or remove the data type and use APIs such as HasMaxLength."); } + } - protected override void ValidateMapping(CoreTypeMapping mapping, IProperty property) - { - var relationalMapping = mapping as RelationalTypeMapping; + RelationalTypeMapping FindRawMapping(RelationalTypeMappingInfo mappingInfo) + { + var clrType = mappingInfo.ClrType; + var storeTypeName = mappingInfo.StoreTypeName; + var storeTypeNameBase = mappingInfo.StoreTypeNameBase; + var isUnicode = IsUnicode(mappingInfo.IsUnicode); - if (_disallowedMappings.Contains(relationalMapping?.StoreType)) + if (storeTypeName != null) + { + if (clrType == typeof(float) + && mappingInfo.Size != null + && mappingInfo.Size <= 24 + && (storeTypeNameBase.Equals("FLOAT", StringComparison.OrdinalIgnoreCase) + || storeTypeNameBase.Equals("DOUBLE PRECISION", StringComparison.OrdinalIgnoreCase))) { - if (property == null) - { - throw new ArgumentException($"Data type '{relationalMapping.StoreType}' is not supported in this form. Either specify the length explicitly in the type name or remove the data type and use APIs such as HasMaxLength."); - } + return _float; + } - throw new ArgumentException($"Data type '{relationalMapping.StoreType}' for property '{property}' is not supported in this form. Either specify the length explicitly in the type name or remove the data type and use APIs such as HasMaxLength."); + if (_storeTypeMappings.TryGetValue(storeTypeName, out var mapping) || _storeTypeMappings.TryGetValue(storeTypeNameBase, out mapping)) + { + return clrType == null || mapping.ClrType == clrType + ? mapping + : null; } } - RelationalTypeMapping FindRawMapping(RelationalTypeMappingInfo mappingInfo) + if (clrType != null) { - var clrType = mappingInfo.ClrType; - var storeTypeName = mappingInfo.StoreTypeName; - var storeTypeNameBase = mappingInfo.StoreTypeNameBase; + if (_clrTypeMappings.TryGetValue(clrType, out var mapping)) + { + return mapping; + } - if (storeTypeName != null) + if (clrType == typeof(string)) { - if (clrType == typeof(float) - && mappingInfo.Size != null - && mappingInfo.Size <= 24 - && (storeTypeNameBase.Equals("FLOAT", StringComparison.OrdinalIgnoreCase) - || storeTypeNameBase.Equals("DOUBLE PRECISION", StringComparison.OrdinalIgnoreCase))) - { - return _float; - } + var isFixedLength = mappingInfo.IsFixedLength == true; + var size = mappingInfo.Size ?? (mappingInfo.IsKeyOrIndex ? 256 : (int?)null); + var maxSize = isUnicode ? UnicodeVarcharMaxSize : VarcharMaxSize; - if (_storeTypeMappings.TryGetValue(storeTypeName, out var mapping) || _storeTypeMappings.TryGetValue(storeTypeNameBase, out mapping)) + if (size > maxSize) { - return clrType == null || mapping.ClrType == clrType - ? mapping - : null; + size = isFixedLength ? maxSize : (int?)null; } - } - if (clrType != null) - { - if (_clrTypeMappings.TryGetValue(clrType, out var mapping)) + if (size == null) { - return mapping; + return _clob; } - - if (clrType == typeof(string)) + else { - var isFixedLength = mappingInfo.IsFixedLength == true; - var size = mappingInfo.Size ?? (mappingInfo.IsKeyOrIndex ? 256 : (int?)null); - - if (size > VarcharMaxSize) - { - size = isFixedLength ? VarcharMaxSize : (int?)null; - } - - if (size == null) + if (!isFixedLength) { - return _clob; + return new IBStringTypeMapping($"VARCHAR({size})", DbType.String, IBDbType.VarChar, size, isUnicode); } else { - if (!isFixedLength) - { - return new IBStringTypeMapping($"VARCHAR({size})", IBDbType.VarChar, size); - } - else - { - return new IBStringTypeMapping($"CHAR({size})", IBDbType.Char, size); - } + return new IBStringTypeMapping($"CHAR({size})", DbType.StringFixedLength, IBDbType.Char, size, isUnicode); } } - - if (clrType == typeof(byte[])) - { - return _binary; - } } - return null; + if (clrType == typeof(byte[])) + { + return _binary; + } } + + return null; } + public static bool IsUnicode(RelationalTypeMapping mapping) => IsUnicode(mapping?.IsUnicode); + public static bool IsUnicode(RelationalTypeMappingInfo mappingInfo) => IsUnicode(mappingInfo.IsUnicode); + public static bool IsUnicode(bool? isUnicode) => isUnicode ?? true; } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IIBSqlGenerationHelper.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IIBSqlGenerationHelper.cs index 01480d5..016bd10 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IIBSqlGenerationHelper.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IIBSqlGenerationHelper.cs @@ -21,12 +21,12 @@ using System.Text; using Microsoft.EntityFrameworkCore.Storage; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; + +public interface IIBSqlGenerationHelper : ISqlGenerationHelper { - public interface IIBSqlGenerationHelper : ISqlGenerationHelper - { - string StringLiteralQueryType(string s); - string StringParameterQueryType(); - void GenerateBlockParameterName(StringBuilder builder, string name); - } + string StringLiteralQueryType(string s); + string StringParameterQueryType(bool isUnicode); + void GenerateBlockParameterName(StringBuilder builder, string name); + string AlternativeStatementTerminator { get; } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IRelationalIBConnection.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IRelationalIBConnection.cs index 5ec74e4..74c8bec 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IRelationalIBConnection.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IRelationalIBConnection.cs @@ -20,8 +20,7 @@ using Microsoft.EntityFrameworkCore.Storage; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal -{ - public interface IIBRelationalConnection : IRelationalConnection - { } -} +namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; + +public interface IIBRelationalConnection : IRelationalConnection +{ } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FiltersInheritanceIBFixture.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IRelationalIBTransaction.cs similarity index 57% rename from NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FiltersInheritanceIBFixture.cs rename to NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IRelationalIBTransaction.cs index 05451e5..210e088 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests/Query/FiltersInheritanceIBFixture.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Storage/Internal/IRelationalIBTransaction.cs @@ -3,25 +3,21 @@ * Developer's Public License Version 1.0 (the "License"); * you may not use this file except in compliance with the * License. You may obtain a copy of the License at - * https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt. + * https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt. * * Software distributed under the License is distributed on * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either * express or implied. See the License for the specific * language governing rights and limitations under the License. * - * The Initial Developer(s) of the Original Code are listed below. - * Portions created by Embarcadero are Copyright (C) Embarcadero. - * * All Rights Reserved. */ //$Authors = Jiri Cincura (jiri@cincura.net) -namespace InterBaseSql.EntityFrameworkCore.InterBase.FunctionalTests.Query -{ - public class FiltersInheritanceIBFixture : InheritanceIBFixture - { - protected override bool EnableFilters => true; - } -} +using Microsoft.EntityFrameworkCore.Storage; + +namespace InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal; + +public interface IIBRelationalTransaction +{ } \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/Changelog.md new file mode 100644 index 0000000..a7407d2 --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/Changelog.md @@ -0,0 +1,23 @@ +#Changes for 7.13.6 (updated for EFCore 6.0 and to Fb 9.x) + +## IBUpdateSqlGenerator.cs +* removed returning values from insert and updates since IB does not support this. + +# Changes for 7.10.2 + +## General - +* All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. + +## Common - +* Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Storage.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal +* Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. + +* All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. +* For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup + +## FbUpdateSqlGenerator.cs renamed to IBUpdateSqlGenerator.cs +* FbUpdateSqlGenerator now IBUpdateSqlGenerator +* AppendInsertOperation removed the anyread section as IB does not support RETURNING VALUES in insert statements +* AppendUpdateOperation removed the execute block that was used to get updated values. IB version does not update server side changes, user needs ot refresh te object in that situation +* AppendDeleteOperation removed the execute block that was used to determine rows affected. + diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/Changelog.txt b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/Changelog.txt deleted file mode 100644 index 286b442..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/Changelog.txt +++ /dev/null @@ -1,18 +0,0 @@ -Changes for 7.10.2 - - General - - All class names and name spaces are changed to be IB vs Fb or Fes. This was done so that both the Fb driver and this driver it is based on will not have any naming conflicts if both used in the same application. - - Common - - Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Storage.Internal to InterBaseSql.EntityFrameworkCore.InterBase.Storage.Internal - Use the IB named versions of classes and variable names where appropriate moved from fb to ib prefixes. - - All files renamed from FbXxxxx.cs to IBXxxxx.cs with the internal class matching that same change. - For example FbBackup.cs becomes IBBackup.cs and the class FbBackup is now IBBackup - - FbUpdateSqlGenerator.cs renamed to IBUpdateSqlGenerator.cs - FbUpdateSqlGenerator now IBUpdateSqlGenerator - AppendInsertOperation removed the anyread section as IB does not support RETURNING VALUES in insert statements - AppendUpdateOperation removed the execute block that was used to get updated values. IB version does not update server side changes, user needs ot refresh te object in that situation - AppendDeleteOperation removed the execute block that was used to determine rows affected. - diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/IBModificationCommandBatchFactory.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/IBModificationCommandBatchFactory.cs index 82ff16a..04dca0e 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/IBModificationCommandBatchFactory.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/IBModificationCommandBatchFactory.cs @@ -20,20 +20,19 @@ using Microsoft.EntityFrameworkCore.Update; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Update.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Update.Internal; + +public class IBModificationCommandBatchFactory : IModificationCommandBatchFactory { - public class IBModificationCommandBatchFactory : IModificationCommandBatchFactory - { - readonly ModificationCommandBatchFactoryDependencies _dependencies; + readonly ModificationCommandBatchFactoryDependencies _dependencies; - public IBModificationCommandBatchFactory(ModificationCommandBatchFactoryDependencies dependencies) - { - _dependencies = dependencies; - } + public IBModificationCommandBatchFactory(ModificationCommandBatchFactoryDependencies dependencies) + { + _dependencies = dependencies; + } - public ModificationCommandBatch Create() - { - return new IBServerModificationCommandBatch(_dependencies); - } + public ModificationCommandBatch Create() + { + return new IBServerModificationCommandBatch(_dependencies); } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/IBServerModificationCommandBatch.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/IBServerModificationCommandBatch.cs index cbbda80..3eeba5a 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/IBServerModificationCommandBatch.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/IBServerModificationCommandBatch.cs @@ -10,108 +10,106 @@ using Microsoft.EntityFrameworkCore.Diagnostics; using InterBaseSql.Data.Isql; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Update.Internal +namespace InterBaseSql.EntityFrameworkCore.InterBase.Update.Internal; + +class IBServerModificationCommandBatch : SingularModificationCommandBatch { - class IBServerModificationCommandBatch : SingularModificationCommandBatch - { - public IBServerModificationCommandBatch(ModificationCommandBatchFactoryDependencies dependencies) - : base(dependencies) { } + public IBServerModificationCommandBatch(ModificationCommandBatchFactoryDependencies dependencies) + : base(dependencies) { } - protected override int ConsumeResultSetWithoutPropagation(int commandIndex, Microsoft.EntityFrameworkCore.Storage.RelationalDataReader reader) + protected override int ConsumeResultSetWithoutPropagation(int commandIndex, Microsoft.EntityFrameworkCore.Storage.RelationalDataReader reader) + { + var expectedRowsAffected = 1; + while (++commandIndex < CommandResultSet.Count + && CommandResultSet[commandIndex - 1] == ResultSetMapping.NotLastInResultSet) { - var expectedRowsAffected = 1; - while (++commandIndex < CommandResultSet.Count - && CommandResultSet[commandIndex - 1] == ResultSetMapping.NotLastInResultSet) - { - Debug.Assert(!ModificationCommands[commandIndex].RequiresResultPropagation); + Debug.Assert(!ModificationCommands[commandIndex].RequiresResultPropagation); - expectedRowsAffected++; - } - using (var ibcommand = (IBCommand)reader.DbCommand) + expectedRowsAffected++; + } + using (var ibcommand = (IBCommand)reader.DbCommand) + { + // Inserts and Deletes will not have result sets. In that case just check the records affected property + if (!ibcommand.HasFields) { - // Inserts and Deletes will not have result sets. In that case just check the records affected property - if (!ibcommand.HasFields) + if(ibcommand.RecordsAffected != expectedRowsAffected) { - if(ibcommand.RecordsAffected != expectedRowsAffected) - { - ThrowAggregateUpdateConcurrencyException(commandIndex, expectedRowsAffected, ibcommand.RecordsAffected); - } + ThrowAggregateUpdateConcurrencyException(commandIndex, expectedRowsAffected, ibcommand.RecordsAffected); } - else - if (reader.Read()) - { - var rowsAffected = ibcommand.RecordsAffected; - if (rowsAffected != expectedRowsAffected) - { - ThrowAggregateUpdateConcurrencyException(commandIndex, expectedRowsAffected, rowsAffected); - } - } - else + } + else + if (reader.Read()) + { + var rowsAffected = ibcommand.RecordsAffected; + if (rowsAffected != expectedRowsAffected) { - ThrowAggregateUpdateConcurrencyException(commandIndex, 1, 0); + ThrowAggregateUpdateConcurrencyException(commandIndex, expectedRowsAffected, rowsAffected); } } - - return commandIndex; + else + { + ThrowAggregateUpdateConcurrencyException(commandIndex, 1, 0); + } } - protected override int ConsumeResultSetWithPropagation(int commandIndex, RelationalDataReader reader) + return commandIndex; + } + + protected override int ConsumeResultSetWithPropagation(int commandIndex, RelationalDataReader reader) + { + var rowsAffected = 0; + do { - var rowsAffected = 0; - do - { - var tableModification = ModificationCommands[commandIndex]; - Debug.Assert(tableModification.RequiresResultPropagation); + var tableModification = ModificationCommands[commandIndex]; + Debug.Assert(tableModification.RequiresResultPropagation); - if (!reader.Read()) + if (!reader.Read()) + { + var expectedRowsAffected = rowsAffected + 1; + while (++commandIndex < CommandResultSet.Count + && CommandResultSet[commandIndex - 1] == ResultSetMapping.NotLastInResultSet) { - var expectedRowsAffected = rowsAffected + 1; - while (++commandIndex < CommandResultSet.Count - && CommandResultSet[commandIndex - 1] == ResultSetMapping.NotLastInResultSet) - { - expectedRowsAffected++; - } - - ThrowAggregateUpdateConcurrencyException(commandIndex, expectedRowsAffected, rowsAffected); + expectedRowsAffected++; } - var valueBufferFactory = CreateValueBufferFactory(tableModification.ColumnModifications); - - tableModification.PropagateResults(valueBufferFactory.Create(reader.DbDataReader)); - rowsAffected++; + ThrowAggregateUpdateConcurrencyException(commandIndex, expectedRowsAffected, rowsAffected); } - while (++commandIndex < CommandResultSet.Count - && CommandResultSet[commandIndex - 1] == ResultSetMapping.NotLastInResultSet); - return commandIndex; + var valueBufferFactory = CreateValueBufferFactory(tableModification.ColumnModifications); + + tableModification.PropagateResults(valueBufferFactory.Create(reader.DbDataReader)); + rowsAffected++; } + while (++commandIndex < CommandResultSet.Count + && CommandResultSet[commandIndex - 1] == ResultSetMapping.NotLastInResultSet); - public override void Execute(IRelationalConnection connection) + return commandIndex; + } + + public override void Execute(IRelationalConnection connection) + { + var storeCommand = CreateStoreCommand(); + try { - var storeCommand = CreateStoreCommand(); - try + using (var dataReader = storeCommand.RelationalCommand.ExecuteReader( + new RelationalCommandParameterObject( + connection, + storeCommand.ParameterValues, + null, + Dependencies.CurrentContext.Context, + Dependencies.Logger))) { - using (var dataReader = storeCommand.RelationalCommand.ExecuteReader( - new RelationalCommandParameterObject( - connection, - storeCommand.ParameterValues, - null, - Dependencies.CurrentContext.Context, - Dependencies.Logger))) - { - Consume(dataReader); - } - } - catch (DbUpdateException) - { - throw; - } - catch (Exception ex) - { - throw new DbUpdateException(RelationalStrings.UpdateStoreException, ex); + Consume(dataReader); } } + catch (DbUpdateException) + { + throw; + } + catch (Exception ex) + { + throw new DbUpdateException(RelationalStrings.UpdateStoreException, ex); + } } - } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/IBUpdateSqlGenerator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/IBUpdateSqlGenerator.cs index 7471f26..dee755f 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/IBUpdateSqlGenerator.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/IBUpdateSqlGenerator.cs @@ -27,127 +27,152 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Update; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Update.Internal -{ +namespace InterBaseSql.EntityFrameworkCore.InterBase.Update.Internal; - public class IBUpdateSqlGenerator : UpdateSqlGenerator, IIBUpdateSqlGenerator - { - public IBUpdateSqlGenerator(UpdateSqlGeneratorDependencies dependencies) - : base(dependencies) - { } - protected override void AppendIdentityWhereCondition(StringBuilder commandStringBuilder, ColumnModification columnModification) - => throw new InvalidOperationException(); +public class IBUpdateSqlGenerator : UpdateSqlGenerator, IIBUpdateSqlGenerator +{ + public IBUpdateSqlGenerator(UpdateSqlGeneratorDependencies dependencies) + : base(dependencies) + { } - protected override void AppendRowsAffectedWhereCondition(StringBuilder commandStringBuilder, int expectedRowsAffected) - => throw new InvalidOperationException(); + protected override void AppendIdentityWhereCondition(StringBuilder commandStringBuilder, IColumnModification columnModification) + => throw new InvalidOperationException(); - protected override void AppendWhereAffectedClause(StringBuilder commandStringBuilder, IReadOnlyList operations) - { - commandStringBuilder - .AppendLine() - .Append("WHERE "); + protected override void AppendRowsAffectedWhereCondition(StringBuilder commandStringBuilder, int expectedRowsAffected) + => throw new InvalidOperationException(); - if (operations.Count > 0) - { - commandStringBuilder - .AppendJoin( - operations, (sb, v) => - { - if (v.IsKey) - { - AppendWhereCondition(sb, v, v.UseOriginalValueParameter); - } - }, " AND "); - } - } + public override ResultSetMapping AppendInsertOperation(StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition) + { + var result = ResultSetMapping.NoResultSet; + var name = command.TableName; + var operations = command.ColumnModifications; + var writeOperations = operations.Where(o => o.IsWrite).ToList(); + var readOperations = operations.Where(o => o.IsRead).ToList(); + var anyRead = readOperations.Any(); + AppendInsertCommandHeader(commandStringBuilder, name, null, writeOperations); + AppendValuesHeader(commandStringBuilder, writeOperations); + AppendValues(commandStringBuilder, name, null, writeOperations); +// if (anyRead) +// { +// commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); +// var keyOperations = operations.Where(o => o.IsKey).ToList(); - protected override ResultSetMapping AppendSelectAffectedCommand(StringBuilder commandStringBuilder, string name, string schema, - IReadOnlyList readOperations, IReadOnlyList conditionOperations, int commandPosition) - { +// result = AppendSelectCommand(commandStringBuilder, name, null, readOperations, keyOperations, commandPosition); +// throw new NotSupportedInInterBase("InterBase does not support returning values from an insert statement"); +// } + commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); + return result; + } - AppendSelectCommandHeader(commandStringBuilder, readOperations); - AppendFromClause(commandStringBuilder, name, schema); - // TODO: there is no notion of operator - currently all the where conditions check equality - AppendWhereAffectedClause(commandStringBuilder, conditionOperations); - commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); + public override ResultSetMapping AppendUpdateOperation(StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition) + { + var name = command.TableName; + var operations = command.ColumnModifications; + var writeOperations = operations.Where(o => o.IsWrite).ToList(); + var readOperations = operations.Where(o => o.IsRead).ToList(); + var conditionOperations = operations.Where(o => o.IsCondition).ToList(); + var anyRead = readOperations.Any(); + AppendUpdateCommandHeader(commandStringBuilder, name, null, writeOperations); + AppendWhereClause(commandStringBuilder, conditionOperations); + commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); + + //if (anyRead) + //{ + // var keyOperations = operations.Where(o => o.IsKey).ToList(); + + // return AppendSelectAffectedCommand(commandStringBuilder, name, null, readOperations, keyOperations, commandPosition); + //} + // commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); + return ResultSetMapping.NoResultSet; + } - return ResultSetMapping.LastInResultSet; - } + public override ResultSetMapping AppendDeleteOperation(StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition) + { + var name = command.TableName; + var operations = command.ColumnModifications; + var conditionOperations = operations.Where(o => o.IsCondition).ToList(); + var inputOperations = GenerateParameters(conditionOperations); + AppendDeleteCommandHeader(commandStringBuilder, name, null); + AppendWhereClause(commandStringBuilder, conditionOperations); + commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); + return ResultSetMapping.LastInResultSet; + } - public override ResultSetMapping AppendInsertOperation(StringBuilder commandStringBuilder, ModificationCommand command, int commandPosition) - { - var result = ResultSetMapping.NoResultSet; - var name = command.TableName; - var operations = command.ColumnModifications; - var writeOperations = operations.Where(o => o.IsWrite).ToList(); - var readOperations = operations.Where(o => o.IsRead).ToList(); - var anyRead = readOperations.Any(); - AppendInsertCommand(commandStringBuilder, name, null, writeOperations); - //if (anyRead) - //{ - // var keyOperations = operations.Where(o => o.IsKey).ToList(); - - // result = AppendSelectAffectedCommand(commandStringBuilder, name, null, readOperations, keyOperations, commandPosition); - // // throw new NotSupportedInInterBase("InterBase does not support returning values from an insert statement"); - //} - return result; - } + // workaround for GenerateBlockParameterName + protected override void AppendUpdateCommandHeader(StringBuilder commandStringBuilder, string name, string schema, IReadOnlyList operations) + { + commandStringBuilder.Append("UPDATE "); + SqlGenerationHelper.DelimitIdentifier(commandStringBuilder, name, schema); + commandStringBuilder.Append(" SET ") + .AppendJoin( + operations, + SqlGenerationHelper, + (sb, o, helper) => + { + helper.DelimitIdentifier(sb, o.ColumnName); + sb.Append(" = "); + if (!o.UseCurrentValueParameter) + { + AppendSqlLiteral(sb, o.Value, o.Property); + } + else + { + ((IIBSqlGenerationHelper)helper).GenerateBlockParameterName(sb, o.ParameterName); + } + }); + } - public override ResultSetMapping AppendUpdateOperation(StringBuilder commandStringBuilder, ModificationCommand command, int commandPosition) + // workaround for GenerateBlockParameterName + protected override void AppendWhereCondition(StringBuilder commandStringBuilder, IColumnModification columnModification, bool useOriginalValue) + { + SqlGenerationHelper.DelimitIdentifier(commandStringBuilder, columnModification.ColumnName); + if ((useOriginalValue ? columnModification.OriginalValue : columnModification.Value) == null) { - var name = command.TableName; - var operations = command.ColumnModifications; - var writeOperations = operations.Where(o => o.IsWrite).ToList(); - var readOperations = operations.Where(o => o.IsRead).ToList(); - var conditionOperations = operations.Where(o => o.IsCondition).ToList(); - var anyRead = readOperations.Any(); - AppendUpdateCommandHeader(commandStringBuilder, name, null, writeOperations); - AppendWhereClause(commandStringBuilder, conditionOperations); - commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); - - //if (anyRead) - //{ - // var keyOperations = operations.Where(o => o.IsKey).ToList(); - - // return AppendSelectAffectedCommand(commandStringBuilder, name, null, readOperations, keyOperations, commandPosition); - //} -// commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); - return ResultSetMapping.NoResultSet; + commandStringBuilder.Append(" IS NULL"); + return; } - public override ResultSetMapping AppendDeleteOperation(StringBuilder commandStringBuilder, ModificationCommand command, int commandPosition) + commandStringBuilder.Append(" = "); + if (!columnModification.UseCurrentValueParameter && !columnModification.UseOriginalValueParameter) { - var name = command.TableName; - var operations = command.ColumnModifications; - var conditionOperations = operations.Where(o => o.IsCondition).ToList(); - var inputOperations = GenerateParameters(conditionOperations); - AppendDeleteCommandHeader(commandStringBuilder, name, null); - AppendWhereClause(commandStringBuilder, conditionOperations); - commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); - return ResultSetMapping.LastInResultSet; + AppendSqlLiteral(commandStringBuilder, columnModification.Value, columnModification.Property); } - - string GetColumnType(ColumnModification column) + else { - return Dependencies.TypeMappingSource.GetMapping(column.Property).StoreType; + ((IIBSqlGenerationHelper)SqlGenerationHelper).GenerateBlockParameterName(commandStringBuilder, useOriginalValue ? columnModification.OriginalParameterName : columnModification.ParameterName); } + } + + string GetColumnType(IColumnModification column) + { + return Dependencies.TypeMappingSource.GetMapping(column.Property).StoreType; + } - IEnumerable<(string name, string type)> GenerateParameters(IEnumerable columns) + IEnumerable<(string name, string type)> GenerateParameters(IEnumerable columns) + { + foreach (var item in columns) { - foreach (var item in columns) + var type = GetColumnType(item); + if (item.UseCurrentValueParameter) { - var type = GetColumnType(item); - if (item.UseCurrentValueParameter) - { - yield return (item.ParameterName, type); - } - if (item.UseOriginalValueParameter) - { - yield return (item.OriginalParameterName, type); - } + yield return (item.ParameterName, type); + } + if (item.UseOriginalValueParameter) + { + yield return (item.OriginalParameterName, type); } } } + + /*override*/ + void AppendSqlLiteral(StringBuilder commandStringBuilder, object value, IProperty property) + { + var mapping = property != null + ? Dependencies.TypeMappingSource.FindMapping(property) + : null; + mapping ??= Dependencies.TypeMappingSource.GetMappingForValue(value); + commandStringBuilder.Append(mapping.GenerateProviderValueSqlLiteral(value)); + } } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/IIBUpdateSqlGenerator.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/IIBUpdateSqlGenerator.cs index cf53640..121a79d 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/IIBUpdateSqlGenerator.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/IIBUpdateSqlGenerator.cs @@ -20,8 +20,7 @@ using Microsoft.EntityFrameworkCore.Update; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Update.Internal -{ - public interface IIBUpdateSqlGenerator : IUpdateSqlGenerator - { } -} +namespace InterBaseSql.EntityFrameworkCore.InterBase.Update.Internal; + +public interface IIBUpdateSqlGenerator : IUpdateSqlGenerator +{ } diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/Changelog.md b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/Changelog.md new file mode 100644 index 0000000..b0ef27d --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/Changelog.md @@ -0,0 +1,8 @@ +#Changes for 7.13.6 (updated for EFCore 6.0 and to Fb 9.x) + +## added EnumerableMethods.cs + +# Changes for 7.10.2 + +## TranslatorsHelper.cs +* Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Utilities to InterBaseSql.EntityFrameworkCore.InterBase.Utilities diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/Changelog.txt b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/Changelog.txt deleted file mode 100644 index 2341c23..0000000 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/Changelog.txt +++ /dev/null @@ -1,3 +0,0 @@ -Changes for 7.10.2 - - TranslatorsHelper.cs Namespace changed from FirebirdSql.EntityFrameworkCore.Firebird.Utilities to InterBaseSql.EntityFrameworkCore.InterBase.Utilities diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/EnumerableMethods.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/EnumerableMethods.cs new file mode 100644 index 0000000..86f79ee --- /dev/null +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/EnumerableMethods.cs @@ -0,0 +1,728 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +#nullable enable + +namespace Microsoft.EntityFrameworkCore; + +internal static class EnumerableMethods +{ + //public static MethodInfo AggregateWithoutSeed { get; } + + //public static MethodInfo AggregateWithSeedWithoutSelector { get; } + + //public static MethodInfo AggregateWithSeedSelector { get; } + + public static MethodInfo All { get; } + + public static MethodInfo AnyWithoutPredicate { get; } + + public static MethodInfo AnyWithPredicate { get; } + + //public static Append { get; } + + public static MethodInfo AsEnumerable { get; } + + public static MethodInfo Cast { get; } + + public static MethodInfo Concat { get; } + + public static MethodInfo Contains { get; } + + //public static MethodInfo ContainsWithComparer { get; } + + public static MethodInfo CountWithoutPredicate { get; } + + public static MethodInfo CountWithPredicate { get; } + + public static MethodInfo DefaultIfEmptyWithoutArgument { get; } + + public static MethodInfo DefaultIfEmptyWithArgument { get; } + + public static MethodInfo Distinct { get; } + + //public static MethodInfo DistinctWithComparer { get; } + + public static MethodInfo ElementAt { get; } + + public static MethodInfo ElementAtOrDefault { get; } + + //public static MethodInfo Empty { get; } + + public static MethodInfo Except { get; } + + //public static MethodInfo ExceptWithComparer { get; } + + public static MethodInfo FirstWithoutPredicate { get; } + + public static MethodInfo FirstWithPredicate { get; } + + public static MethodInfo FirstOrDefaultWithoutPredicate { get; } + + public static MethodInfo FirstOrDefaultWithPredicate { get; } + + public static MethodInfo GroupByWithKeySelector { get; } + + public static MethodInfo GroupByWithKeyElementSelector { get; } + + //public static MethodInfo GroupByWithKeySelectorAndComparer { get; } + + //public static MethodInfo GroupByWithKeyElementSelectorAndComparer { get; } + + public static MethodInfo GroupByWithKeyElementResultSelector { get; } + + public static MethodInfo GroupByWithKeyResultSelector { get; } + + //public static MethodInfo GroupByWithKeyResultSelectorAndComparer { get; } + + //public static MethodInfo GroupByWithKeyElementResultSelectorAndComparer { get; } + + public static MethodInfo GroupJoin { get; } + + //public static MethodInfo GroupJoinWithComparer { get; } + + public static MethodInfo Intersect { get; } + + //public static MethodInfo IntersectWithComparer { get; } + + public static MethodInfo Join { get; } + + //public static MethodInfo JoinWithComparer { get; } + + public static MethodInfo LastWithoutPredicate { get; } + + public static MethodInfo LastWithPredicate { get; } + + public static MethodInfo LastOrDefaultWithoutPredicate { get; } + + public static MethodInfo LastOrDefaultWithPredicate { get; } + + public static MethodInfo LongCountWithoutPredicate { get; } + + public static MethodInfo LongCountWithPredicate { get; } + + public static MethodInfo MaxWithoutSelector { get; } + + public static MethodInfo MaxWithSelector { get; } + + public static MethodInfo MinWithoutSelector { get; } + + public static MethodInfo MinWithSelector { get; } + + public static MethodInfo OfType { get; } + + public static MethodInfo OrderBy { get; } + + //public static MethodInfo OrderByWithComparer { get; } + + public static MethodInfo OrderByDescending { get; } + + //public static MethodInfo OrderByDescendingWithComparer { get; } + + //public static MethodInfo Prepend { get; } + + //public static MethodInfo Range { get; } + + //public static MethodInfo Repeat { get; } + + public static MethodInfo Reverse { get; } + + public static MethodInfo Select { get; } + + public static MethodInfo SelectWithOrdinal { get; } + + public static MethodInfo SelectManyWithoutCollectionSelector { get; } + + //public static MethodInfo SelectManyWithoutCollectionSelectorOrdinal { get; } + + public static MethodInfo SelectManyWithCollectionSelector { get; } + + //public static MethodInfo SelectManyWithCollectionSelectorOrdinal { get; } + + public static MethodInfo SequenceEqual { get; } + + //public static MethodInfo SequenceEqualWithComparer { get; } + + public static MethodInfo SingleWithoutPredicate { get; } + + public static MethodInfo SingleWithPredicate { get; } + + public static MethodInfo SingleOrDefaultWithoutPredicate { get; } + + public static MethodInfo SingleOrDefaultWithPredicate { get; } + + public static MethodInfo Skip { get; } + + public static MethodInfo SkipWhile { get; } + + //public static MethodInfo SkipWhileOrdinal { get; } + + public static MethodInfo Take { get; } + + public static MethodInfo TakeWhile { get; } + + //public static MethodInfo TakeWhileOrdinal { get; } + + public static MethodInfo ThenBy { get; } + + //public static MethodInfo ThenByWithComparer { get; } + + public static MethodInfo ThenByDescending { get; } + + //public static MethodInfo ThenByDescendingWithComparer { get; } + + public static MethodInfo ToArray { get; } + + //public static MethodInfo ToDictionaryWithKeySelector { get; } + //public static MethodInfo ToDictionaryWithKeySelectorAndComparer { get; } + //public static MethodInfo ToDictionaryWithKeyElementSelector { get; } + //public static MethodInfo ToDictionaryWithKeyElementSelectorAndComparer { get; } + + //public static MethodInfo ToHashSet { get; } + //public static MethodInfo ToHashSetWithComparer { get; } + + public static MethodInfo ToList { get; } + + //public static MethodInfo ToLookupWithKeySelector { get; } + //public static MethodInfo ToLookupWithKeySelectorAndComparer { get; } + //public static MethodInfo ToLookupWithKeyElementSelector { get; } + //public static MethodInfo ToLookupWithKeyElementSelectorAndComparer { get; } + + public static MethodInfo Union { get; } + + //public static MethodInfo UnionWithComparer { get; } + + public static MethodInfo Where { get; } + + //public static MethodInfo WhereOrdinal { get; } + + //public static MethodInfo Zip { get; } + + private static Dictionary SumWithoutSelectorMethods { get; } + private static Dictionary SumWithSelectorMethods { get; } + private static Dictionary AverageWithoutSelectorMethods { get; } + private static Dictionary AverageWithSelectorMethods { get; } + private static Dictionary MaxWithoutSelectorMethods { get; } + private static Dictionary MaxWithSelectorMethods { get; } + private static Dictionary MinWithoutSelectorMethods { get; } + private static Dictionary MinWithSelectorMethods { get; } + + public static bool IsSumWithoutSelector(MethodInfo methodInfo) + => SumWithoutSelectorMethods.Values.Contains(methodInfo); + + public static bool IsSumWithSelector(MethodInfo methodInfo) + => methodInfo.IsGenericMethod + && SumWithSelectorMethods.Values.Contains(methodInfo.GetGenericMethodDefinition()); + + public static bool IsAverageWithoutSelector(MethodInfo methodInfo) + => AverageWithoutSelectorMethods.Values.Contains(methodInfo); + + public static bool IsAverageWithSelector(MethodInfo methodInfo) + => methodInfo.IsGenericMethod + && AverageWithSelectorMethods.Values.Contains(methodInfo.GetGenericMethodDefinition()); + + public static MethodInfo GetSumWithoutSelector(Type type) + => SumWithoutSelectorMethods[type]; + + public static MethodInfo GetSumWithSelector(Type type) + => SumWithSelectorMethods[type]; + + public static MethodInfo GetAverageWithoutSelector(Type type) + => AverageWithoutSelectorMethods[type]; + + public static MethodInfo GetAverageWithSelector(Type type) + => AverageWithSelectorMethods[type]; + + public static MethodInfo GetMaxWithoutSelector(Type type) + => MaxWithoutSelectorMethods.TryGetValue(type, out var method) + ? method + : MaxWithoutSelector; + + public static MethodInfo GetMaxWithSelector(Type type) + => MaxWithSelectorMethods.TryGetValue(type, out var method) + ? method + : MaxWithSelector; + + public static MethodInfo GetMinWithoutSelector(Type type) + => MinWithoutSelectorMethods.TryGetValue(type, out var method) + ? method + : MinWithoutSelector; + + public static MethodInfo GetMinWithSelector(Type type) + => MinWithSelectorMethods.TryGetValue(type, out var method) + ? method + : MinWithSelector; + + static EnumerableMethods() + { + var queryableMethodGroups = typeof(Enumerable) + .GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly) + .GroupBy(mi => mi.Name) + .ToDictionary(e => e.Key, l => l.ToList()); + + All = GetMethod( + nameof(Enumerable.All), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], typeof(bool)) + }); + + AnyWithoutPredicate = GetMethod( + nameof(Enumerable.Any), 1, + types => new[] { typeof(IEnumerable<>).MakeGenericType(types[0]) }); + + AnyWithPredicate = GetMethod( + nameof(Enumerable.Any), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], typeof(bool)) + }); + + AsEnumerable = GetMethod( + nameof(Enumerable.AsEnumerable), 1, + types => new[] { typeof(IEnumerable<>).MakeGenericType(types[0]) }); + + Cast = GetMethod(nameof(Enumerable.Cast), 1, types => new[] { typeof(IEnumerable) }); + + Concat = GetMethod( + nameof(Enumerable.Concat), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(IEnumerable<>).MakeGenericType(types[0]) + }); + + Contains = GetMethod( + nameof(Enumerable.Contains), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + types[0] + }); + + CountWithoutPredicate = GetMethod( + nameof(Enumerable.Count), 1, + types => new[] { typeof(IEnumerable<>).MakeGenericType(types[0]) }); + + CountWithPredicate = GetMethod( + nameof(Enumerable.Count), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], typeof(bool)) + }); + + DefaultIfEmptyWithoutArgument = GetMethod( + nameof(Enumerable.DefaultIfEmpty), 1, + types => new[] { typeof(IEnumerable<>).MakeGenericType(types[0]) }); + + DefaultIfEmptyWithArgument = GetMethod( + nameof(Enumerable.DefaultIfEmpty), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + types[0] + }); + + Distinct = GetMethod(nameof(Enumerable.Distinct), 1, types => new[] { typeof(IEnumerable<>).MakeGenericType(types[0]) }); + + ElementAt = GetMethod( + nameof(Enumerable.ElementAt), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(int) + }); + + ElementAtOrDefault = GetMethod( + nameof(Enumerable.ElementAtOrDefault), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(int) + }); + + Except = GetMethod( + nameof(Enumerable.Except), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(IEnumerable<>).MakeGenericType(types[0]) + }); + + FirstWithoutPredicate = GetMethod( + nameof(Enumerable.First), 1, types => new[] { typeof(IEnumerable<>).MakeGenericType(types[0]) }); + + FirstWithPredicate = GetMethod( + nameof(Enumerable.First), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], typeof(bool)) + }); + + FirstOrDefaultWithoutPredicate = GetMethod( + nameof(Enumerable.FirstOrDefault), 1, + types => new[] { typeof(IEnumerable<>).MakeGenericType(types[0]) }); + + FirstOrDefaultWithPredicate = GetMethod( + nameof(Enumerable.FirstOrDefault), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], typeof(bool)) + }); + + GroupByWithKeySelector = GetMethod( + nameof(Enumerable.GroupBy), 2, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], types[1]) + }); + + GroupByWithKeyElementSelector = GetMethod( + nameof(Enumerable.GroupBy), 3, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], types[1]), + typeof(Func<,>).MakeGenericType(types[0], types[2]) + }); + + GroupByWithKeyElementResultSelector = GetMethod( + nameof(Enumerable.GroupBy), 4, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], types[1]), + typeof(Func<,>).MakeGenericType(types[0], types[2]), + typeof(Func<,,>).MakeGenericType( + types[1], typeof(IEnumerable<>).MakeGenericType(types[2]), types[3]) + }); + + GroupByWithKeyResultSelector = GetMethod( + nameof(Enumerable.GroupBy), 3, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], types[1]), + typeof(Func<,,>).MakeGenericType( + types[1], typeof(IEnumerable<>).MakeGenericType(types[0]), types[2]) + }); + + GroupJoin = GetMethod( + nameof(Enumerable.GroupJoin), 4, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(IEnumerable<>).MakeGenericType(types[1]), + typeof(Func<,>).MakeGenericType(types[0], types[2]), + typeof(Func<,>).MakeGenericType(types[1], types[2]), + typeof(Func<,,>).MakeGenericType( + types[0], typeof(IEnumerable<>).MakeGenericType(types[1]), types[3]) + }); + + Intersect = GetMethod( + nameof(Enumerable.Intersect), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(IEnumerable<>).MakeGenericType(types[0]) + }); + + Join = GetMethod( + nameof(Enumerable.Join), 4, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(IEnumerable<>).MakeGenericType(types[1]), + typeof(Func<,>).MakeGenericType(types[0], types[2]), + typeof(Func<,>).MakeGenericType(types[1], types[2]), + typeof(Func<,,>).MakeGenericType(types[0], types[1], types[3]) + }); + + LastWithoutPredicate = GetMethod( + nameof(Enumerable.Last), 1, types => new[] { typeof(IEnumerable<>).MakeGenericType(types[0]) }); + + LastWithPredicate = GetMethod( + nameof(Enumerable.Last), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], typeof(bool)) + }); + + LastOrDefaultWithoutPredicate = GetMethod( + nameof(Enumerable.LastOrDefault), 1, + types => new[] { typeof(IEnumerable<>).MakeGenericType(types[0]) }); + + LastOrDefaultWithPredicate = GetMethod( + nameof(Enumerable.LastOrDefault), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], typeof(bool)) + }); + + LongCountWithoutPredicate = GetMethod( + nameof(Enumerable.LongCount), 1, + types => new[] { typeof(IEnumerable<>).MakeGenericType(types[0]) }); + + LongCountWithPredicate = GetMethod( + nameof(Enumerable.LongCount), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], typeof(bool)) + }); + + MaxWithoutSelector = GetMethod(nameof(Enumerable.Max), 1, types => new[] { typeof(IEnumerable<>).MakeGenericType(types[0]) }); + + MaxWithSelector = GetMethod( + nameof(Enumerable.Max), 2, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], types[1]) + }); + + MinWithoutSelector = GetMethod(nameof(Enumerable.Min), 1, types => new[] { typeof(IEnumerable<>).MakeGenericType(types[0]) }); + + MinWithSelector = GetMethod( + nameof(Enumerable.Min), 2, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], types[1]) + }); + + OfType = GetMethod(nameof(Enumerable.OfType), 1, types => new[] { typeof(IEnumerable) }); + + OrderBy = GetMethod( + nameof(Enumerable.OrderBy), 2, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], types[1]) + }); + + OrderByDescending = GetMethod( + nameof(Enumerable.OrderByDescending), 2, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], types[1]) + }); + + Reverse = GetMethod(nameof(Enumerable.Reverse), 1, types => new[] { typeof(IEnumerable<>).MakeGenericType(types[0]) }); + + Select = GetMethod( + nameof(Enumerable.Select), 2, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], types[1]) + }); + + SelectWithOrdinal = GetMethod( + nameof(Enumerable.Select), 2, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,,>).MakeGenericType(types[0], typeof(int), types[1]) + }); + + SelectManyWithoutCollectionSelector = GetMethod( + nameof(Enumerable.SelectMany), 2, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType( + types[0], typeof(IEnumerable<>).MakeGenericType(types[1])) + }); + + SelectManyWithCollectionSelector = GetMethod( + nameof(Enumerable.SelectMany), 3, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType( + types[0], typeof(IEnumerable<>).MakeGenericType(types[1])), + typeof(Func<,,>).MakeGenericType(types[0], types[1], types[2]) + }); + + SequenceEqual = GetMethod( + nameof(Enumerable.SequenceEqual), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(IEnumerable<>).MakeGenericType(types[0]) + }); + + SingleWithoutPredicate = GetMethod( + nameof(Enumerable.Single), 1, types => new[] { typeof(IEnumerable<>).MakeGenericType(types[0]) }); + + SingleWithPredicate = GetMethod( + nameof(Enumerable.Single), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], typeof(bool)) + }); + + SingleOrDefaultWithoutPredicate = GetMethod( + nameof(Enumerable.SingleOrDefault), 1, + types => new[] { typeof(IEnumerable<>).MakeGenericType(types[0]) }); + + SingleOrDefaultWithPredicate = GetMethod( + nameof(Enumerable.SingleOrDefault), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], typeof(bool)) + }); + + Skip = GetMethod( + nameof(Enumerable.Skip), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(int) + }); + + SkipWhile = GetMethod( + nameof(Enumerable.SkipWhile), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], typeof(bool)) + }); + + ToArray = GetMethod(nameof(Enumerable.ToArray), 1, types => new[] { typeof(IEnumerable<>).MakeGenericType(types[0]) }); + + ToList = GetMethod(nameof(Enumerable.ToList), 1, types => new[] { typeof(IEnumerable<>).MakeGenericType(types[0]) }); + + Take = GetMethod( + nameof(Enumerable.Take), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(int) + }); + + TakeWhile = GetMethod( + nameof(Enumerable.TakeWhile), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], typeof(bool)) + }); + + ThenBy = GetMethod( + nameof(Enumerable.ThenBy), 2, + types => new[] + { + typeof(IOrderedEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], types[1]) + }); + + ThenByDescending = GetMethod( + nameof(Enumerable.ThenByDescending), 2, + types => new[] + { + typeof(IOrderedEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], types[1]) + }); + + Union = GetMethod( + nameof(Enumerable.Union), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(IEnumerable<>).MakeGenericType(types[0]) + }); + + Where = GetMethod( + nameof(Enumerable.Where), 1, + types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], typeof(bool)) + }); + + var numericTypes = new[] + { + typeof(int), + typeof(int?), + typeof(long), + typeof(long?), + typeof(float), + typeof(float?), + typeof(double), + typeof(double?), + typeof(decimal), + typeof(decimal?) + }; + + AverageWithoutSelectorMethods = new Dictionary(); + AverageWithSelectorMethods = new Dictionary(); + MaxWithoutSelectorMethods = new Dictionary(); + MaxWithSelectorMethods = new Dictionary(); + MinWithoutSelectorMethods = new Dictionary(); + MinWithSelectorMethods = new Dictionary(); + SumWithoutSelectorMethods = new Dictionary(); + SumWithSelectorMethods = new Dictionary(); + + foreach (var type in numericTypes) + { + AverageWithoutSelectorMethods[type] = GetMethod( + nameof(Enumerable.Average), 0, types => new[] { typeof(IEnumerable<>).MakeGenericType(type) }); + AverageWithSelectorMethods[type] = GetMethod( + nameof(Enumerable.Average), 1, types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], type) + }); + MaxWithoutSelectorMethods[type] = GetMethod( + nameof(Enumerable.Max), 0, types => new[] { typeof(IEnumerable<>).MakeGenericType(type) }); + MaxWithSelectorMethods[type] = GetMethod( + nameof(Enumerable.Max), 1, types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], type) + }); + MinWithoutSelectorMethods[type] = GetMethod( + nameof(Enumerable.Min), 0, types => new[] { typeof(IEnumerable<>).MakeGenericType(type) }); + MinWithSelectorMethods[type] = GetMethod( + nameof(Enumerable.Min), 1, types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], type) + }); + SumWithoutSelectorMethods[type] = GetMethod( + nameof(Enumerable.Sum), 0, types => new[] { typeof(IEnumerable<>).MakeGenericType(type) }); + SumWithSelectorMethods[type] = GetMethod( + nameof(Enumerable.Sum), 1, types => new[] + { + typeof(IEnumerable<>).MakeGenericType(types[0]), + typeof(Func<,>).MakeGenericType(types[0], type) + }); + } + + MethodInfo GetMethod(string name, int genericParameterCount, Func parameterGenerator) + => queryableMethodGroups[name].Single( + mi => ((genericParameterCount == 0 && !mi.IsGenericMethod) + || (mi.IsGenericMethod && mi.GetGenericArguments().Length == genericParameterCount)) + && mi.GetParameters().Select(e => e.ParameterType).SequenceEqual( + parameterGenerator(mi.IsGenericMethod ? mi.GetGenericArguments() : Array.Empty()))); + } +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/SharedTypeExtensions.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/SharedTypeExtensions.cs index ec17f04..3b3947d 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/SharedTypeExtensions.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/SharedTypeExtensions.cs @@ -1,229 +1,665 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Linq.Expressions; using System.Reflection; +using System.Runtime.CompilerServices; +using System.Text; + +#nullable enable // ReSharper disable once CheckNamespace -namespace System +namespace System; + +[DebuggerStepThrough] +internal static class SharedTypeExtensions { - [DebuggerStepThrough] - internal static class SharedTypeExtensions + private static readonly Dictionary _builtInTypeNames = new() { - public static Type UnwrapNullableType(this Type type) => Nullable.GetUnderlyingType(type) ?? type; - - public static bool IsNullableType(this Type type) + { typeof(bool), "bool" }, + { typeof(byte), "byte" }, + { typeof(char), "char" }, + { typeof(decimal), "decimal" }, + { typeof(double), "double" }, + { typeof(float), "float" }, + { typeof(int), "int" }, + { typeof(long), "long" }, + { typeof(object), "object" }, + { typeof(sbyte), "sbyte" }, + { typeof(short), "short" }, + { typeof(string), "string" }, + { typeof(uint), "uint" }, + { typeof(ulong), "ulong" }, + { typeof(ushort), "ushort" }, + { typeof(void), "void" } + }; + + public static Type UnwrapNullableType(this Type type) + => Nullable.GetUnderlyingType(type) ?? type; + + public static bool IsNullableValueType(this Type type) + => type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>); + + public static bool IsNullableType(this Type type) + => !type.IsValueType || type.IsNullableValueType(); + + public static bool IsValidEntityType(this Type type) + => type.IsClass + && !type.IsArray; + + public static bool IsPropertyBagType(this Type type) + { + if (type.IsGenericTypeDefinition) { - var typeInfo = type.GetTypeInfo(); - - return !typeInfo.IsValueType - || (typeInfo.IsGenericType - && (typeInfo.GetGenericTypeDefinition() == typeof(Nullable<>))); + return false; } - public static Type MakeNullable(this Type type) - => type.IsNullableType() - ? type - : typeof(Nullable<>).MakeGenericType(type); + var types = GetGenericTypeImplementations(type, typeof(IDictionary<,>)); + return types.Any( + t => t.GetGenericArguments()[0] == typeof(string) + && t.GetGenericArguments()[1] == typeof(object)); + } - public static bool IsInteger(this Type type) - { - type = type.UnwrapNullableType(); + public static Type MakeNullable(this Type type, bool nullable = true) + => type.IsNullableType() == nullable + ? type + : nullable + ? typeof(Nullable<>).MakeGenericType(type) + : type.UnwrapNullableType(); + + public static bool IsNumeric(this Type type) + { + type = type.UnwrapNullableType(); + + return type.IsInteger() + || type == typeof(decimal) + || type == typeof(float) + || type == typeof(double); + } + + public static bool IsInteger(this Type type) + { + type = type.UnwrapNullableType(); + + return type == typeof(int) + || type == typeof(long) + || type == typeof(short) + || type == typeof(byte) + || type == typeof(uint) + || type == typeof(ulong) + || type == typeof(ushort) + || type == typeof(sbyte) + || type == typeof(char); + } + + public static bool IsSignedInteger(this Type type) + => type == typeof(int) + || type == typeof(long) + || type == typeof(short) + || type == typeof(sbyte); - return (type == typeof(int)) - || (type == typeof(long)) - || (type == typeof(short)) - || (type == typeof(byte)) - || (type == typeof(uint)) - || (type == typeof(ulong)) - || (type == typeof(ushort)) - || (type == typeof(sbyte)) - || (type == typeof(char)); + public static bool IsAnonymousType(this Type type) + => type.Name.StartsWith("<>", StringComparison.Ordinal) + && type.GetCustomAttributes(typeof(CompilerGeneratedAttribute), inherit: false).Length > 0 + && type.Name.Contains("AnonymousType"); + + public static bool IsTupleType(this Type type) + { + if (type == typeof(Tuple)) + { + return true; } - public static PropertyInfo GetAnyProperty(this Type type, string name) + if (type.IsGenericType) { - var props = type.GetRuntimeProperties().Where(p => p.Name == name).ToList(); - if (props.Count > 1) + var genericDefinition = type.GetGenericTypeDefinition(); + if (genericDefinition == typeof(Tuple<>) + || genericDefinition == typeof(Tuple<,>) + || genericDefinition == typeof(Tuple<,,>) + || genericDefinition == typeof(Tuple<,,,>) + || genericDefinition == typeof(Tuple<,,,,>) + || genericDefinition == typeof(Tuple<,,,,,>) + || genericDefinition == typeof(Tuple<,,,,,,>) + || genericDefinition == typeof(Tuple<,,,,,,,>) + || genericDefinition == typeof(Tuple<,,,,,,,>)) { - throw new AmbiguousMatchException(); + return true; } + } - return props.SingleOrDefault(); + return false; + } + + public static PropertyInfo? GetAnyProperty(this Type type, string name) + { + var props = type.GetRuntimeProperties().Where(p => p.Name == name).ToList(); + if (props.Count > 1) + { + throw new AmbiguousMatchException(); } - private static bool IsNonIntegerPrimitive(this Type type) + return props.SingleOrDefault(); + } + + public static MethodInfo GetRequiredMethod(this Type type, string name, params Type[] parameters) + { + var method = type.GetTypeInfo().GetMethod(name, parameters); + + if (method == null + && parameters.Length == 0) { - type = type.UnwrapNullableType(); + method = type.GetMethod(name); + } - return (type == typeof(bool)) - || (type == typeof(byte[])) - || (type == typeof(DateTime)) - || (type == typeof(DateTimeOffset)) - || (type == typeof(decimal)) - || (type == typeof(double)) - || (type == typeof(float)) - || (type == typeof(Guid)) - || (type == typeof(string)) - || (type == typeof(TimeSpan)) - || type.GetTypeInfo().IsEnum; + if (method == null) + { + throw new InvalidOperationException(); } - public static bool IsPrimitive(this Type type) - => type.IsInteger() || type.IsNonIntegerPrimitive(); + return method; + } + + public static PropertyInfo GetRequiredProperty(this Type type, string name) + => type.GetTypeInfo().GetProperty(name) + ?? throw new InvalidOperationException($"Could not find property '{name}' on type '{type}'"); + + public static FieldInfo GetRequiredDeclaredField(this Type type, string name) + => type.GetTypeInfo().GetDeclaredField(name) + ?? throw new InvalidOperationException($"Could not find field '{name}' on type '{type}'"); + + public static MethodInfo GetRequiredDeclaredMethod(this Type type, string name) + => type.GetTypeInfo().GetDeclaredMethod(name) + ?? throw new InvalidOperationException($"Could not find method '{name}' on type '{type}'"); - public static bool IsInstantiable(this Type type) => IsInstantiable(type.GetTypeInfo()); + public static MethodInfo GetRequiredDeclaredMethod(this Type type, string name, Func methodSelector) + => type.GetTypeInfo().GetDeclaredMethods(name).Single(methodSelector); - private static bool IsInstantiable(TypeInfo type) - => !type.IsAbstract - && !type.IsInterface - && (!type.IsGenericType || !type.IsGenericTypeDefinition); + public static PropertyInfo GetRequiredDeclaredProperty(this Type type, string name) + => type.GetTypeInfo().GetDeclaredProperty(name) + ?? throw new InvalidOperationException($"Could not find property '{name}' on type '{type}'"); - public static Type UnwrapEnumType(this Type type) + public static MethodInfo GetRequiredRuntimeMethod(this Type type, string name, params Type[] parameters) + => type.GetTypeInfo().GetRuntimeMethod(name, parameters) + ?? throw new InvalidOperationException($"Could not find method '{name}' on type '{type}'"); + + public static PropertyInfo GetRequiredRuntimeProperty(this Type type, string name) + => type.GetTypeInfo().GetRuntimeProperty(name) + ?? throw new InvalidOperationException($"Could not find property '{name}' on type '{type}'"); + + public static bool IsInstantiable(this Type type) + => !type.IsAbstract + && !type.IsInterface + && (!type.IsGenericType || !type.IsGenericTypeDefinition); + + public static Type UnwrapEnumType(this Type type) + { + var isNullable = type.IsNullableType(); + var underlyingNonNullableType = isNullable ? type.UnwrapNullableType() : type; + if (!underlyingNonNullableType.IsEnum) { - var isNullable = type.IsNullableType(); - var underlyingNonNullableType = isNullable ? type.UnwrapNullableType() : type; - if (!underlyingNonNullableType.GetTypeInfo().IsEnum) + return type; + } + + var underlyingEnumType = Enum.GetUnderlyingType(underlyingNonNullableType); + return isNullable ? MakeNullable(underlyingEnumType) : underlyingEnumType; + } + + public static Type GetSequenceType(this Type type) + { + var sequenceType = TryGetSequenceType(type); + if (sequenceType == null) + { + throw new ArgumentException($"The type {type.Name} does not represent a sequence"); + } + + return sequenceType; + } + + public static Type? TryGetSequenceType(this Type type) + => type.TryGetElementType(typeof(IEnumerable<>)) + ?? type.TryGetElementType(typeof(IAsyncEnumerable<>)); + + public static Type? TryGetElementType(this Type type, Type interfaceOrBaseType) + { + if (type.IsGenericTypeDefinition) + { + return null; + } + + var types = GetGenericTypeImplementations(type, interfaceOrBaseType); + + Type? singleImplementation = null; + foreach (var implementation in types) + { + if (singleImplementation == null) { - return type; + singleImplementation = implementation; } + else + { + singleImplementation = null; + break; + } + } - var underlyingEnumType = Enum.GetUnderlyingType(underlyingNonNullableType); - return isNullable ? MakeNullable(underlyingEnumType) : underlyingEnumType; + return singleImplementation?.GenericTypeArguments.FirstOrDefault(); + } + + public static bool IsCompatibleWith(this Type propertyType, Type fieldType) + { + if (propertyType.IsAssignableFrom(fieldType) + || fieldType.IsAssignableFrom(propertyType)) + { + return true; } - public static Type GetSequenceType(this Type type) + var propertyElementType = propertyType.TryGetSequenceType(); + var fieldElementType = fieldType.TryGetSequenceType(); + + return propertyElementType != null + && fieldElementType != null + && IsCompatibleWith(propertyElementType, fieldElementType); + } + + public static IEnumerable GetGenericTypeImplementations(this Type type, Type interfaceOrBaseType) + { + var typeInfo = type.GetTypeInfo(); + if (!typeInfo.IsGenericTypeDefinition) { - var sequenceType = TryGetSequenceType(type); - if (sequenceType == null) + var baseTypes = interfaceOrBaseType.GetTypeInfo().IsInterface + ? typeInfo.ImplementedInterfaces + : type.GetBaseTypes(); + foreach (var baseType in baseTypes) + { + if (baseType.IsGenericType + && baseType.GetGenericTypeDefinition() == interfaceOrBaseType) + { + yield return baseType; + } + } + + if (type.IsGenericType + && type.GetGenericTypeDefinition() == interfaceOrBaseType) { - // TODO: Add exception message - throw new ArgumentException(); + yield return type; } + } + } + + public static IEnumerable GetBaseTypes(this Type type) + { + var currentType = type.BaseType; - return sequenceType; + while (currentType != null) + { + yield return currentType; + + currentType = currentType.BaseType; } + } - public static Type TryGetSequenceType(this Type type) - => type.TryGetElementType(typeof(IEnumerable<>)) - ?? type.TryGetElementType(typeof(IAsyncEnumerable<>)); + public static List GetBaseTypesAndInterfacesInclusive(this Type type) + { + var baseTypes = new List(); + var typesToProcess = new Queue(); + typesToProcess.Enqueue(type); - public static Type TryGetElementType(this Type type, Type interfaceOrBaseType) + while (typesToProcess.Count > 0) { - if (!type.GetTypeInfo().IsGenericTypeDefinition) + type = typesToProcess.Dequeue(); + baseTypes.Add(type); + + if (type.IsNullableValueType()) { - var types = GetGenericTypeImplementations(type, interfaceOrBaseType).ToArray(); + typesToProcess.Enqueue(Nullable.GetUnderlyingType(type)!); + } - return types.Length == 1 ? types[0].GetTypeInfo().GenericTypeArguments.FirstOrDefault() : null; + if (type.IsConstructedGenericType) + { + typesToProcess.Enqueue(type.GetGenericTypeDefinition()); } - return null; + if (!type.IsGenericTypeDefinition + && !type.IsInterface) + { + if (type.BaseType != null) + { + typesToProcess.Enqueue(type.BaseType); + } + + foreach (var @interface in GetDeclaredInterfaces(type)) + { + typesToProcess.Enqueue(@interface); + } + } + } + + return baseTypes; + } + + public static IEnumerable GetTypesInHierarchy(this Type type) + { + var currentType = type; + + while (currentType != null) + { + yield return currentType; + + currentType = currentType.BaseType; } + } - public static IEnumerable GetGenericTypeImplementations(this Type type, Type interfaceOrBaseType) + public static IEnumerable GetDeclaredInterfaces(this Type type) + { + var interfaces = type.GetInterfaces(); + if (type.BaseType == typeof(object) + || type.BaseType == null) { - var typeInfo = type.GetTypeInfo(); - if (!typeInfo.IsGenericTypeDefinition) + return interfaces; + } + + return interfaces.Except(type.BaseType.GetInterfaces()); + } + + public static ConstructorInfo GetDeclaredConstructor(this Type type, Type[]? types) + { + types ??= Array.Empty(); + + return type.GetTypeInfo().DeclaredConstructors + .SingleOrDefault( + c => !c.IsStatic + && c.GetParameters().Select(p => p.ParameterType).SequenceEqual(types))!; + } + + public static IEnumerable GetPropertiesInHierarchy(this Type type, string name) + { + var currentType = type; + do + { + var typeInfo = currentType.GetTypeInfo(); + foreach (var propertyInfo in typeInfo.DeclaredProperties) { - return (interfaceOrBaseType.GetTypeInfo().IsInterface ? typeInfo.ImplementedInterfaces : type.GetBaseTypes()) - .Union(new[] { type }) - .Where( - t => t.GetTypeInfo().IsGenericType - && (t.GetGenericTypeDefinition() == interfaceOrBaseType)); + if (propertyInfo.Name.Equals(name, StringComparison.Ordinal) + && !(propertyInfo.GetMethod ?? propertyInfo.SetMethod)!.IsStatic) + { + yield return propertyInfo; + } } - return Enumerable.Empty(); + currentType = typeInfo.BaseType; } + while (currentType != null); + } - public static IEnumerable GetBaseTypes(this Type type) - { - type = type.GetTypeInfo().BaseType; + // Looking up the members through the whole hierarchy allows to find inherited private members. + public static IEnumerable GetMembersInHierarchy(this Type type) + { + var currentType = type; - while (type != null) + do + { + // Do the whole hierarchy for properties first since looking for fields is slower. + foreach (var propertyInfo in currentType.GetRuntimeProperties().Where(pi => !(pi.GetMethod ?? pi.SetMethod)!.IsStatic)) { - yield return type; + yield return propertyInfo; + } - type = type.GetTypeInfo().BaseType; + foreach (var fieldInfo in currentType.GetRuntimeFields().Where(f => !f.IsStatic)) + { + yield return fieldInfo; } + + currentType = currentType.BaseType; + } + while (currentType != null); + } + + public static IEnumerable GetMembersInHierarchy(this Type type, string name) + => type.GetMembersInHierarchy().Where(m => m.Name == name); + + private static readonly Dictionary _commonTypeDictionary = new() + { +#pragma warning disable IDE0034 // Simplify 'default' expression - default causes default(object) + { typeof(int), default(int) }, + { typeof(Guid), default(Guid) }, + { typeof(DateOnly), default(DateOnly) }, + { typeof(DateTime), default(DateTime) }, + { typeof(DateTimeOffset), default(DateTimeOffset) }, + { typeof(TimeOnly), default(TimeOnly) }, + { typeof(long), default(long) }, + { typeof(bool), default(bool) }, + { typeof(double), default(double) }, + { typeof(short), default(short) }, + { typeof(float), default(float) }, + { typeof(byte), default(byte) }, + { typeof(char), default(char) }, + { typeof(uint), default(uint) }, + { typeof(ushort), default(ushort) }, + { typeof(ulong), default(ulong) }, + { typeof(sbyte), default(sbyte) } +#pragma warning restore IDE0034 // Simplify 'default' expression + }; + + public static object? GetDefaultValue(this Type type) + { + if (!type.IsValueType) + { + return null; } - public static ConstructorInfo GetDeclaredConstructor(this Type type, Type[] types) + // A bit of perf code to avoid calling Activator.CreateInstance for common types and + // to avoid boxing on every call. This is about 50% faster than just calling CreateInstance + // for all value types. + return _commonTypeDictionary.TryGetValue(type, out var value) + ? value + : Activator.CreateInstance(type); + } + + public static IEnumerable GetConstructibleTypes(this Assembly assembly) + => assembly.GetLoadableDefinedTypes().Where( + t => !t.IsAbstract + && !t.IsGenericTypeDefinition); + + public static IEnumerable GetLoadableDefinedTypes(this Assembly assembly) + { + try + { + return assembly.DefinedTypes; + } + catch (ReflectionTypeLoadException ex) { - types = types ?? new Type[0]; + return ex.Types.Where(t => t != null).Select(IntrospectionExtensions.GetTypeInfo!); + } + } - return type.GetTypeInfo().DeclaredConstructors - .SingleOrDefault( - c => !c.IsStatic - && c.GetParameters().Select(p => p.ParameterType).SequenceEqual(types)); + public static bool IsQueryableType(this Type type) + { + if (type.IsGenericType + && type.GetGenericTypeDefinition() == typeof(IQueryable<>)) + { + return true; } - public static IEnumerable GetPropertiesInHierarchy(this Type type, string name) + return type.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IQueryable<>)); + } + + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + public static string DisplayName(this Type type, bool fullName = true, bool compilable = false) + { + var stringBuilder = new StringBuilder(); + ProcessType(stringBuilder, type, fullName, compilable); + return stringBuilder.ToString(); + } + + private static void ProcessType(StringBuilder builder, Type type, bool fullName, bool compilable) + { + if (type.IsGenericType) + { + var genericArguments = type.GetGenericArguments(); + ProcessGenericType(builder, type, genericArguments, genericArguments.Length, fullName, compilable); + } + else if (type.IsArray) + { + ProcessArrayType(builder, type, fullName, compilable); + } + else if (_builtInTypeNames.TryGetValue(type, out var builtInName)) + { + builder.Append(builtInName); + } + else if (!type.IsGenericParameter) { - do + if (compilable) { - var typeInfo = type.GetTypeInfo(); - var propertyInfo = typeInfo.GetDeclaredProperty(name); - if ((propertyInfo != null) - && !(propertyInfo.GetMethod ?? propertyInfo.SetMethod).IsStatic) + if (type.IsNested) { - yield return propertyInfo; + ProcessType(builder, type.DeclaringType!, fullName, compilable); + builder.Append('.'); + } + else if (fullName) + { + builder.Append(type.Namespace).Append('.'); } - type = typeInfo.BaseType; + + builder.Append(type.Name); + } + else + { + builder.Append(fullName ? type.FullName : type.Name); } - while (type != null); } + } - private static readonly Dictionary _commonTypeDictionary = new Dictionary + private static void ProcessArrayType(StringBuilder builder, Type type, bool fullName, bool compilable) + { + var innerType = type; + while (innerType.IsArray) { - { typeof(int), default(int) }, - { typeof(Guid), default(Guid) }, - { typeof(DateTime), default(DateTime) }, - { typeof(DateTimeOffset), default(DateTimeOffset) }, - { typeof(long), default(long) }, - { typeof(bool), default(bool) }, - { typeof(double), default(double) }, - { typeof(short), default(short) }, - { typeof(float), default(float) }, - { typeof(byte), default(byte) }, - { typeof(char), default(char) }, - { typeof(uint), default(uint) }, - { typeof(ushort), default(ushort) }, - { typeof(ulong), default(ulong) }, - { typeof(sbyte), default(sbyte) } - }; + innerType = innerType.GetElementType()!; + } - public static object GetDefaultValue(this Type type) + ProcessType(builder, innerType, fullName, compilable); + + while (type.IsArray) + { + builder.Append('['); + builder.Append(',', type.GetArrayRank() - 1); + builder.Append(']'); + type = type.GetElementType()!; + } + } + + private static void ProcessGenericType( + StringBuilder builder, + Type type, + Type[] genericArguments, + int length, + bool fullName, + bool compilable) + { + if (type.IsConstructedGenericType + && type.GetGenericTypeDefinition() == typeof(Nullable<>)) + { + ProcessType(builder, type.UnwrapNullableType(), fullName, compilable); + builder.Append('?'); + return; + } + + var offset = type.IsNested ? type.DeclaringType!.GetGenericArguments().Length : 0; + + if (compilable) + { + if (type.IsNested) + { + ProcessType(builder, type.DeclaringType!, fullName, compilable); + builder.Append('.'); + } + else if (fullName) + { + builder.Append(type.Namespace); + builder.Append('.'); + } + } + else { - if (!type.GetTypeInfo().IsValueType) + if (fullName) { - return null; + if (type.IsNested) + { + ProcessGenericType(builder, type.DeclaringType!, genericArguments, offset, fullName, compilable); + builder.Append('+'); + } + else + { + builder.Append(type.Namespace); + builder.Append('.'); + } } + } - // A bit of perf code to avoid calling Activator.CreateInstance for common types and - // to avoid boxing on every call. This is about 50% faster than just calling CreateInstance - // for all value types. - return _commonTypeDictionary.TryGetValue(type, out var value) - ? value - : Activator.CreateInstance(type); + var genericPartIndex = type.Name.IndexOf('`'); + if (genericPartIndex <= 0) + { + builder.Append(type.Name); + return; } - public static IEnumerable GetConstructableTypes(this Assembly assembly) - => assembly.GetLoadableDefinedTypes().Where( - t => !t.IsAbstract - && !t.IsGenericTypeDefinition); + builder.Append(type.Name, 0, genericPartIndex); + builder.Append('<'); - public static IEnumerable GetLoadableDefinedTypes(this Assembly assembly) + for (var i = offset; i < length; i++) { - try + ProcessType(builder, genericArguments[i], fullName, compilable); + if (i + 1 == length) { - return assembly.DefinedTypes; + continue; } - catch (ReflectionTypeLoadException ex) + + builder.Append(','); + if (!genericArguments[i + 1].IsGenericParameter) { - return ex.Types.Where(t => t != null).Select(IntrospectionExtensions.GetTypeInfo); + builder.Append(' '); } } + + builder.Append('>'); } + + public static IEnumerable GetNamespaces(this Type type) + { + if (_builtInTypeNames.ContainsKey(type)) + { + yield break; + } + + yield return type.Namespace!; + + if (type.IsGenericType) + { + foreach (var typeArgument in type.GenericTypeArguments) + { + foreach (var ns in typeArgument.GetNamespaces()) + { + yield return ns; + } + } + } + } + + public static ConstantExpression GetDefaultValueConstant(this Type type) + => (ConstantExpression)_generateDefaultValueConstantMethod + .MakeGenericMethod(type).Invoke(null, Array.Empty())!; + + private static readonly MethodInfo _generateDefaultValueConstantMethod = + typeof(SharedTypeExtensions).GetTypeInfo().GetDeclaredMethod(nameof(GenerateDefaultValueConstant))!; + + private static ConstantExpression GenerateDefaultValueConstant() + => Expression.Constant(default(TDefault), typeof(TDefault)); } \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/StringBuilderExtensions.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/StringBuilderExtensions.cs index f63a541..70a2cd3 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/StringBuilderExtensions.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/StringBuilderExtensions.cs @@ -1,90 +1,114 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Globalization; -namespace System.Text +#nullable enable + +namespace System.Text; + +internal static class StringBuilderExtensions { - internal static class StringBuilderExtensions - { - public static StringBuilder AppendJoin( - this StringBuilder stringBuilder, IEnumerable values, string separator = ", ") - => stringBuilder.AppendJoin(values, (sb, value) => sb.Append(value), separator); - - public static StringBuilder AppendJoin( - this StringBuilder stringBuilder, string separator, params string[] values) - => stringBuilder.AppendJoin(values, (sb, value) => sb.Append(value), separator); - - public static StringBuilder AppendJoin( - this StringBuilder stringBuilder, - IEnumerable values, - Action joinAction, - string separator = ", ") - { - var appended = false; + public static StringBuilder AppendJoin( + this StringBuilder stringBuilder, + IEnumerable values, + string separator = ", ") + => stringBuilder.AppendJoin(values, (sb, value) => sb.Append(value), separator); - foreach (var value in values) - { - joinAction(stringBuilder, value); - stringBuilder.Append(separator); - appended = true; - } + public static StringBuilder AppendJoin( + this StringBuilder stringBuilder, + string separator, + params string[] values) + => stringBuilder.AppendJoin(values, (sb, value) => sb.Append(value), separator); - if (appended) - { - stringBuilder.Length -= separator.Length; - } + public static StringBuilder AppendJoin( + this StringBuilder stringBuilder, + IEnumerable values, + Action joinAction, + string separator = ", ") + { + var appended = false; - return stringBuilder; + foreach (var value in values) + { + joinAction(stringBuilder, value); + stringBuilder.Append(separator); + appended = true; } - public static StringBuilder AppendJoin( - this StringBuilder stringBuilder, - IEnumerable values, - TParam param, - Action joinAction, - string separator = ", ") + if (appended) { - var appended = false; + stringBuilder.Length -= separator.Length; + } + + return stringBuilder; + } - foreach (var value in values) + public static StringBuilder AppendJoin( + this StringBuilder stringBuilder, + IEnumerable values, + Func joinFunc, + string separator = ", ") + { + var appended = false; + + foreach (var value in values) + { + if (joinFunc(stringBuilder, value)) { - joinAction(stringBuilder, value, param); stringBuilder.Append(separator); appended = true; } + } - if (appended) - { - stringBuilder.Length -= separator.Length; - } + if (appended) + { + stringBuilder.Length -= separator.Length; + } + + return stringBuilder; + } + + public static StringBuilder AppendJoin( + this StringBuilder stringBuilder, + IEnumerable values, + TParam param, + Action joinAction, + string separator = ", ") + { + var appended = false; - return stringBuilder; + foreach (var value in values) + { + joinAction(stringBuilder, value, param); + stringBuilder.Append(separator); + appended = true; } - public static StringBuilder AppendJoin( - this StringBuilder stringBuilder, - IEnumerable values, - TParam1 param1, - TParam2 param2, - Action joinAction, - string separator = ", ") + if (appended) { - var appended = false; + stringBuilder.Length -= separator.Length; + } - foreach (var value in values) - { - joinAction(stringBuilder, value, param1, param2); - stringBuilder.Append(separator); - appended = true; - } + return stringBuilder; + } - if (appended) + public static void AppendBytes(this StringBuilder builder, byte[] bytes) + { + builder.Append("'0x"); + + for (var i = 0; i < bytes.Length; i++) + { + if (i > 31) { - stringBuilder.Length -= separator.Length; + builder.Append("..."); + break; } - return stringBuilder; + builder.Append(bytes[i].ToString("X2", CultureInfo.InvariantCulture)); } + + builder.Append('\''); } -} +} \ No newline at end of file diff --git a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/TranslatorsHelper.cs b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/TranslatorsHelper.cs index c183cb7..76b9fd0 100644 --- a/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/TranslatorsHelper.cs +++ b/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Utilities/TranslatorsHelper.cs @@ -23,14 +23,13 @@ using System.Linq; using System.Reflection; -namespace InterBaseSql.EntityFrameworkCore.InterBase.Utilities +namespace InterBaseSql.EntityFrameworkCore.InterBase.Utilities; + +public class TranslatorsHelper { - public class TranslatorsHelper + public static IEnumerable GetTranslators() { - public static IEnumerable GetTranslators() - { - return Assembly.GetExecutingAssembly().GetTypes() - .Where(t => t.GetInterfaces().Any(i => i == typeof(TInterface))); - } + return Assembly.GetExecutingAssembly().GetTypes() + .Where(t => t.GetInterfaces().Any(i => i == typeof(TInterface))); } } diff --git a/NETProvider/Provider/src/Perf/Perf.csproj b/NETProvider/Provider/src/Perf/Perf.csproj index 25e894e..0f42dfc 100644 --- a/NETProvider/Provider/src/Perf/Perf.csproj +++ b/NETProvider/Provider/src/Perf/Perf.csproj @@ -19,6 +19,6 @@ - +