不要怂,就是干,撸起袖子干!

Commit 7feb5f5e by Mick Hansen

feat: jsonb querying

1 parent 315b4cf7
......@@ -335,9 +335,9 @@ JSONTYPE.prototype.key = JSONTYPE.key = 'JSON';
*/
var JSONB = function() {
if (!(this instanceof JSONB)) return new JSONB();
ABSTRACT.apply(this, arguments);
JSONTYPE.apply(this, arguments);
};
util.inherits(JSONB, ABSTRACT);
util.inherits(JSONB, JSONTYPE);
JSONB.prototype.key = JSONB.key = 'JSONB';
......
......@@ -5,7 +5,8 @@ var Utils = require('../../utils')
, Model = require('../../model')
, DataTypes = require('../../data-types')
, _ = require('lodash')
, util = require('util');
, util = require('util')
, Dottie = require('dottie');
module.exports = (function() {
var QueryGenerator = {
......@@ -1607,8 +1608,21 @@ module.exports = (function() {
, comparatorMap
, aliasMap
, comparator = '='
, field = options.field || options.model && options.model.rawAttributes && options.model.rawAttributes[key] && options.model.rawAttributes[key]
, fieldType = options.type || (field && field.type);
, field = options.field || options.model && options.model.rawAttributes && options.model.rawAttributes[key]
, fieldType = options.type || (field && field.type)
, tmp;
if (key && typeof key === 'string' && key.indexOf('.') !== -1 && options.model) {
if (options.model.rawAttributes[key.split('.')[0]] && options.model.rawAttributes[key.split('.')[0]].type instanceof DataTypes.JSON) {
field = options.model.rawAttributes[key.split('.')[0]];
fieldType = field.type;
tmp = value;
value = {};
Dottie.set(value, key.split('.').slice(1), tmp);
key = key.split('.')[0];
}
}
comparatorMap = {
$eq: '=',
......@@ -1730,6 +1744,51 @@ module.exports = (function() {
}
}
if (_.isPlainObject(value) && fieldType instanceof DataTypes.JSON && options.json !== false) {
//console.log(key, value);
return (function () {
var $items = []
, result
, traverse;
traverse = function (prop, item, path) {
var $where = {}
, $key;
$key = new Utils.literal(self.quoteIdentifier(key)+'#>>\'{'+path.join(', ')+'}\'');
if (_.isPlainObject(item)) {
_.forOwn(item, function ($item, $prop) {
if ($prop.indexOf('$') === 0) {
$where[$prop] = $item;
$items.push(self.whereItemQuery($key, $where, _.pick(options, 'prefix')));
} else {
traverse($prop, $item, path.concat([$prop]));
}
});
} else {
$where.$eq = item;
$items.push(self.whereItemQuery($key, $where, _.pick(options, 'prefix')));
}
};
_.forOwn(value, function (item, prop) {
if (prop.indexOf('$') === 0) {
var $where = {};
$where[prop] = item;
$items.push(self.whereItemQuery(key, $where, _.assign({}, options, {json: false})));
return;
}
traverse(prop, item, [prop]);
});
result = $items.join(' AND ');
return $items.length > 1 ? '('+result+')' : result;
})();
}
// If multiple keys we combine the different logic conditions
if (_.isPlainObject(value) && Object.keys(value).length > 1) {
return (function () {
......@@ -1816,7 +1875,11 @@ module.exports = (function() {
// Really retarded BC^TM
if (key === undefined) key = 'id';
key = this.quoteIdentifier(key);
if (key._isSequelizeMethod) {
key = this.handleSequelizeMethod(key);
} else {
key = this.quoteIdentifier(key);
}
if (options.prefix) {
if (options.prefix instanceof Utils.literal) {
......@@ -1825,6 +1888,7 @@ module.exports = (function() {
key = [this.quoteTable(options.prefix), key].join('.');
}
}
return [key, value].join(' '+comparator+' ');
},
......
......@@ -462,6 +462,72 @@ suite(Support.getTestDialectTeaser('SQL'), function() {
postgres: "profile->>'id' = CAST('12346-78912' AS TEXT)"
});
});
testsql('data', {
nested: {
attribute: 'value'
}
}, {
field: {
type: new DataTypes.JSONB()
},
prefix: 'User'
}, {
default: "[User].[data]#>>'{nested, attribute}' = 'value'"
});
testsql('data.nested.attribute', 'value', {
model: {
rawAttributes: {
data: {
type: new DataTypes.JSONB()
}
}
}
}, {
default: "[data]#>>'{nested, attribute}' = 'value'"
});
testsql('data.nested.attribute', {
$in: [3, 7]
}, {
model: {
rawAttributes: {
data: {
type: new DataTypes.JSONB()
}
}
}
}, {
default: "[data]#>>'{nested, attribute}' IN (3, 7)"
});
testsql('data', {
nested: {
attribute: {
$gt: 2
}
}
}, {
field: {
type: new DataTypes.JSONB()
}
}, {
default: "[data]#>>'{nested, attribute}' > 2"
});
testsql('data', {
$contains: {
company: 'Magnafone'
}
}, {
field: {
type: new DataTypes.JSONB()
}
}, {
default: '[data] @> \'{"company":"Magnafone"}\''
});
});
}
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!