增加了在filter判定时,如果属性缺失要不要报warning
This commit is contained in:
parent
3c74bf363f
commit
530d6b3c07
|
|
@ -9,6 +9,7 @@ import { Context } from 'oak-domain/lib/types';
|
|||
export interface TreeStoreSelectOption extends SelectOption {
|
||||
nodeDict?: NodeDict;
|
||||
disableSubQueryHashjoin?: boolean;
|
||||
warnWhenAttributeMiss?: boolean;
|
||||
}
|
||||
export interface TreeStoreOperateOption extends OperateOption {
|
||||
}
|
||||
|
|
|
|||
91
es/store.js
91
es/store.js
|
|
@ -14,6 +14,9 @@ import { combineFilters, getRelevantIds } from 'oak-domain/lib/store/filter';
|
|||
;
|
||||
class OakExpressionUnresolvedException extends OakException {
|
||||
}
|
||||
function showWarningAttributeMiss(entity, attr) {
|
||||
console.warn(`attribute miss: entity: ${entity}, attr: ${attr}`);
|
||||
}
|
||||
;
|
||||
export default class TreeStore extends CascadeStore {
|
||||
store;
|
||||
|
|
@ -354,7 +357,11 @@ export default class TreeStore extends CascadeStore {
|
|||
return (row, nodeDict) => {
|
||||
if (expression.hasOwnProperty('#attr')) {
|
||||
// 说明是本结点的属性;
|
||||
return row[expression['#attr']];
|
||||
const attr = row[expression['#attr']];
|
||||
if (attr === undefined && option.warnWhenAttributeMiss) {
|
||||
showWarningAttributeMiss(entity, expression['#attr']);
|
||||
}
|
||||
return attr;
|
||||
}
|
||||
else {
|
||||
assert(expression.hasOwnProperty('#refId'));
|
||||
|
|
@ -396,21 +403,28 @@ export default class TreeStore extends CascadeStore {
|
|||
const { $search } = filter;
|
||||
return (node) => {
|
||||
const row = this.constructRow(node, context, option);
|
||||
for (const attr of attributes) {
|
||||
const { name } = attr;
|
||||
if (row && row[name] && (typeof row[name] === 'string' && row[name].includes($search))) {
|
||||
return true;
|
||||
if (row) {
|
||||
for (const attr of attributes) {
|
||||
const { name } = attr;
|
||||
const value = row[name];
|
||||
if (value === undefined && option.warnWhenAttributeMiss) {
|
||||
showWarningAttributeMiss(entity, name);
|
||||
}
|
||||
if (typeof value === 'string' && row[name].includes($search)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
translatePredicate(path, predicate, value, option) {
|
||||
translatePredicate(entity, path, predicate, value, option) {
|
||||
switch (predicate) {
|
||||
case '$gt': {
|
||||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return ['number', 'string'].includes(typeof data) && data > value;
|
||||
};
|
||||
}
|
||||
|
|
@ -418,6 +432,7 @@ export default class TreeStore extends CascadeStore {
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return ['number', 'string'].includes(typeof data) && data < value;
|
||||
};
|
||||
}
|
||||
|
|
@ -425,6 +440,7 @@ export default class TreeStore extends CascadeStore {
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return ['number', 'string'].includes(typeof data) && data >= value;
|
||||
};
|
||||
}
|
||||
|
|
@ -432,6 +448,7 @@ export default class TreeStore extends CascadeStore {
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return ['number', 'string'].includes(typeof data) && data <= value;
|
||||
};
|
||||
}
|
||||
|
|
@ -439,6 +456,7 @@ export default class TreeStore extends CascadeStore {
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return ['number', 'string'].includes(typeof data) && data === value;
|
||||
};
|
||||
}
|
||||
|
|
@ -446,6 +464,7 @@ export default class TreeStore extends CascadeStore {
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return ['number', 'string'].includes(typeof data) && data !== value;
|
||||
};
|
||||
}
|
||||
|
|
@ -453,6 +472,7 @@ export default class TreeStore extends CascadeStore {
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return ['number', 'string'].includes(typeof data) && data >= value[0] && data <= value[1];
|
||||
};
|
||||
}
|
||||
|
|
@ -460,6 +480,7 @@ export default class TreeStore extends CascadeStore {
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return typeof data === 'number' && data % value[0] === value[1];
|
||||
};
|
||||
}
|
||||
|
|
@ -467,6 +488,7 @@ export default class TreeStore extends CascadeStore {
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return ['string'].includes(typeof data) && data.startsWith(value);
|
||||
};
|
||||
}
|
||||
|
|
@ -474,6 +496,7 @@ export default class TreeStore extends CascadeStore {
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return ['string'].includes(typeof data) && data.endsWith(value);
|
||||
};
|
||||
}
|
||||
|
|
@ -481,6 +504,7 @@ export default class TreeStore extends CascadeStore {
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return ['string'].includes(typeof data) && data.includes(value);
|
||||
};
|
||||
}
|
||||
|
|
@ -489,6 +513,7 @@ export default class TreeStore extends CascadeStore {
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
if (value) {
|
||||
return ![null, undefined].includes(data);
|
||||
}
|
||||
|
|
@ -501,6 +526,7 @@ export default class TreeStore extends CascadeStore {
|
|||
assert(value instanceof Array);
|
||||
return (row) => {
|
||||
const data = get(row, path);
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return value.includes(data);
|
||||
};
|
||||
}
|
||||
|
|
@ -508,6 +534,7 @@ export default class TreeStore extends CascadeStore {
|
|||
assert(value instanceof Array);
|
||||
return (row) => {
|
||||
const data = get(row, path);
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return !value.includes(data);
|
||||
};
|
||||
}
|
||||
|
|
@ -516,6 +543,7 @@ export default class TreeStore extends CascadeStore {
|
|||
const array = value instanceof Array ? value : [value];
|
||||
return (row) => {
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return differenceBy(array, data, (value) => {
|
||||
if (typeof value === 'object') {
|
||||
return JSON.stringify(value);
|
||||
|
|
@ -529,6 +557,7 @@ export default class TreeStore extends CascadeStore {
|
|||
const array = value instanceof Array ? value : [value];
|
||||
return (row) => {
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return intersectionBy(array, data, (value) => {
|
||||
if (typeof value === 'object') {
|
||||
return JSON.stringify(value);
|
||||
|
|
@ -542,7 +571,7 @@ export default class TreeStore extends CascadeStore {
|
|||
}
|
||||
}
|
||||
}
|
||||
translateObjectPredicate(filter) {
|
||||
translateObjectPredicate(entity, filter) {
|
||||
const fns = [];
|
||||
const translatePredicateInner = (p, path, fns2) => {
|
||||
if (p instanceof Array) {
|
||||
|
|
@ -550,7 +579,7 @@ export default class TreeStore extends CascadeStore {
|
|||
const path2 = `${path}[${idx}]`;
|
||||
if (typeof ele !== 'object') {
|
||||
if (![null, undefined].includes(ele)) {
|
||||
fns2.push(this.translatePredicate(path2, '$eq', ele));
|
||||
fns2.push(this.translatePredicate(entity, path2, '$eq', ele));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -577,13 +606,13 @@ export default class TreeStore extends CascadeStore {
|
|||
}
|
||||
else if (attr.startsWith('$')) {
|
||||
assert(Object.keys(p).length === 1);
|
||||
fns2.push(this.translatePredicate(path, attr, p[attr]));
|
||||
fns2.push(this.translatePredicate(entity, path, attr, p[attr]));
|
||||
}
|
||||
else {
|
||||
const attr2 = attr.startsWith('.') ? attr.slice(1) : attr;
|
||||
const path2 = path ? `${path}.${attr2}` : attr2;
|
||||
if (typeof p[attr] !== 'object') {
|
||||
fns2.push(this.translatePredicate(path2, '$eq', p[attr]));
|
||||
fns2.push(this.translatePredicate(entity, path2, '$eq', p[attr]));
|
||||
}
|
||||
else {
|
||||
translatePredicateInner(p[attr], path2, fns2);
|
||||
|
|
@ -607,7 +636,14 @@ export default class TreeStore extends CascadeStore {
|
|||
if (typeof filter !== 'object') {
|
||||
return (node) => {
|
||||
const row = this.constructRow(node, context, option);
|
||||
return row ? row[attr] === filter : false;
|
||||
if (row) {
|
||||
const value = row[attr];
|
||||
if (value === undefined && option.warnWhenAttributeMiss) {
|
||||
showWarningAttributeMiss(entity, attr);
|
||||
}
|
||||
return value === filter;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
else {
|
||||
|
|
@ -617,7 +653,7 @@ export default class TreeStore extends CascadeStore {
|
|||
throw new Error('子查询已经改用一对多的外键连接方式');
|
||||
}
|
||||
else {
|
||||
const fn = this.translatePredicate(attr, predicate, filter[predicate], option);
|
||||
const fn = this.translatePredicate(entity, attr, predicate, filter[predicate], option);
|
||||
return (node) => {
|
||||
const row = this.constructRow(node, context, option);
|
||||
if (!row) {
|
||||
|
|
@ -642,7 +678,7 @@ export default class TreeStore extends CascadeStore {
|
|||
};
|
||||
}
|
||||
else {
|
||||
const fn = this.translateObjectPredicate(filter);
|
||||
const fn = this.translateObjectPredicate(entity, filter);
|
||||
return (node) => {
|
||||
const row = this.constructRow(node, context, option);
|
||||
if (!row) {
|
||||
|
|
@ -702,8 +738,8 @@ export default class TreeStore extends CascadeStore {
|
|||
return false;
|
||||
}
|
||||
if (row.entityId === undefined || row.entity === undefined) {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.warn(`对象${entity}上的entity/entityId不能确定值,可能会影响判定结果`);
|
||||
if (option.warnWhenAttributeMiss) {
|
||||
showWarningAttributeMiss(entity, 'entity/entityId');
|
||||
}
|
||||
return false; // 若不能确定,认定为条件不满足
|
||||
}
|
||||
|
|
@ -736,8 +772,8 @@ export default class TreeStore extends CascadeStore {
|
|||
return filterFn(node2, nodeDict, exprResolveFns);
|
||||
}
|
||||
if (row[`${attr}Id`] === undefined) {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.warn(`对象${entity}上的${attr}Id不能确定值,可能会影响判定结果`);
|
||||
if (option.warnWhenAttributeMiss) {
|
||||
showWarningAttributeMiss(entity, `${attr}Id`);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
@ -787,13 +823,17 @@ export default class TreeStore extends CascadeStore {
|
|||
}
|
||||
});
|
||||
}
|
||||
const option2 = Object.assign({}, option, { nodeDict, dontCollect: true });
|
||||
const subQuerySet = (this.selectAbjointRow(otmEntity, {
|
||||
data: otmProjection,
|
||||
filter: otmFilter,
|
||||
indexFrom: 0,
|
||||
count: 1,
|
||||
}, context, option2)).map((ele) => {
|
||||
}, context, {
|
||||
...option,
|
||||
nodeDict,
|
||||
dontCollect: true,
|
||||
warnWhenAttributeMiss: false, // 一对多连接不必要考虑这个属性缺失
|
||||
})).map((ele) => {
|
||||
return (ele)[fk];
|
||||
});
|
||||
switch (predicate) {
|
||||
|
|
@ -833,7 +873,11 @@ export default class TreeStore extends CascadeStore {
|
|||
filter: otmFilter,
|
||||
indexFrom: 0,
|
||||
count: 1,
|
||||
}, context, { dontCollect: true })).map((ele) => {
|
||||
}, context, {
|
||||
...option,
|
||||
dontCollect: true,
|
||||
warnWhenAttributeMiss: false, // 一对多连接不必要考虑这个属性缺失
|
||||
})).map((ele) => {
|
||||
return (ele)[fk];
|
||||
});
|
||||
self.push((node) => {
|
||||
|
|
@ -869,12 +913,15 @@ export default class TreeStore extends CascadeStore {
|
|||
/**
|
||||
* 尝试用hashjoin将内表数组取出,因为memory中的表都不会太大,且用不了索引(未来优化了可能可以用id直接取值),因而用hash应当会更快
|
||||
*/
|
||||
const option2 = Object.assign({}, option, { dontCollect: true });
|
||||
try {
|
||||
const subQueryRows = this.selectAbjointRow(otmEntity, {
|
||||
data: otmProjection,
|
||||
filter: filter[attr],
|
||||
}, context, option2);
|
||||
}, context, {
|
||||
...option,
|
||||
dontCollect: true,
|
||||
warnWhenAttributeMiss: false, // 一对多连接不必要考虑这个属性缺失
|
||||
});
|
||||
const buckets = groupBy(subQueryRows, fk);
|
||||
otm.push((node, nodeDict) => {
|
||||
const row = this.constructRow(node, context, option);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { Context } from 'oak-domain/lib/types';
|
|||
export interface TreeStoreSelectOption extends SelectOption {
|
||||
nodeDict?: NodeDict;
|
||||
disableSubQueryHashjoin?: boolean;
|
||||
warnWhenAttributeMiss?: boolean;
|
||||
}
|
||||
export interface TreeStoreOperateOption extends OperateOption {
|
||||
}
|
||||
|
|
|
|||
91
lib/store.js
91
lib/store.js
|
|
@ -16,6 +16,9 @@ const filter_1 = require("oak-domain/lib/store/filter");
|
|||
;
|
||||
class OakExpressionUnresolvedException extends Exception_1.OakException {
|
||||
}
|
||||
function showWarningAttributeMiss(entity, attr) {
|
||||
console.warn(`attribute miss: entity: ${entity}, attr: ${attr}`);
|
||||
}
|
||||
;
|
||||
class TreeStore extends CascadeStore_1.CascadeStore {
|
||||
store;
|
||||
|
|
@ -356,7 +359,11 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
return (row, nodeDict) => {
|
||||
if (expression.hasOwnProperty('#attr')) {
|
||||
// 说明是本结点的属性;
|
||||
return row[expression['#attr']];
|
||||
const attr = row[expression['#attr']];
|
||||
if (attr === undefined && option.warnWhenAttributeMiss) {
|
||||
showWarningAttributeMiss(entity, expression['#attr']);
|
||||
}
|
||||
return attr;
|
||||
}
|
||||
else {
|
||||
(0, assert_1.assert)(expression.hasOwnProperty('#refId'));
|
||||
|
|
@ -398,21 +405,28 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
const { $search } = filter;
|
||||
return (node) => {
|
||||
const row = this.constructRow(node, context, option);
|
||||
for (const attr of attributes) {
|
||||
const { name } = attr;
|
||||
if (row && row[name] && (typeof row[name] === 'string' && row[name].includes($search))) {
|
||||
return true;
|
||||
if (row) {
|
||||
for (const attr of attributes) {
|
||||
const { name } = attr;
|
||||
const value = row[name];
|
||||
if (value === undefined && option.warnWhenAttributeMiss) {
|
||||
showWarningAttributeMiss(entity, name);
|
||||
}
|
||||
if (typeof value === 'string' && row[name].includes($search)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
translatePredicate(path, predicate, value, option) {
|
||||
translatePredicate(entity, path, predicate, value, option) {
|
||||
switch (predicate) {
|
||||
case '$gt': {
|
||||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? (0, lodash_1.get)(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return ['number', 'string'].includes(typeof data) && data > value;
|
||||
};
|
||||
}
|
||||
|
|
@ -420,6 +434,7 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? (0, lodash_1.get)(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return ['number', 'string'].includes(typeof data) && data < value;
|
||||
};
|
||||
}
|
||||
|
|
@ -427,6 +442,7 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? (0, lodash_1.get)(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return ['number', 'string'].includes(typeof data) && data >= value;
|
||||
};
|
||||
}
|
||||
|
|
@ -434,6 +450,7 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? (0, lodash_1.get)(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return ['number', 'string'].includes(typeof data) && data <= value;
|
||||
};
|
||||
}
|
||||
|
|
@ -441,6 +458,7 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? (0, lodash_1.get)(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return ['number', 'string'].includes(typeof data) && data === value;
|
||||
};
|
||||
}
|
||||
|
|
@ -448,6 +466,7 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? (0, lodash_1.get)(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return ['number', 'string'].includes(typeof data) && data !== value;
|
||||
};
|
||||
}
|
||||
|
|
@ -455,6 +474,7 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? (0, lodash_1.get)(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return ['number', 'string'].includes(typeof data) && data >= value[0] && data <= value[1];
|
||||
};
|
||||
}
|
||||
|
|
@ -462,6 +482,7 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? (0, lodash_1.get)(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return typeof data === 'number' && data % value[0] === value[1];
|
||||
};
|
||||
}
|
||||
|
|
@ -469,6 +490,7 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? (0, lodash_1.get)(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return ['string'].includes(typeof data) && data.startsWith(value);
|
||||
};
|
||||
}
|
||||
|
|
@ -476,6 +498,7 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? (0, lodash_1.get)(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return ['string'].includes(typeof data) && data.endsWith(value);
|
||||
};
|
||||
}
|
||||
|
|
@ -483,6 +506,7 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? (0, lodash_1.get)(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return ['string'].includes(typeof data) && data.includes(value);
|
||||
};
|
||||
}
|
||||
|
|
@ -491,6 +515,7 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? (0, lodash_1.get)(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
if (value) {
|
||||
return ![null, undefined].includes(data);
|
||||
}
|
||||
|
|
@ -503,6 +528,7 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
(0, assert_1.assert)(value instanceof Array);
|
||||
return (row) => {
|
||||
const data = (0, lodash_1.get)(row, path);
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return value.includes(data);
|
||||
};
|
||||
}
|
||||
|
|
@ -510,6 +536,7 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
(0, assert_1.assert)(value instanceof Array);
|
||||
return (row) => {
|
||||
const data = (0, lodash_1.get)(row, path);
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return !value.includes(data);
|
||||
};
|
||||
}
|
||||
|
|
@ -518,6 +545,7 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
const array = value instanceof Array ? value : [value];
|
||||
return (row) => {
|
||||
const data = path ? (0, lodash_1.get)(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return (0, lodash_1.differenceBy)(array, data, (value) => {
|
||||
if (typeof value === 'object') {
|
||||
return JSON.stringify(value);
|
||||
|
|
@ -531,6 +559,7 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
const array = value instanceof Array ? value : [value];
|
||||
return (row) => {
|
||||
const data = path ? (0, lodash_1.get)(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss(entity, path);
|
||||
return (0, lodash_1.intersectionBy)(array, data, (value) => {
|
||||
if (typeof value === 'object') {
|
||||
return JSON.stringify(value);
|
||||
|
|
@ -544,7 +573,7 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
}
|
||||
}
|
||||
}
|
||||
translateObjectPredicate(filter) {
|
||||
translateObjectPredicate(entity, filter) {
|
||||
const fns = [];
|
||||
const translatePredicateInner = (p, path, fns2) => {
|
||||
if (p instanceof Array) {
|
||||
|
|
@ -552,7 +581,7 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
const path2 = `${path}[${idx}]`;
|
||||
if (typeof ele !== 'object') {
|
||||
if (![null, undefined].includes(ele)) {
|
||||
fns2.push(this.translatePredicate(path2, '$eq', ele));
|
||||
fns2.push(this.translatePredicate(entity, path2, '$eq', ele));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -579,13 +608,13 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
}
|
||||
else if (attr.startsWith('$')) {
|
||||
(0, assert_1.assert)(Object.keys(p).length === 1);
|
||||
fns2.push(this.translatePredicate(path, attr, p[attr]));
|
||||
fns2.push(this.translatePredicate(entity, path, attr, p[attr]));
|
||||
}
|
||||
else {
|
||||
const attr2 = attr.startsWith('.') ? attr.slice(1) : attr;
|
||||
const path2 = path ? `${path}.${attr2}` : attr2;
|
||||
if (typeof p[attr] !== 'object') {
|
||||
fns2.push(this.translatePredicate(path2, '$eq', p[attr]));
|
||||
fns2.push(this.translatePredicate(entity, path2, '$eq', p[attr]));
|
||||
}
|
||||
else {
|
||||
translatePredicateInner(p[attr], path2, fns2);
|
||||
|
|
@ -609,7 +638,14 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
if (typeof filter !== 'object') {
|
||||
return (node) => {
|
||||
const row = this.constructRow(node, context, option);
|
||||
return row ? row[attr] === filter : false;
|
||||
if (row) {
|
||||
const value = row[attr];
|
||||
if (value === undefined && option.warnWhenAttributeMiss) {
|
||||
showWarningAttributeMiss(entity, attr);
|
||||
}
|
||||
return value === filter;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
else {
|
||||
|
|
@ -619,7 +655,7 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
throw new Error('子查询已经改用一对多的外键连接方式');
|
||||
}
|
||||
else {
|
||||
const fn = this.translatePredicate(attr, predicate, filter[predicate], option);
|
||||
const fn = this.translatePredicate(entity, attr, predicate, filter[predicate], option);
|
||||
return (node) => {
|
||||
const row = this.constructRow(node, context, option);
|
||||
if (!row) {
|
||||
|
|
@ -644,7 +680,7 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
};
|
||||
}
|
||||
else {
|
||||
const fn = this.translateObjectPredicate(filter);
|
||||
const fn = this.translateObjectPredicate(entity, filter);
|
||||
return (node) => {
|
||||
const row = this.constructRow(node, context, option);
|
||||
if (!row) {
|
||||
|
|
@ -704,8 +740,8 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
return false;
|
||||
}
|
||||
if (row.entityId === undefined || row.entity === undefined) {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.warn(`对象${entity}上的entity/entityId不能确定值,可能会影响判定结果`);
|
||||
if (option.warnWhenAttributeMiss) {
|
||||
showWarningAttributeMiss(entity, 'entity/entityId');
|
||||
}
|
||||
return false; // 若不能确定,认定为条件不满足
|
||||
}
|
||||
|
|
@ -738,8 +774,8 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
return filterFn(node2, nodeDict, exprResolveFns);
|
||||
}
|
||||
if (row[`${attr}Id`] === undefined) {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.warn(`对象${entity}上的${attr}Id不能确定值,可能会影响判定结果`);
|
||||
if (option.warnWhenAttributeMiss) {
|
||||
showWarningAttributeMiss(entity, `${attr}Id`);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
@ -789,13 +825,17 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
}
|
||||
});
|
||||
}
|
||||
const option2 = Object.assign({}, option, { nodeDict, dontCollect: true });
|
||||
const subQuerySet = (this.selectAbjointRow(otmEntity, {
|
||||
data: otmProjection,
|
||||
filter: otmFilter,
|
||||
indexFrom: 0,
|
||||
count: 1,
|
||||
}, context, option2)).map((ele) => {
|
||||
}, context, {
|
||||
...option,
|
||||
nodeDict,
|
||||
dontCollect: true,
|
||||
warnWhenAttributeMiss: false, // 一对多连接不必要考虑这个属性缺失
|
||||
})).map((ele) => {
|
||||
return (ele)[fk];
|
||||
});
|
||||
switch (predicate) {
|
||||
|
|
@ -835,7 +875,11 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
filter: otmFilter,
|
||||
indexFrom: 0,
|
||||
count: 1,
|
||||
}, context, { dontCollect: true })).map((ele) => {
|
||||
}, context, {
|
||||
...option,
|
||||
dontCollect: true,
|
||||
warnWhenAttributeMiss: false, // 一对多连接不必要考虑这个属性缺失
|
||||
})).map((ele) => {
|
||||
return (ele)[fk];
|
||||
});
|
||||
self.push((node) => {
|
||||
|
|
@ -871,12 +915,15 @@ class TreeStore extends CascadeStore_1.CascadeStore {
|
|||
/**
|
||||
* 尝试用hashjoin将内表数组取出,因为memory中的表都不会太大,且用不了索引(未来优化了可能可以用id直接取值),因而用hash应当会更快
|
||||
*/
|
||||
const option2 = Object.assign({}, option, { dontCollect: true });
|
||||
try {
|
||||
const subQueryRows = this.selectAbjointRow(otmEntity, {
|
||||
data: otmProjection,
|
||||
filter: filter[attr],
|
||||
}, context, option2);
|
||||
}, context, {
|
||||
...option,
|
||||
dontCollect: true,
|
||||
warnWhenAttributeMiss: false, // 一对多连接不必要考虑这个属性缺失
|
||||
});
|
||||
const buckets = (0, lodash_1.groupBy)(subQueryRows, fk);
|
||||
otm.push((node, nodeDict) => {
|
||||
const row = this.constructRow(node, context, option);
|
||||
|
|
|
|||
96
src/store.ts
96
src/store.ts
|
|
@ -39,6 +39,11 @@ class OakExpressionUnresolvedException<ED extends EntityDict & BaseEntityDict> e
|
|||
export interface TreeStoreSelectOption extends SelectOption {
|
||||
nodeDict?: NodeDict;
|
||||
disableSubQueryHashjoin?: boolean; // 禁用hashjoin优化,可能会导致性能下降严重(对比测试用)
|
||||
warnWhenAttributeMiss?: boolean; // 当有属性miss时,报一个Warning(debug使用)
|
||||
}
|
||||
|
||||
function showWarningAttributeMiss<ED extends EntityDict & BaseEntityDict>(entity: keyof ED, attr: string) {
|
||||
console.warn(`attribute miss: entity: ${entity as string}, attr: ${attr}`);
|
||||
}
|
||||
|
||||
export interface TreeStoreOperateOption extends OperateOption {
|
||||
|
|
@ -471,9 +476,15 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
return (row, nodeDict) => {
|
||||
if (expression.hasOwnProperty('#attr')) {
|
||||
// 说明是本结点的属性;
|
||||
return row[(expression as {
|
||||
const attr = row[(expression as {
|
||||
'#attr': keyof ED[T]['Schema'];
|
||||
})['#attr']] as ExpressionConstant;
|
||||
if (attr === undefined && option.warnWhenAttributeMiss) {
|
||||
showWarningAttributeMiss<ED>(entity, (expression as {
|
||||
'#attr': string;
|
||||
})['#attr']);
|
||||
}
|
||||
return attr;
|
||||
}
|
||||
else {
|
||||
assert(expression.hasOwnProperty('#refId'));
|
||||
|
|
@ -532,22 +543,30 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
|
||||
return (node) => {
|
||||
const row = this.constructRow(node, context, option) as any;
|
||||
for (const attr of attributes) {
|
||||
const { name } = attr;
|
||||
if (row && row[name] && (typeof row[name] === 'string' && row[name].includes($search))) {
|
||||
return true;
|
||||
if (row) {
|
||||
for (const attr of attributes) {
|
||||
const { name } = attr;
|
||||
const value = row[name];
|
||||
if (value === undefined && option.warnWhenAttributeMiss) {
|
||||
showWarningAttributeMiss<ED>(entity, name as string);
|
||||
}
|
||||
|
||||
if (typeof value === 'string' && row[name].includes($search)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
private translatePredicate<OP extends TreeStoreSelectOption>(path: string, predicate: string, value: any, option?: OP): (row: Record<string, any>) => boolean {
|
||||
private translatePredicate<OP extends TreeStoreSelectOption>(entity: keyof ED, path: string, predicate: string, value: any, option?: OP): (row: Record<string, any>) => boolean {
|
||||
switch (predicate) {
|
||||
case '$gt': {
|
||||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss<ED>(entity, path);
|
||||
return ['number', 'string'].includes(typeof data) && data > value;
|
||||
};
|
||||
}
|
||||
|
|
@ -555,12 +574,14 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss<ED>(entity, path);
|
||||
return ['number', 'string'].includes(typeof data) && data < value;
|
||||
};
|
||||
} case '$gte': {
|
||||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss<ED>(entity, path);
|
||||
return ['number', 'string'].includes(typeof data) && data >= value;
|
||||
};
|
||||
}
|
||||
|
|
@ -568,6 +589,7 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss<ED>(entity, path);
|
||||
return ['number', 'string'].includes(typeof data) && data <= value;
|
||||
};
|
||||
}
|
||||
|
|
@ -575,6 +597,7 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss<ED>(entity, path);
|
||||
return ['number', 'string'].includes(typeof data) && data === value;
|
||||
};
|
||||
}
|
||||
|
|
@ -582,6 +605,7 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss<ED>(entity, path);
|
||||
return ['number', 'string'].includes(typeof data) && data !== value;
|
||||
};
|
||||
}
|
||||
|
|
@ -589,6 +613,7 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss<ED>(entity, path);
|
||||
return ['number', 'string'].includes(typeof data) && data >= value[0] && data <= value[1];
|
||||
};
|
||||
}
|
||||
|
|
@ -596,6 +621,7 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss<ED>(entity, path);
|
||||
return typeof data === 'number' && data % value[0] === value[1];
|
||||
};
|
||||
}
|
||||
|
|
@ -603,6 +629,7 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss<ED>(entity, path);
|
||||
return ['string'].includes(typeof data) && data.startsWith(value);
|
||||
};
|
||||
}
|
||||
|
|
@ -610,6 +637,7 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss<ED>(entity, path);
|
||||
return ['string'].includes(typeof data) && data.endsWith(value);
|
||||
};
|
||||
}
|
||||
|
|
@ -617,6 +645,7 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss<ED>(entity, path);
|
||||
return ['string'].includes(typeof data) && data.includes(value);
|
||||
};
|
||||
}
|
||||
|
|
@ -625,6 +654,7 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
return (row) => {
|
||||
// JsonFilter有可能是根结点,path为空
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss<ED>(entity, path);
|
||||
if (value) {
|
||||
return ![null, undefined].includes(data);
|
||||
}
|
||||
|
|
@ -637,6 +667,7 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
assert(value instanceof Array);
|
||||
return (row) => {
|
||||
const data = get(row, path);
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss<ED>(entity, path);
|
||||
return value.includes(data);
|
||||
};
|
||||
}
|
||||
|
|
@ -644,6 +675,7 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
assert(value instanceof Array);
|
||||
return (row) => {
|
||||
const data = get(row, path);
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss<ED>(entity, path);
|
||||
return !value.includes(data);
|
||||
};
|
||||
}
|
||||
|
|
@ -652,6 +684,7 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
const array = value instanceof Array ? value : [value];
|
||||
return (row) => {
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss<ED>(entity, path);
|
||||
return differenceBy(array, data, (value: any) => {
|
||||
if (typeof value === 'object') {
|
||||
return JSON.stringify(value);
|
||||
|
|
@ -665,6 +698,7 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
const array = value instanceof Array ? value : [value];
|
||||
return (row) => {
|
||||
const data = path ? get(row, path) : row;
|
||||
data === undefined && option.warnWhenAttributeMiss && showWarningAttributeMiss<ED>(entity, path);
|
||||
return intersectionBy(array, data, (value: any) => {
|
||||
if (typeof value === 'object') {
|
||||
return JSON.stringify(value);
|
||||
|
|
@ -679,7 +713,7 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
}
|
||||
}
|
||||
|
||||
private translateObjectPredicate(filter: Record<string, any>) {
|
||||
private translateObjectPredicate(entity: keyof ED, filter: Record<string, any>) {
|
||||
const fns: Array<(value: any) => boolean> = [];
|
||||
const translatePredicateInner = (p: Record<string, any> | Array<any>, path: string, fns2: Array<(value: any) => boolean>) => {
|
||||
if (p instanceof Array) {
|
||||
|
|
@ -688,7 +722,7 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
const path2 = `${path}[${idx}]`;
|
||||
if (typeof ele !== 'object') {
|
||||
if (![null, undefined].includes(ele)) {
|
||||
fns2.push(this.translatePredicate(path2, '$eq', ele));
|
||||
fns2.push(this.translatePredicate(entity, path2, '$eq', ele));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -723,14 +757,14 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
else if (attr.startsWith('$')) {
|
||||
assert(Object.keys(p).length === 1);
|
||||
fns2.push(
|
||||
this.translatePredicate(path, attr, p[attr])
|
||||
this.translatePredicate(entity, path, attr, p[attr])
|
||||
);
|
||||
}
|
||||
else {
|
||||
const attr2 = attr.startsWith('.') ? attr.slice(1) : attr;
|
||||
const path2 = path ? `${path}.${attr2}` : attr2;
|
||||
if (typeof p[attr] !== 'object') {
|
||||
fns2.push(this.translatePredicate(path2, '$eq', p[attr]));
|
||||
fns2.push(this.translatePredicate(entity, path2, '$eq', p[attr]));
|
||||
}
|
||||
else {
|
||||
translatePredicateInner(p[attr], path2, fns2);
|
||||
|
|
@ -762,7 +796,14 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
if (typeof filter !== 'object') {
|
||||
return (node) => {
|
||||
const row = this.constructRow(node, context, option);
|
||||
return row ? (row as any)[attr] === filter : false;
|
||||
if (row) {
|
||||
const value = row[attr];
|
||||
if (value === undefined && option.warnWhenAttributeMiss) {
|
||||
showWarningAttributeMiss<ED>(entity, attr);
|
||||
}
|
||||
return value === filter;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
else {
|
||||
|
|
@ -772,7 +813,7 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
throw new Error('子查询已经改用一对多的外键连接方式');
|
||||
}
|
||||
else {
|
||||
const fn = this.translatePredicate(attr, predicate, (filter as Record<string, any>)[predicate], option);
|
||||
const fn = this.translatePredicate(entity, attr, predicate, (filter as Record<string, any>)[predicate], option);
|
||||
return (node) => {
|
||||
const row = this.constructRow(node, context, option);
|
||||
if (!row) {
|
||||
|
|
@ -797,7 +838,7 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
}
|
||||
}
|
||||
else {
|
||||
const fn = this.translateObjectPredicate(filter);
|
||||
const fn = this.translateObjectPredicate(entity, filter);
|
||||
return (node) => {
|
||||
const row = this.constructRow(node, context, option);
|
||||
if (!row) {
|
||||
|
|
@ -875,8 +916,8 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
return false;
|
||||
}
|
||||
if ((row as any).entityId === undefined || (row as any).entity === undefined) {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.warn(`对象${entity as string}上的entity/entityId不能确定值,可能会影响判定结果`);
|
||||
if (option.warnWhenAttributeMiss) {
|
||||
showWarningAttributeMiss<ED>(entity, 'entity/entityId');
|
||||
}
|
||||
return false; // 若不能确定,认定为条件不满足
|
||||
}
|
||||
|
|
@ -911,8 +952,8 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
return filterFn(node2, nodeDict, exprResolveFns);
|
||||
}
|
||||
if ((row as any)[`${attr}Id`] === undefined) {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.warn(`对象${entity as string}上的${attr}Id不能确定值,可能会影响判定结果`);
|
||||
if (option.warnWhenAttributeMiss) {
|
||||
showWarningAttributeMiss<ED>(entity, `${attr}Id`);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
@ -964,13 +1005,17 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
}
|
||||
});
|
||||
}
|
||||
const option2 = Object.assign({}, option, { nodeDict, dontCollect: true });
|
||||
const subQuerySet = (this.selectAbjointRow(otmEntity, {
|
||||
data: otmProjection,
|
||||
filter: otmFilter,
|
||||
indexFrom: 0,
|
||||
count: 1,
|
||||
}, context, option2)).map(
|
||||
}, context, {
|
||||
...option,
|
||||
nodeDict,
|
||||
dontCollect: true,
|
||||
warnWhenAttributeMiss: false, // 一对多连接不必要考虑这个属性缺失
|
||||
})).map(
|
||||
(ele) => {
|
||||
return (ele)[fk] as string | null;
|
||||
}
|
||||
|
|
@ -1013,7 +1058,11 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
filter: otmFilter,
|
||||
indexFrom: 0,
|
||||
count: 1,
|
||||
}, context, { dontCollect: true })).map(
|
||||
}, context, {
|
||||
...option,
|
||||
dontCollect: true,
|
||||
warnWhenAttributeMiss: false, // 一对多连接不必要考虑这个属性缺失
|
||||
})).map(
|
||||
(ele) => {
|
||||
return (ele)[fk] as string | null;
|
||||
}
|
||||
|
|
@ -1052,12 +1101,15 @@ export default class TreeStore<ED extends EntityDict & BaseEntityDict> extends C
|
|||
/**
|
||||
* 尝试用hashjoin将内表数组取出,因为memory中的表都不会太大,且用不了索引(未来优化了可能可以用id直接取值),因而用hash应当会更快
|
||||
*/
|
||||
const option2 = Object.assign({}, option, { dontCollect: true });
|
||||
try {
|
||||
const subQueryRows = this.selectAbjointRow(otmEntity, {
|
||||
data: otmProjection,
|
||||
filter: filter[attr],
|
||||
}, context, option2);
|
||||
}, context, {
|
||||
...option,
|
||||
dontCollect: true,
|
||||
warnWhenAttributeMiss: false, // 一对多连接不必要考虑这个属性缺失
|
||||
});
|
||||
|
||||
const buckets = groupBy(subQueryRows, fk);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue