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;
|
let geoQueryObject;
|
||||||
|
|
||||||
if (near) {
|
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) {
|
if (supportsGeo) {
|
||||||
// convert it
|
// convert it
|
||||||
connector.buildNearFilter(query, near);
|
connector.buildNearFilter(query, near);
|
||||||
|
@ -1568,7 +1574,6 @@ DataAccessObject.find = function find(query, options, cb) {
|
||||||
// already handled
|
// already handled
|
||||||
return cb.promise;
|
return cb.promise;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function geoCallback(err, data) {
|
function geoCallback(err, data) {
|
||||||
const memory = new Memory();
|
const memory = new Memory();
|
||||||
|
@ -1599,6 +1604,25 @@ DataAccessObject.find = function find(query, options, cb) {
|
||||||
geoQueryObject = query;
|
geoQueryObject = query;
|
||||||
near = query && geo.nearFilter(query.where);
|
near = query && geo.nearFilter(query.where);
|
||||||
invokeConnectorMethod(connector, 'all', self, [{}], options, geoCallback);
|
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) {
|
function allCb(err, data) {
|
||||||
|
@ -1699,6 +1723,11 @@ DataAccessObject.find = function find(query, options, cb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.notify === false) {
|
if (options.notify === false) {
|
||||||
|
if (options.splitLongInq && isInqQuery(query.where)) {
|
||||||
|
queryWithInqSplit();
|
||||||
|
return cb.promise;
|
||||||
|
}
|
||||||
|
|
||||||
invokeConnectorMethod(connector, 'all', self, [query], options, allCb);
|
invokeConnectorMethod(connector, 'all', self, [query], options, allCb);
|
||||||
} else {
|
} else {
|
||||||
const context = {
|
const context = {
|
||||||
|
@ -1709,6 +1738,12 @@ DataAccessObject.find = function find(query, options, cb) {
|
||||||
};
|
};
|
||||||
this.notifyObserversOf('access', context, function(err, ctx) {
|
this.notifyObserversOf('access', context, function(err, ctx) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
|
|
||||||
|
if (options.splitLongInq && isInqQuery(query.where)) {
|
||||||
|
queryWithInqSplit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
invokeConnectorMethod(connector, 'all', self, [ctx.query], options, allCb);
|
invokeConnectorMethod(connector, 'all', self, [ctx.query], options, allCb);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ const bdd = require('./helpers/bdd-if');
|
||||||
const should = require('./init.js');
|
const should = require('./init.js');
|
||||||
const uid = require('./helpers/uid-generator');
|
const uid = require('./helpers/uid-generator');
|
||||||
|
|
||||||
let db, User;
|
let db, User, Product;
|
||||||
|
|
||||||
describe('basic-querying', function() {
|
describe('basic-querying', function() {
|
||||||
before(function(done) {
|
before(function(done) {
|
||||||
|
@ -52,6 +52,11 @@ describe('basic-querying', function() {
|
||||||
(db.adapter.name != 'informix') && (db.adapter.name != 'cassandra');
|
(db.adapter.name != 'informix') && (db.adapter.name != 'cassandra');
|
||||||
if (connectorCapabilities.geoPoint) userModelDef.addressLoc = {type: 'GeoPoint'};
|
if (connectorCapabilities.geoPoint) userModelDef.addressLoc = {type: 'GeoPoint'};
|
||||||
User = db.define('User', userModelDef);
|
User = db.define('User', userModelDef);
|
||||||
|
|
||||||
|
Product = db.define('Product', {
|
||||||
|
name: {type: String, required: true},
|
||||||
|
});
|
||||||
|
|
||||||
db.automigrate(done);
|
db.automigrate(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1127,6 +1132,71 @@ describe('basic-querying', function() {
|
||||||
}, done);
|
}, 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.
|
// FIXME: This should either be re-enabled or removed.
|
||||||
|
|
Loading…
Reference in New Issue