jeremyevans / sequel

Sequel: The Database Toolkit for Ruby
http://sequel.jeremyevans.net
Other
4.99k stars 1.07k forks source link

feature request: support for Ruby Sets #1997

Closed will closed 1 year ago

will commented 1 year ago

Complete Description of Issue

With Set being fully in Ruby 3.2 without needing to require it, I think it'd be nice if you could pass sets into queries directly.

I know you can cast it down to an array, which is what I do now, so it's not really that necessary of a feature.

Simplest Possible Self-Contained Example Showing the request

> DB["select 'two' in ?", ["one", "two"]].all
(0.000527s) select 'two' in ('one', 'two')
[{:"?column?"=>true}]

> DB["select 'two' in ?", Set.new(["one", "two"])].all
lib/sequel/dataset/sql.rb:1406:in `literal_other_append': can't express #<Set: {"one", "two"}> as a SQL literal (Sequel::Error)

Full Backtrace of Exception (if any)

/nix/store/l9ffj3pjchr33n671g0xqdx1cvk4min4-ruby3.2.0-sequel-5.65.0/lib/ruby/gems/3.2.0/gems/sequel-5.65.0/lib/sequel/dataset/sql.rb:1406:in `literal_other_append': can't express #<Set: {"one", "two"}> as a SQL literal (Sequel::Error)
    from /nix/store/l9ffj3pjchr33n671g0xqdx1cvk4min4-ruby3.2.0-sequel-5.65.0/lib/ruby/gems/3.2.0/gems/sequel-5.65.0/lib/sequel/extensions/pg_range.rb:292:in `literal_other_append'
    from /nix/store/l9ffj3pjchr33n671g0xqdx1cvk4min4-ruby3.2.0-sequel-5.65.0/lib/ruby/gems/3.2.0/gems/sequel-5.65.0/lib/sequel/dataset/sql.rb:89:in `literal_append'
    from /nix/store/l9ffj3pjchr33n671g0xqdx1cvk4min4-ruby3.2.0-sequel-5.65.0/lib/ruby/gems/3.2.0/gems/sequel-5.65.0/lib/sequel/dataset/sql.rb:635:in `placeholder_literal_string_sql_append'
    from /nix/store/l9ffj3pjchr33n671g0xqdx1cvk4min4-ruby3.2.0-sequel-5.65.0/lib/ruby/gems/3.2.0/gems/sequel-5.65.0/lib/sequel/sql.rb:112:in `to_s_append'
    from /nix/store/l9ffj3pjchr33n671g0xqdx1cvk4min4-ruby3.2.0-sequel-5.65.0/lib/ruby/gems/3.2.0/gems/sequel-5.65.0/lib/sequel/dataset/sql.rb:1364:in `literal_expression_append'
    from /nix/store/l9ffj3pjchr33n671g0xqdx1cvk4min4-ruby3.2.0-sequel-5.65.0/lib/ruby/gems/3.2.0/gems/sequel-5.65.0/lib/sequel/dataset/sql.rb:67:in `literal_append'
    from /nix/store/l9ffj3pjchr33n671g0xqdx1cvk4min4-ruby3.2.0-sequel-5.65.0/lib/ruby/gems/3.2.0/gems/sequel-5.65.0/lib/sequel/dataset/sql.rb:266:in `literal'
    from /nix/store/l9ffj3pjchr33n671g0xqdx1cvk4min4-ruby3.2.0-sequel-5.65.0/lib/ruby/gems/3.2.0/gems/sequel-5.65.0/lib/sequel/dataset/sql.rb:1720:in `static_sql'
    from /nix/store/l9ffj3pjchr33n671g0xqdx1cvk4min4-ruby3.2.0-sequel-5.65.0/lib/ruby/gems/3.2.0/gems/sequel-5.65.0/lib/sequel/dataset/sql.rb:239:in `select_sql'
    from /nix/store/l9ffj3pjchr33n671g0xqdx1cvk4min4-ruby3.2.0-sequel-5.65.0/lib/ruby/gems/3.2.0/gems/sequel-5.65.0/lib/sequel/dataset/actions.rb:164:in `each'
    from /nix/store/blbkf3dqcjymy1jj9s15xa3vhkwyfkl1-ruby3.2.0-sequel_pg-1.17.1/lib/ruby/gems/3.2.0/gems/sequel_pg-1.17.1/lib/sequel_pg/sequel_pg.rb:83:in `each'
    from /nix/store/l9ffj3pjchr33n671g0xqdx1cvk4min4-ruby3.2.0-sequel-5.65.0/lib/ruby/gems/3.2.0/gems/sequel-5.65.0/lib/sequel/dataset/actions.rb:51:in `block in all'
    from /nix/store/l9ffj3pjchr33n671g0xqdx1cvk4min4-ruby3.2.0-sequel-5.65.0/lib/ruby/gems/3.2.0/gems/sequel-5.65.0/lib/sequel/dataset/actions.rb:1093:in `_all'
    from /nix/store/l9ffj3pjchr33n671g0xqdx1cvk4min4-ruby3.2.0-sequel-5.65.0/lib/ruby/gems/3.2.0/gems/sequel-5.65.0/lib/sequel/dataset/actions.rb:51:in `all'
    from (irb):71:in `<main>'
    from /Users/will/code/owl/bin/irb:30:in `<main>'
jeremyevans commented 1 year ago

Set actually isn't fully in Ruby 3.2, it's just autoloaded:

$ ruby -ve 'p Object.autoload?(:Set)'
ruby 3.2.0 (2022-12-25 revision a528908271) [x86_64-openbsd]
"set"

So if you don't use it, you don't pay the penalty for loading it. Having Sequel handle Set would force the autoloading.

If you want this behavior, it is fairly easy to add:

class Set
  def sql_literal_append(ds, sql)
    ds.literal_append(sql, to_a)
  end
end

Maybe I can add a Dataset extension that supports Set so that users that want this behavior can get it.

In the future, as discussed in the contribution guidelines, please use GitHub Discussions for feature requests. Only open a GitHub Issue to report a bug in Sequel.

will commented 1 year ago

Ah sorry! I haven't read those in a long time

jeremyevans commented 1 year ago

@will I added a set_literalizer extension, it will be in the next release: a3e8a3f802c2f67225fdc0ccbf33f62e8419f917

will commented 1 year ago

Oh cool, thanks, and thanks for coming back to this issue!