odps/tableschema/expression_parser.go (60 lines of code) (raw):
package tableschema
import (
"encoding/json"
"fmt"
"strings"
"github.com/aliyun/aliyun-odps-go-sdk/odps/data"
)
// GenerateExpression generates a column expression, used to generate partition values for the Auto-Partition table
type GenerateExpression interface {
generate(record *data.Record, schema *TableSchema) (string, error)
String() string
}
func parseGenerateExpression(exprJSON string) (GenerateExpression, error) {
if len(exprJSON) == 0 {
return nil, nil
}
generateExpression, err := parseFromJSON(exprJSON)
if err != nil {
return nil, err
}
// 后续遍历,最后一个项目为顶层表达式
topLevelExpression := generateExpression[len(generateExpression)-1]
functionCall := topLevelExpression.FunctionCall
if functionCall != nil && strings.ToLower(functionCall.Name) == "trunc_time" {
return newTruncTimeWithConstant(
generateExpression[0].LeafExprDesc.Reference.Name,
generateExpression[1].LeafExprDesc.Constant,
)
}
return nil, fmt.Errorf("unknown generate expression: %s", getFunctionName(functionCall))
}
type expressionItem struct {
LeafExprDesc leafExprDesc `json:"leafExprDesc"`
FunctionCall *functionCall `json:"functionCall"`
}
type leafExprDesc struct {
Reference reference `json:"reference"`
Constant string `json:"constant"`
IsNull bool `json:"isNull"`
Type string `json:"type"`
}
type reference struct {
Name string `json:"name"`
}
type functionCall struct {
Name string `json:"name"`
ParameterCount *int `json:"parameterCount"`
Type string `json:"type"`
}
func parseFromJSON(exprJSON string) ([]expressionItem, error) {
var expressionItems []expressionItem
if err := json.Unmarshal([]byte(exprJSON), &expressionItems); err != nil {
return nil, err
}
return expressionItems, nil
}
func getFunctionName(functionCall *functionCall) string {
if functionCall != nil {
return functionCall.Name
}
return "null"
}