-
Notifications
You must be signed in to change notification settings - Fork 227
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
npgsql 6 breaks after DateTime migration: "year must be between 1 and 9999" #2177
Comments
@qwertie your proposed suggestion with Math.Max would silently read PostgreSQL timestamps from before the year 0 to DateTime.MinValue (which is Can you provide full information on your problem, and how I'd reproduce this? Is your column |
I'm not actually sure how to reproduce. I thought that the 0001/01/01 values were the result of adding the
Looking at it now, yes, lots of rows have values of "2019-12-31 17:00:00-07" - and I'm not sure, can you tell me if the timezone "-07" is physically stored in the database or if Beekeeper just prefers to show local time? So I'm not sure how those values got in there, but they must have been there as a result of storing ordinary |
The offset (-07) isn't stored in the database; the However, I think there may be some confusion here: PostgreSQL only shows a string representation with an offset ( Now, when following the migration guide, did you also take care to add I hope the above sheds some light. If you need more help, I need to know what the actual column type is in the database ( |
Yes, and I believe Pre-migration I was using UTC timestamps stored in default-typed DateTime fields, and as you can see above, the migration generator was choosing "timestamp without time zone" for this. Edit: Also, our generated migrationBuilder.AlterColumn<DateTime>(
name: "last_updated",
table: "entities",
type: "timestamp with time zone",
nullable: false,
oldClrType: typeof(DateTime),
oldType: "timestamp without time zone"); "UTC-ness" was enforced using conversions like this: entity.Property(nameof(LastUpdated))
.HasConversion<DateTime, DateTime>(
d => d.ToUniversalTime(), d => new DateTime(d.Ticks, DateTimeKind.Utc)); where public static PropertyBuilder HasConversion<ModelT, DBT>(this PropertyBuilder property,
Expression<Func<ModelT, DBT>> onSave, Expression<Func<DBT, ModelT>> onLoad,
ConverterMappingHints? hints = null)
=> property.HasConversion(new ValueConverter<ModelT, DBT>(onSave, onLoad, hints)); Just before or after the migration (can't remember, but it shouldn't matter), I changed the HasConversion code to .HasConversion<DateTime, DateTime>(d => d.ToUniversalTime(), d => d); So the puzzle is how it's possible that some |
So can you confirm you have negative timestamps in the database? If so, what is their exact value (preferably in UTC)? That might shed some light on what happened. |
Thanks for your responsiveness! Sadly I "blew away" the exact timestamps as part of the workaround mentioned above. I have a backup of the non-migrated production database that I have now experimented with... and I cannot reproduce the problem even though it does contain dates in year 0001: select last_updated, EXTRACT(EPOCH FROM last_updated) from entities
...
2020-01-01 00:00:00 1577836800
2020-01-01 00:00:00 1577836800
0001-01-01 00:00:00 -62135596800
0001-01-01 00:00:00 -62135596800
...
-- where 1970 is 0
select * FROM EXTRACT(EPOCH FROM TIMESTAMP '1970-01-01 00:00:00')
0 As expected, running the query post-migration gives the same integers, and the app works, though Beekeeper's output is odd: select last_updated, EXTRACT(EPOCH FROM last_updated) from entities
...
2019-12-31 17:00:00-07 1577836800
2019-12-31 17:00:00-07 1577836800
0001-12-31 17:00:04-06:59:56 BC -62135596800
0001-12-31 17:00:04-06:59:56 BC -62135596800
... And if I use my code to create new rows in the upgraded table with their default .NET value, again it is displayed wrong but the number makes sense, as it is 7 hours after 0001-01-01 00:00:04-06:59:56 -62135571600 I am closing as not reproducible. |
@qwertie ok. Re the display issue, keep in mind that as I wrote above, that should just be a matter of your PostgreSQL |
Yeah, I couldn't figure out how to make that work. A |
@qwertie you can set it in your PostgreSQL's postgresql.conf, that would make it the default value for all connections. Otherwise maybe there's a way to tell Beekeeper to set a parameter for its connections... |
Can I reopen this? I have old data in my database which causes a crash after upgrading to npgsql 6. An example of a timestamp in the database (which the pgAdmin can read just fine) is "0001-01-01 00:00:00+01:39:49" (in pgAdmin view). pgAdmin does not crash but npgsql does, since it cannot READ that timestamp without throwing this particular exeption: "year must be between 1 and 9999", inner: "Ticks must be between DateTime.MinValue.Ticks and DateTime.MaxValue.Ticks. (Parameter 'ticks')". Thanks! |
@TriHyde your case seems to be the same as @qwertie - please see the discussion above. You have negative timestamp data in your database, and that's simply not representable with .NET DateTime. I recommend fixing up your data; for example, you could convert those values to If that isn't suitable, can you please provide more on context on why, and how exactly you're using those values? |
After following the date migration guide to change types from "without time zone" to "with time zone", I'm still having multiple errors. One of them occurs when reading rows from three of our tables:
My database contains some dates that I think were set to 0001/01/01 00:00:00, but which BeeKeeper (incorrectly) reports as 0001/12/31... and this breaks npgsql v6. As a workaround I have executed a series of queries like this to fix the problem:
I think the problem can be fixed by changing this function in Npgsql\Internal\TypeHandlers\DateTimeHandlers\DateTimeUtils.cs:
do instead:
or maybe even:
The other error I'm getting occurs when I create a fresh database by calling
Migrate()
.The text was updated successfully, but these errors were encountered: