更新了localebuilder中出错处理,在判定attrUpdateMatrix时,增加了对cascade更新条件的判定
This commit is contained in:
parent
8f433f84bf
commit
68289a281e
|
|
@ -133,9 +133,14 @@ class LocaleBuilder {
|
|||
this.locales[ns] = [module, position.replace(/\\/g, '/'), language, data];
|
||||
if (watch) {
|
||||
fs_1.default.watch(filepath, () => {
|
||||
const data = this.readLocaleFileContent(filepath);
|
||||
this.locales[ns] = [module, position.replace(/\\/g, '/'), language, data];
|
||||
this.outputDataFile();
|
||||
try {
|
||||
const data = this.readLocaleFileContent(filepath);
|
||||
this.locales[ns] = [module, position.replace(/\\/g, '/'), language, data];
|
||||
this.outputDataFile();
|
||||
}
|
||||
catch (err) {
|
||||
// 啥都不干
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeIntrinsicCheckers = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const types_1 = require("../types");
|
||||
const lodash_1 = require("../utils/lodash");
|
||||
const filter_1 = require("./filter");
|
||||
const modi_1 = require("./modi");
|
||||
const checker_1 = require("./checker");
|
||||
const action_1 = require("../actions/action");
|
||||
const assert_1 = tslib_1.__importDefault(require("assert"));
|
||||
function checkUniqueBetweenRows(rows, uniqAttrs) {
|
||||
// 先检查这些行本身之间有无unique冲突
|
||||
const dict = {};
|
||||
|
|
@ -241,6 +243,60 @@ function createActionTransformerCheckers(actionDefDict) {
|
|||
}
|
||||
return checkers;
|
||||
}
|
||||
/**
|
||||
* 检查一次更新是否有关联通过的可能
|
||||
* 例如,更新A的条件是B = 1,此时行上的B并不等于1,但由于更新数据是: { B: 1, A: .. }
|
||||
* 此时如果B更新可以成功则A也可以成功
|
||||
* @param entity
|
||||
* @param data
|
||||
* @param filters
|
||||
* @param context
|
||||
*/
|
||||
function cascadelyCheckUpdateFilters(entity, schema, data, filter, matrix, restAttrs, context) {
|
||||
const successAttrs = (0, lodash_1.difference)(Object.keys(data), restAttrs);
|
||||
const successAttrFilter = (0, lodash_1.pick)(data, successAttrs);
|
||||
/**
|
||||
* 先找到能直接更新成功的属性
|
||||
*/
|
||||
const legalAttrResult = restAttrs.map((attr) => {
|
||||
const { filter: f } = matrix[attr];
|
||||
if (!f) {
|
||||
return true;
|
||||
}
|
||||
// 此时看应用了success的attributes更新后,能否消除掉f中的部分条件
|
||||
const result = (0, filter_1.analyzeFilterRelation)(entity, schema, successAttrFilter, f, true);
|
||||
if (typeof result === 'boolean') {
|
||||
return result;
|
||||
}
|
||||
const { sureAttributes } = result;
|
||||
const f2 = (0, lodash_1.omit)(f, sureAttributes);
|
||||
return (0, filter_1.checkFilterContains)(entity, context, f2, filter, true);
|
||||
});
|
||||
const checkResult1 = (lar) => {
|
||||
const legalAttrs = [];
|
||||
const illegalAttrs = [];
|
||||
(0, assert_1.default)(lar.length === restAttrs.length);
|
||||
lar.forEach((ele, idx) => {
|
||||
if (ele) {
|
||||
legalAttrs.push(restAttrs[idx]);
|
||||
}
|
||||
else {
|
||||
illegalAttrs.push(restAttrs[idx]);
|
||||
}
|
||||
});
|
||||
if (illegalAttrs.length === 0) {
|
||||
return;
|
||||
}
|
||||
if (legalAttrs.length === 0) {
|
||||
throw new types_1.OakAttrCantUpdateException(entity, illegalAttrs, '更新的行当前属性不满足约束,请仔细检查数据');
|
||||
}
|
||||
return cascadelyCheckUpdateFilters(entity, schema, data, filter, matrix, illegalAttrs, context);
|
||||
};
|
||||
if (legalAttrResult.find(ele => ele instanceof Promise)) {
|
||||
return Promise.all(legalAttrResult).then((lar) => checkResult1(lar));
|
||||
}
|
||||
return checkResult1(legalAttrResult);
|
||||
}
|
||||
function createAttrUpdateCheckers(schema, attrUpdateMatrix) {
|
||||
const checkers = [];
|
||||
for (const entity in attrUpdateMatrix) {
|
||||
|
|
@ -270,19 +326,27 @@ function createAttrUpdateCheckers(schema, attrUpdateMatrix) {
|
|||
if (!a.includes(action)) {
|
||||
// 找到不满足的那个attr
|
||||
const attrsIllegal = attrs.filter((attr) => matrix[attr]?.actions && !matrix[attr]?.actions?.includes(action));
|
||||
throw new types_1.OakAttrCantUpdateException(entity, attrsIllegal, `${attrsIllegal}不允许被${action}动作更新`);
|
||||
throw new types_1.OakAttrCantUpdateException(entity, attrsIllegal, `${attrsIllegal.join(',')}不允许被${action}动作更新`);
|
||||
}
|
||||
}
|
||||
if (f) {
|
||||
const rr = (0, filter_1.contains)(entity, context.getSchema(), data, f);
|
||||
console.log(rr);
|
||||
const result = (0, filter_1.checkFilterContains)(entity, context, f, filter, true);
|
||||
if (result instanceof Promise) {
|
||||
return result.then((v) => {
|
||||
if (!v) {
|
||||
if (attrs.length > 1) {
|
||||
return cascadelyCheckUpdateFilters(entity, schema, data, filter, matrix, attrs, context);
|
||||
}
|
||||
throw new types_1.OakAttrCantUpdateException(entity, attrs, '更新的行当前属性不满足约束,请仔细检查数据');
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!result) {
|
||||
if (attrs.length > 1) {
|
||||
return cascadelyCheckUpdateFilters(entity, schema, data, filter, matrix, attrs, context);
|
||||
}
|
||||
throw new types_1.OakAttrCantUpdateException(entity, attrs, '更新的行当前属性不满足约束,请仔细检查数据');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,14 @@ import { AsyncContext } from './AsyncRowStore';
|
|||
import { SyncContext } from './SyncRowStore';
|
||||
export declare function translateCreateDataToFilter<ED extends EntityDict & BaseEntityDict, T extends keyof ED>(schema: StorageSchema<ED>, entity: T, data: ED[T]['CreateSingle']['data'], allowUnrecoganized: boolean): ED[T]["Selection"]["filter"];
|
||||
export declare function combineFilters<ED extends EntityDict & BaseEntityDict, T extends keyof ED>(entity: T, schema: StorageSchema<ED>, filters: Array<ED[T]['Selection']['filter']>, union?: true): ED[T]["Selection"]["filter"] | undefined;
|
||||
type DeducedFilter<ED extends EntityDict & BaseEntityDict, T extends keyof ED> = {
|
||||
entity: T;
|
||||
filter: ED[T]['Selection']['filter'];
|
||||
};
|
||||
type DeducedFilterCombination<ED extends EntityDict & BaseEntityDict> = {
|
||||
$or?: (DeducedFilterCombination<ED> | DeducedFilter<ED, keyof ED>)[];
|
||||
$and?: (DeducedFilterCombination<ED> | DeducedFilter<ED, keyof ED>)[];
|
||||
};
|
||||
/**
|
||||
* 在以下判断相容或相斥的过程中,相容/相斥的事实标准是:满足两个条件的查询集合是否被包容/互斥,但如果两个filter在逻辑上相容或者相斥,在事实上不一定相容或者相斥
|
||||
* 例如:{ a: 1 } 和 { a: { $ne: 1 } } 是明显不相容的查询,但如果数据为空集,则这两个查询并不能否定其相容
|
||||
|
|
@ -35,6 +43,44 @@ export declare function combineFilters<ED extends EntityDict & BaseEntityDict, T
|
|||
* @attention: 1)这里的测试不够充分,有些算子之间的相容或相斥可能有遗漏, 2)有新的算子加入需要修改代码
|
||||
*/
|
||||
export declare function judgeValueRelation(value1: any, value2: any, contained: boolean): boolean | undefined;
|
||||
/**
|
||||
* 根据filter对compared查询的各个条件进行逐项分析
|
||||
* @param entity
|
||||
* @param schema
|
||||
* @param filter
|
||||
* @param compared
|
||||
* @param contained
|
||||
* @returns
|
||||
* sureAttributes中包含被判定肯定相容或肯定不相斥的属性(不用再继续判定了)
|
||||
* uncertainAttributes中包含的是无法判定结果的属性
|
||||
* totalAndDeducedFilters包含的是判定过程中推论的相容的充分条件(and关系)
|
||||
* totalOrDeducedFilters包含的是判定过程中推论的相斥的充分条件(or关系)
|
||||
*/
|
||||
export declare function analyzeFilterRelation<ED extends EntityDict & BaseEntityDict, T extends keyof ED>(entity: T, schema: StorageSchema<ED>, filter: NonNullable<ED[T]['Selection']['filter']>, compared: NonNullable<ED[T]['Selection']['filter']>, contained: boolean): boolean | {
|
||||
totalAndDeducedFilters: (DeducedFilterCombination<ED> | DeducedFilter<ED, T>)[];
|
||||
totalOrDeducedFilters: (DeducedFilterCombination<ED> | DeducedFilter<ED, T>)[];
|
||||
uncertainAttributes: string[];
|
||||
sureAttributes: string[];
|
||||
};
|
||||
/**
|
||||
*
|
||||
* 判断filter是否包含contained中的查询条件,即filter查询的结果一定是contained查询结果的子集
|
||||
* filter = {
|
||||
* a: 1
|
||||
* b: 2,
|
||||
* c: 3,
|
||||
* },
|
||||
* conditionalFilter = {
|
||||
* a: 1
|
||||
* }
|
||||
* 则包含
|
||||
* @param entity
|
||||
* @param schema
|
||||
* @param filter
|
||||
* @param contained
|
||||
* @returns
|
||||
*/
|
||||
export declare function contains<ED extends EntityDict & BaseEntityDict, T extends keyof ED>(entity: T, schema: StorageSchema<ED>, filter: ED[T]['Selection']['filter'], contained: ED[T]['Selection']['filter']): boolean | DeducedFilterCombination<ED>;
|
||||
/**
|
||||
* 从filter中判断是否有确定的id对象,如果有则返回这些id,没有返回空数组
|
||||
* @param filter
|
||||
|
|
@ -84,3 +130,4 @@ export declare function checkFilterRepel<ED extends EntityDict & BaseEntityDict,
|
|||
* @param filter
|
||||
*/
|
||||
export declare function translateFilterToObjectPredicate(filter: Record<string, any>): {};
|
||||
export {};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.translateFilterToObjectPredicate = exports.checkFilterRepel = exports.checkFilterContains = exports.makeTreeDescendantFilter = exports.makeTreeAncestorFilter = exports.same = exports.getRelevantIds = exports.judgeValueRelation = exports.combineFilters = exports.translateCreateDataToFilter = void 0;
|
||||
exports.translateFilterToObjectPredicate = exports.checkFilterRepel = exports.checkFilterContains = exports.makeTreeDescendantFilter = exports.makeTreeAncestorFilter = exports.same = exports.getRelevantIds = exports.contains = exports.analyzeFilterRelation = exports.judgeValueRelation = exports.combineFilters = exports.translateCreateDataToFilter = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const assert_1 = tslib_1.__importDefault(require("assert"));
|
||||
const types_1 = require("../types");
|
||||
|
|
@ -43,9 +43,24 @@ function addFilterSegment(entity, schema, ...filters) {
|
|||
if (!filter[attr]) {
|
||||
filter[attr] = value;
|
||||
}
|
||||
// 只优化一种情况,就是两个都等值且相等
|
||||
// 优化两个都等值且相等
|
||||
else if (filter[attr] === value) {
|
||||
}
|
||||
// value定义的查询被当前查询包含
|
||||
else if (contains(entity, schema, {
|
||||
[attr]: value,
|
||||
}, {
|
||||
[attr]: filter[attr],
|
||||
}) === true) {
|
||||
filter[attr] = value;
|
||||
}
|
||||
// 当前查询被value所定义的查询包含
|
||||
else if (contains(entity, schema, {
|
||||
[attr]: filter[attr],
|
||||
}, {
|
||||
[attr]: value
|
||||
}) == true) {
|
||||
}
|
||||
else {
|
||||
addIntoAnd({
|
||||
[attr]: value,
|
||||
|
|
@ -1041,15 +1056,20 @@ function judgeFilterSingleAttrRelation(entity, schema, attr, filter, compared, c
|
|||
// 到这里说明无法直接判断此attr上的相容或者相斥,也无法把判定推断到更深层的算子之上
|
||||
return;
|
||||
}
|
||||
/** 判断filter条件对compared条件是否相容或相斥
|
||||
/**
|
||||
* 根据filter对compared查询的各个条件进行逐项分析
|
||||
* @param entity
|
||||
* @param schema
|
||||
* @param filter
|
||||
* @param compared
|
||||
* @param contained: true代表判定filter包容compared(filter的查询结果是compared查询结果的子集), false代表判定filter与compared相斥(filter的查询结果与compared没有交集)
|
||||
* @returns 返回true说明肯定相容(相斥),返回false说明无法判定相容(相斥),返回DeducedFilterCombination说明需要进一步判断此推断的条件
|
||||
* @param contained
|
||||
* @returns
|
||||
* sureAttributes中包含被判定肯定相容或肯定不相斥的属性(不用再继续判定了)
|
||||
* uncertainAttributes中包含的是无法判定结果的属性
|
||||
* totalAndDeducedFilters包含的是判定过程中推论的相容的充分条件(and关系)
|
||||
* totalOrDeducedFilters包含的是判定过程中推论的相斥的充分条件(or关系)
|
||||
*/
|
||||
function judgeFilterRelation(entity, schema, filter, compared, contained) {
|
||||
function analyzeFilterRelation(entity, schema, filter, compared, contained) {
|
||||
const totalAndDeducedFilters = [];
|
||||
const totalOrDeducedFilters = [];
|
||||
const uncertainAttributes = [];
|
||||
|
|
@ -1239,6 +1259,28 @@ function judgeFilterRelation(entity, schema, filter, compared, contained) {
|
|||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
totalAndDeducedFilters,
|
||||
totalOrDeducedFilters,
|
||||
uncertainAttributes,
|
||||
sureAttributes,
|
||||
};
|
||||
}
|
||||
exports.analyzeFilterRelation = analyzeFilterRelation;
|
||||
/** 判断filter条件对compared条件是否相容或相斥
|
||||
* @param entity
|
||||
* @param schema
|
||||
* @param filter
|
||||
* @param compared
|
||||
* @param contained: true代表判定filter包容compared(filter的查询结果是compared查询结果的子集), false代表判定filter与compared相斥(filter的查询结果与compared没有交集)
|
||||
* @returns 返回true说明肯定相容(相斥),返回false说明无法判定相容(相斥),返回DeducedFilterCombination说明需要进一步判断此推断的条件
|
||||
*/
|
||||
function judgeFilterRelation(entity, schema, filter, compared, contained) {
|
||||
const result = analyzeFilterRelation(entity, schema, filter, compared, contained);
|
||||
if (typeof result === 'boolean') {
|
||||
return result;
|
||||
}
|
||||
const { sureAttributes, uncertainAttributes, totalAndDeducedFilters, totalOrDeducedFilters, } = result;
|
||||
if (contained) {
|
||||
if (sureAttributes.length === Object.keys(compared).length) {
|
||||
return true;
|
||||
|
|
@ -1296,6 +1338,7 @@ function contains(entity, schema, filter, contained) {
|
|||
return judgeFilterRelation(entity, schema, filter, contained, true);
|
||||
// return false;
|
||||
}
|
||||
exports.contains = contains;
|
||||
/**
|
||||
* 判断filter1和filter2是否相斥,即filter1和filter2查询的结果一定没有交集
|
||||
* filter1 = {
|
||||
|
|
|
|||
|
|
@ -219,9 +219,14 @@ export default class LocaleBuilder {
|
|||
|
||||
if (watch) {
|
||||
fs.watch(filepath, () => {
|
||||
const data = this.readLocaleFileContent(filepath);
|
||||
this.locales[ns] = [module, position.replace(/\\/g, '/'), language, data];
|
||||
this.outputDataFile();
|
||||
try {
|
||||
const data = this.readLocaleFileContent(filepath);
|
||||
this.locales[ns] = [module, position.replace(/\\/g, '/'), language, data];
|
||||
this.outputDataFile();
|
||||
}
|
||||
catch(err) {
|
||||
// 啥都不干
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
import { ActionDefDict, Checker, EntityDict, StorageSchema, RowChecker, OakUniqueViolationException, CHECKER_MAX_PRIORITY, AttrUpdateMatrix, LogicalChecker, OakAttrCantUpdateException } from "../types";
|
||||
import { SyncContext } from "./SyncRowStore";
|
||||
import { AsyncContext } from "./AsyncRowStore";
|
||||
import { pick, intersection, difference } from '../utils/lodash';
|
||||
import { checkFilterContains, combineFilters } from "./filter";
|
||||
import { pick, intersection, difference, omit } from '../utils/lodash';
|
||||
import { analyzeFilterRelation, checkFilterContains, combineFilters, contains } from "./filter";
|
||||
import { EntityDict as BaseEntityDict } from '../base-app-domain/EntityDict';
|
||||
import { createModiRelatedCheckers } from "./modi";
|
||||
import { createCreateCheckers, createRemoveCheckers } from "./checker";
|
||||
import { readOnlyActions } from "../actions/action";
|
||||
import assert from 'assert';
|
||||
|
||||
|
||||
function checkUniqueBetweenRows(rows: Record<string, any>[], uniqAttrs: string[]) {
|
||||
|
|
@ -270,7 +271,7 @@ function createActionTransformerCheckers<ED extends EntityDict & BaseEntityDict,
|
|||
}
|
||||
);
|
||||
}
|
||||
else if (data){
|
||||
else if (data) {
|
||||
if (!(data as Readonly<ED[keyof ED]['CreateSingle']['data']>)[attr]) {
|
||||
Object.assign(data, {
|
||||
[attr]: is,
|
||||
|
|
@ -286,6 +287,82 @@ function createActionTransformerCheckers<ED extends EntityDict & BaseEntityDict,
|
|||
return checkers;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查一次更新是否有关联通过的可能
|
||||
* 例如,更新A的条件是B = 1,此时行上的B并不等于1,但由于更新数据是: { B: 1, A: .. }
|
||||
* 此时如果B更新可以成功则A也可以成功
|
||||
* @param entity
|
||||
* @param data
|
||||
* @param filters
|
||||
* @param context
|
||||
*/
|
||||
function cascadelyCheckUpdateFilters<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>, FrontCxt extends SyncContext<ED>>(
|
||||
entity: T,
|
||||
schema: StorageSchema<ED>,
|
||||
data: ED[T]['Update']['data'],
|
||||
filter: ED[T]['Update']['filter'],
|
||||
matrix: NonNullable<AttrUpdateMatrix<ED>[T]>,
|
||||
restAttrs: string[],
|
||||
context: Cxt | FrontCxt
|
||||
): void | Promise<void> {
|
||||
const successAttrs = difference(Object.keys(data), restAttrs);
|
||||
const successAttrFilter = pick(data, successAttrs);
|
||||
/**
|
||||
* 先找到能直接更新成功的属性
|
||||
*/
|
||||
const legalAttrResult = restAttrs.map(
|
||||
(attr) => {
|
||||
const { filter: f } = matrix[attr]!;
|
||||
if (!f) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 此时看应用了success的attributes更新后,能否消除掉f中的部分条件
|
||||
const result = analyzeFilterRelation(entity, schema, successAttrFilter, f, true);
|
||||
if (typeof result === 'boolean') {
|
||||
return result;
|
||||
}
|
||||
const { sureAttributes } = result;
|
||||
const f2 = omit(f, sureAttributes);
|
||||
|
||||
return checkFilterContains<ED, keyof ED, Cxt | FrontCxt>(entity, context, f2, filter, true);
|
||||
}
|
||||
);
|
||||
|
||||
const checkResult1 = (lar: boolean[]) => {
|
||||
const legalAttrs: string[] = [];
|
||||
const illegalAttrs: string[] = [];
|
||||
|
||||
|
||||
assert(lar.length === restAttrs.length);
|
||||
lar.forEach(
|
||||
(ele, idx) => {
|
||||
if (ele) {
|
||||
legalAttrs.push(restAttrs[idx]);
|
||||
}
|
||||
else {
|
||||
illegalAttrs.push(restAttrs[idx]);
|
||||
}
|
||||
}
|
||||
);
|
||||
if (illegalAttrs.length === 0) {
|
||||
return;
|
||||
}
|
||||
if (legalAttrs.length === 0) {
|
||||
throw new OakAttrCantUpdateException(entity as keyof ED, illegalAttrs, '更新的行当前属性不满足约束,请仔细检查数据');
|
||||
}
|
||||
return cascadelyCheckUpdateFilters(entity, schema, data, filter, matrix, illegalAttrs, context);
|
||||
};
|
||||
|
||||
if (legalAttrResult.find(ele => ele instanceof Promise)) {
|
||||
return Promise.all(legalAttrResult).then(
|
||||
(lar) => checkResult1(lar)
|
||||
);
|
||||
}
|
||||
|
||||
return checkResult1(legalAttrResult as boolean[]);
|
||||
}
|
||||
|
||||
function createAttrUpdateCheckers<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>, FrontCxt extends SyncContext<ED>>(
|
||||
schema: StorageSchema<ED>,
|
||||
attrUpdateMatrix: AttrUpdateMatrix<ED>
|
||||
|
|
@ -323,21 +400,31 @@ function createAttrUpdateCheckers<ED extends EntityDict & BaseEntityDict, Cxt ex
|
|||
const attrsIllegal = attrs.filter(
|
||||
(attr) => matrix[attr]?.actions && !matrix[attr]?.actions?.includes(action!)
|
||||
);
|
||||
throw new OakAttrCantUpdateException(entity, attrsIllegal, `${attrsIllegal}不允许被${action}动作更新`);
|
||||
throw new OakAttrCantUpdateException(entity, attrsIllegal, `${attrsIllegal.join(',')}不允许被${action}动作更新`);
|
||||
}
|
||||
}
|
||||
if (f) {
|
||||
const result = checkFilterContains<ED, keyof ED, Cxt>(entity, context as any, f, filter, true);
|
||||
const rr = contains<ED, keyof ED>(entity, context.getSchema(), data, f);
|
||||
console.log(rr);
|
||||
const result = checkFilterContains<ED, keyof ED, Cxt | FrontCxt>(entity, context, f, filter, true);
|
||||
if (result instanceof Promise) {
|
||||
return result.then(
|
||||
(v) => {
|
||||
if (!v) {
|
||||
if (attrs.length > 1) {
|
||||
return cascadelyCheckUpdateFilters(entity, schema, data as ED[keyof ED]['Update']['data'],
|
||||
filter, matrix, attrs, context);
|
||||
}
|
||||
throw new OakAttrCantUpdateException(entity, attrs, '更新的行当前属性不满足约束,请仔细检查数据');
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
if (!result) {
|
||||
if (attrs.length > 1) {
|
||||
return cascadelyCheckUpdateFilters(entity, schema, data as ED[keyof ED]['Update']['data'],
|
||||
filter, matrix, attrs, context);
|
||||
}
|
||||
throw new OakAttrCantUpdateException(entity, attrs, '更新的行当前属性不满足约束,请仔细检查数据');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { AsyncContext } from './AsyncRowStore';
|
|||
import { judgeRelation } from './relation';
|
||||
import { SyncContext } from './SyncRowStore';
|
||||
|
||||
export function translateCreateDataToFilter<ED extends EntityDict & BaseEntityDict, T extends keyof ED> (
|
||||
export function translateCreateDataToFilter<ED extends EntityDict & BaseEntityDict, T extends keyof ED>(
|
||||
schema: StorageSchema<ED>,
|
||||
entity: T,
|
||||
data: ED[T]['CreateSingle']['data'],
|
||||
|
|
@ -53,9 +53,24 @@ function addFilterSegment<ED extends EntityDict & BaseEntityDict, T extends keyo
|
|||
if (!filter[attr]) {
|
||||
filter[attr] = value;
|
||||
}
|
||||
// 只优化一种情况,就是两个都等值且相等
|
||||
// 优化两个都等值且相等
|
||||
else if (filter[attr] === value) {
|
||||
|
||||
}
|
||||
// value定义的查询被当前查询包含
|
||||
else if (contains(entity, schema, {
|
||||
[attr]: value,
|
||||
}, {
|
||||
[attr]: filter[attr],
|
||||
}) === true) {
|
||||
filter[attr] = value;
|
||||
}
|
||||
// 当前查询被value所定义的查询包含
|
||||
else if (contains(entity, schema, {
|
||||
[attr]: filter[attr],
|
||||
}, {
|
||||
[attr]: value
|
||||
}) == true) {
|
||||
}
|
||||
else {
|
||||
addIntoAnd({
|
||||
|
|
@ -1194,21 +1209,25 @@ function judgeFilterSingleAttrRelation<ED extends EntityDict & BaseEntityDict, T
|
|||
return;
|
||||
}
|
||||
|
||||
/** 判断filter条件对compared条件是否相容或相斥
|
||||
/**
|
||||
* 根据filter对compared查询的各个条件进行逐项分析
|
||||
* @param entity
|
||||
* @param schema
|
||||
* @param filter
|
||||
* @param compared
|
||||
* @param contained: true代表判定filter包容compared(filter的查询结果是compared查询结果的子集), false代表判定filter与compared相斥(filter的查询结果与compared没有交集)
|
||||
* @returns 返回true说明肯定相容(相斥),返回false说明无法判定相容(相斥),返回DeducedFilterCombination说明需要进一步判断此推断的条件
|
||||
* @param compared
|
||||
* @param contained
|
||||
* @returns
|
||||
* sureAttributes中包含被判定肯定相容或肯定不相斥的属性(不用再继续判定了)
|
||||
* uncertainAttributes中包含的是无法判定结果的属性
|
||||
* totalAndDeducedFilters包含的是判定过程中推论的相容的充分条件(and关系)
|
||||
* totalOrDeducedFilters包含的是判定过程中推论的相斥的充分条件(or关系)
|
||||
*/
|
||||
function judgeFilterRelation<ED extends EntityDict & BaseEntityDict, T extends keyof ED>(
|
||||
export function analyzeFilterRelation<ED extends EntityDict & BaseEntityDict, T extends keyof ED>(
|
||||
entity: T,
|
||||
schema: StorageSchema<ED>,
|
||||
filter: NonNullable<ED[T]['Selection']['filter']>,
|
||||
compared: NonNullable<ED[T]['Selection']['filter']>,
|
||||
contained: boolean): boolean | DeducedFilterCombination<ED> {
|
||||
|
||||
contained: boolean) {
|
||||
const totalAndDeducedFilters: (DeducedFilterCombination<ED> | DeducedFilter<ED, T>)[] = [];
|
||||
const totalOrDeducedFilters: (DeducedFilterCombination<ED> | DeducedFilter<ED, T>)[] = [];
|
||||
const uncertainAttributes: string[] = [];
|
||||
|
|
@ -1405,6 +1424,40 @@ function judgeFilterRelation<ED extends EntityDict & BaseEntityDict, T extends k
|
|||
}
|
||||
}
|
||||
|
||||
return {
|
||||
totalAndDeducedFilters,
|
||||
totalOrDeducedFilters,
|
||||
uncertainAttributes,
|
||||
sureAttributes,
|
||||
};
|
||||
}
|
||||
/** 判断filter条件对compared条件是否相容或相斥
|
||||
* @param entity
|
||||
* @param schema
|
||||
* @param filter
|
||||
* @param compared
|
||||
* @param contained: true代表判定filter包容compared(filter的查询结果是compared查询结果的子集), false代表判定filter与compared相斥(filter的查询结果与compared没有交集)
|
||||
* @returns 返回true说明肯定相容(相斥),返回false说明无法判定相容(相斥),返回DeducedFilterCombination说明需要进一步判断此推断的条件
|
||||
*/
|
||||
function judgeFilterRelation<ED extends EntityDict & BaseEntityDict, T extends keyof ED>(
|
||||
entity: T,
|
||||
schema: StorageSchema<ED>,
|
||||
filter: NonNullable<ED[T]['Selection']['filter']>,
|
||||
compared: NonNullable<ED[T]['Selection']['filter']>,
|
||||
contained: boolean): boolean | DeducedFilterCombination<ED> {
|
||||
|
||||
const result = analyzeFilterRelation(entity, schema, filter, compared, contained);
|
||||
if (typeof result === 'boolean') {
|
||||
return result;
|
||||
}
|
||||
|
||||
const {
|
||||
sureAttributes,
|
||||
uncertainAttributes,
|
||||
totalAndDeducedFilters,
|
||||
totalOrDeducedFilters,
|
||||
} = result;
|
||||
|
||||
if (contained) {
|
||||
if (sureAttributes.length === Object.keys(compared).length) {
|
||||
return true;
|
||||
|
|
@ -1457,7 +1510,7 @@ function judgeFilterRelation<ED extends EntityDict & BaseEntityDict, T extends k
|
|||
* @param contained
|
||||
* @returns
|
||||
*/
|
||||
function contains<ED extends EntityDict & BaseEntityDict, T extends keyof ED>(
|
||||
export function contains<ED extends EntityDict & BaseEntityDict, T extends keyof ED>(
|
||||
entity: T,
|
||||
schema: StorageSchema<ED>,
|
||||
filter: ED[T]['Selection']['filter'],
|
||||
|
|
|
|||
Loading…
Reference in New Issue