@@ -415,7 +415,7 @@ defmodule Ecto.Query do
415415 lock: nil ,
416416 windows: [ ] ,
417417 with_ctes: nil ,
418- label: nil
418+ comments: [ ]
419419
420420 defmodule FromExpr do
421421 @ moduledoc false
@@ -956,6 +956,7 @@ defmodule Ecto.Query do
956956 Ecto.Query.exclude(query, :limit)
957957 Ecto.Query.exclude(query, :offset)
958958 Ecto.Query.exclude(query, :lock)
959+ Ecto.Query.exclude(query, :comments)
959960 Ecto.Query.exclude(query, :preload)
960961 Ecto.Query.exclude(query, :update)
961962 Ecto.Query.exclude(query, :windows)
@@ -1025,6 +1026,7 @@ defmodule Ecto.Query do
10251026 defp do_exclude ( % Ecto.Query { } = query , :limit ) , do: % { query | limit: nil }
10261027 defp do_exclude ( % Ecto.Query { } = query , :offset ) , do: % { query | offset: nil }
10271028 defp do_exclude ( % Ecto.Query { } = query , :lock ) , do: % { query | lock: nil }
1029+ defp do_exclude ( % Ecto.Query { } = query , :comments ) , do: % { query | comments: [ ] }
10281030 defp do_exclude ( % Ecto.Query { } = query , :preload ) , do: % { query | preloads: [ ] , assocs: [ ] }
10291031 defp do_exclude ( % Ecto.Query { } = query , :update ) , do: % { query | updates: [ ] }
10301032 defp do_exclude ( % Ecto.Query { } = query , :windows ) , do: % { query | windows: [ ] }
@@ -1151,7 +1153,8 @@ defmodule Ecto.Query do
11511153 end
11521154
11531155 @ from_join_opts [ :as , :prefix , :hints ]
1154- @ no_binds [ :union , :union_all , :except , :except_all , :intersect , :intersect_all ]
1156+ @ no_binds [ :union , :union_all , :except , :except_all , :intersect , :intersect_all ] ++
1157+ [ :pre_comment , :post_comment ]
11551158 @ binds [ :lock , :where , :or_where , :select , :distinct , :order_by , :group_by , :windows ] ++
11561159 [ :having , :or_having , :limit , :offset , :preload , :update , :select_merge , :with_ctes ]
11571160
@@ -2538,6 +2541,56 @@ defmodule Ecto.Query do
25382541 Builder.Lock . build ( query , binding , expr , __CALLER__ )
25392542 end
25402543
2544+ @ doc ~S"""
2545+ Adds a comment *before* the generated statement.
2546+
2547+ The text is rendered as a leading SQL comment, immediately before the
2548+ statement keyword:
2549+
2550+ /* list_users */ SELECT ...
2551+
2552+ This is useful to tag and identify queries in database logs and monitoring
2553+ tools. A leading comment (rather than a trailing one, see `post_comment/2`)
2554+ survives truncation of long statements in logs.
2555+
2556+ The comment must be a compile-time literal string, so the set of comments for
2557+ a given query stays bounded and the query remains safely cacheable. It is
2558+ embedded verbatim and therefore cannot contain `/*`, `*/`, or null bytes. For
2559+ dynamic comments, use the `:comments` option on the repository operation
2560+ instead. Multiple comments may be added and are rendered in order.
2561+
2562+ ## Keywords example
2563+
2564+ from(p in Post, pre_comment: "list_posts", select: p.title)
2565+
2566+ ## Expressions example
2567+
2568+ Post |> pre_comment("list_posts") |> select([p], p.title)
2569+ """
2570+ defmacro pre_comment ( query , expr ) do
2571+ Builder.Comment . build ( :pre , query , expr , __CALLER__ )
2572+ end
2573+
2574+ @ doc ~S"""
2575+ Adds a comment *after* the generated statement.
2576+
2577+ Works like `pre_comment/2` but renders the text as a trailing SQL comment,
2578+ after the statement (the SQLCommenter convention):
2579+
2580+ SELECT ... /* list_users */
2581+
2582+ ## Keywords example
2583+
2584+ from(p in Post, post_comment: "list_posts", select: p.title)
2585+
2586+ ## Expressions example
2587+
2588+ Post |> post_comment("list_posts") |> select([p], p.title)
2589+ """
2590+ defmacro post_comment ( query , expr ) do
2591+ Builder.Comment . build ( :post , query , expr , __CALLER__ )
2592+ end
2593+
25412594
25422595 @ doc ~S"""
25432596 An update query expression.
0 commit comments