On Saturday, July 28, 2018 at 12:58:17 PM UTC-7, Dennis D wrote:
>
> JRuby 9.2
> Sequel 5.10.0 
>
> I've notices couple side effects with clone functionality in Sequel 5.x 
>
> when I have a prepared statement, 
>
> like "<Sequel::JDBC::Dataset/PreparedStatement "INSERT INTO 
> [schema_migrations] ([filename]) VALUES (?)">" 
>
> and whe I do clone to extand it 
>
> ps.clone()
> opts[:prepared_args] get dulicated every time I call clone 
>
> {:from=>[:schema_migrations],
>
>  :bind_vars=>{},
>
>  :prepared_statement_name=>"batch_insert",
>
>  :prepared_type=>:insert,
>
>  :prepared_modify_values=>[{:filename=>:$filename}],
>
>  :orig_dataset=>#<Sequel::JDBC::Dataset: "SELECT * FROM 
> [schema_migrations]">,
>
>  :no_cache_sql=>true,
>
>  :prepared_args=>[:filename],
>
>  :no_delayed_evaluations=>true}
>
> ps.clone()
>
> {:from=>[:schema_migrations],
>
>  :bind_vars=>{},
>
>  :prepared_statement_name=>"batch_insert",
>
>  :prepared_type=>:insert,
>
>  :prepared_modify_values=>[{:filename=>:$filename}],
>
>  :orig_dataset=>#<Sequel::JDBC::Dataset: "SELECT * FROM 
> [schema_migrations]">,
>
>  :no_cache_sql=>true,
>
>  :prepared_args=>[:filename, :filename],
>
>  :no_delayed_evaluations=>true}
>

My guess is when you clone a prepared statement, it probably doesn't keep 
the cached prepared sql, so it recalculates the prepared_args, appending to 
the existing values.  Trying to clone/extend prepared statements is not 
something I've attempted to support before (only #call on a prepared 
statement is supported).  Something like this patch will probably work for 
your case:

diff --git a/lib/sequel/dataset/prepared_statements.rb 
b/lib/sequel/dataset/prepared_statements.rb
index bb26ea404..b02096307 100644
--- a/lib/sequel/dataset/prepared_statements.rb
+++ b/lib/sequel/dataset/prepared_statements.rb
@@ -315,7 +315,9 @@ module Sequel
     #   DB.call(:select_by_name, name: 'Blah') # Same thing
     def prepare(type, name, *values)
       ps = to_prepared_statement(type, values, :name=>name, 
:extend=>prepared_statement_modules, :no_delayed_evaluations=>true)
-      ps.prepared_sql
+      sql = ps.prepared_sql
+      ps.prepared_args.freeze
+      ps = ps.clone(:prepared_sql=>sql, :sql=>sql)
       db.set_prepared_statement(name, ps)
       ps
     end

However it would break the case where prepared statement support is 
emulated via string interpolation because the adapter lacks native support, 
as in those cases the SQL cannot be cached.  The code could probably be 
changed to add a flag for the emulated vs not-emulated case, and only run 
that code in the not-emulated case.  However, it's fairly close until the 
next release, and such a change needs testing on all adapters, so it's 
probably not a change that would make 5.11.0.

Thanks,
Jeremy

-- 
You received this message because you are subscribed to the Google Groups 
"sequel-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sequel-talk.
For more options, visit https://groups.google.com/d/optout.

Reply via email to