@@ -305,6 +305,27 @@ defmodule AshSql.Expr do
305305 ) , acc }
306306 end
307307
308+ defp default_dynamic_expr (
309+ query ,
310+ % Ago { arguments: [ duration ] , embedded?: pred_embedded? } ,
311+ bindings ,
312+ embedded? ,
313+ acc ,
314+ _type
315+ ) do
316+ { duration , acc } =
317+ do_dynamic_expr (
318+ query ,
319+ duration ,
320+ set_location ( bindings , :sub_expr ) ,
321+ pred_embedded? || embedded? ,
322+ acc ,
323+ :duration
324+ )
325+
326+ { Ecto.Query . dynamic ( fragment ( "(?::timestamp - ?)" , ^ DateTime . utc_now ( ) , ^ duration ) ) , acc }
327+ end
328+
308329 defp default_dynamic_expr (
309330 query ,
310331 % StartOfDay { arguments: [ value ] , embedded?: pred_embedded? } ,
@@ -446,6 +467,27 @@ defmodule AshSql.Expr do
446467 ) , acc }
447468 end
448469
470+ defp default_dynamic_expr (
471+ query ,
472+ % FromNow { arguments: [ duration ] , embedded?: pred_embedded? } ,
473+ bindings ,
474+ embedded? ,
475+ acc ,
476+ _type
477+ ) do
478+ { duration , acc } =
479+ do_dynamic_expr (
480+ query ,
481+ duration ,
482+ set_location ( bindings , :sub_expr ) ,
483+ pred_embedded? || embedded? ,
484+ acc ,
485+ :duration
486+ )
487+
488+ { Ecto.Query . dynamic ( fragment ( "(?::timestamp + ?)" , ^ DateTime . utc_now ( ) , ^ duration ) ) , acc }
489+ end
490+
449491 defp default_dynamic_expr (
450492 query ,
451493 % DateTimeAdd { arguments: [ datetime , amount , interval ] , embedded?: pred_embedded? } ,
@@ -478,6 +520,36 @@ defmodule AshSql.Expr do
478520 acc }
479521 end
480522
523+ defp default_dynamic_expr (
524+ query ,
525+ % DateTimeAdd { arguments: [ datetime , duration ] , embedded?: pred_embedded? } ,
526+ bindings ,
527+ embedded? ,
528+ acc ,
529+ _type
530+ ) do
531+ { datetime , acc } =
532+ do_dynamic_expr (
533+ query ,
534+ datetime ,
535+ set_location ( bindings , :sub_expr ) ,
536+ pred_embedded? || embedded? ,
537+ acc
538+ )
539+
540+ { duration , acc } =
541+ do_dynamic_expr (
542+ query ,
543+ duration ,
544+ set_location ( bindings , :sub_expr ) ,
545+ pred_embedded? || embedded? ,
546+ acc ,
547+ :duration
548+ )
549+
550+ { Ecto.Query . dynamic ( fragment ( "(?::timestamp + ?)" , ^ datetime , ^ duration ) ) , acc }
551+ end
552+
481553 defp default_dynamic_expr (
482554 query ,
483555 % DateAdd { arguments: [ date , amount , interval ] , embedded?: pred_embedded? } ,
@@ -509,6 +581,38 @@ defmodule AshSql.Expr do
509581 { Ecto.Query . dynamic ( fragment ( "(?)" , date_add ( ^ date , ^ amount , ^ to_string ( interval ) ) ) ) , acc }
510582 end
511583
584+ defp default_dynamic_expr (
585+ query ,
586+ % DateAdd { arguments: [ date , duration ] , embedded?: pred_embedded? } ,
587+ bindings ,
588+ embedded? ,
589+ acc ,
590+ _type
591+ ) do
592+ { date , acc } =
593+ do_dynamic_expr (
594+ query ,
595+ date ,
596+ set_location ( bindings , :sub_expr ) ,
597+ pred_embedded? || embedded? ,
598+ acc
599+ )
600+
601+ { duration , acc } =
602+ do_dynamic_expr (
603+ query ,
604+ duration ,
605+ set_location ( bindings , :sub_expr ) ,
606+ pred_embedded? || embedded? ,
607+ acc ,
608+ :duration
609+ )
610+
611+ # `date + interval` is a timestamp in Postgres, so cast back, as Ecto's own
612+ # `date_add/3` does.
613+ { Ecto.Query . dynamic ( fragment ( "((?::date + ?)::date)" , ^ date , ^ duration ) ) , acc }
614+ end
615+
512616 defp default_dynamic_expr (
513617 query ,
514618 % GetPath {
0 commit comments