Warning on compare to `nil` in short-circuited query

I have a query with an expression like this:
expr(
is_nil(^start_date) or
^start_date <= fragment("date(?)", completed_date)
)
expr(
is_nil(^start_date) or
^start_date <= fragment("date(?)", completed_date)
)
This gives a warning about comparing to nil:
warning: Comparing values with `nil` will always return `false`. Use `is_nil/1` instead. In: `nil <= fragment("date(?)", completed_date)`
warning: Comparing values with `nil` will always return `false`. Use `is_nil/1` instead. In: `nil <= fragment("date(?)", completed_date)`
Is there a better way to implement this behaviour? If not, is it possible to detect that the check for nil is already performed in the query?
13 Replies
aidalgol
aidalgol2mo ago
Are you using the latest ash release? There was a bug around a very similar warning fix in the past couple weeks. https://github.com/ash-project/ash/issues/2288
GitHub
Warning: Comparing values with nil will always return false. ·...
Code of Conduct I agree to follow this project&#39;s Code of Conduct AI Policy I agree to follow this project&#39;s AI Policy, or I agree that AI was not used while creating this issue. Versions As...
Rutgerdj
RutgerdjOP2mo ago
Yes, I'm at 3.5.37
ZachDaniel
ZachDaniel2mo ago
Was it released? It may only be in main
Rutgerdj
RutgerdjOP2mo ago
Still getting the same error when using main
Kamaro
Kamaro2mo ago
According to the bug, it looks like you are on ash 3.5.36
ZachDaniel
ZachDaniel2mo ago
That bug report was from someone else @Rutgerdj if you can put together a reproduction and comment on that existing issue or open a new one that would be great I'll look into it. Actually when do you get that warning?
Rutgerdj
RutgerdjOP2mo ago
Will do
ZachDaniel
ZachDaniel2mo ago
Can I see the stacktrace?
Rutgerdj
RutgerdjOP2mo ago
warning: Comparing values with `nil` will always return `false`. Use `is_nil/1` instead. In: `nil >= fragment("date(?)", entry_conclusion.entry.timeslot.matching_table.start_datetime)`
(cvs 0.1.0) lib/cvs/matching_table/resources/entry_conclusion_referral.ex:236: Cvs.MatchingTable.EntryConclusionReferral.apply_mt_date_filters/1
(cvs 0.1.0) lib/cvs/matching_table/resources/entry_conclusion_referral.ex:173: Cvs.MatchingTable.EntryConclusionReferral.apply_default_filter/1
(ash 3.5.37) lib/ash/resource/preparation/preparation.ex:82: Ash.Resource.Preparation.prepare/4
(ash 3.5.37) lib/ash/query/query.ex:1311: Ash.Query.run_preparation/6
(elixir 1.17.3) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3
(ash 3.5.37) lib/ash/query/query.ex:926: Ash.Query.for_read/4
(cvs 0.1.0) deps/ash/lib/ash/code_interface.ex:812: Cvs.MatchingTable.EntryConclusionReferral.read_results!/2
(cvs 0.1.0) lib/cvs_web/live/result/index.ex:912: CvsWeb.Live.Result.Index.get_mt_referrals/1
(cvs 0.1.0) lib/cvs_web/live/result/index.ex:485: CvsWeb.Live.Result.Index.mount/3
(phoenix_live_view 1.0.17) lib/phoenix_live_view/utils.ex:348: anonymous fn/6 in Phoenix.LiveView.Utils.maybe_call_live_view_mount!/5
(telemetry 1.3.0) /home/rutger/bettr/cvs/deps/telemetry/src/telemetry.erl:324: :telemetry.span/3
(phoenix_live_view 1.0.17) lib/phoenix_live_view/channel.ex:1207: Phoenix.LiveView.Channel.verified_mount/8
(phoenix_live_view 1.0.17) lib/phoenix_live_view/channel.ex:84: Phoenix.LiveView.Channel.handle_info/2
(stdlib 6.2.2) gen_server.erl:2345: :gen_server.try_handle_info/3
(stdlib 6.2.2) gen_server.erl:2433: :gen_server.handle_msg/6
(stdlib 6.2.2) proc_lib.erl:329: :proc_lib.init_p_do_apply/3
warning: Comparing values with `nil` will always return `false`. Use `is_nil/1` instead. In: `nil >= fragment("date(?)", entry_conclusion.entry.timeslot.matching_table.start_datetime)`
(cvs 0.1.0) lib/cvs/matching_table/resources/entry_conclusion_referral.ex:236: Cvs.MatchingTable.EntryConclusionReferral.apply_mt_date_filters/1
(cvs 0.1.0) lib/cvs/matching_table/resources/entry_conclusion_referral.ex:173: Cvs.MatchingTable.EntryConclusionReferral.apply_default_filter/1
(ash 3.5.37) lib/ash/resource/preparation/preparation.ex:82: Ash.Resource.Preparation.prepare/4
(ash 3.5.37) lib/ash/query/query.ex:1311: Ash.Query.run_preparation/6
(elixir 1.17.3) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3
(ash 3.5.37) lib/ash/query/query.ex:926: Ash.Query.for_read/4
(cvs 0.1.0) deps/ash/lib/ash/code_interface.ex:812: Cvs.MatchingTable.EntryConclusionReferral.read_results!/2
(cvs 0.1.0) lib/cvs_web/live/result/index.ex:912: CvsWeb.Live.Result.Index.get_mt_referrals/1
(cvs 0.1.0) lib/cvs_web/live/result/index.ex:485: CvsWeb.Live.Result.Index.mount/3
(phoenix_live_view 1.0.17) lib/phoenix_live_view/utils.ex:348: anonymous fn/6 in Phoenix.LiveView.Utils.maybe_call_live_view_mount!/5
(telemetry 1.3.0) /home/rutger/bettr/cvs/deps/telemetry/src/telemetry.erl:324: :telemetry.span/3
(phoenix_live_view 1.0.17) lib/phoenix_live_view/channel.ex:1207: Phoenix.LiveView.Channel.verified_mount/8
(phoenix_live_view 1.0.17) lib/phoenix_live_view/channel.ex:84: Phoenix.LiveView.Channel.handle_info/2
(stdlib 6.2.2) gen_server.erl:2345: :gen_server.try_handle_info/3
(stdlib 6.2.2) gen_server.erl:2433: :gen_server.handle_msg/6
(stdlib 6.2.2) proc_lib.erl:329: :proc_lib.init_p_do_apply/3
apply_mt_date_filters:
defp apply_mt_date_filters(query) do
start_date = Ash.Query.get_argument(query, :start_date)
end_date = Ash.Query.get_argument(query, :end_date)

