瀏覽代碼

refactor(all): format by go fmt

ngjaying 5 年之前
父節點
當前提交
1674c039b2
共有 74 個文件被更改,包括 2735 次插入2816 次删除
  1. 23 23
      common/data.go
  2. 2 3
      common/plugin_manager/manager.go
  3. 4 4
      common/templates/funcs.go
  4. 24 24
      common/time_util.go
  5. 48 48
      common/util.go
  6. 3 3
      common/util_test.go
  7. 11 11
      common/utils/dynamic_channel_buffer.go
  8. 3 3
      plugins/functions/countPlusOne.go
  9. 2 2
      plugins/functions/echo.go
  10. 13 13
      plugins/sinks/file.go
  11. 3 4
      plugins/sinks/memory.go
  12. 12 13
      plugins/sinks/zmq.go
  13. 20 20
      plugins/sources/random.go
  14. 14 14
      plugins/sources/zmq.go
  15. 101 104
      xsql/ast.go
  16. 14 14
      xsql/ast_agg_stmt_test.go
  17. 1 1
      xsql/expression_evaluator.go
  18. 33 33
      xsql/funcs_aggregate.go
  19. 28 29
      xsql/funcs_ast_validator.go
  20. 101 105
      xsql/funcs_ast_validator_test.go
  21. 1 1
      xsql/funcs_math.go
  22. 3 5
      xsql/funcs_misc.go
  23. 15 16
      xsql/funcs_str.go
  24. 10 10
      xsql/functions.go
  25. 23 21
      xsql/lexical.go
  26. 4 3
      xsql/metadata_util.go
  27. 15 17
      xsql/parser.go
  28. 337 351
      xsql/parser_test.go
  29. 6 7
      xsql/plans/aggregate_operator.go
  30. 61 62
      xsql/plans/aggregate_test.go
  31. 4 4
      xsql/plans/filter_operator.go
  32. 51 52
      xsql/plans/filter_test.go
  33. 1 1
      xsql/plans/having_operator.go
  34. 35 37
      xsql/plans/having_test.go
  35. 118 118
      xsql/plans/join_multi_test.go
  36. 10 11
      xsql/plans/join_operator.go
  37. 457 478
      xsql/plans/join_test.go
  38. 8 9
      xsql/plans/math_func_test.go
  39. 30 31
      xsql/plans/misc_func_test.go
  40. 3 3
      xsql/plans/order_operator.go
  41. 92 92
      xsql/plans/order_test.go
  42. 83 83
      xsql/plans/preprocessor.go
  43. 62 62
      xsql/plans/preprocessor_test.go
  44. 18 19
      xsql/plans/project_operator.go
  45. 263 274
      xsql/plans/project_test.go
  46. 82 82
      xsql/plans/str_func_test.go
  47. 13 14
      xsql/processors/extension_test.go
  48. 5 5
      xsql/processors/xsql_processor.go
  49. 26 26
      xsql/processors/xsql_processor_test.go
  50. 7 7
      xsql/util.go
  51. 2 3
      xsql/xsql_manager.go
  52. 8 9
      xsql/xsql_parser_tree_test.go
  53. 52 53
      xsql/xsql_stream_test.go
  54. 48 50
      xstream/cli/main.go
  55. 4 4
      xstream/collectors/func.go
  56. 1 2
      xstream/contexts/default.go
  57. 2 3
      xstream/demo/func_visitor.go
  58. 4 4
      xstream/extensions/mqtt_source.go
  59. 1 1
      xstream/funcs.go
  60. 1 3
      xstream/nodes/common_func.go
  61. 15 15
      xstream/nodes/prometheus.go
  62. 30 30
      xstream/nodes/sink_cache.go
  63. 29 29
      xstream/nodes/sink_node.go
  64. 12 12
      xstream/nodes/source_node.go
  65. 13 12
      xstream/nodes/stats_manager.go
  66. 8 8
      xstream/operators/operations.go
  67. 5 5
      xstream/server/server/server.go
  68. 5 5
      xstream/sinks/log_sink.go
  69. 6 7
      xstream/sinks/mqtt_sink.go
  70. 42 42
      xstream/sinks/rest_sink.go
  71. 120 120
      xstream/sinks/rest_sink_test.go
  72. 6 6
      xstream/streams.go
  73. 9 10
      xstream/test/mock_source.go
  74. 9 11
      xstream/util.go

+ 23 - 23
common/data.go

@@ -18,15 +18,15 @@ type Ticker interface {
 	Trigger(ti int64)
 }
 
