Project

General

Profile

Feature #4939 » issue4939_match_operators.patch

Patch for match operators; patch file based on orfilter patch - Emanuel Reisinger, 2019-10-07 17:51

View differences:

config/locales/en.yml (date 1570461592896)
1077 1077
  label_orfilter_and_any: "AND any following"
1078 1078
  label_orfilter_or_any: "OR any following"
1079 1079
  label_orfilter_or_all: "OR all following"
1080
  label_match: "match"
1081
  label_not_match: "not match"
1080 1082

  
1081 1083
  button_login: Login
1082 1084
  button_submit: Submit
app/models/query.rb (date 1570461296060)
290 290
    "!p"  => :label_no_issues_in_project,
291 291
    "*o"  => :label_any_open_issues,
292 292
    "!o"  => :label_no_open_issues,
293
    "match"  => :label_match,
294
    "!match" => :label_not_match
293 295
  }
294 296

  
295 297
  class_attribute :operators_by_filter_type
......
301 303
    :date => [ "=", ">=", "<=", "><", "<t+", ">t+", "><t+", "t+", "nd", "t", "ld", "nw", "w", "lw", "l2w", "nm", "m", "lm", "y", ">t-", "<t-", "><t-", "t-", "!*", "*" ],
302 304
    :date_past => [ "=", ">=", "<=", "><", ">t-", "<t-", "><t-", "t-", "t", "ld", "w", "lw", "l2w", "m", "lm", "y", "!*", "*" ],
303 305
    :string => [ "~", "=", "!~", "!", "^", "$", "!*", "*" ],
304
    :text => [  "~", "!~", "^", "$", "!*", "*" ],
306
    :text => [  "~", "!~", "^", "$", "!*", "*", "match", "!match" ],
305 307
    :integer => [ "=", ">=", "<=", "><", "!*", "*" ],
306 308
    :float => [ "=", ">=", "<=", "><", "!*", "*" ],
307 309
    :relation => ["=", "=p", "=!p", "!p", "*o", "!o", "!*", "*"],
......
1324 1326
      sql = sql_contains("#{db_table}.#{db_field}", value.first, :starts_with => true)
1325 1327
    when "$"
1326 1328
      sql = sql_contains("#{db_table}.#{db_field}", value.first, :ends_with => true)
1329
    when "match"
1330
      sql = sql_for_match_operators(field, operator, value, db_table, db_field, is_custom_filter)
1331
    when "!match"
1332
      sql = sql_for_match_operators(field, operator, value, db_table, db_field, is_custom_filter)
1327 1333
    else
1328 1334
      raise "Unknown query operator #{operator}"
1329 1335
    end
1330 1336

  
1337
    return sql
1338
  end
1339

  
1340
  def sql_for_match_operators(field, operator, value, db_table, db_field, is_custom_filter=false)
1341
    sql = ''
1342
    v = "(" + value.first.strip + ")"
1343

  
1344
    match = true
1345
    op = ""
1346
    term = ""
1347
    in_term = false
1348

  
1349
    in_bracket = false
1350

  
1351
    v.chars.each do |c|
1352

  
1353
      if (!in_bracket && "()+~!".include?(c) && in_term  ) || (in_bracket && "}".include?(c))
1354
        if !term.empty?
1355
          sql += "(" + sql_contains("#{db_table}.#{db_field}", term, match) + ")"
1356
        end
1357
        #reset
1358
        op = ""
1359
        term = ""
1360
        in_term = false
1361

  
1362
        in_bracket = (c == "{")
1363
      end
1364

  
1365
      if in_bracket && (!"{}".include? c)
1366
        term += c
1367
        in_term = true
1368
      else
1369

  
1370
        case c
1371
        when "{"
1372
          in_bracket = true
1373
        when "}"
1374
          in_bracket = false
1375
        when "("
1376
          sql += c
1377
        when ")"
1378
          sql += c
1379
        when "+"
1380
          sql += " AND " if sql.last != "("
1381
        when "~"
1382
          sql += " OR " if sql.last != "("
1383
        when "!"
1384
          sql += " NOT "
1385
        else
1386
          if c != " "
1387
            term += c
1388
            in_term = true
1389
          end
1390
        end
1391

  
1392
      end
1393
    end
1394

  
1395
    if operator.include? "!"
1396
      sql = " NOT " + sql
1397
    end
1398

  
1399
    Rails.logger.info "MATCH EXPRESSION: V=#{value.first}, SQL=#{sql}"
1331 1400
    return sql
1332 1401
  end
1333 1402

  
test/unit/query_test.rb (date 1570461091027)
1381 1381
    assert_equal [5, 8, 9], issues.collect(&:id).sort
1382 1382
  end
1383 1383

  
1384
  def test_filter_on_subject_match
1385
    query = IssueQuery.new(:name => '_')
1386
    query.filters = {'subject' => {:operator => 'match', :values => ['issue']}}
1387
    issues = find_issues_with_query(query)
1388
    assert_equal [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], issues.collect(&:id).sort
1389

  
1390
    query = IssueQuery.new(:name => '_')
1391
    query.filters = {'subject' => {:operator => 'match', :values => ['(~project ~recipe) +!sub']}}
1392
    issues = find_issues_with_query(query)
1393
    assert_equal [1, 3, 4, 14], issues.collect(&:id).sort
1394

  
1395
    query = IssueQuery.new(:name => '_')
1396
    query.filters = {'subject' => {:operator => 'match', :values => ['!(~sub project ~block) +issue']}}
1397
    issues = find_issues_with_query(query)
1398
    assert_equal [4, 7, 8, 11, 12, 14], issues.collect(&:id).sort
1399

  
1400
    query = IssueQuery.new(:name => '_')
1401
    query.filters = {'subject' => {:operator => 'match', :values => ['+{closed ver} ~{locked ver}']}}
1402
    issues = find_issues_with_query(query)
1403
    assert_equal [11, 12], issues.collect(&:id).sort
1404
  end
1405

  
1406
  def test_filter_on_subject_not_match
1407
    query = IssueQuery.new(:name => '_')
1408
    query.filters = {'subject' => {:operator => '!match', :values => ['issue']}}
1409
    issues = find_issues_with_query(query)
1410
    assert_equal [1, 2, 3], issues.collect(&:id).sort
1411

  
1412
    query = IssueQuery.new(:name => '_')
1413
    query.filters = {'subject' => {:operator => '!match', :values => ['(~project ~recipe) +!sub']}}
1414
    issues = find_issues_with_query(query)
1415
    assert_equal [2, 5, 6, 7, 8, 9, 10, 11, 12, 13], issues.collect(&:id).sort
1416

  
1417
    query = IssueQuery.new(:name => '_')
1418
    query.filters = {'subject' => {:operator => '!match', :values => ['!(~sub project ~block) +issue']}}
1419
    issues = find_issues_with_query(query)
1420
    assert_equal [1, 2, 3, 5, 6, 9, 10, 13], issues.collect(&:id).sort
1421

  
1422
    query = IssueQuery.new(:name => '_')
1423
    query.filters = {'subject' => {:operator => '!match', :values => ['+{closed ver} ~{locked ver}']}}
1424
    issues = find_issues_with_query(query)
1425
    assert_equal [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 13, 14], issues.collect(&:id).sort
1426
  end
1427

  
1384 1428
  def test_filter_on_orfilter_and_any
1385 1429
    query = IssueQuery.new(:name => '_')
1386 1430
    query.filters = {'project_id' => {:operator => '=', :values => [1]},
(7-7/15)