midway-fatcms 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +635 -352
- package/dist/controller/manage/CrudStandardDesignApi.d.ts +0 -2
- package/dist/controller/manage/CrudStandardDesignApi.js +11 -85
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/libs/crud-pro/CrudPro.d.ts +9 -1
- package/dist/libs/crud-pro/CrudPro.js +15 -0
- package/dist/libs/crud-pro/README.md +809 -0
- package/dist/libs/crud-pro/README_FUNC.md +193 -0
- package/dist/libs/crud-pro/exceptions.d.ts +2 -0
- package/dist/libs/crud-pro/exceptions.js +2 -0
- package/dist/libs/crud-pro/interfaces.d.ts +34 -1
- package/dist/libs/crud-pro/models/ExecuteContext.d.ts +3 -3
- package/dist/libs/crud-pro/models/ExecuteContext.js +2 -0
- package/dist/libs/crud-pro/models/RequestModel.d.ts +41 -1
- package/dist/libs/crud-pro/models/RequestModel.js +103 -39
- package/dist/libs/crud-pro/models/ResModel.d.ts +6 -4
- package/dist/libs/crud-pro/models/ServiceHub.d.ts +1 -0
- package/dist/libs/crud-pro/models/keys.d.ts +6 -1
- package/dist/libs/crud-pro/models/keys.js +5 -0
- package/dist/libs/crud-pro/services/CrudProDataTypeConvertService.d.ts +52 -0
- package/dist/libs/crud-pro/services/CrudProDataTypeConvertService.js +158 -0
- package/dist/libs/crud-pro/services/CrudProExecuteSqlService.js +20 -1
- package/dist/libs/crud-pro/services/CrudProFieldValidateService.d.ts +7 -0
- package/dist/libs/crud-pro/services/CrudProFieldValidateService.js +32 -0
- package/dist/libs/crud-pro/services/CrudProGenSqlService.d.ts +13 -0
- package/dist/libs/crud-pro/services/CrudProGenSqlService.js +44 -7
- package/dist/libs/crud-pro/services/CrudProOriginToExecuteSql.d.ts +43 -0
- package/dist/libs/crud-pro/services/CrudProOriginToExecuteSql.js +132 -1
- package/dist/libs/crud-pro/services/CrudProTableMetaService.d.ts +15 -1
- package/dist/libs/crud-pro/services/CrudProTableMetaService.js +107 -0
- package/dist/libs/crud-pro/services/CurdProServiceHub.d.ts +5 -1
- package/dist/libs/crud-pro/services/CurdProServiceHub.js +11 -0
- package/dist/libs/crud-pro/utils/DateTimeUtils.d.ts +1 -0
- package/dist/libs/crud-pro/utils/DateTimeUtils.js +3 -0
- package/dist/libs/crud-pro/utils/MixinUtils.d.ts +32 -0
- package/dist/libs/crud-pro/utils/MixinUtils.js +85 -1
- package/dist/libs/crud-pro/utils/ValidateUtils.js +1 -1
- package/dist/libs/crud-sharding/ROUTING_LOGIC.md +944 -0
- package/dist/libs/crud-sharding/ShardingConfig.d.ts +218 -0
- package/dist/libs/crud-sharding/ShardingConfig.js +32 -0
- package/dist/libs/crud-sharding/ShardingCountCache.d.ts +69 -0
- package/dist/libs/crud-sharding/ShardingCountCache.js +160 -0
- package/dist/libs/crud-sharding/ShardingCrudPro.d.ts +363 -0
- package/dist/libs/crud-sharding/ShardingCrudPro.js +699 -0
- package/dist/libs/crud-sharding/ShardingMerger.d.ts +130 -0
- package/dist/libs/crud-sharding/ShardingMerger.js +280 -0
- package/dist/libs/crud-sharding/ShardingRouter.d.ts +69 -0
- package/dist/libs/crud-sharding/ShardingRouter.js +377 -0
- package/dist/libs/crud-sharding/ShardingTableCreator.d.ts +146 -0
- package/dist/libs/crud-sharding/ShardingTableCreator.js +805 -0
- package/dist/libs/crud-sharding/ShardingUtils.d.ts +38 -0
- package/dist/libs/crud-sharding/ShardingUtils.js +77 -0
- package/dist/libs/crud-sharding/index.d.ts +45 -0
- package/dist/libs/crud-sharding/index.js +55 -0
- package/dist/models/StandardColumns.d.ts +71 -0
- package/dist/models/StandardColumns.js +28 -0
- package/dist/service/SysAppService.js +2 -2
- package/dist/service/SysConfigService.js +1 -1
- package/dist/service/SysDictDataService.js +2 -2
- package/dist/service/SysMenuService.js +1 -1
- package/dist/service/UserAccountService.d.ts +1 -1
- package/dist/service/crudstd/CrudStdService.d.ts +0 -1
- package/dist/service/crudstd/CrudStdService.js +0 -27
- package/dist/service/curd/CrudProQuick.d.ts +134 -4
- package/dist/service/curd/CrudProQuick.js +155 -3
- package/dist/service/curd/CurdMixService.d.ts +2 -1
- package/dist/service/curd/CurdMixService.js +5 -1
- package/dist/service/curd/CurdProService.d.ts +44 -2
- package/dist/service/curd/CurdProService.js +53 -1
- package/dist/service/curd/README.md +1001 -0
- package/dist/service/curd/fixSoftDelete.d.ts +14 -0
- package/dist/service/curd/fixSoftDelete.js +29 -11
- package/dist/service/flow/FlowConfigService.js +1 -1
- package/dist/service/flow/FlowInstanceCrudService.js +1 -1
- package/package.json +3 -1
- package/src/controller/gateway/AsyncTaskController.ts +1 -1
- package/src/controller/manage/CrudStandardDesignApi.ts +16 -100
- package/src/index.ts +3 -0
- package/src/libs/crud-pro/CrudPro.ts +19 -1
- package/src/libs/crud-pro/README.md +809 -0
- package/src/libs/crud-pro/README_FUNC.md +193 -0
- package/src/libs/crud-pro/exceptions.ts +2 -0
- package/src/libs/crud-pro/interfaces.ts +38 -1
- package/src/libs/crud-pro/models/ExecuteContext.ts +6 -3
- package/src/libs/crud-pro/models/RequestModel.ts +108 -44
- package/src/libs/crud-pro/models/ResModel.ts +10 -4
- package/src/libs/crud-pro/models/ServiceHub.ts +2 -0
- package/src/libs/crud-pro/models/keys.ts +5 -0
- package/src/libs/crud-pro/services/CrudProDataTypeConvertService.ts +171 -0
- package/src/libs/crud-pro/services/CrudProExecuteSqlService.ts +24 -1
- package/src/libs/crud-pro/services/CrudProFieldValidateService.ts +53 -1
- package/src/libs/crud-pro/services/CrudProGenSqlService.ts +51 -7
- package/src/libs/crud-pro/services/CrudProOriginToExecuteSql.ts +159 -2
- package/src/libs/crud-pro/services/CrudProTableMetaService.ts +139 -1
- package/src/libs/crud-pro/services/CurdProServiceHub.ts +16 -1
- package/src/libs/crud-pro/utils/DateTimeUtils.ts +3 -0
- package/src/libs/crud-pro/utils/MixinUtils.ts +97 -1
- package/src/libs/crud-pro/utils/ValidateUtils.ts +1 -1
- package/src/libs/crud-sharding/ROUTING_LOGIC.md +944 -0
- package/src/libs/crud-sharding/ShardingConfig.ts +240 -0
- package/src/libs/crud-sharding/ShardingCountCache.ts +200 -0
- package/src/libs/crud-sharding/ShardingCrudPro.ts +856 -0
- package/src/libs/crud-sharding/ShardingMerger.ts +382 -0
- package/src/libs/crud-sharding/ShardingRouter.ts +512 -0
- package/src/libs/crud-sharding/ShardingTableCreator.ts +1007 -0
- package/src/libs/crud-sharding/ShardingUtils.ts +84 -0
- package/src/libs/crud-sharding/index.ts +64 -0
- package/src/models/StandardColumns.ts +76 -0
- package/src/service/FileCenterService.ts +1 -1
- package/src/service/SysAppService.ts +2 -2
- package/src/service/SysConfigService.ts +1 -1
- package/src/service/SysDictDataService.ts +2 -2
- package/src/service/SysMenuService.ts +2 -2
- package/src/service/WorkbenchService.ts +1 -1
- package/src/service/anyapi/AnyApiService.ts +1 -1
- package/src/service/asyncTask/AsyncTaskRunnerService.ts +1 -1
- package/src/service/crudstd/CrudStdService.ts +0 -32
- package/src/service/curd/CrudProQuick.ts +164 -5
- package/src/service/curd/CurdMixService.ts +7 -2
- package/src/service/curd/CurdProService.ts +62 -3
- package/src/service/curd/README.md +1001 -0
- package/src/service/curd/fixCfgModel.ts +1 -2
- package/src/service/curd/fixSoftDelete.ts +38 -16
- package/src/service/flow/FlowConfigService.ts +1 -1
- package/src/service/flow/FlowInstanceCrudService.ts +1 -1
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# CrudPro 内置函数参考
|
|
2
|
+
|
|
3
|
+
CrudPro 的 `IFuncCfgModel` 支持 `functionName` 方式调用内置函数。内置函数由四个工具类注册:`DateTimeUtils`、`CompareUtils`、`MixinUtils`、`TypeUtils`。
|
|
4
|
+
|
|
5
|
+
> 源码位置:`src/libs/crud-pro/services/CrudProServiceBase.ts` → `createBuildInExecuteFuncMap()`
|
|
6
|
+
|
|
7
|
+
## 调用方式
|
|
8
|
+
|
|
9
|
+
`functionName` 是 `IFuncCfgModel` 的属性之一,可在 `updateCfg`、`validateCfg`、`executeWhen`、`validate` 等配置中使用。
|
|
10
|
+
|
|
11
|
+
### 无参调用
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
'data.created_at': { functionName: 'getCurrentTimeString' }
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### 带参调用
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
'data.order_date': { functionName: 'getCurrentDateFormat', functionParams: ['YYYYMMDD'] }
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`functionParams` 中的每个元素可以是基础类型(string / number / boolean),也可以嵌套 `IFuncCfgModel` 对象:
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
{
|
|
27
|
+
functionName: 'eq',
|
|
28
|
+
functionParams: [
|
|
29
|
+
{ contextAsBool: 'res.is_exist' },
|
|
30
|
+
{ constBool: false }
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## DateTimeUtils — 日期时间
|
|
36
|
+
|
|
37
|
+
| 函数名 | 参数 | 返回值 | 说明 |
|
|
38
|
+
|--------|------|--------|------|
|
|
39
|
+
| `getCurrentTimeStampMs` | 无 | `number` | 当前时间戳(毫秒) |
|
|
40
|
+
| `getCurrentTimeStampSecond` | 无 | `number` | 当前时间戳(秒) |
|
|
41
|
+
| `getCurrentTimeString` | 无 | `string` | 当前时间,格式 `YYYY-MM-DD HH:mm:ss` |
|
|
42
|
+
| `getCurrentDateFormat` | `format: string` | `string` | 按指定格式返回当前时间 |
|
|
43
|
+
| `getYesterdayDateFormat` | `format: string` | `string` | 按指定格式返回昨天时间 |
|
|
44
|
+
|
|
45
|
+
**示例:**
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
updateCfg: {
|
|
49
|
+
'data.created_at': { functionName: 'getCurrentTimeString' },
|
|
50
|
+
'data.created_ts': { functionName: 'getCurrentTimeStampMs' },
|
|
51
|
+
'data.order_date': { functionName: 'getCurrentDateFormat', functionParams: ['YYYYMMDD'] },
|
|
52
|
+
'data.yesterday': { functionName: 'getYesterdayDateFormat', functionParams: ['YYYY-MM-DD'] },
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## CompareUtils — 比较运算
|
|
57
|
+
|
|
58
|
+
| 函数名 | 参数 | 返回值 | 说明 |
|
|
59
|
+
|--------|------|--------|------|
|
|
60
|
+
| `eq` | `a: any, b: any` | `boolean` | 相等比较(`==`,兼容类型转换) |
|
|
61
|
+
| `ne` | `a: any, b: any` | `boolean` | 不相等 |
|
|
62
|
+
| `gt` | `a: any, b: any` | `boolean` | 大于 |
|
|
63
|
+
| `gte` | `a: any, b: any` | `boolean` | 大于等于 |
|
|
64
|
+
| `lt` | `a: any, b: any` | `boolean` | 小于 |
|
|
65
|
+
| `lte` | `a: any, b: any` | `boolean` | 小于等于 |
|
|
66
|
+
|
|
67
|
+
**示例:**
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// executeWhen:仅当 is_exist 为 false 时执行插入
|
|
71
|
+
executeWhen: {
|
|
72
|
+
functionName: 'eq',
|
|
73
|
+
functionParams: [{ contextAsBool: 'res.is_exist' }, { constBool: false }]
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// validate:确保数量大于 0
|
|
77
|
+
validate: {
|
|
78
|
+
functionName: 'gt',
|
|
79
|
+
functionParams: [{ context: '$current' }, { constNumber: 0 }],
|
|
80
|
+
message: '数量必须大于0'
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## MixinUtils — 通用工具
|
|
85
|
+
|
|
86
|
+
| 函数名 | 参数 | 返回值 | 说明 |
|
|
87
|
+
|--------|------|--------|------|
|
|
88
|
+
| `isNil` | `obj: any` | `boolean` | 是否为 null 或 undefined |
|
|
89
|
+
| `isNotNil` | `obj: any` | `boolean` | 不为 null 且不为 undefined |
|
|
90
|
+
| `isEmpty` | `obj: any` | `boolean` | 是否为空(null / undefined / 空字符串 / 空数组 / 空对象) |
|
|
91
|
+
| `isNotEmpty` | `obj: any` | `boolean` | 是否非空 |
|
|
92
|
+
| `equals` | `obj1: any, obj2: any` | `boolean` | 严格相等(`===`) |
|
|
93
|
+
| `equalsIgnoreCase` | `str1: string, str2: string` | `boolean` | 忽略大小写比较字符串 |
|
|
94
|
+
| `startsWith` | `str1: string, str2: string` | `boolean` | 字符串前缀判断 |
|
|
95
|
+
| `isValidFieldName` | `s: string` | `boolean` | 合法字段名(字母开头,仅含字母/数字/下划线) |
|
|
96
|
+
| `selectNotEmpty` | `a: any, b: any` | `any` | 返回第一个非空值 |
|
|
97
|
+
| `hasAny` | `a: string[], b: string[]` | `boolean` | 集合 A 是否包含集合 B 中的任意元素 |
|
|
98
|
+
| `parseValueByType` | `value: any, targetType: string` | `any` | 按类型转换值(string / number / boolean / array / JSONObject) |
|
|
99
|
+
| `sleepMs` | `ms: number` | `Promise` | 延时等待 |
|
|
100
|
+
| `uuid` | 无 | `string` | 生成 UUID v4(优先 `crypto.getRandomValues`,降级 `Math.random`) |
|
|
101
|
+
| `generateSnowflakeId` | `machineId?: number` | `string` | 生成雪花ID(64位整数字符串) |
|
|
102
|
+
|
|
103
|
+
**uuid 和雪花ID 示例:**
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
updateCfg: {
|
|
107
|
+
// UUID v4:适合需要标准唯一标识的场景
|
|
108
|
+
'data.id': { functionName: 'uuid' },
|
|
109
|
+
|
|
110
|
+
// 雪花ID:适合需要趋势递增、时间有序的场景
|
|
111
|
+
'data.order_id': { functionName: 'generateSnowflakeId' },
|
|
112
|
+
|
|
113
|
+
// 雪花ID:指定机器ID(0-1023),多实例部署时区分
|
|
114
|
+
'data.trace_id': { functionName: 'generateSnowflakeId', functionParams: [1] },
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
> **雪花ID machineId 获取优先级**:函数参数 > 环境变量 `SNOWFLAKE_MACHINE_ID` > `process.pid` 低10位。多实例部署时建议设置环境变量 `SNOWFLAKE_MACHINE_ID` 为 0-1023 的唯一值。
|
|
119
|
+
|
|
120
|
+
## TypeUtils — 类型判断
|
|
121
|
+
|
|
122
|
+
| 函数名 | 参数 | 返回值 | 说明 |
|
|
123
|
+
|--------|------|--------|------|
|
|
124
|
+
| `isBasicType` | `value: any` | `boolean` | 基础类型(boolean / string / number / null) |
|
|
125
|
+
| `isBoolean` | `value: any` | `boolean` | 布尔值 |
|
|
126
|
+
| `isString` | `value: any` | `boolean` | 字符串 |
|
|
127
|
+
| `isInteger` | `value: any` | `boolean` | 整数 |
|
|
128
|
+
| `isNumber` | `value: any` | `boolean` | 数字 |
|
|
129
|
+
| `isNumeric` | `value: any` | `boolean` | 数字或可转换数字的字符串 |
|
|
130
|
+
| `isValidName` | `value: any` | `boolean` | 合法命名(字母开头,字母/数字/下划线) |
|
|
131
|
+
| `isChinesePhone` | `value: string` | `boolean` | 中文手机号 |
|
|
132
|
+
| `isEmailStrValid` | `value: string` | `boolean` | 合法邮箱地址 |
|
|
133
|
+
| `pickNumber` | `s: string` | `number \| null` | 从字符串中提取数字部分 |
|
|
134
|
+
|
|
135
|
+
## 自定义函数扩展
|
|
136
|
+
|
|
137
|
+
除内置函数外,可通过覆写 `IExecuteContextFunc.getFunctionMap()` 注册自定义函数。
|
|
138
|
+
|
|
139
|
+
函数查找顺序:`getFunctionMap()` → `buildInExecuteFuncMap`(内置函数),自定义函数优先级更高,可覆盖内置函数。
|
|
140
|
+
|
|
141
|
+
### 注册方式
|
|
142
|
+
|
|
143
|
+
继承 `BaseExecuteContextFunc`,覆写 `getFunctionMap()` 方法返回函数映射表:
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
import { BaseExecuteContextFunc } from './libs/crud-pro/models/ExecuteContextFunc';
|
|
147
|
+
|
|
148
|
+
class MyContextFunc extends BaseExecuteContextFunc {
|
|
149
|
+
|
|
150
|
+
// 覆写此方法,返回自定义函数映射表
|
|
151
|
+
getFunctionMap(): any {
|
|
152
|
+
return {
|
|
153
|
+
// 无参函数
|
|
154
|
+
generateOrderNo: (prefix: string) => {
|
|
155
|
+
return prefix + Date.now().toString(36).toUpperCase();
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
// 带参函数:参数来自 functionParams 配置
|
|
159
|
+
formatAmount: (amount: number, currency: string) => {
|
|
160
|
+
return currency + ' ' + amount.toFixed(2);
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
// 可访问 FuncContext 的函数(通过 this 关键字)
|
|
164
|
+
getVisitorName: function(this: any) {
|
|
165
|
+
return this.reqModel?.visitor?.nickName || 'anonymous';
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// 创建 CrudPro 实例时注入
|
|
172
|
+
const crudPro = new CrudPro();
|
|
173
|
+
crudPro.contextFunc = new MyContextFunc(/* 构造参数 */);
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### 在配置中使用
|
|
177
|
+
|
|
178
|
+
注册后即可在 `updateCfg`、`validateCfg`、`functionCfg` 等场景中通过 `functionName` 调用:
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
const cfgJson: IRequestCfgModel = {
|
|
182
|
+
method: 'order.create',
|
|
183
|
+
sqlSimpleName: KeysOfSimpleSQL.SIMPLE_INSERT,
|
|
184
|
+
updateCfg: {
|
|
185
|
+
'data.order_no': { functionName: 'generateOrderNo', functionParams: ['PRE'] },
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
> **注意**:`functionParams` 中配置的参数会按顺序传入函数。如果函数需要访问 `FuncContext`(如 `reqModel`、`resModel`、`currentValue`),
|
|
191
|
+
> 需使用普通 `function`(非箭头函数)并通过 `this` 访问,框架会以 `func.apply(funcContext, params)` 方式调用。
|
|
192
|
+
|
|
193
|
+
> **注意**:`generateOrderNo` 等并非内置函数,需通过 `contextFunc` 扩展注册后才可使用,否则运行时抛出 `RUN_FUNCTION_NOT_FOUND` 异常。
|
|
@@ -46,6 +46,7 @@ export declare enum Exceptions {
|
|
|
46
46
|
CFG_UNIQUE_COLUMN_COUNT_MUST_ONE = "CFG_UNIQUE_COLUMN_COUNT_MUST_ONE",
|
|
47
47
|
CFG_ORDER_BY_TYPE_ERROR = "CFG_ORDER_BY_TYPE_ERROR",
|
|
48
48
|
CFG_ERROR_POSTGRES_COLUMN_NAME_INVALID = "CFG_ERROR_POSTGRES_COLUMN_NAME_INVALID",
|
|
49
|
+
CFG_INVALID_DATA_TYPE = "CFG_INVALID_DATA_TYPE",
|
|
49
50
|
/**
|
|
50
51
|
* 数据传错
|
|
51
52
|
*/
|
|
@@ -54,6 +55,7 @@ export declare enum Exceptions {
|
|
|
54
55
|
DATA_GET_DATA_EMPTY_ON_UPDATE = "DATA_GET_DATA_EMPTY_ON_UPDATE",
|
|
55
56
|
DATA_GET_DATA_EMPTY_ON_INSERT_KEYS = "DATA_GET_DATA_EMPTY_ON_INSERT_KEYS",
|
|
56
57
|
DATA_GET_DATA_EMPTY_ON_INSERT_VALUES = "DATA_GET_DATA_EMPTY_ON_INSERT_VALUES",
|
|
58
|
+
BATCH_INSERT_KEYS_MISMATCH = "BATCH_INSERT_KEYS_MISMATCH",
|
|
57
59
|
/**
|
|
58
60
|
* 请求的Method字段为空
|
|
59
61
|
*/
|
|
@@ -50,6 +50,7 @@ var Exceptions;
|
|
|
50
50
|
Exceptions["CFG_UNIQUE_COLUMN_COUNT_MUST_ONE"] = "CFG_UNIQUE_COLUMN_COUNT_MUST_ONE";
|
|
51
51
|
Exceptions["CFG_ORDER_BY_TYPE_ERROR"] = "CFG_ORDER_BY_TYPE_ERROR";
|
|
52
52
|
Exceptions["CFG_ERROR_POSTGRES_COLUMN_NAME_INVALID"] = "CFG_ERROR_POSTGRES_COLUMN_NAME_INVALID";
|
|
53
|
+
Exceptions["CFG_INVALID_DATA_TYPE"] = "CFG_INVALID_DATA_TYPE";
|
|
53
54
|
/**
|
|
54
55
|
* 数据传错
|
|
55
56
|
*/
|
|
@@ -58,6 +59,7 @@ var Exceptions;
|
|
|
58
59
|
Exceptions["DATA_GET_DATA_EMPTY_ON_UPDATE"] = "DATA_GET_DATA_EMPTY_ON_UPDATE";
|
|
59
60
|
Exceptions["DATA_GET_DATA_EMPTY_ON_INSERT_KEYS"] = "DATA_GET_DATA_EMPTY_ON_INSERT_KEYS";
|
|
60
61
|
Exceptions["DATA_GET_DATA_EMPTY_ON_INSERT_VALUES"] = "DATA_GET_DATA_EMPTY_ON_INSERT_VALUES";
|
|
62
|
+
Exceptions["BATCH_INSERT_KEYS_MISMATCH"] = "BATCH_INSERT_KEYS_MISMATCH";
|
|
61
63
|
/**
|
|
62
64
|
* 请求的Method字段为空
|
|
63
65
|
*/
|
|
@@ -46,7 +46,7 @@ export interface IRequestModel {
|
|
|
46
46
|
method?: string;
|
|
47
47
|
columns?: string | string[];
|
|
48
48
|
condition?: Record<string, any>;
|
|
49
|
-
data?: Record<string, any
|
|
49
|
+
data?: Record<string, any> | Record<string, any>[];
|
|
50
50
|
orderBy?: string | IOrderByItem[];
|
|
51
51
|
limit?: number;
|
|
52
52
|
offset?: number;
|
|
@@ -156,6 +156,7 @@ export interface IRequestCfgModel extends IBaseCfgModel {
|
|
|
156
156
|
transactionIsolation?: number;
|
|
157
157
|
sqlSimpleName?: KeysOfSimpleSQL;
|
|
158
158
|
sqlCfgList?: ISqlCfgModel[];
|
|
159
|
+
uniqueColumn?: string[];
|
|
159
160
|
updateCfg?: Record<string, IFuncCfgModel>;
|
|
160
161
|
allowCfg?: Record<string, string[]>;
|
|
161
162
|
rejectCfg?: Record<string, string[]>;
|
|
@@ -192,4 +193,36 @@ export interface ITableMetaQuery {
|
|
|
192
193
|
sqlDbType: SqlDbType;
|
|
193
194
|
sqlSchema?: string;
|
|
194
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* 表名列表查询参数
|
|
198
|
+
*/
|
|
199
|
+
export interface ITableNamesQuery {
|
|
200
|
+
sqlDatabase: string;
|
|
201
|
+
sqlDbType: SqlDbType;
|
|
202
|
+
sqlSchema?: string;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* 表名查询缓存选项
|
|
206
|
+
*/
|
|
207
|
+
export interface ITableNamesOptions {
|
|
208
|
+
/** 是否跳过缓存,直接查询数据库 */
|
|
209
|
+
skipCache?: boolean;
|
|
210
|
+
/** 查询后是否更新缓存 */
|
|
211
|
+
refreshCache?: boolean;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* 表信息项(包含表名和类型)
|
|
215
|
+
*/
|
|
216
|
+
export interface ITableInfo {
|
|
217
|
+
name: string;
|
|
218
|
+
tableType: string;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* 表信息查询结果
|
|
222
|
+
*/
|
|
223
|
+
export interface ITableListResult {
|
|
224
|
+
tables: ITableInfo[];
|
|
225
|
+
tableNames: string[];
|
|
226
|
+
viewNames: string[];
|
|
227
|
+
}
|
|
195
228
|
export {};
|
|
@@ -4,7 +4,7 @@ import { SqlCfgModel } from './SqlCfgModel';
|
|
|
4
4
|
import { Transaction } from './Transaction';
|
|
5
5
|
import { ColumnRelation, ICrudProCfg, ILogger, IVisitor } from '../interfaces';
|
|
6
6
|
import { IExecuteContextFunc } from './ExecuteContextFunc';
|
|
7
|
-
import { ResModelFlexible, ResModelPageQuery } from './ResModel';
|
|
7
|
+
import { ResModelFlexible, ResModelPageQuery, ResModelRowEntity } from './ResModel';
|
|
8
8
|
declare class ExecuteContext {
|
|
9
9
|
private transaction;
|
|
10
10
|
private logger;
|
|
@@ -26,8 +26,8 @@ declare class ExecuteContext {
|
|
|
26
26
|
getReqModel(): RequestModel;
|
|
27
27
|
setReqModel(reqModel: RequestModel): void;
|
|
28
28
|
getResModel(): ResModelFlexible;
|
|
29
|
-
getOneObj():
|
|
30
|
-
getResRows():
|
|
29
|
+
getOneObj(): ResModelRowEntity;
|
|
30
|
+
getResRows(): ResModelRowEntity[];
|
|
31
31
|
setResModelItem(resName: string, data: any): void;
|
|
32
32
|
getResModelItem(resName: string): any;
|
|
33
33
|
getResModelForQueryPage(): ResModelPageQuery;
|
|
@@ -4,18 +4,58 @@ declare class RequestModel {
|
|
|
4
4
|
method: string;
|
|
5
5
|
columns?: string[];
|
|
6
6
|
condition?: Record<string, any>;
|
|
7
|
-
data?: Record<string, any
|
|
7
|
+
data?: Record<string, any> | Record<string, any>[];
|
|
8
8
|
limit: number;
|
|
9
9
|
offset: number;
|
|
10
10
|
orderBys?: IOrderByItem[];
|
|
11
11
|
constructor(req: IRequestModel, visitor: IVisitor);
|
|
12
|
+
/**
|
|
13
|
+
* 解析 orderBy 参数为 IOrderByItem 数组
|
|
14
|
+
*
|
|
15
|
+
* 支持的格式:
|
|
16
|
+
* 1. 字符串格式(逗号分隔多个字段):
|
|
17
|
+
* - 标准 SQL 格式:'created_at DESC, amount ASC'
|
|
18
|
+
* - 简写 +/- 格式:'created_at-, amount+'('-' 表示 DESC,'+' 或省略表示 ASC)
|
|
19
|
+
* - 默认升序:'order_id'(无后缀时默认为 ASC)
|
|
20
|
+
*
|
|
21
|
+
* 2. 数组格式:
|
|
22
|
+
* - 纯对象数组:[{ fieldName: 'created_at', orderType: 'desc' }]
|
|
23
|
+
* - 混合数组1(字符串+对象):['order_id', { fieldName: 'amount', orderType: 'asc' }]
|
|
24
|
+
* - 混合数组2(字符串+对象):['order_id+', { fieldName: 'amount', orderType: 'asc' }]
|
|
25
|
+
* - 混合数组3(字符串+对象):['order_id DESC', { fieldName: 'amount', orderType: 'asc' }]
|
|
26
|
+
* 注:数组中的字符串元素支持标准 SQL 格式和简写格式,与字符串参数格式一致。
|
|
27
|
+
*
|
|
28
|
+
* SQL 注入防护:
|
|
29
|
+
* - 所有字段名必须通过 MixinUtils.isValidFieldName() 校验
|
|
30
|
+
* - 只允许 ASC/DESC 作为排序方向
|
|
31
|
+
*
|
|
32
|
+
* @param orderByStr 排序参数,可以是字符串或数组
|
|
33
|
+
* @returns IOrderByItem[] 解析后的排序项数组
|
|
34
|
+
*/
|
|
12
35
|
private parseOrderBys;
|
|
36
|
+
/**
|
|
37
|
+
* 解析单个排序项(数组元素)
|
|
38
|
+
*/
|
|
39
|
+
private parseOrderByItem;
|
|
40
|
+
/**
|
|
41
|
+
* 解析字符串格式的排序项(支持标准 SQL 和简写格式)
|
|
42
|
+
*/
|
|
43
|
+
private parseOrderByString;
|
|
44
|
+
/**
|
|
45
|
+
* SQL 注入防护:校验字段名格式
|
|
46
|
+
*/
|
|
47
|
+
private validateFieldName;
|
|
13
48
|
private parseOffsetList;
|
|
14
49
|
/**
|
|
15
50
|
* 获取对象数据类型
|
|
16
51
|
* @param attrName
|
|
17
52
|
*/
|
|
18
53
|
getCondOrDataJsonObject(attrName: string): any;
|
|
54
|
+
/**
|
|
55
|
+
* 获取数组类型的数据(用于批量插入)
|
|
56
|
+
* @param attrName
|
|
57
|
+
*/
|
|
58
|
+
getCondOrDataAsArray(attrName: string): Record<string, any>[];
|
|
19
59
|
/**
|
|
20
60
|
* 获取基本数据类型
|
|
21
61
|
* @param attrName
|
|
@@ -15,57 +15,103 @@ class RequestModel {
|
|
|
15
15
|
this.limit = limitOffset.limit;
|
|
16
16
|
this.offset = limitOffset.offset;
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* 解析 orderBy 参数为 IOrderByItem 数组
|
|
20
|
+
*
|
|
21
|
+
* 支持的格式:
|
|
22
|
+
* 1. 字符串格式(逗号分隔多个字段):
|
|
23
|
+
* - 标准 SQL 格式:'created_at DESC, amount ASC'
|
|
24
|
+
* - 简写 +/- 格式:'created_at-, amount+'('-' 表示 DESC,'+' 或省略表示 ASC)
|
|
25
|
+
* - 默认升序:'order_id'(无后缀时默认为 ASC)
|
|
26
|
+
*
|
|
27
|
+
* 2. 数组格式:
|
|
28
|
+
* - 纯对象数组:[{ fieldName: 'created_at', orderType: 'desc' }]
|
|
29
|
+
* - 混合数组1(字符串+对象):['order_id', { fieldName: 'amount', orderType: 'asc' }]
|
|
30
|
+
* - 混合数组2(字符串+对象):['order_id+', { fieldName: 'amount', orderType: 'asc' }]
|
|
31
|
+
* - 混合数组3(字符串+对象):['order_id DESC', { fieldName: 'amount', orderType: 'asc' }]
|
|
32
|
+
* 注:数组中的字符串元素支持标准 SQL 格式和简写格式,与字符串参数格式一致。
|
|
33
|
+
*
|
|
34
|
+
* SQL 注入防护:
|
|
35
|
+
* - 所有字段名必须通过 MixinUtils.isValidFieldName() 校验
|
|
36
|
+
* - 只允许 ASC/DESC 作为排序方向
|
|
37
|
+
*
|
|
38
|
+
* @param orderByStr 排序参数,可以是字符串或数组
|
|
39
|
+
* @returns IOrderByItem[] 解析后的排序项数组
|
|
40
|
+
*/
|
|
18
41
|
parseOrderBys(orderByStr) {
|
|
19
42
|
if (MixinUtils_1.MixinUtils.isEmpty(orderByStr)) {
|
|
20
43
|
return [];
|
|
21
44
|
}
|
|
45
|
+
// 数组格式:支持字符串和对象混合
|
|
22
46
|
if (Array.isArray(orderByStr)) {
|
|
23
47
|
return orderByStr
|
|
24
|
-
.map(
|
|
25
|
-
|
|
26
|
-
return { fieldName: obj, orderType: 'asc' };
|
|
27
|
-
}
|
|
28
|
-
const { fieldName, orderType = 'asc' } = obj;
|
|
29
|
-
if (fieldName) {
|
|
30
|
-
return { fieldName, orderType };
|
|
31
|
-
}
|
|
32
|
-
return null;
|
|
33
|
-
})
|
|
34
|
-
.filter(o => {
|
|
35
|
-
return !!o;
|
|
36
|
-
});
|
|
48
|
+
.map(item => this.parseOrderByItem(item))
|
|
49
|
+
.filter((o) => !!o);
|
|
37
50
|
}
|
|
38
|
-
|
|
39
|
-
|
|
51
|
+
// 字符串格式:逗号分隔多个字段
|
|
52
|
+
return orderByStr
|
|
40
53
|
.split(',')
|
|
41
|
-
.map(s =>
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
.filter(
|
|
45
|
-
|
|
46
|
-
|
|
54
|
+
.map(s => s.trim())
|
|
55
|
+
.filter(s => !!s)
|
|
56
|
+
.map(item => this.parseOrderByString(item))
|
|
57
|
+
.filter((o) => !!o);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* 解析单个排序项(数组元素)
|
|
61
|
+
*/
|
|
62
|
+
parseOrderByItem(item) {
|
|
63
|
+
// 字符串格式:解析标准 SQL 格式或简写格式
|
|
64
|
+
if (typeof item === 'string') {
|
|
65
|
+
return this.parseOrderByString(item);
|
|
47
66
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
67
|
+
// 对象格式:提取 fieldName 和 orderType
|
|
68
|
+
const { fieldName, orderType = 'asc' } = item || {};
|
|
69
|
+
if (!fieldName) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
this.validateFieldName(fieldName, fieldName);
|
|
73
|
+
return { fieldName, orderType };
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* 解析字符串格式的排序项(支持标准 SQL 和简写格式)
|
|
77
|
+
*/
|
|
78
|
+
parseOrderByString(orderByStr) {
|
|
79
|
+
let orderType = 'asc';
|
|
80
|
+
let fieldName = orderByStr;
|
|
81
|
+
// 检查是否为空格分隔的标准 SQL 格式(如 'created_at DESC')
|
|
82
|
+
const spaceIndex = orderByStr.lastIndexOf(' ');
|
|
83
|
+
if (spaceIndex > 0) {
|
|
84
|
+
const beforeSpace = orderByStr.substring(0, spaceIndex).trim();
|
|
85
|
+
const afterSpace = orderByStr.substring(spaceIndex + 1).trim().toUpperCase();
|
|
86
|
+
if (afterSpace === 'ASC' || afterSpace === 'DESC') {
|
|
87
|
+
fieldName = beforeSpace;
|
|
88
|
+
orderType = afterSpace.toLowerCase();
|
|
61
89
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
throw new exceptions_1.CommonException(exceptions_1.Exceptions.REQUEST_MODEL_PARSE_ORDER_BY_FAILED, orderByItem);
|
|
90
|
+
else {
|
|
91
|
+
throw new exceptions_1.CommonException(exceptions_1.Exceptions.REQUEST_MODEL_PARSE_ORDER_BY_FAILED, orderByStr);
|
|
65
92
|
}
|
|
66
|
-
orderByResult.push({ fieldName, orderType });
|
|
67
93
|
}
|
|
68
|
-
|
|
94
|
+
else if (orderByStr.endsWith('+')) {
|
|
95
|
+
// 简写格式:+ 表示升序
|
|
96
|
+
fieldName = orderByStr.slice(0, -1);
|
|
97
|
+
orderType = 'asc';
|
|
98
|
+
}
|
|
99
|
+
else if (orderByStr.endsWith('-')) {
|
|
100
|
+
// 简写格式:- 表示降序
|
|
101
|
+
fieldName = orderByStr.slice(0, -1);
|
|
102
|
+
orderType = 'desc';
|
|
103
|
+
}
|
|
104
|
+
fieldName = fieldName.trim();
|
|
105
|
+
this.validateFieldName(fieldName, orderByStr);
|
|
106
|
+
return { fieldName, orderType };
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* SQL 注入防护:校验字段名格式
|
|
110
|
+
*/
|
|
111
|
+
validateFieldName(fieldName, originalValue) {
|
|
112
|
+
if (MixinUtils_1.MixinUtils.isEmpty(fieldName) || !MixinUtils_1.MixinUtils.isValidFieldName(fieldName)) {
|
|
113
|
+
throw new exceptions_1.CommonException(exceptions_1.Exceptions.REQUEST_MODEL_PARSE_ORDER_BY_FAILED, originalValue);
|
|
114
|
+
}
|
|
69
115
|
}
|
|
70
116
|
parseOffsetList(req) {
|
|
71
117
|
const { limit, offset, pageSize, pageNo } = req;
|
|
@@ -102,6 +148,24 @@ class RequestModel {
|
|
|
102
148
|
}
|
|
103
149
|
throw new exceptions_1.CommonException(exceptions_1.Exceptions.RUN_GET_COND_OR_DATA_JSONOBJECT, attrName);
|
|
104
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* 获取数组类型的数据(用于批量插入)
|
|
153
|
+
* @param attrName
|
|
154
|
+
*/
|
|
155
|
+
getCondOrDataAsArray(attrName) {
|
|
156
|
+
if (attrName.startsWith('data')) {
|
|
157
|
+
const dataValue = _.get(this, attrName);
|
|
158
|
+
if (!dataValue) {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
// 如果是数组直接返回
|
|
162
|
+
if (Array.isArray(dataValue)) {
|
|
163
|
+
return dataValue;
|
|
164
|
+
}
|
|
165
|
+
throw new exceptions_1.CommonException(exceptions_1.Exceptions.RUN_GET_COND_OR_DATA_JSONOBJECT, attrName);
|
|
166
|
+
}
|
|
167
|
+
throw new exceptions_1.CommonException(exceptions_1.Exceptions.RUN_GET_COND_OR_DATA_JSONOBJECT, attrName);
|
|
168
|
+
}
|
|
105
169
|
/**
|
|
106
170
|
* 获取基本数据类型
|
|
107
171
|
* @param attrName
|
|
@@ -2,19 +2,21 @@ interface ResModelAffected {
|
|
|
2
2
|
insertId?: string | number;
|
|
3
3
|
affectedRows: number;
|
|
4
4
|
}
|
|
5
|
+
declare type ResModelRowEntity = Record<string, any>;
|
|
5
6
|
interface ResModelStandard {
|
|
6
|
-
row?:
|
|
7
|
-
rows?:
|
|
7
|
+
row?: ResModelRowEntity;
|
|
8
|
+
rows?: ResModelRowEntity[];
|
|
8
9
|
total_count?: number;
|
|
10
|
+
is_exist?: boolean;
|
|
9
11
|
affected?: ResModelAffected;
|
|
10
12
|
insert_affected?: ResModelAffected;
|
|
11
13
|
update_affected?: ResModelAffected;
|
|
12
14
|
}
|
|
13
15
|
interface ResModelPageQuery {
|
|
14
|
-
rows:
|
|
16
|
+
rows: ResModelRowEntity[];
|
|
15
17
|
total_count: number;
|
|
16
18
|
}
|
|
17
19
|
declare type ResModelFlexible = ResModelStandard & {
|
|
18
20
|
[key: string]: any;
|
|
19
21
|
};
|
|
20
|
-
export { ResModelAffected, ResModelStandard, ResModelFlexible, ResModelPageQuery };
|
|
22
|
+
export { ResModelAffected, ResModelStandard, ResModelFlexible, ResModelPageQuery, ResModelRowEntity };
|
|
@@ -17,4 +17,5 @@ export interface ICurdProServiceHub {
|
|
|
17
17
|
convertOriginToExecuteSql(sqlCfgModel: SqlCfgModel): Promise<void>;
|
|
18
18
|
executeFuncCfg(tmpFunCfg: IFuncCfgModel, exeFunCtx: FuncContext): string;
|
|
19
19
|
getTableMeta(query: ITableMetaQuery): Promise<ITableMeta>;
|
|
20
|
+
convertDataTypeByTableMeta(reqModel: RequestModel, cfgModel: RequestCfgModel): Promise<void>;
|
|
20
21
|
}
|
|
@@ -51,8 +51,10 @@ export declare enum KeysOfSimpleSQL {
|
|
|
51
51
|
SIMPLE_QUERY_ONE = "SIMPLE_QUERY_ONE",
|
|
52
52
|
SIMPLE_QUERY_PAGE = "SIMPLE_QUERY_PAGE",
|
|
53
53
|
SIMPLE_QUERY_COUNT = "SIMPLE_QUERY_COUNT",
|
|
54
|
+
SIMPLE_QUERY_EXIST = "SIMPLE_QUERY_EXIST",
|
|
54
55
|
SIMPLE_UPDATE = "SIMPLE_UPDATE",
|
|
55
56
|
SIMPLE_INSERT = "SIMPLE_INSERT",
|
|
57
|
+
SIMPLE_BATCH_INSERT = "SIMPLE_BATCH_INSERT",
|
|
56
58
|
SIMPLE_DELETE = "SIMPLE_DELETE",
|
|
57
59
|
SIMPLE_INSERT_ON_DUPLICATE_UPDATE = "SIMPLE_INSERT_ON_DUPLICATE_UPDATE",
|
|
58
60
|
SIMPLE_INSERT_OR_UPDATE = "SIMPLE_INSERT_OR_UPDATE",
|
|
@@ -62,7 +64,8 @@ export declare enum KeysOfSqlResPicker {
|
|
|
62
64
|
UPDATE_RESULT = "UPDATE_RESULT",
|
|
63
65
|
RESULT_FIRST_ROW = "RESULT_FIRST_ROW",
|
|
64
66
|
RESULT_TOTAL_COUNT = "RESULT_TOTAL_COUNT",
|
|
65
|
-
RESULT_ONE_VALUE = "RESULT_ONE_VALUE"
|
|
67
|
+
RESULT_ONE_VALUE = "RESULT_ONE_VALUE",
|
|
68
|
+
RESULT_IS_EXIST = "RESULT_IS_EXIST"
|
|
66
69
|
}
|
|
67
70
|
export declare const KeysOfCustomSQL: {
|
|
68
71
|
SQL_COLUMNS: string;
|
|
@@ -73,6 +76,8 @@ export declare const KeysOfCustomSQL: {
|
|
|
73
76
|
SQL_AS_UPDATE: string;
|
|
74
77
|
SQL_AS_INSERT_KEYS: string;
|
|
75
78
|
SQL_AS_INSERT_VALUES: string;
|
|
79
|
+
SQL_AS_BATCH_INSERT_KEYS: string;
|
|
80
|
+
SQL_AS_BATCH_INSERT_VALUES: string;
|
|
76
81
|
SQL_GET_DATA_ATTR_START: string;
|
|
77
82
|
SQL_GET_CONDITION_ATTR_START: string;
|
|
78
83
|
SQL_PICK_RES_AS_NUMBER: string;
|
|
@@ -61,8 +61,10 @@ var KeysOfSimpleSQL;
|
|
|
61
61
|
KeysOfSimpleSQL["SIMPLE_QUERY_ONE"] = "SIMPLE_QUERY_ONE";
|
|
62
62
|
KeysOfSimpleSQL["SIMPLE_QUERY_PAGE"] = "SIMPLE_QUERY_PAGE";
|
|
63
63
|
KeysOfSimpleSQL["SIMPLE_QUERY_COUNT"] = "SIMPLE_QUERY_COUNT";
|
|
64
|
+
KeysOfSimpleSQL["SIMPLE_QUERY_EXIST"] = "SIMPLE_QUERY_EXIST";
|
|
64
65
|
KeysOfSimpleSQL["SIMPLE_UPDATE"] = "SIMPLE_UPDATE";
|
|
65
66
|
KeysOfSimpleSQL["SIMPLE_INSERT"] = "SIMPLE_INSERT";
|
|
67
|
+
KeysOfSimpleSQL["SIMPLE_BATCH_INSERT"] = "SIMPLE_BATCH_INSERT";
|
|
66
68
|
KeysOfSimpleSQL["SIMPLE_DELETE"] = "SIMPLE_DELETE";
|
|
67
69
|
KeysOfSimpleSQL["SIMPLE_INSERT_ON_DUPLICATE_UPDATE"] = "SIMPLE_INSERT_ON_DUPLICATE_UPDATE";
|
|
68
70
|
KeysOfSimpleSQL["SIMPLE_INSERT_OR_UPDATE"] = "SIMPLE_INSERT_OR_UPDATE";
|
|
@@ -74,6 +76,7 @@ var KeysOfSqlResPicker;
|
|
|
74
76
|
KeysOfSqlResPicker["RESULT_FIRST_ROW"] = "RESULT_FIRST_ROW";
|
|
75
77
|
KeysOfSqlResPicker["RESULT_TOTAL_COUNT"] = "RESULT_TOTAL_COUNT";
|
|
76
78
|
KeysOfSqlResPicker["RESULT_ONE_VALUE"] = "RESULT_ONE_VALUE";
|
|
79
|
+
KeysOfSqlResPicker["RESULT_IS_EXIST"] = "RESULT_IS_EXIST";
|
|
77
80
|
})(KeysOfSqlResPicker = exports.KeysOfSqlResPicker || (exports.KeysOfSqlResPicker = {}));
|
|
78
81
|
exports.KeysOfCustomSQL = {
|
|
79
82
|
SQL_COLUMNS: '@@columns',
|
|
@@ -84,6 +87,8 @@ exports.KeysOfCustomSQL = {
|
|
|
84
87
|
SQL_AS_UPDATE: '@@asUpdate:',
|
|
85
88
|
SQL_AS_INSERT_KEYS: '@@asInsertKeys:',
|
|
86
89
|
SQL_AS_INSERT_VALUES: '@@asInsertValues:',
|
|
90
|
+
SQL_AS_BATCH_INSERT_KEYS: '@@asBatchInsertKeys:',
|
|
91
|
+
SQL_AS_BATCH_INSERT_VALUES: '@@asBatchInsertValues:',
|
|
87
92
|
// 从Req中取值:单独取Data中的某个字段:获取单个值。
|
|
88
93
|
SQL_GET_DATA_ATTR_START: '@@data',
|
|
89
94
|
SQL_GET_CONDITION_ATTR_START: '@@condition',
|