From 7b600800901067d43644f287b5f8148d17f3cd9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=C3=89vrard?= Date: Wed, 27 Jun 2018 10:25:17 +0200 Subject: [PATCH] Add (i)like support to domain inversion issue7522 review58261002 --- CHANGELOG | 1 + src/common.js | 53 +++++++++++++++++++++++++++++++++++++++++++++++---- tests/sao.js | 33 ++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 0f7c038a41..e7c66543f3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Add (i)like support to domain inversion * Improve loading strategy by using views * Add support of width attribute on tree view * Use non conflicting keyboard shortcuts diff --git a/src/common.js b/src/common.js index 50df92abdc..c66fbd42c4 100644 --- a/src/common.js +++ b/src/common.js @@ -2021,11 +2021,19 @@ 'not in': function(a, b) { return !Sao.common.DomainInversion.in_(a, b); }, + 'like': function(a, b) { + return Sao.common.DomainInversion.sql_like(a, b, false); + }, + 'ilike': function(a, b) { + return Sao.common.DomainInversion.sql_like(a, b, true); + }, + 'not like': function(a, b) { + return !Sao.common.DomainInversion.sql_like(a, b, false); + }, + 'not ilike': function(a, b) { + return !Sao.common.DomainInversion.sql_like(a, b, true); + }, // Those operators are not supported (yet ?) - 'like': function() {return true;}, - 'ilike': function() {return true;}, - 'not like': function() {return true;}, - 'not ilike': function() {return true;}, 'child_of': function() {return true;}, 'not child_of': function() {return true;} }, @@ -2285,6 +2293,43 @@ return Boolean(~b.indexOf(a)); } }; + Sao.common.DomainInversion.sql_like = function(value, pattern, ignore_case) + { + var escape = false; + var chars = []; + var splitted = pattern.split(/(.|\\)/); + var char; + for (var i=1, len=splitted.length; i < len; i = i+2) { + char = splitted[i]; + if (escape) { + if ((char == '%') || (char == '_')) { + chars.push(char); + } else { + chars.push('\\', char); + } + escape = false; + } else if (char == '\\') { + escape = true; + } else if (char == '_') { + chars.push('.'); + } else if (char == '%') { + chars.push('.*'); + } else { + chars.push(char); + } + } + + if (!pattern.startsWith('%')) { + chars.splice(0, 0, '^'); + } + if (!pattern.endsWith('%')) { + chars.push('$'); + } + + var flags = ignore_case ? 'i' : ''; + var regexp = new RegExp(chars.join(''), flags); + return regexp.test(value); + }; Sao.common.DomainInversion.And = Sao.class_(Object, { init: function(expressions) { this.domain_inversion = new Sao.common.DomainInversion(); diff --git a/tests/sao.js b/tests/sao.js index 13157a132b..43e4558dcf 100644 --- a/tests/sao.js +++ b/tests/sao.js @@ -2194,6 +2194,39 @@ [[['x', 'in', [3, 5]]], {'x': [3]}, true], [[['x', 'in', [3, 5]]], {'x': [3, 4]}, true], [[['x', 'in', [3, 5]]], {'x': [1, 2]}, false], + [[['x', 'like', 'abc']], {'x': 'abc'}, true], + [[['x', 'like', 'abc']], {'x': ''}, false], + [[['x', 'like', 'abc']], {'x': 'xyz'}, false], + [[['x', 'like', 'abc']], {'x': 'abcd'}, false], + [[['x', 'not like', 'abc']], {'x': 'xyz'}, true], + [[['x', 'not like', 'abc']], {'x': 'ABC'}, true], + [[['x', 'not like', 'abc']], {'x': 'abc'}, false], + [[['x', 'not ilike', 'abc']], {'x': 'xyz'}, true], + [[['x', 'not ilike', 'abc']], {'x': 'ABC'}, false], + [[['x', 'not ilike', 'abc']], {'x': 'abc'}, false], + [[['x', 'like', 'a%']], {'x': 'a'}, true], + [[['x', 'like', 'a%']], {'x': 'abcde'}, true], + [[['x', 'like', 'a%']], {'x': ''}, false], + [[['x', 'like', 'a%']], {'x': 'ABCDE'}, false], + [[['x', 'like', 'a%']], {'x': 'xyz'}, false], + [[['x', 'ilike', 'a%']], {'x': 'a'}, true], + [[['x', 'ilike', 'a%']], {'x': 'A'}, true], + [[['x', 'ilike', 'a%']], {'x': ''}, false], + [[['x', 'ilike', 'a%']], {'x': 'xyz'}, false], + [[['x', 'like', 'a_']], {'x': 'ab'}, true], + [[['x', 'like', 'a_']], {'x': 'a'}, false], + [[['x', 'like', 'a_']], {'x': 'abc'}, false], + [[['x', 'like', 'a\\%b']], {'x': 'a%b'}, true], + [[['x', 'like', 'a\\%b']], {'x': 'ab'}, false], + [[['x', 'like', 'a\\%b']], {'x': 'a123b'}, false], + [[['x', 'like', '\\%b']], {'x': '%b'}, true], + [[['x', 'like', '\\%b']], {'x': 'b'}, false], + [[['x', 'like', '\\%b']], {'x': '123b'}, false], + [[['x', 'like', 'a\\_c']], {'x': 'a_c'}, true], + [[['x', 'like', 'a\\_c']], {'x': 'abc'}, false], + [[['x', 'like', 'a\\_c']], {'x': 'ac'}, false], + [[['x', 'like', 'a\\\\_c']], {'x': 'a\\bc'}, true], + [[['x', 'like', 'a\\\\_c']], {'x': 'abc'}, false], [['OR', ['x', '>', 10], ['x', '<', 0]], {'x': 11}, true], [['OR', ['x', '>', 10], ['x', '<', 0]], {'x': -4}, true], [['OR', ['x', '>', 10], ['x', '<', 0]], {'x': 5}, false],