-type DefaultTicker struct{
+type DefaultTicker struct {
 	time.Ticker
 }
 
-func NewDefaultTicker(d int) *DefaultTicker{
+func NewDefaultTicker(d int) *DefaultTicker {
 	return &DefaultTicker{*(time.NewTicker(time.Duration(d) * time.Millisecond))}
 }
 
-func (t *DefaultTicker) GetC() <-chan time.Time{
+func (t *DefaultTicker) GetC() <-chan time.Time {
 	return t.C
 }
 
@@ -35,30 +35,30 @@ func (t *DefaultTicker) Trigger(ti int64) {
 }
 
 type MockTicker struct {
-	c chan time.Time
+	c        chan time.Time
 	duration int64
 	lastTick int64
 }
 
-func NewMockTicker(d int) *MockTicker{
+func NewMockTicker(d int) *MockTicker {
 	if d <= 0 {
 		panic(errors.New("non-positive interval for MockTicker"))
 	}
 	c := make(chan time.Time, 1)
 	t := &MockTicker{
-		c: c,
+		c:        c,
 		duration: int64(d),
 		lastTick: GetMockNow(),
 	}
 	return t
 }
 
-func (t *MockTicker) SetDuration(d int){
+func (t *MockTicker) SetDuration(d int) {
 	t.duration = int64(d)
 	t.lastTick = GetMockNow()
 }
 
-func (t *MockTicker) GetC() <-chan time.Time{
+func (t *MockTicker) GetC() <-chan time.Time {
 	return t.c
 }
 
@@ -76,7 +76,7 @@ func (t *MockTicker) DoTick(c int64) {
 	if t.lastTick == 0 {
 		t.lastTick = c
 	}
-	if c >= (t.lastTick + t.duration){
+	if c >= (t.lastTick + t.duration) {
 		Log.Debugf("trigger tick")
 		t.Trigger(t.lastTick + t.duration)
 	}
@@ -90,15 +90,15 @@ type Timer interface {
 	Trigger(ti int64)
 }
 
-type DefaultTimer struct{
+type DefaultTimer struct {
 	time.Timer
 }
 
-func NewDefaultTimer(d int) *DefaultTimer{
+func NewDefaultTimer(d int) *DefaultTimer {
 	return &DefaultTimer{*(time.NewTimer(time.Duration(d) * time.Millisecond))}
 }
 
-func (t *DefaultTimer) GetC() <-chan time.Time{
+func (t *DefaultTimer) GetC() <-chan time.Time {
 	return t.C
 }
 
@@ -107,42 +107,42 @@ func (t *DefaultTimer) Trigger(ti int64) {
 }
 
 type MockTimer struct {
-	c chan time.Time
-	duration int64
+	c         chan time.Time
+	duration  int64
 	createdAt int64
 }
 
-func NewMockTimer(d int) *MockTimer{
+func NewMockTimer(d int) *MockTimer {
 	if d <= 0 {
 		panic(errors.New("non-positive interval for MockTimer"))
 	}
 	c := make(chan time.Time, 1)
 	t := &MockTimer{
-		c: c,
-		duration: int64(d),
+		c:         c,
+		duration:  int64(d),
 		createdAt: GetMockNow(),
 	}
 	return t
 }
 
-func (t *MockTimer) GetC() <-chan time.Time{
+func (t *MockTimer) GetC() <-chan time.Time {
 	return t.c
 }
 
-func (t *MockTimer) Stop() bool{
+func (t *MockTimer) Stop() bool {
 	t.createdAt = 0
 	return true
 }
 
-func (t *MockTimer) SetDuration(d int){
+func (t *MockTimer) SetDuration(d int) {
 	t.duration = int64(d)
 	t.createdAt = GetMockNow()
 	Log.Debugf("reset timer created at %v", t.createdAt)
 }
 
-func (t *MockTimer) Reset(d time.Duration) bool{
+func (t *MockTimer) Reset(d time.Duration) bool {
 	Log.Debugln("reset timer")
-	t.SetDuration(int(d.Nanoseconds()/1e6))
+	t.SetDuration(int(d.Nanoseconds() / 1e6))
 	return true
 }
 
@@ -153,7 +153,7 @@ func (t *MockTimer) Trigger(ti int64) {
 
 func (t *MockTimer) DoTick(c int64) {
 	Log.Debugf("do tick at %d, created at %v", c, t.createdAt)
-	if t.createdAt > 0 && c >= (t.createdAt + t.duration){
+	if t.createdAt > 0 && c >= (t.createdAt+t.duration) {
 		Log.Info("trigger timer")
 		t.Trigger(t.createdAt + t.duration)
 	}

+ 2 - 3
common/plugin_manager/manager.go

@@ -10,7 +10,7 @@ import (
 
 var registry map[string]plugin.Symbol
 
-func init(){
+func init() {
 	registry = make(map[string]plugin.Symbol)
 }
 
@@ -24,7 +24,7 @@ func GetPlugin(t string, ptype string) (plugin.Symbol, error) {
 		if err != nil {
 			return nil, fmt.Errorf("cannot find the plugins folder")
 		}
-		mod := path.Join(loc, ptype, t +".so")
+		mod := path.Join(loc, ptype, t+".so")
 		plug, err := plugin.Open(mod)
 		if err != nil {
 			return nil, fmt.Errorf("cannot open %s: %v", mod, err)
@@ -43,4 +43,3 @@ func ucFirst(str string) string {
 	}
 	return ""
 }
-

+ 4 - 4
common/templates/funcs.go

@@ -5,10 +5,10 @@ import (
 )
 
 //Use the name json in func map
-func JsonMarshal(v interface {}) (string, error) {
-	if a, err := json.Marshal(v); err != nil{
+func JsonMarshal(v interface{}) (string, error) {
+	if a, err := json.Marshal(v); err != nil {
 		return "", err
-	}else{
+	} else {
 		return string(a), nil
 	}
-}
+}

+ 24 - 24
common/time_util.go

@@ -66,14 +66,14 @@ func InterfaceToUnixMilli(i interface{}, format string) (int64, error) {
 		var ti time.Time
 		var err error
 		var f = JSISO
-		if format != ""{
+		if format != "" {
 			f, err = convertFormat(format)
-			if err != nil{
+			if err != nil {
 				return 0, err
 			}
 		}
 		ti, err = time.Parse(f, t)
-		if err != nil{
+		if err != nil {
 			return 0, err
 		}
 		return TimeToUnixMilli(ti), nil
@@ -96,14 +96,14 @@ func InterfaceToTime(i interface{}, format string) (time.Time, error) {
 		var ti time.Time
 		var err error
 		var f = JSISO
-		if format != ""{
+		if format != "" {
 			f, err = convertFormat(format)
-			if err != nil{
+			if err != nil {
 				return ti, err
 			}
 		}
 		ti, err = time.Parse(f, t)
-		if err != nil{
+		if err != nil {
 			return ti, err
 		}
 		return ti, nil
@@ -116,18 +116,18 @@ func TimeFromUnixMilli(t int64) time.Time {
 	return time.Unix(t/1000, t%1000).UTC()
 }
 
-func ParseTime(t string, f string) (time.Time, error){
-	if f, err := convertFormat(f); err != nil{
+func ParseTime(t string, f string) (time.Time, error) {
+	if f, err := convertFormat(f); err != nil {
 		return time.Now(), err
-	}else{
+	} else {
 		return time.Parse(f, t)
 	}
 }
 
-func FormatTime(time time.Time, f string) (string, error){
-	if f, err := convertFormat(f); err != nil{
+func FormatTime(time time.Time, f string) (string, error) {
+	if f, err := convertFormat(f); err != nil {
 		return "", err
-	}else{
+	} else {
 		return time.Format(f), nil
 	}
 }
@@ -144,7 +144,7 @@ func FormatTime(time time.Time, f string) (string, error){
 //	return f
 //}
 
-func convertFormat(f string) (string, error){
+func convertFormat(f string) (string, error) {
 	formatRune := []rune(f)
 	lenFormat := len(formatRune)
 	out := ""
@@ -152,7 +152,7 @@ func convertFormat(f string) (string, error){
 		switch r := formatRune[i]; r {
 		case 'Y', 'y':
 			j := 1
-			for ; i+j < lenFormat && j<=4; j++ {
+			for ; i+j < lenFormat && j <= 4; j++ {
 				if formatRune[i+j] != r {
 					break
 				}
@@ -170,7 +170,7 @@ func convertFormat(f string) (string, error){
 			out += "AD"
 		case 'M': // M MM MMM MMMM month of year
 			j := 1
-			for ; i+j < lenFormat && j<=4; j++ {
+			for ; i+j < lenFormat && j <= 4; j++ {
 				if formatRune[i+j] != r {
 					break
 				}
@@ -188,7 +188,7 @@ func convertFormat(f string) (string, error){
 			}
 		case 'd': // d dd day of month
 			j := 1
-			for ; i+j < lenFormat && j<=2; j++ {
+			for ; i+j < lenFormat && j <= 2; j++ {
 				if formatRune[i+j] != r {
 					break
 				}
@@ -203,7 +203,7 @@ func convertFormat(f string) (string, error){
 			}
 		case 'E': // M MM MMM MMMM month of year
 			j := 1
-			for ; i+j < lenFormat && j<=4; j++ {
+			for ; i+j < lenFormat && j <= 4; j++ {
 				if formatRune[i+j] != r {
 					break
 				}
@@ -219,7 +219,7 @@ func convertFormat(f string) (string, error){
 			}
 		case 'H': // HH
 			j := 1
-			for ; i+j < lenFormat && j<=2; j++ {
+			for ; i+j < lenFormat && j <= 2; j++ {
 				if formatRune[i+j] != r {
 					break
 				}
@@ -234,14 +234,14 @@ func convertFormat(f string) (string, error){
 			}
 		case 'h': // h hh
 			j := 1
-			for ; i+j < lenFormat && j<=2; j++ {
+			for ; i+j < lenFormat && j <= 2; j++ {
 				if formatRune[i+j] != r {
 					break
 				}
 			}
 			i = i + j - 1
 			switch j {
-			case 1:  // h
+			case 1: // h
 				out += "3"
 			case 2: // hh
 				out += "03"
@@ -265,7 +265,7 @@ func convertFormat(f string) (string, error){
 			}
 		case 's': // s ss
 			j := 1
-			for ; i+j < lenFormat && j<=2 ; j++ {
+			for ; i+j < lenFormat && j <= 2; j++ {
 				if formatRune[i+j] != r {
 					break
 				}
@@ -281,7 +281,7 @@ func convertFormat(f string) (string, error){
 
 		case 'S': // S SS SSS
 			j := 1
-			for ; i+j < lenFormat && j<=3; j++ {
+			for ; i+j < lenFormat && j <= 3; j++ {
 				if formatRune[i+j] != r {
 					break
 				}
@@ -301,7 +301,7 @@ func convertFormat(f string) (string, error){
 			out += "-0700"
 		case 'X': // X XX XXX
 			j := 1
-			for ; i+j < lenFormat && j<=3; j++ {
+			for ; i+j < lenFormat && j <= 3; j++ {
 				if formatRune[i+j] != r {
 					break
 				}
@@ -340,4 +340,4 @@ func convertFormat(f string) (string, error){
 		}
 	}
 	return out, nil
-}
+}

+ 48 - 48
common/util.go

@@ -16,23 +16,22 @@ import (
 
 const (
 	logFileName = "stream.log"
-	etc_dir = "/etc/"
-	data_dir = "/data/"
-	log_dir = "/log/"
+	etc_dir     = "/etc/"
+	data_dir    = "/data/"
+	log_dir     = "/log/"
 )
 
 var (
-	Log *logrus.Logger
-	Config *XStreamConf
-	IsTesting bool
-	logFile *os.File
+	Log        *logrus.Logger
+	Config     *XStreamConf
+	IsTesting  bool
+	logFile    *os.File
 	mockTicker *MockTicker
-	mockTimer *MockTimer
-	mockNow int64
+	mockTimer  *MockTimer
+	mockNow    int64
 )
 
 type logRedirect struct {
-
 }
 
 func (l *logRedirect) Errorf(f string, v ...interface{}) {
@@ -66,15 +65,17 @@ func LoadConf(confName string) ([]byte, error) {
 }
 
 type XStreamConf struct {
-	Debug bool `yaml:"debug"`
-	Port int `yaml:"port"`
-	Prometheus bool `yaml:"prometheus"`
-	PrometheusPort int `yaml:"prometheusPort"`
+	Debug          bool `yaml:"debug"`
+	Port           int  `yaml:"port"`
+	Prometheus     bool `yaml:"prometheus"`
+	PrometheusPort int  `yaml:"prometheusPort"`
 }
 
 var StreamConf = "kuiper.yaml"
+
 const KuiperBaseKey = "KuiperBaseKey"
-func init(){
+
+func init() {
 	Log = logrus.New()
 	Log.SetFormatter(&logrus.TextFormatter{
 		DisableColors: true,
@@ -92,7 +93,7 @@ func InitConf() {
 		Log.Fatal(err)
 	}
 
-	if c, ok := cfg["basic"]; !ok{
+	if c, ok := cfg["basic"]; !ok {
 		Log.Fatal("No basic config in kuiper.yaml")
 	} else {
 		Config = &c
@@ -127,10 +128,9 @@ type KeyValue interface {
 
 type SimpleKVStore struct {
 	path string
-	c *cache.Cache;
+	c    *cache.Cache
 }
 
-
 var stores = make(map[string]*SimpleKVStore)
 
 func GetSimpleKVStore(path string) *SimpleKVStore {
@@ -147,7 +147,7 @@ func GetSimpleKVStore(path string) *SimpleKVStore {
 	}
 }
 
-func (m *SimpleKVStore) Open() error  {
+func (m *SimpleKVStore) Open() error {
 	if _, err := os.Stat(m.path); os.IsNotExist(err) {
 		return nil
 	}
@@ -157,7 +157,7 @@ func (m *SimpleKVStore) Open() error  {
 	return nil
 }
 
-func (m *SimpleKVStore) Close() error  {
+func (m *SimpleKVStore) Close() error {
 	e := m.saveToFile()
 	m.c.Flush() //Delete all of the values from memory.
 	return e
@@ -170,7 +170,7 @@ func (m *SimpleKVStore) saveToFile() error {
 	return nil
 }
 
-func (m *SimpleKVStore) Set(key string, value interface{}) error  {
+func (m *SimpleKVStore) Set(key string, value interface{}) error {
 	if m.c == nil {
 		return fmt.Errorf("cache %s has not been initialized yet", m.path)
 	}
@@ -180,7 +180,7 @@ func (m *SimpleKVStore) Set(key string, value interface{}) error  {
 	return m.saveToFile()
 }
 
-func (m *SimpleKVStore) Replace(key string, value interface{}) error  {
+func (m *SimpleKVStore) Replace(key string, value interface{}) error {
 	if m.c == nil {
 		return fmt.Errorf("cache %s has not been initialized yet", m.path)
 	}
@@ -188,7 +188,7 @@ func (m *SimpleKVStore) Replace(key string, value interface{}) error  {
 	return m.saveToFile()
 }
 
-func (m *SimpleKVStore) Get(key string) (interface{}, bool)  {
+func (m *SimpleKVStore) Get(key string) (interface{}, bool) {
 	return m.c.Get(key)
 }
 
@@ -198,7 +198,7 @@ func (m *SimpleKVStore) Delete(key string) error {
 	}
 	if _, found := m.c.Get(key); found {
 		m.c.Delete(key)
-	}else{
+	} else {
 		return fmt.Errorf("%s is not found", key)
 	}
 	return m.saveToFile()
@@ -223,13 +223,13 @@ func PrintMap(m map[string]string, buff *bytes.Buffer) {
 	}
 }
 
-func CloseLogger(){
+func CloseLogger() {
 	if logFile != nil {
 		logFile.Close()
 	}
 }
 
-func GetConfLoc()(string, error){
+func GetConfLoc() (string, error) {
 	return GetLoc(etc_dir)
 }
 
@@ -237,7 +237,7 @@ func GetDataLoc() (string, error) {
 	return GetLoc(data_dir)
 }
 
-func GetLoc(subdir string)(string, error) {
+func GetLoc(subdir string) (string, error) {
 	dir, err := os.Getwd()
 	if err != nil {
 		return "", err
@@ -290,35 +290,35 @@ func GetAndCreateDataLoc(dir string) (string, error) {
 
 //Time related. For Mock
 func GetTicker(duration int) Ticker {
-	if IsTesting{
-		if mockTicker == nil{
+	if IsTesting {
+		if mockTicker == nil {
 			mockTicker = NewMockTicker(duration)
-		}else{
+		} else {
 			mockTicker.SetDuration(duration)
 		}
 		return mockTicker
-	}else{
+	} else {
 		return NewDefaultTicker(duration)
 	}
 }
 
 func GetTimer(duration int) Timer {
-	if IsTesting{
-		if mockTimer == nil{
+	if IsTesting {
+		if mockTimer == nil {
 			mockTimer = NewMockTimer(duration)
-		}else{
+		} else {
 			mockTimer.SetDuration(duration)
 		}
 		return mockTimer
-	}else{
+	} else {
 		return NewDefaultTimer(duration)
 	}
 }
 
-func GetNowInMilli() int64{
+func GetNowInMilli() int64 {
 	if IsTesting {
 		return GetMockNow()
-	}else{
+	} else {
 		return TimeToUnixMilli(time.Now())
 	}
 }
@@ -328,41 +328,41 @@ func ProcessPath(p string) (string, error) {
 		return "", nil
 	} else {
 		if _, err := os.Stat(abs); os.IsNotExist(err) {
-			return "", err;
+			return "", err
 		}
 		return abs, nil
 	}
 }
 
 /****** For Test Only ********/
-func GetMockTicker() *MockTicker{
+func GetMockTicker() *MockTicker {
 	return mockTicker
 }
 
-func ResetMockTicker(){
-	if mockTicker != nil{
+func ResetMockTicker() {
+	if mockTicker != nil {
 		mockTicker.lastTick = 0
 	}
 }
 
-func GetMockTimer() *MockTimer{
+func GetMockTimer() *MockTimer {
 	return mockTimer
 }
 
-func SetMockNow(now int64){
+func SetMockNow(now int64) {
 	mockNow = now
 }
 
-func GetMockNow() int64{
+func GetMockNow() int64 {
 	return mockNow
 }
 
 /*********** Type Cast Utilities *****/
 //TODO datetime type
-func ToString(input interface{}) string{
+func ToString(input interface{}) string {
 	return fmt.Sprintf("%v", input)
 }
-func ToInt(input interface{}) (int, error){
+func ToInt(input interface{}) (int, error) {
 	switch t := input.(type) {
 	case float64:
 		return int(t), nil
@@ -379,10 +379,10 @@ func ToInt(input interface{}) (int, error){
 *   Convert a map into a struct. The output parameter must be a pointer to a struct
 *   The struct can have the json meta data
  */
-func MapToStruct(input map[string]interface{}, output interface{}) error{
+func MapToStruct(input map[string]interface{}, output interface{}) error {
 	// convert map to json
 	jsonString, err := json.Marshal(input)
-	if err != nil{
+	if err != nil {
 		return err
 	}
 

+ 3 - 3
common/util_test.go

@@ -9,7 +9,7 @@ import (
 
 func TestSimpleKVStore_Funcs(t *testing.T) {
 	abs, _ := filepath.Abs("test.data")
-	if f, _ := os.Stat(abs); f != nil{
+	if f, _ := os.Stat(abs); f != nil {
 		_ = os.Remove(abs)
 	}
 
@@ -22,7 +22,7 @@ func TestSimpleKVStore_Funcs(t *testing.T) {
 	v, _ := ks.Get("foo")
 	reflect.DeepEqual("bar", v)
 
-	_= ks.Set("foo1", "bar1")
+	_ = ks.Set("foo1", "bar1")
 	v1, _ := ks.Get("foo1")
 	reflect.DeepEqual("bar1", v1)
 
@@ -56,4 +56,4 @@ func TestSimpleKVStore_Funcs(t *testing.T) {
 	}
 
 	_ = os.Remove(abs)
-}
+}

+ 11 - 11
common/utils/dynamic_channel_buffer.go

@@ -1,24 +1,24 @@
 package utils
 
 type DynamicChannelBuffer struct {
-	In chan interface{}
-	Out chan interface{}
+	In     chan interface{}
+	Out    chan interface{}
 	buffer []interface{}
-	limit int
+	limit  int
 }
 
 func NewDynamicChannelBuffer() *DynamicChannelBuffer {
 	buffer := &DynamicChannelBuffer{
-		In: make(chan interface{}),
-		Out: make(chan interface{}),
+		In:     make(chan interface{}),
+		Out:    make(chan interface{}),
 		buffer: make([]interface{}, 0),
-		limit: 102400,
+		limit:  102400,
 	}
 	go buffer.run()
 	return buffer
 }
 
-func (b *DynamicChannelBuffer) SetLimit(limit int){
+func (b *DynamicChannelBuffer) SetLimit(limit int) {
 	if limit > 0 {
 		b.limit = limit
 	}
@@ -27,18 +27,18 @@ func (b *DynamicChannelBuffer) SetLimit(limit int){
 func (b *DynamicChannelBuffer) run() {
 	for {
 		l := len(b.buffer)
-		if l >= b.limit{
+		if l >= b.limit {
 			b.Out <- b.buffer[0]
 			b.buffer = b.buffer[1:]
-		}else if l > 0 {
+		} else if l > 0 {
 			select {
 			case b.Out <- b.buffer[0]:
 				b.buffer = b.buffer[1:]
-			case value := <- b.In:
+			case value := <-b.In:
 				b.buffer = append(b.buffer, value)
 			}
 		} else {
-			value := <- b.In
+			value := <-b.In
 			b.buffer = append(b.buffer, value)
 		}
 	}

+ 3 - 3
plugins/functions/countPlusOne.go

@@ -5,8 +5,8 @@ import "fmt"
 type countPlusOneFunc struct {
 }
 
-func (f *countPlusOneFunc) Validate(args []interface{}) error{
-	if len(args) != 1{
+func (f *countPlusOneFunc) Validate(args []interface{}) error {
+	if len(args) != 1 {
 		return fmt.Errorf("countPlusOne function only supports 1 parameter but got %d", len(args))
 	}
 	return nil
@@ -14,7 +14,7 @@ func (f *countPlusOneFunc) Validate(args []interface{}) error{
 
 func (f *countPlusOneFunc) Exec(args []interface{}) (interface{}, bool) {
 	arg, ok := args[0].([]interface{})
-	if !ok{
+	if !ok {
 		return fmt.Errorf("arg is not a slice, got %v", args[0]), false
 	}
 	return len(arg) + 1, true

+ 2 - 2
plugins/functions/echo.go

@@ -7,8 +7,8 @@ import (
 type echo struct {
 }
 
-func (f *echo) Validate(args []interface{}) error{
-	if len(args) != 1{
+func (f *echo) Validate(args []interface{}) error {
+	if len(args) != 1 {
 		return fmt.Errorf("echo function only supports 1 parameter but got %d", len(args))
 	}
 	return nil

+ 13 - 13
plugins/sinks/file.go

@@ -12,12 +12,12 @@ import (
 
 type fileSink struct {
 	interval int
-	path string
+	path     string
 
-	results  [][]byte
-	file *os.File
-	mux sync.Mutex
-	cancel context.CancelFunc
+	results [][]byte
+	file    *os.File
+	mux     sync.Mutex
+	cancel  context.CancelFunc
 }
 
 func (m *fileSink) Configure(props map[string]interface{}) error {
@@ -46,18 +46,18 @@ func (m *fileSink) Open(ctx api.StreamContext) error {
 		_, err = os.Create(m.path)
 	}
 	f, err = os.OpenFile(m.path, os.O_APPEND|os.O_WRONLY, os.ModeAppend)
-	if err != nil{
+	if err != nil {
 		return fmt.Errorf("fail to open file sink for %v", err)
 	}
 	m.file = f
 	t := time.NewTicker(time.Duration(m.interval) * time.Millisecond)
 	exeCtx, cancel := ctx.WithCancel()
 	m.cancel = cancel
-	go func(){
+	go func() {
 		defer t.Stop()
-		for{
-			select{
-			case <- t.C:
+		for {
+			select {
+			case <-t.C:
 				m.save(logger)
 			case <-exeCtx.Done():
 				logger.Info("file sink done")
@@ -98,7 +98,7 @@ func (m *fileSink) Collect(ctx api.StreamContext, item interface{}) error {
 		m.mux.Lock()
 		m.results = append(m.results, v)
 		m.mux.Unlock()
-	}else{
+	} else {
 		logger.Debug("file sink receive non byte data")
 	}
 	return nil
@@ -108,11 +108,11 @@ func (m *fileSink) Close(ctx api.StreamContext) error {
 	if m.cancel != nil {
 		m.cancel()
 	}
-	if m.file != nil{
+	if m.file != nil {
 		m.save(ctx.GetLogger())
 		return m.file.Close()
 	}
 	return nil
 }
 
-var File fileSink
+var File fileSink

+ 3 - 4
plugins/sinks/memory.go

@@ -3,7 +3,7 @@ package main
 import "github.com/emqx/kuiper/xstream/api"
 
 type memory struct {
-	results  [][]byte
+	results [][]byte
 }
 
 func (m *memory) Open(ctx api.StreamContext) error {
@@ -18,7 +18,7 @@ func (m *memory) Collect(ctx api.StreamContext, item interface{}) error {
 	if v, ok := item.([]byte); ok {
 		logger.Debugf("memory sink receive %s", item)
 		m.results = append(m.results, v)
-	}else{
+	} else {
 		logger.Debug("memory sink receive non byte data")
 	}
 	return nil
@@ -29,9 +29,8 @@ func (m *memory) Close(ctx api.StreamContext) error {
 	return nil
 }
 
-
 func (m *memory) Configure(props map[string]interface{}) error {
 	return nil
 }
 
-var Memory memory
+var Memory memory

+ 12 - 13
plugins/sinks/zmq.go

@@ -8,11 +8,10 @@ import (
 
 type zmqSink struct {
 	publisher *zmq.Socket
-	srv string
-	topic string
+	srv       string
+	topic     string
 }
 
-
 func (m *zmqSink) Configure(props map[string]interface{}) error {
 	srv, ok := props["server"]
 	if !ok {
@@ -22,10 +21,10 @@ func (m *zmqSink) Configure(props map[string]interface{}) error {
 	if !ok {
 		return fmt.Errorf("zmq source property server %v is not a string", srv)
 	}
-	if tpc, ok := props["topic"]; ok{
-		if t, ok := tpc.(string); !ok{
+	if tpc, ok := props["topic"]; ok {
+		if t, ok := tpc.(string); !ok {
 			return fmt.Errorf("zmq source property topic %v is not a string", tpc)
-		}else{
+		} else {
 			m.topic = t
 		}
 	}
@@ -40,11 +39,11 @@ func (m *zmqSink) Configure(props map[string]interface{}) error {
 func (m *zmqSink) Open(ctx api.StreamContext) (err error) {
 	logger := ctx.GetLogger()
 	m.publisher, err = zmq.NewSocket(zmq.PUB)
-	if err != nil{
+	if err != nil {
 		return fmt.Errorf("zmq sink fails to create socket: %v", err)
 	}
 	err = m.publisher.Bind(m.srv)
-	if err != nil{
+	if err != nil {
 		return fmt.Errorf("zmq sink fails to bind to %s: %v", m.srv, err)
 	}
 	logger.Debugf("zmq sink open")
@@ -55,26 +54,26 @@ func (m *zmqSink) Collect(ctx api.StreamContext, item interface{}) (err error) {
 	logger := ctx.GetLogger()
 	if v, ok := item.([]byte); ok {
 		logger.Debugf("zmq sink receive %s", item)
-		if m.topic == ""{
+		if m.topic == "" {
 			_, err = m.publisher.Send(string(v), 0)
-		}else{
+		} else {
 			msgs := []string{
 				m.topic,
 				string(v),
 			}
 			_, err = m.publisher.SendMessage(msgs)
 		}
-	}else{
+	} else {
 		logger.Debug("zmq sink receive non byte data %v", item)
 	}
-	if err != nil{
+	if err != nil {
 		logger.Debugf("send to zmq error %v", err)
 	}
 	return
 }
 
 func (m *zmqSink) Close(ctx api.StreamContext) error {
-	if m.publisher != nil{
+	if m.publisher != nil {
 		return m.publisher.Close()
 	}
 	return nil

+ 20 - 20
plugins/sources/random.go

@@ -10,26 +10,26 @@ import (
 //Emit data randomly with only a string field
 type randomSource struct {
 	interval int
-	seed int
-	pattern map[string]interface{}
-	cancel context.CancelFunc
+	seed     int
+	pattern  map[string]interface{}
+	cancel   context.CancelFunc
 }
 
-func (s *randomSource) Configure(topic string, props map[string]interface{}) error{
-	if i, ok := props["interval"].(float64); ok{
+func (s *randomSource) Configure(topic string, props map[string]interface{}) error {
+	if i, ok := props["interval"].(float64); ok {
 		s.interval = int(i)
-	}else{
+	} else {
 		s.interval = 1000
 	}
-	if p, ok := props["pattern"].(map[string]interface{}); ok{
+	if p, ok := props["pattern"].(map[string]interface{}); ok {
 		s.pattern = p
-	}else{
+	} else {
 		s.pattern = make(map[string]interface{})
 		s.pattern["count"] = 50
 	}
-	if i, ok := props["seed"].(float64); ok{
+	if i, ok := props["seed"].(float64); ok {
 		s.seed = int(i)
-	}else{
+	} else {
 		s.seed = 1
 	}
 	return nil
@@ -39,13 +39,13 @@ func (s *randomSource) Open(ctx api.StreamContext, consume api.ConsumeFunc) (err
 	t := time.NewTicker(time.Duration(s.interval) * time.Millisecond)
 	exeCtx, cancel := ctx.WithCancel()
 	s.cancel = cancel
-	go func(exeCtx api.StreamContext){
+	go func(exeCtx api.StreamContext) {
 		defer t.Stop()
-		for{
-			select{
-			case <- t.C:
+		for {
+			select {
+			case <-t.C:
 				consume(randomize(s.pattern, s.seed), nil)
-			case <- exeCtx.Done():
+			case <-exeCtx.Done():
 				return
 			}
 		}
@@ -53,20 +53,20 @@ func (s *randomSource) Open(ctx api.StreamContext, consume api.ConsumeFunc) (err
 	return nil
 }
 
-func randomize(p map[string]interface{}, seed int) map[string]interface{}{
+func randomize(p map[string]interface{}, seed int) map[string]interface{} {
 	r := make(map[string]interface{})
-	for k, v := range p{
+	for k, v := range p {
 		vi := v.(int)
 		r[k] = vi + rand.Intn(seed)
 	}
 	return r
 }
 
-func (s *randomSource) Close(ctx api.StreamContext) error{
-	if s.cancel != nil{
+func (s *randomSource) Close(ctx api.StreamContext) error {
+	if s.cancel != nil {
 		s.cancel()
 	}
 	return nil
 }
 
-var Random randomSource
+var Random randomSource

+ 14 - 14
plugins/sources/zmq.go

@@ -9,11 +9,11 @@ import (
 
 type zmqSource struct {
 	subscriber *zmq.Socket
-	srv string
-	topic string
+	srv        string
+	topic      string
 }
 
-func (s *zmqSource) Configure(topic string, props map[string]interface{}) error{
+func (s *zmqSource) Configure(topic string, props map[string]interface{}) error {
 	s.topic = topic
 	srv, ok := props["server"]
 	if !ok {
@@ -26,16 +26,16 @@ func (s *zmqSource) Configure(topic string, props map[string]interface{}) error{
 func (s *zmqSource) Open(ctx api.StreamContext, consume api.ConsumeFunc) (err error) {
 	logger := ctx.GetLogger()
 	s.subscriber, err = zmq.NewSocket(zmq.SUB)
-	if err != nil{
+	if err != nil {
 		return fmt.Errorf("zmq source fails to create socket: %v", err)
 	}
 	err = s.subscriber.Connect(s.srv)
-	if err != nil{
+	if err != nil {
 		return fmt.Errorf("zmq source fails to connect to %s: %v", s.srv, err)
 	}
 	s.subscriber.SetSubscribe(s.topic)
 	logger.Debugf("zmq source subscribe to topic %s", s.topic)
-	go func(){
+	go func() {
 		logger.Debugf("start to listen")
 		for {
 			msgs, err := s.subscriber.RecvMessage(0)
@@ -45,25 +45,25 @@ func (s *zmqSource) Open(ctx api.StreamContext, consume api.ConsumeFunc) (err er
 			} else {
 				logger.Debugf("zmq source receive %v", msgs)
 				var m string
-				for i, msg := range msgs{
-					if i == 0 && s.topic != ""{
+				for i, msg := range msgs {
+					if i == 0 && s.topic != "" {
 						continue
 					}
 					m += msg
 				}
 				meta := make(map[string]interface{})
-				if s.topic != ""{
+				if s.topic != "" {
 					meta["topic"] = msgs[0]
 				}
 				result := make(map[string]interface{})
 				if e := json.Unmarshal([]byte(m), &result); e != nil {
 					logger.Warnf("zmq source message %s is not json", m)
-				}else{
+				} else {
 					consume(result, meta)
 				}
 			}
-			select{
-			case <- ctx.Done():
+			select {
+			case <-ctx.Done():
 				logger.Infof("zmq source done")
 				return
 			default:
@@ -74,8 +74,8 @@ func (s *zmqSource) Open(ctx api.StreamContext, consume api.ConsumeFunc) (err er
 	return nil
 }
 
-func (s *zmqSource) Close(ctx api.StreamContext) error{
-	if s.subscriber != nil{
+func (s *zmqSource) Close(ctx api.StreamContext) error {
+	if s.subscriber != nil {
 		return s.subscriber.Close()
 	}
 	return nil

+ 101 - 104
xsql/ast.go

@@ -11,8 +11,6 @@ import (
 	"time"
 )
 
-
-
 type Node interface {
 	node()
 }
@@ -35,18 +33,18 @@ type Source interface {
 
 type Sources []Source
 
-func (ss Sources) node(){}
+func (ss Sources) node() {}
 
 type Table struct {
-	Name string
+	Name  string
 	Alias string
 }
 
 func (t *Table) source() {}
-func (ss *Table) node(){}
-
+func (ss *Table) node()  {}
 
 type JoinType int
+
 const (
 	LEFT_JOIN JoinType = iota
 	INNER_JOIN
@@ -63,12 +61,13 @@ type Join struct {
 }
 
 func (j *Join) source() {}
-func (ss *Join) node(){}
+func (ss *Join) node()  {}
 
 type Joins []Join
-func (ss Joins) node(){}
 
-type Statement interface{
+func (ss Joins) node() {}
+
+type Statement interface {
 	Stmt()
 	Node
 }
@@ -79,12 +78,12 @@ type SelectStatement struct {
 	Joins      Joins
 	Condition  Expr
 	Dimensions Dimensions
-	Having	   Expr
+	Having     Expr
 	SortFields SortFields
 }
 
 func (ss *SelectStatement) Stmt() {}
-func (ss *SelectStatement) node(){}
+func (ss *SelectStatement) node() {}
 
 type Literal interface {
 	Expr
@@ -105,7 +104,7 @@ type BracketExpr struct {
 
 type ColonExpr struct {
 	Start int
-	End int
+	End   int
 }
 
 type IndexExpr struct {
@@ -141,7 +140,7 @@ type Dimension struct {
 }
 
 type SortField struct {
-	Name string
+	Name      string
 	Ascending bool
 }
 
@@ -150,62 +149,62 @@ type SortFields []SortField
 type Dimensions []Dimension
 
 func (f *Field) expr() {}
-func (f *Field) node(){}
+func (f *Field) node() {}
 
 func (pe *ParenExpr) expr() {}
-func (pe *ParenExpr) node(){}
+func (pe *ParenExpr) node() {}
 
 func (ae *ArrowExpr) expr() {}
-func (ae *ArrowExpr) node(){}
+func (ae *ArrowExpr) node() {}
 
 func (be *BracketExpr) expr() {}
-func (be *BracketExpr) node(){}
+func (be *BracketExpr) node() {}
 
 func (be *ColonExpr) expr() {}
-func (be *ColonExpr) node(){}
+func (be *ColonExpr) node() {}
 
 func (be *IndexExpr) expr() {}
-func (be *IndexExpr) node(){}
+func (be *IndexExpr) node() {}
 
 func (w *Wildcard) expr() {}
-func (w *Wildcard) node(){}
+func (w *Wildcard) node() {}
 
 func (bl *BooleanLiteral) expr()    {}
 func (bl *BooleanLiteral) literal() {}
-func (bl *BooleanLiteral) node(){}
+func (bl *BooleanLiteral) node()    {}
 
 func (tl *TimeLiteral) expr()    {}
 func (tl *TimeLiteral) literal() {}
-func (tl *TimeLiteral) node(){}
+func (tl *TimeLiteral) node()    {}
 
 func (il *IntegerLiteral) expr()    {}
 func (il *IntegerLiteral) literal() {}
-func (il *IntegerLiteral) node(){}
+func (il *IntegerLiteral) node()    {}
 
 func (nl *NumberLiteral) expr()    {}
 func (nl *NumberLiteral) literal() {}
-func (nl *NumberLiteral) node(){}
+func (nl *NumberLiteral) node()    {}
 
 func (sl *StringLiteral) expr()    {}
 func (sl *StringLiteral) literal() {}
-func (sl *StringLiteral) node(){}
+func (sl *StringLiteral) node()    {}
 
 func (d *Dimension) expr() {}
-func (d *Dimension) node(){}
+func (d *Dimension) node() {}
 
-func (d Dimensions) node(){}
-func (d *Dimensions) GetWindow() *Window{
+func (d Dimensions) node() {}
+func (d *Dimensions) GetWindow() *Window {
 	for _, child := range *d {
-		if w, ok := child.Expr.(*Window); ok{
+		if w, ok := child.Expr.(*Window); ok {
 			return w
 		}
 	}
 	return nil
 }
-func (d *Dimensions) GetGroups() Dimensions{
+func (d *Dimensions) GetGroups() Dimensions {
 	var nd Dimensions
 	for _, child := range *d {
-		if _, ok := child.Expr.(*Window); !ok{
+		if _, ok := child.Expr.(*Window); !ok {
 			nd = append(nd, child)
 		}
 	}
@@ -213,18 +212,18 @@ func (d *Dimensions) GetGroups() Dimensions{
 }
 
 func (sf *SortField) expr() {}
-func (sf *SortField) node(){}
+func (sf *SortField) node() {}
 
-func (sf SortFields) node(){}
+func (sf SortFields) node() {}
 
 type Call struct {
 	Name string
 	Args []Expr
 }
 
-func (c *Call) expr() {}
+func (c *Call) expr()    {}
 func (c *Call) literal() {}
-func (c *Call) node(){}
+func (c *Call) node()    {}
 
 type WindowType int
 
@@ -238,7 +237,7 @@ const (
 
 type Window struct {
 	WindowType WindowType
-	Length	   *IntegerLiteral
+	Length     *IntegerLiteral
 	Interval   *IntegerLiteral
 }
 
@@ -246,48 +245,49 @@ func (w *Window) expr()    {}
 func (w *Window) literal() {}
 func (w *Window) node()    {}
 
-type  SelectStatements []SelectStatement
+type SelectStatements []SelectStatement
 
-func (ss *SelectStatements) node(){}
+func (ss *SelectStatements) node() {}
 
 type Fields []Field
-func (fs Fields) node(){}
+
+func (fs Fields) node() {}
 
 type BinaryExpr struct {
-	OP Token
+	OP  Token
 	LHS Expr
 	RHS Expr
 }
 
 func (fe *BinaryExpr) expr() {}
-func (be *BinaryExpr) node(){}
+func (be *BinaryExpr) node() {}
 
 type FieldRef struct {
 	StreamName StreamName
-	Name  string
+	Name       string
 }
 
 func (fr *FieldRef) expr() {}
-func (fr *FieldRef) node(){}
-
+func (fr *FieldRef) node() {}
 
 // The stream AST tree
 type Options map[string]string
+
 func (o Options) node() {}
 
 type StreamName string
+
 func (sn *StreamName) node() {}
 
 type StreamStmt struct {
-	Name StreamName
+	Name         StreamName
 	StreamFields StreamFields
-	Options Options
+	Options      Options
 }
 
-func (ss *StreamStmt) node(){}
+func (ss *StreamStmt) node() {}
 func (ss *StreamStmt) Stmt() {}
 
-
 type FieldType interface {
 	fieldType()
 	Node
@@ -300,29 +300,31 @@ type StreamField struct {
 
 type StreamFields []StreamField
 
-func (sf StreamFields) node(){}
+func (sf StreamFields) node() {}
 
 type BasicType struct {
 	Type DataType
 }
+
 func (bt *BasicType) fieldType() {}
-func (bt *BasicType) node(){}
+func (bt *BasicType) node()      {}
 
 type ArrayType struct {
 	Type DataType
 	FieldType
 }
+
 func (at *ArrayType) fieldType() {}
-func (at *ArrayType) node(){}
+func (at *ArrayType) node()      {}
 
 type RecType struct {
 	StreamFields StreamFields
 }
+
 func (rt *RecType) fieldType() {}
-func (rt *RecType) node(){}
+func (rt *RecType) node()      {}
 
 type ShowStreamsStatement struct {
-
 }
 
 type DescribeStreamStatement struct {
@@ -338,17 +340,16 @@ type DropStreamStatement struct {
 }
 
 func (ss *ShowStreamsStatement) Stmt() {}
-func (ss *ShowStreamsStatement) node(){}
+func (ss *ShowStreamsStatement) node() {}
 
 func (dss *DescribeStreamStatement) Stmt() {}
-func (dss *DescribeStreamStatement) node(){}
+func (dss *DescribeStreamStatement) node() {}
 
 func (ess *ExplainStreamStatement) Stmt() {}
-func (ess *ExplainStreamStatement) node(){}
+func (ess *ExplainStreamStatement) node() {}
 
 func (dss *DropStreamStatement) Stmt() {}
-func (dss *DropStreamStatement) node(){}
-
+func (dss *DropStreamStatement) node() {}
 
 type Visitor interface {
 	Visit(Node) Visitor
@@ -442,7 +443,6 @@ func Walk(v Visitor, node Node) {
 	}
 }
 
-
 // WalkFunc traverses a node hierarchy in depth-first order.
 func WalkFunc(node Node, fn func(Node)) {
 	Walk(walkFuncVisitor(fn), node)
@@ -452,14 +452,12 @@ type walkFuncVisitor func(Node)
 
 func (fn walkFuncVisitor) Visit(n Node) Visitor { fn(n); return fn }
 
-
 // Valuer is the interface that wraps the Value() method.
 type Valuer interface {
 	// Value returns the value and existence flag for a given key.
 	Value(key string) (interface{}, bool)
 }
 
-
 // CallValuer implements the Call method for evaluating function calls.
 type CallValuer interface {
 	Valuer
@@ -489,13 +487,13 @@ type WildcardValuer struct {
 
 //TODO deal with wildcard of a stream, e.g. SELECT Table.* from Table inner join Table1
 func (wv *WildcardValuer) Value(key string) (interface{}, bool) {
-	if key == ""{
+	if key == "" {
 		return wv.Data.All(key)
-	}else{
+	} else {
 		a := strings.Index(key, ".*")
-		if a <= 0{
+		if a <= 0 {
 			return nil, false
-		}else{
+		} else {
 			return wv.Data.All(key[:a])
 		}
 	}
@@ -578,14 +576,13 @@ func (t *Tuple) GetMetadata() Metadata {
 	return t.Metadata
 }
 
-
 func (t *Tuple) IsWatermark() bool {
 	return false
 }
 
 type WindowTuples struct {
 	Emitter string
-	Tuples []Tuple
+	Tuples  []Tuple
 }
 
 type WindowTuplesSet []WindowTuples
@@ -600,26 +597,26 @@ func (w WindowTuplesSet) GetBySrc(src string) []Tuple {
 }
 
 func (w WindowTuplesSet) Len() int {
-	if len(w) > 0{
+	if len(w) > 0 {
 		return len(w[0].Tuples)
 	}
 	return 0
 }
 func (w WindowTuplesSet) Swap(i, j int) {
-	if len(w) > 0{
+	if len(w) > 0 {
 		s := w[0].Tuples
 		s[i], s[j] = s[j], s[i]
 	}
 }
 func (w WindowTuplesSet) Index(i int) Valuer {
-	if len(w) > 0{
+	if len(w) > 0 {
 		s := w[0].Tuples
 		return &(s[i])
 	}
 	return nil
 }
 
-func (w WindowTuplesSet) AddTuple(tuple *Tuple) WindowTuplesSet{
+func (w WindowTuplesSet) AddTuple(tuple *Tuple) WindowTuplesSet {
 	found := false
 	for i, t := range w {
 		if t.Emitter == tuple.Emitter {
@@ -680,15 +677,15 @@ func (jt *JoinTuple) Value(key string) (interface{}, bool) {
 	switch len(keys) {
 	case 1:
 		if len(tuples) > 1 {
-			for _, tuple := range tuples {	//TODO support key without modifier?
+			for _, tuple := range tuples { //TODO support key without modifier?
 				v, ok := tuple.Message[key]
-				if ok{
+				if ok {
 					return v, ok
 				}
 			}
 			common.Log.Infoln("Wrong key: ", key, ", not found")
 			return nil, false
-		} else{
+		} else {
 			v, ok := tuples[0].Message[key]
 			return v, ok
 		}
@@ -709,17 +706,17 @@ func (jt *JoinTuple) Value(key string) (interface{}, bool) {
 }
 
 func (jt *JoinTuple) All(stream string) (interface{}, bool) {
-	if stream != ""{
-		for _, t := range jt.Tuples{
-			if t.Emitter == stream{
+	if stream != "" {
+		for _, t := range jt.Tuples {
+			if t.Emitter == stream {
 				return t.Message, true
 			}
 		}
-	}else{
+	} else {
 		var r Message = make(map[string]interface{})
-		for _, t := range jt.Tuples{
-			for k, v := range t.Message{
-				if _, ok := r[k]; !ok{
+		for _, t := range jt.Tuples {
+			for k, v := range t.Message {
+				if _, ok := r[k]; !ok {
 					r[k] = v
 				}
 			}
@@ -730,8 +727,9 @@ func (jt *JoinTuple) All(stream string) (interface{}, bool) {
 }
 
 type JoinTupleSets []JoinTuple
-func (s JoinTupleSets) Len() int      { return len(s) }
-func (s JoinTupleSets) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+func (s JoinTupleSets) Len() int           { return len(s) }
+func (s JoinTupleSets) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
 func (s JoinTupleSets) Index(i int) Valuer { return &(s[i]) }
 
 func (s JoinTupleSets) AggregateEval(expr Expr) []interface{} {
@@ -743,6 +741,7 @@ func (s JoinTupleSets) AggregateEval(expr Expr) []interface{} {
 }
 
 type GroupedTuples []DataValuer
+
 func (s GroupedTuples) AggregateEval(expr Expr) []interface{} {
 	var result []interface{}
 	for _, t := range s {
@@ -752,6 +751,7 @@ func (s GroupedTuples) AggregateEval(expr Expr) []interface{} {
 }
 
 type GroupedTuplesSet []GroupedTuples
+
 func (s GroupedTuplesSet) Len() int           { return len(s) }
 func (s GroupedTuplesSet) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
 func (s GroupedTuplesSet) Index(i int) Valuer { return s[i][0] }
@@ -863,14 +863,14 @@ func (a multiValuer) Call(name string, args []interface{}) (interface{}, bool) {
 	return nil, false
 }
 
-type multiAggregateValuer struct{
-	data AggregateData
+type multiAggregateValuer struct {
+	data    AggregateData
 	valuers []Valuer
 }
 
 func MultiAggregateValuer(data AggregateData, valuers ...Valuer) Valuer {
 	return &multiAggregateValuer{
-		data: data,
+		data:    data,
 		valuers: valuers,
 	}
 }
@@ -892,12 +892,12 @@ func (a *multiAggregateValuer) Call(name string, args []interface{}) (interface{
 			if v, ok := a.Call(name, args); ok {
 				return v, true
 			}
-		}else if c, ok := valuer.(CallValuer); ok{
-			if singleArgs == nil{
-				for _, arg := range args{
-					if arg, ok := arg.([]interface{}); ok{
+		} else if c, ok := valuer.(CallValuer); ok {
+			if singleArgs == nil {
+				for _, arg := range args {
+					if arg, ok := arg.([]interface{}); ok {
 						singleArgs = append(singleArgs, arg[0])
-					}else{
+					} else {
 						common.Log.Infof("multiAggregateValuer does not get [][] args but get %v", args)
 						return nil, false
 					}
@@ -944,20 +944,20 @@ func (v *ValuerEval) Eval(expr Expr) interface{} {
 	case *BooleanLiteral:
 		return expr.Val
 	case *ColonExpr:
-		return &BracketEvalResult{Start:expr.Start, End:expr.End}
+		return &BracketEvalResult{Start: expr.Start, End: expr.End}
 	case *IndexExpr:
-		return &BracketEvalResult{Start:expr.Index, End:expr.Index}
+		return &BracketEvalResult{Start: expr.Index, End: expr.Index}
 	case *Call:
 		if valuer, ok := v.Valuer.(CallValuer); ok {
 			var args []interface{}
 
 			if len(expr.Args) > 0 {
 				args = make([]interface{}, len(expr.Args))
-				if aggreValuer, ok := valuer.(AggregateCallValuer); ok{
+				if aggreValuer, ok := valuer.(AggregateCallValuer); ok {
 					for i := range expr.Args {
 						args[i] = aggreValuer.GetAllTuples().AggregateEval(expr.Args[i])
 					}
-				}else{
+				} else {
 					for i := range expr.Args {
 						args[i] = v.Eval(expr.Args[i])
 					}
@@ -984,7 +984,6 @@ func (v *ValuerEval) Eval(expr Expr) interface{} {
 	}
 }
 
-
 func (v *ValuerEval) evalBinaryExpr(expr *BinaryExpr) interface{} {
 	lhs := v.Eval(expr.LHS)
 	switch val := lhs.(type) {
@@ -1010,8 +1009,7 @@ func (v *ValuerEval) evalBinaryExpr(expr *BinaryExpr) interface{} {
 	return v.simpleDataEval(lhs, rhs, expr.OP)
 }
 
-
-func (v *ValuerEval) evalJsonExpr(result interface{}, op Token,  expr Expr) interface{} {
+func (v *ValuerEval) evalJsonExpr(result interface{}, op Token, expr Expr) interface{} {
 	if val, ok := result.(map[string]interface{}); ok {
 		switch op {
 		case ARROW:
@@ -1049,7 +1047,7 @@ func (v *ValuerEval) evalJsonExpr(result interface{}, op Token,  expr Expr) inte
 						fmt.Printf("End value is out of index: %d of %d.\n", berVal.End, len(val))
 						return nil
 					}
-					return val[berVal.Start : berVal.End]
+					return val[berVal.Start:berVal.End]
 				}
 			} else {
 				fmt.Printf("Invalid evaluation result - %v.\n", berVal)
@@ -1426,7 +1424,7 @@ func (v *ValuerEval) simpleDataEval(lhs, rhs interface{}, op Token) interface{}
 		}
 	case time.Time:
 		rt, err := common.InterfaceToTime(rhs, "")
-		if err != nil{
+		if err != nil {
 			return false
 		}
 		switch op {
@@ -1556,7 +1554,7 @@ func isAggFunc(f *Call) bool {
 	return false
 }
 func HasAggFuncs(node Node) bool {
-	if node == nil{
+	if node == nil {
 		return false
 	}
 	var r = false
@@ -1567,12 +1565,12 @@ func HasAggFuncs(node Node) bool {
 				return
 			}
 		}
-	});
+	})
 	return r
 }
 
 func HasNoAggFuncs(node Node) bool {
-	if node == nil{
+	if node == nil {
 		return false
 	}
 	var r = false
@@ -1586,4 +1584,3 @@ func HasNoAggFuncs(node Node) bool {
 	})
 	return r
 }
-

+ 14 - 14
xsql/ast_agg_stmt_test.go

@@ -9,23 +9,23 @@ import (
 
 func TestIsAggStatement(t *testing.T) {
 	var tests = []struct {
-		s    string
-		agg  bool
-		err  string
+		s   string
+		agg bool
+		err string
 	}{
-		{s: `SELECT avg(1) FROM tbl`,agg: true},
-		{s: `SELECT sin(1) FROM tbl`,agg: false},
-		{s: `SELECT sin(avg(f1)) FROM tbl`,agg: true},
+		{s: `SELECT avg(1) FROM tbl`, agg: true},
+		{s: `SELECT sin(1) FROM tbl`, agg: false},
+		{s: `SELECT sin(avg(f1)) FROM tbl`, agg: true},
 
-		{s: `SELECT sum(f1) FROM tbl GROUP by f1`,agg: true},
-		{s: `SELECT f1 FROM tbl GROUP by f1`,agg: true},
+		{s: `SELECT sum(f1) FROM tbl GROUP by f1`, agg: true},
+		{s: `SELECT f1 FROM tbl GROUP by f1`, agg: true},
 
-		{s: `SELECT count(f1) FROM tbl`,agg: true},
-		{s: `SELECT max(f1) FROM tbl`,agg: true},
-		{s: `SELECT min(f1) FROM tbl`,agg: true},
-		{s: `SELECT count(f1) FROM tbl group by tumblingwindow(ss, 5)`,agg: true},
+		{s: `SELECT count(f1) FROM tbl`, agg: true},
+		{s: `SELECT max(f1) FROM tbl`, agg: true},
+		{s: `SELECT min(f1) FROM tbl`, agg: true},
+		{s: `SELECT count(f1) FROM tbl group by tumblingwindow(ss, 5)`, agg: true},
 
-		{s: `SELECT f1 FROM tbl left join tbl2 on tbl1.f1 = tbl2.f2`,agg: false},
+		{s: `SELECT f1 FROM tbl left join tbl2 on tbl1.f1 = tbl2.f2`, agg: false},
 	}
 
 	fmt.Printf("The test bucket size is %d.\n\n", len(tests))
@@ -39,4 +39,4 @@ func TestIsAggStatement(t *testing.T) {
 			t.Errorf("Error: expected %t, actual %t.", tt.agg, isAgg)
 		}
 	}
-}
+}

+ 1 - 1
xsql/expression_evaluator.go

@@ -1,8 +1,8 @@
 package xsql
 
 import (
-	"github.com/emqx/kuiper/common"
 	"github.com/buger/jsonparser"
+	"github.com/emqx/kuiper/common"
 	"github.com/golang-collections/collections/stack"
 )
 

+ 33 - 33
xsql/funcs_aggregate.go

@@ -8,7 +8,7 @@ import (
 	"strings"
 )
 
-type AggregateFunctionValuer struct{
+type AggregateFunctionValuer struct {
 	Data AggregateData
 }
 
@@ -21,15 +21,15 @@ func (v AggregateFunctionValuer) Call(name string, args []interface{}) (interfac
 	switch lowerName {
 	case "avg":
 		arg0 := args[0].([]interface{})
-		if len(arg0) > 0{
+		if len(arg0) > 0 {
 			v := getFirstValidArg(arg0)
-			switch v.(type){
+			switch v.(type) {
 			case int:
-				return sliceIntTotal(arg0)/len(arg0), true
+				return sliceIntTotal(arg0) / len(arg0), true
 			case int64:
-				return sliceIntTotal(arg0)/len(arg0), true
+				return sliceIntTotal(arg0) / len(arg0), true
 			case float64:
-				return sliceFloatTotal(arg0)/float64(len(arg0)), true
+				return sliceFloatTotal(arg0) / float64(len(arg0)), true
 			default:
 				return fmt.Errorf("invalid data type for avg function"), false
 			}
@@ -40,9 +40,9 @@ func (v AggregateFunctionValuer) Call(name string, args []interface{}) (interfac
 		return len(arg0), true
 	case "max":
 		arg0 := args[0].([]interface{})
-		if len(arg0) > 0{
+		if len(arg0) > 0 {
 			v := getFirstValidArg(arg0)
-			switch t := v.(type){
+			switch t := v.(type) {
 			case int:
 				return sliceIntMax(arg0, t), true
 			case int64:
@@ -58,9 +58,9 @@ func (v AggregateFunctionValuer) Call(name string, args []interface{}) (interfac
 		return fmt.Errorf("empty data for max function"), false
 	case "min":
 		arg0 := args[0].([]interface{})
-		if len(arg0) > 0{
+		if len(arg0) > 0 {
 			v := getFirstValidArg(arg0)
-			switch t := v.(type){
+			switch t := v.(type) {
 			case int:
 				return sliceIntMin(arg0, t), true
 			case int64:
@@ -76,9 +76,9 @@ func (v AggregateFunctionValuer) Call(name string, args []interface{}) (interfac
 		return fmt.Errorf("empty data for max function"), false
 	case "sum":
 		arg0 := args[0].([]interface{})
-		if len(arg0) > 0{
+		if len(arg0) > 0 {
 			v := getFirstValidArg(arg0)
-			switch v.(type){
+			switch v.(type) {
 			case int:
 				return sliceIntTotal(arg0), true
 			case int64:
@@ -94,12 +94,12 @@ func (v AggregateFunctionValuer) Call(name string, args []interface{}) (interfac
 		common.Log.Debugf("run aggregate func %s", name)
 		if nf, err := plugin_manager.GetPlugin(name, "functions"); err != nil {
 			return nil, false
-		}else{
+		} else {
 			f, ok := nf.(api.Function)
 			if !ok {
 				return nil, false
 			}
-			if !f.IsAggregate(){
+			if !f.IsAggregate() {
 				return nil, false
 			}
 			result, ok := f.Exec(args)
@@ -113,18 +113,18 @@ func (v *AggregateFunctionValuer) GetAllTuples() AggregateData {
 	return v.Data
 }
 
-func getFirstValidArg(s []interface{}) interface{}{
-	for _, v := range s{
-		if v != nil{
+func getFirstValidArg(s []interface{}) interface{} {
+	for _, v := range s {
+		if v != nil {
 			return v
 		}
 	}
 	return nil
 }
 
-func sliceIntTotal(s []interface{}) int{
+func sliceIntTotal(s []interface{}) int {
 	var total int
-	for _, v := range s{
+	for _, v := range s {
 		if v, ok := v.(int); ok {
 			total += v
 		}
@@ -132,17 +132,17 @@ func sliceIntTotal(s []interface{}) int{
 	return total
 }
 
-func sliceFloatTotal(s []interface{}) float64{
+func sliceFloatTotal(s []interface{}) float64 {
 	var total float64
-	for _, v := range s{
+	for _, v := range s {
 		if v, ok := v.(float64); ok {
 			total += v
 		}
 	}
 	return total
 }
-func sliceIntMax(s []interface{}, max int) int{
-	for _, v := range s{
+func sliceIntMax(s []interface{}, max int) int {
+	for _, v := range s {
 		if v, ok := v.(int); ok {
 			if max < v {
 				max = v
@@ -151,8 +151,8 @@ func sliceIntMax(s []interface{}, max int) int{
 	}
 	return max
 }
-func sliceFloatMax(s []interface{}, max float64) float64{
-	for _, v := range s{
+func sliceFloatMax(s []interface{}, max float64) float64 {
+	for _, v := range s {
 		if v, ok := v.(float64); ok {
 			if max < v {
 				max = v
@@ -162,8 +162,8 @@ func sliceFloatMax(s []interface{}, max float64) float64{
 	return max
 }
 
-func sliceStringMax(s []interface{}, max string) string{
-	for _, v := range s{
+func sliceStringMax(s []interface{}, max string) string {
+	for _, v := range s {
 		if v, ok := v.(string); ok {
 			if max < v {
 				max = v
@@ -172,8 +172,8 @@ func sliceStringMax(s []interface{}, max string) string{
 	}
 	return max
 }
-func sliceIntMin(s []interface{}, min int) int{
-	for _, v := range s{
+func sliceIntMin(s []interface{}, min int) int {
+	for _, v := range s {
 		if v, ok := v.(int); ok {
 			if min > v {
 				min = v
@@ -182,8 +182,8 @@ func sliceIntMin(s []interface{}, min int) int{
 	}
 	return min
 }
-func sliceFloatMin(s []interface{}, min float64) float64{
-	for _, v := range s{
+func sliceFloatMin(s []interface{}, min float64) float64 {
+	for _, v := range s {
 		if v, ok := v.(float64); ok {
 			if min > v {
 				min = v
@@ -193,8 +193,8 @@ func sliceFloatMin(s []interface{}, min float64) float64{
 	return min
 }
 
-func sliceStringMin(s []interface{}, min string) string{
-	for _, v := range s{
+func sliceStringMin(s []interface{}, min string) string {
+	for _, v := range s {
 		if v, ok := v.(string); ok {
 			if min < v {
 				min = v

+ 28 - 29
xsql/funcs_ast_validator.go

@@ -1,9 +1,9 @@
 package xsql
 
 import (
+	"fmt"
 	"github.com/emqx/kuiper/common/plugin_manager"
 	"github.com/emqx/kuiper/xstream/api"
-	"fmt"
 	"strings"
 )
 
@@ -28,13 +28,13 @@ func validateFuncs(funcName string, args []Expr) error {
 	} else {
 		if nf, err := plugin_manager.GetPlugin(funcName, "functions"); err != nil {
 			return err
-		}else{
+		} else {
 			f, ok := nf.(api.Function)
 			if !ok {
 				return fmt.Errorf("exported symbol %s is not type of api.Function", funcName)
 			}
 			var targs []interface{}
-			for _, arg := range args{
+			for _, arg := range args {
 				targs = append(targs, arg)
 			}
 			return f.Validate(targs)
@@ -46,18 +46,18 @@ func validateMathFunc(name string, args []Expr) error {
 	len := len(args)
 	switch name {
 	case "abs", "acos", "asin", "atan", "ceil", "cos", "cosh", "exp", "ln", "log", "round", "sign", "sin", "sinh",
-	"sqrt", "tan", "tanh" :
+		"sqrt", "tan", "tanh":
 		if err := validateLen(name, 1, len); err != nil {
-			return  err
+			return err
 		}
 		if isStringArg(args[0]) || isTimeArg(args[0]) || isBooleanArg(args[0]) {
 			return produceErrInfo(name, 0, "number - float or int")
 		}
 	case "bitand", "bitor", "bitxor":
 		if err := validateLen(name, 2, len); err != nil {
-			return  err
+			return err
 		}
-		if isFloatArg(args[0]) || isStringArg(args[0]) || isTimeArg(args[0]) || isBooleanArg(args[0]){
+		if isFloatArg(args[0]) || isStringArg(args[0]) || isTimeArg(args[0]) || isBooleanArg(args[0]) {
 			return produceErrInfo(name, 0, "int")
 		}
 		if isFloatArg(args[1]) || isStringArg(args[1]) || isTimeArg(args[1]) || isBooleanArg(args[1]) {
@@ -66,26 +66,26 @@ func validateMathFunc(name string, args []Expr) error {
 
 	case "bitnot":
 		if err := validateLen(name, 1, len); err != nil {
-			return  err
+			return err
 		}
-		if isFloatArg(args[0]) || isStringArg(args[0]) || isTimeArg(args[0]) || isBooleanArg(args[0])  {
+		if isFloatArg(args[0]) || isStringArg(args[0]) || isTimeArg(args[0]) || isBooleanArg(args[0]) {
 			return produceErrInfo(name, 0, "int")
 		}
 
 	case "atan2", "mod", "power":
 		if err := validateLen(name, 2, len); err != nil {
-			return  err
+			return err
 		}
 		if isStringArg(args[0]) || isTimeArg(args[0]) || isBooleanArg(args[0]) {
 			return produceErrInfo(name, 0, "number - float or int")
 		}
-		if isStringArg(args[1]) || isTimeArg(args[1]) || isBooleanArg(args[1]){
+		if isStringArg(args[1]) || isTimeArg(args[1]) || isBooleanArg(args[1]) {
 			return produceErrInfo(name, 1, "number - float or int")
 		}
 
 	case "rand":
 		if err := validateLen(name, 0, len); err != nil {
-			return  err
+			return err
 		}
 	}
 	return nil
@@ -105,44 +105,44 @@ func validateStrFunc(name string, args []Expr) error {
 		}
 	case "endswith", "indexof", "regexp_matches", "startswith":
 		if err := validateLen(name, 2, len); err != nil {
-			return  err
+			return err
 		}
 		for i := 0; i < 2; i++ {
-			if isNumericArg(args[i]) || isTimeArg(args[i])|| isBooleanArg(args[i]) {
+			if isNumericArg(args[i]) || isTimeArg(args[i]) || isBooleanArg(args[i]) {
 				return produceErrInfo(name, i, "string")
 			}
 		}
 	case "format_time":
 		if err := validateLen(name, 2, len); err != nil {
-			return  err
+			return err
 		}
 
-		if isNumericArg(args[0]) || isStringArg(args[0])|| isBooleanArg(args[0]) {
+		if isNumericArg(args[0]) || isStringArg(args[0]) || isBooleanArg(args[0]) {
 			return produceErrInfo(name, 0, "datetime")
 		}
-		if isNumericArg(args[1]) || isTimeArg(args[1])|| isBooleanArg(args[1]) {
+		if isNumericArg(args[1]) || isTimeArg(args[1]) || isBooleanArg(args[1]) {
 			return produceErrInfo(name, 1, "string")
 		}
 
 	case "regexp_replace":
 		if err := validateLen(name, 3, len); err != nil {
-			return  err
+			return err
 		}
 		for i := 0; i < 3; i++ {
-			if isNumericArg(args[i]) || isTimeArg(args[i])|| isBooleanArg(args[i]) {
+			if isNumericArg(args[i]) || isTimeArg(args[i]) || isBooleanArg(args[i]) {
 				return produceErrInfo(name, i, "string")
 			}
 		}
 	case "length", "lower", "ltrim", "numbytes", "rtrim", "trim", "upper":
 		if err := validateLen(name, 1, len); err != nil {
-			return  err
+			return err
 		}
 		if isNumericArg(args[0]) || isTimeArg(args[0]) || isBooleanArg(args[0]) {
 			return produceErrInfo(name, 0, "string")
 		}
 	case "lpad", "rpad":
 		if err := validateLen(name, 2, len); err != nil {
-			return  err
+			return err
 		}
 		if isNumericArg(args[0]) || isTimeArg(args[0]) || isBooleanArg(args[0]) {
 			return produceErrInfo(name, 0, "string")
@@ -168,7 +168,7 @@ func validateStrFunc(name string, args []Expr) error {
 			if sv < 0 {
 				return fmt.Errorf("The start index should not be a nagtive integer.")
 			}
-			if len == 3{
+			if len == 3 {
 				if e, ok1 := args[2].(*IntegerLiteral); ok1 {
 					ev := e.Val
 					if ev < sv {
@@ -204,7 +204,7 @@ func validateConvFunc(name string, args []Expr) error {
 	switch name {
 	case "cast":
 		if err := validateLen(name, 2, len); err != nil {
-			return  err
+			return err
 		}
 		a := args[1]
 		if !isStringArg(a) {
@@ -217,14 +217,14 @@ func validateConvFunc(name string, args []Expr) error {
 		}
 	case "chr":
 		if err := validateLen(name, 1, len); err != nil {
-			return  err
+			return err
 		}
 		if isFloatArg(args[0]) || isTimeArg(args[0]) || isBooleanArg(args[0]) {
 			return produceErrInfo(name, 0, "int")
 		}
 	case "encode":
 		if err := validateLen(name, 2, len); err != nil {
-			return  err
+			return err
 		}
 
 		if isNumericArg(args[0]) || isTimeArg(args[0]) || isBooleanArg(args[0]) {
@@ -242,7 +242,7 @@ func validateConvFunc(name string, args []Expr) error {
 		}
 	case "trunc":
 		if err := validateLen(name, 2, len); err != nil {
-			return  err
+			return err
 		}
 
 		if isTimeArg(args[0]) || isBooleanArg(args[0]) || isStringArg(args[0]) {
@@ -287,7 +287,7 @@ func validateOtherFunc(name string, args []Expr) error {
 		}
 	case "newuuid":
 		if err := validateLen(name, 0, len); err != nil {
-			return  err
+			return err
 		}
 	case "mqtt":
 		if err := validateLen(name, 1, len); err != nil {
@@ -310,7 +310,7 @@ func validateAggFunc(name string, args []Expr) error {
 	switch name {
 	case "avg", "max", "min", "sum":
 		if err := validateLen(name, 1, len); err != nil {
-			return  err
+			return err
 		}
 		if isStringArg(args[0]) || isTimeArg(args[0]) || isBooleanArg(args[0]) {
 			return produceErrInfo(name, 0, "number - float or int")
@@ -323,7 +323,6 @@ func validateAggFunc(name string, args []Expr) error {
 	return nil
 }
 
-
 // Index is starting from 0
 func produceErrInfo(name string, index int, expect string) (err error) {
 	index++

+ 101 - 105
xsql/funcs_ast_validator_test.go

@@ -17,406 +17,404 @@ func TestFuncValidator(t *testing.T) {
 		{
 			s: `SELECT abs(1) FROM tbl`,
 			stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "abs", Expr: &Call{Name: "abs", Args: []Expr{&IntegerLiteral{Val: 1}}}}},
-				Sources: []Source{&Table{Name:"tbl"}},
+				Sources: []Source{&Table{Name: "tbl"}},
 			},
 		},
 
 		{
 			s: `SELECT abs(field1) FROM tbl`,
 			stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "abs", Expr: &Call{Name: "abs", Args: []Expr{&FieldRef{Name: "field1"}}}}},
-				Sources: []Source{&Table{Name:"tbl"}},
+				Sources: []Source{&Table{Name: "tbl"}},
 			},
 		},
 
 		{
-			s: `SELECT abs(1,2) FROM tbl`,
+			s:    `SELECT abs(1,2) FROM tbl`,
 			stmt: nil,
-			err: "The arguments for abs should be 1.",
+			err:  "The arguments for abs should be 1.",
 		},
 
 		{
 			s: `SELECT abs(1.1) FROM tbl`,
 			stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "abs", Expr: &Call{Name: "abs", Args: []Expr{&NumberLiteral{Val: 1.1}}}}},
-				Sources: []Source{&Table{Name:"tbl"}},
+				Sources: []Source{&Table{Name: "tbl"}},
 			},
 		},
 
 		{
-			s: `SELECT abs(true) FROM tbl`,
+			s:    `SELECT abs(true) FROM tbl`,
 			stmt: nil,
-			err: "Expect number - float or int type for 1 parameter of function abs.",
+			err:  "Expect number - float or int type for 1 parameter of function abs.",
 		},
 
 		{
-			s: `SELECT abs("test") FROM tbl`,
+			s:    `SELECT abs("test") FROM tbl`,
 			stmt: nil,
-			err: "Expect number - float or int type for 1 parameter of function abs.",
+			err:  "Expect number - float or int type for 1 parameter of function abs.",
 		},
 
 		{
-			s: `SELECT abs(ss) FROM tbl`,
+			s:    `SELECT abs(ss) FROM tbl`,
 			stmt: nil,
-			err: "Expect number - float or int type for 1 parameter of function abs.",
+			err:  "Expect number - float or int type for 1 parameter of function abs.",
 		},
 
-
 		///
 		{
 			s: `SELECT sin(1) FROM tbl`,
 			stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "sin", Expr: &Call{Name: "sin", Args: []Expr{&IntegerLiteral{Val: 1}}}}},
-				Sources: []Source{&Table{Name:"tbl"}},
+				Sources: []Source{&Table{Name: "tbl"}},
 			},
 		},
 
 		{
 			s: `SELECT sin(1.1) FROM tbl`,
 			stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "sin", Expr: &Call{Name: "sin", Args: []Expr{&NumberLiteral{Val: 1.1}}}}},
-				Sources: []Source{&Table{Name:"tbl"}},
+				Sources: []Source{&Table{Name: "tbl"}},
 			},
 		},
 
 		{
-			s: `SELECT sin(true) FROM tbl`,
+			s:    `SELECT sin(true) FROM tbl`,
 			stmt: nil,
-			err: "Expect number - float or int type for 1 parameter of function sin.",
+			err:  "Expect number - float or int type for 1 parameter of function sin.",
 		},
 
 		{
-			s: `SELECT sin("test") FROM tbl`,
+			s:    `SELECT sin("test") FROM tbl`,
 			stmt: nil,
-			err: "Expect number - float or int type for 1 parameter of function sin.",
+			err:  "Expect number - float or int type for 1 parameter of function sin.",
 		},
 
 		{
-			s: `SELECT sin(ss) FROM tbl`,
+			s:    `SELECT sin(ss) FROM tbl`,
 			stmt: nil,
-			err: "Expect number - float or int type for 1 parameter of function sin.",
+			err:  "Expect number - float or int type for 1 parameter of function sin.",
 		},
 		///
 		{
 			s: `SELECT tanh(1) FROM tbl`,
 			stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "tanh", Expr: &Call{Name: "tanh", Args: []Expr{&IntegerLiteral{Val: 1}}}}},
-				Sources: []Source{&Table{Name:"tbl"}},
+				Sources: []Source{&Table{Name: "tbl"}},
 			},
 		},
 
 		{
 			s: `SELECT tanh(1.1) FROM tbl`,
 			stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "tanh", Expr: &Call{Name: "tanh", Args: []Expr{&NumberLiteral{Val: 1.1}}}}},
-				Sources: []Source{&Table{Name:"tbl"}},
+				Sources: []Source{&Table{Name: "tbl"}},
 			},
 		},
 
 		{
-			s: `SELECT tanh(true) FROM tbl`,
+			s:    `SELECT tanh(true) FROM tbl`,
 			stmt: nil,
-			err: "Expect number - float or int type for 1 parameter of function tanh.",
+			err:  "Expect number - float or int type for 1 parameter of function tanh.",
 		},
 
 		{
-			s: `SELECT tanh("test") FROM tbl`,
+			s:    `SELECT tanh("test") FROM tbl`,
 			stmt: nil,
-			err: "Expect number - float or int type for 1 parameter of function tanh.",
+			err:  "Expect number - float or int type for 1 parameter of function tanh.",
 		},
 
 		{
-			s: `SELECT tanh(ss) FROM tbl`,
+			s:    `SELECT tanh(ss) FROM tbl`,
 			stmt: nil,
-			err: "Expect number - float or int type for 1 parameter of function tanh.",
+			err:  "Expect number - float or int type for 1 parameter of function tanh.",
 		},
 
 		///
 		{
 			s: `SELECT bitxor(1, 2) FROM tbl`,
 			stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "bitxor", Expr: &Call{Name: "bitxor", Args: []Expr{&IntegerLiteral{Val: 1}, &IntegerLiteral{Val: 2}}}}},
-				Sources: []Source{&Table{Name:"tbl"}},
+				Sources: []Source{&Table{Name: "tbl"}},
 			},
 		},
 
 		{
-			s: `SELECT bitxor(1.1, 2) FROM tbl`,
+			s:    `SELECT bitxor(1.1, 2) FROM tbl`,
 			stmt: nil,
-			err: "Expect int type for 1 parameter of function bitxor.",
+			err:  "Expect int type for 1 parameter of function bitxor.",
 		},
 
 		{
-			s: `SELECT bitxor(true, 2) FROM tbl`,
+			s:    `SELECT bitxor(true, 2) FROM tbl`,
 			stmt: nil,
-			err: "Expect int type for 1 parameter of function bitxor.",
+			err:  "Expect int type for 1 parameter of function bitxor.",
 		},
 
 		{
-			s: `SELECT bitxor(1, ss) FROM tbl`,
+			s:    `SELECT bitxor(1, ss) FROM tbl`,
 			stmt: nil,
-			err: "Expect int type for 2 parameter of function bitxor.",
+			err:  "Expect int type for 2 parameter of function bitxor.",
 		},
 
 		{
-			s: `SELECT bitxor(1, 2.2) FROM tbl`,
+			s:    `SELECT bitxor(1, 2.2) FROM tbl`,
 			stmt: nil,
-			err: "Expect int type for 2 parameter of function bitxor.",
+			err:  "Expect int type for 2 parameter of function bitxor.",
 		},
 
 		///
 		{
 			s: `SELECT bitnot(1) FROM tbl`,
 			stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "bitnot", Expr: &Call{Name: "bitnot", Args: []Expr{&IntegerLiteral{Val: 1}}}}},
-				Sources: []Source{&Table{Name:"tbl"}},
+				Sources: []Source{&Table{Name: "tbl"}},
 			},
 		},
 
 		{
-			s: `SELECT bitnot(1.1) FROM tbl`,
+			s:    `SELECT bitnot(1.1) FROM tbl`,
 			stmt: nil,
-			err: "Expect int type for 1 parameter of function bitnot.",
+			err:  "Expect int type for 1 parameter of function bitnot.",
 		},
 
 		{
-			s: `SELECT bitnot(true) FROM tbl`,
+			s:    `SELECT bitnot(true) FROM tbl`,
 			stmt: nil,
-			err: "Expect int type for 1 parameter of function bitnot.",
+			err:  "Expect int type for 1 parameter of function bitnot.",
 		},
 
 		///
 		{
 			s: `SELECT mod(1, 2) FROM tbl`,
 			stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "mod", Expr: &Call{Name: "mod", Args: []Expr{&IntegerLiteral{Val: 1}, &IntegerLiteral{Val: 2}}}}},
-				Sources: []Source{&Table{Name:"tbl"}},
+				Sources: []Source{&Table{Name: "tbl"}},
 			},
 		},
 
 		{
-			s: `SELECT mod("1.1", 2) FROM tbl`,
+			s:    `SELECT mod("1.1", 2) FROM tbl`,
 			stmt: nil,
-			err: "Expect number - float or int type for 1 parameter of function mod.",
+			err:  "Expect number - float or int type for 1 parameter of function mod.",
 		},
 
 		{
-			s: `SELECT mod(1.1, true) FROM tbl`,
+			s:    `SELECT mod(1.1, true) FROM tbl`,
 			stmt: nil,
-			err: "Expect number - float or int type for 2 parameter of function mod.",
+			err:  "Expect number - float or int type for 2 parameter of function mod.",
 		},
 
 		{
-			s: `SELECT mod(1, ss) FROM tbl`,
+			s:    `SELECT mod(1, ss) FROM tbl`,
 			stmt: nil,
-			err: "Expect number - float or int type for 2 parameter of function mod.",
+			err:  "Expect number - float or int type for 2 parameter of function mod.",
 		},
 
 		///
 		{
 			s: `SELECT concat(field, "hello") FROM tbl`,
 			stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "concat", Expr: &Call{Name: "concat", Args: []Expr{&FieldRef{Name: "field"}, &StringLiteral{Val: "hello"}}}}},
-				Sources: []Source{&Table{Name:"tbl"}},
+				Sources: []Source{&Table{Name: "tbl"}},
 			},
 		},
 
 		{
-			s: `SELECT concat("1.1", 2) FROM tbl`,
+			s:    `SELECT concat("1.1", 2) FROM tbl`,
 			stmt: nil,
-			err: "Expect string type for 2 parameter of function concat.",
+			err:  "Expect string type for 2 parameter of function concat.",
 		},
 
 		{
-			s: `SELECT concat("1.1", true) FROM tbl`,
+			s:    `SELECT concat("1.1", true) FROM tbl`,
 			stmt: nil,
-			err: "Expect string type for 2 parameter of function concat.",
+			err:  "Expect string type for 2 parameter of function concat.",
 		},
 
 		{
-			s: `SELECT concat("1", ss) FROM tbl`,
+			s:    `SELECT concat("1", ss) FROM tbl`,
 			stmt: nil,
-			err: "Expect string type for 2 parameter of function concat.",
+			err:  "Expect string type for 2 parameter of function concat.",
 		},
 
 		///
 		{
 			s: `SELECT regexp_matches(field, "hello") FROM tbl`,
 			stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "regexp_matches", Expr: &Call{Name: "regexp_matches", Args: []Expr{&FieldRef{Name: "field"}, &StringLiteral{Val: "hello"}}}}},
-				Sources: []Source{&Table{Name:"tbl"}},
+				Sources: []Source{&Table{Name: "tbl"}},
 			},
 		},
 
 		{
-			s: `SELECT regexp_matches(1, "true") FROM tbl`,
+			s:    `SELECT regexp_matches(1, "true") FROM tbl`,
 			stmt: nil,
-			err: "Expect string type for 1 parameter of function regexp_matches.",
+			err:  "Expect string type for 1 parameter of function regexp_matches.",
 		},
 
 		{
-			s: `SELECT regexp_matches("1.1", 2) FROM tbl`,
+			s:    `SELECT regexp_matches("1.1", 2) FROM tbl`,
 			stmt: nil,
-			err: "Expect string type for 2 parameter of function regexp_matches.",
+			err:  "Expect string type for 2 parameter of function regexp_matches.",
 		},
 
 		///
 		{
 			s: `SELECT regexp_replace(field, "hello", "h") FROM tbl`,
 			stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "regexp_replace", Expr: &Call{Name: "regexp_replace", Args: []Expr{&FieldRef{Name: "field"}, &StringLiteral{Val: "hello"}, &StringLiteral{Val: "h"}}}}},
-				Sources: []Source{&Table{Name:"tbl"}},
+				Sources: []Source{&Table{Name: "tbl"}},
 			},
 		},
 
 		{
-			s: `SELECT regexp_replace(field1, "true", true) FROM tbl`,
+			s:    `SELECT regexp_replace(field1, "true", true) FROM tbl`,
 			stmt: nil,
-			err: "Expect string type for 3 parameter of function regexp_replace.",
+			err:  "Expect string type for 3 parameter of function regexp_replace.",
 		},
 
 		///
 		{
 			s: `SELECT trim(field) FROM tbl`,
 			stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "trim", Expr: &Call{Name: "trim", Args: []Expr{&FieldRef{Name: "field"}}}}},
-				Sources: []Source{&Table{Name:"tbl"}},
+				Sources: []Source{&Table{Name: "tbl"}},
 			},
 		},
 
 		{
-			s: `SELECT trim(1) FROM tbl`,
+			s:    `SELECT trim(1) FROM tbl`,
 			stmt: nil,
-			err: "Expect string type for 1 parameter of function trim.",
+			err:  "Expect string type for 1 parameter of function trim.",
 		},
 
 		///
 		{
 			s: `SELECT rpad(field, 3) FROM tbl`,
 			stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "rpad", Expr: &Call{Name: "rpad", Args: []Expr{&FieldRef{Name: "field"}, &IntegerLiteral{Val: 3}}}}},
-				Sources: []Source{&Table{Name:"tbl"}},
+				Sources: []Source{&Table{Name: "tbl"}},
 			},
 		},
 
 		{
-			s: `SELECT rpad("ff", true) FROM tbl`,
+			s:    `SELECT rpad("ff", true) FROM tbl`,
 			stmt: nil,
-			err: "Expect int type for 2 parameter of function rpad.",
+			err:  "Expect int type for 2 parameter of function rpad.",
 		},
 
 		///
 		{
 			s: `SELECT substring(field, 3, 4) FROM tbl`,
 			stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "substring", Expr: &Call{Name: "substring", Args: []Expr{&FieldRef{Name: "field"}, &IntegerLiteral{Val: 3}, &IntegerLiteral{Val: 4}}}}},
-				Sources: []Source{&Table{Name:"tbl"}},
+				Sources: []Source{&Table{Name: "tbl"}},
 			},
 		},
 
 		{
-			s: `SELECT substring(field, -1, 4) FROM tbl`,
+			s:    `SELECT substring(field, -1, 4) FROM tbl`,
 			stmt: nil,
-			err: "The start index should not be a nagtive integer.",
+			err:  "The start index should not be a nagtive integer.",
 		},
 
 		{
-			s: `SELECT substring(field, 0, -1) FROM tbl`,
+			s:    `SELECT substring(field, 0, -1) FROM tbl`,
 			stmt: nil,
-			err: "The end index should be larger than start index.",
+			err:  "The end index should be larger than start index.",
 		},
 
 		{
-			s: `SELECT substring(field, 0, true) FROM tbl`,
+			s:    `SELECT substring(field, 0, true) FROM tbl`,
 			stmt: nil,
-			err: "Expect int type for 3 parameter of function substring.",
+			err:  "Expect int type for 3 parameter of function substring.",
 		},
 
 		///
 		{
 			s: `SELECT cast(field, "bigint") FROM tbl`,
 			stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "cast", Expr: &Call{Name: "cast", Args: []Expr{&FieldRef{Name: "field"}, &StringLiteral{Val: "bigint"}}}}},
-				Sources: []Source{&Table{Name:"tbl"}},
+				Sources: []Source{&Table{Name: "tbl"}},
 			},
 		},
 
 		{
-			s: `SELECT cast("12", "bool") FROM tbl`,
+			s:    `SELECT cast("12", "bool") FROM tbl`,
 			stmt: nil,
-			err: "Expect one of following value for the 2nd parameter: bigint, float, string, boolean, datetime.",
+			err:  "Expect one of following value for the 2nd parameter: bigint, float, string, boolean, datetime.",
 		},
 
 		///
 		{
 			s: `SELECT chr(field) FROM tbl`,
 			stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "chr", Expr: &Call{Name: "chr", Args: []Expr{&FieldRef{Name: "field"}}}}},
-				Sources: []Source{&Table{Name:"tbl"}},
+				Sources: []Source{&Table{Name: "tbl"}},
 			},
 		},
 
 		{
-			s: `SELECT chr(true) FROM tbl`,
+			s:    `SELECT chr(true) FROM tbl`,
 			stmt: nil,
-			err: "Expect int type for 1 parameter of function chr.",
+			err:  "Expect int type for 1 parameter of function chr.",
 		},
 
 		///
 		{
 			s: `SELECT encode(field, "base64") FROM tbl`,
 			stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "encode", Expr: &Call{Name: "encode", Args: []Expr{&FieldRef{Name: "field"}, &StringLiteral{Val: "base64"}}}}},
-				Sources: []Source{&Table{Name:"tbl"}},
+				Sources: []Source{&Table{Name: "tbl"}},
 			},
 		},
 
 		{
-			s: `SELECT encode(field, true) FROM tbl`,
+			s:    `SELECT encode(field, true) FROM tbl`,
 			stmt: nil,
-			err: "Expect string type for 2 parameter of function encode.",
+			err:  "Expect string type for 2 parameter of function encode.",
 		},
 
 		///
 		{
 			s: `SELECT trunc(field, 3) FROM tbl`,
 			stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "trunc", Expr: &Call{Name: "trunc", Args: []Expr{&FieldRef{Name: "field"}, &IntegerLiteral{Val: 3}}}}},
-				Sources: []Source{&Table{Name:"tbl"}},
+				Sources: []Source{&Table{Name: "tbl"}},
 			},
 		},
 
 		{
-			s: `SELECT trunc(5, ss) FROM tbl`,
+			s:    `SELECT trunc(5, ss) FROM tbl`,
 			stmt: nil,
-			err: "Expect int type for 2 parameter of function trunc.",
+			err:  "Expect int type for 2 parameter of function trunc.",
 		},
 
 		///
 		{
 			s: `SELECT sha512(field) FROM tbl`,
 			stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "sha512", Expr: &Call{Name: "sha512", Args: []Expr{&FieldRef{Name: "field"}}}}},
-				Sources: []Source{&Table{Name:"tbl"}},
+				Sources: []Source{&Table{Name: "tbl"}},
 			},
 		},
 
 		{
-			s: `SELECT sha512(20) FROM tbl`,
+			s:    `SELECT sha512(20) FROM tbl`,
 			stmt: nil,
-			err: "Expect string type for 1 parameter of function sha512.",
+			err:  "Expect string type for 1 parameter of function sha512.",
 		},
 
 		{
-			s: `SELECT mqtt("topic") FROM tbl`,
+			s:    `SELECT mqtt("topic") FROM tbl`,
 			stmt: nil,
-			err: "Expect field reference type for 1 parameter of function mqtt.",
+			err:  "Expect field reference type for 1 parameter of function mqtt.",
 		},
 
 		{
-			s: `SELECT mqtt(topic1) FROM tbl`,
+			s:    `SELECT mqtt(topic1) FROM tbl`,
 			stmt: nil,
-			err: "Parameter of mqtt function can be only topic or messageid.",
+			err:  "Parameter of mqtt function can be only topic or messageid.",
 		},
 
 		{
-			s: `SELECT split_value(topic1) FROM tbl`,
+			s:    `SELECT split_value(topic1) FROM tbl`,
 			stmt: nil,
-			err: "the arguments for split_value should be 3",
+			err:  "the arguments for split_value should be 3",
 		},
 
 		{
-			s: `SELECT split_value(topic1, 3, 1) FROM tbl`,
+			s:    `SELECT split_value(topic1, 3, 1) FROM tbl`,
 			stmt: nil,
-			err: "Expect string type for 2 parameter of function split_value.",
+			err:  "Expect string type for 2 parameter of function split_value.",
 		},
 
 		{
-			s: `SELECT split_value(topic1, "hello", -1) FROM tbl`,
+			s:    `SELECT split_value(topic1, "hello", -1) FROM tbl`,
 			stmt: nil,
-			err: "The index should not be a nagtive integer.",
+			err:  "The index should not be a nagtive integer.",
 		},
-
 	}
 
 	fmt.Printf("The test bucket size is %d.\n\n", len(tests))
@@ -430,5 +428,3 @@ func TestFuncValidator(t *testing.T) {
 		}
 	}
 }
-
-

+ 1 - 1
xsql/funcs_math.go

@@ -197,4 +197,4 @@ func toF64(arg interface{}) (float64, error) {
 		return float64(v), nil
 	}
 	return 0, fmt.Errorf("only float64 & int type are supported")
-}
+}

+ 3 - 5
xsql/funcs_misc.go

@@ -6,8 +6,8 @@ import (
 	"crypto/sha256"
 	"crypto/sha512"
 	b64 "encoding/base64"
-	"github.com/emqx/kuiper/common"
 	"fmt"
+	"github.com/emqx/kuiper/common"
 	"github.com/google/uuid"
 	"hash"
 	"io"
@@ -165,7 +165,7 @@ func round(num float64) int {
 
 func toFixed(num float64, precision int) float64 {
 	output := math.Pow(10, float64(precision))
-	return float64(round(num * output)) / output
+	return float64(round(num*output)) / output
 }
 
 func hashCall(name string, args []interface{}) (interface{}, bool) {
@@ -196,7 +196,7 @@ func otherCall(name string, args []interface{}) (interface{}, bool) {
 	case "newuuid":
 		if uuid, err := uuid.NewUUID(); err != nil {
 			return err, false
-		}else{
+		} else {
 			return uuid.String(), true
 		}
 	case "timestamp":
@@ -210,5 +210,3 @@ func otherCall(name string, args []interface{}) (interface{}, bool) {
 		return fmt.Errorf("unknown function name %s", name), false
 	}
 }
-
-

+ 15 - 16
xsql/funcs_str.go

@@ -2,8 +2,8 @@ package xsql
 
 import (
 	"bytes"
-	"github.com/emqx/kuiper/common"
 	"fmt"
+	"github.com/emqx/kuiper/common"
 	"regexp"
 	"strings"
 	"time"
@@ -34,7 +34,7 @@ func strCall(name string, args []interface{}) (interface{}, bool) {
 	case "lpad":
 		arg0 := common.ToString(args[0])
 		arg1, err := common.ToInt(args[1])
-		if err != nil{
+		if err != nil {
 			return err, false
 		}
 		return strings.Repeat(" ", arg1) + arg0, true
@@ -46,38 +46,38 @@ func strCall(name string, args []interface{}) (interface{}, bool) {
 		return len(arg0), true
 	case "format_time":
 		arg0 := args[0]
-		if t, ok := arg0.(time.Time); ok{
+		if t, ok := arg0.(time.Time); ok {
 			arg1 := common.ToString(args[1])
-			if s, err := common.FormatTime(t, arg1); err==nil{
+			if s, err := common.FormatTime(t, arg1); err == nil {
 				return s, true
 			}
 		}
 		return "", false
 	case "regexp_matches":
 		arg0, arg1 := common.ToString(args[0]), common.ToString(args[1])
-		if matched, err := regexp.MatchString(arg1, arg0); err != nil{
+		if matched, err := regexp.MatchString(arg1, arg0); err != nil {
 			return err, false
-		}else{
+		} else {
 			return matched, true
 		}
 	case "regexp_replace":
 		arg0, arg1, arg2 := common.ToString(args[0]), common.ToString(args[1]), common.ToString(args[2])
-		if re, err := regexp.Compile(arg1); err != nil{
+		if re, err := regexp.Compile(arg1); err != nil {
 			return err, false
-		}else{
+		} else {
 			return re.ReplaceAllString(arg0, arg2), true
 		}
 	case "regexp_substr":
 		arg0, arg1 := common.ToString(args[0]), common.ToString(args[1])
-		if re, err := regexp.Compile(arg1); err != nil{
+		if re, err := regexp.Compile(arg1); err != nil {
 			return err, false
-		}else{
+		} else {
 			return re.FindString(arg0), true
 		}
 	case "rpad":
 		arg0 := common.ToString(args[0])
 		arg1, err := common.ToInt(args[1])
-		if err != nil{
+		if err != nil {
 			return err, false
 		}
 		return arg0 + strings.Repeat(" ", arg1), true
@@ -87,16 +87,16 @@ func strCall(name string, args []interface{}) (interface{}, bool) {
 	case "substring":
 		arg0 := common.ToString(args[0])
 		arg1, err := common.ToInt(args[1])
-		if err != nil{
+		if err != nil {
 			return err, false
 		}
-		if len(args) > 2{
+		if len(args) > 2 {
 			arg2, err := common.ToInt(args[2])
-			if err != nil{
+			if err != nil {
 				return err, false
 			}
 			return arg0[arg1:arg2], true
-		}else{
+		} else {
 			return arg0[arg1:], true
 		}
 	case "startswith":
@@ -121,4 +121,3 @@ func strCall(name string, args []interface{}) (interface{}, bool) {
 		return fmt.Errorf("unknown string function name %s", name), false
 	}
 }
-

+ 10 - 10
xsql/functions.go

@@ -15,8 +15,8 @@ func (*FunctionValuer) Value(key string) (interface{}, bool) {
 
 var aggFuncMap = map[string]string{"avg": "",
 	"count": "",
-	"max": "", "min": "",
-	"sum":  "",
+	"max":   "", "min": "",
+	"sum": "",
 }
 
 var mathFuncMap = map[string]string{"abs": "", "acos": "", "asin": "", "atan": "", "atan2": "",
@@ -32,10 +32,10 @@ var mathFuncMap = map[string]string{"abs": "", "acos": "", "asin": "", "atan": "
 }
 
 var strFuncMap = map[string]string{"concat": "",
-	"endswith": "",
+	"endswith":    "",
 	"format_time": "",
-	"indexof":  "",
-	"length":   "", "lower": "", "lpad": "", "ltrim": "",
+	"indexof":     "",
+	"length":      "", "lower": "", "lpad": "", "ltrim": "",
 	"numbytes":       "",
 	"regexp_matches": "", "regexp_replace": "", "regexp_substr": "", "rpad": "", "rtrim": "",
 	"substring": "", "startswith": "", "split_value": "",
@@ -48,7 +48,7 @@ var convFuncMap = map[string]string{"concat": "", "cast": "", "chr": "",
 	"trunc":  "",
 }
 
-var hashFuncMap = map[string]string{ "md5": "",
+var hashFuncMap = map[string]string{"md5": "",
 	"sha1": "", "sha256": "", "sha384": "", "sha512": "",
 }
 
@@ -68,18 +68,18 @@ func (*FunctionValuer) Call(name string, args []interface{}) (interface{}, bool)
 		return hashCall(lowerName, args)
 	} else if _, ok := otherFuncMap[lowerName]; ok {
 		return otherCall(lowerName, args)
-	} else if _, ok :=  aggFuncMap[lowerName]; ok {
+	} else if _, ok := aggFuncMap[lowerName]; ok {
 		return nil, false
 	} else {
 		common.Log.Debugf("run func %s", name)
 		if nf, err := plugin_manager.GetPlugin(name, "functions"); err != nil {
 			return nil, false
-		}else{
+		} else {
 			f, ok := nf.(api.Function)
 			if !ok {
 				return nil, false
 			}
-			if f.IsAggregate(){
+			if f.IsAggregate() {
 				return nil, false
 			}
 			result, ok := f.Exec(args)
@@ -87,4 +87,4 @@ func (*FunctionValuer) Call(name string, args []interface{}) (interface{}, bool)
 			return result, ok
 		}
 	}
-}
+}

+ 23 - 21
xsql/lexical.go

@@ -47,7 +47,7 @@ const (
 	GTE // >=
 
 	SUBSET //[
-	ARROW //->
+	ARROW  //->
 
 	operatorEnd
 
@@ -56,11 +56,11 @@ const (
 	COMMA     // ,
 	LPAREN    // (
 	RPAREN    // )
-	LBRACKET //[
+	LBRACKET  //[
 	RBRACKET  //]
 	HASH      // #
 	DOT       // .
-	COLON	  //:
+	COLON     //:
 	SEMICOLON //;
 
 	// Keywords
@@ -166,7 +166,7 @@ var tokens = []string{
 	WHERE:  "WHERE",
 	GROUP:  "GROUP",
 	ORDER:  "ORDER",
-	HAVING:  "HAVING",
+	HAVING: "HAVING",
 	BY:     "BY",
 	ASC:    "ASC",
 	DESC:   "DESC",
@@ -188,18 +188,18 @@ var tokens = []string{
 	XARRAY:    "ARRAY",
 	XSTRUCT:   "STRUCT",
 
-	DATASOURCE:   "DATASOURCE",
-	KEY:      "KEY",
-	FORMAT:   "FORMAT",
-	CONF_KEY: "CONF_KEY",
-	TYPE: 	  "TYPE",
+	DATASOURCE:        "DATASOURCE",
+	KEY:               "KEY",
+	FORMAT:            "FORMAT",
+	CONF_KEY:          "CONF_KEY",
+	TYPE:              "TYPE",
 	STRICT_VALIDATION: "STRICT_VALIDATION",
-	TIMESTAMP: "TIMESTAMP",
-	TIMESTAMP_FORMAT: "TIMESTAMP_FORMAT",
+	TIMESTAMP:         "TIMESTAMP",
+	TIMESTAMP_FORMAT:  "TIMESTAMP_FORMAT",
 
-	AND: "AND",
-	OR:  "OR",
-	TRUE: "TRUE",
+	AND:   "AND",
+	OR:    "OR",
+	TRUE:  "TRUE",
 	FALSE: "FALSE",
 
 	DD: "DD",
@@ -591,7 +591,9 @@ func isDigit(ch rune) bool { return ch >= '0' && ch <= '9' }
 
 func isQuotation(ch rune) bool { return ch == '"' }
 
-func (tok Token) isOperator() bool { return (tok > operatorBeg && tok < operatorEnd) || tok == ASTERISK || tok == LBRACKET }
+func (tok Token) isOperator() bool {
+	return (tok > operatorBeg && tok < operatorEnd) || tok == ASTERISK || tok == LBRACKET
+}
 
 func (tok Token) isTimeLiteral() bool { return tok >= DD && tok <= MS }
 
@@ -632,13 +634,13 @@ const (
 )
 
 var dataTypes = []string{
-	BIGINT	: "bigint",
-	FLOAT	: "float",
-	STRINGS	: "string",
+	BIGINT:   "bigint",
+	FLOAT:    "float",
+	STRINGS:  "string",
 	DATETIME: "datetime",
-	BOOLEAN	: "boolean",
-	ARRAY	: "array",
-	STRUCT	: "struct",
+	BOOLEAN:  "boolean",
+	ARRAY:    "array",
+	STRUCT:   "struct",
 }
 
 func (d DataType) isSimpleType() bool {

+ 4 - 3
xsql/metadata_util.go

@@ -7,7 +7,8 @@ const INTERNAL_MQTT_MSG_ID_KEY string = "internal_mqtt_msg_id_key_$$"
 
 //For functions such as mqtt(topic). If the field definitions also has a field named "topic", then it need to
 //have an internal key for "topic" to avoid key conflicts.
-var SpecialKeyMapper = map[string]string{"topic" : INTERNAL_MQTT_TOPIC_KEY, "messageid" : INTERNAL_MQTT_MSG_ID_KEY}
+var SpecialKeyMapper = map[string]string{"topic": INTERNAL_MQTT_TOPIC_KEY, "messageid": INTERNAL_MQTT_MSG_ID_KEY}
+
 func AddSpecialKeyMap(left, right string) {
 	SpecialKeyMapper[left] = right
 }
@@ -16,7 +17,7 @@ func AddSpecialKeyMap(left, right string) {
 The function is used for re-write the parameter names.
 For example, for mqtt function, the arguments could be 'topic' or 'messageid'.
 If the field name defined in stream happens to be 'topic' or 'messageid', it will have conflicts.
- */
+*/
 func (c Call) rewrite_func() *Call {
 	if strings.ToLower(c.Name) == "mqtt" {
 		if f, ok := c.Args[0].(*FieldRef); ok {
@@ -27,4 +28,4 @@ func (c Call) rewrite_func() *Call {
 		}
 	}
 	return &c
-}
+}

+ 15 - 17
xsql/parser.go

@@ -270,7 +270,7 @@ func (p *Parser) parseJoins() (Joins, error) {
 }
 
 func (p *Parser) ParseJoin(joinType JoinType) (*Join, error) {
-	var j = &Join{ JoinType : joinType }
+	var j = &Join{JoinType: joinType}
 	if src, alias, err := p.parseSourceLiteral(); err != nil {
 		return nil, err
 	} else {
@@ -319,7 +319,6 @@ func (p *Parser) parseDimensions() (Dimensions, error) {
 	return ds, nil
 }
 
-
 func (p *Parser) parseHaving() (Expr, error) {
 	if tok, _ := p.scanIgnoreWhitespace(); tok != HAVING {
 		p.unscan()
@@ -332,7 +331,6 @@ func (p *Parser) parseHaving() (Expr, error) {
 	return expr, nil
 }
 
-
 func (p *Parser) parseSorts() (SortFields, error) {
 	var ss SortFields
 	if t, _ := p.scanIgnoreWhitespace(); t == ORDER {
@@ -527,20 +525,20 @@ func (p *Parser) parseUnaryExpr() (Expr, error) {
 		if v, err := strconv.ParseBool(lit); err != nil {
 			return nil, fmt.Errorf("found %q, invalid boolean value.", lit)
 		} else {
-			return &BooleanLiteral{Val:v}, nil
+			return &BooleanLiteral{Val: v}, nil
 		}
 	} else if tok.isTimeLiteral() {
-		return &TimeLiteral{Val:tok}, nil
+		return &TimeLiteral{Val: tok}, nil
 	}
 
 	return nil, fmt.Errorf("found %q, expected expression.", lit)
 }
 
-func (p *Parser) parseBracketExpr() (Expr, error){
+func (p *Parser) parseBracketExpr() (Expr, error) {
 	tok2, lit2 := p.scanIgnoreWhitespace()
 	if tok2 == RBRACKET {
 		//field[]
-		return &ColonExpr{Start:0, End:-1}, nil
+		return &ColonExpr{Start: 0, End: -1}, nil
 	} else if tok2 == INTEGER {
 		start, err := strconv.Atoi(lit2)
 		if err != nil {
@@ -548,7 +546,7 @@ func (p *Parser) parseBracketExpr() (Expr, error){
 		}
 		if tok3, _ := p.scanIgnoreWhitespace(); tok3 == RBRACKET {
 			//Such as field[2]
-			return &IndexExpr{Index:start}, nil
+			return &IndexExpr{Index: start}, nil
 		} else if tok3 == COLON {
 			//Such as field[2:] or field[2:4]
 			return p.parseColonExpr(start)
@@ -569,12 +567,12 @@ func (p *Parser) parseColonExpr(start int) (Expr, error) {
 		}
 
 		if tok1, lit1 := p.scanIgnoreWhitespace(); tok1 == RBRACKET {
-			return &ColonExpr{Start:start, End: end}, nil
+			return &ColonExpr{Start: start, End: end}, nil
 		} else {
 			return nil, fmt.Errorf("Found %q, expected right bracket.", lit1)
 		}
 	} else if tok == RBRACKET {
-		return &ColonExpr{Start:start, End: -1}, nil
+		return &ColonExpr{Start: start, End: -1}, nil
 	}
 	return nil, fmt.Errorf("Found %q, expected right bracket.", lit)
 }
@@ -597,7 +595,7 @@ func (p *Parser) parseCall(name string) (Expr, error) {
 			if tok2, lit2 := p.scanIgnoreWhitespace(); tok2 != RPAREN {
 				return nil, fmt.Errorf("found %q, expected right paren.", lit2)
 			} else {
-				args = append(args, &StringLiteral{Val:"*"})
+				args = append(args, &StringLiteral{Val: "*"})
 				return Call{Name: name, Args: args}.rewrite_func(), nil
 			}
 		} else {
@@ -667,7 +665,7 @@ func validateWindow(funcName string, expectLen int, args []Expr) error {
 		return fmt.Errorf("The 1st argument for %s is expecting timer literal expression. One value of [dd|hh|mi|ss|ms].\n", funcName)
 	}
 
-	for i := 1; i< len(args); i++ {
+	for i := 1; i < len(args); i++ {
 		if _, ok := args[i].(*IntegerLiteral); !ok {
 			return fmt.Errorf("The %d argument for %s is expecting interger literal expression. \n", i, funcName)
 		}
@@ -680,7 +678,7 @@ func (p *Parser) ConvertToWindows(wtype WindowType, name string, args []Expr) (*
 	win := &Window{WindowType: wtype}
 	var unit = 1
 	v := args[0].(*TimeLiteral).Val
-	switch v{
+	switch v {
 	case DD:
 		unit = 24 * 3600 * 1000
 	case HH:
@@ -694,10 +692,10 @@ func (p *Parser) ConvertToWindows(wtype WindowType, name string, args []Expr) (*
 	default:
 		return nil, fmt.Errorf("Invalid timeliteral %s", v)
 	}
-	win.Length = &IntegerLiteral{Val :  args[1].(*IntegerLiteral).Val * unit}
-	if len(args) > 2{
-		win.Interval = &IntegerLiteral{Val : args[2].(*IntegerLiteral).Val * unit}
-	}else{
+	win.Length = &IntegerLiteral{Val: args[1].(*IntegerLiteral).Val * unit}
+	if len(args) > 2 {
+		win.Interval = &IntegerLiteral{Val: args[2].(*IntegerLiteral).Val * unit}
+	} else {
 		win.Interval = &IntegerLiteral{Val: 0}
 	}
 	return win, nil

File diff suppressed because it is too large
+ 337 - 351
xsql/parser_test.go


+ 6 - 7
xsql/plans/aggregate_operator.go

@@ -1,16 +1,15 @@
 package plans
 
 import (
+	"fmt"
 	"github.com/emqx/kuiper/xsql"
 	"github.com/emqx/kuiper/xstream/api"
-	"fmt"
 )
 
 type AggregatePlan struct {
 	Dimensions xsql.Dimensions
 }
 
-
 /**
  *  input: *xsql.Tuple from preprocessor | xsql.WindowTuplesSet from windowOp | xsql.JoinTupleSets from joinOp
  *  output: xsql.GroupedTuplesSet
@@ -51,19 +50,19 @@ func (p *AggregatePlan) Apply(ctx api.StreamContext, data interface{}) interface
 		for _, d := range p.Dimensions {
 			name += fmt.Sprintf("%v,", ve.Eval(d.Expr))
 		}
-		if ts, ok := result[name]; !ok{
+		if ts, ok := result[name]; !ok {
 			result[name] = xsql.GroupedTuples{m}
-		}else{
+		} else {
 			result[name] = append(ts, m)
 		}
 	}
-	if len(result) > 0{
+	if len(result) > 0 {
 		g := make([]xsql.GroupedTuples, 0, len(result))
 		for _, v := range result {
 			g = append(g, v)
 		}
 		return xsql.GroupedTuplesSet(g)
-	}else{
+	} else {
 		return nil
 	}
-}
+}

+ 61 - 62
xsql/plans/aggregate_test.go

@@ -12,8 +12,8 @@ import (
 
 func TestAggregatePlan_Apply(t *testing.T) {
 	var tests = []struct {
-		sql  string
-		data interface{}
+		sql    string
+		data   interface{}
 		result xsql.GroupedTuplesSet
 	}{
 		{
@@ -21,8 +21,8 @@ func TestAggregatePlan_Apply(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "tbl",
 				Message: xsql.Message{
-					"abc" : int64(6),
-					"def" : "hello",
+					"abc": int64(6),
+					"def": "hello",
 				},
 			},
 			result: xsql.GroupedTuplesSet{
@@ -30,30 +30,29 @@ func TestAggregatePlan_Apply(t *testing.T) {
 					&xsql.Tuple{
 						Emitter: "tbl",
 						Message: xsql.Message{
-							"abc" : int64(6),
-							"def" : "hello",
+							"abc": int64(6),
+							"def": "hello",
 						},
 					},
 				},
 			},
 		},
 
-
 		{
 			sql: "SELECT abc FROM src1 GROUP BY TUMBLINGWINDOW(ss, 10), f1",
 			data: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 1, "f1" : "v1", },
-						},{
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 2, "f1" : "v2", },
-						},{
+							Message: xsql.Message{"id1": 2, "f1": "v2"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 3, "f1" : "v1", },
+							Message: xsql.Message{"id1": 3, "f1": "v1"},
 						},
 					},
 				},
@@ -62,17 +61,17 @@ func TestAggregatePlan_Apply(t *testing.T) {
 				{
 					&xsql.Tuple{
 						Emitter: "src1",
-						Message: xsql.Message{ "id1" : 1, "f1" : "v1", },
+						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					},
 					&xsql.Tuple{
 						Emitter: "src1",
-						Message: xsql.Message{ "id1" : 3, "f1" : "v1", },
+						Message: xsql.Message{"id1": 3, "f1": "v1"},
 					},
 				},
 				{
 					&xsql.Tuple{
 						Emitter: "src1",
-						Message: xsql.Message{ "id1" : 2, "f1" : "v2", },
+						Message: xsql.Message{"id1": 2, "f1": "v2"},
 					},
 				},
 			},
@@ -81,17 +80,17 @@ func TestAggregatePlan_Apply(t *testing.T) {
 			sql: "SELECT abc FROM src1 GROUP BY id1, TUMBLINGWINDOW(ss, 10), f1",
 			data: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 1, "f1" : "v1", },
-						},{
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 2, "f1" : "v2", },
-						},{
+							Message: xsql.Message{"id1": 2, "f1": "v2"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 3, "f1" : "v1", },
+							Message: xsql.Message{"id1": 3, "f1": "v1"},
 						},
 					},
 				},
@@ -100,19 +99,19 @@ func TestAggregatePlan_Apply(t *testing.T) {
 				{
 					&xsql.Tuple{
 						Emitter: "src1",
-						Message: xsql.Message{ "id1" : 1, "f1" : "v1", },
+						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					},
 				},
 				{
 					&xsql.Tuple{
 						Emitter: "src1",
-						Message: xsql.Message{ "id1" : 2, "f1" : "v2", },
+						Message: xsql.Message{"id1": 2, "f1": "v2"},
 					},
 				},
 				{
 					&xsql.Tuple{
 						Emitter: "src1",
-						Message: xsql.Message{ "id1" : 3, "f1" : "v1", },
+						Message: xsql.Message{"id1": 3, "f1": "v1"},
 					},
 				},
 			},
@@ -123,19 +122,19 @@ func TestAggregatePlan_Apply(t *testing.T) {
 			data: xsql.JoinTupleSets{
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 1, "f1" : "v1",},},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 2, "f2" : "w2",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 					},
 				},
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 2, "f1" : "v2",},},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 4, "f2" : "w3",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 					},
 				},
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 3, "f1" : "v1",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 					},
 				},
 			},
@@ -143,23 +142,23 @@ func TestAggregatePlan_Apply(t *testing.T) {
 				{
 					&xsql.JoinTuple{
 						Tuples: []xsql.Tuple{
-							{Emitter: "src1", Message: xsql.Message{ "id1" : 1, "f1" : "v1",},},
-							{Emitter: "src2", Message: xsql.Message{ "id2" : 2, "f2" : "w2",},},
+							{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
+							{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 						},
 					},
 				},
 				{
 					&xsql.JoinTuple{
 						Tuples: []xsql.Tuple{
-							{Emitter: "src1", Message: xsql.Message{ "id1" : 2, "f1" : "v2",},},
-							{Emitter: "src2", Message: xsql.Message{ "id2" : 4, "f2" : "w3",},},
+							{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
+							{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 						},
 					},
 				},
 				{
 					&xsql.JoinTuple{
 						Tuples: []xsql.Tuple{
-							{Emitter: "src1", Message: xsql.Message{ "id1" : 3, "f1" : "v1",},},
+							{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 						},
 					},
 				},
@@ -170,19 +169,19 @@ func TestAggregatePlan_Apply(t *testing.T) {
 			data: xsql.JoinTupleSets{
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 1, "f1" : "v1",},},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 2, "f2" : "w2",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 					},
 				},
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 2, "f1" : "v2",},},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 4, "f2" : "w3",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 					},
 				},
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 3, "f1" : "v1",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 					},
 				},
 			},
@@ -190,21 +189,21 @@ func TestAggregatePlan_Apply(t *testing.T) {
 				{
 					&xsql.JoinTuple{
 						Tuples: []xsql.Tuple{
-							{Emitter: "src1", Message: xsql.Message{ "id1" : 1, "f1" : "v1",},},
-							{Emitter: "src2", Message: xsql.Message{ "id2" : 2, "f2" : "w2",},},
+							{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
+							{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 						},
 					},
 					&xsql.JoinTuple{
 						Tuples: []xsql.Tuple{
-							{Emitter: "src1", Message: xsql.Message{ "id1" : 3, "f1" : "v1",},},
+							{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 						},
 					},
 				},
 				{
 					&xsql.JoinTuple{
 						Tuples: []xsql.Tuple{
-							{Emitter: "src1", Message: xsql.Message{ "id1" : 2, "f1" : "v2",},},
-							{Emitter: "src2", Message: xsql.Message{ "id2" : 4, "f2" : "w3",},},
+							{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
+							{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 						},
 					},
 				},
@@ -215,19 +214,19 @@ func TestAggregatePlan_Apply(t *testing.T) {
 			data: xsql.JoinTupleSets{
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 1, "f1" : "v1", "ts": common.TimeFromUnixMilli(1568854515000),},},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 2, "f2" : "w2",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1", "ts": common.TimeFromUnixMilli(1568854515000)}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 					},
 				},
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 2, "f1" : "v2","ts": common.TimeFromUnixMilli(1568854573431),},},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 4, "f2" : "w3",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2", "ts": common.TimeFromUnixMilli(1568854573431)}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 					},
 				},
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 3, "f1" : "v1","ts": common.TimeFromUnixMilli(1568854515000),},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1", "ts": common.TimeFromUnixMilli(1568854515000)}},
 					},
 				},
 			},
@@ -235,21 +234,21 @@ func TestAggregatePlan_Apply(t *testing.T) {
 				{
 					&xsql.JoinTuple{
 						Tuples: []xsql.Tuple{
-							{Emitter: "src1", Message: xsql.Message{ "id1" : 1, "f1" : "v1", "ts": common.TimeFromUnixMilli(1568854515000),},},
-							{Emitter: "src2", Message: xsql.Message{ "id2" : 2, "f2" : "w2",},},
+							{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1", "ts": common.TimeFromUnixMilli(1568854515000)}},
+							{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 						},
 					},
 					&xsql.JoinTuple{
 						Tuples: []xsql.Tuple{
-							{Emitter: "src1", Message: xsql.Message{ "id1" : 3, "f1" : "v1", "ts": common.TimeFromUnixMilli(1568854515000),},},
+							{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1", "ts": common.TimeFromUnixMilli(1568854515000)}},
 						},
 					},
 				},
 				{
 					&xsql.JoinTuple{
 						Tuples: []xsql.Tuple{
-							{Emitter: "src1", Message: xsql.Message{ "id1" : 2, "f1" : "v2","ts": common.TimeFromUnixMilli(1568854573431),},},
-							{Emitter: "src2", Message: xsql.Message{ "id2" : 4, "f2" : "w3",},},
+							{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2", "ts": common.TimeFromUnixMilli(1568854573431)}},
+							{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 						},
 					},
 				},
@@ -267,7 +266,7 @@ func TestAggregatePlan_Apply(t *testing.T) {
 			break
 		}
 
-		pp := &AggregatePlan{Dimensions:stmt.Dimensions.GetGroups()}
+		pp := &AggregatePlan{Dimensions: stmt.Dimensions.GetGroups()}
 		result := pp.Apply(ctx, tt.data)
 		gr, ok := result.(xsql.GroupedTuplesSet)
 		if !ok {
@@ -277,14 +276,14 @@ func TestAggregatePlan_Apply(t *testing.T) {
 			t.Errorf("%d. %q\n\nresult mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.sql, tt.result, gr)
 		}
 
-		for _, r := range tt.result{
+		for _, r := range tt.result {
 			matched := false
-			for _, gre := range gr{
-				if reflect.DeepEqual(r, gre){
+			for _, gre := range gr {
+				if reflect.DeepEqual(r, gre) {
 					matched = true
 				}
 			}
-			if !matched{
+			if !matched {
 				t.Errorf("%d. %q\n\nresult mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.sql, tt.result, r)
 			}
 		}

+ 4 - 4
xsql/plans/filter_operator.go

@@ -10,8 +10,8 @@ type FilterPlan struct {
 }
 
 /**
-  *  input: *xsql.Tuple from preprocessor | xsql.WindowTuplesSet from windowOp | xsql.JoinTupleSets from joinOp
-  *  output: *xsql.Tuple | xsql.WindowTuplesSet | xsql.JoinTupleSets
+ *  input: *xsql.Tuple from preprocessor | xsql.WindowTuplesSet from windowOp | xsql.JoinTupleSets from joinOp
+ *  output: *xsql.Tuple | xsql.WindowTuplesSet | xsql.JoinTupleSets
  */
 func (p *FilterPlan) Apply(ctx api.StreamContext, data interface{}) interface{} {
 	log := ctx.GetLogger()
@@ -65,7 +65,7 @@ func (p *FilterPlan) Apply(ctx api.StreamContext, data interface{}) interface{}
 				return nil
 			}
 		}
-		if len(r) > 0{
+		if len(r) > 0 {
 			return r
 		}
 	default:
@@ -73,4 +73,4 @@ func (p *FilterPlan) Apply(ctx api.StreamContext, data interface{}) interface{}
 		return nil
 	}
 	return nil
-}
+}

+ 51 - 52
xsql/plans/filter_test.go

@@ -12,8 +12,8 @@ import (
 
 func TestFilterPlan_Apply(t *testing.T) {
 	var tests = []struct {
-		sql  string
-		data interface{}
+		sql    string
+		data   interface{}
 		result interface{}
 	}{
 		{
@@ -21,7 +21,7 @@ func TestFilterPlan_Apply(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "tbl",
 				Message: xsql.Message{
-					"a" : int64(6),
+					"a": int64(6),
 				},
 			},
 			result: nil,
@@ -32,17 +32,17 @@ func TestFilterPlan_Apply(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "tbl",
 				Message: xsql.Message{
-					"abc" : common.TimeFromUnixMilli(1568854515000),
-					"def" : common.TimeFromUnixMilli(1568853515000),
-					"ghi" : common.TimeFromUnixMilli(1568854515000),
+					"abc": common.TimeFromUnixMilli(1568854515000),
+					"def": common.TimeFromUnixMilli(1568853515000),
+					"ghi": common.TimeFromUnixMilli(1568854515000),
 				},
 			},
 			result: &xsql.Tuple{
 				Emitter: "tbl",
 				Message: xsql.Message{
-					"abc" : common.TimeFromUnixMilli(1568854515000),
-					"def" : common.TimeFromUnixMilli(1568853515000),
-					"ghi" : common.TimeFromUnixMilli(1568854515000),
+					"abc": common.TimeFromUnixMilli(1568854515000),
+					"def": common.TimeFromUnixMilli(1568853515000),
+					"ghi": common.TimeFromUnixMilli(1568854515000),
 				},
 			},
 		},
@@ -52,7 +52,7 @@ func TestFilterPlan_Apply(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "tbl",
 				Message: xsql.Message{
-					"abc" : int64(6),
+					"abc": int64(6),
 				},
 			},
 			result: &xsql.Tuple{
@@ -68,15 +68,15 @@ func TestFilterPlan_Apply(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "tbl",
 				Message: xsql.Message{
-					"abc" : int64(34),
-					"def" : "hello",
+					"abc": int64(34),
+					"def": "hello",
 				},
 			},
 			result: &xsql.Tuple{
 				Emitter: "tbl",
 				Message: xsql.Message{
-					"abc" : int64(34),
-					"def" : "hello",
+					"abc": int64(34),
+					"def": "hello",
 				},
 			},
 		},
@@ -86,15 +86,15 @@ func TestFilterPlan_Apply(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "tbl",
 				Message: xsql.Message{
-					"abc" : common.TimeFromUnixMilli(1568854515678),
-					"def" : "hello",
+					"abc": common.TimeFromUnixMilli(1568854515678),
+					"def": "hello",
 				},
 			},
 			result: &xsql.Tuple{
 				Emitter: "tbl",
 				Message: xsql.Message{
-					"abc" : common.TimeFromUnixMilli(1568854515678),
-					"def" : "hello",
+					"abc": common.TimeFromUnixMilli(1568854515678),
+					"def": "hello",
 				},
 			},
 		},
@@ -103,31 +103,31 @@ func TestFilterPlan_Apply(t *testing.T) {
 			sql: "SELECT abc FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10)",
 			data: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{"id1" : 1, "f1" : "v1"},
-						},{
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{"id1" : 2, "f1" : "v2"},
-						},{
+							Message: xsql.Message{"id1": 2, "f1": "v2"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{"id1" : 3, "f1" : "v1"},
+							Message: xsql.Message{"id1": 3, "f1": "v1"},
 						},
 					},
 				},
 			},
 			result: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{"id1" : 1, "f1" : "v1"},
-						},{
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{"id1" : 3, "f1" : "v1"},
+							Message: xsql.Message{"id1": 3, "f1": "v1"},
 						},
 					},
 				},
@@ -138,17 +138,17 @@ func TestFilterPlan_Apply(t *testing.T) {
 			sql: "SELECT abc FROM src1 WHERE f1 = \"v8\" GROUP BY TUMBLINGWINDOW(ss, 10)",
 			data: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 1, "f1" : "v1"},
-						},{
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 2, "f1" : "v2"},
-						},{
+							Message: xsql.Message{"id1": 2, "f1": "v2"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 3, "f1" : "v1"},
+							Message: xsql.Message{"id1": 3, "f1": "v1"},
 						},
 					},
 				},
@@ -161,32 +161,32 @@ func TestFilterPlan_Apply(t *testing.T) {
 			data: xsql.JoinTupleSets{
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 1, "f1" : "v1",},},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 2, "f2" : "w2",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 					},
 				},
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 2, "f1" : "v2",},},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 4, "f2" : "w3",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 					},
 				},
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 3, "f1" : "v1",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 					},
 				},
 			},
 			result: xsql.JoinTupleSets{
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 1, "f1" : "v1",},},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 2, "f2" : "w2",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 					},
 				},
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 3, "f1" : "v1",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 					},
 				},
 			},
@@ -197,25 +197,24 @@ func TestFilterPlan_Apply(t *testing.T) {
 			data: xsql.JoinTupleSets{
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 1, "f1" : "v1",},},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 2, "f2" : "w2",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 					},
 				},
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 2, "f1" : "v2",},},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 4, "f2" : "w3",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 					},
 				},
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 3, "f1" : "v1",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 					},
 				},
 			},
 			result: nil,
 		},
-
 	}
 
 	fmt.Printf("The test bucket size is %d.\n\n", len(tests))
@@ -228,7 +227,7 @@ func TestFilterPlan_Apply(t *testing.T) {
 			break
 		}
 
-		pp := &FilterPlan{Condition:stmt.Condition}
+		pp := &FilterPlan{Condition: stmt.Condition}
 		result := pp.Apply(ctx, tt.data)
 		if !reflect.DeepEqual(tt.result, result) {
 			t.Errorf("%d. %q\n\nresult mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.sql, tt.result, result)

+ 1 - 1
xsql/plans/having_operator.go

@@ -71,7 +71,7 @@ func (p *HavingPlan) Apply(ctx api.StreamContext, data interface{}) interface{}
 				return nil
 			}
 		}
-		if len(r) > 0{
+		if len(r) > 0 {
 			return r
 		}
 	default:

+ 35 - 37
xsql/plans/having_test.go

@@ -12,43 +12,42 @@ import (
 
 func TestHavingPlan_Apply(t *testing.T) {
 	var tests = []struct {
-		sql  string
-		data interface{}
+		sql    string
+		data   interface{}
 		result interface{}
 	}{
 		{
 			sql: `SELECT id1 FROM src1 HAVING avg(id1) > 1`,
 			data: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{"id1" : 1, "f1" : "v1"},
-						},{
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{"id1" : 2, "f1" : "v2"},
-						},{
+							Message: xsql.Message{"id1": 2, "f1": "v2"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{"id1" : 5, "f1" : "v1"},
+							Message: xsql.Message{"id1": 5, "f1": "v1"},
 						},
-
 					},
 				},
 			},
 			result: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{"id1" : 1, "f1" : "v1"},
-						},{
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{"id1" : 2, "f1" : "v2"},
-						},{
+							Message: xsql.Message{"id1": 2, "f1": "v2"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{"id1" : 5, "f1" : "v1"},
+							Message: xsql.Message{"id1": 5, "f1": "v1"},
 						},
 					},
 				},
@@ -59,11 +58,11 @@ func TestHavingPlan_Apply(t *testing.T) {
 			sql: `SELECT id1 FROM src1 HAVING sum(id1) > 1`,
 			data: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{"id1" : 1, "f1" : "v1"},
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
 						},
 					},
 				},
@@ -75,38 +74,37 @@ func TestHavingPlan_Apply(t *testing.T) {
 			sql: `SELECT id1 FROM src1 HAVING sum(id1) = 1`,
 			data: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{"id1" : 1, "f1" : "v1"},
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
 						},
 					},
 				},
 			},
 			result: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{"id1" : 1, "f1" : "v1"},
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
 						},
 					},
 				},
 			},
 		},
 
-
 		{
 			sql: `SELECT id1 FROM src1 HAVING max(id1) > 10`,
 			data: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{"id1" : 1, "f1" : "v1"},
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
 						},
 					},
 				},
@@ -118,22 +116,22 @@ func TestHavingPlan_Apply(t *testing.T) {
 			sql: `SELECT id1 FROM src1 HAVING max(id1) = 1`,
 			data: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{"id1" : 1, "f1" : "v1"},
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
 						},
 					},
 				},
 			},
 			result: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{"id1" : 1, "f1" : "v1"},
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
 						},
 					},
 				},
@@ -151,7 +149,7 @@ func TestHavingPlan_Apply(t *testing.T) {
 			break
 		}
 
-		pp := &HavingPlan{Condition:stmt.Having}
+		pp := &HavingPlan{Condition: stmt.Having}
 		result := pp.Apply(ctx, tt.data)
 		if !reflect.DeepEqual(tt.result, result) {
 			t.Errorf("%d. %q\n\nresult mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.sql, tt.result, result)

+ 118 - 118
xsql/plans/join_multi_test.go

@@ -20,40 +20,40 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			sql: "SELECT id1 FROM src1 left join src2 on src1.id1 = src2.id2 left join src3 on src2.id2 = src3.id3",
 			data: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 1, "f1" : "v1" },
-						},{
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 3, "f1" : "v3" },
+							Message: xsql.Message{"id1": 3, "f1": "v3"},
 						},
 					},
 				},
 
 				xsql.WindowTuples{
-					Emitter:"src2",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src2",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src2",
-							Message: xsql.Message{ "id2" : 1, "f2" : "w1" },
-						},{
+							Message: xsql.Message{"id2": 1, "f2": "w1"},
+						}, {
 							Emitter: "src2",
-							Message: xsql.Message{ "id2" : 4, "f2" : "w3" },
+							Message: xsql.Message{"id2": 4, "f2": "w3"},
 						},
 					},
 				},
 
 				xsql.WindowTuples{
-					Emitter:"src3",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src3",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src3",
-							Message: xsql.Message{ "id3" : 1, "f3" : "x1" },
-						},{
+							Message: xsql.Message{"id3": 1, "f3": "x1"},
+						}, {
 							Emitter: "src3",
-							Message: xsql.Message{ "id3" : 5, "f3" : "x5" },
+							Message: xsql.Message{"id3": 5, "f3": "x5"},
 						},
 					},
 				},
@@ -61,15 +61,15 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: xsql.JoinTupleSets{
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 1, "f1" : "v1" },},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 1, "f2" : "w1" },},
-						{Emitter: "src3", Message: xsql.Message{ "id3" : 1, "f3" : "x1" },},
+						{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w1"}},
+						{Emitter: "src3", Message: xsql.Message{"id3": 1, "f3": "x1"}},
 					},
 				},
 
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 3, "f1" : "v3" },},
+						{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v3"}},
 					},
 				},
 			},
@@ -79,40 +79,40 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			sql: "SELECT id1 FROM src1 left join src2 on src1.id1 = src2.id2 inner join src3 on src2.id2 = src3.id3",
 			data: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 1, "f1" : "v1" },
-						},{
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 3, "f1" : "v3" },
+							Message: xsql.Message{"id1": 3, "f1": "v3"},
 						},
 					},
 				},
 
 				xsql.WindowTuples{
-					Emitter:"src2",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src2",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src2",
-							Message: xsql.Message{ "id2" : 1, "f2" : "w1" },
-						},{
+							Message: xsql.Message{"id2": 1, "f2": "w1"},
+						}, {
 							Emitter: "src2",
-							Message: xsql.Message{ "id2" : 4, "f2" : "w3" },
+							Message: xsql.Message{"id2": 4, "f2": "w3"},
 						},
 					},
 				},
 
 				xsql.WindowTuples{
-					Emitter:"src3",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src3",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src3",
-							Message: xsql.Message{ "id3" : 1, "f3" : "x1" },
-						},{
+							Message: xsql.Message{"id3": 1, "f3": "x1"},
+						}, {
 							Emitter: "src3",
-							Message: xsql.Message{ "id3" : 5, "f3" : "x5" },
+							Message: xsql.Message{"id3": 5, "f3": "x5"},
 						},
 					},
 				},
@@ -120,9 +120,9 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: xsql.JoinTupleSets{
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 1, "f1" : "v1" },},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 1, "f2" : "w1" },},
-						{Emitter: "src3", Message: xsql.Message{ "id3" : 1, "f3" : "x1" },},
+						{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w1"}},
+						{Emitter: "src3", Message: xsql.Message{"id3": 1, "f3": "x1"}},
 					},
 				},
 			},
@@ -132,40 +132,40 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			sql: "SELECT id1 FROM src1 left join src2 on src1.id1 = src2.id2 inner join src3 on src1.id1 = src3.id3",
 			data: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 1, "f1" : "v1" },
-						},{
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 5, "f1" : "v5" },
+							Message: xsql.Message{"id1": 5, "f1": "v5"},
 						},
 					},
 				},
 
 				xsql.WindowTuples{
-					Emitter:"src2",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src2",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src2",
-							Message: xsql.Message{ "id2" : 1, "f2" : "w1" },
-						},{
+							Message: xsql.Message{"id2": 1, "f2": "w1"},
+						}, {
 							Emitter: "src2",
-							Message: xsql.Message{ "id2" : 4, "f2" : "w3" },
+							Message: xsql.Message{"id2": 4, "f2": "w3"},
 						},
 					},
 				},
 
 				xsql.WindowTuples{
-					Emitter:"src3",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src3",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src3",
-							Message: xsql.Message{ "id3" : 2, "f3" : "x1" },
-						},{
+							Message: xsql.Message{"id3": 2, "f3": "x1"},
+						}, {
 							Emitter: "src3",
-							Message: xsql.Message{ "id3" : 5, "f3" : "x5" },
+							Message: xsql.Message{"id3": 5, "f3": "x5"},
 						},
 					},
 				},
@@ -173,8 +173,8 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: xsql.JoinTupleSets{
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 5, "f1" : "v5" },},
-						{Emitter: "src3", Message: xsql.Message{ "id3" : 5, "f3" : "x5" },},
+						{Emitter: "src1", Message: xsql.Message{"id1": 5, "f1": "v5"}},
+						{Emitter: "src3", Message: xsql.Message{"id3": 5, "f3": "x5"}},
 					},
 				},
 			},
@@ -184,40 +184,40 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			sql: "SELECT id1 FROM src1 left join src2 on src1.id1 = src2.id2 full join src3 on src1.id1 = src3.id3",
 			data: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 1, "f1" : "v1" },
-						},{
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 5, "f1" : "v5" },
+							Message: xsql.Message{"id1": 5, "f1": "v5"},
 						},
 					},
 				},
 
 				xsql.WindowTuples{
-					Emitter:"src2",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src2",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src2",
-							Message: xsql.Message{ "id2" : 1, "f2" : "w1" },
-						},{
+							Message: xsql.Message{"id2": 1, "f2": "w1"},
+						}, {
 							Emitter: "src2",
-							Message: xsql.Message{ "id2" : 4, "f2" : "w3" },
+							Message: xsql.Message{"id2": 4, "f2": "w3"},
 						},
 					},
 				},
 
 				xsql.WindowTuples{
-					Emitter:"src3",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src3",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src3",
-							Message: xsql.Message{ "id3" : 2, "f3" : "x1" },
-						},{
+							Message: xsql.Message{"id3": 2, "f3": "x1"},
+						}, {
 							Emitter: "src3",
-							Message: xsql.Message{ "id3" : 5, "f3" : "x5" },
+							Message: xsql.Message{"id3": 5, "f3": "x5"},
 						},
 					},
 				},
@@ -225,21 +225,21 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: xsql.JoinTupleSets{
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 1, "f1" : "v1" },},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 1, "f2" : "w1" },},
+						{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w1"}},
 					},
 				},
 
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 5, "f1" : "v5" },},
-						{Emitter: "src3", Message: xsql.Message{ "id3" : 5, "f3" : "x5" },},
+						{Emitter: "src1", Message: xsql.Message{"id1": 5, "f1": "v5"}},
+						{Emitter: "src3", Message: xsql.Message{"id3": 5, "f3": "x5"}},
 					},
 				},
 
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src3", Message: xsql.Message{ "id3" : 2, "f3" : "x1" },},
+						{Emitter: "src3", Message: xsql.Message{"id3": 2, "f3": "x1"}},
 					},
 				},
 			},
@@ -249,40 +249,40 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			sql: "SELECT id1 FROM src1 left join src2 on src1.id1 = src2.id2 right join src3 on src2.id2 = src3.id3",
 			data: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 1, "f1" : "v1" },
-						},{
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 3, "f1" : "v3" },
+							Message: xsql.Message{"id1": 3, "f1": "v3"},
 						},
 					},
 				},
 
 				xsql.WindowTuples{
-					Emitter:"src2",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src2",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src2",
-							Message: xsql.Message{ "id2" : 1, "f2" : "w1" },
-						},{
+							Message: xsql.Message{"id2": 1, "f2": "w1"},
+						}, {
 							Emitter: "src2",
-							Message: xsql.Message{ "id2" : 4, "f2" : "w3" },
+							Message: xsql.Message{"id2": 4, "f2": "w3"},
 						},
 					},
 				},
 
 				xsql.WindowTuples{
-					Emitter:"src3",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src3",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src3",
-							Message: xsql.Message{ "id3" : 1, "f3" : "x1" },
-						},{
+							Message: xsql.Message{"id3": 1, "f3": "x1"},
+						}, {
 							Emitter: "src3",
-							Message: xsql.Message{ "id3" : 5, "f3" : "x5" },
+							Message: xsql.Message{"id3": 5, "f3": "x5"},
 						},
 					},
 				},
@@ -290,15 +290,15 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: xsql.JoinTupleSets{
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src3", Message: xsql.Message{ "id3" : 1, "f3" : "x1" },},
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 1, "f1" : "v1" },},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 1, "f2" : "w1" },},
+						{Emitter: "src3", Message: xsql.Message{"id3": 1, "f3": "x1"}},
+						{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w1"}},
 					},
 				},
 
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src3", Message: xsql.Message{ "id3" : 5, "f3" : "x5" },},
+						{Emitter: "src3", Message: xsql.Message{"id3": 5, "f3": "x5"}},
 					},
 				},
 			},
@@ -308,40 +308,40 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			sql: "SELECT id1 FROM src1 left join src2 on src1.id1 = src2.id2 cross join src3",
 			data: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 1, "f1" : "v1" },
-						},{
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 5, "f1" : "v5" },
+							Message: xsql.Message{"id1": 5, "f1": "v5"},
 						},
 					},
 				},
 
 				xsql.WindowTuples{
-					Emitter:"src2",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src2",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src2",
-							Message: xsql.Message{ "id2" : 1, "f2" : "w1" },
-						},{
+							Message: xsql.Message{"id2": 1, "f2": "w1"},
+						}, {
 							Emitter: "src2",
-							Message: xsql.Message{ "id2" : 4, "f2" : "w3" },
+							Message: xsql.Message{"id2": 4, "f2": "w3"},
 						},
 					},
 				},
 
 				xsql.WindowTuples{
-					Emitter:"src3",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src3",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src3",
-							Message: xsql.Message{ "id3" : 2, "f3" : "x1" },
-						},{
+							Message: xsql.Message{"id3": 2, "f3": "x1"},
+						}, {
 							Emitter: "src3",
-							Message: xsql.Message{ "id3" : 5, "f3" : "x5" },
+							Message: xsql.Message{"id3": 5, "f3": "x5"},
 						},
 					},
 				},
@@ -349,10 +349,10 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: xsql.JoinTupleSets{
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 1, "f1" : "v1" },},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 1, "f2" : "w1" },},
-						{Emitter: "src3", Message: xsql.Message{ "id3" : 2, "f3" : "x1" },},
-						{Emitter: "src3", Message: xsql.Message{ "id3" : 5, "f3" : "x5" },},
+						{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w1"}},
+						{Emitter: "src3", Message: xsql.Message{"id3": 2, "f3": "x1"}},
+						{Emitter: "src3", Message: xsql.Message{"id3": 5, "f3": "x5"}},
 					},
 				},
 
@@ -366,9 +366,9 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 5, "f1" : "v5" },},
-						{Emitter: "src3", Message: xsql.Message{ "id3" : 2, "f3" : "x1" },},
-						{Emitter: "src3", Message: xsql.Message{ "id3" : 5, "f3" : "x5" },},
+						{Emitter: "src1", Message: xsql.Message{"id1": 5, "f1": "v5"}},
+						{Emitter: "src3", Message: xsql.Message{"id3": 2, "f3": "x1"}},
+						{Emitter: "src3", Message: xsql.Message{"id3": 5, "f3": "x5"}},
 					},
 				},
 
@@ -393,9 +393,9 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			break
 		}
 
-		if table, ok := stmt.Sources[0].(*xsql.Table); !ok{
+		if table, ok := stmt.Sources[0].(*xsql.Table); !ok {
 			t.Errorf("statement source is not a table")
-		}else{
+		} else {
 			pp := &JoinPlan{Joins: stmt.Joins, From: table}
 			result := pp.Apply(ctx, tt.data)
 			if !reflect.DeepEqual(tt.result, result) {
@@ -403,4 +403,4 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			}
 		}
 	}
-}
+}

+ 10 - 11
xsql/plans/join_operator.go

@@ -1,15 +1,15 @@
 package plans
 
 import (
+	"fmt"
 	"github.com/emqx/kuiper/common"
 	"github.com/emqx/kuiper/xsql"
 	"github.com/emqx/kuiper/xstream/api"
-	"fmt"
 )
 
 //TODO join expr should only be the equal op between 2 streams like tb1.id = tb2.id
 type JoinPlan struct {
-	From *xsql.Table
+	From  *xsql.Table
 	Joins xsql.Joins
 }
 
@@ -53,7 +53,7 @@ func (jp *JoinPlan) Apply(ctx api.StreamContext, data interface{}) interface{} {
 func getStreamNames(join *xsql.Join) ([]string, error) {
 	var srcs []string
 	xsql.WalkFunc(join, func(node xsql.Node) {
-		if f,ok := node.(*xsql.FieldRef); ok {
+		if f, ok := node.(*xsql.FieldRef); ok {
 			if string(f.StreamName) == "" {
 				return
 			}
@@ -120,7 +120,7 @@ func (jp *JoinPlan) evalSet(input xsql.WindowTuplesSet, join xsql.Join) (xsql.Jo
 							merged.AddTuple(right)
 							sets = append(sets, *merged)
 							merged = &xsql.JoinTuple{}
-						}else{
+						} else {
 							merged.AddTuple(right)
 						}
 					}
@@ -168,7 +168,7 @@ func (jp *JoinPlan) evalSetWithRightJoin(input xsql.WindowTuplesSet, join xsql.J
 			temp.AddTuple(right)
 			temp.AddTuple(left)
 			ve := &xsql.ValuerEval{Valuer: xsql.MultiValuer(temp, &xsql.FunctionValuer{})}
-			if r, ok  := ve.Eval(join.Expr).(bool); ok {
+			if r, ok := ve.Eval(join.Expr).(bool); ok {
 				if r {
 					merged.AddTuple(left)
 					isJoint = true
@@ -190,8 +190,7 @@ func (jp *JoinPlan) evalSetWithRightJoin(input xsql.WindowTuplesSet, join xsql.J
 	return sets, nil
 }
 
-
-func (jp *JoinPlan) evalJoinSets(set *xsql.JoinTupleSets, input xsql.WindowTuplesSet, join xsql.Join) (interface{}, error)  {
+func (jp *JoinPlan) evalJoinSets(set *xsql.JoinTupleSets, input xsql.WindowTuplesSet, join xsql.Join) (interface{}, error) {
 	var rightStream string
 	if join.Alias == "" {
 		rightStream = join.Name
@@ -203,7 +202,7 @@ func (jp *JoinPlan) evalJoinSets(set *xsql.JoinTupleSets, input xsql.WindowTuple
 
 	newSets := xsql.JoinTupleSets{}
 	if join.JoinType == xsql.RIGHT_JOIN {
-		return jp.evalRightJoinSets(set, input, join,false)
+		return jp.evalRightJoinSets(set, input, join, false)
 	}
 	for _, left := range *set {
 		merged := &xsql.JoinTuple{}
@@ -244,7 +243,7 @@ func (jp *JoinPlan) evalJoinSets(set *xsql.JoinTupleSets, input xsql.WindowTuple
 	return newSets, nil
 }
 
-func (jp *JoinPlan) evalRightJoinSets(set *xsql.JoinTupleSets, input xsql.WindowTuplesSet, join xsql.Join, excludeJoint bool) (xsql.JoinTupleSets, error)  {
+func (jp *JoinPlan) evalRightJoinSets(set *xsql.JoinTupleSets, input xsql.WindowTuplesSet, join xsql.Join, excludeJoint bool) (xsql.JoinTupleSets, error) {
 	var rightStream string
 	if join.Alias == "" {
 		rightStream = join.Name
@@ -270,7 +269,7 @@ func (jp *JoinPlan) evalRightJoinSets(set *xsql.JoinTupleSets, input xsql.Window
 		}
 
 		if excludeJoint {
-			if len(merged.Tuples) > 0  && (!isJoint) {
+			if len(merged.Tuples) > 0 && (!isJoint) {
 				newSets = append(newSets, *merged)
 			}
 		} else {
@@ -280,4 +279,4 @@ func (jp *JoinPlan) evalRightJoinSets(set *xsql.JoinTupleSets, input xsql.Window
 		}
 	}
 	return newSets, nil
-}
+}

File diff suppressed because it is too large
+ 457 - 478
xsql/plans/join_test.go


+ 8 - 9
xsql/plans/math_func_test.go

@@ -13,8 +13,8 @@ import (
 
 func TestMathAndConversionFunc_Apply1(t *testing.T) {
 	var tests = []struct {
-		sql  string
-		data *xsql.Tuple
+		sql    string
+		data   *xsql.Tuple
 		result []map[string]interface{}
 	}{
 		{
@@ -22,7 +22,7 @@ func TestMathAndConversionFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : -1,
+					"a": -1,
 				},
 			},
 			result: []map[string]interface{}{{
@@ -35,7 +35,7 @@ func TestMathAndConversionFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : -1.1,
+					"a": -1.1,
 				},
 			},
 			result: []map[string]interface{}{{
@@ -48,7 +48,7 @@ func TestMathAndConversionFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : 1.1,
+					"a": 1.1,
 				},
 			},
 			result: []map[string]interface{}{{
@@ -451,7 +451,6 @@ func TestMathAndConversionFunc_Apply1(t *testing.T) {
 				"a": float64(3.00),
 			}},
 		},
-
 	}
 
 	fmt.Printf("The test bucket size is %d.\n\n", len(tests))
@@ -462,11 +461,11 @@ func TestMathAndConversionFunc_Apply1(t *testing.T) {
 		stmt, err := xsql.NewParser(strings.NewReader(tt.sql)).Parse()
 		if err != nil && tt.result == nil {
 			continue
-		} else if err != nil && tt.result != nil{
+		} else if err != nil && tt.result != nil {
 			t.Errorf("%q", err)
 			continue
 		}
-		pp := &ProjectPlan{Fields:stmt.Fields}
+		pp := &ProjectPlan{Fields: stmt.Fields}
 		pp.isTest = true
 		result := pp.Apply(ctx, tt.data)
 		var mapRes []map[string]interface{}
@@ -485,4 +484,4 @@ func TestMathAndConversionFunc_Apply1(t *testing.T) {
 			t.Errorf("The returned result is not type of []byte\n")
 		}
 	}
-}
+}

+ 30 - 31
xsql/plans/misc_func_test.go

@@ -13,8 +13,8 @@ import (
 
 func TestHashFunc_Apply1(t *testing.T) {
 	var tests = []struct {
-		sql  string
-		data *xsql.Tuple
+		sql    string
+		data   *xsql.Tuple
 		result []map[string]interface{}
 	}{
 		{
@@ -22,9 +22,9 @@ func TestHashFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "The quick brown fox jumps over the lazy dog",
-					"b" : "myb",
-					"c" : "myc",
+					"a": "The quick brown fox jumps over the lazy dog",
+					"b": "myb",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -36,9 +36,9 @@ func TestHashFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "The quick brown fox jumps over the lazy dog",
-					"b" : "myb",
-					"c" : "myc",
+					"a": "The quick brown fox jumps over the lazy dog",
+					"b": "myb",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -50,9 +50,9 @@ func TestHashFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "The quick brown fox jumps over the lazy dog",
-					"b" : "myb",
-					"c" : "myc",
+					"a": "The quick brown fox jumps over the lazy dog",
+					"b": "myb",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -64,9 +64,9 @@ func TestHashFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "The quick brown fox jumps over the lazy dog",
-					"b" : "myb",
-					"c" : "myc",
+					"a": "The quick brown fox jumps over the lazy dog",
+					"b": "myb",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -78,9 +78,9 @@ func TestHashFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "The quick brown fox jumps over the lazy dog",
-					"b" : "myb",
-					"c" : "myc",
+					"a": "The quick brown fox jumps over the lazy dog",
+					"b": "myb",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -93,7 +93,7 @@ func TestHashFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					xsql.INTERNAL_MQTT_TOPIC_KEY : "devices/device_001/message",
+					xsql.INTERNAL_MQTT_TOPIC_KEY: "devices/device_001/message",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -106,7 +106,7 @@ func TestHashFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					xsql.INTERNAL_MQTT_TOPIC_KEY : "devices/device_001/message",
+					xsql.INTERNAL_MQTT_TOPIC_KEY: "devices/device_001/message",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -119,16 +119,15 @@ func TestHashFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"topic" : "fff",
-					xsql.INTERNAL_MQTT_TOPIC_KEY : "devices/device_001/message",
+					"topic":                      "fff",
+					xsql.INTERNAL_MQTT_TOPIC_KEY: "devices/device_001/message",
 				},
 			},
 			result: []map[string]interface{}{{
 				"topic": "fff",
-				"a": "devices/device_001/message",
+				"a":     "devices/device_001/message",
 			}},
 		},
-
 	}
 
 	fmt.Printf("The test bucket size is %d.\n\n", len(tests))
@@ -139,7 +138,7 @@ func TestHashFunc_Apply1(t *testing.T) {
 		if err != nil || stmt == nil {
 			t.Errorf("parse sql %s error %v", tt.sql, err)
 		}
-		pp := &ProjectPlan{Fields:stmt.Fields}
+		pp := &ProjectPlan{Fields: stmt.Fields}
 		pp.isTest = true
 		result := pp.Apply(ctx, tt.data)
 		var mapRes []map[string]interface{}
@@ -161,8 +160,8 @@ func TestHashFunc_Apply1(t *testing.T) {
 }
 func TestMqttFunc_Apply2(t *testing.T) {
 	var tests = []struct {
-		sql  string
-		data xsql.JoinTupleSets
+		sql    string
+		data   xsql.JoinTupleSets
 		result []map[string]interface{}
 	}{
 		{
@@ -170,15 +169,15 @@ func TestMqttFunc_Apply2(t *testing.T) {
 			data: xsql.JoinTupleSets{
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : "1", "f1" : "v1" , xsql.INTERNAL_MQTT_TOPIC_KEY: "devices/type1/device001"},},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : "1", "f2" : "w1", xsql.INTERNAL_MQTT_TOPIC_KEY: "devices/type2/device001" },},
+						{Emitter: "src1", Message: xsql.Message{"id1": "1", "f1": "v1", xsql.INTERNAL_MQTT_TOPIC_KEY: "devices/type1/device001"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": "1", "f2": "w1", xsql.INTERNAL_MQTT_TOPIC_KEY: "devices/type2/device001"}},
 					},
 				},
 			},
 			result: []map[string]interface{}{{
 				"id1": "1",
-				"a": "devices/type1/device001",
-				"b": "devices/type2/device001",
+				"a":   "devices/type1/device001",
+				"b":   "devices/type2/device001",
 			}},
 		},
 	}
@@ -191,7 +190,7 @@ func TestMqttFunc_Apply2(t *testing.T) {
 		if err != nil || stmt == nil {
 			t.Errorf("parse sql %s error %v", tt.sql, err)
 		}
-		pp := &ProjectPlan{Fields:stmt.Fields}
+		pp := &ProjectPlan{Fields: stmt.Fields}
 		pp.isTest = true
 		result := pp.Apply(ctx, tt.data)
 		var mapRes []map[string]interface{}

+ 3 - 3
xsql/plans/order_operator.go

@@ -10,8 +10,8 @@ type OrderPlan struct {
 }
 
 /**
-  *  input: *xsql.Tuple from preprocessor | xsql.WindowTuplesSet from windowOp | xsql.JoinTupleSets from joinOp
-  *  output: *xsql.Tuple | xsql.WindowTuplesSet | xsql.JoinTupleSets
+ *  input: *xsql.Tuple from preprocessor | xsql.WindowTuplesSet from windowOp | xsql.JoinTupleSets from joinOp
+ *  output: *xsql.Tuple | xsql.WindowTuplesSet | xsql.JoinTupleSets
  */
 func (p *OrderPlan) Apply(ctx api.StreamContext, data interface{}) interface{} {
 	log := ctx.GetLogger()
@@ -27,4 +27,4 @@ func (p *OrderPlan) Apply(ctx api.StreamContext, data interface{}) interface{} {
 		log.Errorf("Expect xsql.Valuer or its array type.")
 		return nil
 	}
-}
+}

+ 92 - 92
xsql/plans/order_test.go

@@ -12,8 +12,8 @@ import (
 
 func TestOrderPlan_Apply(t *testing.T) {
 	var tests = []struct {
-		sql  string
-		data interface{}
+		sql    string
+		data   interface{}
 		result interface{}
 	}{
 		{
@@ -21,13 +21,13 @@ func TestOrderPlan_Apply(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "tbl",
 				Message: xsql.Message{
-					"abc" : int64(6),
+					"abc": int64(6),
 				},
 			},
 			result: &xsql.Tuple{
 				Emitter: "tbl",
 				Message: xsql.Message{
-					"abc" : int64(6),
+					"abc": int64(6),
 				},
 			},
 		},
@@ -37,15 +37,15 @@ func TestOrderPlan_Apply(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "tbl",
 				Message: xsql.Message{
-					"abc" : int64(34),
-					"def" : "hello",
+					"abc": int64(34),
+					"def": "hello",
 				},
 			},
 			result: &xsql.Tuple{
 				Emitter: "tbl",
 				Message: xsql.Message{
-					"abc" : int64(34),
-					"def" : "hello",
+					"abc": int64(34),
+					"def": "hello",
 				},
 			},
 		},
@@ -54,34 +54,34 @@ func TestOrderPlan_Apply(t *testing.T) {
 			sql: "SELECT id1 FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10) ORDER BY id1 DESC",
 			data: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 1, "f1" : "v1", },
-						},{
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 2, "f1" : "v2", },
-						},{
+							Message: xsql.Message{"id1": 2, "f1": "v2"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 3, "f1" : "v1", },
+							Message: xsql.Message{"id1": 3, "f1": "v1"},
 						},
 					},
 				},
 			},
 			result: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 3, "f1" : "v1", },
-						},{
+							Message: xsql.Message{"id1": 3, "f1": "v1"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 2, "f1" : "v2", },
-						},{
+							Message: xsql.Message{"id1": 2, "f1": "v2"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 1, "f1" : "v1", },
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
 						},
 					},
 				},
@@ -92,34 +92,34 @@ func TestOrderPlan_Apply(t *testing.T) {
 			sql: "SELECT * FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10) ORDER BY f1, id1 DESC",
 			data: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 1, "f1" : "v1", },
-						},{
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 2, "f1" : "v2", },
-						},{
+							Message: xsql.Message{"id1": 2, "f1": "v2"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 3, "f1" : "v1", },
+							Message: xsql.Message{"id1": 3, "f1": "v1"},
 						},
 					},
 				},
 			},
 			result: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 3, "f1" : "v1", },
-						},{
+							Message: xsql.Message{"id1": 3, "f1": "v1"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 1, "f1" : "v1", },
-						},{
+							Message: xsql.Message{"id1": 1, "f1": "v1"},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 2, "f1" : "v2", },
+							Message: xsql.Message{"id1": 2, "f1": "v2"},
 						},
 					},
 				},
@@ -129,34 +129,34 @@ func TestOrderPlan_Apply(t *testing.T) {
 			sql: "SELECT * FROM src1 GROUP BY TUMBLINGWINDOW(ss, 10) ORDER BY ts DESC",
 			data: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 1, "f1" : "v1", "ts": common.TimeFromUnixMilli(1568854515000)},
-						},{
+							Message: xsql.Message{"id1": 1, "f1": "v1", "ts": common.TimeFromUnixMilli(1568854515000)},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 2, "f1" : "v2", "ts": common.TimeFromUnixMilli(1568854525000)},
-						},{
+							Message: xsql.Message{"id1": 2, "f1": "v2", "ts": common.TimeFromUnixMilli(1568854525000)},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 3, "f1" : "v1", "ts": common.TimeFromUnixMilli(1568854535000)},
+							Message: xsql.Message{"id1": 3, "f1": "v1", "ts": common.TimeFromUnixMilli(1568854535000)},
 						},
 					},
 				},
 			},
 			result: xsql.WindowTuplesSet{
 				xsql.WindowTuples{
-					Emitter:"src1",
-					Tuples:[]xsql.Tuple{
+					Emitter: "src1",
+					Tuples: []xsql.Tuple{
 						{
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 3, "f1" : "v1", "ts": common.TimeFromUnixMilli(1568854535000)},
-						},{
+							Message: xsql.Message{"id1": 3, "f1": "v1", "ts": common.TimeFromUnixMilli(1568854535000)},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 2, "f1" : "v2", "ts": common.TimeFromUnixMilli(1568854525000)},
-						},{
+							Message: xsql.Message{"id1": 2, "f1": "v2", "ts": common.TimeFromUnixMilli(1568854525000)},
+						}, {
 							Emitter: "src1",
-							Message: xsql.Message{ "id1" : 1, "f1" : "v1", "ts": common.TimeFromUnixMilli(1568854515000)},
+							Message: xsql.Message{"id1": 1, "f1": "v1", "ts": common.TimeFromUnixMilli(1568854515000)},
 						},
 					},
 				},
@@ -168,38 +168,38 @@ func TestOrderPlan_Apply(t *testing.T) {
 			data: xsql.JoinTupleSets{
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 1, "f1" : "v1",},},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 2, "f2" : "w2",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 					},
 				},
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 2, "f1" : "v2",},},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 4, "f2" : "w3",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 					},
 				},
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 3, "f1" : "v1",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 					},
 				},
 			},
 			result: xsql.JoinTupleSets{
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 3, "f1" : "v1",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 					},
 				},
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 2, "f1" : "v2",},},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 4, "f2" : "w3",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 					},
 				},
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 1, "f1" : "v1",},},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 2, "f2" : "w2",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 					},
 				},
 			},
@@ -209,38 +209,38 @@ func TestOrderPlan_Apply(t *testing.T) {
 			data: xsql.JoinTupleSets{
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 1, "f1" : "v1",},},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 2, "f2" : "w2",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 					},
 				},
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 2, "f1" : "v2",},},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 4, "f2" : "w3",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 					},
 				},
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 3, "f1" : "v1",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 					},
 				},
 			},
 			result: xsql.JoinTupleSets{
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 1, "f1" : "v1",},},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 2, "f2" : "w2",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 					},
 				},
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 2, "f1" : "v2",},},
-						{Emitter: "src2", Message: xsql.Message{ "id2" : 4, "f2" : "w3",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
+						{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 					},
 				},
 				xsql.JoinTuple{
 					Tuples: []xsql.Tuple{
-						{Emitter: "src1", Message: xsql.Message{ "id1" : 3, "f1" : "v1",},},
+						{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 					},
 				},
 			},
@@ -253,19 +253,19 @@ func TestOrderPlan_Apply(t *testing.T) {
 					&xsql.Tuple{
 						Emitter: "tbl",
 						Message: xsql.Message{
-							"abc" : int64(6),
-							"def" : "hello",
+							"abc": int64(6),
+							"def": "hello",
 						},
 					},
 				},
 			},
-			result:xsql.GroupedTuplesSet{
+			result: xsql.GroupedTuplesSet{
 				{
 					&xsql.Tuple{
 						Emitter: "tbl",
 						Message: xsql.Message{
-							"abc" : int64(6),
-							"def" : "hello",
+							"abc": int64(6),
+							"def": "hello",
 						},
 					},
 				},
@@ -277,17 +277,17 @@ func TestOrderPlan_Apply(t *testing.T) {
 				{
 					&xsql.Tuple{
 						Emitter: "src1",
-						Message: xsql.Message{ "id1" : 1, "f1" : "v1", },
+						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					},
 					&xsql.Tuple{
 						Emitter: "src1",
-						Message: xsql.Message{ "id1" : 3, "f1" : "v1", },
+						Message: xsql.Message{"id1": 3, "f1": "v1"},
 					},
 				},
 				{
 					&xsql.Tuple{
 						Emitter: "src1",
-						Message: xsql.Message{ "id1" : 2, "f1" : "v2", },
+						Message: xsql.Message{"id1": 2, "f1": "v2"},
 					},
 				},
 			},
@@ -295,17 +295,17 @@ func TestOrderPlan_Apply(t *testing.T) {
 				{
 					&xsql.Tuple{
 						Emitter: "src1",
-						Message: xsql.Message{ "id1" : 2, "f1" : "v2", },
+						Message: xsql.Message{"id1": 2, "f1": "v2"},
 					},
 				},
 				{
 					&xsql.Tuple{
 						Emitter: "src1",
-						Message: xsql.Message{ "id1" : 1, "f1" : "v1", },
+						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					},
 					&xsql.Tuple{
 						Emitter: "src1",
-						Message: xsql.Message{ "id1" : 3, "f1" : "v1", },
+						Message: xsql.Message{"id1": 3, "f1": "v1"},
 					},
 				},
 			},
@@ -316,23 +316,23 @@ func TestOrderPlan_Apply(t *testing.T) {
 				{
 					&xsql.JoinTuple{
 						Tuples: []xsql.Tuple{
-							{Emitter: "src1", Message: xsql.Message{ "id1" : 1, "f1" : "v1",},},
-							{Emitter: "src2", Message: xsql.Message{ "id2" : 2, "f2" : "w2",},},
+							{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
+							{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 						},
 					},
 				},
 				{
 					&xsql.JoinTuple{
 						Tuples: []xsql.Tuple{
-							{Emitter: "src1", Message: xsql.Message{ "id1" : 2, "f1" : "v2",},},
-							{Emitter: "src2", Message: xsql.Message{ "id2" : 4, "f2" : "w3",},},
+							{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
+							{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 						},
 					},
 				},
 				{
 					&xsql.JoinTuple{
 						Tuples: []xsql.Tuple{
-							{Emitter: "src1", Message: xsql.Message{ "id1" : 3, "f1" : "v1",},},
+							{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 						},
 					},
 				},
@@ -341,23 +341,23 @@ func TestOrderPlan_Apply(t *testing.T) {
 				{
 					&xsql.JoinTuple{
 						Tuples: []xsql.Tuple{
-							{Emitter: "src1", Message: xsql.Message{ "id1" : 3, "f1" : "v1",},},
+							{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 						},
 					},
 				},
 				{
 					&xsql.JoinTuple{
 						Tuples: []xsql.Tuple{
-							{Emitter: "src1", Message: xsql.Message{ "id1" : 2, "f1" : "v2",},},
-							{Emitter: "src2", Message: xsql.Message{ "id2" : 4, "f2" : "w3",},},
+							{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
+							{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 						},
 					},
 				},
 				{
 					&xsql.JoinTuple{
 						Tuples: []xsql.Tuple{
-							{Emitter: "src1", Message: xsql.Message{ "id1" : 1, "f1" : "v1",},},
-							{Emitter: "src2", Message: xsql.Message{ "id2" : 2, "f2" : "w2",},},
+							{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
+							{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 						},
 					},
 				},
@@ -375,7 +375,7 @@ func TestOrderPlan_Apply(t *testing.T) {
 			break
 		}
 
-		pp := &OrderPlan{SortFields:stmt.SortFields}
+		pp := &OrderPlan{SortFields: stmt.SortFields}
 		result := pp.Apply(ctx, tt.data)
 		if !reflect.DeepEqual(tt.result, result) {
 			t.Errorf("%d. %q\n\nresult mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.sql, tt.result, result)

+ 83 - 83
xsql/plans/preprocessor.go

@@ -13,22 +13,22 @@ import (
 )
 
 type Preprocessor struct {
-	streamStmt  *xsql.StreamStmt
-	fields xsql.Fields
-	isEventTime bool
-	timestampField string
+	streamStmt      *xsql.StreamStmt
+	fields          xsql.Fields
+	isEventTime     bool
+	timestampField  string
 	timestampFormat string
 }
 
-func NewPreprocessor(s *xsql.StreamStmt, fs xsql.Fields, iet bool) (*Preprocessor, error){
+func NewPreprocessor(s *xsql.StreamStmt, fs xsql.Fields, iet bool) (*Preprocessor, error) {
 	p := &Preprocessor{streamStmt: s, fields: fs, isEventTime: iet}
 	if iet {
-		if tf, ok := s.Options["TIMESTAMP"]; ok{
+		if tf, ok := s.Options["TIMESTAMP"]; ok {
 			p.timestampField = tf
-		}else{
+		} else {
 			return nil, fmt.Errorf("preprocessor is set to be event time but stream option TIMESTAMP not found")
 		}
-		if ts, ok := s.Options["TIMESTAMP_FORMAT"]; ok{
+		if ts, ok := s.Options["TIMESTAMP_FORMAT"]; ok {
 			p.timestampFormat = ts
 		}
 	}
@@ -53,7 +53,7 @@ func (p *Preprocessor) Apply(ctx api.StreamContext, data interface{}) interface{
 	result := make(map[string]interface{})
 	for _, f := range p.streamStmt.StreamFields {
 		fname := strings.ToLower(f.Name)
-		if e := p.addRecField(f.FieldType, result, tuple.Message, fname); e != nil{
+		if e := p.addRecField(f.FieldType, result, tuple.Message, fname); e != nil {
 			log.Errorf("error in preprocessor: %s", e)
 			return nil
 		}
@@ -71,16 +71,16 @@ func (p *Preprocessor) Apply(ctx api.StreamContext, data interface{}) interface{
 	}
 
 	tuple.Message = result
-	if p.isEventTime{
-		if t, ok := result[p.timestampField]; ok{
-			if ts, err := common.InterfaceToUnixMilli(t, p.timestampFormat); err != nil{
+	if p.isEventTime {
+		if t, ok := result[p.timestampField]; ok {
+			if ts, err := common.InterfaceToUnixMilli(t, p.timestampFormat); err != nil {
 				log.Errorf("cannot convert timestamp field %s to timestamp with error %v", p.timestampField, err)
 				return nil
-			}else{
+			} else {
 				tuple.Timestamp = ts
 				log.Debugf("preprocessor calculate timstamp %d", tuple.Timestamp)
 			}
-		}else{
+		} else {
 			log.Errorf("cannot find timestamp field %s in tuple %v", p.timestampField, result)
 			return nil
 		}
@@ -88,10 +88,10 @@ func (p *Preprocessor) Apply(ctx api.StreamContext, data interface{}) interface{
 	return tuple
 }
 
-func (p *Preprocessor) parseTime(s string) (time.Time, error){
-	if f, ok := p.streamStmt.Options["TIMESTAMP_FORMAT"]; ok{
+func (p *Preprocessor) parseTime(s string) (time.Time, error) {
+	if f, ok := p.streamStmt.Options["TIMESTAMP_FORMAT"]; ok {
 		return common.ParseTime(s, f)
-	}else{
+	} else {
 		return time.Parse(common.JSISO, s)
 	}
 }
@@ -106,35 +106,35 @@ func (p *Preprocessor) addRecField(ft xsql.FieldType, r map[string]interface{},
 			case xsql.UNKNOWN:
 				return fmt.Errorf("invalid data type unknown defined for %s, please check the stream definition", t)
 			case xsql.BIGINT:
-				if jtype == reflect.Int{
+				if jtype == reflect.Int {
 					r[n] = t.(int)
-				}else if jtype == reflect.Float64{
+				} else if jtype == reflect.Float64 {
 					r[n] = int(t.(float64))
-				}else if jtype == reflect.String {
-					if i, err := strconv.Atoi(t.(string)); err != nil{
+				} else if jtype == reflect.String {
+					if i, err := strconv.Atoi(t.(string)); err != nil {
 						return fmt.Errorf("invalid data type for %s, expect bigint but found %s", n, t)
-					}else{
+					} else {
 						r[n] = i
 					}
-				}else{
+				} else {
 					return fmt.Errorf("invalid data type for %s, expect bigint but found %s", n, t)
 				}
 			case xsql.FLOAT:
-				if jtype == reflect.Float64{
+				if jtype == reflect.Float64 {
 					r[n] = t.(float64)
-				}else if jtype == reflect.String {
-					if f, err := strconv.ParseFloat(t.(string), 64); err != nil{
+				} else if jtype == reflect.String {
+					if f, err := strconv.ParseFloat(t.(string), 64); err != nil {
 						return fmt.Errorf("invalid data type for %s, expect float but found %s", n, t)
-					}else{
+					} else {
 						r[n] = f
 					}
-				}else{
+				} else {
 					return fmt.Errorf("invalid data type for %s, expect float but found %s", n, t)
 				}
 			case xsql.STRINGS:
-				if jtype == reflect.String{
+				if jtype == reflect.String {
 					r[n] = t.(string)
-				}else{
+				} else {
 					return fmt.Errorf("invalid data type for %s, expect string but found %s", n, t)
 				}
 			case xsql.DATETIME:
@@ -146,24 +146,24 @@ func (p *Preprocessor) addRecField(ft xsql.FieldType, r map[string]interface{},
 					ai := int64(t.(float64))
 					r[n] = common.TimeFromUnixMilli(ai)
 				case reflect.String:
-					if t, err := p.parseTime(t.(string)); err != nil{
+					if t, err := p.parseTime(t.(string)); err != nil {
 						return fmt.Errorf("invalid data type for %s, cannot convert to datetime: %s", n, err)
-					}else{
+					} else {
 						r[n] = t
 					}
 				default:
 					return fmt.Errorf("invalid data type for %s, expect datatime but find %v", n, t)
 				}
 			case xsql.BOOLEAN:
-				if jtype == reflect.Bool{
+				if jtype == reflect.Bool {
 					r[n] = t.(bool)
-				}else if jtype == reflect.String {
-					if i, err := strconv.ParseBool(t.(string)); err != nil{
+				} else if jtype == reflect.String {
+					if i, err := strconv.ParseBool(t.(string)); err != nil {
 						return fmt.Errorf("invalid data type for %s, expect boolean but found %s", n, t)
-					}else{
+					} else {
 						r[n] = i
 					}
-				}else{
+				} else {
 					return fmt.Errorf("invalid data type for %s, expect boolean but found %s", n, t)
 				}
 			default:
@@ -171,41 +171,41 @@ func (p *Preprocessor) addRecField(ft xsql.FieldType, r map[string]interface{},
 			}
 		case *xsql.ArrayType:
 			var s []interface{}
-			if jtype == reflect.Slice{
+			if jtype == reflect.Slice {
 				s = t.([]interface{})
-			}else if jtype == reflect.String {
+			} else if jtype == reflect.String {
 				err := json.Unmarshal([]byte(t.(string)), &s)
-				if err != nil{
+				if err != nil {
 					return fmt.Errorf("invalid data type for %s, expect array but found %s", n, t)
 				}
-			}else{
+			} else {
 				return fmt.Errorf("invalid data type for %s, expect array but found %s", n, t)
 			}
 
-			if tempArr, err := p.addArrayField(st, s); err !=nil{
+			if tempArr, err := p.addArrayField(st, s); err != nil {
 				return err
-			}else {
+			} else {
 				r[n] = tempArr
 			}
 		case *xsql.RecType:
 			nextJ := make(map[string]interface{})
-			if jtype == reflect.Map{
+			if jtype == reflect.Map {
 				nextJ, ok = t.(map[string]interface{})
 				if !ok {
 					return fmt.Errorf("invalid data type for %s, expect map but found %s", n, t)
 				}
-			}else if jtype == reflect.String {
+			} else if jtype == reflect.String {
 				err := json.Unmarshal([]byte(t.(string)), &nextJ)
-				if err != nil{
+				if err != nil {
 					return fmt.Errorf("invalid data type for %s, expect map but found %s", n, t)
 				}
-			}else{
+			} else {
 				return fmt.Errorf("invalid data type for %s, expect struct but found %s", n, t)
 			}
 			nextR := make(map[string]interface{})
 			for _, nextF := range st.StreamFields {
 				nextP := strings.ToLower(nextF.Name)
-				if e := p.addRecField(nextF.FieldType, nextR, nextJ, nextP); e != nil{
+				if e := p.addRecField(nextF.FieldType, nextR, nextJ, nextP); e != nil {
 					return e
 				}
 			}
@@ -214,7 +214,7 @@ func (p *Preprocessor) addRecField(ft xsql.FieldType, r map[string]interface{},
 			return fmt.Errorf("unsupported type %T", st)
 		}
 		return nil
-	}else{
+	} else {
 		return fmt.Errorf("invalid data %s, field %s not found", j, n)
 	}
 }
@@ -227,49 +227,49 @@ func (p *Preprocessor) addArrayField(ft *xsql.ArrayType, srcSlice []interface{})
 		case *xsql.ArrayType: //TODO handle array of array. Now the type is treated as interface{}
 			var tempSlice [][]interface{}
 			var s []interface{}
-			for i, t := range srcSlice{
+			for i, t := range srcSlice {
 				jtype := reflect.ValueOf(t).Kind()
-				if jtype == reflect.Slice || jtype == reflect.Array{
+				if jtype == reflect.Slice || jtype == reflect.Array {
 					s = t.([]interface{})
-				}else if jtype == reflect.String {
+				} else if jtype == reflect.String {
 					err := json.Unmarshal([]byte(t.(string)), &s)
-					if err != nil{
+					if err != nil {
 						return nil, fmt.Errorf("invalid data type for [%d], expect array but found %s", i, t)
 					}
-				}else{
+				} else {
 					return nil, fmt.Errorf("invalid data type for [%d], expect array but found %s", i, t)
 				}
-				if tempArr, err := p.addArrayField(st, s); err !=nil{
+				if tempArr, err := p.addArrayField(st, s); err != nil {
 					return nil, err
-				}else {
+				} else {
 					tempSlice = append(tempSlice, tempArr.([]interface{}))
 				}
 			}
 			return tempSlice, nil
 		case *xsql.RecType:
 			var tempSlice []map[string]interface{}
-			for i, t := range srcSlice{
+			for i, t := range srcSlice {
 				jtype := reflect.ValueOf(t).Kind()
 				j := make(map[string]interface{})
 				var ok bool
-				if jtype == reflect.Map{
+				if jtype == reflect.Map {
 					j, ok = t.(map[string]interface{})
 					if !ok {
 						return nil, fmt.Errorf("invalid data type for [%d], expect map but found %s", i, t)
 					}
 
-				}else if jtype == reflect.String {
+				} else if jtype == reflect.String {
 					err := json.Unmarshal([]byte(t.(string)), &j)
-					if err != nil{
+					if err != nil {
 						return nil, fmt.Errorf("invalid data type for [%d], expect map but found %s", i, t)
 					}
-				}else{
+				} else {
 					return nil, fmt.Errorf("invalid data type for [%d], expect map but found %s", i, t)
 				}
 				r := make(map[string]interface{})
 				for _, f := range st.StreamFields {
 					n := f.Name
-					if e := p.addRecField(f.FieldType, r, j, n); e != nil{
+					if e := p.addRecField(f.FieldType, r, j, n); e != nil {
 						return nil, e
 					}
 				}
@@ -279,7 +279,7 @@ func (p *Preprocessor) addArrayField(ft *xsql.ArrayType, srcSlice []interface{})
 		default:
 			return nil, fmt.Errorf("unsupported type %T", st)
 		}
-	}else{ //basic type
+	} else { //basic type
 		switch ft.Type {
 		case xsql.UNKNOWN:
 			return nil, fmt.Errorf("invalid data type unknown defined for %s, please checke the stream definition", srcSlice)
@@ -287,15 +287,15 @@ func (p *Preprocessor) addArrayField(ft *xsql.ArrayType, srcSlice []interface{})
 			var tempSlice []int
 			for i, t := range srcSlice {
 				jtype := reflect.ValueOf(t).Kind()
-				if jtype == reflect.Float64{
+				if jtype == reflect.Float64 {
 					tempSlice = append(tempSlice, int(t.(float64)))
-				}else if jtype == reflect.String {
-					if v, err := strconv.Atoi(t.(string)); err != nil{
+				} else if jtype == reflect.String {
+					if v, err := strconv.Atoi(t.(string)); err != nil {
 						return nil, fmt.Errorf("invalid data type for [%d], expect float but found %s", i, t)
-					}else{
+					} else {
 						tempSlice = append(tempSlice, v)
 					}
-				}else{
+				} else {
 					return nil, fmt.Errorf("invalid data type for [%d], expect float but found %s", i, t)
 				}
 			}
@@ -304,15 +304,15 @@ func (p *Preprocessor) addArrayField(ft *xsql.ArrayType, srcSlice []interface{})
 			var tempSlice []float64
 			for i, t := range srcSlice {
 				jtype := reflect.ValueOf(t).Kind()
-				if jtype == reflect.Float64{
+				if jtype == reflect.Float64 {
 					tempSlice = append(tempSlice, t.(float64))
-				}else if jtype == reflect.String {
-					if f, err := strconv.ParseFloat(t.(string), 64); err != nil{
+				} else if jtype == reflect.String {
+					if f, err := strconv.ParseFloat(t.(string), 64); err != nil {
 						return nil, fmt.Errorf("invalid data type for [%d], expect float but found %s", i, t)
-					}else{
+					} else {
 						tempSlice = append(tempSlice, f)
 					}
-				}else{
+				} else {
 					return nil, fmt.Errorf("invalid data type for [%d], expect float but found %s", i, t)
 				}
 			}
@@ -320,9 +320,9 @@ func (p *Preprocessor) addArrayField(ft *xsql.ArrayType, srcSlice []interface{})
 		case xsql.STRINGS:
 			var tempSlice []string
 			for i, t := range srcSlice {
-				if reflect.ValueOf(t).Kind() == reflect.String{
+				if reflect.ValueOf(t).Kind() == reflect.String {
 					tempSlice = append(tempSlice, t.(string))
-				}else{
+				} else {
 					return nil, fmt.Errorf("invalid data type for [%d], expect string but found %s", i, t)
 				}
 			}
@@ -339,9 +339,9 @@ func (p *Preprocessor) addArrayField(ft *xsql.ArrayType, srcSlice []interface{})
 					ai := int64(t.(float64))
 					tempSlice = append(tempSlice, common.TimeFromUnixMilli(ai))
 				case reflect.String:
-					if ai, err := p.parseTime(t.(string)); err != nil{
+					if ai, err := p.parseTime(t.(string)); err != nil {
 						return nil, fmt.Errorf("invalid data type for %s, cannot convert to datetime: %s", t, err)
-					}else{
+					} else {
 						tempSlice = append(tempSlice, ai)
 					}
 				default:
@@ -353,15 +353,15 @@ func (p *Preprocessor) addArrayField(ft *xsql.ArrayType, srcSlice []interface{})
 			var tempSlice []bool
 			for i, t := range srcSlice {
 				jtype := reflect.ValueOf(t).Kind()
-				if jtype == reflect.Bool{
+				if jtype == reflect.Bool {
 					tempSlice = append(tempSlice, t.(bool))
-				}else if jtype == reflect.String {
-					if v, err := strconv.ParseBool(t.(string)); err != nil{
+				} else if jtype == reflect.String {
+					if v, err := strconv.ParseBool(t.(string)); err != nil {
 						return nil, fmt.Errorf("invalid data type for [%d], expect boolean but found %s", i, t)
-					}else{
+					} else {
 						tempSlice = append(tempSlice, v)
 					}
-				}else{
+				} else {
 					return nil, fmt.Errorf("invalid data type for [%d], expect boolean but found %s", i, t)
 				}
 			}
@@ -370,4 +370,4 @@ func (p *Preprocessor) addArrayField(ft *xsql.ArrayType, srcSlice []interface{})
 			return nil, fmt.Errorf("invalid data type for %T, datetime type is not supported yet", ft.Type)
 		}
 	}
-}
+}

+ 62 - 62
xsql/plans/preprocessor_test.go

@@ -15,8 +15,8 @@ import (
 func TestPreprocessor_Apply(t *testing.T) {
 
 	var tests = []struct {
-		stmt *xsql.StreamStmt
-		data []byte
+		stmt   *xsql.StreamStmt
+		data   []byte
 		result interface{}
 	}{
 		//Basic type
@@ -27,7 +27,7 @@ func TestPreprocessor_Apply(t *testing.T) {
 					{Name: "abc", FieldType: &xsql.BasicType{Type: xsql.BIGINT}},
 				},
 			},
-			data: []byte(`{"a": 6}`),
+			data:   []byte(`{"a": 6}`),
 			result: nil,
 		},
 
@@ -40,8 +40,8 @@ func TestPreprocessor_Apply(t *testing.T) {
 			},
 			data: []byte(`{"abc": 6}`),
 			result: &xsql.Tuple{Message: xsql.Message{
-					"abc": int(6),
-				},
+				"abc": int(6),
+			},
 			},
 		},
 		{
@@ -56,7 +56,7 @@ func TestPreprocessor_Apply(t *testing.T) {
 			result: &xsql.Tuple{Message: xsql.Message{
 				"abc": float64(34),
 				"def": "hello",
-				},
+			},
 			},
 		},
 		{
@@ -82,7 +82,7 @@ func TestPreprocessor_Apply(t *testing.T) {
 					{Name: "def", FieldType: &xsql.BasicType{Type: xsql.BOOLEAN}},
 				},
 			},
-			data: []byte(`{"abc": 77, "def" : "hello"}`),
+			data:   []byte(`{"abc": 77, "def" : "hello"}`),
 			result: nil,
 		},
 		{
@@ -93,7 +93,7 @@ func TestPreprocessor_Apply(t *testing.T) {
 					{Name: "def", FieldType: &xsql.BasicType{Type: xsql.BOOLEAN}},
 				},
 			},
-			data: []byte(`{"a": {"b" : "hello"}}`),
+			data:   []byte(`{"a": {"b" : "hello"}}`),
 			result: nil,
 		},
 		//Rec type
@@ -110,7 +110,7 @@ func TestPreprocessor_Apply(t *testing.T) {
 			},
 			data: []byte(`{"a": {"b" : "hello"}}`),
 			result: &xsql.Tuple{Message: xsql.Message{
-					"a": map[string]interface{}{
+				"a": map[string]interface{}{
 					"b": "hello",
 				},
 			},
@@ -153,12 +153,12 @@ func TestPreprocessor_Apply(t *testing.T) {
 			},
 			data: []byte(`{"a": [{"b" : "hello1"}, {"b" : "hello2"}]}`),
 			result: &xsql.Tuple{Message: xsql.Message{
-					"a": []map[string]interface{}{
-						{"b": "hello1"},
-						{"b": "hello2"},
-					},
+				"a": []map[string]interface{}{
+					{"b": "hello1"},
+					{"b": "hello2"},
 				},
 			},
+			},
 		},
 		{
 			stmt: &xsql.StreamStmt{
@@ -197,14 +197,14 @@ func TestPreprocessor_Apply(t *testing.T) {
 			},
 			data: []byte(`{"a": {"b" : "hello", "c": {"d": 35.2}}}`),
 			result: &xsql.Tuple{Message: xsql.Message{
-					"a": map[string]interface{}{
-						"b": "hello",
-						"c": map[string]interface{}{
-							"d": int(35),
-						},
+				"a": map[string]interface{}{
+					"b": "hello",
+					"c": map[string]interface{}{
+						"d": int(35),
 					},
 				},
 			},
+			},
 		},
 	}
 
@@ -222,7 +222,7 @@ func TestPreprocessor_Apply(t *testing.T) {
 			log.Fatal(e)
 			return
 		} else {
-			tuple := &xsql.Tuple{Message:dm}
+			tuple := &xsql.Tuple{Message: dm}
 			result := pp.Apply(ctx, tuple)
 			if !reflect.DeepEqual(tt.result, result) {
 				t.Errorf("%d. %q\n\nresult mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tuple, tt.result, result)
@@ -232,10 +232,10 @@ func TestPreprocessor_Apply(t *testing.T) {
 	}
 }
 
-func TestPreprocessorTime_Apply(t *testing.T){
+func TestPreprocessorTime_Apply(t *testing.T) {
 	var tests = []struct {
-		stmt *xsql.StreamStmt
-		data []byte
+		stmt   *xsql.StreamStmt
+		data   []byte
 		result interface{}
 	}{
 		{
@@ -261,7 +261,7 @@ func TestPreprocessorTime_Apply(t *testing.T){
 					{Name: "def", FieldType: &xsql.BasicType{Type: xsql.DATETIME}},
 				},
 			},
-			data: []byte(`{"abc": "2019-09-19T00:55:1dd5Z", "def" : 111568854573431}`),
+			data:   []byte(`{"abc": "2019-09-19T00:55:1dd5Z", "def" : 111568854573431}`),
 			result: nil,
 		},
 		{
@@ -272,13 +272,13 @@ func TestPreprocessorTime_Apply(t *testing.T){
 					{Name: "def", FieldType: &xsql.BasicType{Type: xsql.DATETIME}},
 				},
 				Options: map[string]string{
-					"DATASOURCE" : "users",
-					"FORMAT" : "AVRO",
-					"KEY" : "USERID",
-					"CONF_KEY" : "srv1",
-					"TYPE" : "MQTT",
-					"TIMESTAMP" : "USERID",
-					"TIMESTAMP_FORMAT" : "yyyy-MM-dd 'at' HH:mm:ss'Z'X",
+					"DATASOURCE":       "users",
+					"FORMAT":           "AVRO",
+					"KEY":              "USERID",
+					"CONF_KEY":         "srv1",
+					"TYPE":             "MQTT",
+					"TIMESTAMP":        "USERID",
+					"TIMESTAMP_FORMAT": "yyyy-MM-dd 'at' HH:mm:ss'Z'X",
 				},
 			},
 			data: []byte(`{"abc": "2019-09-19 at 18:55:15Z+07", "def" : 1568854573431}`),
@@ -343,11 +343,11 @@ func TestPreprocessorTime_Apply(t *testing.T){
 			log.Fatal(e)
 			return
 		} else {
-			tuple := &xsql.Tuple{Message:dm}
+			tuple := &xsql.Tuple{Message: dm}
 			result := pp.Apply(ctx, tuple)
 			//workaround make sure all the timezone are the same for time vars or the DeepEqual will be false.
-			if rt, ok := result.(*xsql.Tuple); ok{
-				if rtt, ok := rt.Message["abc"].(time.Time); ok{
+			if rt, ok := result.(*xsql.Tuple); ok {
+				if rtt, ok := rt.Message["abc"].(time.Time); ok {
 					rt.Message["abc"] = rtt.UTC()
 				}
 			}
@@ -362,8 +362,8 @@ func TestPreprocessorTime_Apply(t *testing.T){
 func TestPreprocessorEventtime_Apply(t *testing.T) {
 
 	var tests = []struct {
-		stmt *xsql.StreamStmt
-		data []byte
+		stmt   *xsql.StreamStmt
+		data   []byte
 		result interface{}
 	}{
 		//Basic type
@@ -374,13 +374,13 @@ func TestPreprocessorEventtime_Apply(t *testing.T) {
 					{Name: "abc", FieldType: &xsql.BasicType{Type: xsql.BIGINT}},
 				},
 				Options: map[string]string{
-					"DATASOURCE" : "users",
-					"FORMAT" : "AVRO",
-					"KEY" : "USERID",
-					"CONF_KEY" : "srv1",
-					"TYPE" : "MQTT",
-					"TIMESTAMP" : "abc",
-					"TIMESTAMP_FORMAT" : "yyyy-MM-dd''T''HH:mm:ssX'",
+					"DATASOURCE":       "users",
+					"FORMAT":           "AVRO",
+					"KEY":              "USERID",
+					"CONF_KEY":         "srv1",
+					"TYPE":             "MQTT",
+					"TIMESTAMP":        "abc",
+					"TIMESTAMP_FORMAT": "yyyy-MM-dd''T''HH:mm:ssX'",
 				},
 			},
 			data: []byte(`{"abc": 1568854515000}`),
@@ -396,11 +396,11 @@ func TestPreprocessorEventtime_Apply(t *testing.T) {
 					{Name: "abc", FieldType: &xsql.BasicType{Type: xsql.BOOLEAN}},
 				},
 				Options: map[string]string{
-					"DATASOURCE" : "users",
-					"TIMESTAMP" : "abc",
+					"DATASOURCE": "users",
+					"TIMESTAMP":  "abc",
 				},
 			},
-			data: []byte(`{"abc": true}`),
+			data:   []byte(`{"abc": true}`),
 			result: nil,
 		},
 		{
@@ -411,8 +411,8 @@ func TestPreprocessorEventtime_Apply(t *testing.T) {
 					{Name: "def", FieldType: &xsql.BasicType{Type: xsql.STRINGS}},
 				},
 				Options: map[string]string{
-					"DATASOURCE" : "users",
-					"TIMESTAMP" : "def",
+					"DATASOURCE": "users",
+					"TIMESTAMP":  "def",
 				},
 			},
 			data: []byte(`{"abc": 34, "def" : "2019-09-23T02:47:29.754Z", "ghi": 50}`),
@@ -430,8 +430,8 @@ func TestPreprocessorEventtime_Apply(t *testing.T) {
 					{Name: "def", FieldType: &xsql.BasicType{Type: xsql.DATETIME}},
 				},
 				Options: map[string]string{
-					"DATASOURCE" : "users",
-					"TIMESTAMP" : "abc",
+					"DATASOURCE": "users",
+					"TIMESTAMP":  "abc",
 				},
 			},
 			data: []byte(`{"abc": "2019-09-19T00:55:15.000Z", "def" : 1568854573431}`),
@@ -449,9 +449,9 @@ func TestPreprocessorEventtime_Apply(t *testing.T) {
 					{Name: "def", FieldType: &xsql.BasicType{Type: xsql.STRINGS}},
 				},
 				Options: map[string]string{
-					"DATASOURCE" : "users",
-					"TIMESTAMP" : "def",
-					"TIMESTAMP_FORMAT" : "yyyy-MM-dd'AT'HH:mm:ss",
+					"DATASOURCE":       "users",
+					"TIMESTAMP":        "def",
+					"TIMESTAMP_FORMAT": "yyyy-MM-dd'AT'HH:mm:ss",
 				},
 			},
 			data: []byte(`{"abc": 34, "def" : "2019-09-23AT02:47:29", "ghi": 50}`),
@@ -469,12 +469,12 @@ func TestPreprocessorEventtime_Apply(t *testing.T) {
 					{Name: "def", FieldType: &xsql.BasicType{Type: xsql.STRINGS}},
 				},
 				Options: map[string]string{
-					"DATASOURCE" : "users",
-					"TIMESTAMP" : "def",
-					"TIMESTAMP_FORMAT" : "yyyy-MM-ddaHH:mm:ss",
+					"DATASOURCE":       "users",
+					"TIMESTAMP":        "def",
+					"TIMESTAMP_FORMAT": "yyyy-MM-ddaHH:mm:ss",
 				},
 			},
-			data: []byte(`{"abc": 34, "def" : "2019-09-23AT02:47:29", "ghi": 50}`),
+			data:   []byte(`{"abc": 34, "def" : "2019-09-23AT02:47:29", "ghi": 50}`),
 			result: nil,
 		},
 	}
@@ -486,8 +486,8 @@ func TestPreprocessorEventtime_Apply(t *testing.T) {
 	ctx := contexts.WithValue(contexts.Background(), contexts.LoggerKey, contextLogger)
 	for i, tt := range tests {
 
-		pp, err := NewPreprocessor(tt.stmt, nil,true)
-		if err != nil{
+		pp, err := NewPreprocessor(tt.stmt, nil, true)
+		if err != nil {
 			t.Error(err)
 		}
 
@@ -496,11 +496,11 @@ func TestPreprocessorEventtime_Apply(t *testing.T) {
 			log.Fatal(e)
 			return
 		} else {
-			tuple := &xsql.Tuple{Message:dm}
+			tuple := &xsql.Tuple{Message: dm}
 			result := pp.Apply(ctx, tuple)
 			//workaround make sure all the timezone are the same for time vars or the DeepEqual will be false.
-			if rt, ok := result.(*xsql.Tuple); ok{
-				if rtt, ok := rt.Message["abc"].(time.Time); ok{
+			if rt, ok := result.(*xsql.Tuple); ok {
+				if rtt, ok := rt.Message["abc"].(time.Time); ok {
 					rt.Message["abc"] = rtt.UTC()
 				}
 			}
@@ -510,4 +510,4 @@ func TestPreprocessorEventtime_Apply(t *testing.T) {
 		}
 
 	}
-}
+}

+ 18 - 19
xsql/plans/project_operator.go

@@ -10,7 +10,7 @@ import (
 )
 
 type ProjectPlan struct {
-	Fields xsql.Fields
+	Fields      xsql.Fields
 	IsAggregate bool
 
 	isTest bool
@@ -37,7 +37,7 @@ func (pp *ProjectPlan) Apply(ctx api.StreamContext, data interface{}) interface{
 		for _, v := range ms {
 			ve := pp.getVE(&v, input)
 			results = append(results, project(pp.Fields, ve, pp.isTest))
-			if pp.IsAggregate{
+			if pp.IsAggregate {
 				break
 			}
 		}
@@ -46,12 +46,12 @@ func (pp *ProjectPlan) Apply(ctx api.StreamContext, data interface{}) interface{
 		for _, v := range ms {
 			ve := pp.getVE(&v, input)
 			results = append(results, project(pp.Fields, ve, pp.isTest))
-			if pp.IsAggregate{
+			if pp.IsAggregate {
 				break
 			}
 		}
 	case xsql.GroupedTuplesSet:
-		for _, v := range input{
+		for _, v := range input {
 			ve := pp.getVE(v[0], v)
 			results = append(results, project(pp.Fields, ve, pp.isTest))
 		}
@@ -68,10 +68,10 @@ func (pp *ProjectPlan) Apply(ctx api.StreamContext, data interface{}) interface{
 	}
 }
 
-func (pp *ProjectPlan) getVE(tuple xsql.DataValuer, agg xsql.AggregateData) *xsql.ValuerEval{
-	if pp.IsAggregate{
+func (pp *ProjectPlan) getVE(tuple xsql.DataValuer, agg xsql.AggregateData) *xsql.ValuerEval {
+	if pp.IsAggregate {
 		return &xsql.ValuerEval{Valuer: xsql.MultiAggregateValuer(agg, tuple, &xsql.FunctionValuer{}, &xsql.AggregateFunctionValuer{Data: agg}, &xsql.WildcardValuer{Data: tuple})}
-	}else{
+	} else {
 		return &xsql.ValuerEval{Valuer: xsql.MultiValuer(tuple, &xsql.FunctionValuer{}, &xsql.WildcardValuer{Data: tuple})}
 	}
 }
@@ -80,23 +80,23 @@ func project(fs xsql.Fields, ve *xsql.ValuerEval, isTest bool) map[string]interf
 	result := make(map[string]interface{})
 	for _, f := range fs {
 		//Avoid to re-evaluate for non-agg field has alias name, which was already evaluated in pre-processor operator.
-		if f.AName != "" && (!xsql.HasAggFuncs(f.Expr)) && !isTest{
-			fr := &xsql.FieldRef{StreamName:"", Name:f.AName}
+		if f.AName != "" && (!xsql.HasAggFuncs(f.Expr)) && !isTest {
+			fr := &xsql.FieldRef{StreamName: "", Name: f.AName}
 			v := ve.Eval(fr)
 			result[f.AName] = v
 		} else {
 			v := ve.Eval(f.Expr)
-			if _, ok := f.Expr.(*xsql.Wildcard); ok || f.Name == "*"{
+			if _, ok := f.Expr.(*xsql.Wildcard); ok || f.Name == "*" {
 				switch val := v.(type) {
-				case map[string]interface{} :
-					for k, v := range val{
-						if _, ok := result[k]; !ok{
+				case map[string]interface{}:
+					for k, v := range val {
+						if _, ok := result[k]; !ok {
 							result[k] = v
 						}
 					}
 				case xsql.Message:
-					for k, v := range val{
-						if _, ok := result[k]; !ok{
+					for k, v := range val {
+						if _, ok := result[k]; !ok {
 							result[k] = v
 						}
 					}
@@ -106,7 +106,7 @@ func project(fs xsql.Fields, ve *xsql.ValuerEval, isTest bool) map[string]interf
 			} else {
 				if v != nil {
 					n := assignName(f.Name, f.AName, result)
-					if _, ok := result[n]; !ok{
+					if _, ok := result[n]; !ok {
 						result[n] = v
 					}
 				}
@@ -116,10 +116,9 @@ func project(fs xsql.Fields, ve *xsql.ValuerEval, isTest bool) map[string]interf
 	return result
 }
 
-
 const DEFAULT_FIELD_NAME_PREFIX string = "rengine_field_"
 
-func assignName(name, alias string, fields map[string] interface{}) string {
+func assignName(name, alias string, fields map[string]interface{}) string {
 	if result := strings.Trim(alias, " "); result != "" {
 		return result
 	}
@@ -136,4 +135,4 @@ func assignName(name, alias string, fields map[string] interface{}) string {
 	}
 	fmt.Printf("Cannot assign a default field name")
 	return ""
-}
+}

File diff suppressed because it is too large
+ 263 - 274
xsql/plans/project_test.go


+ 82 - 82
xsql/plans/str_func_test.go

@@ -13,8 +13,8 @@ import (
 
 func TestStrFunc_Apply1(t *testing.T) {
 	var tests = []struct {
-		sql  string
-		data *xsql.Tuple
+		sql    string
+		data   *xsql.Tuple
 		result []map[string]interface{}
 	}{
 		{
@@ -22,9 +22,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "mya",
-					"b" : "myb",
-					"c" : "myc",
+					"a": "mya",
+					"b": "myb",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -37,9 +37,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "mya",
-					"b" : "myb",
-					"c" : "myc",
+					"a": "mya",
+					"b": "myb",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -51,9 +51,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "mya",
-					"b" : "ya",
-					"c" : "myc",
+					"a": "mya",
+					"b": "ya",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -65,9 +65,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : common.TimeFromUnixMilli(1568854515000),
-					"b" : "ya",
-					"c" : "myc",
+					"a": common.TimeFromUnixMilli(1568854515000),
+					"b": "ya",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -79,9 +79,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "mya",
-					"b" : "ya",
-					"c" : "myc",
+					"a": "mya",
+					"b": "ya",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -93,9 +93,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "中国",
-					"b" : "ya",
-					"c" : "myc",
+					"a": "中国",
+					"b": "ya",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -107,9 +107,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "中国",
-					"b" : "ya",
-					"c" : "myc",
+					"a": "中国",
+					"b": "ya",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -121,9 +121,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "NYCNicks",
-					"b" : "ya",
-					"c" : "myc",
+					"a": "NYCNicks",
+					"b": "ya",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -135,9 +135,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "NYCNicks",
-					"b" : "ya",
-					"c" : "myc",
+					"a": "NYCNicks",
+					"b": "ya",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -149,9 +149,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : " \ttrimme\n ",
-					"b" : "ya",
-					"c" : "myc",
+					"a": " \ttrimme\n ",
+					"b": "ya",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -163,9 +163,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "中国",
-					"b" : "ya",
-					"c" : "myc",
+					"a": "中国",
+					"b": "ya",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -177,9 +177,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "中国",
-					"b" : "ya",
-					"c" : "myc",
+					"a": "中国",
+					"b": "ya",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -191,9 +191,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "seafood",
-					"b" : "ya",
-					"c" : "myc",
+					"a": "seafood",
+					"b": "ya",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -205,9 +205,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "seafood",
-					"b" : "ya",
-					"c" : "myc",
+					"a": "seafood",
+					"b": "ya",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -219,9 +219,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "-ab-axxb-",
-					"b" : "ya",
-					"c" : "myc",
+					"a": "-ab-axxb-",
+					"b": "ya",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -233,9 +233,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "seafood",
-					"b" : "ya",
-					"c" : "myc",
+					"a": "seafood",
+					"b": "ya",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -247,9 +247,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "NYCNicks",
-					"b" : "ya",
-					"c" : "myc",
+					"a": "NYCNicks",
+					"b": "ya",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -261,9 +261,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : " \ttrimme\n ",
-					"b" : "ya",
-					"c" : "myc",
+					"a": " \ttrimme\n ",
+					"b": "ya",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -275,9 +275,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "NYCNicks",
-					"b" : "ya",
-					"c" : "myc",
+					"a": "NYCNicks",
+					"b": "ya",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -289,9 +289,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "NYCNicks",
-					"b" : "ya",
-					"c" : "myc",
+					"a": "NYCNicks",
+					"b": "ya",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -303,9 +303,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "mya",
-					"b" : "ya",
-					"c" : "myc",
+					"a": "mya",
+					"b": "ya",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -317,9 +317,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "mya",
-					"b" : "ya",
-					"c" : "myc",
+					"a": "mya",
+					"b": "ya",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -331,9 +331,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : " \ttrimme\n ",
-					"b" : "ya",
-					"c" : "myc",
+					"a": " \ttrimme\n ",
+					"b": "ya",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -345,9 +345,9 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "NYCNicks",
-					"b" : "ya",
-					"c" : "myc",
+					"a": "NYCNicks",
+					"b": "ya",
+					"c": "myc",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -360,7 +360,7 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "test/device001/message",
+					"a": "test/device001/message",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -373,7 +373,7 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "test/device001/message",
+					"a": "test/device001/message",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -386,7 +386,7 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "test/device001/message",
+					"a": "test/device001/message",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -399,7 +399,7 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "/test/device001/message",
+					"a": "/test/device001/message",
 				},
 			},
 			result: []map[string]interface{}{{
@@ -413,10 +413,10 @@ func TestStrFunc_Apply1(t *testing.T) {
 			data: &xsql.Tuple{
 				Emitter: "test",
 				Message: xsql.Message{
-					"a" : "test/device001/message",
+					"a": "test/device001/message",
 				},
 			},
-			result: []map[string]interface{}{map[string]interface {}{}},
+			result: []map[string]interface{}{map[string]interface{}{}},
 		},
 	}
 
@@ -428,7 +428,7 @@ func TestStrFunc_Apply1(t *testing.T) {
 		if err != nil || stmt == nil {
 			t.Errorf("parse sql %s error %v", tt.sql, err)
 		}
-		pp := &ProjectPlan{Fields:stmt.Fields}
+		pp := &ProjectPlan{Fields: stmt.Fields}
 		pp.isTest = true
 		result := pp.Apply(ctx, tt.data)
 		var mapRes []map[string]interface{}
@@ -447,4 +447,4 @@ func TestStrFunc_Apply1(t *testing.T) {
 			t.Errorf("The returned result is not type of []byte\n")
 		}
 	}
-}
+}

+ 13 - 14
xsql/processors/extension_test.go

@@ -29,7 +29,7 @@ func setup() *RuleProcessor {
 	demo = "CREATE STREAM ext (count bigint) WITH (DATASOURCE=\"users\", FORMAT=\"JSON\", TYPE=\"random\", CONF_KEY=\"ext\")"
 
 	_, err = NewStreamProcessor(demo, path.Join(dbDir, "stream")).Exec()
-	if err != nil{
+	if err != nil {
 		panic(err)
 	}
 	rp := NewRuleProcessor(dbDir)
@@ -43,14 +43,13 @@ var CACHE_FILE = "cache"
 func TestExtensions(t *testing.T) {
 	log := common.Log
 	var tests = []struct {
-		name    string
-		rj	string
+		name string
+		rj   string
 		r    [][]map[string]interface{}
 	}{
 		{
 			name: `$$test1`,
-			rj: "{\"sql\": \"SELECT echo(count) as e, countPlusOne(count) as p FROM ext where count > 49\",\"actions\": [{\"file\":  {\"path\":\"" + CACHE_FILE + "\"}}]}",
-
+			rj:   "{\"sql\": \"SELECT echo(count) as e, countPlusOne(count) as p FROM ext where count > 49\",\"actions\": [{\"file\":  {\"path\":\"" + CACHE_FILE + "\"}}]}",
 		},
 	}
 	fmt.Printf("The test bucket size is %d.\n\n", len(tests))
@@ -66,7 +65,7 @@ func TestExtensions(t *testing.T) {
 		}
 
 		tp, err := rp.ExecInitRule(rs)
-		if err != nil{
+		if err != nil {
 			t.Errorf("fail to init rule: %v", err)
 			continue
 		}
@@ -81,13 +80,13 @@ func TestExtensions(t *testing.T) {
 		time.Sleep(5000 * time.Millisecond)
 		log.Printf("exit main program after 5 seconds")
 		results := getResults()
-		if len(results) == 0{
+		if len(results) == 0 {
 			t.Errorf("no result found")
 			continue
 		}
 		log.Debugf("get results %v", results)
 		var maps [][]map[string]interface{}
-		for _, v := range results{
+		for _, v := range results {
 			var mapRes []map[string]interface{}
 			err := json.Unmarshal([]byte(v), &mapRes)
 			if err != nil {
@@ -97,14 +96,14 @@ func TestExtensions(t *testing.T) {
 			maps = append(maps, mapRes)
 		}
 
-		for _, r := range maps{
-			if len(r) != 1{
+		for _, r := range maps {
+			if len(r) != 1 {
 				t.Errorf("%d. %q\n\nresult mismatch:\n\ngot=%#v\n\n", i, tt.rj, maps)
 				break
 			}
 			r := r[0]
 			e := int((r["e"]).(float64))
-			if e != 50 && e != 51{
+			if e != 50 && e != 51 {
 				t.Errorf("%d. %q\n\nresult mismatch:\n\ngot=%#v\n\n", i, tt.rj, maps)
 				break
 			}
@@ -118,15 +117,15 @@ func TestExtensions(t *testing.T) {
 	}
 }
 
-func getResults() []string{
+func getResults() []string {
 	f, err := os.Open(CACHE_FILE)
-	if err != nil{
+	if err != nil {
 		panic(err)
 	}
 	defer f.Close()
 	result := make([]string, 0)
 	scanner := bufio.NewScanner(f)
-	for scanner.Scan(){
+	for scanner.Scan() {
 		result = append(result, scanner.Text())
 	}
 	if err := scanner.Err(); err != nil {

+ 5 - 5
xsql/processors/xsql_processor.go

@@ -231,7 +231,7 @@ func (p *RuleProcessor) ExecQuery(ruleid, sql string) (*xstream.TopologyNew, err
 	if tp, inputs, err := p.createTopo(&api.Rule{Id: ruleid, Sql: sql}); err != nil {
 		return nil, err
 	} else {
-		tp.AddSink(inputs, nodes.NewSinkNode("sink_memory_log", "logToMemory", nil ))
+		tp.AddSink(inputs, nodes.NewSinkNode("sink_memory_log", "logToMemory", nil))
 		go func() {
 			select {
 			case err := <-tp.Open():
@@ -313,9 +313,9 @@ func (p *RuleProcessor) createTopoWithSources(rule *api.Rule, sources []*nodes.S
 	name := rule.Id
 	sql := rule.Sql
 	var (
-		isEventTime bool
-		lateTol int64
-		concurrency = 1
+		isEventTime  bool
+		lateTol      int64
+		concurrency  = 1
 		bufferLength = 1024
 	)
 
@@ -456,4 +456,4 @@ func (p *RuleProcessor) createTopoWithSources(rule *api.Rule, sources []*nodes.S
 			return tp, inputs, nil
 		}
 	}
-}
+}

+ 26 - 26
xsql/processors/xsql_processor_test.go

@@ -94,7 +94,7 @@ func TestStreamCreateProcessor(t *testing.T) {
 			t.Errorf("%d. %q: error mismatch:\n  exp=%s\n  got=%s\n\n", i, tt.s, tt.err, err)
 		} else if tt.err == "" {
 			if !reflect.DeepEqual(tt.r, results) {
-				t.Errorf("%d. %q\n\nstmt mismatch:\nexp=%s\ngot=%#v\n\n", i, tt.s,tt.r, results)
+				t.Errorf("%d. %q\n\nstmt mismatch:\nexp=%s\ngot=%#v\n\n", i, tt.s, tt.r, results)
 			}
 		}
 	}
@@ -509,7 +509,7 @@ func TestSingleSQL(t *testing.T) {
 				}
 			}
 		}
-		tp, inputs, err := p.createTopoWithSources(&api.Rule{Id: tt.name, Sql: tt.sql, Options:map[string]interface{}{
+		tp, inputs, err := p.createTopoWithSources(&api.Rule{Id: tt.name, Sql: tt.sql, Options: map[string]interface{}{
 			"bufferLength": float64(100),
 		}}, sources)
 		if err != nil {
@@ -559,26 +559,26 @@ func TestSingleSQL(t *testing.T) {
 		//	log.Printf("%s:%v", k, values[i])
 		//}
 		for k, v := range tt.m {
-			var(
-				index int
-				key   string
+			var (
+				index   int
+				key     string
 				matched bool
 			)
-			for index, key = range keys{
+			for index, key = range keys {
 				if k == key {
-					if values[index] == v{
+					if values[index] == v {
 						matched = true
 					}
 					break
 				}
 			}
-			if matched{
+			if matched {
 				continue
 			}
 			//do not find
-			if index < len(values){
+			if index < len(values) {
 				t.Errorf("%d. %q\n\nmetrics mismatch for %s:\n\nexp=%#v(%t)\n\ngot=%#v(%t)\n\n", i, tt.sql, k, v, v, values[index], values[index])
-			}else{
+			} else {
 				t.Errorf("%d. %q\n\nmetrics mismatch for %s:\n\nexp=%#v\n\ngot=nil\n\n", i, tt.sql, k, v)
 			}
 			break
@@ -1037,26 +1037,26 @@ func TestWindow(t *testing.T) {
 		}
 		keys, values := tp.GetMetrics()
 		for k, v := range tt.m {
-			var(
-				index int
-				key   string
+			var (
+				index   int
+				key     string
 				matched bool
 			)
-			for index, key = range keys{
+			for index, key = range keys {
 				if k == key {
-					if values[index] == v{
+					if values[index] == v {
 						matched = true
 					}
 					break
 				}
 			}
-			if matched{
+			if matched {
 				continue
 			}
 			//do not find
-			if index < len(values){
+			if index < len(values) {
 				t.Errorf("%d. %q\n\nmetrics mismatch for %s:\n\nexp=%#v(%t)\n\ngot=%#v(%t)\n\n", i, tt.sql, k, v, v, values[index], values[index])
-			}else{
+			} else {
 				t.Errorf("%d. %q\n\nmetrics mismatch for %s:\n\nexp=%#v\n\ngot=nil\n\n", i, tt.sql, k, v)
 			}
 			break
@@ -1804,26 +1804,26 @@ func TestEventWindow(t *testing.T) {
 		//	log.Printf("%s:%v", k, values[i])
 		//}
 		for k, v := range tt.m {
-			var(
-				index int
-				key   string
+			var (
+				index   int
+				key     string
 				matched bool
 			)
-			for index, key = range keys{
+			for index, key = range keys {
 				if k == key {
-					if values[index] == v{
+					if values[index] == v {
 						matched = true
 					}
 					break
 				}
 			}
-			if matched{
+			if matched {
 				continue
 			}
 			//do not find
-			if index < len(values){
+			if index < len(values) {
 				t.Errorf("%d. %q\n\nmetrics mismatch for %s:\n\nexp=%#v(%t)\n\ngot=%#v(%t)\n\n", i, tt.sql, k, v, v, values[index], values[index])
-			}else{
+			} else {
 				t.Errorf("%d. %q\n\nmetrics mismatch for %s:\n\nexp=%#v\n\ngot=nil\n\n", i, tt.sql, k, v)
 			}
 			break

+ 7 - 7
xsql/util.go

@@ -13,7 +13,7 @@ func PrintFieldType(ft FieldType, buff *bytes.Buffer) {
 		buff.WriteString("array(")
 		if t.FieldType != nil {
 			PrintFieldType(t.FieldType, buff)
-		}else{
+		} else {
 			buff.WriteString(t.Type.String())
 		}
 		buff.WriteString(")")
@@ -21,9 +21,9 @@ func PrintFieldType(ft FieldType, buff *bytes.Buffer) {
 		buff.WriteString("struct(")
 		isFirst := true
 		for _, f := range t.StreamFields {
-			if isFirst{
+			if isFirst {
 				isFirst = false
-			}else{
+			} else {
 				buff.WriteString(", ")
 			}
 			buff.WriteString(f.Name + " ")
@@ -33,17 +33,17 @@ func PrintFieldType(ft FieldType, buff *bytes.Buffer) {
 	}
 }
 
-func GetStreams(stmt *SelectStatement) (result []string){
+func GetStreams(stmt *SelectStatement) (result []string) {
 	if stmt == nil {
 		return nil
 	}
-	for _, source := range stmt.Sources{
+	for _, source := range stmt.Sources {
 		if s, ok := source.(*Table); ok {
 			result = append(result, s.Name)
 		}
 	}
 
-	for _, join := range stmt.Joins{
+	for _, join := range stmt.Joins {
 		result = append(result, join.Name)
 	}
 	return
@@ -59,4 +59,4 @@ func LowercaseKeyMap(m map[string]interface{}) map[string]interface{} {
 		}
 	}
 	return m1
-}
+}

+ 2 - 3
xsql/xsql_manager.go

@@ -27,11 +27,10 @@ func (t *ParseTree) Handle(tok Token, fn func(*Parser) (Statement, error)) {
 	t.Keys = append(t.Keys, tok.String())
 }
 
-
 func (pt *ParseTree) Parse(p *Parser) (Statement, error) {
 	tok, _ := p.scanIgnoreWhitespace()
 	p.unscan()
-	if f, ok  := pt.Handlers[tok]; ok {
+	if f, ok := pt.Handlers[tok]; ok {
 		return f(p)
 	}
 	return nil, nil
@@ -61,4 +60,4 @@ func init() {
 	Language.Handle(DROP, func(p *Parser) (statement Statement, e error) {
 		return p.parseDropStreamsStmt()
 	})
-}
+}

+ 8 - 9
xsql/xsql_parser_tree_test.go

@@ -23,28 +23,28 @@ func TestParser_ParseTree(t *testing.T) {
 					{Name: "USERID", FieldType: &BasicType{Type: BIGINT}},
 				},
 				Options: map[string]string{
-					"DATASOURCE" : "users",
-					"FORMAT" : "JSON",
-					"KEY" : "USERID",
+					"DATASOURCE": "users",
+					"FORMAT":     "JSON",
+					"KEY":        "USERID",
 				},
 			},
 		},
 
 		{
-			s: `SHOW STREAMS`,
+			s:    `SHOW STREAMS`,
 			stmt: &ShowStreamsStatement{},
 		},
 
 		{
-			s: `SHOW STREAMSf`,
+			s:    `SHOW STREAMSf`,
 			stmt: nil,
-			err: `found "STREAMSf", expected keyword streams.`,
+			err:  `found "STREAMSf", expected keyword streams.`,
 		},
 
 		{
-			s: `SHOW STREAMS d`,
+			s:    `SHOW STREAMS d`,
 			stmt: nil,
-			err: `found "d", expected semecolon or EOF.`,
+			err:  `found "d", expected semecolon or EOF.`,
 		},
 
 		{
@@ -70,7 +70,6 @@ func TestParser_ParseTree(t *testing.T) {
 			},
 			err: ``,
 		},
-
 	}
 
 	fmt.Printf("The test bucket size is %d.\n\n", len(tests))

+ 52 - 53
xsql/xsql_stream_test.go

@@ -38,17 +38,17 @@ func TestParser_ParseCreateStream(t *testing.T) {
 					}},
 				},
 				Options: map[string]string{
-					"DATASOURCE" : "users",
-					"FORMAT" : "AVRO",
-					"KEY" : "USERID",
-					"CONF_KEY" : "srv1",
-					"TYPE" : "MQTT",
-					"TIMESTAMP" : "USERID",
-					"TIMESTAMP_FORMAT" : "yyyy-MM-dd''T''HH:mm:ssX'",
+					"DATASOURCE":       "users",
+					"FORMAT":           "AVRO",
+					"KEY":              "USERID",
+					"CONF_KEY":         "srv1",
+					"TYPE":             "MQTT",
+					"TIMESTAMP":        "USERID",
+					"TIMESTAMP_FORMAT": "yyyy-MM-dd''T''HH:mm:ssX'",
 				},
 			},
 		},
-		
+
 		{
 			s: `CREATE STREAM demo (
 					USERID BIGINT,
@@ -59,14 +59,14 @@ func TestParser_ParseCreateStream(t *testing.T) {
 					{Name: "USERID", FieldType: &BasicType{Type: BIGINT}},
 				},
 				Options: map[string]string{
-					"DATASOURCE" : "users",
-					"FORMAT" : "JSON",
-					"KEY" : "USERID",
-					"STRICT_VALIDATION" : "true",
+					"DATASOURCE":        "users",
+					"FORMAT":            "JSON",
+					"KEY":               "USERID",
+					"STRICT_VALIDATION": "true",
 				},
 			},
 		},
-		
+
 		{
 			s: `CREATE STREAM demo (
 					ADDRESSES ARRAY(STRUCT(STREET_NAME STRING, NUMBER BIGINT)),
@@ -85,14 +85,14 @@ func TestParser_ParseCreateStream(t *testing.T) {
 					}},
 				},
 				Options: map[string]string{
-					"DATASOURCE" : "users",
-					"FORMAT" : "AVRO",
-					"KEY" : "USERID",
+					"DATASOURCE":        "users",
+					"FORMAT":            "AVRO",
+					"KEY":               "USERID",
 					"STRICT_VALIDATION": "FAlse",
 				},
 			},
 		},
-		
+
 		{
 			s: `CREATE STREAM demo (
 					ADDRESSES ARRAY(STRUCT(STREET_NAME STRING, NUMBER BIGINT)),
@@ -113,13 +113,13 @@ func TestParser_ParseCreateStream(t *testing.T) {
 					{Name: "birthday", FieldType: &BasicType{Type: DATETIME}},
 				},
 				Options: map[string]string{
-					"DATASOURCE" : "users",
-					"FORMAT" : "AVRO",
-					"KEY" : "USERID",
+					"DATASOURCE": "users",
+					"FORMAT":     "AVRO",
+					"KEY":        "USERID",
 				},
 			},
 		},
-		
+
 		{
 			s: `CREATE STREAM demo (
 					NAME string,
@@ -142,28 +142,28 @@ func TestParser_ParseCreateStream(t *testing.T) {
 					{Name: "birthday", FieldType: &BasicType{Type: DATETIME}},
 				},
 				Options: map[string]string{
-					"DATASOURCE" : "users",
-					"FORMAT" : "AVRO",
-					"KEY" : "USERID",
+					"DATASOURCE": "users",
+					"FORMAT":     "AVRO",
+					"KEY":        "USERID",
 				},
 			},
 		},
-		
+
 		{
 			s: `CREATE STREAM demo (
 		
 				) WITH (DATASOURCE="users", FORMAT="JSON", KEY="USERID");`,
 			stmt: nil,
-			err: `found ")", expect stream field name.`,
+			err:  `found ")", expect stream field name.`,
 		},
 
 		{
 			s: `CREATE STREAM demo (NAME string)
 				 WITH (DATASOURCE="users", FORMAT="JSON", KEY="USERID", STRICT_VALIDATION="true1");`, //Invalid STRICT_VALIDATION value
 			stmt: nil,
-			err: `found "true1", expect TRUE/FALSE value in STRICT_VALIDATION option.`,
+			err:  `found "true1", expect TRUE/FALSE value in STRICT_VALIDATION option.`,
 		},
-		
+
 		{
 			s: `CREATE STREAM demo (NAME string) WITH (DATASOURCE="users", FORMAT="JSON", KEY="USERID");`,
 			stmt: &StreamStmt{
@@ -172,63 +172,63 @@ func TestParser_ParseCreateStream(t *testing.T) {
 					{Name: "NAME", FieldType: &BasicType{Type: STRINGS}},
 				},
 				Options: map[string]string{
-					"DATASOURCE" : "users",
-					"FORMAT" : "JSON",
-					"KEY" : "USERID",
+					"DATASOURCE": "users",
+					"FORMAT":     "JSON",
+					"KEY":        "USERID",
 				},
 			},
 		},
-		
+
 		{
 			s: `CREATE STREAM demo (NAME string)) WITH (DATASOURCE="users", FORMAT="JSON", KEY="USERID");`,
 			stmt: &StreamStmt{
-				Name: StreamName("demo"),
+				Name:         StreamName("demo"),
 				StreamFields: nil,
-				Options: nil,
+				Options:      nil,
 			},
 			err: `found ")", expect stream options.`,
 		},
-		
+
 		{
 			s: `CREATE STREAM demo (NAME string) WITHs (DATASOURCE="users", FORMAT="JSON", KEY="USERID");`,
 			stmt: &StreamStmt{
-				Name: StreamName("demo"),
+				Name:         StreamName("demo"),
 				StreamFields: nil,
-				Options: nil,
+				Options:      nil,
 			},
 			err: `found "WITHs", expected is with.`,
 		},
-		
+
 		{
 			s: `CREATE STREAM demo (NAME integer) WITH (DATASOURCE="users", FORMAT="JSON", KEY="USERID");`,
 			stmt: &StreamStmt{
-				Name: "demo",
+				Name:         "demo",
 				StreamFields: nil,
-				Options: nil,
+				Options:      nil,
 			},
 			err: `found "integer", expect valid stream field types(BIGINT | FLOAT | STRINGS | DATETIME | BOOLEAN | ARRAY | STRUCT).`,
 		},
-		
+
 		{
 			s: `CREATE STREAM demo (NAME string) WITH (sources="users", FORMAT="JSON", KEY="USERID");`,
 			stmt: &StreamStmt{
-				Name: "demo",
+				Name:         "demo",
 				StreamFields: nil,
-				Options: nil,
+				Options:      nil,
 			},
 			err: `found "sources", unknown option keys(DATASOURCE|FORMAT|KEY|CONF_KEY|STRICT_VALIDATION|TYPE).`,
 		},
-		
+
 		{
 			s: `CREATE STREAM demo ((NAME string) WITH (DATASOURCE="users", FORMAT="JSON", KEY="USERID");`,
 			stmt: &StreamStmt{
-				Name: "demo",
+				Name:         "demo",
 				StreamFields: nil,
-				Options: nil,
+				Options:      nil,
 			},
 			err: `found "(", expect stream field name.`,
 		},
-		
+
 		{
 			s: `CREATE STREAM demo (
 					USERID BIGINT,
@@ -247,9 +247,9 @@ func TestParser_ParseCreateStream(t *testing.T) {
 					USERID BIGINT,
 				) WITH ());`,
 			stmt: &StreamStmt{
-				Name: "",
+				Name:         "",
 				StreamFields: nil,
-				Options: nil,
+				Options:      nil,
 			},
 			err: `found ")", expected semicolon or EOF.`,
 		},
@@ -259,13 +259,12 @@ func TestParser_ParseCreateStream(t *testing.T) {
 					USERID BIGINT,
 				) WITH DATASOURCE="users", FORMAT="JSON", KEY="USERID");`,
 			stmt: &StreamStmt{
-				Name: "",
+				Name:         "",
 				StreamFields: nil,
-				Options: nil,
+				Options:      nil,
 			},
 			//TODO The error string should be more accurate
 			err: `found "DATASOURCE", expect stream options.`,
-
 		},
 	}
 
@@ -287,4 +286,4 @@ func TestParser_ParseCreateStream(t *testing.T) {
 //		return err.Error()
 //	}
 //	return ""
-//}
+//}

+ 48 - 50
xstream/cli/main.go

@@ -2,8 +2,8 @@ package main
 
 import (
 	"bufio"
-	"github.com/emqx/kuiper/common"
 	"fmt"
+	"github.com/emqx/kuiper/common"
 	"github.com/go-yaml/yaml"
 	"github.com/urfave/cli"
 	"io/ioutil"
@@ -16,20 +16,20 @@ import (
 
 type clientConf struct {
 	Host string `yaml:"host"`
-	Port int `yaml:"port"`
+	Port int    `yaml:"port"`
 }
 
 var clientYaml = "client.yaml"
 
-func streamProcess(client *rpc.Client, args string)  {
+func streamProcess(client *rpc.Client, args string) {
 	var reply string
-	if args == ""{
+	if args == "" {
 		args = strings.Join(os.Args[1:], " ")
 	}
 	err := client.Call("Server.Stream", args, &reply)
-	if err != nil{
+	if err != nil {
 		fmt.Println(err)
-	}else{
+	} else {
 		fmt.Println(reply)
 	}
 }
@@ -53,11 +53,11 @@ func main() {
 	var config *clientConf
 	if err := yaml.Unmarshal(b, &cfg); err != nil {
 		fmt.Printf("Failed to load config file with error %s.\n", err)
-	}else{
+	} else {
 		c, ok := cfg["basic"]
-		if !ok{
+		if !ok {
 			fmt.Printf("No basic config in client.yaml, will use the default configuration.\n")
-		}else{
+		} else {
 			config = &c
 		}
 	}
@@ -78,10 +78,10 @@ func main() {
 
 	app.Commands = []cli.Command{
 		{
-			Name:      "query",
-			Aliases:   []string{"query"},
-			Usage:     "query command line",
-			Action:    func(c *cli.Context) error {
+			Name:    "query",
+			Aliases: []string{"query"},
+			Usage:   "query command line",
+			Action: func(c *cli.Context) error {
 				reader := bufio.NewReader(os.Stdin)
 				var inputs []string
 				ticker := time.NewTicker(time.Millisecond * 300)
@@ -101,7 +101,7 @@ func main() {
 					} else {
 						var reply string
 						err := client.Call("Server.CreateQuery", text, &reply)
-						if err != nil{
+						if err != nil {
 							fmt.Println(err)
 							continue
 						} else {
@@ -128,18 +128,18 @@ func main() {
 			},
 		},
 		{
-			Name:      "create",
-			Aliases:   []string{"create"},
-			Usage:     "create stream $stream_name | create stream $stream_name -f $stream_def_file | create rule $rule_name $rule_json | create rule $rule_name -f $rule_def_file",
+			Name:    "create",
+			Aliases: []string{"create"},
+			Usage:   "create stream $stream_name | create stream $stream_name -f $stream_def_file | create rule $rule_name $rule_json | create rule $rule_name -f $rule_def_file",
 
-			Subcommands: []cli.Command {
+			Subcommands: []cli.Command{
 				{
 					Name:  "stream",
 					Usage: "create stream $stream_name [-f stream_def_file]",
-					Flags: []cli.Flag {
+					Flags: []cli.Flag{
 						cli.StringFlag{
-							Name: "file, f",
-							Usage: "the location of stream definition file",
+							Name:     "file, f",
+							Usage:    "the location of stream definition file",
 							FilePath: "/home/mystream.txt",
 						},
 					},
@@ -168,10 +168,10 @@ func main() {
 				{
 					Name:  "rule",
 					Usage: "create rule $rule_name [$rule_json | -f rule_def_file]",
-					Flags: []cli.Flag {
+					Flags: []cli.Flag{
 						cli.StringFlag{
-							Name: "file, f",
-							Usage: "the location of rule definition file",
+							Name:     "file, f",
+							Usage:    "the location of rule definition file",
 							FilePath: "/home/myrule.txt",
 						},
 					},
@@ -222,12 +222,11 @@ func main() {
 					},
 				},
 			},
-
 		},
 		{
-			Name:      "describe",
-			Aliases:   []string{"describe"},
-			Usage:     "describe stream $stream_name | describe rule $rule_name",
+			Name:    "describe",
+			Aliases: []string{"describe"},
+			Usage:   "describe stream $stream_name | describe rule $rule_name",
 			Subcommands: []cli.Command{
 				{
 					Name:  "stream",
@@ -241,7 +240,7 @@ func main() {
 				{
 					Name:  "rule",
 					Usage: "describe rule $rule_name",
-					Action:    func(c *cli.Context) error {
+					Action: func(c *cli.Context) error {
 						if len(c.Args()) != 1 {
 							fmt.Printf("Expect rule name.\n")
 							return nil
@@ -261,9 +260,9 @@ func main() {
 		},
 
 		{
-			Name:        "drop",
-			Aliases:     []string{"drop"},
-			Usage:       "drop stream $stream_name | drop rule $rule_name",
+			Name:    "drop",
+			Aliases: []string{"drop"},
+			Usage:   "drop stream $stream_name | drop rule $rule_name",
 			Subcommands: []cli.Command{
 				{
 					Name:  "stream",
@@ -298,9 +297,9 @@ func main() {
 		},
 
 		{
-			Name:      "show",
-			Aliases:   []string{"show"},
-			Usage:     "show streams | show rules",
+			Name:    "show",
+			Aliases: []string{"show"},
+			Usage:   "show streams | show rules",
 
 			Subcommands: []cli.Command{
 				{
@@ -314,7 +313,7 @@ func main() {
 				{
 					Name:  "rules",
 					Usage: "show rules",
-					Action:    func(c *cli.Context) error {
+					Action: func(c *cli.Context) error {
 						var reply string
 						err = client.Call("Server.ShowRules", 0, &reply)
 						if err != nil {
@@ -329,9 +328,9 @@ func main() {
 		},
 
 		{
-			Name:        "getstatus",
-			Aliases:     []string{"getstatus"},
-			Usage:       "getstatus rule $rule_name",
+			Name:    "getstatus",
+			Aliases: []string{"getstatus"},
+			Usage:   "getstatus rule $rule_name",
 			Subcommands: []cli.Command{
 				{
 					Name:  "rule",
@@ -356,9 +355,9 @@ func main() {
 			},
 		},
 		{
-			Name:        "start",
-			Aliases:     []string{"start"},
-			Usage:       "start rule $rule_name",
+			Name:    "start",
+			Aliases: []string{"start"},
+			Usage:   "start rule $rule_name",
 			Subcommands: []cli.Command{
 				{
 					Name:  "rule",
@@ -383,9 +382,9 @@ func main() {
 			},
 		},
 		{
-			Name:        "stop",
-			Aliases:     []string{"stop"},
-			Usage:       "stop rule $rule_name",
+			Name:    "stop",
+			Aliases: []string{"stop"},
+			Usage:   "stop rule $rule_name",
 			Subcommands: []cli.Command{
 				{
 					Name:  "rule",
@@ -410,9 +409,9 @@ func main() {
 			},
 		},
 		{
-			Name:        "restart",
-			Aliases:     []string{"restart"},
-			Usage:       "restart rule $rule_name",
+			Name:    "restart",
+			Aliases: []string{"restart"},
+			Usage:   "restart rule $rule_name",
 			Subcommands: []cli.Command{
 				{
 					Name:  "rule",
@@ -438,7 +437,6 @@ func main() {
 		},
 	}
 
-
 	app.Name = "Kuiper"
 	app.Usage = "The command line tool for EMQ X Kuiper."
 
@@ -456,4 +454,4 @@ func main() {
 	if err != nil {
 		fmt.Printf("%v", err)
 	}
-}
+}

+ 4 - 4
xstream/collectors/func.go

@@ -1,8 +1,8 @@
 package collectors
 
 import (
-	"github.com/emqx/kuiper/xstream/api"
 	"errors"
+	"github.com/emqx/kuiper/xstream/api"
 )
 
 // CollectorFunc is a function used to colllect
@@ -15,7 +15,7 @@ type CollectorFunc func(api.StreamContext, interface{}) error
 // of type:
 //   CollectorFunc
 type FuncCollector struct {
-	f     CollectorFunc
+	f CollectorFunc
 }
 
 // Func creates a new value *FuncCollector that
@@ -25,7 +25,7 @@ func Func(f CollectorFunc) *FuncCollector {
 	return &FuncCollector{f: f}
 }
 
-func (c *FuncCollector) Configure(props map[string]interface{}) error{
+func (c *FuncCollector) Configure(props map[string]interface{}) error {
 	//do nothing
 	return nil
 }
@@ -47,4 +47,4 @@ func (c *FuncCollector) Collect(ctx api.StreamContext, item interface{}) error {
 
 func (c *FuncCollector) Close(api.StreamContext) error {
 	return nil
-}
+}

+ 1 - 2
xstream/contexts/default.go

@@ -40,7 +40,7 @@ func (c *DefaultContext) Done() <-chan struct{} {
 }
 
 func (c *DefaultContext) Err() error {
-	if c.err != nil{
+	if c.err != nil {
 		return c.err
 	}
 	return c.ctx.Err()
@@ -79,7 +79,6 @@ func (c *DefaultContext) SetError(err error) {
 	c.err = err
 }
 
-
 func (c *DefaultContext) WithMeta(ruleId string, opId string) api.StreamContext {
 	return &DefaultContext{
 		ruleId:     ruleId,

+ 2 - 3
xstream/demo/func_visitor.go

@@ -1,10 +1,9 @@
 package main
 
 import (
-	"github.com/emqx/kuiper/xsql"
 	"fmt"
+	"github.com/emqx/kuiper/xsql"
 	"strings"
-
 )
 
 func main() {
@@ -12,7 +11,7 @@ func main() {
 
 	var srcs []string
 	xsql.WalkFunc(stmt.Joins, func(node xsql.Node) {
-		if f,ok := node.(*xsql.FieldRef); ok {
+		if f, ok := node.(*xsql.FieldRef); ok {
 			if string(f.StreamName) == "" {
 				return
 			}

+ 4 - 4
xstream/extensions/mqtt_source.go

@@ -119,14 +119,14 @@ func (ms *MQTTSource) Open(ctx api.StreamContext, consume api.ConsumeFunc) error
 	opts.SetAutoReconnect(true)
 	var reconn = false
 	opts.SetConnectionLostHandler(func(client MQTT.Client, e error) {
-		log.Errorf("The connection %s is disconnected due to error %s, will try to re-connect later.", ms.srv + ": " + ms.clientid, e)
+		log.Errorf("The connection %s is disconnected due to error %s, will try to re-connect later.", ms.srv+": "+ms.clientid, e)
 		reconn = true
 		subscribe(ms.tpc, client, ctx, consume)
 	})
-	
+
 	opts.SetOnConnectHandler(func(client MQTT.Client) {
 		if reconn {
-			log.Infof("The connection is %s re-established successfully.", ms.srv + ": " + ms.clientid)
+			log.Infof("The connection is %s re-established successfully.", ms.srv+": "+ms.clientid)
 		}
 	})
 
@@ -137,7 +137,7 @@ func (ms *MQTTSource) Open(ctx api.StreamContext, consume api.ConsumeFunc) error
 	log.Infof("The connection to server %s was established successfully", ms.srv)
 	ms.conn = c
 	subscribe(ms.tpc, c, ctx, consume)
-	log.Infof("Successfully subscribe to topic %s", ms.srv + ": " + ms.clientid)
+	log.Infof("Successfully subscribe to topic %s", ms.srv+": "+ms.clientid)
 
 	return nil
 }

+ 1 - 1
xstream/funcs.go

@@ -2,9 +2,9 @@ package xstream
 
 import (
 	"context"
+	"fmt"
 	"github.com/emqx/kuiper/xstream/api"
 	"github.com/emqx/kuiper/xstream/operators"
-	"fmt"
 	"reflect"
 )
 

+ 1 - 3
xstream/nodes/common_func.go

@@ -11,7 +11,7 @@ func Broadcast(outputs map[string]chan<- interface{}, val interface{}, ctx api.S
 	var barrier sync.WaitGroup
 	barrier.Add(len(outputs))
 	for n, out := range outputs {
-		go func(wg *sync.WaitGroup){
+		go func(wg *sync.WaitGroup) {
 			out <- val
 			wg.Done()
 			logger.Debugf("broadcast from %s to %s done", ctx.GetOpId(), n)
@@ -20,5 +20,3 @@ func Broadcast(outputs map[string]chan<- interface{}, val interface{}, ctx api.S
 	logger.Debugf("broadcasting from %s", ctx.GetOpId())
 	barrier.Wait()
 }
-
-

+ 15 - 15
xstream/nodes/prometheus.go

@@ -13,36 +13,36 @@ const LastInvocation = "last_invocation"
 const BufferLength = "buffer_length"
 
 var (
-	MetricNames = []string{RecordsInTotal, RecordsOutTotal, ExceptionsTotal, ProcessLatencyMs, BufferLength, LastInvocation}
+	MetricNames        = []string{RecordsInTotal, RecordsOutTotal, ExceptionsTotal, ProcessLatencyMs, BufferLength, LastInvocation}
 	prometheuseMetrics *PrometheusMetrics
-	mutex sync.RWMutex
+	mutex              sync.RWMutex
 )
 
-func GetPrometheusMetrics() *PrometheusMetrics{
+func GetPrometheusMetrics() *PrometheusMetrics {
 	mutex.Lock()
-	if prometheuseMetrics == nil{
+	if prometheuseMetrics == nil {
 		prometheuseMetrics = newPrometheusMetrics()
 	}
 	mutex.Unlock()
 	return prometheuseMetrics
 }
 
-type MetricGroup struct{
-	TotalRecordsIn *prometheus.CounterVec
+type MetricGroup struct {
+	TotalRecordsIn  *prometheus.CounterVec
 	TotalRecordsOut *prometheus.CounterVec
 	TotalExceptions *prometheus.CounterVec
-	ProcessLatency *prometheus.GaugeVec
-	BufferLength   *prometheus.GaugeVec
+	ProcessLatency  *prometheus.GaugeVec
+	BufferLength    *prometheus.GaugeVec
 }
 
 type PrometheusMetrics struct {
 	vecs []*MetricGroup
 }
 
-func newPrometheusMetrics() *PrometheusMetrics{
+func newPrometheusMetrics() *PrometheusMetrics {
 	var (
-		labelNames = []string{ "rule", "type", "op", "instance" }
-		prefixes = []string{"kuiper_source", "kuiper_op", "kuiper_sink"}
+		labelNames = []string{"rule", "type", "op", "instance"}
+		prefixes   = []string{"kuiper_source", "kuiper_op", "kuiper_sink"}
 	)
 	var vecs []*MetricGroup
 	for _, prefix := range prefixes {
@@ -76,11 +76,11 @@ func newPrometheusMetrics() *PrometheusMetrics{
 			BufferLength:    bufferLength,
 		})
 	}
-	return &PrometheusMetrics{vecs:vecs}
+	return &PrometheusMetrics{vecs: vecs}
 }
 
-func (m *PrometheusMetrics) GetMetricsGroup(opType string) *MetricGroup{
-	switch opType{
+func (m *PrometheusMetrics) GetMetricsGroup(opType string) *MetricGroup {
+	switch opType {
 	case "source":
 		return m.vecs[0]
 	case "op":
@@ -89,4 +89,4 @@ func (m *PrometheusMetrics) GetMetricsGroup(opType string) *MetricGroup{
 		return m.vecs[2]
 	}
 	return nil
-}
+}

+ 30 - 30
xstream/nodes/sink_cache.go

@@ -14,7 +14,7 @@ import (
 
 type CacheTuple struct {
 	index int
-	data interface{}
+	data  interface{}
 }
 
 type LinkedQueue struct {
@@ -22,46 +22,46 @@ type LinkedQueue struct {
 	Tail int
 }
 
-func (l *LinkedQueue) append(item interface{}){
+func (l *LinkedQueue) append(item interface{}) {
 	l.Data[l.Tail] = item
 	l.Tail++
 }
 
-func (l *LinkedQueue) delete(index int){
+func (l *LinkedQueue) delete(index int) {
 	delete(l.Data, index)
 }
 
-func (l *LinkedQueue) reset(){
+func (l *LinkedQueue) reset() {
 	l.Tail = 0
 }
 
-func (l *LinkedQueue) length() int{
+func (l *LinkedQueue) length() int {
 	return len(l.Data)
 }
 
 type Cache struct {
 	//Data and control channels
-	in <-chan interface{}
-	Out chan *CacheTuple
+	in       <-chan interface{}
+	Out      chan *CacheTuple
 	Complete chan int
-	errorCh chan<- error
+	errorCh  chan<- error
 	//states
 	pending *LinkedQueue
 	//serialize
-	key     string  //the key for current cache
+	key     string //the key for current cache
 	store   common.KeyValue
 	changed bool
 	//configs
-	limit int
+	limit        int
 	saveInterval int
 }
 
 func NewCache(in <-chan interface{}, limit int, saveInterval int, errCh chan<- error, ctx api.StreamContext) *Cache {
-	c :=  &Cache{
-		in: in,
-		Out: make(chan *CacheTuple, limit),
+	c := &Cache{
+		in:       in,
+		Out:      make(chan *CacheTuple, limit),
 		Complete: make(chan int),
-		errorCh: errCh,
+		errorCh:  errCh,
 
 		limit:        limit,
 		saveInterval: saveInterval,
@@ -70,7 +70,7 @@ func NewCache(in <-chan interface{}, limit int, saveInterval int, errCh chan<- e
 	return c
 }
 
-func (c *Cache) run(ctx api.StreamContext){
+func (c *Cache) run(ctx api.StreamContext) {
 	logger := ctx.GetLogger()
 	dbDir, err := common.GetAndCreateDataLoc("sink")
 	logger.Debugf("cache saved to %s", dbDir)
@@ -80,13 +80,13 @@ func (c *Cache) run(ctx api.StreamContext){
 	c.store = common.GetSimpleKVStore(path.Join(dbDir, "cache"))
 	c.key = ctx.GetRuleId() + ctx.GetOpId() + strconv.Itoa(ctx.GetInstanceId())
 	//load cache
-	if err :=c.loadCache(); err != nil{
+	if err := c.loadCache(); err != nil {
 		go c.drainError(err)
 		return
 	}
 
 	ticker := common.NewDefaultTicker(c.saveInterval)
-	for{
+	for {
 		select {
 		case item := <-c.in:
 			index := c.pending.Tail
@@ -100,14 +100,14 @@ func (c *Cache) run(ctx api.StreamContext){
 		case index := <-c.Complete:
 			c.pending.delete(index)
 			c.changed = true
-		case <- ticker.GetC():
-			if c.pending.length() == 0{
+		case <-ticker.GetC():
+			if c.pending.length() == 0 {
 				c.pending.reset()
 			}
-			if c.changed{
+			if c.changed {
 				logger.Debugf("save cache")
-				go func(){
-					if err := c.saveCache();err != nil{
+				go func() {
+					if err := c.saveCache(); err != nil {
 						logger.Debugf("%v", err)
 						c.drainError(err)
 					}
@@ -115,7 +115,7 @@ func (c *Cache) run(ctx api.StreamContext){
 				c.changed = false
 			}
 		case <-ctx.Done():
-			if c.changed{
+			if c.changed {
 				c.saveCache()
 			}
 			return
@@ -123,7 +123,7 @@ func (c *Cache) run(ctx api.StreamContext){
 	}
 }
 
-func (c *Cache) loadCache() error{
+func (c *Cache) loadCache() error {
 	c.pending = &LinkedQueue{
 		Data: make(map[int]interface{}),
 		Tail: 0,
@@ -134,7 +134,7 @@ func (c *Cache) loadCache() error{
 		return err
 	}
 	defer c.store.Close()
-	if err == nil{
+	if err == nil {
 		if t, f := c.store.Get(c.key); f {
 			if mt, ok := t.(*LinkedQueue); ok {
 				c.pending = mt
@@ -144,7 +144,7 @@ func (c *Cache) loadCache() error{
 					keys = append(keys, k)
 				}
 				sort.Ints(keys)
-				for _, k := range keys{
+				for _, k := range keys {
 					log.Debugf("send by cache %d", k)
 					c.Out <- &CacheTuple{
 						index: k,
@@ -160,7 +160,7 @@ func (c *Cache) loadCache() error{
 	return nil
 }
 
-func (c *Cache) saveCache() error{
+func (c *Cache) saveCache() error {
 	err := c.store.Open()
 	if err != nil {
 		return err
@@ -169,10 +169,10 @@ func (c *Cache) saveCache() error{
 	return c.store.Replace(c.key, c.pending)
 }
 
-func (c *Cache) drainError(err error){
+func (c *Cache) drainError(err error) {
 	c.errorCh <- err
 }
 
-func (c *Cache) Length() int{
+func (c *Cache) Length() int {
 	return c.pending.length()
-}
+}

+ 29 - 29
xstream/nodes/sink_node.go

@@ -12,20 +12,20 @@ import (
 
 type SinkNode struct {
 	//static
-	input  chan interface{}
-	name   string
+	input    chan interface{}
+	name     string
 	sinkType string
-	mutex   sync.RWMutex
+	mutex    sync.RWMutex
 	//configs (also static for sinks)
 	concurrency int
-	options map[string]interface{}
+	options     map[string]interface{}
 	//states varies after restart
 	ctx          api.StreamContext
 	statManagers []StatManager
 	sinks        []api.Sink
 }
 
-func NewSinkNode(name string, sinkType string, props map[string]interface{}) *SinkNode{
+func NewSinkNode(name string, sinkType string, props map[string]interface{}) *SinkNode {
 	bufferLength := 1024
 	if c, ok := props["bufferLength"]; ok {
 		if t, err := common.ToInt(c); err != nil || t <= 0 {
@@ -35,24 +35,24 @@ func NewSinkNode(name string, sinkType string, props map[string]interface{}) *Si
 		}
 	}
 	return &SinkNode{
-		input: make(chan interface{}, bufferLength),
-		name: name,
-		sinkType: sinkType,
-		options: props,
+		input:       make(chan interface{}, bufferLength),
+		name:        name,
+		sinkType:    sinkType,
+		options:     props,
 		concurrency: 1,
-		ctx: nil,
+		ctx:         nil,
 	}
 }
 
 //Only for mock source, do not use it in production
 func NewSinkNodeWithSink(name string, sink api.Sink) *SinkNode {
 	return &SinkNode{
-		input: make(chan interface{}, 1024),
-		name:  name,
-		sinks: []api.Sink{sink},
-		options: nil,
+		input:       make(chan interface{}, 1024),
+		name:        name,
+		sinks:       []api.Sink{sink},
+		options:     nil,
 		concurrency: 1,
-		ctx:   nil,
+		ctx:         nil,
 	}
 }
 
@@ -103,12 +103,12 @@ func (m *SinkNode) Open(ctx api.StreamContext, result chan<- error) {
 		createSink := len(m.sinks) == 0
 		logger.Infof("open sink node %d instances", m.concurrency)
 		for i := 0; i < m.concurrency; i++ { // workers
-			go func(instance int){
+			go func(instance int) {
 				var sink api.Sink
 				var err error
-				if createSink{
+				if createSink {
 					sink, err = getSink(m.sinkType, m.options)
-					if err != nil{
+					if err != nil {
 						m.drainError(result, err, ctx, logger)
 						return
 					}
@@ -119,12 +119,12 @@ func (m *SinkNode) Open(ctx api.StreamContext, result chan<- error) {
 						m.drainError(result, err, ctx, logger)
 						return
 					}
-				}else{
+				} else {
 					sink = m.sinks[instance]
 				}
 
 				stats, err := NewStatManager("sink", ctx)
-				if err != nil{
+				if err != nil {
 					m.drainError(result, err, ctx, logger)
 					return
 				}
@@ -135,9 +135,9 @@ func (m *SinkNode) Open(ctx api.StreamContext, result chan<- error) {
 				cache := NewCache(m.input, cacheLength, cacheSaveInterval, result, ctx)
 				for {
 					select {
-					case data := <- cache.Out:
+					case data := <-cache.Out:
 						stats.SetBufferLength(int64(cache.Length()))
-						if runAsync{
+						if runAsync {
 							go doCollect(sink, data, stats, retryInterval, cache.Complete, ctx)
 						} else {
 							doCollect(sink, data, stats, retryInterval, cache.Complete, ctx)
@@ -155,18 +155,18 @@ func (m *SinkNode) Open(ctx api.StreamContext, result chan<- error) {
 	}()
 }
 
-func doCollect(sink api.Sink, item *CacheTuple, stats StatManager, retryInterval int, signalCh chan<- int, ctx api.StreamContext, ) {
+func doCollect(sink api.Sink, item *CacheTuple, stats StatManager, retryInterval int, signalCh chan<- int, ctx api.StreamContext) {
 	stats.IncTotalRecordsIn()
 	stats.ProcessTimeStart()
 	logger := ctx.GetLogger()
-	for{
+	for {
 		if err := sink.Collect(ctx, item.data); err != nil {
 			stats.IncTotalExceptions()
 			logger.Warnf("sink node %s instance %d publish %s error: %v", ctx.GetOpId(), ctx.GetInstanceId(), item.data, err)
-			if retryInterval > 0{
+			if retryInterval > 0 {
 				time.Sleep(time.Duration(retryInterval) * time.Millisecond)
 				logger.Debugf("try again")
-			}else{
+			} else {
 				break
 			}
 		} else {
@@ -218,14 +218,14 @@ func (m *SinkNode) GetInput() (chan<- interface{}, string) {
 }
 
 func (m *SinkNode) GetMetrics() (result [][]interface{}) {
-	for _, stats := range m.statManagers{
+	for _, stats := range m.statManagers {
 		result = append(result, stats.GetMetrics())
 	}
 	return result
 }
 
 func (m *SinkNode) drainError(errCh chan<- error, err error, ctx api.StreamContext, logger api.Logger) {
-	go func(){
+	go func() {
 		select {
 		case errCh <- err:
 		case <-ctx.Done():
@@ -243,4 +243,4 @@ func (m *SinkNode) close(ctx api.StreamContext, logger api.Logger) {
 	//reset the states
 	m.sinks = nil
 	m.statManagers = nil
-}
+}

+ 12 - 12
xstream/nodes/source_node.go

@@ -20,10 +20,10 @@ type SourceNode struct {
 	options     map[string]string
 	concurrency int
 
-	mutex   	sync.RWMutex
-	sources 	[]api.Source
+	mutex        sync.RWMutex
+	sources      []api.Source
 	statManagers []StatManager
-	buffer      *utils.DynamicChannelBuffer
+	buffer       *utils.DynamicChannelBuffer
 }
 
 func NewSourceNode(name string, options map[string]string) *SourceNode {
@@ -45,11 +45,11 @@ func NewSourceNode(name string, options map[string]string) *SourceNode {
 //Only for mock source, do not use it in production
 func NewSourceNodeWithSource(name string, source api.Source, options map[string]string) *SourceNode {
 	return &SourceNode{
-		sources: 	 []api.Source{  source},
-		outs:    make(map[string]chan<- interface{}),
-		name:    name,
-		options: options,
-		ctx:     nil,
+		sources:     []api.Source{source},
+		outs:        make(map[string]chan<- interface{}),
+		name:        name,
+		options:     options,
+		ctx:         nil,
 		concurrency: 1,
 		buffer:      utils.NewDynamicChannelBuffer(),
 	}
@@ -82,7 +82,7 @@ func (m *SourceNode) Open(ctx api.StreamContext, errCh chan<- error) {
 				//Do open source instances
 				var source api.Source
 				var err error
-				if createSource{
+				if createSource {
 					source, err = getSource(m.sourceType)
 					if err != nil {
 						m.drainError(errCh, err, ctx, logger)
@@ -96,7 +96,7 @@ func (m *SourceNode) Open(ctx api.StreamContext, errCh chan<- error) {
 					m.mutex.Lock()
 					m.sources = append(m.sources, source)
 					m.mutex.Unlock()
-				}else{
+				} else {
 					source = m.sources[instance]
 				}
 				stats, err := NewStatManager("source", ctx)
@@ -131,7 +131,7 @@ func (m *SourceNode) Open(ctx api.StreamContext, errCh chan<- error) {
 				logger.Infof("source %s done", m.name)
 				m.close(ctx, logger)
 				return
-			case data := <- m.buffer.Out:
+			case data := <-m.buffer.Out:
 				//blocking
 				Broadcast(m.outs, data, ctx)
 			}
@@ -232,7 +232,7 @@ func (m *SourceNode) AddOutput(output chan<- interface{}, name string) (err erro
 }
 
 func (m *SourceNode) GetMetrics() (result [][]interface{}) {
-	for _, stats := range m.statManagers{
+	for _, stats := range m.statManagers {
 		result = append(result, stats.GetMetrics())
 	}
 	return result

+ 13 - 12
xstream/nodes/stats_manager.go

@@ -18,6 +18,7 @@ type StatManager interface {
 	SetBufferLength(l int64)
 	GetMetrics() []interface{}
 }
+
 //The statManager is not thread safe. Make sure it is used in only one instance
 type DefaultStatManager struct {
 	//metrics
@@ -32,17 +33,17 @@ type DefaultStatManager struct {
 	prefix           string
 	processTimeStart time.Time
 	opId             string
-	instanceId		 int
+	instanceId       int
 }
 
-type PrometheusStatManager struct{
+type PrometheusStatManager struct {
 	DefaultStatManager
 	//prometheus metrics
 	pTotalRecordsIn  prometheus.Counter
 	pTotalRecordsOut prometheus.Counter
 	pTotalExceptions prometheus.Counter
 	pProcessLatency  prometheus.Gauge
-	pBufferLength	 prometheus.Gauge
+	pBufferLength    prometheus.Gauge
 }
 
 func NewStatManager(opType string, ctx api.StreamContext) (StatManager, error) {
@@ -63,9 +64,9 @@ func NewStatManager(opType string, ctx api.StreamContext) (StatManager, error) {
 		ctx.GetLogger().Debugf("Create prometheus stat manager")
 		psm := &PrometheusStatManager{
 			DefaultStatManager: DefaultStatManager{
-				opType: opType,
-				prefix: prefix,
-				opId:   ctx.GetOpId(),
+				opType:     opType,
+				prefix:     prefix,
+				opId:       ctx.GetOpId(),
 				instanceId: ctx.GetInstanceId(),
 			},
 		}
@@ -78,11 +79,11 @@ func NewStatManager(opType string, ctx api.StreamContext) (StatManager, error) {
 		psm.pProcessLatency = mg.ProcessLatency.WithLabelValues(ctx.GetRuleId(), opType, ctx.GetOpId(), strInId)
 		psm.pBufferLength = mg.BufferLength.WithLabelValues(ctx.GetRuleId(), opType, ctx.GetOpId(), strInId)
 		sm = psm
-	}else{
+	} else {
 		sm = &DefaultStatManager{
-			opType: opType,
-			prefix: prefix,
-			opId:   ctx.GetOpId(),
+			opType:     opType,
+			prefix:     prefix,
+			opId:       ctx.GetOpId(),
 			instanceId: ctx.GetInstanceId(),
 		}
 	}
@@ -152,9 +153,9 @@ func (sm *DefaultStatManager) GetMetrics() []interface{} {
 		sm.totalRecordsIn, sm.totalRecordsOut, sm.totalExceptions, sm.processLatency, sm.bufferLength,
 	}
 
-	if !sm.lastInvocation.IsZero(){
+	if !sm.lastInvocation.IsZero() {
 		result = append(result, sm.lastInvocation.Format("2006-01-02T15:04:05.999999"))
-	}else{
+	} else {
 		result = append(result, 0)
 	}
 

+ 8 - 8
xstream/operators/operations.go

@@ -21,13 +21,13 @@ func (f UnFunc) Apply(ctx api.StreamContext, data interface{}) interface{} {
 }
 
 type UnaryOperator struct {
-	op          UnOperation
-	concurrency int
-	input       chan interface{}
-	outputs     map[string]chan<- interface{}
-	mutex       sync.RWMutex
-	cancelled   bool
-	name        string
+	op           UnOperation
+	concurrency  int
+	input        chan interface{}
+	outputs      map[string]chan<- interface{}
+	mutex        sync.RWMutex
+	cancelled    bool
+	name         string
 	statManagers []nodes.StatManager
 }
 
@@ -161,7 +161,7 @@ func (o *UnaryOperator) doOp(ctx api.StreamContext, errCh chan<- error) {
 }
 
 func (m *UnaryOperator) GetMetrics() (result [][]interface{}) {
-	for _, stats := range m.statManagers{
+	for _, stats := range m.statManagers {
 		result = append(result, stats.GetMetrics())
 	}
 	return result

+ 5 - 5
xstream/server/server/server.go

@@ -67,7 +67,7 @@ func stopQuery() {
 func (t *Server) GetQueryResult(qid string, reply *string) error {
 	if rs, ok := registry[QUERY_RULE_ID]; ok {
 		c := (*rs.Topology).GetContext()
-		if c != nil && c.Err() != nil{
+		if c != nil && c.Err() != nil {
 			return c.Err()
 		}
 	}
@@ -142,7 +142,7 @@ func (t *Server) GetStatusRule(name string, reply *string) error {
 			case nil:
 				keys, values := (*rs.Topology).GetMetrics()
 				metrics := "{"
-				for i, key := range keys{
+				for i, key := range keys {
 					value := values[i]
 					switch value.(type) {
 					case string:
@@ -151,7 +151,7 @@ func (t *Server) GetStatusRule(name string, reply *string) error {
 						metrics += fmt.Sprintf("\"%s\":%v,", key, value)
 					}
 				}
-				metrics = metrics[:len(metrics) - 1] +  "}"
+				metrics = metrics[:len(metrics)-1] + "}"
 				dst := &bytes.Buffer{}
 				if err = json.Indent(dst, []byte(metrics), "", "  "); err != nil {
 					*reply = "Running with metrics:\n" + metrics
@@ -332,8 +332,8 @@ func StartUp(Version string) {
 	msg := fmt.Sprintf("Serving kuiper (version - %s) on port %d... \n", Version, common.Config.Port)
 	log.Info(msg)
 	fmt.Printf(msg)
-	if common.Config.Prometheus{
-		go func(){
+	if common.Config.Prometheus {
+		go func() {
 			port := common.Config.PrometheusPort
 			if port <= 0 {
 				log.Fatal("Miss configuration prometheusPort")

+ 5 - 5
xstream/sinks/log_sink.go

@@ -1,9 +1,9 @@
 package sinks
 
 import (
+	"fmt"
 	"github.com/emqx/kuiper/xstream/api"
 	"github.com/emqx/kuiper/xstream/collectors"
-	"fmt"
 	"sync"
 	"time"
 )
@@ -19,12 +19,12 @@ func NewLogSink() *collectors.FuncCollector {
 }
 
 type QueryResult struct {
-	Results []string
+	Results   []string
 	LastFetch time.Time
-	Mux sync.Mutex
+	Mux       sync.Mutex
 }
 
-var QR = &QueryResult{LastFetch:time.Now()}
+var QR = &QueryResult{LastFetch: time.Now()}
 
 func NewLogSinkToMemory() *collectors.FuncCollector {
 	QR.Results = make([]string, 10)
@@ -34,4 +34,4 @@ func NewLogSinkToMemory() *collectors.FuncCollector {
 		QR.Mux.Unlock()
 		return nil
 	})
-}
+}

+ 6 - 7
xstream/sinks/mqtt_sink.go

@@ -15,7 +15,7 @@ type MQTTSink struct {
 	tpc      string
 	clientid string
 	pVersion uint
-	uName 	string
+	uName    string
 	password string
 	certPath string
 	pkeyPath string
@@ -33,10 +33,10 @@ func (ms *MQTTSink) Configure(ps map[string]interface{}) error {
 		return fmt.Errorf("mqtt sink is missing property topic")
 	}
 	clientid, ok := ps["clientId"]
-	if !ok{
+	if !ok {
 		if uuid, err := uuid.NewUUID(); err != nil {
 			return fmt.Errorf("mqtt sink fails to get uuid, the error is %s", err)
-		}else{
+		} else {
 
 			clientid = uuid.String()
 		}
@@ -132,14 +132,14 @@ func (ms *MQTTSink) Open(ctx api.StreamContext) error {
 	opts.SetAutoReconnect(true)
 	var reconn = false
 	opts.SetConnectionLostHandler(func(client MQTT.Client, e error) {
-		log.Errorf("The connection %s is disconnected due to error %s, will try to re-connect later.", ms.srv + ": " + ms.clientid, e)
+		log.Errorf("The connection %s is disconnected due to error %s, will try to re-connect later.", ms.srv+": "+ms.clientid, e)
 		ms.conn = client
 		reconn = true
 	})
 
 	opts.SetOnConnectHandler(func(client MQTT.Client) {
 		if reconn {
-			log.Infof("The connection is %s re-established successfully.", ms.srv + ": " + ms.clientid)
+			log.Infof("The connection is %s re-established successfully.", ms.srv+": "+ms.clientid)
 		}
 	})
 
@@ -148,7 +148,6 @@ func (ms *MQTTSink) Open(ctx api.StreamContext) error {
 		return fmt.Errorf("Found error: %s", token.Error())
 	}
 
-
 	log.Infof("The connection to server %s was established successfully", ms.srv)
 	ms.conn = c
 	return nil
@@ -171,4 +170,4 @@ func (ms *MQTTSink) Close(ctx api.StreamContext) error {
 		ms.conn.Disconnect(5000)
 	}
 	return nil
-}
+}

+ 42 - 42
xstream/sinks/rest_sink.go

@@ -16,20 +16,20 @@ import (
 )
 
 type RestSink struct {
-	method      string
-	url         string
-	headers     map[string]string
-	bodyType    string
-	timeout		int64
-	sendSingle  bool
+	method       string
+	url          string
+	headers      map[string]string
+	bodyType     string
+	timeout      int64
+	sendSingle   bool
 	dataTemplate string
 
-	client      *http.Client
-	tp          *template.Template
+	client *http.Client
+	tp     *template.Template
 }
 
 var methodsMap = map[string]bool{"GET": true, "HEAD": true, "POST": true, "PUT": true, "DELETE": true, "PATCH": true}
-var bodyTypeMap = map[string]string{"none":"", "text": "text/plain", "json":"application/json", "html": "text/html", "xml": "application/xml", "javascript": "application/javascript", "form": ""}
+var bodyTypeMap = map[string]string{"none": "", "text": "text/plain", "json": "application/json", "html": "text/html", "xml": "application/xml", "javascript": "application/javascript", "form": ""}
 
 func (ms *RestSink) Configure(ps map[string]interface{}) error {
 	temp, ok := ps["method"]
@@ -39,13 +39,13 @@ func (ms *RestSink) Configure(ps map[string]interface{}) error {
 			return fmt.Errorf("rest sink property method %v is not a string", temp)
 		}
 		ms.method = strings.ToUpper(strings.Trim(ms.method, ""))
-	}else{
+	} else {
 		ms.method = "GET"
 	}
 	if _, ok = methodsMap[ms.method]; !ok {
 		return fmt.Errorf("invalid property method: %s", ms.method)
 	}
-	switch ms.method{
+	switch ms.method {
 	case "GET", "HEAD":
 		ms.bodyType = "none"
 	default:
@@ -63,7 +63,7 @@ func (ms *RestSink) Configure(ps map[string]interface{}) error {
 	ms.url = strings.Trim(ms.url, "")
 
 	temp, ok = ps["headers"]
-	if ok{
+	if ok {
 		ms.headers, ok = temp.(map[string]string)
 		if !ok {
 			return fmt.Errorf("rest sink property headers %v is not a map[string][]string", temp)
@@ -71,7 +71,7 @@ func (ms *RestSink) Configure(ps map[string]interface{}) error {
 	}
 
 	temp, ok = ps["bodyType"]
-	if ok{
+	if ok {
 		ms.bodyType, ok = temp.(string)
 		if !ok {
 			return fmt.Errorf("rest sink property bodyType %v is not a string", temp)
@@ -85,7 +85,7 @@ func (ms *RestSink) Configure(ps map[string]interface{}) error {
 	temp, ok = ps["timeout"]
 	if !ok {
 		ms.timeout = 5000
-	}else{
+	} else {
 		to, ok := temp.(float64)
 		if !ok {
 			return fmt.Errorf("rest sink property timeout %v is not a number", temp)
@@ -94,9 +94,9 @@ func (ms *RestSink) Configure(ps map[string]interface{}) error {
 	}
 
 	temp, ok = ps["sendSingle"]
-	if !ok{
+	if !ok {
 		ms.sendSingle = false
-	}else{
+	} else {
 		ms.sendSingle, ok = temp.(bool)
 		if !ok {
 			return fmt.Errorf("rest sink property sendSingle %v is not a bool", temp)
@@ -104,21 +104,21 @@ func (ms *RestSink) Configure(ps map[string]interface{}) error {
 	}
 
 	temp, ok = ps["dataTemplate"]
-	if ok{
+	if ok {
 		ms.dataTemplate, ok = temp.(string)
 		if !ok {
 			return fmt.Errorf("rest sink property dataTemplate %v is not a string", temp)
 		}
 	}
 
-	if ms.dataTemplate != ""{
+	if ms.dataTemplate != "" {
 		funcMap := template.FuncMap{
 			"json": templates.JsonMarshal,
 		}
 		temp, err := template.New("restSink").Funcs(funcMap).Parse(ms.dataTemplate)
-		if err != nil{
+		if err != nil {
 			return fmt.Errorf("rest sink property dataTemplate %v is invalid: %v", ms.dataTemplate, err)
-		}else{
+		} else {
 			ms.tp = temp
 		}
 	}
@@ -147,14 +147,14 @@ func (ms *RestSink) Open(ctx api.StreamContext) error {
 
 type MultiErrors []error
 
-func (me MultiErrors) AddError(err error) (MultiErrors) {
+func (me MultiErrors) AddError(err error) MultiErrors {
 	me = append(me, err)
 	return me
 }
 
 func (me MultiErrors) Error() string {
 	s := make([]string, len(me))
-	for i, v  := range me {
+	for i, v := range me {
 		s = append(s, fmt.Sprintf("Error %d with info %s. \n", i, v))
 	}
 	return strings.Join(s, "  ")
@@ -167,9 +167,9 @@ func (ms *RestSink) Collect(ctx api.StreamContext, item interface{}) error {
 		logger.Warnf("rest sink receive non []byte data: %v", item)
 	}
 	logger.Debugf("rest sink receive %s", item)
-	if !ms.sendSingle{
+	if !ms.sendSingle {
 		return ms.send(v, logger)
-	}else{
+	} else {
 		j, err := extractInput(v)
 		if err != nil {
 			return err
@@ -215,21 +215,21 @@ func (ms *RestSink) send(v interface{}, logger api.Logger) error {
 					return err
 				}
 				err = ms.tp.Execute(body, j)
-				if err != nil{
+				if err != nil {
 					return fmt.Errorf("fail to decode content: %v", err)
 				}
-			}else{
+			} else {
 				body = bytes.NewBuffer(t)
 			}
 		case map[string]interface{}:
-			if ms.tp != nil{
+			if ms.tp != nil {
 				err = ms.tp.Execute(body, t)
-				if err != nil{
+				if err != nil {
 					return fmt.Errorf("fail to decode content: %v", err)
 				}
-			}else{
+			} else {
 				content, err := json.Marshal(t)
-				if err != nil{
+				if err != nil {
 					return fmt.Errorf("fail to decode content: %v", err)
 				}
 				body = bytes.NewBuffer(content)
@@ -255,7 +255,7 @@ func (ms *RestSink) send(v interface{}, logger api.Logger) error {
 			case []interface{}, map[string]interface{}:
 				if temp, err := json.Marshal(value); err != nil {
 					return fmt.Errorf("fail to parse fomr value: %v", err)
-				}else{
+				} else {
 					vstr = string(temp)
 				}
 			default:
@@ -294,41 +294,41 @@ func (ms *RestSink) send(v interface{}, logger api.Logger) error {
 func convertToMap(v interface{}, tp *template.Template) (map[string]interface{}, error) {
 	switch t := v.(type) {
 	case []byte:
-		if tp != nil{
+		if tp != nil {
 			j, err := extractInput(t)
 			if err != nil {
 				return nil, err
 			}
 			var output bytes.Buffer
 			err = tp.Execute(&output, j)
-			if err != nil{
+			if err != nil {
 				return nil, fmt.Errorf("fail to decode content: %v", err)
 			}
 			r := make(map[string]interface{})
-			if err := json.Unmarshal(output.Bytes(), &r); err != nil{
+			if err := json.Unmarshal(output.Bytes(), &r); err != nil {
 				return nil, fmt.Errorf("fail to decode content: %v", err)
-			}else{
+			} else {
 				return r, nil
 			}
-		}else{
+		} else {
 			r := make(map[string]interface{})
 			r["result"] = string(t)
 			return r, nil
 		}
 	case map[string]interface{}:
-		if tp != nil{
+		if tp != nil {
 			var output bytes.Buffer
 			err := tp.Execute(&output, t)
-			if err != nil{
+			if err != nil {
 				return nil, fmt.Errorf("fail to decode content: %v", err)
 			}
 			r := make(map[string]interface{})
-			if err := json.Unmarshal(output.Bytes(), &r); err != nil{
+			if err := json.Unmarshal(output.Bytes(), &r); err != nil {
 				return nil, fmt.Errorf("fail to decode content: %v", err)
-			}else{
+			} else {
 				return r, nil
 			}
-		}else{
+		} else {
 			return t, nil
 		}
 	default:
@@ -341,4 +341,4 @@ func (ms *RestSink) Close(ctx api.StreamContext) error {
 	logger := ctx.GetLogger()
 	logger.Infof("Closing rest sink")
 	return nil
-}
+}

+ 120 - 120
xstream/sinks/rest_sink_test.go

@@ -12,17 +12,17 @@ import (
 	"testing"
 )
 
-type request struct{
-	Method string
-	Body   string
+type request struct {
+	Method      string
+	Body        string
 	ContentType string
 }
 
 func TestRestSink_Apply(t *testing.T) {
 	var tests = []struct {
-		config  map[string]interface{}
-		data 	[]map[string]interface{}
-		result  []request
+		config map[string]interface{}
+		data   []map[string]interface{}
+		result []request
 	}{
 		{
 			config: map[string]interface{}{
@@ -30,109 +30,109 @@ func TestRestSink_Apply(t *testing.T) {
 				//"url": "http://localhost/test",  //set dynamically to the test server
 				"sendSingle": true,
 			},
-			data:[]map[string]interface{}{{
-				"ab" : "hello1",
-			},{
-				"ab" : "hello2",
+			data: []map[string]interface{}{{
+				"ab": "hello1",
+			}, {
+				"ab": "hello2",
 			}},
 			result: []request{{
-				Method: "POST",
-				Body: `{"ab":"hello1"}`,
+				Method:      "POST",
+				Body:        `{"ab":"hello1"}`,
 				ContentType: "application/json",
-			},{
-				Method: "POST",
-				Body: `{"ab":"hello2"}`,
+			}, {
+				Method:      "POST",
+				Body:        `{"ab":"hello2"}`,
 				ContentType: "application/json",
 			}},
-		},{
+		}, {
 			config: map[string]interface{}{
 				"method": "post",
 				//"url": "http://localhost/test",  //set dynamically to the test server
 			},
-			data:[]map[string]interface{}{{
-				"ab" : "hello1",
-			},{
-				"ab" : "hello2",
+			data: []map[string]interface{}{{
+				"ab": "hello1",
+			}, {
+				"ab": "hello2",
 			}},
 			result: []request{{
-				Method: "POST",
-				Body: `[{"ab":"hello1"},{"ab":"hello2"}]`,
+				Method:      "POST",
+				Body:        `[{"ab":"hello1"},{"ab":"hello2"}]`,
 				ContentType: "application/json",
 			}},
-		},{
+		}, {
 			config: map[string]interface{}{
 				"method": "get",
 				//"url": "http://localhost/test",  //set dynamically to the test server
 			},
-			data:[]map[string]interface{}{{
-				"ab" : "hello1",
-			},{
-				"ab" : "hello2",
+			data: []map[string]interface{}{{
+				"ab": "hello1",
+			}, {
+				"ab": "hello2",
 			}},
 			result: []request{{
-				Method: "GET",
+				Method:      "GET",
 				ContentType: "",
 			}},
-		},{
+		}, {
 			config: map[string]interface{}{
 				"method": "put",
 				//"url": "http://localhost/test",  //set dynamically to the test server
 				"bodyType": "text",
 			},
-			data:[]map[string]interface{}{{
-				"ab" : "hello1",
-			},{
-				"ab" : "hello2",
+			data: []map[string]interface{}{{
+				"ab": "hello1",
+			}, {
+				"ab": "hello2",
 			}},
 			result: []request{{
-				Method: "PUT",
+				Method:      "PUT",
 				ContentType: "text/plain",
-				Body: `[{"ab":"hello1"},{"ab":"hello2"}]`,
+				Body:        `[{"ab":"hello1"},{"ab":"hello2"}]`,
 			}},
-		},{
+		}, {
 			config: map[string]interface{}{
 				"method": "post",
 				//"url": "http://localhost/test",  //set dynamically to the test server
 				"bodyType": "form",
 			},
-			data:[]map[string]interface{}{{
-				"ab" : "hello1",
-			},{
-				"ab" : "hello2",
+			data: []map[string]interface{}{{
+				"ab": "hello1",
+			}, {
+				"ab": "hello2",
 			}},
 			result: []request{{
-				Method: "POST",
+				Method:      "POST",
 				ContentType: "application/x-www-form-urlencoded;param=value",
-				Body: `result=%5B%7B%22ab%22%3A%22hello1%22%7D%2C%7B%22ab%22%3A%22hello2%22%7D%5D`,
+				Body:        `result=%5B%7B%22ab%22%3A%22hello1%22%7D%2C%7B%22ab%22%3A%22hello2%22%7D%5D`,
 			}},
-		},{
+		}, {
 			config: map[string]interface{}{
 				"method": "post",
 				//"url": "http://localhost/test",  //set dynamically to the test server
-				"bodyType": "form",
+				"bodyType":   "form",
 				"sendSingle": true,
 			},
-			data:[]map[string]interface{}{{
-				"ab" : "hello1",
-			},{
-				"ab" : "hello2",
+			data: []map[string]interface{}{{
+				"ab": "hello1",
+			}, {
+				"ab": "hello2",
 			}},
 			result: []request{{
-				Method: "POST",
+				Method:      "POST",
 				ContentType: "application/x-www-form-urlencoded;param=value",
-				Body: `ab=hello1`,
-			},{
-				Method: "POST",
+				Body:        `ab=hello1`,
+			}, {
+				Method:      "POST",
 				ContentType: "application/x-www-form-urlencoded;param=value",
-				Body: `ab=hello2`,
+				Body:        `ab=hello2`,
 			}},
 		}, {
 			config: map[string]interface{}{
 				"method": "post",
 				//"url": "http://localhost/test",  //set dynamically to the test server
-				"bodyType": "json",
+				"bodyType":   "json",
 				"sendSingle": true,
-				"timeout": float64(1000),
+				"timeout":    float64(1000),
 			},
 			data: []map[string]interface{}{{
 				"ab": "hello1",
@@ -155,7 +155,7 @@ func TestRestSink_Apply(t *testing.T) {
 	ctx := contexts.WithValue(contexts.Background(), contexts.LoggerKey, contextLogger)
 
 	var requests []request
-	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){
+	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		body, err := ioutil.ReadAll(r.Body)
 		if err != nil {
 			fmt.Printf("Error reading body: %v", err)
@@ -164,8 +164,8 @@ func TestRestSink_Apply(t *testing.T) {
 		}
 
 		requests = append(requests, request{
-			Method: r.Method,
-			Body: string(body),
+			Method:      r.Method,
+			Body:        string(body),
 			ContentType: r.Header.Get("Content-Type"),
 		})
 		contextLogger.Debugf(string(body))
@@ -179,7 +179,7 @@ func TestRestSink_Apply(t *testing.T) {
 		s.Configure(tt.config)
 		s.Open(ctx)
 		input, err := json.Marshal(tt.data)
-		if err != nil{
+		if err != nil {
 			t.Errorf("Failed to parse the input into []byte]")
 			continue
 		}
@@ -193,125 +193,125 @@ func TestRestSink_Apply(t *testing.T) {
 
 func TestRestSinkTemplate_Apply(t *testing.T) {
 	var tests = []struct {
-		config  map[string]interface{}
-		data 	[]map[string]interface{}
-		result  []request
+		config map[string]interface{}
+		data   []map[string]interface{}
+		result []request
 	}{
 		{
 			config: map[string]interface{}{
 				"method": "post",
 				//"url": "http://localhost/test",  //set dynamically to the test server
-				"sendSingle": true,
+				"sendSingle":   true,
 				"dataTemplate": `{"wrapper":"w1","content":{{json .}},"ab":"{{.ab}}"}`,
 			},
-			data:[]map[string]interface{}{{
-				"ab" : "hello1",
-			},{
-				"ab" : "hello2",
+			data: []map[string]interface{}{{
+				"ab": "hello1",
+			}, {
+				"ab": "hello2",
 			}},
 			result: []request{{
-				Method: "POST",
-				Body: `{"wrapper":"w1","content":{"ab":"hello1"},"ab":"hello1"}`,
+				Method:      "POST",
+				Body:        `{"wrapper":"w1","content":{"ab":"hello1"},"ab":"hello1"}`,
 				ContentType: "application/json",
-			},{
-				Method: "POST",
-				Body: `{"wrapper":"w1","content":{"ab":"hello2"},"ab":"hello2"}`,
+			}, {
+				Method:      "POST",
+				Body:        `{"wrapper":"w1","content":{"ab":"hello2"},"ab":"hello2"}`,
 				ContentType: "application/json",
 			}},
-		},{
+		}, {
 			config: map[string]interface{}{
 				"method": "post",
 				//"url": "http://localhost/test",  //set dynamically to the test server
 				"dataTemplate": `{"wrapper":"arr","content":{{json .}},"content0":{{json (index . 0)}},ab0":"{{index . 0 "ab"}}"}`,
 			},
-			data:[]map[string]interface{}{{
-				"ab" : "hello1",
-			},{
-				"ab" : "hello2",
+			data: []map[string]interface{}{{
+				"ab": "hello1",
+			}, {
+				"ab": "hello2",
 			}},
 			result: []request{{
-				Method: "POST",
-				Body: `{"wrapper":"arr","content":[{"ab":"hello1"},{"ab":"hello2"}],"content0":{"ab":"hello1"},ab0":"hello1"}`,
+				Method:      "POST",
+				Body:        `{"wrapper":"arr","content":[{"ab":"hello1"},{"ab":"hello2"}],"content0":{"ab":"hello1"},ab0":"hello1"}`,
 				ContentType: "application/json",
 			}},
-		},{
+		}, {
 			config: map[string]interface{}{
 				"method": "get",
 				//"url": "http://localhost/test",  //set dynamically to the test server
 				"dataTemplate": `{"wrapper":"w1","content":{{json .}},"ab":"{{.ab}}"}`,
 			},
-			data:[]map[string]interface{}{{
-				"ab" : "hello1",
-			},{
-				"ab" : "hello2",
+			data: []map[string]interface{}{{
+				"ab": "hello1",
+			}, {
+				"ab": "hello2",
 			}},
 			result: []request{{
-				Method: "GET",
+				Method:      "GET",
 				ContentType: "",
 			}},
-		},{
+		}, {
 			config: map[string]interface{}{
 				"method": "put",
 				//"url": "http://localhost/test",  //set dynamically to the test server
-				"bodyType": "html",
+				"bodyType":     "html",
 				"dataTemplate": `<div>results</div><ul>{{range .}}<li>{{.ab}}</li>{{end}}</ul>`,
 			},
-			data:[]map[string]interface{}{{
-				"ab" : "hello1",
-			},{
-				"ab" : "hello2",
+			data: []map[string]interface{}{{
+				"ab": "hello1",
+			}, {
+				"ab": "hello2",
 			}},
 			result: []request{{
-				Method: "PUT",
+				Method:      "PUT",
 				ContentType: "text/html",
-				Body: `<div>results</div><ul><li>hello1</li><li>hello2</li></ul>`,
+				Body:        `<div>results</div><ul><li>hello1</li><li>hello2</li></ul>`,
 			}},
-		},{
+		}, {
 			config: map[string]interface{}{
 				"method": "post",
 				//"url": "http://localhost/test",  //set dynamically to the test server
-				"bodyType": "form",
+				"bodyType":     "form",
 				"dataTemplate": `{"content":{{json .}}}`,
 			},
-			data:[]map[string]interface{}{{
-				"ab" : "hello1",
-			},{
-				"ab" : "hello2",
+			data: []map[string]interface{}{{
+				"ab": "hello1",
+			}, {
+				"ab": "hello2",
 			}},
 			result: []request{{
-				Method: "POST",
+				Method:      "POST",
 				ContentType: "application/x-www-form-urlencoded;param=value",
-				Body: `content=%5B%7B%22ab%22%3A%22hello1%22%7D%2C%7B%22ab%22%3A%22hello2%22%7D%5D`,
+				Body:        `content=%5B%7B%22ab%22%3A%22hello1%22%7D%2C%7B%22ab%22%3A%22hello2%22%7D%5D`,
 			}},
-		},{
+		}, {
 			config: map[string]interface{}{
 				"method": "post",
 				//"url": "http://localhost/test",  //set dynamically to the test server
-				"bodyType": "form",
-				"sendSingle": true,
+				"bodyType":     "form",
+				"sendSingle":   true,
 				"dataTemplate": `{"newab":"{{.ab}}"}`,
 			},
-			data:[]map[string]interface{}{{
-				"ab" : "hello1",
-			},{
-				"ab" : "hello2",
+			data: []map[string]interface{}{{
+				"ab": "hello1",
+			}, {
+				"ab": "hello2",
 			}},
 			result: []request{{
-				Method: "POST",
+				Method:      "POST",
 				ContentType: "application/x-www-form-urlencoded;param=value",
-				Body: `newab=hello1`,
-			},{
-				Method: "POST",
+				Body:        `newab=hello1`,
+			}, {
+				Method:      "POST",
 				ContentType: "application/x-www-form-urlencoded;param=value",
-				Body: `newab=hello2`,
+				Body:        `newab=hello2`,
 			}},
 		}, {
 			config: map[string]interface{}{
 				"method": "post",
 				//"url": "http://localhost/test",  //set dynamically to the test server
-				"bodyType": "json",
-				"sendSingle": true,
-				"timeout": float64(1000),
+				"bodyType":     "json",
+				"sendSingle":   true,
+				"timeout":      float64(1000),
 				"dataTemplate": `{"newab":"{{.ab}}"}`,
 			},
 			data: []map[string]interface{}{{
@@ -335,7 +335,7 @@ func TestRestSinkTemplate_Apply(t *testing.T) {
 	ctx := contexts.WithValue(contexts.Background(), contexts.LoggerKey, contextLogger)
 
 	var requests []request
-	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){
+	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		body, err := ioutil.ReadAll(r.Body)
 		if err != nil {
 			fmt.Printf("Error reading body: %v", err)
@@ -344,8 +344,8 @@ func TestRestSinkTemplate_Apply(t *testing.T) {
 		}
 
 		requests = append(requests, request{
-			Method: r.Method,
-			Body: string(body),
+			Method:      r.Method,
+			Body:        string(body),
 			ContentType: r.Header.Get("Content-Type"),
 		})
 		contextLogger.Debugf(string(body))
@@ -359,7 +359,7 @@ func TestRestSinkTemplate_Apply(t *testing.T) {
 		s.Configure(tt.config)
 		s.Open(ctx)
 		input, err := json.Marshal(tt.data)
-		if err != nil{
+		if err != nil {
 			t.Errorf("Failed to parse the input into []byte]")
 			continue
 		}

+ 6 - 6
xstream/streams.go

@@ -111,24 +111,24 @@ func (s *TopologyNew) Open() <-chan error {
 func (s *TopologyNew) GetMetrics() (keys []string, values []interface{}) {
 	for _, node := range s.sources {
 		for ins, metrics := range node.GetMetrics() {
-			for i, v := range metrics{
-				keys = append(keys, "source_" + node.GetName() + "_" + strconv.Itoa(ins) + "_" + nodes.MetricNames[i])
+			for i, v := range metrics {
+				keys = append(keys, "source_"+node.GetName()+"_"+strconv.Itoa(ins)+"_"+nodes.MetricNames[i])
 				values = append(values, v)
 			}
 		}
 	}
 	for _, node := range s.ops {
 		for ins, metrics := range node.GetMetrics() {
-			for i, v := range metrics{
-				keys = append(keys, "op_" + node.GetName() + "_" + strconv.Itoa(ins) + "_" + nodes.MetricNames[i])
+			for i, v := range metrics {
+				keys = append(keys, "op_"+node.GetName()+"_"+strconv.Itoa(ins)+"_"+nodes.MetricNames[i])
 				values = append(values, v)
 			}
 		}
 	}
 	for _, node := range s.sinks {
 		for ins, metrics := range node.GetMetrics() {
-			for i, v := range metrics{
-				keys = append(keys, "sink_" + node.GetName() + "_" + strconv.Itoa(ins) + "_" + nodes.MetricNames[i])
+			for i, v := range metrics {
+				keys = append(keys, "sink_"+node.GetName()+"_"+strconv.Itoa(ins)+"_"+nodes.MetricNames[i])
 				values = append(values, v)
 			}
 		}

+ 9 - 10
xstream/test/mock_source.go

@@ -8,16 +8,16 @@ import (
 )
 
 type MockSource struct {
-	data []*xsql.Tuple
-	done chan<- struct{}
+	data        []*xsql.Tuple
+	done        chan<- struct{}
 	isEventTime bool
 }
 
 // New creates a new CsvSource
 func NewMockSource(data []*xsql.Tuple, done chan<- struct{}, isEventTime bool) *MockSource {
 	mock := &MockSource{
-		data: data,
-		done: done,
+		data:        data,
+		done:        done,
 		isEventTime: isEventTime,
 	}
 	return mock
@@ -27,10 +27,10 @@ func (m *MockSource) Open(ctx api.StreamContext, consume api.ConsumeFunc) (err e
 	log := ctx.GetLogger()
 
 	log.Debugln("mock source starts")
-	go func(){
-		for _, d := range m.data{
+	go func() {
+		for _, d := range m.data {
 			log.Debugf("mock source is sending data %s", d)
-			if !m.isEventTime{
+			if !m.isEventTime {
 				common.SetMockNow(d.Timestamp)
 				ticker := common.GetMockTicker()
 				timer := common.GetMockTimer()
@@ -47,7 +47,6 @@ func (m *MockSource) Open(ctx api.StreamContext, consume api.ConsumeFunc) (err e
 			}else{
 				time.Sleep(50 * time.Millisecond) //Let window run to make sure timers are set
 			}
-
 		}
 		if !m.isEventTime {
 			//reset now for the next test
@@ -58,10 +57,10 @@ func (m *MockSource) Open(ctx api.StreamContext, consume api.ConsumeFunc) (err e
 	return nil
 }
 
-func (m *MockSource) Close(ctx api.StreamContext) error{
+func (m *MockSource) Close(ctx api.StreamContext) error {
 	return nil
 }
 
 func (m *MockSource) Configure(topic string, props map[string]interface{}) error {
 	return nil
-}
+}

+ 9 - 11
xstream/util.go

@@ -2,8 +2,8 @@ package xstream
 
 import (
 	"encoding/json"
-	"github.com/emqx/kuiper/common"
 	"fmt"
+	"github.com/emqx/kuiper/common"
 	"io/ioutil"
 	"os"
 	"path/filepath"
@@ -12,7 +12,7 @@ import (
 
 type Conf map[string]interface{}
 
-var confs = make(map[string] Conf)
+var confs = make(map[string]Conf)
 
 func GetConfAsString(file, key string) (string, error) {
 	val, err := getConfValue(file, key)
@@ -25,8 +25,8 @@ func GetConfAsString(file, key string) (string, error) {
 		return v, nil
 	} else if val == nil {
 		return "", nil
-	}else {
-		return "", fmt.Errorf("The value %s is not type of string for key %s", val, key )
+	} else {
+		return "", fmt.Errorf("The value %s is not type of string for key %s", val, key)
 	}
 }
 
@@ -40,7 +40,7 @@ func GetConfAsInt(file, key string) (int, error) {
 	if v, ok := val.(float64); ok {
 		return int(v), nil
 	} else {
-		return 0, fmt.Errorf("The value {0} is not type of int for key {1}", )
+		return 0, fmt.Errorf("The value {0} is not type of int for key {1}")
 	}
 }
 
@@ -54,7 +54,7 @@ func GetConfAsFloat(file, key string) (float64, error) {
 	if v, ok := val.(float64); ok {
 		return v, nil
 	} else {
-		return 0, fmt.Errorf("The value {0} is not type of float for key {1}", )
+		return 0, fmt.Errorf("The value {0} is not type of float for key {1}")
 	}
 }
 
@@ -68,11 +68,10 @@ func GetConfAsBool(file, key string) (bool, error) {
 	if v, ok := val.(bool); ok {
 		return v, nil
 	} else {
-		return false, fmt.Errorf("The value {0} is not type of bool for key {1}", )
+		return false, fmt.Errorf("The value {0} is not type of bool for key {1}")
 	}
 }
 
-
 func getConfValue(file, key string) (interface{}, error) {
 	if conf, ok := confs[file]; !ok {
 		if c, e := initConf(file); e != nil {
@@ -112,7 +111,7 @@ func initConf(file string) (Conf, error) {
 	return conf, nil
 }
 
-func getValue(conf Conf, key string) (interface{}, error)  {
+func getValue(conf Conf, key string) (interface{}, error) {
 	keys := strings.Split(key, ".")
 
 	if len(keys) == 1 {
@@ -122,11 +121,10 @@ func getValue(conf Conf, key string) (interface{}, error)  {
 	nkey := strings.Join(keys[1:], ".")
 	ckey := strings.Join(keys[0:1], "")
 
-	if c, ok := conf[ckey].(map[string]interface {}); ok {
+	if c, ok := conf[ckey].(map[string]interface{}); ok {
 		return getValue(c, nkey)
 	} else {
 
 		return nil, fmt.Errorf("%s does not exsit for key %s.", conf, key)
 	}
 }
-