正在显示
5 个修改的文件
包含
360 行增加
和
1 行删除
| @@ -162,6 +162,97 @@ | @@ -162,6 +162,97 @@ | ||
| 162 | - [ ] 10W .. | 162 | - [ ] 10W .. |
| 163 | - [ ] 保存单个文件、压缩 | 保存多个文件、压缩 | 163 | - [ ] 保存单个文件、压缩 | 保存多个文件、压缩 |
| 164 | 164 | ||
| 165 | +## 表达式解析 | ||
| 166 | + | ||
| 167 | +### 表达式类型说明 | ||
| 168 | +- ValueExprAST: 值表达式(数值,字符串) e.g. 1 、 2011-1-1 、字符串 | ||
| 169 | +```json | ||
| 170 | +{ | ||
| 171 | + "exprType":"ValueExprAST", | ||
| 172 | + "val":"", | ||
| 173 | + "str":"业绩2" | ||
| 174 | +} | ||
| 175 | +``` | ||
| 176 | +- FieldExprAST: 字段表达式(处理的字段) e.g. 生产明细.业绩 | ||
| 177 | +```json | ||
| 178 | +{ | ||
| 179 | + "exprType":"FieldExprAST", | ||
| 180 | + "str":"业绩1", | ||
| 181 | + "field":{ | ||
| 182 | + "tableId":1, | ||
| 183 | + "tableName":"测试ABC", | ||
| 184 | + "tableSqlName":"table_abc_test", | ||
| 185 | + "fieldName":"业绩", | ||
| 186 | + "fieldSqlName":"ye_ji_1", | ||
| 187 | + "fieldSqlType":"Float" | ||
| 188 | + } | ||
| 189 | +} | ||
| 190 | +``` | ||
| 191 | +- BinaryExprAST: 二元表达式 e.g. 1 + 2 、 100 * 生产明细.业绩 | ||
| 192 | +```json | ||
| 193 | +{ | ||
| 194 | + "exprType":"BinaryExprAST", | ||
| 195 | + "op":"/", | ||
| 196 | + "lhs":{}, | ||
| 197 | + "rhs":{} | ||
| 198 | +} | ||
| 199 | +``` | ||
| 200 | + | ||
| 201 | +- FunCallerExprAST:函数表达式 e.g. sum(arg1,arg2,arg3) | ||
| 202 | +```json | ||
| 203 | +{ | ||
| 204 | + "arrayFlag": false, | ||
| 205 | + "exprType": "FunCallerExprAST", | ||
| 206 | + "name": "sum", | ||
| 207 | + "args": [] | ||
| 208 | +} | ||
| 209 | +``` | ||
| 210 | + | ||
| 211 | +### 用例 | ||
| 212 | +- 输入表达式 `SUM(1/COUNTIFS(【业绩】,【业绩】))` | ||
| 213 | +```json | ||
| 214 | +{ | ||
| 215 | + "arrayFlag":false, | ||
| 216 | + "exprType":"FunCallerExprAST", | ||
| 217 | + "name":"sum", | ||
| 218 | + "args":[ | ||
| 219 | + { | ||
| 220 | + "exprType":"BinaryExprAST", | ||
| 221 | + "op":"/", | ||
| 222 | + "lhs":{ | ||
| 223 | + "exprType":"ValueExprAST", | ||
| 224 | + "val":"", | ||
| 225 | + "str":"1" | ||
| 226 | + }, | ||
| 227 | + "rhs":{ | ||
| 228 | + "arrayFlag":false, | ||
| 229 | + "exprType":"FunCallerExprAST", | ||
| 230 | + "name":"countifs", | ||
| 231 | + "args":[ | ||
| 232 | + { | ||
| 233 | + "exprType":"FieldExprAST", | ||
| 234 | + "str":"业绩1", | ||
| 235 | + "field":{ | ||
| 236 | + "tableId":1, | ||
| 237 | + "tableName":"测试ABC", | ||
| 238 | + "tableSqlName":"table_abc_test", | ||
| 239 | + "fieldName":"业绩", | ||
| 240 | + "fieldSqlName":"ye_ji_1", | ||
| 241 | + "fieldSqlType":"Float" | ||
| 242 | + } | ||
| 243 | + }, | ||
| 244 | + { | ||
| 245 | + "exprType":"ValueExprAST", | ||
| 246 | + "val":"", | ||
| 247 | + "str":"业绩2" | ||
| 248 | + } | ||
| 249 | + ] | ||
| 250 | + } | ||
| 251 | + } | ||
| 252 | + ] | ||
| 253 | +} | ||
| 254 | +``` | ||
| 255 | + | ||
| 165 | ## 讨论事项 | 256 | ## 讨论事项 |
| 166 | 257 | ||
| 167 | - [ ] 校验动作,参数模型讨论 | 258 | - [ ] 校验动作,参数模型讨论 |
| @@ -19,7 +19,14 @@ type AppendDataToTableCommand struct { | @@ -19,7 +19,14 @@ type AppendDataToTableCommand struct { | ||
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | func (cmd *AppendDataToTableCommand) Valid(validation *validation.Validation) { | 21 | func (cmd *AppendDataToTableCommand) Valid(validation *validation.Validation) { |
| 22 | - | 22 | + newMappingFields := make([]*domain.MappingField, 0) |
| 23 | + for i := range cmd.MappingFields { | ||
| 24 | + if len(cmd.MappingFields[i].VerifiedFileFieldName) == 0 { | ||
| 25 | + continue | ||
| 26 | + } | ||
| 27 | + newMappingFields = append(newMappingFields, cmd.MappingFields[i]) | ||
| 28 | + } | ||
| 29 | + cmd.MappingFields = newMappingFields | ||
| 23 | } | 30 | } |
| 24 | 31 | ||
| 25 | func (cmd *AppendDataToTableCommand) ValidateCommand() error { | 32 | func (cmd *AppendDataToTableCommand) ValidateCommand() error { |
| @@ -190,6 +190,9 @@ func (fileService *FileService) AppendDataToTable(ctx *domain.Context, cmd *comm | @@ -190,6 +190,9 @@ func (fileService *FileService) AppendDataToTable(ctx *domain.Context, cmd *comm | ||
| 190 | if err := cmd.ValidateCommand(); err != nil { | 190 | if err := cmd.ValidateCommand(); err != nil { |
| 191 | return nil, application.ThrowError(application.ARG_ERROR, err.Error()) | 191 | return nil, application.ThrowError(application.ARG_ERROR, err.Error()) |
| 192 | } | 192 | } |
| 193 | + if len(cmd.MappingFields) == 0 { | ||
| 194 | + return nil, factory.FastError(fmt.Errorf("请选择对应字段")) | ||
| 195 | + } | ||
| 193 | transactionContext, err := factory.CreateTransactionContext(nil) | 196 | transactionContext, err := factory.CreateTransactionContext(nil) |
| 194 | if err != nil { | 197 | if err != nil { |
| 195 | return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | 198 | return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) |
pkg/domain/ast_expr.go
0 → 100644
| 1 | +package domain | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "encoding/json" | ||
| 5 | + "fmt" | ||
| 6 | +) | ||
| 7 | + | ||
| 8 | +const ( | ||
| 9 | + TypeFunCallerExprAST = "FunCallerExprAST" | ||
| 10 | + TypeBinaryExprAST = "BinaryExprAST" | ||
| 11 | + TypeFieldExprAST = "FieldExprAST" | ||
| 12 | + TypeValueExprAST = "ValueExprAST" | ||
| 13 | +) | ||
| 14 | + | ||
| 15 | +type ExprAST interface { | ||
| 16 | + toStr() string | ||
| 17 | +} | ||
| 18 | + | ||
| 19 | +type ValueExprAST struct { | ||
| 20 | + ExprType string `json:"exprType"` | ||
| 21 | + Val string `json:"val"` | ||
| 22 | + Str string `json:"str"` | ||
| 23 | +} | ||
| 24 | + | ||
| 25 | +type FieldExprAST struct { | ||
| 26 | + ExprType string `json:"exprType"` | ||
| 27 | + Str string `json:"str"` | ||
| 28 | + Field *TableField `json:"field"` | ||
| 29 | +} | ||
| 30 | + | ||
| 31 | +type BinaryExprAST struct { | ||
| 32 | + ExprType string `json:"exprType"` | ||
| 33 | + Op string `json:"op"` | ||
| 34 | + Lhs ExprAST `json:"lhs"` | ||
| 35 | + Rhs ExprAST `json:"rhs"` | ||
| 36 | +} | ||
| 37 | + | ||
| 38 | +type FunCallerExprAST struct { | ||
| 39 | + ArrayFlag bool `json:"arrayFlag"` | ||
| 40 | + ExprType string `json:"exprType"` | ||
| 41 | + Name string `json:"name"` | ||
| 42 | + Args []ExprAST `json:"args"` | ||
| 43 | +} | ||
| 44 | + | ||
| 45 | +func (n ValueExprAST) toStr() string { | ||
| 46 | + return fmt.Sprintf( | ||
| 47 | + "ValueExprAST:%s", | ||
| 48 | + n.Str, | ||
| 49 | + ) | ||
| 50 | +} | ||
| 51 | + | ||
| 52 | +func (n FieldExprAST) toStr() string { | ||
| 53 | + return fmt.Sprintf( | ||
| 54 | + "FieldExprAST:%s", | ||
| 55 | + n.Str, | ||
| 56 | + ) | ||
| 57 | +} | ||
| 58 | + | ||
| 59 | +func (b BinaryExprAST) toStr() string { | ||
| 60 | + return fmt.Sprintf( | ||
| 61 | + "BinaryExprAST: (%s %s %s)", | ||
| 62 | + b.Op, | ||
| 63 | + b.Lhs.toStr(), | ||
| 64 | + b.Rhs.toStr(), | ||
| 65 | + ) | ||
| 66 | +} | ||
| 67 | + | ||
| 68 | +func (n FunCallerExprAST) toStr() string { | ||
| 69 | + return fmt.Sprintf( | ||
| 70 | + "FunCallerExprAST:%s", | ||
| 71 | + n.Name, | ||
| 72 | + ) | ||
| 73 | +} | ||
| 74 | + | ||
| 75 | +type CloneFunCallerExprAST struct { | ||
| 76 | + ArrayFlag bool `json:"arrayFlag"` | ||
| 77 | + Name string `json:"name"` | ||
| 78 | + Arg []json.RawMessage `json:"args"` | ||
| 79 | +} | ||
| 80 | + | ||
| 81 | +type CloneBinaryExprAST struct { | ||
| 82 | + Op string `json:"op"` | ||
| 83 | + Lhs json.RawMessage `json:"lhs"` | ||
| 84 | + Rhs json.RawMessage `json:"rhs"` | ||
| 85 | +} | ||
| 86 | + | ||
| 87 | +func AstExprUnmarshalJSON(data []byte) (interface{}, error) { | ||
| 88 | + var m = make(map[string]interface{}) | ||
| 89 | + if err := json.Unmarshal(data, &m); err != nil { | ||
| 90 | + return nil, err | ||
| 91 | + } | ||
| 92 | + value, err := unmarshalMapInterface(m, data) | ||
| 93 | + if err != nil { | ||
| 94 | + return data, err | ||
| 95 | + } | ||
| 96 | + return value, nil | ||
| 97 | +} | ||
| 98 | + | ||
| 99 | +func unmarshalMapInterface(m map[string]interface{}, rawData []byte) (interface{}, error) { | ||
| 100 | + t, ok := m["exprType"] | ||
| 101 | + if !ok { | ||
| 102 | + return nil, nil | ||
| 103 | + } | ||
| 104 | + if t == TypeFunCallerExprAST { | ||
| 105 | + expr := &CloneFunCallerExprAST{} | ||
| 106 | + if err := json.Unmarshal(rawData, expr); err != nil { | ||
| 107 | + return nil, err | ||
| 108 | + } | ||
| 109 | + exprReturn := &FunCallerExprAST{Name: expr.Name, ExprType: TypeFunCallerExprAST} | ||
| 110 | + for i := range expr.Arg { | ||
| 111 | + subExpr, err := AstExprUnmarshalJSON(expr.Arg[i]) | ||
| 112 | + if err != nil { | ||
| 113 | + return nil, err | ||
| 114 | + } | ||
| 115 | + if subExpr == nil { | ||
| 116 | + continue | ||
| 117 | + } | ||
| 118 | + exprReturn.Args = append(exprReturn.Args, subExpr.(ExprAST)) | ||
| 119 | + } | ||
| 120 | + return exprReturn, nil | ||
| 121 | + } | ||
| 122 | + if t == TypeBinaryExprAST { | ||
| 123 | + expr := &CloneBinaryExprAST{} | ||
| 124 | + if err := json.Unmarshal(rawData, expr); err != nil { | ||
| 125 | + return nil, err | ||
| 126 | + } | ||
| 127 | + exprReturn := &BinaryExprAST{Op: expr.Op, ExprType: TypeBinaryExprAST} | ||
| 128 | + if len(expr.Lhs) > 0 { | ||
| 129 | + subExpr, err := AstExprUnmarshalJSON(expr.Lhs) | ||
| 130 | + if err != nil { | ||
| 131 | + return nil, err | ||
| 132 | + } | ||
| 133 | + if subExpr != nil { | ||
| 134 | + exprReturn.Lhs = subExpr.(ExprAST) | ||
| 135 | + } | ||
| 136 | + } | ||
| 137 | + if len(expr.Rhs) > 0 { | ||
| 138 | + subExpr, err := AstExprUnmarshalJSON(expr.Rhs) | ||
| 139 | + if err != nil { | ||
| 140 | + return nil, err | ||
| 141 | + } | ||
| 142 | + if subExpr != nil { | ||
| 143 | + exprReturn.Rhs = subExpr.(ExprAST) | ||
| 144 | + } | ||
| 145 | + } | ||
| 146 | + return exprReturn, nil | ||
| 147 | + } | ||
| 148 | + if t == TypeFieldExprAST { | ||
| 149 | + expr := &FieldExprAST{ExprType: TypeFieldExprAST} | ||
| 150 | + if err := json.Unmarshal(rawData, expr); err != nil { | ||
| 151 | + return nil, err | ||
| 152 | + } | ||
| 153 | + return expr, nil | ||
| 154 | + } | ||
| 155 | + if t == TypeValueExprAST { | ||
| 156 | + expr := &ValueExprAST{ExprType: TypeValueExprAST} | ||
| 157 | + if err := json.Unmarshal(rawData, expr); err != nil { | ||
| 158 | + return nil, err | ||
| 159 | + } | ||
| 160 | + return expr, nil | ||
| 161 | + } | ||
| 162 | + return nil, fmt.Errorf("unkonw expr type '%v'", t) | ||
| 163 | +} |
pkg/domain/ast_expr_test.go
0 → 100644
| 1 | +package domain | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "github.com/linmadan/egglib-go/utils/json" | ||
| 5 | + "github.com/stretchr/testify/assert" | ||
| 6 | + "testing" | ||
| 7 | +) | ||
| 8 | + | ||
| 9 | +func TestAstExprUnmarshalJSON(t *testing.T) { | ||
| 10 | + inputs := []struct { | ||
| 11 | + data ExprAST | ||
| 12 | + }{ | ||
| 13 | + { | ||
| 14 | + data: &FunCallerExprAST{ | ||
| 15 | + Name: "if", | ||
| 16 | + ExprType: TypeFunCallerExprAST, | ||
| 17 | + Args: []ExprAST{ | ||
| 18 | + &BinaryExprAST{ | ||
| 19 | + ExprType: TypeBinaryExprAST, | ||
| 20 | + Op: "<", | ||
| 21 | + Lhs: &FieldExprAST{ | ||
| 22 | + ExprType: TypeFieldExprAST, | ||
| 23 | + Str: "table.count", | ||
| 24 | + }, | ||
| 25 | + Rhs: &FieldExprAST{ | ||
| 26 | + ExprType: TypeFieldExprAST, | ||
| 27 | + Str: "100", | ||
| 28 | + }, | ||
| 29 | + }, | ||
| 30 | + &FieldExprAST{ | ||
| 31 | + ExprType: TypeFieldExprAST, | ||
| 32 | + Str: "200", | ||
| 33 | + }, | ||
| 34 | + &FieldExprAST{ | ||
| 35 | + ExprType: TypeFieldExprAST, | ||
| 36 | + Str: "300", | ||
| 37 | + }, | ||
| 38 | + }, | ||
| 39 | + }, | ||
| 40 | + }, | ||
| 41 | + { | ||
| 42 | + data: &FunCallerExprAST{ | ||
| 43 | + Name: "sum", | ||
| 44 | + ExprType: TypeFunCallerExprAST, | ||
| 45 | + Args: []ExprAST{ | ||
| 46 | + &BinaryExprAST{ | ||
| 47 | + ExprType: TypeBinaryExprAST, | ||
| 48 | + Op: "/", | ||
| 49 | + Lhs: &ValueExprAST{ | ||
| 50 | + ExprType: TypeValueExprAST, | ||
| 51 | + Str: "1", | ||
| 52 | + }, | ||
| 53 | + Rhs: &FunCallerExprAST{ | ||
| 54 | + ExprType: TypeFunCallerExprAST, | ||
| 55 | + Name: "countifs", | ||
| 56 | + Args: []ExprAST{ | ||
| 57 | + &FieldExprAST{ | ||
| 58 | + ExprType: TypeFieldExprAST, | ||
| 59 | + Str: "业绩1", | ||
| 60 | + Field: &TableField{ | ||
| 61 | + TableId: 1, | ||
| 62 | + TableName: "测试ABC", | ||
| 63 | + TableSqlName: "table_abc_test", | ||
| 64 | + FieldName: "业绩", | ||
| 65 | + FieldSqlName: "ye_ji_1", | ||
| 66 | + FieldSQLType: "Float", | ||
| 67 | + }, | ||
| 68 | + }, | ||
| 69 | + &ValueExprAST{ | ||
| 70 | + ExprType: TypeValueExprAST, | ||
| 71 | + Str: "业绩2", | ||
| 72 | + }, | ||
| 73 | + }, | ||
| 74 | + }, | ||
| 75 | + }, | ||
| 76 | + }, | ||
| 77 | + }, | ||
| 78 | + }, | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + for _, input := range inputs { | ||
| 82 | + data, err := json.Marshal(input.data) | ||
| 83 | + if err != nil { | ||
| 84 | + t.Fatal(err) | ||
| 85 | + } | ||
| 86 | + v, err := AstExprUnmarshalJSON(data) | ||
| 87 | + if err != nil { | ||
| 88 | + t.Fatal(err) | ||
| 89 | + } | ||
| 90 | + if v != nil { | ||
| 91 | + | ||
| 92 | + } | ||
| 93 | + assert.Equal(t, input.data, v) | ||
| 94 | + } | ||
| 95 | +} |
-
请 注册 或 登录 后发表评论