Merge branch 'dev'
This commit is contained in:
commit
a31f5a2015
|
|
@ -50,7 +50,7 @@ export declare abstract class AsyncContext<ED extends EntityDict> implements Con
|
|||
abstract getCurrentUserId(allowUnloggedIn?: boolean): string | undefined;
|
||||
abstract setCurrentUserId(userId: string | undefined): void;
|
||||
abstract toString(): Promise<string>;
|
||||
abstract initialize(data: any, later?: boolean): Promise<void>;
|
||||
abstract initialize(data?: any, later?: boolean): Promise<void>;
|
||||
abstract allowUserUpdate(): boolean;
|
||||
abstract openRootMode(): () => void;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ function createUniqueCheckers(schema) {
|
|||
entity,
|
||||
action: 'create',
|
||||
type: 'logicalData',
|
||||
priority: types_1.CHECKER_MAX_PRIORITY, // 优先级要放在最低,所有前置的checker/trigger将数据完整之后再在这里检测
|
||||
priority: types_1.CHECKER_MAX_PRIORITY,
|
||||
checker: (operation, context) => {
|
||||
const { data } = operation;
|
||||
if (data instanceof Array) {
|
||||
|
|
@ -93,9 +93,9 @@ function createUniqueCheckers(schema) {
|
|||
}
|
||||
}, {
|
||||
entity,
|
||||
action: 'update', // 只检查update,其它状态转换的action应该不会涉及unique约束的属性
|
||||
action: 'update',
|
||||
type: 'logicalData',
|
||||
priority: types_1.CHECKER_MAX_PRIORITY, // 优先级要放在最低,所有前置的checker/trigger将数据完整之后再在这里检测
|
||||
priority: types_1.CHECKER_MAX_PRIORITY,
|
||||
checker: (operation, context) => {
|
||||
const { data, filter: operationFilter } = operation;
|
||||
if (data) {
|
||||
|
|
@ -213,7 +213,7 @@ function createActionTransformerCheckers(actionDefDict) {
|
|||
action: 'create',
|
||||
type: 'logicalData',
|
||||
entity,
|
||||
priority: 10, // 优先级要高,先于真正的data检查进行
|
||||
priority: 10,
|
||||
checker: (operation) => {
|
||||
const { data } = operation;
|
||||
if (data instanceof Array) {
|
||||
|
|
|
|||
|
|
@ -441,10 +441,10 @@ class RelationAuth {
|
|||
* @returns
|
||||
*/
|
||||
const makeCreateFilter = (entity, operation) => {
|
||||
const { data, filter } = operation;
|
||||
const { data, filter, bornAt } = operation;
|
||||
(0, assert_1.default)(!(data instanceof Array));
|
||||
if (data) {
|
||||
return (0, filter_1.translateCreateDataToFilter)(this.schema, entity, data);
|
||||
return (0, filter_1.translateCreateDataToFilter)(this.schema, entity, data, !!bornAt);
|
||||
}
|
||||
return filter;
|
||||
};
|
||||
|
|
@ -498,7 +498,7 @@ class RelationAuth {
|
|||
}
|
||||
(0, assert_1.default)(!(data instanceof Array));
|
||||
for (const attr in data) {
|
||||
const rel = (0, relation_1.judgeRelation)(this.schema, entity, attr);
|
||||
const rel = (0, relation_1.judgeRelation)(this.schema, entity, attr, !!operation.bornAt);
|
||||
if (rel === 2 && !isModiUpdate) {
|
||||
(0, assert_1.default)(root === me && !hasParent, 'cascadeUpdate必须是树结构,避免森林');
|
||||
const mtoOperation = data[attr];
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export declare class TriggerExecutor<ED extends EntityDict & BaseEntityDict, Cxt
|
|||
private logger;
|
||||
private contextBuilder;
|
||||
private onVolatileTrigger;
|
||||
constructor(contextBuilder: (cxtString?: string) => Promise<Cxt>, logger?: Logger, onVolatileTrigger?: <T extends keyof ED>(entity: T, trigger: VolatileTrigger<ED, T, Cxt>, ids: string[], cxtStr: string, option: OperateOption) => Promise<void>);
|
||||
constructor(contextBuilder: () => Cxt, logger?: Logger, onVolatileTrigger?: <T extends keyof ED>(entity: T, trigger: VolatileTrigger<ED, T, Cxt>, ids: string[], cxtStr: string, option: OperateOption) => Promise<void>);
|
||||
setOnVolatileTrigger(onVolatileTrigger: <T extends keyof ED>(entity: T, trigger: VolatileTrigger<ED, T, Cxt>, ids: string[], cxtStr: string, option: OperateOption) => Promise<void>): void;
|
||||
registerChecker<T extends keyof ED>(checker: Checker<ED, T, Cxt>, schema: StorageSchema<ED>): void;
|
||||
registerTrigger<T extends keyof ED>(trigger: Trigger<ED, T, Cxt>): void;
|
||||
|
|
|
|||
|
|
@ -39,15 +39,21 @@ class TriggerExecutor {
|
|||
this.volatileEntities = [];
|
||||
this.counter = 0;
|
||||
this.onVolatileTrigger = onVolatileTrigger || (async (entity, trigger, ids, cxtStr, option) => {
|
||||
const context = await this.contextBuilder(cxtStr);
|
||||
await context.begin();
|
||||
const context = this.contextBuilder();
|
||||
if (!context.getCurrentTxnId()) {
|
||||
await context.begin();
|
||||
}
|
||||
await context.initialize(JSON.parse(cxtStr));
|
||||
try {
|
||||
await this.execVolatileTrigger(entity, trigger.name, ids, context, option);
|
||||
await context.commit();
|
||||
}
|
||||
catch (err) {
|
||||
await context.rollback();
|
||||
this.logger.error('error on volatile trigger', entity, trigger.name, ids.join(','), err);
|
||||
if (!(err instanceof types_1.OakMakeSureByMySelfException)) {
|
||||
this.logger.error('error on volatile trigger', entity, trigger.name, ids.join(','), err);
|
||||
}
|
||||
// throw err;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -271,8 +277,8 @@ class TriggerExecutor {
|
|||
}
|
||||
}
|
||||
const number = trigger.fn({ operation: operation }, context, option);
|
||||
if (number > 0) {
|
||||
this.logger.info(`触发器「${trigger.name}」成功触发了「${number}」行数据更改`);
|
||||
if (number > 0 && process.env.NODE_ENV === 'development') {
|
||||
this.logger.info(`前触发器「${trigger.name}」成功触发了「${number}」行数据更改`);
|
||||
}
|
||||
}
|
||||
(0, assert_1.default)(commitTriggers.length === 0, `前台不应有commitTrigger`);
|
||||
|
|
@ -294,8 +300,8 @@ class TriggerExecutor {
|
|||
}
|
||||
}
|
||||
const number = await trigger.fn({ operation: operation }, context, option);
|
||||
if (number > 0) {
|
||||
this.logger.info(`触发器「${trigger.name}」成功触发了「${number}」行数据更改`);
|
||||
if (number > 0 && process.env.NODE_ENV === 'development') {
|
||||
this.logger.info(`前触发器「${trigger.name}」成功触发了「${number}」行数据更改`);
|
||||
}
|
||||
return execPreTrigger(idx + 1);
|
||||
};
|
||||
|
|
@ -382,8 +388,8 @@ class TriggerExecutor {
|
|||
operation: operation,
|
||||
result: result,
|
||||
}, context, option);
|
||||
if (number > 0) {
|
||||
this.logger.info(`触发器「${trigger.name}」成功触发了「${number}」行数据更改`);
|
||||
if (number > 0 && process.env.NODE_ENV === 'development') {
|
||||
this.logger.info(`后触发器「${trigger.name}」成功触发了「${number}」行数据更改`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -398,8 +404,8 @@ class TriggerExecutor {
|
|||
operation: operation,
|
||||
result: result,
|
||||
}, context, option);
|
||||
if (number > 0) {
|
||||
this.logger.info(`触发器「${trigger.name}」成功触发了「${number}」行数据更改`);
|
||||
if (number > 0 && process.env.NODE_ENV === 'development') {
|
||||
this.logger.info(`后触发器「${trigger.name}」成功触发了「${number}」行数据更改`);
|
||||
}
|
||||
return execPostTrigger(idx + 1);
|
||||
};
|
||||
|
|
@ -441,7 +447,7 @@ class TriggerExecutor {
|
|||
$lt: timestamp,
|
||||
}
|
||||
};
|
||||
const context = await this.contextBuilder();
|
||||
const context = this.contextBuilder();
|
||||
if (context.clusterInfo?.usingCluster) {
|
||||
const { instanceCount, instanceId } = context.clusterInfo;
|
||||
filter.$$seq$$ = {
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ function translateCheckerInAsyncContext(checker, schema) {
|
|||
case 'row': {
|
||||
const { filter, errMsg, inconsistentRows } = checker;
|
||||
const fn = (async ({ operation }, context, option) => {
|
||||
const { filter: operationFilter, data, action } = operation;
|
||||
const { filter: operationFilter, data, action, bornAt } = operation;
|
||||
const filter2 = typeof filter === 'function' ? await filter(operation, context, option) : filter;
|
||||
if (['select', 'count', 'stat'].includes(action)) {
|
||||
operation.filter = (0, filter_1.combineFilters)(entity, context.getSchema(), [operationFilter, filter2]);
|
||||
|
|
@ -88,11 +88,11 @@ function translateCheckerInAsyncContext(checker, schema) {
|
|||
(0, assert_1.default)(data);
|
||||
if (data instanceof Array) {
|
||||
for (const d of data) {
|
||||
await checkSingle((0, filter_1.translateCreateDataToFilter)(schema, entity, d));
|
||||
await checkSingle((0, filter_1.translateCreateDataToFilter)(schema, entity, d, !!bornAt));
|
||||
}
|
||||
}
|
||||
else {
|
||||
await checkSingle((0, filter_1.translateCreateDataToFilter)(schema, entity, data));
|
||||
await checkSingle((0, filter_1.translateCreateDataToFilter)(schema, entity, data, !!bornAt));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -139,7 +139,7 @@ function translateCheckerInSyncContext(checker, schema) {
|
|||
case 'row': {
|
||||
const { filter, errMsg, entity } = checker;
|
||||
const fn = (operation, context, option) => {
|
||||
const { filter: operationFilter, data, action } = operation;
|
||||
const { filter: operationFilter, data, action, bornAt } = operation;
|
||||
const filter2 = typeof filter === 'function' ? filter(operation, context, option) : filter;
|
||||
let operationFilter2 = operationFilter;
|
||||
if (action === 'create') {
|
||||
|
|
@ -147,7 +147,7 @@ function translateCheckerInSyncContext(checker, schema) {
|
|||
// 前端的策略是,有data用data,无data用filter
|
||||
// 目前前端应该不可能制造出来createMultiple
|
||||
(0, assert_1.default)(!(data instanceof Array));
|
||||
operationFilter2 = (0, filter_1.translateCreateDataToFilter)(schema, entity, data);
|
||||
operationFilter2 = (0, filter_1.translateCreateDataToFilter)(schema, entity, data, !!bornAt);
|
||||
}
|
||||
}
|
||||
(0, assert_1.default)(!(filter2 instanceof Promise));
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { EntityDict as BaseEntityDict, StorageSchema } from '../types';
|
|||
import { EntityDict } from "../base-app-domain";
|
||||
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']): ED[T]["Selection"]["filter"];
|
||||
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;
|
||||
/**
|
||||
* 在以下判断相容或相斥的过程中,相容/相斥的事实标准是:满足两个条件的查询集合是否被包容/互斥,但如果两个filter在逻辑上相容或者相斥,在事实上不一定相容或者相斥
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ const assert_1 = tslib_1.__importDefault(require("assert"));
|
|||
const types_1 = require("../types");
|
||||
const lodash_1 = require("../utils/lodash");
|
||||
const relation_1 = require("./relation");
|
||||
function translateCreateDataToFilter(schema, entity, data) {
|
||||
function translateCreateDataToFilter(schema, entity, data, allowUnrecoganized) {
|
||||
const data2 = {};
|
||||
for (const attr in data) {
|
||||
const rel = (0, relation_1.judgeRelation)(schema, entity, attr);
|
||||
const rel = (0, relation_1.judgeRelation)(schema, entity, attr, allowUnrecoganized);
|
||||
if (rel === 1) {
|
||||
// 只需要记住id和各种外键属性,不这样处理有些古怪的属性比如coordinate,其作为createdata和作为filter并不同构
|
||||
if (!['geometry', 'geography', 'st_geometry', 'st_point'].includes(schema[entity].attributes[attr]?.type)) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/// <reference types="node" />
|
||||
/**
|
||||
* 防止assert打包体积过大,从这里引用
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ function destructRelationPath(schema, entity, path, relationFilter, recursive) {
|
|||
},
|
||||
filter: relationFilter,
|
||||
} // as ED['userRelation']['Selection']
|
||||
}, // as ED[keyof ED]['Selection']['data'],
|
||||
},
|
||||
getData: (d) => {
|
||||
return d.userRelation$entity;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "oak-domain",
|
||||
"version": "4.4.0",
|
||||
"version": "4.5.0",
|
||||
"author": {
|
||||
"name": "XuChang"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ export abstract class AsyncContext<ED extends EntityDict> implements Context {
|
|||
|
||||
// 此接口将字符串parse成对象再进行初始化
|
||||
// later表示允许延时状态,上下文要处理在时间维度上可能的异常(比如用户token已经注销等)
|
||||
abstract initialize(data: any, later?: boolean): Promise<void>;
|
||||
abstract initialize(data?: any, later?: boolean): Promise<void>;
|
||||
|
||||
abstract allowUserUpdate(): boolean;
|
||||
|
||||
|
|
|
|||
|
|
@ -566,10 +566,10 @@ export class RelationAuth<ED extends EntityDict & BaseEntityDict> {
|
|||
* @returns
|
||||
*/
|
||||
const makeCreateFilter = <T2 extends keyof ED>(entity: T2, operation: Omit<ED[T2]['CreateSingle'], 'id'>) => {
|
||||
const { data, filter } = operation;
|
||||
const { data, filter, bornAt } = operation;
|
||||
assert(!(data instanceof Array));
|
||||
if (data) {
|
||||
return translateCreateDataToFilter(this.schema, entity, data);
|
||||
return translateCreateDataToFilter(this.schema, entity, data, !!bornAt);
|
||||
}
|
||||
return filter;
|
||||
};
|
||||
|
|
@ -636,7 +636,7 @@ export class RelationAuth<ED extends EntityDict & BaseEntityDict> {
|
|||
assert(!(data instanceof Array));
|
||||
|
||||
for (const attr in data) {
|
||||
const rel = judgeRelation(this.schema, entity, attr);
|
||||
const rel = judgeRelation(this.schema, entity, attr, !!operation.bornAt);
|
||||
if (rel === 2 && !isModiUpdate) {
|
||||
assert(root === me && !hasParent, 'cascadeUpdate必须是树结构,避免森林');
|
||||
const mtoOperation = data[attr] as any;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export class TriggerExecutor<ED extends EntityDict & BaseEntityDict, Cxt extends
|
|||
private volatileEntities: Array<keyof ED>;
|
||||
|
||||
private logger: Logger;
|
||||
private contextBuilder: (cxtString?: string) => Promise<Cxt>;
|
||||
private contextBuilder: () => Cxt;
|
||||
private onVolatileTrigger: <T extends keyof ED>(
|
||||
entity: T,
|
||||
trigger: VolatileTrigger<ED, T, Cxt>,
|
||||
|
|
@ -48,7 +48,7 @@ export class TriggerExecutor<ED extends EntityDict & BaseEntityDict, Cxt extends
|
|||
) => Promise<void>;
|
||||
|
||||
constructor(
|
||||
contextBuilder: (cxtString?: string) => Promise<Cxt>,
|
||||
contextBuilder: () => Cxt,
|
||||
logger: Logger = console,
|
||||
onVolatileTrigger?: <T extends keyof ED>(
|
||||
entity: T,
|
||||
|
|
@ -64,15 +64,21 @@ export class TriggerExecutor<ED extends EntityDict & BaseEntityDict, Cxt extends
|
|||
this.volatileEntities = [];
|
||||
this.counter = 0;
|
||||
this.onVolatileTrigger = onVolatileTrigger || (async (entity, trigger, ids, cxtStr, option) => {
|
||||
const context = await this.contextBuilder(cxtStr);
|
||||
await context.begin();
|
||||
const context = this.contextBuilder();
|
||||
if (!context.getCurrentTxnId()) {
|
||||
await context.begin();
|
||||
}
|
||||
await context.initialize(JSON.parse(cxtStr));
|
||||
try {
|
||||
await this.execVolatileTrigger(entity, trigger.name, ids, context, option);
|
||||
await context.commit();
|
||||
}
|
||||
catch (err) {
|
||||
await context.rollback();
|
||||
this.logger.error('error on volatile trigger', entity, trigger.name, ids.join(','), err);
|
||||
if (!(err instanceof OakMakeSureByMySelfException)) {
|
||||
this.logger.error('error on volatile trigger', entity, trigger.name, ids.join(','), err);
|
||||
}
|
||||
// throw err;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -353,8 +359,8 @@ export class TriggerExecutor<ED extends EntityDict & BaseEntityDict, Cxt extends
|
|||
}
|
||||
}
|
||||
const number = (trigger as CreateTriggerInTxn<ED, T, Cxt>).fn({ operation: operation as ED[T]['Create'] }, context, option as OperateOption);
|
||||
if (number as number > 0) {
|
||||
this.logger.info(`触发器「${trigger.name}」成功触发了「${number}」行数据更改`);
|
||||
if (number as number > 0 && process.env.NODE_ENV === 'development') {
|
||||
this.logger.info(`前触发器「${trigger.name}」成功触发了「${number}」行数据更改`);
|
||||
}
|
||||
}
|
||||
assert(commitTriggers.length === 0, `前台不应有commitTrigger`);
|
||||
|
|
@ -376,8 +382,8 @@ export class TriggerExecutor<ED extends EntityDict & BaseEntityDict, Cxt extends
|
|||
}
|
||||
}
|
||||
const number = await (trigger as CreateTriggerInTxn<ED, T, Cxt>).fn({ operation: operation as ED[T]['Create'] }, context, option as OperateOption);
|
||||
if (number as number > 0) {
|
||||
this.logger.info(`触发器「${trigger.name}」成功触发了「${number}」行数据更改`);
|
||||
if (number as number > 0 && process.env.NODE_ENV === 'development') {
|
||||
this.logger.info(`前触发器「${trigger.name}」成功触发了「${number}」行数据更改`);
|
||||
}
|
||||
return execPreTrigger(idx + 1);
|
||||
};
|
||||
|
|
@ -489,8 +495,8 @@ export class TriggerExecutor<ED extends EntityDict & BaseEntityDict, Cxt extends
|
|||
operation: operation as ED[T]['Selection'],
|
||||
result: result!,
|
||||
}, context, option as SelectOption);
|
||||
if (number as number > 0) {
|
||||
this.logger.info(`触发器「${trigger.name}」成功触发了「${number}」行数据更改`);
|
||||
if (number as number > 0 && process.env.NODE_ENV === 'development') {
|
||||
this.logger.info(`后触发器「${trigger.name}」成功触发了「${number}」行数据更改`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -505,8 +511,8 @@ export class TriggerExecutor<ED extends EntityDict & BaseEntityDict, Cxt extends
|
|||
operation: operation as ED[T]['Selection'],
|
||||
result: result!,
|
||||
}, context, option as SelectOption);
|
||||
if (number as number > 0) {
|
||||
this.logger.info(`触发器「${trigger.name}」成功触发了「${number}」行数据更改`);
|
||||
if (number as number > 0 && process.env.NODE_ENV === 'development') {
|
||||
this.logger.info(`后触发器「${trigger.name}」成功触发了「${number}」行数据更改`);
|
||||
}
|
||||
return execPostTrigger(idx + 1);
|
||||
};
|
||||
|
|
@ -551,7 +557,7 @@ export class TriggerExecutor<ED extends EntityDict & BaseEntityDict, Cxt extends
|
|||
$lt: timestamp,
|
||||
}
|
||||
};
|
||||
const context = await this.contextBuilder();
|
||||
const context = this.contextBuilder();
|
||||
if (context.clusterInfo?.usingCluster) {
|
||||
const { instanceCount, instanceId } = context.clusterInfo!;
|
||||
filter.$$seq$$ = {
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ export function translateCheckerInAsyncContext<
|
|||
case 'row': {
|
||||
const { filter, errMsg, inconsistentRows } = checker;
|
||||
const fn = (async ({ operation }, context, option) => {
|
||||
const { filter: operationFilter, data, action } = operation;
|
||||
const { filter: operationFilter, data, action, bornAt } = operation;
|
||||
const filter2 = typeof filter === 'function' ? await filter(operation, context, option) : filter;
|
||||
if (['select', 'count', 'stat'].includes(action)) {
|
||||
operation.filter = combineFilters(entity, context.getSchema(), [operationFilter, filter2]);
|
||||
|
|
@ -102,11 +102,11 @@ export function translateCheckerInAsyncContext<
|
|||
assert(data);
|
||||
if (data instanceof Array) {
|
||||
for (const d of <ED[T]['CreateMulti']['data']>data) {
|
||||
await checkSingle(translateCreateDataToFilter(schema, entity, d))
|
||||
await checkSingle(translateCreateDataToFilter(schema, entity, d, !!bornAt))
|
||||
}
|
||||
}
|
||||
else {
|
||||
await checkSingle(translateCreateDataToFilter(schema, entity, <ED[T]['CreateSingle']['data']><unknown>data))
|
||||
await checkSingle(translateCreateDataToFilter(schema, entity, <ED[T]['CreateSingle']['data']><unknown>data, !!bornAt))
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -160,7 +160,7 @@ export function translateCheckerInSyncContext<
|
|||
case 'row': {
|
||||
const { filter, errMsg, entity } = checker;
|
||||
const fn = (operation: ED[T]['Operation'], context: Cxt, option: OperateOption | SelectOption) => {
|
||||
const { filter: operationFilter, data, action } = operation;
|
||||
const { filter: operationFilter, data, action, bornAt } = operation;
|
||||
const filter2 = typeof filter === 'function' ? filter(operation, context, option) : filter;
|
||||
let operationFilter2 = operationFilter;
|
||||
if (action === 'create') {
|
||||
|
|
@ -168,7 +168,7 @@ export function translateCheckerInSyncContext<
|
|||
// 前端的策略是,有data用data,无data用filter
|
||||
// 目前前端应该不可能制造出来createMultiple
|
||||
assert(!(data instanceof Array));
|
||||
operationFilter2 = translateCreateDataToFilter(schema, entity, data as ED[T]['CreateSingle']['data']);
|
||||
operationFilter2 = translateCreateDataToFilter(schema, entity, data as ED[T]['CreateSingle']['data'], !!bornAt);
|
||||
}
|
||||
}
|
||||
assert(!(filter2 instanceof Promise));
|
||||
|
|
|
|||
|
|
@ -10,10 +10,11 @@ export function translateCreateDataToFilter<ED extends EntityDict & BaseEntityDi
|
|||
schema: StorageSchema<ED>,
|
||||
entity: T,
|
||||
data: ED[T]['CreateSingle']['data'],
|
||||
allowUnrecoganized: boolean,
|
||||
) {
|
||||
const data2: ED[T]['Selection']['filter'] = {};
|
||||
for (const attr in data) {
|
||||
const rel = judgeRelation(schema, entity, attr);
|
||||
const rel = judgeRelation(schema, entity, attr, allowUnrecoganized);
|
||||
if (rel === 1) {
|
||||
// 只需要记住id和各种外键属性,不这样处理有些古怪的属性比如coordinate,其作为createdata和作为filter并不同构
|
||||
if (!['geometry', 'geography', 'st_geometry', 'st_point'].includes(schema[entity].attributes[attr as any]?.type!)) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue