diff --git a/lib/expr.ex b/lib/expr.ex index 1b9ad65..9c3203c 100644 --- a/lib/expr.ex +++ b/lib/expr.ex @@ -305,6 +305,27 @@ defmodule AshSql.Expr do ), acc} end + defp default_dynamic_expr( + query, + %Ago{arguments: [duration], embedded?: pred_embedded?}, + bindings, + embedded?, + acc, + _type + ) do + {duration, acc} = + do_dynamic_expr( + query, + duration, + set_location(bindings, :sub_expr), + pred_embedded? || embedded?, + acc, + :duration + ) + + {Ecto.Query.dynamic(fragment("(?::timestamp - ?)", ^DateTime.utc_now(), ^duration)), acc} + end + defp default_dynamic_expr( query, %StartOfDay{arguments: [value], embedded?: pred_embedded?}, @@ -446,6 +467,27 @@ defmodule AshSql.Expr do ), acc} end + defp default_dynamic_expr( + query, + %FromNow{arguments: [duration], embedded?: pred_embedded?}, + bindings, + embedded?, + acc, + _type + ) do + {duration, acc} = + do_dynamic_expr( + query, + duration, + set_location(bindings, :sub_expr), + pred_embedded? || embedded?, + acc, + :duration + ) + + {Ecto.Query.dynamic(fragment("(?::timestamp + ?)", ^DateTime.utc_now(), ^duration)), acc} + end + defp default_dynamic_expr( query, %DateTimeAdd{arguments: [datetime, amount, interval], embedded?: pred_embedded?}, @@ -478,6 +520,36 @@ defmodule AshSql.Expr do acc} end + defp default_dynamic_expr( + query, + %DateTimeAdd{arguments: [datetime, duration], embedded?: pred_embedded?}, + bindings, + embedded?, + acc, + _type + ) do + {datetime, acc} = + do_dynamic_expr( + query, + datetime, + set_location(bindings, :sub_expr), + pred_embedded? || embedded?, + acc + ) + + {duration, acc} = + do_dynamic_expr( + query, + duration, + set_location(bindings, :sub_expr), + pred_embedded? || embedded?, + acc, + :duration + ) + + {Ecto.Query.dynamic(fragment("(?::timestamp + ?)", ^datetime, ^duration)), acc} + end + defp default_dynamic_expr( query, %DateAdd{arguments: [date, amount, interval], embedded?: pred_embedded?}, @@ -509,6 +581,38 @@ defmodule AshSql.Expr do {Ecto.Query.dynamic(fragment("(?)", date_add(^date, ^amount, ^to_string(interval)))), acc} end + defp default_dynamic_expr( + query, + %DateAdd{arguments: [date, duration], embedded?: pred_embedded?}, + bindings, + embedded?, + acc, + _type + ) do + {date, acc} = + do_dynamic_expr( + query, + date, + set_location(bindings, :sub_expr), + pred_embedded? || embedded?, + acc + ) + + {duration, acc} = + do_dynamic_expr( + query, + duration, + set_location(bindings, :sub_expr), + pred_embedded? || embedded?, + acc, + :duration + ) + + # `date + interval` is a timestamp in Postgres, so cast back, as Ecto's own + # `date_add/3` does. + {Ecto.Query.dynamic(fragment("((?::date + ?)::date)", ^date, ^duration)), acc} + end + defp default_dynamic_expr( query, %GetPath{