Ash.Query.filter(
query,
expr(
(is_nil(^start_date) or
^start_date <=
fragment(
"date(?)",
entry_conclusion.entry.timeslot.matching_table.start_datetime
)) and
(is_nil(^end_date) or
^end_date >=
fragment(
"date(?)",
entry_conclusion.entry.timeslot.matching_table.start_datetime
))
)
)
end
defp apply_mt_date_filters(query) do
start_date = Ash.Query.get_argument(query, :start_date)
end_date = Ash.Query.get_argument(query, :end_date)

Ash.Query.filter(
query,
expr(
(is_nil(^start_date) or
^start_date <=
fragment(
"date(?)",
entry_conclusion.entry.timeslot.matching_table.start_datetime
)) and
(is_nil(^end_date) or
^end_date >=
fragment(
"date(?)",
entry_conclusion.entry.timeslot.matching_table.start_datetime
))
)
)
end
ZachDaniel
ZachDaniel2mo ago
Got it in this case my earlier PR won't affect this This is detecting a nil expression while building it directly
defp apply_mt_date_filters(query) do
start_date = Ash.Query.get_argument(query, :start_date)
end_date = Ash.Query.get_argument(query, :end_date)
matches_start_date =
if is_nil(start_date) do
true
else
expr(^start_date <=
fragment(
"date(?)",
entry_conclusion.entry.timeslot.matching_table.start_datetime
))
end

matches_end_date =
if is_nil(end_date) do
true
else
expr(^end_date >=
fragment(
"date(?)",
entry_conclusion.entry.timeslot.matching_table.start_datetime
)))
end

Ash.Query.filter(
query,
^matches_start_date and ^matches_end_date
)
end
defp apply_mt_date_filters(query) do
start_date = Ash.Query.get_argument(query, :start_date)
end_date = Ash.Query.get_argument(query, :end_date)
matches_start_date =
if is_nil(start_date) do
true
else
expr(^start_date <=
fragment(
"date(?)",
entry_conclusion.entry.timeslot.matching_table.start_datetime
))
end

matches_end_date =
if is_nil(end_date) do
true
else
expr(^end_date >=
fragment(
"date(?)",
entry_conclusion.entry.timeslot.matching_table.start_datetime
)))
end

Ash.Query.filter(
query,
^matches_start_date and ^matches_end_date
)
end
Rutgerdj
RutgerdjOP2mo ago
I see, so it just can't figure out the is_nil() check in an expression outside of the current comparison?
ZachDaniel
ZachDaniel2mo ago
Not currently, no It figures it out when the value is something like ^arg(:whatever) which you can't use in this context
Rutgerdj
RutgerdjOP2mo ago
Thanks for the insights!

Did you find this page helpful?