作者 yangfu

chore:add ExprAST

... ... @@ -162,6 +162,97 @@
- [ ] 10W ..
- [ ] 保存单个文件、压缩 | 保存多个文件、压缩
## 表达式解析
### 表达式类型说明
- ValueExprAST: 值表达式(数值,字符串) e.g. 1 、 2011-1-1 、字符串
```json
{
"exprType":"ValueExprAST",
"val":"",
"str":"业绩2"
}
```
- FieldExprAST: 字段表达式(处理的字段) e.g. 生产明细.业绩
```json
{
"exprType":"FieldExprAST",
"str":"业绩1",
"field":{
"tableId":1,
"tableName":"测试ABC",
"tableSqlName":"table_abc_test",
"fieldName":"业绩",
"fieldSqlName":"ye_ji_1",
"fieldSqlType":"Float"
}
}
```
- BinaryExprAST: 二元表达式 e.g. 1 + 2 、 100 * 生产明细.业绩
```json
{
"exprType":"BinaryExprAST",
"op":"/",
"lhs":{},
"rhs":{}
}
```
- FunCallerExprAST:函数表达式 e.g. sum(arg1,arg2,arg3)
```json
{
"arrayFlag": false,
"exprType": "FunCallerExprAST",
"name": "sum",
"args": []
}
```
### 用例
- 输入表达式 `SUM(1/COUNTIFS(【业绩】,【业绩】))`
```json
{
"arrayFlag":false,
"exprType":"FunCallerExprAST",
"name":"sum",
"args":[
{
"exprType":"BinaryExprAST",
"op":"/",
"lhs":{
"exprType":"ValueExprAST",
"val":"",
"str":"1"
},
"rhs":{
"arrayFlag":false,
"exprType":"FunCallerExprAST",
"name":"countifs",
"args":[
{
"exprType":"FieldExprAST",
"str":"业绩1",
"field":{
"tableId":1,
"tableName":"测试ABC",
"tableSqlName":"table_abc_test",
"fieldName":"业绩",
"fieldSqlName":"ye_ji_1",
"fieldSqlType":"Float"
}
},
{
"exprType":"ValueExprAST",
"val":"",
"str":"业绩2"
}
]
}
}
]
}
```
## 讨论事项
- [ ] 校验动作,参数模型讨论
... ...
... ... @@ -19,7 +19,14 @@ type AppendDataToTableCommand struct {
}
func (cmd *AppendDataToTableCommand) Valid(validation *validation.Validation) {
newMappingFields := make([]*domain.MappingField, 0)
for i := range cmd.MappingFields {
if len(cmd.MappingFields[i].VerifiedFileFieldName) == 0 {
continue
}
newMappingFields = append(newMappingFields, cmd.MappingFields[i])
}
cmd.MappingFields = newMappingFields
}
func (cmd *AppendDataToTableCommand) ValidateCommand() error {
... ...
... ... @@ -190,6 +190,9 @@ func (fileService *FileService) AppendDataToTable(ctx *domain.Context, cmd *comm
if err := cmd.ValidateCommand(); err != nil {
return nil, application.ThrowError(application.ARG_ERROR, err.Error())
}
if len(cmd.MappingFields) == 0 {
return nil, factory.FastError(fmt.Errorf("请选择对应字段"))
}
transactionContext, err := factory.CreateTransactionContext(nil)
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
... ...
package domain
import (
"encoding/json"
"fmt"
)
const (
TypeFunCallerExprAST = "FunCallerExprAST"
TypeBinaryExprAST = "BinaryExprAST"
TypeFieldExprAST = "FieldExprAST"
TypeValueExprAST = "ValueExprAST"
)
type ExprAST interface {
toStr() string
}
type ValueExprAST struct {
ExprType string `json:"exprType"`
Val string `json:"val"`
Str string `json:"str"`
}
type FieldExprAST struct {
ExprType string `json:"exprType"`
Str string `json:"str"`
Field *TableField `json:"field"`
}
type BinaryExprAST struct {
ExprType string `json:"exprType"`
Op string `json:"op"`
Lhs ExprAST `json:"lhs"`
Rhs ExprAST `json:"rhs"`
}
type FunCallerExprAST struct {
ArrayFlag bool `json:"arrayFlag"`
ExprType string `json:"exprType"`
Name string `json:"name"`
Args []ExprAST `json:"args"`
}
func (n ValueExprAST) toStr() string {
return fmt.Sprintf(
"ValueExprAST:%s",
n.Str,
)
}
func (n FieldExprAST) toStr() string {
return fmt.Sprintf(
"FieldExprAST:%s",
n.Str,
)
}
func (b BinaryExprAST) toStr() string {
return fmt.Sprintf(
"BinaryExprAST: (%s %s %s)",
b.Op,
b.Lhs.toStr(),
b.Rhs.toStr(),
)
}
func (n FunCallerExprAST) toStr() string {
return fmt.Sprintf(
"FunCallerExprAST:%s",
n.Name,
)
}
type CloneFunCallerExprAST struct {
ArrayFlag bool `json:"arrayFlag"`
Name string `json:"name"`
Arg []json.RawMessage `json:"args"`
}
type CloneBinaryExprAST struct {
Op string `json:"op"`
Lhs json.RawMessage `json:"lhs"`
Rhs json.RawMessage `json:"rhs"`
}
func AstExprUnmarshalJSON(data []byte) (interface{}, error) {
var m = make(map[string]interface{})
if err := json.Unmarshal(data, &m); err != nil {
return nil, err
}
value, err := unmarshalMapInterface(m, data)
if err != nil {
return data, err
}
return value, nil
}
func unmarshalMapInterface(m map[string]interface{}, rawData []byte) (interface{}, error) {
t, ok := m["exprType"]
if !ok {
return nil, nil
}
if t == TypeFunCallerExprAST {
expr := &CloneFunCallerExprAST{}
if err := json.Unmarshal(rawData, expr); err != nil {
return nil, err
}
exprReturn := &FunCallerExprAST{Name: expr.Name, ExprType: TypeFunCallerExprAST}
for i := range expr.Arg {
subExpr, err := AstExprUnmarshalJSON(expr.Arg[i])
if err != nil {
return nil, err
}
if subExpr == nil {
continue
}
exprReturn.Args = append(exprReturn.Args, subExpr.(ExprAST))
}
return exprReturn, nil
}
if t == TypeBinaryExprAST {
expr := &CloneBinaryExprAST{}
if err := json.Unmarshal(rawData, expr); err != nil {
return nil, err
}
exprReturn := &BinaryExprAST{Op: expr.Op, ExprType: TypeBinaryExprAST}
if len(expr.Lhs) > 0 {
subExpr, err := AstExprUnmarshalJSON(expr.Lhs)
if err != nil {
return nil, err
}
if subExpr != nil {
exprReturn.Lhs = subExpr.(ExprAST)
}
}
if len(expr.Rhs) > 0 {
subExpr, err := AstExprUnmarshalJSON(expr.Rhs)
if err != nil {
return nil, err
}
if subExpr != nil {
exprReturn.Rhs = subExpr.(ExprAST)
}
}
return exprReturn, nil
}
if t == TypeFieldExprAST {
expr := &FieldExprAST{ExprType: TypeFieldExprAST}
if err := json.Unmarshal(rawData, expr); err != nil {
return nil, err
}
return expr, nil
}
if t == TypeValueExprAST {
expr := &ValueExprAST{ExprType: TypeValueExprAST}
if err := json.Unmarshal(rawData, expr); err != nil {
return nil, err
}
return expr, nil
}
return nil, fmt.Errorf("unkonw expr type '%v'", t)
}
... ...
package domain
import (
"github.com/linmadan/egglib-go/utils/json"
"github.com/stretchr/testify/assert"
"testing"
)
func TestAstExprUnmarshalJSON(t *testing.T) {
inputs := []struct {
data ExprAST
}{
{
data: &FunCallerExprAST{
Name: "if",
ExprType: TypeFunCallerExprAST,
Args: []ExprAST{
&BinaryExprAST{
ExprType: TypeBinaryExprAST,
Op: "<",
Lhs: &FieldExprAST{
ExprType: TypeFieldExprAST,
Str: "table.count",
},
Rhs: &FieldExprAST{
ExprType: TypeFieldExprAST,
Str: "100",
},
},
&FieldExprAST{
ExprType: TypeFieldExprAST,
Str: "200",
},
&FieldExprAST{
ExprType: TypeFieldExprAST,
Str: "300",
},
},
},
},
{
data: &FunCallerExprAST{
Name: "sum",
ExprType: TypeFunCallerExprAST,
Args: []ExprAST{
&BinaryExprAST{
ExprType: TypeBinaryExprAST,
Op: "/",
Lhs: &ValueExprAST{
ExprType: TypeValueExprAST,
Str: "1",
},
Rhs: &FunCallerExprAST{
ExprType: TypeFunCallerExprAST,
Name: "countifs",
Args: []ExprAST{
&FieldExprAST{
ExprType: TypeFieldExprAST,
Str: "业绩1",
Field: &TableField{
TableId: 1,
TableName: "测试ABC",
TableSqlName: "table_abc_test",
FieldName: "业绩",
FieldSqlName: "ye_ji_1",
FieldSQLType: "Float",
},
},
&ValueExprAST{
ExprType: TypeValueExprAST,
Str: "业绩2",
},
},
},
},
},
},
},
}
for _, input := range inputs {
data, err := json.Marshal(input.data)
if err != nil {
t.Fatal(err)
}
v, err := AstExprUnmarshalJSON(data)
if err != nil {
t.Fatal(err)
}
if v != nil {
}
assert.Equal(t, input.data, v)
}
}
... ...