Skip to content

Commit

Permalink
chore: code cleanup
Browse files Browse the repository at this point in the history
feat(Database): Only navigation properties in query now valid
  • Loading branch information
Brooooooklyn committed Sep 7, 2017
1 parent 1bdb3a0 commit ac32a6d
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 63 deletions.
3 changes: 0 additions & 3 deletions src/exception/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ export const NonExistentTable =
export const UnmodifiableTable =
() => new ReactiveDBException(`Method: defineSchema cannot be invoked since schema is existed or database is connected`)

export const InvalidQuery =
() => new ReactiveDBException('Only navigation properties were included in query.')

export const AliasConflict =
(column: string, tableName: string) => new ReactiveDBException(`Definition conflict, Column: \`${column}\` on table: ${tableName}.`)

Expand Down
5 changes: 1 addition & 4 deletions src/interface/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,7 @@ export type SchemaDisposeFunction<T> =

export interface ShapeMatcher {
mainTable: lf.schema.Table
pk: {
name: string,
queried: boolean
}
pk: string
definition: Object
}

Expand Down
46 changes: 18 additions & 28 deletions src/storage/Database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ export class Database {
}

return this.database$
.concatMap<any, any>(db => {
.concatMap(db => {
const entity = clone(raw)
const [ table ] = Database.getTables(db, tableName)
const columnMapper = schema!.mapper
Expand Down Expand Up @@ -290,7 +290,7 @@ export class Database {
}

const queries: lf.query.Builder[] = []
const removedIds: any = []
const removedIds: string[] = []
queries.push(predicatableQuery(db, table, predicate!, StatementType.Delete))

const prefetch = predicatableQuery(db, table, predicate!, StatementType.Select)
Expand Down Expand Up @@ -433,7 +433,6 @@ export class Database {
const containFields = !!clause.fields
let predicate: Predicate<T>

const containKey = containFields ? contains(pk, clause.fields!) : true
const [ additionJoinInfo, err ] = !clause.where ? [ null, null ] :
tryCatch(() => {
predicate = parsePredicate(clause.where!)
Expand All @@ -444,24 +443,30 @@ export class Database {
warn('Build addition join info from predicate failed', err.message)
}

const fields = containFields ? clause.fields : Array.from(schema.columns.keys())
let fields: Field[]
if (containFields) {
fields = [ schema.pk, ...clause.fields! ]
} else {
fields = Array.from(schema.columns.keys())
}

if (containFields && additionJoinInfo) {
mergeFields(fields!, additionJoinInfo)
mergeFields(fields, additionJoinInfo)
}

const fieldsSet: Set<Field> = new Set(fields)
const fieldsSet = new Set(fields)

const tablesStruct: TablesStruct = Object.create(null)

const { table, columns, joinInfo, definition, contextName } =
this.traverseQueryFields(db, tableName, fieldsSet, containKey, !containFields, [], {}, tablesStruct, mode)
this.traverseQueryFields(db, tableName, fieldsSet, !containFields, [], {}, tablesStruct, mode)
const query =
predicatableQuery(db, table!, null, StatementType.Select, ...columns)

joinInfo.forEach((info: JoinInfo) => {
const pred = info.predicate
if (pred) {
query.leftOuterJoin(info.table, pred)
const joinPredicate = info.predicate
if (joinPredicate) {
query.leftOuterJoin(info.table, joinPredicate)
}
})

Expand All @@ -475,10 +480,7 @@ export class Database {
})

const matcher = {
pk: {
name: pk,
queried: containKey
},
pk,
definition,
mainTable: table!
}
Expand Down Expand Up @@ -533,7 +535,6 @@ export class Database {
db: lf.Database,
tableName: string,
fieldsValue: Set<Field>,
hasKey: boolean,
glob: boolean,
path: string[] = [],
context: Record = {},
Expand All @@ -560,17 +561,6 @@ export class Database {
navigators.push(nav)
})

const onlyNavigator = Array.from(fieldsValue.keys())
.every(key => contains(key, navigators))
assert(!onlyNavigator, Exception.InvalidQuery())

if (!hasKey) {
// 保证主键一定比关联字段更早的被遍历到
const fields = Array.from(fieldsValue)
fields.unshift(schema.pk)
fieldsValue = new Set(fields)
}

const suffix = (context[tableName] || 0) + 1
context[tableName] = suffix
const contextName = contextTableName(tableName, suffix)
Expand Down Expand Up @@ -648,9 +638,9 @@ export class Database {
handleAdvanced({ columns: [column], advanced: true }, ctx.key, columnDef)
break
case LeafType.navigator:
const { containKey, fields, assocaiation } = ctx.leaf as NavigatorLeaf
const { fields, assocaiation } = ctx.leaf as NavigatorLeaf
const ret =
this.traverseQueryFields(db, assocaiation.name, new Set(fields), containKey, glob, path.slice(0), context, tablesStruct, mode)
this.traverseQueryFields(db, assocaiation.name, new Set(fields), glob, path.slice(0), context, tablesStruct, mode)
handleAdvanced(ret, ctx.key, assocaiation)
ctx.skip()
break
Expand Down
12 changes: 6 additions & 6 deletions src/storage/modules/Selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export class Selector <T> {
}
const { pk, mainTable } = this.shape

const column = mainTable[pk.name]
const column = mainTable[pk]
const rangeQuery = predicatableQuery(this.db, mainTable, predicate, StatementType.Select, column)

if (this.orderDescriptions && this.orderDescriptions.length) {
Expand Down Expand Up @@ -187,7 +187,7 @@ export class Selector <T> {
values(): Observable<T[]> | never {
if (typeof this.limit !== 'undefined' || typeof this.skip !== 'undefined') {
const p = this.rangeQuery.exec()
.then(r => r.map(v => v[this.shape.pk.name]))
.then(r => r.map(v => v[this.shape.pk]))
.then(pks => this.getValue(this.getQuery(this.inPKs(pks))))
return this.mapFn(Observable.fromPromise(p))
} else {
Expand Down Expand Up @@ -229,15 +229,15 @@ export class Selector <T> {

private inPKs(pks: (string | number)[]): lf.Predicate {
const { pk, mainTable } = this.shape
return mainTable[pk.name].in(pks)
return mainTable[pk].in(pks)
}

private getValue(query: lf.query.Select) {
return query.exec()
.then((rows: any[]) => {
const result = graph<T>(rows, this.shape.definition)
const col = this.shape.pk.name
return !this.shape.pk.queried ? this.removeKey(result, col) : result
const col = this.shape.pk
return !this.shape.pk ? this.removeKey(result, col) : result
})
}

Expand Down Expand Up @@ -276,7 +276,7 @@ export class Selector <T> {
const listener = () => {
return rangeQuery.exec()
.then((r) => {
observer.next(r.map(v => v[this.shape.pk.name]))
observer.next(r.map(v => v[this.shape.pk]))
})
.catch(e => observer.error(e))
}
Expand Down
21 changes: 3 additions & 18 deletions test/specs/storage/Database.public.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { TestFixture2 } from '../../schemas/Test'
import { scenarioGen, programGen, postGen, taskGen, subtaskGen } from '../../utils/generators'
import { RDBType, DataStoreType, Database, clone, forEach, JoinMode, Logger } from '../../index'
import { TaskSchema, ProjectSchema, PostSchema, ModuleSchema, ProgramSchema, SubtaskSchema, OrganizationSchema, TasklistSchema } from '../../index'
import { InvalidQuery, NonExistentTable, InvalidType, PrimaryKeyNotProvided, NotConnected, Selector, AssociatedFieldsPostionError } from '../../index'
import { NonExistentTable, InvalidType, PrimaryKeyNotProvided, NotConnected, Selector, AssociatedFieldsPostionError } from '../../index'

use(SinonChai)

Expand Down Expand Up @@ -543,7 +543,7 @@ export default describe('Database Testcase: ', () => {
expect(result).to.deep.equal(innerTarget)
})

it('should get value by deep nested Association query without association fields', function* () {
it('should get value by deep nested Association query without association fields #1', function* () {
const fields = ['_id', 'content']
const queryToken = database.get<TaskSchema>('Task', {
fields,
Expand All @@ -557,7 +557,7 @@ export default describe('Database Testcase: ', () => {
expect(result.project.organization._id).to.equal(innerTarget.project._organizationId)
})

it('should get value by deep nested Association query without association fields', function* () {
it('should get value by deep nested Association query without association fields #2', function* () {
const fields = ['_id', 'content']
const queryToken = database.get<TaskSchema>('Task', {
fields,
Expand Down Expand Up @@ -695,21 +695,6 @@ export default describe('Database Testcase: ', () => {
})
})

it('should throw if only navigator was included in query', function* () {

try {
yield database.get('Task', {
fields: [ 'project', 'subtasks' ],
where: { _id: innerTarget._id }
}).values()

throw new Error('error path reached')
} catch (err) {
const standardErr = InvalidQuery()
expect(err.message).to.equal(standardErr.message)
}
})

it('should throw if failed to build where-clause, and treat it as an empty where-clause', function* () {
let result: any[]

Expand Down
5 changes: 1 addition & 4 deletions test/specs/storage/modules/Selector.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,7 @@ export default describe('Selector test', () => {

tableShape = {
mainTable: table,
pk: {
queried: true,
name: '_id'
},
pk: '_id',
definition: {
_id: {
column: '_id',
Expand Down

0 comments on commit ac32a6d

Please sign in to comment.