Merge branch 'dev' of gitea.51mars.com:Oak-Team/oak-domain into dev
This commit is contained in:
commit
34018c09b3
|
|
@ -29,6 +29,12 @@ export declare abstract class AsyncContext<ED extends EntityDict> implements Con
|
|||
private resetEvents;
|
||||
on(event: 'commit' | 'rollback', callback: (records: OpRecord<ED>[], cxtStr: string) => Promise<void>): void;
|
||||
saveOpRecord<T extends keyof ED>(entity: T, operation: ED[T]['Operation']): void;
|
||||
/**
|
||||
* 查询某operation所处理的row ids
|
||||
* 如果该operation还未执行,可能返回空数组(不知道实际关联的row id);但是在after的trigger中,返回是准确的ids值(此时如果是空数组说明没有有关row id)
|
||||
* @param id
|
||||
*/
|
||||
getRowIdsOfOperation(operation: ED[keyof ED]['Operation']): string[];
|
||||
/**
|
||||
* 一个context中不应该有并发的事务,这里将事务串行化,使用的时候千万要注意不要自己等自己
|
||||
* @param options
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ exports.AsyncContext = void 0;
|
|||
const tslib_1 = require("tslib");
|
||||
const action_1 = require("../actions/action");
|
||||
const assert_1 = tslib_1.__importDefault(require("assert"));
|
||||
const filter_1 = require("./filter");
|
||||
/**
|
||||
* 服务器端执行的异步环境的底层抽象
|
||||
*/
|
||||
|
|
@ -75,7 +76,7 @@ class AsyncContext {
|
|||
id,
|
||||
a: 'c',
|
||||
e: entity,
|
||||
d: data
|
||||
d: data,
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
|
@ -100,6 +101,35 @@ class AsyncContext {
|
|||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 查询某operation所处理的row ids
|
||||
* 如果该operation还未执行,可能返回空数组(不知道实际关联的row id);但是在after的trigger中,返回是准确的ids值(此时如果是空数组说明没有有关row id)
|
||||
* @param id
|
||||
*/
|
||||
getRowIdsOfOperation(operation) {
|
||||
const { id, action, data, filter } = operation;
|
||||
if (action === 'create') {
|
||||
if (data instanceof Array) {
|
||||
return data.map(ele => ele.id);
|
||||
}
|
||||
return [data.id];
|
||||
}
|
||||
else if (filter) {
|
||||
const ids = (0, filter_1.getRelevantIds)(filter);
|
||||
if (ids.length > 0) {
|
||||
return ids;
|
||||
}
|
||||
}
|
||||
const oper = this.opRecords.find(ele => ele.id === id);
|
||||
if (oper) {
|
||||
const { a } = oper;
|
||||
(0, assert_1.default)(a !== 'create');
|
||||
const { f } = oper;
|
||||
(0, assert_1.default)(f && f?.id?.$in && f.id.$in instanceof Array);
|
||||
return f.id.$in;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
/**
|
||||
* 一个context中不应该有并发的事务,这里将事务串行化,使用的时候千万要注意不要自己等自己
|
||||
* @param options
|
||||
|
|
|
|||
|
|
@ -1217,6 +1217,7 @@ class CascadeStore extends RowStore_1.RowStore {
|
|||
};
|
||||
const rows = await this.selectAbjointRowAsync(entity, selection, context, {
|
||||
dontCollect: true,
|
||||
forUpdate: true,
|
||||
});
|
||||
ids.push(...(rows.map(ele => ele.id)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ function createUniqueCheckers(schema) {
|
|||
entity,
|
||||
action: 'create',
|
||||
type: 'logicalData',
|
||||
priority: types_1.CHECKER_MAX_PRIORITY,
|
||||
priority: types_1.CHECKER_MAX_PRIORITY, // 优先级要放在最低,所有前置的checker/trigger将数据完整之后再在这里检测
|
||||
checker: (operation, context) => {
|
||||
const { data } = operation;
|
||||
if (data instanceof Array) {
|
||||
|
|
@ -95,9 +95,9 @@ function createUniqueCheckers(schema) {
|
|||
}
|
||||
}, {
|
||||
entity,
|
||||
action: 'update',
|
||||
action: 'update', // 只检查update,其它状态转换的action应该不会涉及unique约束的属性
|
||||
type: 'logicalData',
|
||||
priority: types_1.CHECKER_MAX_PRIORITY,
|
||||
priority: types_1.CHECKER_MAX_PRIORITY, // 优先级要放在最低,所有前置的checker/trigger将数据完整之后再在这里检测
|
||||
checker: (operation, context) => {
|
||||
const { data, filter: operationFilter } = operation;
|
||||
if (data) {
|
||||
|
|
@ -227,7 +227,7 @@ function createActionTransformerCheckers(actionDefDict) {
|
|||
action: 'create',
|
||||
type: 'logical',
|
||||
entity,
|
||||
priority: 10,
|
||||
priority: 10, // 优先级要高,先于真正的data检查进行
|
||||
checker: (operation) => {
|
||||
const { data } = operation;
|
||||
if (data instanceof Array) {
|
||||
|
|
|
|||
|
|
@ -647,6 +647,7 @@ function judgeValueRelation(value1, value2, contained) {
|
|||
else if (r) {
|
||||
return false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// 互斥
|
||||
if (r) {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/// <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;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ declare const url: {
|
|||
revokeObjectURL(url: string): void;
|
||||
};
|
||||
declare const urlSearchParams: {
|
||||
new (init?: string | Record<string, string> | string[][] | URLSearchParams | undefined): URLSearchParams;
|
||||
new (init?: string | string[][] | Record<string, string> | URLSearchParams | undefined): URLSearchParams;
|
||||
prototype: URLSearchParams;
|
||||
};
|
||||
export { url, urlSearchParams };
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ declare const url: {
|
|||
revokeObjectURL(url: string): void;
|
||||
};
|
||||
declare const urlSearchParams: {
|
||||
new (init?: string | Record<string, string> | string[][] | URLSearchParams | undefined): URLSearchParams;
|
||||
new (init?: string | string[][] | Record<string, string> | URLSearchParams | undefined): URLSearchParams;
|
||||
prototype: URLSearchParams;
|
||||
};
|
||||
export { url, urlSearchParams };
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "oak-domain",
|
||||
"version": "5.0.16",
|
||||
"version": "5.0.17",
|
||||
"author": {
|
||||
"name": "XuChang"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
|
||||
import { EntityDict, RowStore, OperateOption, OperationResult, SelectOption, Context, TxnOption, OpRecord, AggregationResult, ClusterInfo } from "../types";
|
||||
import { EntityDict, RowStore, OperateOption, OperationResult, SelectOption, Context, TxnOption, OpRecord, AggregationResult, ClusterInfo, CreateOpResult, UpdateOpResult } from "../types";
|
||||
import { readOnlyActions } from '../actions/action';
|
||||
import assert from "assert";
|
||||
import { IncomingHttpHeaders } from "http";
|
||||
import { getRelevantIds } from "./filter";
|
||||
|
||||
/**
|
||||
* 服务器端执行的异步环境的底层抽象
|
||||
|
|
@ -91,7 +92,7 @@ export abstract class AsyncContext<ED extends EntityDict> implements Context {
|
|||
id,
|
||||
a: 'c',
|
||||
e: entity,
|
||||
d: data as ED[T]['OpSchema']
|
||||
d: data as ED[T]['OpSchema'],
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
|
@ -117,6 +118,39 @@ export abstract class AsyncContext<ED extends EntityDict> implements Context {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询某operation所处理的row ids
|
||||
* 如果该operation还未执行,可能返回空数组(不知道实际关联的row id);但是在after的trigger中,返回是准确的ids值(此时如果是空数组说明没有有关row id)
|
||||
* @param id
|
||||
*/
|
||||
getRowIdsOfOperation(operation: ED[keyof ED]['Operation']): string[] {
|
||||
const { id, action, data, filter } = operation;
|
||||
if (action === 'create') {
|
||||
if (data instanceof Array) {
|
||||
return data.map(ele => ele.id);
|
||||
}
|
||||
return [data.id!];
|
||||
}
|
||||
else if (filter) {
|
||||
const ids = getRelevantIds(filter);
|
||||
if (ids.length > 0 ) {
|
||||
return ids;
|
||||
}
|
||||
}
|
||||
|
||||
const oper = this.opRecords.find(
|
||||
ele => (ele as CreateOpResult<ED, keyof ED>).id === id
|
||||
);
|
||||
if (oper) {
|
||||
const { a } = oper;
|
||||
assert (a !== 'create');
|
||||
const { f } = oper as UpdateOpResult<ED, keyof ED>;
|
||||
assert(f && f?.id?.$in && f!.id!.$in! instanceof Array);
|
||||
return f!.id!.$in!;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 一个context中不应该有并发的事务,这里将事务串行化,使用的时候千万要注意不要自己等自己
|
||||
* @param options
|
||||
|
|
|
|||
|
|
@ -1490,6 +1490,7 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
|||
};
|
||||
const rows = await this.selectAbjointRowAsync(entity, selection, context, {
|
||||
dontCollect: true,
|
||||
forUpdate: true,
|
||||
});
|
||||
ids.push(...(rows.map(ele => ele.id! as string)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ export function translateCreateDataToFilter<ED extends EntityDict & BaseEntityDi
|
|||
if (rel === 1) {
|
||||
// 只需要记住id和各种外键属性,不这样处理有些古怪的属性比如coordinate,其作为createdata和作为filter并不同构
|
||||
if (![
|
||||
'geometry',
|
||||
'geography',
|
||||
'st_geometry',
|
||||
'geometry',
|
||||
'geography',
|
||||
'st_geometry',
|
||||
'st_point',
|
||||
'function',
|
||||
'sequence',
|
||||
|
|
@ -744,6 +744,7 @@ export function judgeValueRelation(value1: any, value2: any, contained: boolean)
|
|||
else if (r) {
|
||||
return false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// 互斥
|
||||
if (r) {
|
||||
|
|
@ -1856,7 +1857,7 @@ export function checkFilterContains<ED extends EntityDict & BaseEntityDict, T ex
|
|||
filter?: ED[T]['Selection']['filter'],
|
||||
dataCompare?: true,
|
||||
warningOnDataCompare?: true): boolean | Promise<boolean> {
|
||||
|
||||
|
||||
assert(filter);
|
||||
const schema = context.getSchema();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue