rubysql-likesequel

How to combine Sequel.or with Sequel.like? (mssql or sqlite)


I use ruby and sequel in my programm.

I want to execute a deletion in my DB like

DELETE FROM db.tbl WHERE col1 = 'a' and (col2 LIKE '%xxx%' OR col2 LIKE '%yyy%')

But I fail to build the statement with sequel.

I tried to use Sequel.or together with Sequel.like:

DB[:tbl].filter(col1: 'a').filter(
    Sequel.or([Sequel.like(:col2, '%xxx%'),Sequel.like(:col2, '%yyy%')])
    ).delete

This returns me a in ``or': must pass a conditions specifier to Sequel.or (Sequel::Error)

Using a regular expression is not possible with sequel and mssql.

DB[:tbl].filter(col1: 'a').filter(Sequel.like(:col2, /xxx|yyy')).delete

What works is to do it with two statements:

DB[:tbl].filter(col1: 'a').filter(Sequel.like(:col2, '%xxx%')).delete
DB[:tbl].filter(col1: 'a').filter(Sequel.like(:col2, '%yyy%')).delete

But I would prefer to use or, I may get additional values.

A full MWE:

require 'sequel'
Sequel.extension :pretty_table  #Sequel::PrettyTable.print()/Sequel::PrettyTable.string()

DB = Sequel.sqlite
DB.create_table(:tbl){
  primary_key :id
  field :col1, :type => :nvarchar, :size => 10
  field :col2, :type => :nvarchar, :size => 10
} #unless DB.table_exists?(:file)

DB[:tbl].insert(:col1 => 'a', :col2 => 'axxx1')
DB[:tbl].insert(:col1 => 'a', :col2 => 'a2')
DB[:tbl].insert(:col1 => 'a', :col2 => 'ayyy3')

DB[:tbl].insert(:col1 => 'b', :col2 => 'bxxx1')
DB[:tbl].insert(:col1 => 'b', :col2 => 'b2')
DB[:tbl].insert(:col1 => 'b', :col2 => 'byyy3')

#Two statements without Sequel.or work
DB[:tbl].filter(col1: 'a').filter(Sequel.like(:col2, '%xxx%')).delete
DB[:tbl].filter(col1: 'a').filter(Sequel.like(:col2, '%yyy%')).delete

#Does not work
DB[:tbl].filter(col1: 'a').filter(
    Sequel.or([Sequel.like(:col2, '%xxx%'),Sequel.like(:col2, '%yyy%')])
    ).delete

sel = DB[:tbl]
Sequel::PrettyTable.print(sel, sel.columns)

Solution

  • You can use the bitwise OR operator to join the two LIKE conditions:

    DB[:tbl].filter(col1: "a").filter(
      Sequel.like(:col2, "%xxx%") | Sequel.like(:col2, "%yyy%")
    ).delete
    

    Output:

    +--+----+-----+
    |id|col1|col2 |
    +--+----+-----+
    | 2|a   |a2   |
    | 4|b   |bxxx1|
    | 5|b   |b2   |
    | 6|b   |byyy3|
    +--+----+-----+
    

    This is the SQL query Sequel executes (from the logs):

    DELETE FROM `tbl` WHERE ((`col1` = 'a') AND ((`col2` LIKE '%xxx%' ESCAPE '\') OR (`col2` LIKE '%yyy%' ESCAPE '\')))