wip
This commit is contained in:
parent
58b3c4f148
commit
9338ac0bcb
37
lib/dao.js
37
lib/dao.js
|
@ -1540,6 +1540,12 @@ DataAccessObject.find = function find(query, options, cb) {
|
|||
let geoQueryObject;
|
||||
|
||||
if (near) {
|
||||
if (options.splitLongInq) {
|
||||
const msg = g.f('The option "splitLongInq" is not supported for near/geo queries.');
|
||||
const error = new Error(msg);
|
||||
cb(error);
|
||||
return cb.promise;
|
||||
}
|
||||
if (supportsGeo) {
|
||||
// convert it
|
||||
connector.buildNearFilter(query, near);
|
||||
|
@ -1568,7 +1574,6 @@ DataAccessObject.find = function find(query, options, cb) {
|
|||
// already handled
|
||||
return cb.promise;
|
||||
}
|
||||
}
|
||||
|
||||
function geoCallback(err, data) {
|
||||
const memory = new Memory();
|
||||
|
@ -1599,6 +1604,25 @@ DataAccessObject.find = function find(query, options, cb) {
|
|||
geoQueryObject = query;
|
||||
near = query && geo.nearFilter(query.where);
|
||||
invokeConnectorMethod(connector, 'all', self, [{}], options, geoCallback);
|
||||
}
|
||||
|
||||
function queryWithInqSplit() {
|
||||
const inqLimit = self.dataSource && self.dataSource.settings &&
|
||||
self.dataSource.settings.inqLimit || 256;
|
||||
|
||||
// clone the original query
|
||||
const query = Object.assign({}, query);
|
||||
query.where = Object.assign({}, query.where);
|
||||
|
||||
if (query.where.and || query.where.or) {
|
||||
const msg = g.f('The option "splitLongInq" does not support "and" and "or" operators yet.');
|
||||
const error = new Error(msg);
|
||||
cb(error);
|
||||
return cb.promise;
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
function allCb(err, data) {
|
||||
|
@ -1699,6 +1723,11 @@ DataAccessObject.find = function find(query, options, cb) {
|
|||
}
|
||||
|
||||
if (options.notify === false) {
|
||||
if (options.splitLongInq && isInqQuery(query.where)) {
|
||||
queryWithInqSplit();
|
||||
return cb.promise;
|
||||
}
|
||||
|
||||
invokeConnectorMethod(connector, 'all', self, [query], options, allCb);
|
||||
} else {
|
||||
const context = {
|
||||
|
@ -1709,6 +1738,12 @@ DataAccessObject.find = function find(query, options, cb) {
|
|||
};
|
||||
this.notifyObserversOf('access', context, function(err, ctx) {
|
||||
if (err) return cb(err);
|
||||
|
||||
if (options.splitLongInq && isInqQuery(query.where)) {
|
||||
queryWithInqSplit();
|
||||
return;
|
||||
}
|
||||
|
||||
invokeConnectorMethod(connector, 'all', self, [ctx.query], options, allCb);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ const bdd = require('./helpers/bdd-if');
|
|||
const should = require('./init.js');
|
||||
const uid = require('./helpers/uid-generator');
|
||||
|
||||
let db, User;
|
||||
let db, User, Product;
|
||||
|
||||
describe('basic-querying', function() {
|
||||
before(function(done) {
|
||||
|
@ -52,6 +52,11 @@ describe('basic-querying', function() {
|
|||
(db.adapter.name != 'informix') && (db.adapter.name != 'cassandra');
|
||||
if (connectorCapabilities.geoPoint) userModelDef.addressLoc = {type: 'GeoPoint'};
|
||||
User = db.define('User', userModelDef);
|
||||
|
||||
Product = db.define('Product', {
|
||||
name: {type: String, required: true},
|
||||
});
|
||||
|
||||
db.automigrate(done);
|
||||
});
|
||||
|
||||
|
@ -1127,6 +1132,71 @@ describe('basic-querying', function() {
|
|||
}, done);
|
||||
});
|
||||
});
|
||||
|
||||
bdd.describeIf(connectorCapabilities.supportInq !== false, 'inq query', () => {
|
||||
let originalInqLimit;
|
||||
let originalAll;
|
||||
let observedCalls;
|
||||
|
||||
before(async function setupTestModels() {
|
||||
Product = db.define('Product', {
|
||||
name: {type: String, required: true},
|
||||
});
|
||||
|
||||
await db.automigrate(Product.modelName);
|
||||
|
||||
originalInqLimit = db.settings.inqLimit;
|
||||
originalAll = db.connector.all;
|
||||
|
||||
if ((db.settings.inqLimit || Infinity) > 5) {
|
||||
// artificially reduce the inqLimit to a small number to trigger
|
||||
// inq splitting even for connectors that support arbitrarily-long
|
||||
// inq lists and also to keep the test fast
|
||||
db.settings.inqLimit = 3;
|
||||
}
|
||||
});
|
||||
|
||||
afterEach(function restoreOriginalState() {
|
||||
db.settings.inqLimit = originalInqLimit;
|
||||
db.connector.all = originalAll;
|
||||
});
|
||||
|
||||
it('rejects geo queries with inq splitting', function() {
|
||||
const where = {
|
||||
id: {inq: [1, 2, 3]},
|
||||
location: {near: {lat: 29.9, lng: -90.07}},
|
||||
};
|
||||
return Product.find({where}, {splitLongInq: true})
|
||||
.should.be.rejectedWith(/splitLongInq.*not supported/);
|
||||
});
|
||||
|
||||
it('splits large inq list', async function() {
|
||||
const observedCalls = [];
|
||||
db.connector.all = function(modelName, query, options, cb) {
|
||||
observedCalls.push({modelName, query, options});
|
||||
originalAll.apply(this, arguments);
|
||||
};
|
||||
|
||||
const created = [];
|
||||
// Notice that 10 is not divisible by inqLimit
|
||||
for (let i = 0; i < 10; i++) {
|
||||
// Create a product that we will look for
|
||||
created.push(await Product.create({name: `a-product-${i}`}));
|
||||
// Create also a product that won't be matched by the query
|
||||
await Product.create({name: `another-product-${i}`});
|
||||
}
|
||||
|
||||
const found = await Product.find(
|
||||
{where: {id: {inq: created.map(u => u.id)}}},
|
||||
{splitLongInq: true}
|
||||
);
|
||||
|
||||
// Records were found correctly
|
||||
found.map(u => u.name).should.eql(created.map(u => u.name));
|
||||
// Multiple database queries were sent
|
||||
observedCalls.length.should.be.greaterThan(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// FIXME: This should either be re-enabled or removed.
|
||||
|
|
Loading…
Reference in New Issue