From 594ca63b1f8a0e76280757f9f4bbaac51152c4bb Mon Sep 17 00:00:00 2001 From: Abito Prakash Date: Sun, 8 Sep 2024 00:53:28 +0530 Subject: [PATCH 1/4] Modifying where clause by replacing LIKE with ILIKE when is true --- helpers/avg.js | 2 +- helpers/count.js | 2 +- helpers/destroy.js | 2 +- helpers/private/query/compile-statement.js | 7 ++- helpers/private/query/modify-where-clause.js | 61 ++++++++++++++++++++ helpers/select.js | 2 +- helpers/sum.js | 2 +- helpers/update.js | 2 +- 8 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 helpers/private/query/modify-where-clause.js diff --git a/helpers/avg.js b/helpers/avg.js index 1fad2c8..e367423 100644 --- a/helpers/avg.js +++ b/helpers/avg.js @@ -123,7 +123,7 @@ module.exports = require('machine').build({ // Compile the original Waterline Query var compiledQuery; try { - compiledQuery = Helpers.query.compileStatement(statement); + compiledQuery = Helpers.query.compileStatement(statement, query.meta); } catch (e) { return exits.error(e); } diff --git a/helpers/count.js b/helpers/count.js index 8629d4c..786ecae 100644 --- a/helpers/count.js +++ b/helpers/count.js @@ -122,7 +122,7 @@ module.exports = require('machine').build({ // Compile the original Waterline Query var compiledQuery; try { - compiledQuery = Helpers.query.compileStatement(statement); + compiledQuery = Helpers.query.compileStatement(statement, query.meta); } catch (e) { return exits.error(e); } diff --git a/helpers/destroy.js b/helpers/destroy.js index 348411a..eee8001 100644 --- a/helpers/destroy.js +++ b/helpers/destroy.js @@ -142,7 +142,7 @@ module.exports = require('machine').build({ // Compile the original Waterline Query var compiledQuery; try { - compiledQuery = Helpers.query.compileStatement(statement); + compiledQuery = Helpers.query.compileStatement(statement, query.meta); } catch (e) { return exits.error(e); } diff --git a/helpers/private/query/compile-statement.js b/helpers/private/query/compile-statement.js index 05f40a1..1d37d40 100644 --- a/helpers/private/query/compile-statement.js +++ b/helpers/private/query/compile-statement.js @@ -15,8 +15,13 @@ // Transform a Waterline Query Statement into a SQL query. var PG = require('machinepack-postgresql'); +var modifyWhereClause = require('./modify-where-clause'); + +module.exports = function compileStatement(statement, meta) { + if (statement.where) { + statement.where = modifyWhereClause(statement.where, meta); + } -module.exports = function compileStatement(statement) { var report = PG.compileStatement({ statement: statement }).execSync(); diff --git a/helpers/private/query/modify-where-clause.js b/helpers/private/query/modify-where-clause.js new file mode 100644 index 0000000..34ff45d --- /dev/null +++ b/helpers/private/query/modify-where-clause.js @@ -0,0 +1,61 @@ +// ███╗ ███╗ ██████╗ ██████╗ ██╗███████╗██╗ ██╗ ██╗ ██╗██╗ ██╗███████╗██████╗ ███████╗ +// ████╗ ████║██╔═══██╗██╔══██╗██║██╔════╝╚██╗ ██╔╝ ██║ ██║██║ ██║██╔════╝██╔══██╗██╔════╝ +// ██╔████╔██║██║ ██║██║ ██║██║█████╗ ╚████╔╝ ██║ █╗ ██║███████║█████╗ ██████╔╝█████╗ +// ██║╚██╔╝██║██║ ██║██║ ██║██║██╔══╝ ╚██╔╝ ██║███╗██║██╔══██║██╔══╝ ██╔══██╗██╔══╝ +// ██║ ╚═╝ ██║╚██████╔╝██████╔╝██║██║ ██║ ╚███╔███╔╝██║ ██║███████╗██║ ██║███████╗ +// ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝╚═╝ ╚═╝ ╚══╝╚══╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚══════╝ + +// ██████╗██╗ █████╗ ██╗ ██╗███████╗███████╗ +// ██╔════╝██║ ██╔══██╗██║ ██║██╔════╝██╔════╝ +// ██║ ██║ ███████║██║ ██║███████╗█████╗ +// ██║ ██║ ██╔══██║██║ ██║╚════██║██╔══╝ +// ╚██████╗███████╗██║ ██║╚██████╔╝███████║███████╗ +// ╚═════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚══════╝ + +// Modify the where clause of a query object + +var _ = require("@sailshq/lodash"); + +module.exports = function modifyWhereClause(whereClause, meta) { + // Handle empty `where` clause. + if (_.keys(whereClause).length === 0) { + return whereClause; + } + + var makeLikeModifierCaseInsensitive = meta && meta.makeLikeModifierCaseInsensitive; + + // Recursively modify the `where` clause. + var queryFilter = (function recurse(branch) { + var loneKey = _.first(_.keys(branch)); + + // Handle AND/OR conditions + if (loneKey === "and" || loneKey === "or") { + var conjunctsOrDisjuncts = branch[loneKey]; + branch[loneKey] = _.map(conjunctsOrDisjuncts, function (conjunctOrDisjunct) { + return recurse(conjunctOrDisjunct); + }); + + return branch; + } + + // We're dealing with a constraint of some kind. + var constraintColumnName = loneKey; + var constraint = branch[constraintColumnName]; + + // If it's a primitive, return as is. + if (_.isString(constraint) || _.isNumber(constraint) || _.isBoolean(constraint) || _.isNull(constraint)) { + return branch; + } + + // Modify `LIKE` to `ILIKE` if case insensitivity is enabled. + if (constraint.like && makeLikeModifierCaseInsensitive) { + constraint.ilike = constraint.like; + delete constraint.like; + } + + return branch; + })(whereClause); + + // Return the modified Postgres query filter. + return queryFilter; +}; diff --git a/helpers/select.js b/helpers/select.js index ce8c3b1..b3c1efa 100644 --- a/helpers/select.js +++ b/helpers/select.js @@ -124,7 +124,7 @@ module.exports = require('machine').build({ // Compile the original Waterline Query var compiledQuery; try { - compiledQuery = Helpers.query.compileStatement(statement); + compiledQuery = Helpers.query.compileStatement(statement, query.meta); } catch (e) { return exits.error(e); } diff --git a/helpers/sum.js b/helpers/sum.js index 0c4c997..5e04fa8 100644 --- a/helpers/sum.js +++ b/helpers/sum.js @@ -123,7 +123,7 @@ module.exports = require('machine').build({ // Compile the original Waterline Query var compiledQuery; try { - compiledQuery = Helpers.query.compileStatement(statement); + compiledQuery = Helpers.query.compileStatement(statement, query.meta); } catch (e) { return exits.error(e); } diff --git a/helpers/update.js b/helpers/update.js index 33d4ea8..fe0725f 100644 --- a/helpers/update.js +++ b/helpers/update.js @@ -171,7 +171,7 @@ module.exports = require('machine').build({ // Compile statement into a native query. var compiledQuery; try { - compiledQuery = Helpers.query.compileStatement(statement); + compiledQuery = Helpers.query.compileStatement(statement, query.meta); } catch (e) { return exits.error(e); } From 0d7b56bcbd3c4c0cc9204b89908b3f397f898c95 Mon Sep 17 00:00:00 2001 From: Abito Prakash Date: Sun, 8 Sep 2024 00:53:54 +0530 Subject: [PATCH 2/4] Adding test cases to check case insensitivity and eslint fix --- lib/private/redact-passwords.js | 2 +- test/adapter/unit/destroy.js | 32 ++++++++++++++++++++++++++++++++ test/adapter/unit/find.js | 28 ++++++++++++++++++++++++++++ test/adapter/unit/update.js | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 1 deletion(-) diff --git a/lib/private/redact-passwords.js b/lib/private/redact-passwords.js index cffa70d..bea7c77 100644 --- a/lib/private/redact-passwords.js +++ b/lib/private/redact-passwords.js @@ -28,4 +28,4 @@ module.exports = function redactPasswords(err) { } } return err; -} +}; diff --git a/test/adapter/unit/destroy.js b/test/adapter/unit/destroy.js index 8300277..d3febdc 100644 --- a/test/adapter/unit/destroy.js +++ b/test/adapter/unit/destroy.js @@ -47,6 +47,38 @@ describe('Unit Tests ::', function() { }); }); + it('should ensure the record is deleted with case insensitive like', function(done) { + var query = { + using: 'test_destroy', + criteria: { + where: { + fieldB: { + like: 'BAR' + } + } + }, + meta: { + makeLikeModifierCaseInsensitive: true + } + }; + + Adapter.destroy('test', query, function(err) { + if (err) { + return done(err); + } + + Adapter.find('test', query, function(err, results) { + if (err) { + return done(err); + } + + assert.equal(results.length, 0); + + return done(); + }); + }); + }); + // Look into the bowels of the PG Driver and ensure the Create function handles // it's connections properly. it('should release its connection when completed', function(done) { diff --git a/test/adapter/unit/find.js b/test/adapter/unit/find.js index f02f90b..f8553a7 100644 --- a/test/adapter/unit/find.js +++ b/test/adapter/unit/find.js @@ -88,6 +88,34 @@ describe('Unit Tests ::', function() { }); }); + it('should be case insensitive when `meta.makeLikeModifierCaseInsensitive` is true', function(done) { + var query = { + using: 'test_find', + criteria: { + where: { + fieldB: { + like: 'bar_2' + } + } + }, + meta: { + makeLikeModifierCaseInsensitive: true + } + }; + + Adapter.find('test', query, function(err, results) { + if (err) { + return done(err); + } + + assert(_.isArray(results)); + assert.equal(results.length, 1); + assert.equal(_.first(results).fieldB, 'bAr_2'); + + return done(); + }); + }); + it('should return `ref` type attributes unchanged', function(done) { var query = { using: 'test_find', diff --git a/test/adapter/unit/update.js b/test/adapter/unit/update.js index 1f3bff6..330a2f5 100644 --- a/test/adapter/unit/update.js +++ b/test/adapter/unit/update.js @@ -81,6 +81,39 @@ describe('Unit Tests ::', function() { }); }); + it('should be case insensitive when `meta.makeLikeModifierCaseInsensitive` is true', function(done) { + var query = { + using: 'test_update', + criteria: { + where: { + fieldB: { + like: 'bar_2' + } + } + }, + valuesToSet: { + fieldA: 'FooBar2' + }, + meta: { + fetch: true, + makeLikeModifierCaseInsensitive: true + } + }; + + Adapter.update('test', query, function(err, results) { + if (err) { + return done(err); + } + + assert(_.isArray(results)); + assert.equal(results.length, 1); + assert.equal(_.first(results).fieldA, 'FooBar2'); + assert.equal(_.first(results).fieldB, 'bAr_2'); + + return done(); + }); + }); + // Look into the bowels of the PG Driver and ensure the Create function handles // it's connections properly. it('should release its connection when completed', function(done) { From 2d36620361c49a83a3cca9eaaa765f63d58fc885 Mon Sep 17 00:00:00 2001 From: Abito Prakash Date: Sun, 8 Sep 2024 00:58:17 +0530 Subject: [PATCH 3/4] Fix - comment in modify-where-clause --- helpers/private/query/modify-where-clause.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers/private/query/modify-where-clause.js b/helpers/private/query/modify-where-clause.js index 34ff45d..74c5dfc 100644 --- a/helpers/private/query/modify-where-clause.js +++ b/helpers/private/query/modify-where-clause.js @@ -56,6 +56,6 @@ module.exports = function modifyWhereClause(whereClause, meta) { return branch; })(whereClause); - // Return the modified Postgres query filter. + // Return the modified query filter. return queryFilter; }; From dd558ccb99b50fd9dc34b3f8cdf98e7aed461964 Mon Sep 17 00:00:00 2001 From: Abito Prakash Date: Sun, 8 Sep 2024 01:01:51 +0530 Subject: [PATCH 4/4] Refactor modifyWhereClause to handle missing meta --- helpers/private/query/modify-where-clause.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/helpers/private/query/modify-where-clause.js b/helpers/private/query/modify-where-clause.js index 74c5dfc..a808e5e 100644 --- a/helpers/private/query/modify-where-clause.js +++ b/helpers/private/query/modify-where-clause.js @@ -17,12 +17,12 @@ var _ = require("@sailshq/lodash"); module.exports = function modifyWhereClause(whereClause, meta) { - // Handle empty `where` clause. - if (_.keys(whereClause).length === 0) { + // Handle empty `where` clause and missing meta. + if (_.keys(whereClause).length === 0 || !meta) { return whereClause; } - var makeLikeModifierCaseInsensitive = meta && meta.makeLikeModifierCaseInsensitive; + var makeLikeModifierCaseInsensitive = meta.makeLikeModifierCaseInsensitive; // Recursively modify the `where` clause. var queryFilter = (function recurse(branch) {