@@ -204,7 +204,7 @@ defmodule Ecto.Query.Builder do
204204 { { :{} , [ ] , [ :fragment , [ ] , [ expr ] ] } , params_acc }
205205 end
206206
207- def escape ( { :fragment , _ , [ query | frags ] } , _type , params_acc , vars , env ) do
207+ def escape ( { :fragment , _ , [ query | frags ] } , _type , { params , acc } , vars , env ) do
208208 pieces = expand_and_split_fragment ( query , env )
209209
210210 if length ( pieces ) != length ( frags ) + 1 do
@@ -214,8 +214,17 @@ defmodule Ecto.Query.Builder do
214214 )
215215 end
216216
217- { frags , params_acc } = Enum . map_reduce ( frags , params_acc , & escape_fragment ( & 1 , & 2 , vars , env ) )
218- { { :{} , [ ] , [ :fragment , [ ] , merge_fragments ( pieces , frags , [ ] ) ] } , params_acc }
217+ { frags , { params , acc , compile_merge? } } =
218+ Enum . map_reduce ( frags , { params , acc , true } , & escape_fragment ( & 1 , & 2 , vars , env ) )
219+
220+ merged =
221+ if compile_merge? do
222+ merge_fragments ( pieces , frags , [ ] )
223+ else
224+ quote do: Ecto.Query.Builder . merge_fragments ( unquote ( pieces ) , unquote ( frags ) , [ ] )
225+ end
226+
227+ { { :{} , [ ] , [ :fragment , [ ] , merged ] } , { params , acc } }
219228 end
220229
221230 # subqueries
@@ -790,12 +799,10 @@ defmodule Ecto.Query.Builder do
790799 end
791800 end
792801
793- defp escape_fragment ( { :splice , _meta , [ { :^ , _ , [ value ] } = expr ] } , params_acc , vars , env ) do
794- checked = quote do: Ecto.Query.Builder . splice! ( unquote ( value ) )
795- length = quote do: length ( unquote ( checked ) )
796- { expr , params_acc } = escape ( expr , { :splice , :any } , params_acc , vars , env )
797- escaped = { :{} , [ ] , [ :splice , [ ] , [ expr , length ] ] }
798- { escaped , params_acc }
802+ defp escape_fragment ( { :splice , _meta , [ { :^ , _ , [ value ] } ] } , { params , acc , _ } , _vars , _env ) do
803+ checked = quote do: Ecto.Query.Builder . splice! ( unquote ( value ) , length ( unquote ( params ) ) )
804+ param = { value , { :splice , :any } }
805+ { { :splice , checked } , { [ param | params ] , acc , false } }
799806 end
800807
801808 defp escape_fragment ( { :splice , _meta , [ exprs ] } , params_acc , vars , env ) when is_list ( exprs ) do
@@ -811,29 +818,31 @@ defmodule Ecto.Query.Builder do
811818 )
812819 end
813820
814- defp escape_fragment ( expr , params_acc , vars , env ) do
815- escape ( expr , :any , params_acc , vars , env )
821+ defp escape_fragment ( expr , { params , acc , compile_merge? } , vars , env ) do
822+ { expr , { params , acc } } =
823+ escape ( expr , :any , { params , acc } , vars , env )
824+
825+ { expr , { params , acc , compile_merge? } }
816826 end
817827
818- defp merge_fragments ( [ raw_h | raw_t ] , [ { :splice , exprs } | expr_t ] , [ ] ) ,
828+ def merge_fragments ( [ raw_h | raw_t ] , [ { :splice , exprs } | expr_t ] , [ ] ) ,
819829 do: [ { :raw , raw_h } | merge_fragments ( raw_t , expr_t , exprs ) ]
820830
821- defp merge_fragments ( [ raw_h | raw_t ] , [ expr_h | expr_t ] , [ ] ) ,
831+ def merge_fragments ( [ raw_h | raw_t ] , [ expr_h | expr_t ] , [ ] ) ,
822832 do: [ { :raw , raw_h } , { :expr , expr_h } | merge_fragments ( raw_t , expr_t , [ ] ) ]
823833
824- defp merge_fragments ( [ raw_h ] , [ ] , [ ] ) ,
834+ def merge_fragments ( [ raw_h ] , [ ] , [ ] ) ,
825835 do: [ { :raw , raw_h } ]
826836
827- defp merge_fragments ( raw , expr , [ { :splice , exprs } | splice_t ] ) ,
837+ def merge_fragments ( raw , expr , [ { :splice , exprs } | splice_t ] ) ,
828838 do: merge_fragments ( raw , expr , exprs ++ splice_t )
829839
830- defp merge_fragments ( raw , expr , [ splice_h ] ) ,
840+ def merge_fragments ( raw , expr , [ splice_h ] ) ,
831841 do: [ { :expr , splice_h } | merge_fragments ( raw , expr , [ ] ) ]
832842
833- defp merge_fragments ( raw , expr , [ splice_h | splice_t ] ) ,
843+ def merge_fragments ( raw , expr , [ splice_h | splice_t ] ) ,
834844 do: [ { :expr , splice_h } , { :raw , "," } | merge_fragments ( raw , expr , splice_t ) ]
835845
836-
837846 for { agg , arity } <- @ dynamic_aggregates do
838847 defp call_type ( unquote ( agg ) , unquote ( arity ) ) , do: { :any , :any }
839848 end
@@ -1336,9 +1345,9 @@ defmodule Ecto.Query.Builder do
13361345 @ doc """
13371346 Called by escaper at runtime to verify splice in fragments.
13381347 """
1339- def splice! ( value ) do
1348+ def splice! ( value , param_num ) do
13401349 if is_list ( value ) do
1341- value
1350+ Enum . map ( value , fn _ -> { :^ , [ ] , [ param_num ] } end )
13421351 else
13431352 raise ArgumentError ,
13441353 "splice(^value) expects `value` to be a list, got `#{ inspect ( value ) } `"
0 commit comments