@@ -215,7 +215,7 @@ defmodule Ecto.Query.Builder do
215215 end
216216
217217 { frags , params_acc } = Enum . map_reduce ( frags , params_acc , & escape_fragment ( & 1 , & 2 , vars , env ) )
218- { { :{} , [ ] , [ :fragment , [ ] , merge_fragments ( pieces , frags ) ] } , params_acc }
218+ { { :{} , [ ] , [ :fragment , [ ] , merge_fragments ( pieces , frags , [ ] ) ] } , params_acc }
219219 end
220220
221221 # subqueries
@@ -638,7 +638,7 @@ defmodule Ecto.Query.Builder do
638638 def fragment_pieces ( frag , args ) do
639639 frag
640640 |> split_fragment ( "" )
641- |> merge_fragments ( args )
641+ |> merge_fragments ( args , [ ] )
642642 end
643643
644644 defp escape_window_description ( [ ] , params_acc , _vars , _env ) ,
@@ -791,31 +791,49 @@ defmodule Ecto.Query.Builder do
791791 end
792792 end
793793
794- defp escape_fragment ( { :splice , _meta , [ splice ] } , params_acc , vars , env ) do
795- case splice do
796- { :^ , _ , [ value ] } = expr ->
797- checked = quote do: Ecto.Query.Builder . splice! ( unquote ( value ) )
798- length = quote do: length ( unquote ( checked ) )
799- { expr , params_acc } = escape ( expr , { :splice , :any } , params_acc , vars , env )
800- escaped = { :{} , [ ] , [ :splice , [ ] , [ expr , length ] ] }
801- { escaped , params_acc }
794+ defp escape_fragment ( { :splice , _meta , [ { :^ , _ , [ value ] } = expr ] } , params_acc , vars , env ) do
795+ checked = quote do: Ecto.Query.Builder . splice! ( unquote ( value ) )
796+ length = quote do: length ( unquote ( checked ) )
797+ { expr , params_acc } = escape ( expr , { :splice , :any } , params_acc , vars , env )
798+ escaped = { :{} , [ ] , [ :splice , [ ] , [ expr , length ] ] }
799+ { escaped , params_acc }
800+ end
802801
803- _ ->
804- error! (
805- "splice/1 in fragment expects an interpolated value, such as splice(^value), got `#{ Macro . to_string ( splice ) } `"
806- )
807- end
802+ defp escape_fragment ( { :splice , _meta , [ exprs ] } , params_acc , vars , env ) when is_list ( exprs ) do
803+ { escaped , params_acc } =
804+ Enum . map_reduce ( exprs , params_acc , & escape_fragment ( & 1 , & 2 , vars , env ) )
805+
806+ { { :splice , escaped } , params_acc }
807+ end
808+
809+ defp escape_fragment ( { :splice , _meta , [ other ] } , _params_acc , _vars , _env ) do
810+ error! (
811+ "splice/1 in fragment expects a compile-time list or interpolated value, got `#{ Macro . to_string ( other ) } `"
812+ )
808813 end
809814
810815 defp escape_fragment ( expr , params_acc , vars , env ) do
811816 escape ( expr , :any , params_acc , vars , env )
812817 end
813818
814- defp merge_fragments ( [ h1 | t1 ] , [ h2 | t2 ] ) ,
815- do: [ { :raw , h1 } , { :expr , h2 } | merge_fragments ( t1 , t2 ) ]
819+ defp merge_fragments ( [ raw_h | raw_t ] , [ { :splice , exprs } | expr_t ] , [ ] ) ,
820+ do: [ { :raw , raw_h } | merge_fragments ( raw_t , expr_t , exprs ) ]
821+
822+ defp merge_fragments ( [ raw_h | raw_t ] , [ expr_h | expr_t ] , [ ] ) ,
823+ do: [ { :raw , raw_h } , { :expr , expr_h } | merge_fragments ( raw_t , expr_t , [ ] ) ]
824+
825+ defp merge_fragments ( [ raw_h ] , [ ] , [ ] ) ,
826+ do: [ { :raw , raw_h } ]
827+
828+ defp merge_fragments ( raw , expr , [ { :splice , exprs } | splice_t ] ) ,
829+ do: merge_fragments ( raw , expr , exprs ++ splice_t )
830+
831+ defp merge_fragments ( raw , expr , [ splice_h ] ) ,
832+ do: [ { :expr , splice_h } | merge_fragments ( raw , expr , [ ] ) ]
833+
834+ defp merge_fragments ( raw , expr , [ splice_h | splice_t ] ) ,
835+ do: [ { :expr , splice_h } , { :raw , "," } | merge_fragments ( raw , expr , splice_t ) ]
816836
817- defp merge_fragments ( [ h1 ] , [ ] ) ,
818- do: [ { :raw , h1 } ]
819837
820838 for { agg , arity } <- @ dynamic_aggregates do
821839 defp call_type ( unquote ( agg ) , unquote ( arity ) ) , do: { :any , :any }
0 commit comments