From eca280563221b0dc7a669a5d3b3115d90b108c85 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Fri, 24 Oct 2025 15:44:14 +0500 Subject: [PATCH 01/20] InfinityAliasTest changes --- .../PostgreSql/InfinityAliasTest.cs | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs b/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs index a3a321719..77fba5d8d 100644 --- a/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs +++ b/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs @@ -29,6 +29,8 @@ public sealed class InfinityAliasTest : SqlTest private TypeMapping dateTimeTypeMapping; private TypeMapping dateTimeOffsetTypeMapping; + private TimeSpan localTimezone; + protected override void CheckRequirements() { Require.ProviderIs(StorageProvider.PostgreSql); @@ -39,6 +41,7 @@ protected override void TestFixtureSetUp() base.TestFixtureSetUp(); var localZone = DateTimeOffset.Now.ToLocalTime().Offset; + localTimezone = localZone; var localZoneString = ((localZone < TimeSpan.Zero) ? "-" : "+") + localZone.ToString(@"hh\:mm"); var initConnectionCommand = Connection.CreateCommand($"SET TIME ZONE INTERVAL '{localZoneString}' HOUR TO MINUTE"); _ = initConnectionCommand.ExecuteNonQuery(); @@ -546,27 +549,39 @@ public void DateTimeOffsetMaxSelectDatePartDateTest() private void TestMaxDateTimeOffsetSelectDatePart(bool isOn) { + var overflowHappens = localTimezone > TimeSpan.Zero; + // There is overflow of year because of PostgreSQL time zone functionality + var overflowYearValue = overflowHappens ? 1 : 0; TestDateTimeOffsetPartExtraction(DateTimeOffsetMaxValueTable, SqlDateTimeOffsetPart.Year, - DateTimeOffset.MaxValue.Year + 1, - (isOn) ? DateTimeOffset.MaxValue.Year : DateTimeOffset.MaxValue.Year + 1, + DateTimeOffset.MaxValue.Year + overflowYearValue, + (isOn) ? DateTimeOffset.MaxValue.Year + overflowYearValue : DateTimeOffset.MaxValue.Year + overflowYearValue, isOn); // there is value overflow to 01 in case of no aliases + var serverSideMonths = (localTimezone > TimeSpan.Zero) ? 1 : 12; TestDateTimeOffsetPartExtraction(DateTimeOffsetMaxValueTable, SqlDateTimeOffsetPart.Month, - 1, - (isOn) ? DateTimeOffset.MaxValue.Month : 1, + serverSideMonths, + (isOn) ? serverSideMonths : serverSideMonths, isOn); + // there is value overflow to 01 in case of no aliases + var serverSideDays = (localTimezone > TimeSpan.Zero) ? 1 : 31; TestDateTimeOffsetPartExtraction(DateTimeOffsetMaxValueTable, SqlDateTimeOffsetPart.Day, - 1, - (isOn) ? DateTimeOffset.MaxValue.Day : 1, + serverSideDays, + (isOn) ? serverSideDays : serverSideDays, isOn); // timezone for DateTimeOffset.MaxValue value in postgre is set to 04:59:59.999999, at least when instance is in UTC+5 timezone + var serverSideHours = (localTimezone > TimeSpan.Zero) + ? localTimezone.Hours - 1 // positive zone + : (localTimezone < TimeSpan.Zero) + ? 24 + localTimezone.Hours // negative zone + : 0; // UTC + TestDateTimeOffsetPartExtraction(DateTimeOffsetMaxValueTable, SqlDateTimeOffsetPart.Hour, - 4, - (isOn) ? DateTimeOffset.MaxValue.Hour : 4, + serverSideHours, + (isOn) ? serverSideHours : serverSideHours, isOn); TestDateTimeOffsetPartExtraction(DateTimeOffsetMaxValueTable, SqlDateTimeOffsetPart.Minute, DateTimeOffset.MaxValue.Minute, @@ -686,7 +701,7 @@ private void TestDateTimeOffsetPartExtraction(string table, SqlDateTimeOffsetPar Assert.That(partValue, Is.Zero); } } - if (Driver.CoreServerInfo.ServerVersion < StorageProviderVersion.PostgreSql96) { + else if (Driver.CoreServerInfo.ServerVersion < StorageProviderVersion.PostgreSql96) { var partValue = reader.GetDouble(0); Assert.That(partValue, Is.Zero); } From 97e8520c5f818400a543fdb1904cf7b56c215d55 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Fri, 24 Oct 2025 17:11:49 +0500 Subject: [PATCH 02/20] InfinityAliasTest changes --- Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs b/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs index 77fba5d8d..ae8cd0627 100644 --- a/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs +++ b/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs @@ -576,8 +576,8 @@ private void TestMaxDateTimeOffsetSelectDatePart(bool isOn) var serverSideHours = (localTimezone > TimeSpan.Zero) ? localTimezone.Hours - 1 // positive zone : (localTimezone < TimeSpan.Zero) - ? 24 + localTimezone.Hours // negative zone - : 0; // UTC + ? 23 + localTimezone.Hours // negative zone + : 23; // UTC TestDateTimeOffsetPartExtraction(DateTimeOffsetMaxValueTable, SqlDateTimeOffsetPart.Hour, serverSideHours, From 7550a79e554e2a8856485f71c0b33658b7368431 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Fri, 24 Oct 2025 18:50:06 +0500 Subject: [PATCH 03/20] InfinityAliasTest: Fixed reading data --- Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs b/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs index ae8cd0627..97cdb5d58 100644 --- a/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs +++ b/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs @@ -613,7 +613,7 @@ private void TestDatePartExtraction(string table, SqlDatePart part, int expected Assert.That(partValue, Is.Zero); } } - if (Driver.CoreServerInfo.ServerVersion < StorageProviderVersion.PostgreSql96) { + else if (Driver.CoreServerInfo.ServerVersion < StorageProviderVersion.PostgreSql96) { var partValue = reader.GetDouble(0); Assert.That(partValue, Is.Zero); } @@ -657,7 +657,7 @@ private void TestDateTimePartExtraction(string table, SqlDateTimePart part, int Assert.That(partValue, Is.Zero); } } - if (Driver.CoreServerInfo.ServerVersion < StorageProviderVersion.PostgreSql96) { + else if (Driver.CoreServerInfo.ServerVersion < StorageProviderVersion.PostgreSql96) { var partValue = reader.GetDouble(0); Assert.That(partValue, Is.Zero); } From d2ef8c99df64ef52abdda755525d19c34a9558e4 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Fri, 24 Oct 2025 20:04:27 +0500 Subject: [PATCH 04/20] InfinityAliasTest changes --- Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs b/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs index 97cdb5d58..512bf7e57 100644 --- a/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs +++ b/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs @@ -471,8 +471,8 @@ private void TestMinDateTimeOffsetSelectDatePart(bool isOn) // timezone for DateTimeOffset.MinValue value in postgre is set to 04:02:33, at least when instance is in UTC+5 timezone TestDateTimeOffsetPartExtraction(DateTimeOffsetMinValueTable, SqlDateTimeOffsetPart.Hour, - 5, - isOn ? DateTimeOffset.MinValue.Hour : 5, + localTimezone.Hours, + isOn ? localTimezone.Hours : localTimezone.Hours, isOn); TestDateTimeOffsetPartExtraction(DateTimeOffsetMinValueTable, SqlDateTimeOffsetPart.Minute, DateTimeOffset.MinValue.Minute, From 309fdd438cf0f5cc1cfbef75cda00c3c15904084 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Sat, 25 Oct 2025 12:57:21 +0500 Subject: [PATCH 05/20] Add temp logging for Npgsql switches --- .../Sql.Drivers.PostgreSql/DriverFactory.cs | 60 +++++++++++++++++-- 1 file changed, 55 insertions(+), 5 deletions(-) diff --git a/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/DriverFactory.cs b/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/DriverFactory.cs index da9f3ca70..718c9bbcc 100644 --- a/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/DriverFactory.cs +++ b/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/DriverFactory.cs @@ -13,6 +13,7 @@ using Xtensive.Orm; using Xtensive.Sql.Info; using Xtensive.Sql.Drivers.PostgreSql.Resources; +using System.Reflection; namespace Xtensive.Sql.Drivers.PostgreSql { @@ -212,13 +213,56 @@ private static bool SetOrGetExistingLegacyTimeStampBehaviorSwitch(bool valueToSe private static bool GetSwitchValueOrSet(string switchName, bool valueToSet) { - if (!AppContext.TryGetSwitch(switchName, out var currentValue)) { - AppContext.SetSwitch(switchName, valueToSet); - return valueToSet; + using (var logWriter = CreateFile(switchName)) { + logWriter?.WriteLine($"GetSwitchValueOrSet called for switch '{switchName}' in attempt to set it to {valueToSet}"); + if (!AppContext.TryGetSwitch(switchName, out var currentValue)) { + logWriter?.WriteLine($"Switch '{switchName}' is not set to any value at the moment, setting it to {valueToSet}"); + AppContext.SetSwitch(switchName, valueToSet); + logWriter?.WriteLine($"Switch '{switchName}' is set to {valueToSet}"); + return valueToSet; + } + else { + logWriter?.WriteLine($"Switch '{switchName}' is already set to value {currentValue}. Setting to {valueToSet} skipped"); + return currentValue; + } } - else { - return currentValue; + } + + private static System.IO.TextWriter CreateFile(string switchName) + { + //F:\Projects\DataObjects.Net\Main Projects\do-public\new-master\_Build\tests\Debug\lib\net6.0 + var runningDirectory = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + if (!runningDirectory.Contains("_Build/tests") && !runningDirectory.Contains(@"_Build\tests")) { + return null; + } + + var dirInfo = new System.IO.DirectoryInfo(runningDirectory); + var dotnetName = dirInfo.Name; //net6.0 + var libFolder = dirInfo.Parent; // lib + var buildConfigFolder = libFolder.Parent;//Debug/Release + + var tempFilesFolder = buildConfigFolder.CreateSubdirectory(dotnetName); + var fileToWrite = System.IO.File.CreateText(System.IO.Path.Combine(tempFilesFolder.FullName, $"Switch_{switchName.Replace('.', '_')}_{Guid.NewGuid()}.log")); + return fileToWrite; + } + + private static System.IO.TextWriter CreateFile() + { + //F:\Projects\DataObjects.Net\Main Projects\do-public\new-master\_Build\tests\Debug\lib\net6.0 + var runningDirectory = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + if (!runningDirectory.Contains($"_Build{System.IO.Path.DirectorySeparatorChar}tests") + && !runningDirectory.Contains($"_Build{System.IO.Path.AltDirectorySeparatorChar}tests")) { + return null; } + + var dirInfo = new System.IO.DirectoryInfo(runningDirectory); + var dotnetName = dirInfo.Name; //net6.0 + var libFolder = dirInfo.Parent; // lib + var buildConfigFolder = libFolder.Parent;//Debug/Release + + var tempFilesFolder = buildConfigFolder.CreateSubdirectory(dotnetName); + var fileToWrite = System.IO.File.CreateText(System.IO.Path.Combine(tempFilesFolder.FullName, $"CtorCall_{Guid.NewGuid()}.log")); + return fileToWrite; } #endregion @@ -253,6 +297,12 @@ static DriverFactory() // DO NOT REPLACE method call with constant value when debugging, CHANGE THE PARAMETER VALUE. LegacyTimestamptBehaviorEnabled = SetOrGetExistingLegacyTimeStampBehaviorSwitch(valueToSet: false); + + using(var logWriter = CreateFile()) { + logWriter.WriteLine($"Driver factory was initialized with"); + logWriter.WriteLine($" InfinityAliasForDatesEnabled = {InfinityAliasForDatesEnabled}"); + logWriter.WriteLine($" LegacyTimestamptBehaviorEnabled = {LegacyTimestamptBehaviorEnabled}"); + } } } } From 53fd56962a58aee05f765bff78ecc22824e2178a Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Sat, 25 Oct 2025 13:03:35 +0500 Subject: [PATCH 06/20] Publish temp log files as wf artifacts --- .../workflows/reusable-storage-dependant-tests.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/reusable-storage-dependant-tests.yml b/.github/workflows/reusable-storage-dependant-tests.yml index 689ec66da..69779e80f 100644 --- a/.github/workflows/reusable-storage-dependant-tests.yml +++ b/.github/workflows/reusable-storage-dependant-tests.yml @@ -166,6 +166,18 @@ jobs: echo "reproc step outcome: ${{ steps.reprocessing.outcome }}" echo "complex step outcome: ${{ steps.complex_tests.outcome }}" + - name: Publish temp log files + if: | + (!cancelled() + timeout-minutes: 1 + uses: actions/upload-artifact@v4 + with: + name: DO_${{ github.ref_name }}_${{ github.run_number }}_on_${{ inputs.storage }}_${{inputs.target_framework}} + path: | + _Build/tests/${{ inputs.build_config }}/${{ inputs.target_framework }}/** + if-no-files-found: ignore + retention-days: 1 + - name: Publish raw test results as files if: | (!cancelled() && inputs.publish_raw_results) || failure() From d4955ca0b4cd9b901b00e9a1a96d0a31f4bd45d1 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Sat, 25 Oct 2025 13:04:14 +0500 Subject: [PATCH 07/20] Fix typo in comment --- .../Sql.Drivers.PostgreSql/DriverFactory.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/DriverFactory.cs b/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/DriverFactory.cs index 718c9bbcc..22e1e570f 100644 --- a/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/DriverFactory.cs +++ b/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/DriverFactory.cs @@ -269,8 +269,8 @@ private static System.IO.TextWriter CreateFile() static DriverFactory() { - // Starging from Npgsql 6.0 they broke compatibility by forcefully replacing - // DateTime.MinValue/MaxValue of parameters with -Infinity and Infinity values. + // Starting from Npgsql 6.0 they broke compatibility by forcefully replacing + // DateTime.MinValue/MaxValue in parameters with -Infinity and Infinity values. // This new "feature", though doesn't affect reading/writing of values and equality/inequality // filters, breaks some of operations such as parts extraction, default values for columns // (which are constants and declared on high levels of abstraction) and some others. From e83ab74d0ec22f70fe19d7733701de59c3a0be17 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Sat, 25 Oct 2025 13:05:21 +0500 Subject: [PATCH 08/20] Fix error in wf --- .github/workflows/reusable-storage-dependant-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reusable-storage-dependant-tests.yml b/.github/workflows/reusable-storage-dependant-tests.yml index 69779e80f..217727301 100644 --- a/.github/workflows/reusable-storage-dependant-tests.yml +++ b/.github/workflows/reusable-storage-dependant-tests.yml @@ -168,7 +168,7 @@ jobs: - name: Publish temp log files if: | - (!cancelled() + !cancelled() timeout-minutes: 1 uses: actions/upload-artifact@v4 with: From e0508e0e69213d5358a26e1d1f279a4920179d3c Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Sat, 25 Oct 2025 13:10:26 +0500 Subject: [PATCH 09/20] Try fix more problems with wf --- .github/workflows/reusable-storage-dependant-tests.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/reusable-storage-dependant-tests.yml b/.github/workflows/reusable-storage-dependant-tests.yml index 217727301..19f530bc0 100644 --- a/.github/workflows/reusable-storage-dependant-tests.yml +++ b/.github/workflows/reusable-storage-dependant-tests.yml @@ -172,9 +172,8 @@ jobs: timeout-minutes: 1 uses: actions/upload-artifact@v4 with: - name: DO_${{ github.ref_name }}_${{ github.run_number }}_on_${{ inputs.storage }}_${{inputs.target_framework}} - path: | - _Build/tests/${{ inputs.build_config }}/${{ inputs.target_framework }}/** + name: Log_PgsqlSwitches_${{ github.ref_name }}_${{ github.run_number }}_${{inputs.target_framework}} + path: _Build/tests/${{ inputs.build_config }}/${{ inputs.target_framework }}/** if-no-files-found: ignore retention-days: 1 From c57a9b3a8e7232c4d05f120a47be2b4c40c0ce9e Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Sat, 25 Oct 2025 13:27:11 +0500 Subject: [PATCH 10/20] Publish temp log files as artifacts --- .../workflows/reusable-storage-dependant-tests.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/reusable-storage-dependant-tests.yml b/.github/workflows/reusable-storage-dependant-tests.yml index 689ec66da..19f530bc0 100644 --- a/.github/workflows/reusable-storage-dependant-tests.yml +++ b/.github/workflows/reusable-storage-dependant-tests.yml @@ -166,6 +166,17 @@ jobs: echo "reproc step outcome: ${{ steps.reprocessing.outcome }}" echo "complex step outcome: ${{ steps.complex_tests.outcome }}" + - name: Publish temp log files + if: | + !cancelled() + timeout-minutes: 1 + uses: actions/upload-artifact@v4 + with: + name: Log_PgsqlSwitches_${{ github.ref_name }}_${{ github.run_number }}_${{inputs.target_framework}} + path: _Build/tests/${{ inputs.build_config }}/${{ inputs.target_framework }}/** + if-no-files-found: ignore + retention-days: 1 + - name: Publish raw test results as files if: | (!cancelled() && inputs.publish_raw_results) || failure() From da6a63bb5ef02ffb03d3d80bc1d86eeea1dc5c82 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Sat, 25 Oct 2025 13:28:40 +0500 Subject: [PATCH 11/20] Change default target framework for test --- .github/workflows/reusable-storage-dependant-tests.yml | 2 +- .github/workflows/reusable-storage-independant-tests.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reusable-storage-dependant-tests.yml b/.github/workflows/reusable-storage-dependant-tests.yml index 19f530bc0..7a090e0bf 100644 --- a/.github/workflows/reusable-storage-dependant-tests.yml +++ b/.github/workflows/reusable-storage-dependant-tests.yml @@ -16,7 +16,7 @@ on: target_framework: description: 'Target framework' required: true - default: 'net6.0' + default: 'net8.0' type: string specific_sha: description: 'Commit SHA to checkout' diff --git a/.github/workflows/reusable-storage-independant-tests.yml b/.github/workflows/reusable-storage-independant-tests.yml index 822032cc8..db928391a 100644 --- a/.github/workflows/reusable-storage-independant-tests.yml +++ b/.github/workflows/reusable-storage-independant-tests.yml @@ -11,7 +11,7 @@ on: target_framework: description: 'Target framework' required: true - default: 'net6.0' + default: 'net8.0' type: string test_output_verbosity: description: 'Verbosity for dotnet test command' From 43eda37201f302a2c768dae1108e00581fe87cce Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Sat, 25 Oct 2025 13:29:25 +0500 Subject: [PATCH 12/20] Change making final report condition --- .github/workflows/reusable-storage-independant-tests.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/reusable-storage-independant-tests.yml b/.github/workflows/reusable-storage-independant-tests.yml index db928391a..3322cebd6 100644 --- a/.github/workflows/reusable-storage-independant-tests.yml +++ b/.github/workflows/reusable-storage-independant-tests.yml @@ -123,10 +123,9 @@ jobs: - name: Make Final Test report if: | - (github.event_name == 'push' && steps.complex_tests.outcome != 'cancelled') - || (github.event_name == 'pull_request' && steps.complex_tests.outcome != 'cancelled') - || (github.event_name == 'workflow_dispatch' && steps.complex_tests.outcome != 'cancelled') - || steps.complex_tests.outcome == 'failure' + !cancelled() + && ((github.event_name == 'push') || (github.event_name == 'pull_request') || (github.event_name == 'workflow_dispatch') + || (steps.reprocessing.outcome == 'failure' || steps.complex_tests.outcome == 'failure')) timeout-minutes: 1 uses: dorny/test-reporter@v2.1.1 with: From f07899fa08e753356647922dc2c714ee21c90fc4 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Sat, 25 Oct 2025 13:53:36 +0500 Subject: [PATCH 13/20] Instance Identifier for driver factory --- .../Sql.Drivers.PostgreSql/DriverFactory.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/DriverFactory.cs b/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/DriverFactory.cs index 22e1e570f..2b2ff132b 100644 --- a/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/DriverFactory.cs +++ b/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/DriverFactory.cs @@ -24,6 +24,8 @@ public class DriverFactory : SqlDriverFactory { private const string DatabaseAndSchemaQuery = "select current_database(), current_schema()"; + private readonly static Guid InstanceIdentifier; + private readonly static bool InfinityAliasForDatesEnabled; private readonly static bool LegacyTimestamptBehaviorEnabled; @@ -242,7 +244,7 @@ private static System.IO.TextWriter CreateFile(string switchName) var buildConfigFolder = libFolder.Parent;//Debug/Release var tempFilesFolder = buildConfigFolder.CreateSubdirectory(dotnetName); - var fileToWrite = System.IO.File.CreateText(System.IO.Path.Combine(tempFilesFolder.FullName, $"Switch_{switchName.Replace('.', '_')}_{Guid.NewGuid()}.log")); + var fileToWrite = System.IO.File.CreateText(System.IO.Path.Combine(tempFilesFolder.FullName, $"Switch_{switchName.Replace('.', '_')}_{InstanceIdentifier}.log")); return fileToWrite; } @@ -261,7 +263,7 @@ private static System.IO.TextWriter CreateFile() var buildConfigFolder = libFolder.Parent;//Debug/Release var tempFilesFolder = buildConfigFolder.CreateSubdirectory(dotnetName); - var fileToWrite = System.IO.File.CreateText(System.IO.Path.Combine(tempFilesFolder.FullName, $"CtorCall_{Guid.NewGuid()}.log")); + var fileToWrite = System.IO.File.CreateText(System.IO.Path.Combine(tempFilesFolder.FullName, $"CtorCall_{InstanceIdentifier}.log")); return fileToWrite; } @@ -269,6 +271,8 @@ private static System.IO.TextWriter CreateFile() static DriverFactory() { + InstanceIdentifier = Guid.NewGuid(); + // Starting from Npgsql 6.0 they broke compatibility by forcefully replacing // DateTime.MinValue/MaxValue in parameters with -Infinity and Infinity values. // This new "feature", though doesn't affect reading/writing of values and equality/inequality From 40047d932dc616ec5fdd524dbb1121f9bc26ab90 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Sat, 25 Oct 2025 16:46:15 +0500 Subject: [PATCH 14/20] Remove unnecessary ternary operator --- .../PostgreSql/InfinityAliasTest.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs b/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs index 512bf7e57..316d0da27 100644 --- a/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs +++ b/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs @@ -472,7 +472,7 @@ private void TestMinDateTimeOffsetSelectDatePart(bool isOn) // timezone for DateTimeOffset.MinValue value in postgre is set to 04:02:33, at least when instance is in UTC+5 timezone TestDateTimeOffsetPartExtraction(DateTimeOffsetMinValueTable, SqlDateTimeOffsetPart.Hour, localTimezone.Hours, - isOn ? localTimezone.Hours : localTimezone.Hours, + localTimezone.Hours, isOn); TestDateTimeOffsetPartExtraction(DateTimeOffsetMinValueTable, SqlDateTimeOffsetPart.Minute, DateTimeOffset.MinValue.Minute, @@ -555,21 +555,21 @@ private void TestMaxDateTimeOffsetSelectDatePart(bool isOn) var overflowYearValue = overflowHappens ? 1 : 0; TestDateTimeOffsetPartExtraction(DateTimeOffsetMaxValueTable, SqlDateTimeOffsetPart.Year, DateTimeOffset.MaxValue.Year + overflowYearValue, - (isOn) ? DateTimeOffset.MaxValue.Year + overflowYearValue : DateTimeOffset.MaxValue.Year + overflowYearValue, + DateTimeOffset.MaxValue.Year + overflowYearValue, isOn); // there is value overflow to 01 in case of no aliases var serverSideMonths = (localTimezone > TimeSpan.Zero) ? 1 : 12; TestDateTimeOffsetPartExtraction(DateTimeOffsetMaxValueTable, SqlDateTimeOffsetPart.Month, serverSideMonths, - (isOn) ? serverSideMonths : serverSideMonths, + serverSideMonths, isOn); // there is value overflow to 01 in case of no aliases var serverSideDays = (localTimezone > TimeSpan.Zero) ? 1 : 31; TestDateTimeOffsetPartExtraction(DateTimeOffsetMaxValueTable, SqlDateTimeOffsetPart.Day, serverSideDays, - (isOn) ? serverSideDays : serverSideDays, + serverSideDays, isOn); // timezone for DateTimeOffset.MaxValue value in postgre is set to 04:59:59.999999, at least when instance is in UTC+5 timezone @@ -581,7 +581,7 @@ private void TestMaxDateTimeOffsetSelectDatePart(bool isOn) TestDateTimeOffsetPartExtraction(DateTimeOffsetMaxValueTable, SqlDateTimeOffsetPart.Hour, serverSideHours, - (isOn) ? serverSideHours : serverSideHours, + serverSideHours, isOn); TestDateTimeOffsetPartExtraction(DateTimeOffsetMaxValueTable, SqlDateTimeOffsetPart.Minute, DateTimeOffset.MaxValue.Minute, From 776de681849758a9e7f3f9b1cfb7f92a87393f8b Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Sun, 26 Oct 2025 11:25:08 +0500 Subject: [PATCH 15/20] Try make test to be suitable for any timezone --- .../DateTimeOffset/PartsExtractionTest.cs | 185 ++++++++---------- .../DateTimeOffsetBaseTest.cs | 4 +- 2 files changed, 87 insertions(+), 102 deletions(-) diff --git a/Orm/Xtensive.Orm.Tests/Linq/DateTimeAndDateTimeOffset/DateTimeOffset/PartsExtractionTest.cs b/Orm/Xtensive.Orm.Tests/Linq/DateTimeAndDateTimeOffset/DateTimeOffset/PartsExtractionTest.cs index b2d1c1806..9806a63bd 100644 --- a/Orm/Xtensive.Orm.Tests/Linq/DateTimeAndDateTimeOffset/DateTimeOffset/PartsExtractionTest.cs +++ b/Orm/Xtensive.Orm.Tests/Linq/DateTimeAndDateTimeOffset/DateTimeOffset/PartsExtractionTest.cs @@ -40,9 +40,17 @@ public void ExtractYearMinValueTest() public void ExtractYearMaxValueTest() { Require.ProviderIs(StorageProvider.PostgreSql); + ExecuteInsideSession((s) => { - RunTest(s, c => c.MaxValue.Year == DateTimeOffset.MaxValue.Year + 1); - RunWrongTest(s, c => c.MaxValue.Year == DateTimeOffset.MaxValue.AddYears(-1).Year); + var overflowHappens = localTimezone > TimeSpan.Zero; + if (overflowHappens) { + RunTest(s, c => c.MaxValue.Year == DateTimeOffset.MaxValue.Year + 1); + RunWrongTest(s, c => c.MaxValue.Year == DateTimeOffset.MaxValue.AddYears(-1).Year); + } + else { + RunTest(s, c => c.MaxValue.Year == DateTimeOffset.MaxValue.Year); + RunWrongTest(s, c => c.MaxValue.Year == DateTimeOffset.MaxValue.AddYears(-1).Year); + } }); } @@ -74,9 +82,17 @@ public void ExtractMonthMinValueTest() public void ExtractMonthMaxValueTest() { Require.ProviderIs(StorageProvider.PostgreSql); + ExecuteInsideSession((s) => { - RunTest(s, c => c.MaxValue.Month == DateTimeOffset.MaxValue.Month - 11); - RunWrongTest(s, c => c.MaxValue.Month == DateTimeOffset.MaxValue.AddMonths(-1).Month); + var overflowHappens = localTimezone > TimeSpan.Zero; + if (overflowHappens) { + RunTest(s, c => c.MaxValue.Month == 1); + RunWrongTest(s, c => c.MaxValue.Month == DateTimeOffset.MaxValue.AddMonths(-1).Month); + } + else { + RunTest(s, c => c.MaxValue.Month == 12); + RunWrongTest(s, c => c.MaxValue.Month == DateTimeOffset.MaxValue.AddMonths(-1).Month); + } }); } @@ -117,9 +133,17 @@ public void ExtractDayMaxValueTest() { Require.ProviderIs(StorageProvider.PostgreSql); ExecuteInsideSession((s) => { - // year overflow happens on server side because of timezone - RunTest(s, c => c.MaxValue.Day == 1); - RunWrongTest(s, c => c.MaxValue.Day == DateTimeOffset.MaxValue.AddDays(-1).Day); + var overflowHappens = localTimezone > TimeSpan.Zero; + if (overflowHappens) { + // year overflow happens on server side because of timezone + RunTest(s, c => c.MaxValue.Day == 1); + RunWrongTest(s, c => c.MaxValue.Day == DateTimeOffset.MaxValue.AddDays(-1).Day); + } + else { + // year overflow happens on server side because of timezone + RunTest(s, c => c.MaxValue.Day == 31); + RunWrongTest(s, c => c.MaxValue.Day == DateTimeOffset.MaxValue.AddDays(-1).Day); + } }); } @@ -151,48 +175,12 @@ public void ExtractHourMinValueTest() Require.ProviderIs(StorageProvider.PostgreSql); ExecuteInsideSession((s) => { - var service = s.Services.Get(); - - var command = service.CreateCommand(); - command.CommandText = $"SELECT COUNT(*) FROM public.\"MinMaxDateTimeOffsetEntity\" WHERE EXTRACT (HOUR FROM \"MinValue\") = 4"; - - using (command) - using (var reader = command.ExecuteReader()) { - - while (reader.Read()) { - var rowCount = reader.GetInt32(0); - Console.WriteLine($"Rows with HOUR 4 : {rowCount}"); - } - } - - command = service.CreateCommand(); - command.CommandText = $"SELECT COUNT(*) FROM public.\"MinMaxDateTimeOffsetEntity\" WHERE EXTRACT (HOUR FROM \"MinValue\") = 5"; - - using (command) - using (var reader = command.ExecuteReader()) { - - while (reader.Read()) { - var rowCount = reader.GetInt32(0); - Console.WriteLine($"Rows with HOUR 5 : {rowCount}"); - } - } - - command = service.CreateCommand(); - command.CommandText = $"SELECT (EXTRACT (TIMEZONE FROM \"MinValue\"))::integer FROM public.\"MinMaxDateTimeOffsetEntity\""; - - using (command) - using (var reader = command.ExecuteReader()) { - - while (reader.Read()) { - var timezoneInSeconds = reader.GetDouble(0); - Console.WriteLine($"Timezone : {TimeSpan.FromSeconds(timezoneInSeconds)}"); - } - } - }); - - - ExecuteInsideSession((s) => { - RunTest(s, c => c.MinValue.Hour == 5); + var serverSideHours = (localTimezone > TimeSpan.Zero) + ? localTimezone.Hours - 1 // positive zone + : (localTimezone < TimeSpan.Zero) + ? 23 + localTimezone.Hours // negative zone + : 23; // UTC + RunTest(s, c => c.MinValue.Hour == serverSideHours); RunWrongTest(s, c => c.MinValue.Hour == DateTimeOffset.MinValue.AddHours(1).Hour); }); } @@ -203,47 +191,12 @@ public void ExtractHourMaxValueTest() Require.ProviderIs(StorageProvider.PostgreSql); ExecuteInsideSession((s) => { - var service = s.Services.Get(); - - var command = service.CreateCommand(); - command.CommandText = $"SELECT COUNT(*) FROM public.\"MinMaxDateTimeOffsetEntity\" WHERE EXTRACT (HOUR FROM \"MaxValue\") = 4"; - - using (command) - using (var reader = command.ExecuteReader()) { - - while (reader.Read()) { - var rowCount = reader.GetInt32(0); - Console.WriteLine($"Rows with HOUR 4 : {rowCount}"); - } - } - - command = service.CreateCommand(); - command.CommandText = $"SELECT COUNT(*) FROM public.\"MinMaxDateTimeOffsetEntity\" WHERE EXTRACT (HOUR FROM \"MaxValue\") = 5"; - - using (command) - using (var reader = command.ExecuteReader()) { - - while (reader.Read()) { - var rowCount = reader.GetInt32(0); - Console.WriteLine($"Rows with HOUR 5 : {rowCount}"); - } - } - - command = service.CreateCommand(); - command.CommandText = $"SELECT (EXTRACT (TIMEZONE FROM \"MaxValue\"))::integer FROM public.\"MinMaxDateTimeOffsetEntity\""; - - using (command) - using (var reader = command.ExecuteReader()) { - - while (reader.Read()) { - var timezoneInSeconds = reader.GetDouble(0); - Console.WriteLine($"Timezone : {TimeSpan.FromSeconds(timezoneInSeconds)}"); - } - } - }); - - ExecuteInsideSession((s) => { - RunTest(s, c => c.MaxValue.Hour == 4); + var serverSideHours = (localTimezone > TimeSpan.Zero) + ? localTimezone.Hours - 1 // positive zone + : (localTimezone < TimeSpan.Zero) + ? 23 + localTimezone.Hours // negative zone + : 23; // UTC + RunTest(s, c => c.MaxValue.Hour == serverSideHours); RunWrongTest(s, c => c.MaxValue.Hour == DateTimeOffset.MaxValue.AddHours(-1).Hour); }); } @@ -380,11 +333,19 @@ public void ExtractDateMinValueTest() public void ExtractDateMaxValueTest() { Require.ProviderIs(StorageProvider.PostgreSql); - ExecuteInsideSession((s) => { - // overflow of year from 9999-12-31 to 10000-01-01 because of how postgre works with timezones - // can't validate - RunWrongTest(s, c => c.MaxValue.DateTime == DateTimeOffset.MaxValue.DateTime); - RunWrongTest(s, c => c.MaxValue.Date == DateTimeOffset.MaxValue.AddDays(-1).Date); + + ExecuteInsideSession((s) => { + var overflowHappens = localTimezone > TimeSpan.Zero; + if (overflowHappens) { + // overflow of year from 9999-12-31 to 10000-01-01 because of how postgre works with timezones + // can't validate + RunWrongTest(s, c => c.MaxValue.DateTime == DateTimeOffset.MaxValue.DateTime); + RunWrongTest(s, c => c.MaxValue.Date == DateTimeOffset.MaxValue.AddDays(-1).Date); + } + else { + RunTest(s, c => c.MaxValue.DateTime == DateTimeOffset.MaxValue.DateTime); + RunWrongTest(s, c => c.MaxValue.Date == DateTimeOffset.MaxValue.AddDays(-2).Date); + } }); } @@ -511,8 +472,15 @@ public void ExtractDayOfYearMaxValueTest() { Require.ProviderIs(StorageProvider.PostgreSql); ExecuteInsideSession((s) => { - RunTest(s, c => c.MaxValue.DayOfYear == 1); - RunWrongTest(s, c => c.MaxValue.DayOfYear == DateTimeOffset.MaxValue.AddDays(-1).DayOfYear); + var overflowHappens = localTimezone > TimeSpan.Zero; + if (overflowHappens) { + RunTest(s, c => c.MaxValue.DayOfYear == 1); + RunWrongTest(s, c => c.MaxValue.DayOfYear == DateTimeOffset.MaxValue.AddDays(-1).DayOfYear); + } + else { + RunTest(s, c => c.MaxValue.DayOfYear == DateTimeOffset.MaxValue.DayOfYear); + RunWrongTest(s, c => c.MaxValue.DayOfYear == DateTimeOffset.MaxValue.AddDays(-1).DayOfYear); + } }); } @@ -550,8 +518,15 @@ public void ExtractDayOfWeekMaxValueTest() { Require.ProviderIs(StorageProvider.PostgreSql); ExecuteInsideSession((s) => { - RunTest(s, c => c.MaxValue.DayOfWeek == DateTimeOffset.MaxValue.DayOfWeek + 1); - RunWrongTest(s, c => c.MaxValue.DayOfWeek == DateTimeOffset.MaxValue.AddDays(-1).DayOfWeek); + var overflowHappens = localTimezone > TimeSpan.Zero; + if (overflowHappens) { + RunTest(s, c => c.MaxValue.DayOfWeek == DateTimeOffset.MaxValue.DayOfWeek + 1); + RunWrongTest(s, c => c.MaxValue.DayOfWeek == DateTimeOffset.MaxValue.AddDays(-1).DayOfWeek); + } + else { + RunTest(s, c => c.MaxValue.DayOfWeek == DateTimeOffset.MaxValue.DayOfWeek); + RunWrongTest(s, c => c.MaxValue.DayOfWeek == DateTimeOffset.MaxValue.AddDays(-1).DayOfWeek); + } }); } @@ -592,8 +567,16 @@ public void ExtractDateTimeMaxValueTest() ExecuteInsideSession((s) => { // overflow of year from 9999-12-31 to 10000-01-01 because of how postgre works with timezones // can't validate - RunWrongTest(s, c => c.MaxValue.DateTime == DateTimeOffset.MaxValue.DateTime); - RunWrongTest(s, c => c.MaxValue.DateTime == DateTimeOffset.MaxValue.AddDays(-1).DateTime); + var overflowHappens = localTimezone > TimeSpan.Zero; + if (overflowHappens) { + RunWrongTest(s, c => c.MaxValue.DateTime == DateTimeOffset.MaxValue.DateTime); + RunWrongTest(s, c => c.MaxValue.DateTime == DateTimeOffset.MaxValue.AddDays(-1).DateTime); + } + else { + RunTest(s, c => c.MaxValue.DateTime == DateTimeOffset.MaxValue.DateTime); + RunWrongTest(s, c => c.MaxValue.DateTime == DateTimeOffset.MaxValue.AddDays(-1).DateTime); + } + }); } diff --git a/Orm/Xtensive.Orm.Tests/Linq/DateTimeAndDateTimeOffset/DateTimeOffsetBaseTest.cs b/Orm/Xtensive.Orm.Tests/Linq/DateTimeAndDateTimeOffset/DateTimeOffsetBaseTest.cs index c298b24dc..7d888d7ae 100644 --- a/Orm/Xtensive.Orm.Tests/Linq/DateTimeAndDateTimeOffset/DateTimeOffsetBaseTest.cs +++ b/Orm/Xtensive.Orm.Tests/Linq/DateTimeAndDateTimeOffset/DateTimeOffsetBaseTest.cs @@ -35,6 +35,8 @@ public abstract class DateTimeOffsetBaseTest : BaseTest protected static readonly DateTimeOffset SecondMillisecondDateTimeOffset = new DateTimeOffset(SecondMillisecondDateTime, SecondOffset); protected static readonly DateTimeOffset WrongMillisecondDateTimeOffset = new DateTimeOffset(WrongMillisecondDateTime, WrongOffset); + protected static readonly TimeSpan localTimezone = DateTimeOffset.Now.ToLocalTime().Offset; + protected override void RegisterTypes(DomainConfiguration configuration) { configuration.Types.Register(typeof(SingleDateTimeOffsetEntity)); @@ -51,7 +53,7 @@ protected override void InitializeCustomSettings(DomainConfiguration configurati { var providerInfo = StorageProviderInfo.Instance.Info; if (providerInfo.ProviderName==WellKnown.Provider.PostgreSql) { - var localZone = DateTimeOffset.Now.ToLocalTime().Offset; + var localZone = localTimezone; var localZoneString = ((localZone < TimeSpan.Zero) ? "-" : "+") + localZone.ToString(@"hh\:mm"); configuration.ConnectionInitializationSql = string.Format("SET TIME ZONE INTERVAL '{0}' HOUR TO MINUTE", localZoneString); } From 038887889008e67dda23eb25f6e21425c21467e5 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Sun, 26 Oct 2025 11:51:40 +0500 Subject: [PATCH 16/20] Handle hour part extraction in different timezones --- .../PostgreSql/InfinityAliasTest.cs | 10 +++++++--- .../DateTimeOffset/PartsExtractionTest.cs | 16 ++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs b/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs index 316d0da27..02d0fed96 100644 --- a/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs +++ b/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs @@ -469,10 +469,14 @@ private void TestMinDateTimeOffsetSelectDatePart(bool isOn) DateTimeOffset.MinValue.Day, isOn); - // timezone for DateTimeOffset.MinValue value in postgre is set to 04:02:33, at least when instance is in UTC+5 timezone + var serverSideHours = (localTimezone > TimeSpan.Zero) + ? localTimezone.Hours // positive zone + : (localTimezone < TimeSpan.Zero) + ? 23 + localTimezone.Hours // negative zone + : localTimezone.Hours; // UTC TestDateTimeOffsetPartExtraction(DateTimeOffsetMinValueTable, SqlDateTimeOffsetPart.Hour, - localTimezone.Hours, - localTimezone.Hours, + serverSideHours, + serverSideHours, isOn); TestDateTimeOffsetPartExtraction(DateTimeOffsetMinValueTable, SqlDateTimeOffsetPart.Minute, DateTimeOffset.MinValue.Minute, diff --git a/Orm/Xtensive.Orm.Tests/Linq/DateTimeAndDateTimeOffset/DateTimeOffset/PartsExtractionTest.cs b/Orm/Xtensive.Orm.Tests/Linq/DateTimeAndDateTimeOffset/DateTimeOffset/PartsExtractionTest.cs index 9806a63bd..a606fbcde 100644 --- a/Orm/Xtensive.Orm.Tests/Linq/DateTimeAndDateTimeOffset/DateTimeOffset/PartsExtractionTest.cs +++ b/Orm/Xtensive.Orm.Tests/Linq/DateTimeAndDateTimeOffset/DateTimeOffset/PartsExtractionTest.cs @@ -176,10 +176,10 @@ public void ExtractHourMinValueTest() ExecuteInsideSession((s) => { var serverSideHours = (localTimezone > TimeSpan.Zero) - ? localTimezone.Hours - 1 // positive zone - : (localTimezone < TimeSpan.Zero) - ? 23 + localTimezone.Hours // negative zone - : 23; // UTC + ? localTimezone.Hours // positive zone + : (localTimezone < TimeSpan.Zero) + ? 23 + localTimezone.Hours // negative zone + : localTimezone.Hours; // UTC RunTest(s, c => c.MinValue.Hour == serverSideHours); RunWrongTest(s, c => c.MinValue.Hour == DateTimeOffset.MinValue.AddHours(1).Hour); }); @@ -192,10 +192,10 @@ public void ExtractHourMaxValueTest() ExecuteInsideSession((s) => { var serverSideHours = (localTimezone > TimeSpan.Zero) - ? localTimezone.Hours - 1 // positive zone - : (localTimezone < TimeSpan.Zero) - ? 23 + localTimezone.Hours // negative zone - : 23; // UTC + ? localTimezone.Hours - 1 // positive zone + : (localTimezone < TimeSpan.Zero) + ? 23 + localTimezone.Hours // negative zone + : 23; // UTC RunTest(s, c => c.MaxValue.Hour == serverSideHours); RunWrongTest(s, c => c.MaxValue.Hour == DateTimeOffset.MaxValue.AddHours(-1).Hour); }); From f857da7e81780f8e37f78692e7434e468b8300fc Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Sun, 26 Oct 2025 13:46:27 +0500 Subject: [PATCH 17/20] Improve checks of native extraction results --- .../PostgreSql/InfinityAliasTest.cs | 60 ++++++++++++------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs b/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs index 02d0fed96..dd768d1dd 100644 --- a/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs +++ b/Orm/Xtensive.Orm.Tests.Sql/PostgreSql/InfinityAliasTest.cs @@ -606,22 +606,26 @@ private void TestDatePartExtraction(string table, SqlDatePart part, int expected using (var reader = command.ExecuteReader()) { while (reader.Read()) { - if (aliasesEnabled && part != SqlDatePart.Year) { - // year from +-infinity -> +-infinity + if (aliasesEnabled) { + // +-infinify + // year from +-infinity -> +-infinity (or 0 in case of versions older than 9.6) // month from +-infinity -> null (or 0 in case of versions older that 9.6) if (Driver.CoreServerInfo.ServerVersion >= StorageProviderVersion.PostgreSql96) { - Assert.That(reader.IsDBNull(0)); + if (part != SqlDatePart.Year) { + Assert.That(reader.IsDBNull(0)); + } + else { + var partValue = reader.GetDouble(0); + Assert.That(double.IsInfinity(partValue), Is.True); + } } else { var partValue = reader.GetDouble(0); Assert.That(partValue, Is.Zero); } } - else if (Driver.CoreServerInfo.ServerVersion < StorageProviderVersion.PostgreSql96) { - var partValue = reader.GetDouble(0); - Assert.That(partValue, Is.Zero); - } else { + // pure dates var partValue = reader.GetDouble(0); CheckPartNative(partValue, expectedValueNative, aliasesEnabled); } @@ -651,21 +655,26 @@ private void TestDateTimePartExtraction(string table, SqlDateTimePart part, int using (var reader = command.ExecuteReader()) { while (reader.Read()) { - if (aliasesEnabled && part != SqlDateTimePart.Year) { - // year from +-infinity -> +-infinity + if (aliasesEnabled) { + // +-infinify + // year from +-infinity -> +-infinity (or 0 in case of versions older than 9.6) // month from +-infinity -> null (or 0 in case of versions older that 9.6) - if (Driver.CoreServerInfo.ServerVersion >= StorageProviderVersion.PostgreSql96) - Assert.That(reader.IsDBNull(0)); + if (Driver.CoreServerInfo.ServerVersion >= StorageProviderVersion.PostgreSql96) { + if (part != SqlDateTimePart.Year) { + Assert.That(reader.IsDBNull(0)); + } + else { + var partValue = reader.GetDouble(0); + Assert.That(double.IsInfinity(partValue), Is.True); + } + } else { var partValue = reader.GetDouble(0); Assert.That(partValue, Is.Zero); } } - else if (Driver.CoreServerInfo.ServerVersion < StorageProviderVersion.PostgreSql96) { - var partValue = reader.GetDouble(0); - Assert.That(partValue, Is.Zero); - } else { + // pure dates var partValue = reader.GetDouble(0); CheckPartNative(partValue, expectedValueNative, aliasesEnabled); } @@ -695,21 +704,26 @@ private void TestDateTimeOffsetPartExtraction(string table, SqlDateTimeOffsetPar using (var reader = command.ExecuteReader()) { while (reader.Read()) { - if (aliasesEnabled && part != SqlDateTimeOffsetPart.Year) { - // year from +-infinity -> +-infinity + if (aliasesEnabled) { + // +-infinify + // year from +-infinity -> +-infinity (or 0 in case of versions older than 9.6) // month from +-infinity -> null (or 0 in case of versions older that 9.6) - if (Driver.CoreServerInfo.ServerVersion >= StorageProviderVersion.PostgreSql96 ) - Assert.That(reader.IsDBNull(0)); + if (Driver.CoreServerInfo.ServerVersion >= StorageProviderVersion.PostgreSql96) { + if (part != SqlDateTimeOffsetPart.Year) { + Assert.That(reader.IsDBNull(0)); + } + else { + var partValue = reader.GetDouble(0); + Assert.That(double.IsInfinity(partValue), Is.True); + } + } else { var partValue = reader.GetDouble(0); Assert.That(partValue, Is.Zero); } } - else if (Driver.CoreServerInfo.ServerVersion < StorageProviderVersion.PostgreSql96) { - var partValue = reader.GetDouble(0); - Assert.That(partValue, Is.Zero); - } else { + // pure dates var partValue = reader.GetDouble(0); CheckPartNative(partValue, expectedValueNative, aliasesEnabled); } From 457e652f4d5256a21d11235482c68bf911a74292 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Sun, 26 Oct 2025 14:42:12 +0500 Subject: [PATCH 18/20] Revert temp changes for logging --- .../reusable-storage-dependant-tests.yml | 19 ------ .../Sql.Drivers.PostgreSql/DriverFactory.cs | 60 ++----------------- 2 files changed, 5 insertions(+), 74 deletions(-) diff --git a/.github/workflows/reusable-storage-dependant-tests.yml b/.github/workflows/reusable-storage-dependant-tests.yml index 7a090e0bf..86b2fcb18 100644 --- a/.github/workflows/reusable-storage-dependant-tests.yml +++ b/.github/workflows/reusable-storage-dependant-tests.yml @@ -158,25 +158,6 @@ jobs: run: | docker stop $(docker ps -a -q) - - name: Temp log output - if: | - !cancelled() - run: | - echo "github event name: ${{ github.event_name }}" - echo "reproc step outcome: ${{ steps.reprocessing.outcome }}" - echo "complex step outcome: ${{ steps.complex_tests.outcome }}" - - - name: Publish temp log files - if: | - !cancelled() - timeout-minutes: 1 - uses: actions/upload-artifact@v4 - with: - name: Log_PgsqlSwitches_${{ github.ref_name }}_${{ github.run_number }}_${{inputs.target_framework}} - path: _Build/tests/${{ inputs.build_config }}/${{ inputs.target_framework }}/** - if-no-files-found: ignore - retention-days: 1 - - name: Publish raw test results as files if: | (!cancelled() && inputs.publish_raw_results) || failure() diff --git a/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/DriverFactory.cs b/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/DriverFactory.cs index 2b2ff132b..47e9b310a 100644 --- a/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/DriverFactory.cs +++ b/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/DriverFactory.cs @@ -13,7 +13,6 @@ using Xtensive.Orm; using Xtensive.Sql.Info; using Xtensive.Sql.Drivers.PostgreSql.Resources; -using System.Reflection; namespace Xtensive.Sql.Drivers.PostgreSql { @@ -215,56 +214,13 @@ private static bool SetOrGetExistingLegacyTimeStampBehaviorSwitch(bool valueToSe private static bool GetSwitchValueOrSet(string switchName, bool valueToSet) { - using (var logWriter = CreateFile(switchName)) { - logWriter?.WriteLine($"GetSwitchValueOrSet called for switch '{switchName}' in attempt to set it to {valueToSet}"); - if (!AppContext.TryGetSwitch(switchName, out var currentValue)) { - logWriter?.WriteLine($"Switch '{switchName}' is not set to any value at the moment, setting it to {valueToSet}"); - AppContext.SetSwitch(switchName, valueToSet); - logWriter?.WriteLine($"Switch '{switchName}' is set to {valueToSet}"); - return valueToSet; - } - else { - logWriter?.WriteLine($"Switch '{switchName}' is already set to value {currentValue}. Setting to {valueToSet} skipped"); - return currentValue; - } - } - } - - private static System.IO.TextWriter CreateFile(string switchName) - { - //F:\Projects\DataObjects.Net\Main Projects\do-public\new-master\_Build\tests\Debug\lib\net6.0 - var runningDirectory = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - if (!runningDirectory.Contains("_Build/tests") && !runningDirectory.Contains(@"_Build\tests")) { - return null; + if (!AppContext.TryGetSwitch(switchName, out var currentValue)) { + AppContext.SetSwitch(switchName, valueToSet); + return valueToSet; } - - var dirInfo = new System.IO.DirectoryInfo(runningDirectory); - var dotnetName = dirInfo.Name; //net6.0 - var libFolder = dirInfo.Parent; // lib - var buildConfigFolder = libFolder.Parent;//Debug/Release - - var tempFilesFolder = buildConfigFolder.CreateSubdirectory(dotnetName); - var fileToWrite = System.IO.File.CreateText(System.IO.Path.Combine(tempFilesFolder.FullName, $"Switch_{switchName.Replace('.', '_')}_{InstanceIdentifier}.log")); - return fileToWrite; - } - - private static System.IO.TextWriter CreateFile() - { - //F:\Projects\DataObjects.Net\Main Projects\do-public\new-master\_Build\tests\Debug\lib\net6.0 - var runningDirectory = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - if (!runningDirectory.Contains($"_Build{System.IO.Path.DirectorySeparatorChar}tests") - && !runningDirectory.Contains($"_Build{System.IO.Path.AltDirectorySeparatorChar}tests")) { - return null; + else { + return currentValue; } - - var dirInfo = new System.IO.DirectoryInfo(runningDirectory); - var dotnetName = dirInfo.Name; //net6.0 - var libFolder = dirInfo.Parent; // lib - var buildConfigFolder = libFolder.Parent;//Debug/Release - - var tempFilesFolder = buildConfigFolder.CreateSubdirectory(dotnetName); - var fileToWrite = System.IO.File.CreateText(System.IO.Path.Combine(tempFilesFolder.FullName, $"CtorCall_{InstanceIdentifier}.log")); - return fileToWrite; } #endregion @@ -301,12 +257,6 @@ static DriverFactory() // DO NOT REPLACE method call with constant value when debugging, CHANGE THE PARAMETER VALUE. LegacyTimestamptBehaviorEnabled = SetOrGetExistingLegacyTimeStampBehaviorSwitch(valueToSet: false); - - using(var logWriter = CreateFile()) { - logWriter.WriteLine($"Driver factory was initialized with"); - logWriter.WriteLine($" InfinityAliasForDatesEnabled = {InfinityAliasForDatesEnabled}"); - logWriter.WriteLine($" LegacyTimestamptBehaviorEnabled = {LegacyTimestamptBehaviorEnabled}"); - } } } } From 905570e85363c303930978f643c7a968aeed812f Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Sun, 26 Oct 2025 14:44:44 +0500 Subject: [PATCH 19/20] Reusable workflows' improvements --- .github/workflows/reusable-storage-dependant-tests.yml | 9 ++++----- .github/workflows/reusable-storage-independant-tests.yml | 9 ++++----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/.github/workflows/reusable-storage-dependant-tests.yml b/.github/workflows/reusable-storage-dependant-tests.yml index 93418b506..e5a56de1e 100644 --- a/.github/workflows/reusable-storage-dependant-tests.yml +++ b/.github/workflows/reusable-storage-dependant-tests.yml @@ -16,7 +16,7 @@ on: target_framework: description: 'Target framework' required: true - default: 'net6.0' + default: 'netcoreapp2.0' type: string specific_sha: description: 'Commit SHA to checkout' @@ -171,10 +171,9 @@ jobs: - name: Make Final Test report if: | - (github.event_name == 'push' && (steps.reprocessing.outcome != 'cancelled' && steps.complex_tests.outcome != 'cancelled')) - || (github.event_name == 'pull_request' && (steps.reprocessing.outcome != 'cancelled' && steps.complex_tests.outcome != 'cancelled')) - || (github.event_name == 'workflow_dispatch' && (steps.reprocessing.outcome != 'cancelled' && steps.complex_tests.outcome != 'cancelled')) - || (steps.reprocessing.outcome == 'failure' || steps.complex_tests.outcome == 'failure') + !cancelled() + && ((github.event_name == 'push') || (github.event_name == 'pull_request') || (github.event_name == 'workflow_dispatch') + || (steps.reprocessing.outcome == 'failure' || steps.complex_tests.outcome == 'failure')) timeout-minutes: 1 uses: dorny/test-reporter@v2.1.1 with: diff --git a/.github/workflows/reusable-storage-independant-tests.yml b/.github/workflows/reusable-storage-independant-tests.yml index c20f443f6..cd753676e 100644 --- a/.github/workflows/reusable-storage-independant-tests.yml +++ b/.github/workflows/reusable-storage-independant-tests.yml @@ -11,7 +11,7 @@ on: target_framework: description: 'Target framework' required: true - default: 'net6.0' + default: 'netcoreapp2.0' type: string test_output_verbosity: description: 'Verbosity for dotnet test command' @@ -122,10 +122,9 @@ jobs: - name: Make Final Test report if: | - (github.event_name == 'push' && steps.complex_tests.outcome != 'cancelled') - || (github.event_name == 'pull_request' && steps.complex_tests.outcome != 'cancelled') - || (github.event_name == 'workflow_dispatch' && steps.complex_tests.outcome != 'cancelled') - || steps.complex_tests.outcome == 'failure' + !cancelled() + && ((github.event_name == 'push') || (github.event_name == 'pull_request') || (github.event_name == 'workflow_dispatch') + || (steps.reprocessing.outcome == 'failure' || steps.complex_tests.outcome == 'failure')) timeout-minutes: 1 uses: dorny/test-reporter@v2.1.1 with: From d4e7aa229dc16c801d60b52cf76e069889af7e46 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Sun, 26 Oct 2025 14:46:22 +0500 Subject: [PATCH 20/20] Reusable workflows: change default target framework --- .github/workflows/reusable-storage-dependant-tests.yml | 2 +- .github/workflows/reusable-storage-independant-tests.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reusable-storage-dependant-tests.yml b/.github/workflows/reusable-storage-dependant-tests.yml index e5a56de1e..8dac52f7f 100644 --- a/.github/workflows/reusable-storage-dependant-tests.yml +++ b/.github/workflows/reusable-storage-dependant-tests.yml @@ -16,7 +16,7 @@ on: target_framework: description: 'Target framework' required: true - default: 'netcoreapp2.0' + default: 'netcoreapp3.1' type: string specific_sha: description: 'Commit SHA to checkout' diff --git a/.github/workflows/reusable-storage-independant-tests.yml b/.github/workflows/reusable-storage-independant-tests.yml index cd753676e..5b6b09459 100644 --- a/.github/workflows/reusable-storage-independant-tests.yml +++ b/.github/workflows/reusable-storage-independant-tests.yml @@ -11,7 +11,7 @@ on: target_framework: description: 'Target framework' required: true - default: 'netcoreapp2.0' + default: 'netcoreapp3.1' type: string test_output_verbosity: description: 'Verbosity for dotnet test command'