cockroachdb / cockroach

CockroachDB — the cloud native, distributed SQL database designed for high availability, effortless scale, and control over data placement.
https://www.cockroachlabs.com
Other
29.86k stars 3.77k forks source link

.NET DateTime.MaxValue Exceeds Supported Timestamp Bounds #125054

Closed RDoll-Repo closed 1 week ago

RDoll-Repo commented 3 months ago

Describe the problem

When updating an entity with a field of DateTime, if we attempt to give that field a value of DateTime.MaxValue, we get the following exception:

An exception of type 'Microsoft.EntityFrameworkCore.DbUpdateException' occurred in System.Private.CoreLib.dll but was not handled in user code: 'An error occurred while saving the entity changes. See the inner exception for details.'
 Inner exceptions found, see $exception in variables window for more details.
 Innermost exception     Npgsql.PostgresException : 22009: error in argument for $2: timestamp "294277-01-09T04:00:54Z" exceeds supported timestamp bounds
   at Npgsql.Internal.NpgsqlConnector.<ReadMessageLong>d__233.MoveNext()
   at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
   at Npgsql.NpgsqlDataReader.<NextResult>d__52.MoveNext()
   at Npgsql.NpgsqlDataReader.<NextResult>d__52.MoveNext()
   at Npgsql.NpgsqlDataReader.NextResult()
   at Npgsql.NpgsqlCommand.<ExecuteReader>d__119.MoveNext()
   at Npgsql.NpgsqlCommand.<ExecuteReader>d__119.MoveNext()
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at Npgsql.NpgsqlCommand.ExecuteReader(CommandBehavior behavior)
   at Npgsql.NpgsqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
   at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)

I originally opened this issue with the EF Core team here, but after determining that this only happens with Cockroach and not Postgres, I was directed to try opening the issue here.

To Reproduce

1.) Use the provided reproduction project DateTimeSample.zip

2.) Run docker-compose up to start the server

3.) Run dotnet ef migrations add Initial then dotnet ef database update to create a table reflecting the Purchase class in Program.cs

4.) Run project to attempt to insert a row into the database. You should see the error shown above.

Expected behavior When running this, I would expect the table to be updated with a row that reflects an Expiry of 9999-12-31T23:59:59Z

Additional data / screenshots N/A

Environment:

Additional context We effectively need to hardcode the expected value instead of using DateTime.MaxValue

I also wasn't sure how exactly to present this issue, since it occurs in a .NET project which is perhaps not entirely in the wheelhouse of this repo, so if there is a more helpful way to present this, let me know.

Jira issue: CRDB-39217

blathers-crl[bot] commented 3 months ago

Hi @RDoll-Repo, please add branch-* labels to identify which branch(es) this C-bug affects.

:owl: Hoot! I am a Blathers, a bot for CockroachDB. My owner is dev-inf.

blathers-crl[bot] commented 3 months ago

Hello, I am Blathers. I am here to help you get the issue triaged.

Hoot - a bug! Though bugs are the bane of my existence, rest assured the wretched thing will get the best of care here.

I was unable to automatically find someone to ping.

If we have not gotten back to your issue within a few business days, you can try the following:

:owl: Hoot! I am a Blathers, a bot for CockroachDB. My owner is dev-inf.

RDoll-Repo commented 3 months ago

Hi @RDoll-Repo, please add branch-* labels to identify which branch(es) this C-bug affects.

It doesn't look like I can add further labels beyond what was automatically assigned to the issue.

rafiss commented 2 months ago

Thanks for the report!

One question about the expected behavior:

When running this, I would expect the table to be updated with a row that reflects an Expiry of 9999-12-31T23:59:59Z

When I tried your example with Postgres, I see that it actually has a row with an expiry of infinity. Are you sure you see 9999-12-31T23:59:59Z?

CockroachDB currently cannot represent infinity timestamps. The tracking issue is: https://github.com/cockroachdb/cockroach/issues/41564

RDoll-Repo commented 2 months ago

Thanks for the report!

One question about the expected behavior:

When running this, I would expect the table to be updated with a row that reflects an Expiry of 9999-12-31T23:59:59Z

When I tried your example with Postgres, I see that it actually has a row with an expiry of infinity. Are you sure you see 9999-12-31T23:59:59Z?

CockroachDB currently cannot represent infinity timestamps. The tracking issue is: #41564

When I inspect what DateTime.MaxValue evaluates to in .NET, I'm seeing the attached. I guess when this data goes through npgsql, it's coming out as infinity and that's what's getting inserted SQL side? But yeah, that essentially seems to mean that DateTime.MaxValue is unusable with CRDB right now. Hardcoding an equivalent string seems to be the workaround, but I figured I should report this behavior nonetheless and see if there's anything to be done about it

› ExpirationDate  DateTime  {12319999 115959PM}
roji commented 2 months ago

Just noting that Npgsql by default convert DateTime.{Min,Max}Value to PG infinity values. This behavior can be disabled (see docs).

rafiss commented 1 week ago

v24.3 will support the infinity timestamp in the same way Postgres does. see https://github.com/cockroachdb/cockroach/pull/127141