-
Notifications
You must be signed in to change notification settings - Fork 2
/
column.go
95 lines (88 loc) · 2.9 KB
/
column.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package sqlparser
import (
"github.com/viant/sqlparser/column"
"github.com/viant/sqlparser/expr"
"github.com/viant/sqlparser/query"
"strings"
)
// Column represent column
type Column column.Spec
func (c *Column) Identity() string {
if c.Alias != "" {
return c.Alias
}
return c.Name
}
func NewColumn(item *query.Item) *Column {
column := newColumn(item)
if column.Comments == "" {
column.Comments = item.Comments
}
column.Tag = item.Tag
return column
}
func newColumn(item *query.Item) *Column {
switch actual := item.Expr.(type) {
case *expr.Call:
call := Stringify(actual)
fn, args := extractArguments(call)
lcArgs := strings.ToLower(args)
if item.DataType == "" {
item.DataType = "string"
}
name := ""
if strings.EqualFold(fn, "cast") {
if index := strings.Index(lcArgs, " as "); index != -1 {
name = strings.TrimSpace(args[:index])
targetType := strings.TrimSpace(args[index+4:])
item.DataType = adjustDataType(targetType)
}
}
if strings.EqualFold(fn, "tag") {
params := strings.SplitN(args, ",", 2)
name = params[0]
item.Tag = params[1]
}
return &Column{Name: name, Alias: item.Alias, Type: item.DataType, Tag: item.Tag, Expression: call}
case *expr.Ident:
return &Column{Name: actual.Name, Alias: item.Alias, Type: item.DataType, Tag: item.Tag}
case *expr.Selector:
return &Column{Name: Stringify(actual.X), Namespace: actual.Name, Type: item.DataType, Alias: item.Alias, Tag: item.Tag}
case *expr.Star:
switch star := actual.X.(type) {
case *expr.Ident:
return &Column{Namespace: star.Name, Except: actual.Except, Tag: item.Tag, Expression: Stringify(star)}
case *expr.Selector:
return &Column{Namespace: star.Name, Except: actual.Except, Comments: actual.Comments, Tag: item.Tag, Expression: Stringify(star)}
}
case *expr.Literal:
return &Column{Name: "", Alias: item.Alias, Type: actual.Kind, Tag: item.Tag, Expression: actual.Value}
case *expr.Binary:
expression := Stringify(actual)
if item.DataType == "" || (strings.Contains(expression, "+") || strings.Contains(expression, "-") || strings.Contains(expression, "/") || strings.Contains(expression, "*")) {
item.DataType = "float64"
}
return &Column{Alias: item.Alias, Type: item.DataType, Tag: item.Tag, Expression: expression}
case *expr.Parenthesis:
return &Column{Name: Stringify(actual), Alias: item.Alias, Type: item.DataType, Tag: item.Tag, Expression: actual.Raw}
}
return &Column{Name: item.Raw, Expression: Stringify(item.Expr), Alias: item.Alias, Comments: item.Comments}
}
func extractArguments(expr string) (string, string) {
fn := ""
if index := strings.Index(expr, "("); index != -1 {
fn = expr[:index]
expr = expr[index+1:]
}
if index := strings.LastIndex(expr, ")"); index != -1 {
expr = expr[:index]
}
return fn, expr
}
func adjustDataType(targetType string) string {
switch strings.ToLower(targetType) {
case "signed":
return "int"
}
return "string"
}