diff --git a/src/storage/Database.ts b/src/storage/Database.ts index fed6a5e..072f2c2 100644 --- a/src/storage/Database.ts +++ b/src/storage/Database.ts @@ -445,7 +445,7 @@ export class Database { mainTable: table! } const { limit, skip } = clause - const provider = new PredicateProvider(table!, clause.where!) + const provider = clause.where ? new PredicateProvider(table!, clause.where) : null return new Selector(db, query, matcher, provider, limit, skip, orderDesc) }) diff --git a/src/storage/modules/Selector.ts b/src/storage/modules/Selector.ts index f674b4d..6ad6207 100644 --- a/src/storage/modules/Selector.ts +++ b/src/storage/modules/Selector.ts @@ -201,12 +201,19 @@ export class Selector { concat(... selectors: Selector[]): Selector { const orderStr = Selector.stringifyOrder(this.orderDescriptions!) - const equal = selectors.every(m => - m.select === this.select && - m.predicateProvider!.toString() === this.predicateProvider!.toString() && - Selector.stringifyOrder(m.orderDescriptions!) === orderStr && - m.mapFn.toString() === this.mapFn.toString() - ) + const equal = selectors.every(m => { + const hasEqualPredProvider = + m.predicateProvider == null && this.predicateProvider == null + || ( + m.predicateProvider && this.predicateProvider + && m.predicateProvider.toString() === this.predicateProvider.toString() + ) + + return !!hasEqualPredProvider + && m.select === this.select + && Selector.stringifyOrder(m.orderDescriptions!) === orderStr + && m.mapFn.toString() === this.mapFn.toString() + }) assert(equal, Exception.TokenConcatFailed()) return Selector.concatFactory(this, ...selectors) @@ -236,19 +243,27 @@ export class Selector { } private getQuery(additional?: lf.Predicate): lf.query.Select { - if (this.predicateBuildErr && !additional) { - return this.query + if (this.predicateBuildErr) { + return additional ? this.query.where(additional) : this.query } - // !this.predicateBuildErr || additional + // !this.predicateBuildErr + const preds: lf.Predicate[] = [] - if (this.predicateProvider && !this.predicateBuildErr) { + if (this.predicateProvider) { preds.push(this.predicateProvider.getPredicate()!) } if (additional) { preds.push(additional) } - const pred = lf.op.and(...preds) - return this.query.where(pred) + + switch (preds.length) { + case 0: + return this.query + case 1: + return this.query.where(preds[0]) + default: + return this.query.where(lf.op.and(...preds)) + } } private removeKey(data: any[], key: string) { diff --git a/test/specs/storage/Database.public.spec.ts b/test/specs/storage/Database.public.spec.ts index 85c98fb..eaeeda7 100644 --- a/test/specs/storage/Database.public.spec.ts +++ b/test/specs/storage/Database.public.spec.ts @@ -1,4 +1,4 @@ -import { Observable } from 'rxjs/Observable' +import { Observable, Scheduler } from 'rxjs' import * as moment from 'moment' import { describe, it, beforeEach, afterEach } from 'tman' import { expect, assert, use } from 'chai' @@ -10,7 +10,7 @@ import { TestFixture2 } from '../../schemas/Test' import { scenarioGen, programGen, postGen, taskGen, subtaskGen } from '../../utils/generators' import { RDBType, DataStoreType, Database, clone, forEach, JoinMode } from '../../index' import { TaskSchema, ProjectSchema, PostSchema, ModuleSchema, ProgramSchema, SubtaskSchema } from '../../index' -import { InvalidQuery, NonExistentTable, InvalidType, PrimaryKeyNotProvided, NotConnected } from '../../index' +import { InvalidQuery, NonExistentTable, InvalidType, PrimaryKeyNotProvided, NotConnected, Selector } from '../../index' use(SinonChai) @@ -251,6 +251,15 @@ export default describe('Database Testcase: ', () => { expect(_projectId).to.equal(target._projectId) }) + it('on query without `where`, should result in QueryToken whose Selector does not have predicateProvider', function* () { + yield database.get('Task', {}).selector$ + .subscribeOn(Scheduler.async) + .do((x: Selector) => { + console.info(x.toString()) + expect(x.predicateProvider).to.be.null + }) + }) + it('should get single record successfully', function* () { const result = yield database.get('Task', { where: { _id: target._id } diff --git a/test/specs/storage/modules/Selector.spec.ts b/test/specs/storage/modules/Selector.spec.ts index 8a2e65e..23eed31 100644 --- a/test/specs/storage/modules/Selector.spec.ts +++ b/test/specs/storage/modules/Selector.spec.ts @@ -153,7 +153,7 @@ export default describe('Selector test', () => { const sql = selector.toString() - expect(sql).to.equal('SELECT * FROM TestSelectMetadata WHERE ((TestSelectMetadata.time > 50));') + expect(sql).to.equal('SELECT * FROM TestSelectMetadata WHERE (TestSelectMetadata.time > 50);') }) it('should get correct results with orderBy', function* () { @@ -922,6 +922,26 @@ export default describe('Selector test', () => { .do(r => expect(r[75].name).equal(update3)) }) + it('concat selector should ok when neither selectors have predicateProvider', function* () { + selector1 = new Selector(db, + db.select().from(table), + tableShape, + null, + 20, 0 + ) + selector2 = new Selector(db, + db.select().from(table), + tableShape, + null, + 20, 20 + ) + const result = yield selector1.concat(selector2).values() + expect(result).to.have.lengthOf(40) + result.forEach((r: any, index: number) => { + expect(r).to.deep.equal(storeData[index]) + }) + }) + it('concat selector should ok with OrderDescription', function* () { const selector6 = new Selector(db, db.select().from(table),