-
Notifications
You must be signed in to change notification settings - Fork 48
DateTime passed into query producing incorrect results #74
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
Comments
One possible workaround is to use |> where([t], fragment("(?, ?) < (datetime(?), ?)", t.timestamp, t.thing_id, ^since_timestamp, ^since_thing_id)) |
@tomtaylor also can you throw |
@warmwaffles here's the simplest query that returns incorrect result on that data. github.com/ruslandoga/issue74 iex> since_timestamp = ~U[2016-02-25 19:02:15Z]
iex> import Ecto.Query
iex> Thing |> where([t], t.timestamp < ^since_timestamp) |> Repo.all()
# [debug] QUERY OK source="things" db=0.5ms queue=0.1ms idle=1714.0ms
# SELECT t0."id", t0."thing_id", t0."user_id", t0."timestamp" FROM things AS t0 WHERE (t0."timestamp" < ?) ["2016-02-25T19:02:15"]
[
%Thing{
__meta__: #Ecto.Schema.Metadata<:loaded, "things">,
id: 9,
thing_id: 9,
timestamp: ~U[2016-02-25 19:02:16Z], # shouldn't have been returned
user_id: 2
},
%Thing{
__meta__: #Ecto.Schema.Metadata<:loaded, "things">,
id: 10,
thing_id: 10,
timestamp: ~U[2016-02-24 17:49:14Z],
user_id: 2
}
]
# it comes down to this for SQLite, unless extra info is provided
iex> "2016-02-25 19:02:16" < "2016-02-25T19:02:15Z"
true -- SQLite version 3.38.5 2022-05-06 15:25:27
sqlite> SELECT * FROM things WHERE (timestamp < '2016-02-25T19:02:15');
┌────┬──────────┬─────────┬─────────────────────┐
│ id │ thing_id │ user_id │ timestamp │
├────┼──────────┼─────────┼─────────────────────┤
│ 9 │ 9 │ 2 │ 2016-02-25 19:02:16 │
│ 10 │ 10 │ 2 │ 2016-02-24 17:49:14 │
└────┴──────────┴─────────┴─────────────────────┘
sqlite> SELECT * FROM things WHERE (timestamp < cast('2016-02-25T19:02:15' as text_datetime));
┌────┬──────────┬─────────┬─────────────────────┐
│ id │ thing_id │ user_id │ timestamp │
├────┼──────────┼─────────┼─────────────────────┤
│ 9 │ 9 │ 2 │ 2016-02-25 19:02:16 │
│ 10 │ 10 │ 2 │ 2016-02-24 17:49:14 │
└────┴──────────┴─────────┴─────────────────────┘
sqlite> SELECT * FROM things WHERE (timestamp < datetime('2016-02-25T19:02:15'));
┌────┬──────────┬─────────┬─────────────────────┐
│ id │ thing_id │ user_id │ timestamp │
├────┼──────────┼─────────┼─────────────────────┤
│ 10 │ 10 │ 2 │ 2016-02-24 17:49:14 │
└────┴──────────┴─────────┴─────────────────────┘
sqlite> SELECT * FROM things WHERE (timestamp < '2016-02-25 19:02:15');
┌────┬──────────┬─────────┬─────────────────────┐
│ id │ thing_id │ user_id │ timestamp │
├────┼──────────┼─────────┼─────────────────────┤
│ 10 │ 10 │ 2 │ 2016-02-24 17:49:14 │
└────┴──────────┴─────────┴─────────────────────┘ |
I'll take a look into this soon unless @ruslandoga you find a solution before I do. |
@warmwaffles I don't think there is any fix due to SQLite's lack of real date/time types. As far as I can see, the best thing Ecto can do is cast the input, but SQLite seems to ignore it. sqlite> SELECT * FROM things WHERE (timestamp < cast('2016-02-25T19:02:15' as text_datetime));
┌────┬──────────┬─────────┬─────────────────────┐
│ id │ thing_id │ user_id │ timestamp │
├────┼──────────┼─────────┼─────────────────────┤
│ 9 │ 9 │ 2 │ 2016-02-25 19:02:16 │
│ 10 │ 10 │ 2 │ 2016-02-24 17:49:14 │
└────┴──────────┴─────────┴─────────────────────┘ And replacing any timestamp with a function call like Related: https://sqlite.org/forum/forumpost/9e5b6175fc702f4a |
Heh, I don't think it is so much a short coming but a deliberate decision to leave that to the application level. It also doesn't help that we use |
Thanks for everyone's work looking at this, and for providing a minimal test case. I feel like the current behaviour is a little surprising. While SQLite has no native datetime format, the implication of the Is this something we could make configurable? Perhaps defaulting to |
A PR for the change would be welcome. We simply defaulted to |
@tomtaylor you can give the changes in this PR a try: #84 |
Lemme get a release cut |
The recent set of changes has been released under |
Uh oh!
There was an error while loading. Please reload this page.
I've got a table that looks like this:
With data that looks like:
And a query that's very similar to this:
I've been tearing my hair out trying to work out why it works fine in my SQLite console, but through Ecto it doesn't seem to produce the right results - the dates of the result are incorrect. I was passing a
DateTime
in assince_timestamp
, but I've discovered the query only works correctly if I pass in the same thing in as an ISO8601 String. So"2022-05-29 06:34:29"
instead of~U[2022-05-29 06:34:29Z]
.I guessing this is something to do with how a
DateTime
is cast into a string into Ecto, which is different to the string format in the database. It's really difficult to debug, because I can't see exactly what query is being produced.Let me know if I can provide any more information or a test case.
The text was updated successfully, but these errors were encountered: