浏览代码

refactor(valuer): separate TupleRow and CollectionRow

Signed-off-by: Jiyong Huang <huangjy@emqx.io>
Jiyong Huang 2 年之前
父节点
当前提交
14202e29d9

+ 5 - 5
internal/topo/node/join_align_node.go

@@ -28,13 +28,13 @@ type JoinAlignNode struct {
 	*defaultSinkNode
 	*defaultSinkNode
 	statManager metric.StatManager
 	statManager metric.StatManager
 	// states
 	// states
-	batch map[string][]xsql.Row
+	batch map[string][]xsql.TupleRow
 }
 }
 
 
 const BatchKey = "$$batchInputs"
 const BatchKey = "$$batchInputs"
 
 
 func NewJoinAlignNode(name string, emitters []string, options *api.RuleOption) (*JoinAlignNode, error) {
 func NewJoinAlignNode(name string, emitters []string, options *api.RuleOption) (*JoinAlignNode, error) {
-	batch := make(map[string][]xsql.Row, len(emitters))
+	batch := make(map[string][]xsql.TupleRow, len(emitters))
 	for _, e := range emitters {
 	for _, e := range emitters {
 		batch[e] = nil
 		batch[e] = nil
 	}
 	}
@@ -72,7 +72,7 @@ func (n *JoinAlignNode) Exec(ctx api.StreamContext, errCh chan<- error) {
 			// restore batch state
 			// restore batch state
 			if s, err := ctx.GetState(BatchKey); err == nil {
 			if s, err := ctx.GetState(BatchKey); err == nil {
 				switch st := s.(type) {
 				switch st := s.(type) {
-				case map[string][]xsql.Row:
+				case map[string][]xsql.TupleRow:
 					n.batch = st
 					n.batch = st
 					log.Infof("Restore batch state %+v", st)
 					log.Infof("Restore batch state %+v", st)
 				case nil:
 				case nil:
@@ -84,7 +84,7 @@ func (n *JoinAlignNode) Exec(ctx api.StreamContext, errCh chan<- error) {
 				log.Warnf("Restore batch state fails: %s", err)
 				log.Warnf("Restore batch state fails: %s", err)
 			}
 			}
 			if n.batch == nil {
 			if n.batch == nil {
-				n.batch = make(map[string][]xsql.Row)
+				n.batch = make(map[string][]xsql.TupleRow)
 			}
 			}
 
 
 			for {
 			for {
@@ -109,7 +109,7 @@ func (n *JoinAlignNode) Exec(ctx api.StreamContext, errCh chan<- error) {
 					case *xsql.Tuple:
 					case *xsql.Tuple:
 						log.Debugf("JoinAlignNode receive tuple input %s", d)
 						log.Debugf("JoinAlignNode receive tuple input %s", d)
 						temp := &xsql.WindowTuples{
 						temp := &xsql.WindowTuples{
-							Content: make([]xsql.Row, 0),
+							Content: make([]xsql.TupleRow, 0),
 						}
 						}
 						temp = temp.AddTuple(d)
 						temp = temp.AddTuple(d)
 						n.alignBatch(ctx, temp)
 						n.alignBatch(ctx, temp)

+ 2 - 2
internal/topo/node/window_op.go

@@ -391,7 +391,7 @@ func (tl *TupleList) count() int {
 
 
 func (tl *TupleList) nextCountWindow() *xsql.WindowTuples {
 func (tl *TupleList) nextCountWindow() *xsql.WindowTuples {
 	results := &xsql.WindowTuples{
 	results := &xsql.WindowTuples{
-		Content: make([]xsql.Row, 0),
+		Content: make([]xsql.TupleRow, 0),
 	}
 	}
 	var subT []*xsql.Tuple
 	var subT []*xsql.Tuple
 	subT = tl.tuples[len(tl.tuples)-tl.size : len(tl.tuples)]
 	subT = tl.tuples[len(tl.tuples)-tl.size : len(tl.tuples)]
@@ -421,7 +421,7 @@ func (o *WindowOperator) scan(inputs []*xsql.Tuple, triggerTime int64, ctx api.S
 		delta = o.calDelta(triggerTime, delta, log)
 		delta = o.calDelta(triggerTime, delta, log)
 	}
 	}
 	results := &xsql.WindowTuples{
 	results := &xsql.WindowTuples{
-		Content: make([]xsql.Row, 0),
+		Content: make([]xsql.TupleRow, 0),
 	}
 	}
 	i := 0
 	i := 0
 	//Sync table
 	//Sync table

+ 3 - 3
internal/topo/node/window_op_test.go

@@ -79,7 +79,7 @@ func TestCountWindow(t *testing.T) {
 			expWinCount: 1,
 			expWinCount: 1,
 			winTupleSets: []xsql.WindowTuples{
 			winTupleSets: []xsql.WindowTuples{
 				{
 				{
-					Content: []xsql.Row{
+					Content: []xsql.TupleRow{
 
 
 						&xsql.Tuple{
 						&xsql.Tuple{
 							Message: map[string]interface{}{
 							Message: map[string]interface{}{
@@ -141,7 +141,7 @@ func TestCountWindow(t *testing.T) {
 			expWinCount: 1,
 			expWinCount: 1,
 			winTupleSets: []xsql.WindowTuples{
 			winTupleSets: []xsql.WindowTuples{
 				{
 				{
-					Content: []xsql.Row{
+					Content: []xsql.TupleRow{
 						&xsql.Tuple{
 						&xsql.Tuple{
 							Message: map[string]interface{}{
 							Message: map[string]interface{}{
 								"f3": "v3",
 								"f3": "v3",
@@ -182,7 +182,7 @@ func TestCountWindow(t *testing.T) {
 			expWinCount: 1,
 			expWinCount: 1,
 			winTupleSets: []xsql.WindowTuples{
 			winTupleSets: []xsql.WindowTuples{
 				{
 				{
-					Content: []xsql.Row{
+					Content: []xsql.TupleRow{
 						&xsql.Tuple{
 						&xsql.Tuple{
 							Message: map[string]interface{}{
 							Message: map[string]interface{}{
 								"f4": "v4",
 								"f4": "v4",

+ 3 - 3
internal/topo/operator/aggregate_operator.go

@@ -37,10 +37,10 @@ func (p *AggregateOp) Apply(ctx api.StreamContext, data interface{}, fv *xsql.Fu
 		switch input := data.(type) {
 		switch input := data.(type) {
 		case error:
 		case error:
 			return input
 			return input
-		case xsql.Collection:
+		case xsql.SingleCollection:
 			wr := input.GetWindowRange()
 			wr := input.GetWindowRange()
 			result := make(map[string]*xsql.GroupedTuples)
 			result := make(map[string]*xsql.GroupedTuples)
-			err := input.Range(func(i int, r xsql.Row) (bool, error) {
+			err := input.Range(func(i int, r xsql.TupleRow) (bool, error) {
 				var name string
 				var name string
 				ve := &xsql.ValuerEval{Valuer: xsql.MultiValuer(r, &xsql.WindowRangeValuer{WindowRange: wr}, fv)}
 				ve := &xsql.ValuerEval{Valuer: xsql.MultiValuer(r, &xsql.WindowRangeValuer{WindowRange: wr}, fv)}
 				for _, d := range p.Dimensions {
 				for _, d := range p.Dimensions {
@@ -52,7 +52,7 @@ func (p *AggregateOp) Apply(ctx api.StreamContext, data interface{}, fv *xsql.Fu
 					}
 					}
 				}
 				}
 				if ts, ok := result[name]; !ok {
 				if ts, ok := result[name]; !ok {
-					result[name] = &xsql.GroupedTuples{Content: []xsql.Row{r}, WindowRange: wr}
+					result[name] = &xsql.GroupedTuples{Content: []xsql.TupleRow{r}, WindowRange: wr}
 				} else {
 				} else {
 					ts.Content = append(ts.Content, r)
 					ts.Content = append(ts.Content, r)
 				}
 				}

+ 44 - 44
internal/topo/operator/aggregate_test.go

@@ -35,7 +35,7 @@ func TestAggregatePlan_Apply(t *testing.T) {
 		{
 		{
 			sql: "SELECT abc FROM src1 GROUP BY TUMBLINGWINDOW(ss, 10), f1",
 			sql: "SELECT abc FROM src1 GROUP BY TUMBLINGWINDOW(ss, 10), f1",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{
 					&xsql.Tuple{
 						Emitter: "src1",
 						Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
@@ -52,7 +52,7 @@ func TestAggregatePlan_Apply(t *testing.T) {
 			result: &xsql.GroupedTuplesSet{
 			result: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 1, "f1": "v1"},
 								Message: xsql.Message{"id1": 1, "f1": "v1"},
@@ -65,7 +65,7 @@ func TestAggregatePlan_Apply(t *testing.T) {
 						WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 						WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 2, "f1": "v2"},
 								Message: xsql.Message{"id1": 2, "f1": "v2"},
@@ -79,7 +79,7 @@ func TestAggregatePlan_Apply(t *testing.T) {
 		{
 		{
 			sql: "SELECT abc FROM src1 GROUP BY id1, TUMBLINGWINDOW(ss, 10), f1",
 			sql: "SELECT abc FROM src1 GROUP BY id1, TUMBLINGWINDOW(ss, 10), f1",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{
 					&xsql.Tuple{
 						Emitter: "src1",
 						Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
@@ -95,7 +95,7 @@ func TestAggregatePlan_Apply(t *testing.T) {
 			result: &xsql.GroupedTuplesSet{
 			result: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 1, "f1": "v1"},
 								Message: xsql.Message{"id1": 1, "f1": "v1"},
@@ -103,7 +103,7 @@ func TestAggregatePlan_Apply(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 2, "f1": "v2"},
 								Message: xsql.Message{"id1": 2, "f1": "v2"},
@@ -111,7 +111,7 @@ func TestAggregatePlan_Apply(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 3, "f1": "v1"},
 								Message: xsql.Message{"id1": 3, "f1": "v1"},
@@ -124,7 +124,7 @@ func TestAggregatePlan_Apply(t *testing.T) {
 		{
 		{
 			sql: "SELECT abc FROM src1 GROUP BY meta(topic), TUMBLINGWINDOW(ss, 10)",
 			sql: "SELECT abc FROM src1 GROUP BY meta(topic), TUMBLINGWINDOW(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{
 					&xsql.Tuple{
 						Emitter:  "src1",
 						Emitter:  "src1",
 						Message:  xsql.Message{"id1": 1, "f1": "v1"},
 						Message:  xsql.Message{"id1": 1, "f1": "v1"},
@@ -144,7 +144,7 @@ func TestAggregatePlan_Apply(t *testing.T) {
 			result: &xsql.GroupedTuplesSet{
 			result: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter:  "src1",
 								Emitter:  "src1",
 								Message:  xsql.Message{"id1": 1, "f1": "v1"},
 								Message:  xsql.Message{"id1": 1, "f1": "v1"},
@@ -158,7 +158,7 @@ func TestAggregatePlan_Apply(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter:  "src1",
 								Emitter:  "src1",
 								Message:  xsql.Message{"id1": 2, "f1": "v2"},
 								Message:  xsql.Message{"id1": 2, "f1": "v2"},
@@ -174,19 +174,19 @@ func TestAggregatePlan_Apply(t *testing.T) {
 			data: &xsql.JoinTuples{
 			data: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 						},
 						},
 					},
 					},
@@ -196,9 +196,9 @@ func TestAggregatePlan_Apply(t *testing.T) {
 			result: &xsql.GroupedTuplesSet{
 			result: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 								},
 								},
@@ -207,9 +207,9 @@ func TestAggregatePlan_Apply(t *testing.T) {
 						WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 						WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 								},
 								},
@@ -218,9 +218,9 @@ func TestAggregatePlan_Apply(t *testing.T) {
 						WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 						WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 								},
 								},
 							},
 							},
@@ -235,19 +235,19 @@ func TestAggregatePlan_Apply(t *testing.T) {
 			data: &xsql.JoinTuples{
 			data: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 						},
 						},
 					},
 					},
@@ -256,24 +256,24 @@ func TestAggregatePlan_Apply(t *testing.T) {
 			result: &xsql.GroupedTuplesSet{
 			result: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 								},
 								},
 							},
 							},
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 								},
 								},
@@ -288,19 +288,19 @@ func TestAggregatePlan_Apply(t *testing.T) {
 			data: &xsql.JoinTuples{
 			data: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1", "ts": cast.TimeFromUnixMilli(1568854515000)}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1", "ts": cast.TimeFromUnixMilli(1568854515000)}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2", "ts": cast.TimeFromUnixMilli(1568854573431)}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2", "ts": cast.TimeFromUnixMilli(1568854573431)}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1", "ts": cast.TimeFromUnixMilli(1568854515000)}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1", "ts": cast.TimeFromUnixMilli(1568854515000)}},
 						},
 						},
 					},
 					},
@@ -309,24 +309,24 @@ func TestAggregatePlan_Apply(t *testing.T) {
 			result: &xsql.GroupedTuplesSet{
 			result: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1", "ts": cast.TimeFromUnixMilli(1568854515000)}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1", "ts": cast.TimeFromUnixMilli(1568854515000)}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1", "ts": cast.TimeFromUnixMilli(1568854515000)}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1", "ts": cast.TimeFromUnixMilli(1568854515000)}},
 								},
 								},
 							},
 							},
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2", "ts": cast.TimeFromUnixMilli(1568854573431)}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2", "ts": cast.TimeFromUnixMilli(1568854573431)}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 								},
 								},
@@ -339,7 +339,7 @@ func TestAggregatePlan_Apply(t *testing.T) {
 		{
 		{
 			sql: "SELECT abc FROM src1 GROUP BY TUMBLINGWINDOW(ss, 10), CASE WHEN id1 > 1 THEN \"others\" ELSE \"one\" END",
 			sql: "SELECT abc FROM src1 GROUP BY TUMBLINGWINDOW(ss, 10), CASE WHEN id1 > 1 THEN \"others\" ELSE \"one\" END",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{
 					&xsql.Tuple{
 						Emitter: "src1",
 						Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
@@ -355,7 +355,7 @@ func TestAggregatePlan_Apply(t *testing.T) {
 			result: &xsql.GroupedTuplesSet{
 			result: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 1, "f1": "v1"},
 								Message: xsql.Message{"id1": 1, "f1": "v1"},
@@ -363,7 +363,7 @@ func TestAggregatePlan_Apply(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 2, "f1": "v2"},
 								Message: xsql.Message{"id1": 2, "f1": "v2"},
@@ -383,12 +383,12 @@ func TestAggregatePlan_Apply(t *testing.T) {
 			data: &xsql.JoinTuples{
 			data: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "B", Message: xsql.Message{"module": 1, "topic": "moduleB topic", "value": 1}},
 							&xsql.Tuple{Emitter: "B", Message: xsql.Message{"module": 1, "topic": "moduleB topic", "value": 1}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "C", Message: xsql.Message{"module": 1, "topic": "moduleC topic", "value": 100}},
 							&xsql.Tuple{Emitter: "C", Message: xsql.Message{"module": 1, "topic": "moduleC topic", "value": 100}},
 						},
 						},
 					},
 					},
@@ -397,14 +397,14 @@ func TestAggregatePlan_Apply(t *testing.T) {
 			result: &xsql.GroupedTuplesSet{
 			result: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "B", Message: xsql.Message{"module": 1, "topic": "moduleB topic", "value": 1}},
 									&xsql.Tuple{Emitter: "B", Message: xsql.Message{"module": 1, "topic": "moduleB topic", "value": 1}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "C", Message: xsql.Message{"module": 1, "topic": "moduleC topic", "value": 100}},
 									&xsql.Tuple{Emitter: "C", Message: xsql.Message{"module": 1, "topic": "moduleC topic", "value": 100}},
 								},
 								},
 							},
 							},
@@ -466,7 +466,7 @@ func TestAggregatePlanError(t *testing.T) {
 		{
 		{
 			sql: "SELECT abc FROM src1 GROUP BY TUMBLINGWINDOW(ss, 10), f1 * 2",
 			sql: "SELECT abc FROM src1 GROUP BY TUMBLINGWINDOW(ss, 10), f1 * 2",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{
 					&xsql.Tuple{
 						Emitter: "src1",
 						Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},

+ 3 - 3
internal/topo/operator/filter_operator.go

@@ -35,7 +35,7 @@ func (p *FilterOp) Apply(ctx api.StreamContext, data interface{}, fv *xsql.Funct
 	switch input := data.(type) {
 	switch input := data.(type) {
 	case error:
 	case error:
 		return input
 		return input
-	case xsql.Valuer:
+	case xsql.TupleRow:
 		ve := &xsql.ValuerEval{Valuer: xsql.MultiValuer(input, fv)}
 		ve := &xsql.ValuerEval{Valuer: xsql.MultiValuer(input, fv)}
 		result := ve.Eval(p.Condition)
 		result := ve.Eval(p.Condition)
 		switch r := result.(type) {
 		switch r := result.(type) {
@@ -50,9 +50,9 @@ func (p *FilterOp) Apply(ctx api.StreamContext, data interface{}, fv *xsql.Funct
 		default:
 		default:
 			return fmt.Errorf("run Where error: invalid condition that returns non-bool value %[1]T(%[1]v)", r)
 			return fmt.Errorf("run Where error: invalid condition that returns non-bool value %[1]T(%[1]v)", r)
 		}
 		}
-	case xsql.Collection:
+	case xsql.SingleCollection:
 		var sel []int
 		var sel []int
-		err := input.Range(func(i int, r xsql.Row) (bool, error) {
+		err := input.Range(func(i int, r xsql.TupleRow) (bool, error) {
 			ve := &xsql.ValuerEval{Valuer: xsql.MultiValuer(r, fv)}
 			ve := &xsql.ValuerEval{Valuer: xsql.MultiValuer(r, fv)}
 			result := ve.Eval(p.Condition)
 			result := ve.Eval(p.Condition)
 			switch val := result.(type) {
 			switch val := result.(type) {

+ 22 - 22
internal/topo/operator/filter_test.go

@@ -331,7 +331,7 @@ func TestFilterPlan_Apply(t *testing.T) {
 		{
 		{
 			sql: "SELECT abc FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10)",
 			sql: "SELECT abc FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{
 					&xsql.Tuple{
 						Emitter: "src1",
 						Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
@@ -346,7 +346,7 @@ func TestFilterPlan_Apply(t *testing.T) {
 				WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 				WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 			},
 			},
 			result: &xsql.WindowTuples{
 			result: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{
 					&xsql.Tuple{
 						Emitter: "src1",
 						Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
@@ -361,7 +361,7 @@ func TestFilterPlan_Apply(t *testing.T) {
 		{
 		{
 			sql: "SELECT abc FROM src1 WHERE f1 = \"v8\" GROUP BY TUMBLINGWINDOW(ss, 10)",
 			sql: "SELECT abc FROM src1 WHERE f1 = \"v8\" GROUP BY TUMBLINGWINDOW(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{
 					&xsql.Tuple{
 						Emitter: "src1",
 						Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
@@ -381,19 +381,19 @@ func TestFilterPlan_Apply(t *testing.T) {
 			data: &xsql.JoinTuples{
 			data: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 						},
 						},
 					},
 					},
@@ -403,13 +403,13 @@ func TestFilterPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 						},
 						},
 					},
 					},
@@ -422,19 +422,19 @@ func TestFilterPlan_Apply(t *testing.T) {
 			data: &xsql.JoinTuples{
 			data: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 						},
 						},
 					},
 					},
@@ -444,13 +444,13 @@ func TestFilterPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 						},
 						},
 					},
 					},
@@ -463,19 +463,19 @@ func TestFilterPlan_Apply(t *testing.T) {
 			data: &xsql.JoinTuples{
 			data: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 						},
 						},
 					},
 					},
@@ -645,7 +645,7 @@ func TestFilterPlanError(t *testing.T) {
 		{
 		{
 			sql: "SELECT abc FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10)",
 			sql: "SELECT abc FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{
 					&xsql.Tuple{
 						Emitter: "src1",
 						Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
@@ -668,7 +668,7 @@ func TestFilterPlanError(t *testing.T) {
 				},
 				},
 			},
 			},
 			result: &xsql.WindowTuples{
 			result: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{
 					&xsql.Tuple{
 						Emitter: "src1",
 						Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
@@ -688,7 +688,7 @@ func TestFilterPlanError(t *testing.T) {
 		{
 		{
 			sql: "SELECT abc FROM src1 WHERE f1 = \"v8\" GROUP BY TUMBLINGWINDOW(ss, 10)",
 			sql: "SELECT abc FROM src1 WHERE f1 = \"v8\" GROUP BY TUMBLINGWINDOW(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{
 					&xsql.Tuple{
 						Emitter: "src1",
 						Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
@@ -708,19 +708,19 @@ func TestFilterPlanError(t *testing.T) {
 			data: &xsql.JoinTuples{
 			data: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": 50}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": 50}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 						},
 						},
 					},
 					},

+ 3 - 3
internal/topo/operator/having_operator.go

@@ -33,9 +33,9 @@ func (p *HavingOp) Apply(ctx api.StreamContext, data interface{}, fv *xsql.Funct
 		return input
 		return input
 	case xsql.Collection:
 	case xsql.Collection:
 		var groups []int
 		var groups []int
-		err := input.GroupRange(func(i int, rows xsql.AggregateData, firstRow xsql.Row) (bool, error) {
-			afv.SetData(rows)
-			ve := &xsql.ValuerEval{Valuer: xsql.MultiAggregateValuer(rows, fv, firstRow, fv, afv, &xsql.WildcardValuer{Data: firstRow})}
+		err := input.GroupRange(func(i int, aggRow xsql.CollectionRow) (bool, error) {
+			afv.SetData(aggRow)
+			ve := &xsql.ValuerEval{Valuer: xsql.MultiAggregateValuer(aggRow, fv, aggRow, fv, afv, &xsql.WildcardValuer{Data: aggRow})}
 			result := ve.Eval(p.Condition)
 			result := ve.Eval(p.Condition)
 			switch val := result.(type) {
 			switch val := result.(type) {
 			case error:
 			case error:

+ 37 - 37
internal/topo/operator/having_test.go

@@ -34,7 +34,7 @@ func TestHavingPlan_Apply(t *testing.T) {
 		{
 		{
 			sql: `SELECT id1 FROM src1 HAVING avg(id1) > 1`,
 			sql: `SELECT id1 FROM src1 HAVING avg(id1) > 1`,
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -46,7 +46,7 @@ func TestHavingPlan_Apply(t *testing.T) {
 				WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 				WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 			},
 			},
 			result: &xsql.WindowTuples{
 			result: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -61,7 +61,7 @@ func TestHavingPlan_Apply(t *testing.T) {
 		{
 		{
 			sql: `SELECT id1 FROM src1 HAVING sum(id1) > 1`,
 			sql: `SELECT id1 FROM src1 HAVING sum(id1) > 1`,
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					},
 					},
@@ -73,14 +73,14 @@ func TestHavingPlan_Apply(t *testing.T) {
 		{
 		{
 			sql: `SELECT id1 FROM src1 HAVING sum(id1) = 1`,
 			sql: `SELECT id1 FROM src1 HAVING sum(id1) = 1`,
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					},
 					},
 				},
 				},
 			},
 			},
 			result: &xsql.WindowTuples{
 			result: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					},
 					},
@@ -91,7 +91,7 @@ func TestHavingPlan_Apply(t *testing.T) {
 		{
 		{
 			sql: `SELECT id1 FROM src1 HAVING max(id1) > 10`,
 			sql: `SELECT id1 FROM src1 HAVING max(id1) > 10`,
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					},
 					},
@@ -102,14 +102,14 @@ func TestHavingPlan_Apply(t *testing.T) {
 		{
 		{
 			sql: `SELECT id1 FROM src1 HAVING max(id1) = 1`,
 			sql: `SELECT id1 FROM src1 HAVING max(id1) = 1`,
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					},
 					},
 				},
 				},
 			},
 			},
 			result: &xsql.WindowTuples{
 			result: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					},
 					},
@@ -120,7 +120,7 @@ func TestHavingPlan_Apply(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 1, "f1": "v1"},
 								Message: xsql.Message{"id1": 1, "f1": "v1"},
@@ -133,7 +133,7 @@ func TestHavingPlan_Apply(t *testing.T) {
 						WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 						WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 2, "f1": "v2"},
 								Message: xsql.Message{"id1": 2, "f1": "v2"},
@@ -146,7 +146,7 @@ func TestHavingPlan_Apply(t *testing.T) {
 			result: &xsql.GroupedTuplesSet{
 			result: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 2, "f1": "v2"},
 								Message: xsql.Message{"id1": 2, "f1": "v2"},
@@ -161,15 +161,15 @@ func TestHavingPlan_Apply(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 								},
 								},
@@ -178,15 +178,15 @@ func TestHavingPlan_Apply(t *testing.T) {
 						WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 						WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "color": "w1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "color": "w1"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 14.6}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 14.6}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "color": "w1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "color": "w1"}},
 								},
 								},
@@ -199,15 +199,15 @@ func TestHavingPlan_Apply(t *testing.T) {
 			result: &xsql.GroupedTuplesSet{
 			result: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 								},
 								},
@@ -247,7 +247,7 @@ func TestHavingPlanAlias_Apply(t *testing.T) {
 		{
 		{
 			sql: `SELECT avg(id1) as a FROM src1 HAVING a > 1`,
 			sql: `SELECT avg(id1) as a FROM src1 HAVING a > 1`,
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1", "a": 8 / 3},
 						Message: xsql.Message{"id1": 1, "f1": "v1", "a": 8 / 3},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -258,7 +258,7 @@ func TestHavingPlanAlias_Apply(t *testing.T) {
 				},
 				},
 			},
 			},
 			result: &xsql.WindowTuples{
 			result: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1", "a": 8 / 3},
 						Message: xsql.Message{"id1": 1, "f1": "v1", "a": 8 / 3},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -272,7 +272,7 @@ func TestHavingPlanAlias_Apply(t *testing.T) {
 		{
 		{
 			sql: `SELECT sum(id1) as s FROM src1 HAVING s > 1`,
 			sql: `SELECT sum(id1) as s FROM src1 HAVING s > 1`,
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1", "s": 1},
 						Message: xsql.Message{"id1": 1, "f1": "v1", "s": 1},
 					},
 					},
@@ -284,7 +284,7 @@ func TestHavingPlanAlias_Apply(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 1, "f1": "v1", "c": 2},
 								Message: xsql.Message{"id1": 1, "f1": "v1", "c": 2},
@@ -296,7 +296,7 @@ func TestHavingPlanAlias_Apply(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 2, "f1": "v2", "c": 1},
 								Message: xsql.Message{"id1": 2, "f1": "v2", "c": 1},
@@ -308,7 +308,7 @@ func TestHavingPlanAlias_Apply(t *testing.T) {
 			result: &xsql.GroupedTuplesSet{
 			result: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 1, "f1": "v1", "c": 2},
 								Message: xsql.Message{"id1": 1, "f1": "v1", "c": 2},
@@ -326,15 +326,15 @@ func TestHavingPlanAlias_Apply(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33, "c": 2}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33, "c": 2}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 								},
 								},
@@ -342,9 +342,9 @@ func TestHavingPlanAlias_Apply(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03, "c": 1}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03, "c": 1}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "color": "w1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "color": "w1"}},
 								},
 								},
@@ -356,15 +356,15 @@ func TestHavingPlanAlias_Apply(t *testing.T) {
 			result: &xsql.GroupedTuplesSet{
 			result: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33, "c": 2}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33, "c": 2}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 								},
 								},
@@ -403,7 +403,7 @@ func TestHavingPlanError(t *testing.T) {
 		{
 		{
 			sql: `SELECT id1 FROM src1 HAVING avg(id1) > "str"`,
 			sql: `SELECT id1 FROM src1 HAVING avg(id1) > "str"`,
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -423,7 +423,7 @@ func TestHavingPlanError(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 1, "f1": 3},
 								Message: xsql.Message{"id1": 1, "f1": 3},
@@ -435,7 +435,7 @@ func TestHavingPlanError(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 2, "f1": "v2"},
 								Message: xsql.Message{"id1": 2, "f1": "v2"},

+ 66 - 66
internal/topo/operator/join_multi_test.go

@@ -34,7 +34,7 @@ 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",
 			sql: "SELECT id1 FROM src1 left join src2 on src1.id1 = src2.id2 left join src3 on src2.id2 = src3.id3",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -57,14 +57,14 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 1, "f3": "x1"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v3"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v3"}},
 						},
 						},
 					},
 					},
@@ -75,7 +75,7 @@ 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",
 			sql: "SELECT id1 FROM src1 left join src2 on src1.id1 = src2.id2 inner join src3 on src2.id2 = src3.id3",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -99,7 +99,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 1, "f3": "x1"}},
@@ -112,7 +112,7 @@ 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",
 			sql: "SELECT id1 FROM src1 left join src2 on src1.id1 = src2.id2 inner join src3 on src1.id1 = src3.id3",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -135,7 +135,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 5, "f1": "v5"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 5, "f1": "v5"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 5, "f3": "x5"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 5, "f3": "x5"}},
 						},
 						},
@@ -146,7 +146,7 @@ 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",
 			sql: "SELECT id1 FROM src1 left join src2 on src1.id1 = src2.id2 full join src3 on src1.id1 = src3.id3",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -167,20 +167,20 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w1"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 5, "f1": "v5"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 5, "f1": "v5"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 5, "f3": "x5"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 5, "f3": "x5"}},
 						},
 						},
 					},
 					},
 
 
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 2, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 2, "f3": "x1"}},
 						},
 						},
 					},
 					},
@@ -191,7 +191,7 @@ 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",
 			sql: "SELECT id1 FROM src1 left join src2 on src1.id1 = src2.id2 right join src3 on src2.id2 = src3.id3",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -213,7 +213,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w1"}},
@@ -221,7 +221,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 					},
 					},
 
 
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 5, "f3": "x5"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 5, "f3": "x5"}},
 						},
 						},
 					},
 					},
@@ -232,7 +232,7 @@ 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",
 			sql: "SELECT id1 FROM src1 left join src2 on src1.id1 = src2.id2 right join src3 on src2.id2 = src3.id3",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -255,7 +255,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w1"}},
@@ -263,7 +263,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 					},
 					},
 
 
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w3"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w3"}},
@@ -271,7 +271,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 					},
 					},
 
 
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v3"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v3"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w1"}},
@@ -279,7 +279,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 					},
 					},
 
 
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v3"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v3"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w3"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w3"}},
@@ -287,7 +287,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 					},
 					},
 
 
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 5, "f3": "x5"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 5, "f3": "x5"}},
 						},
 						},
 					},
 					},
@@ -298,7 +298,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 		{
 		{
 			sql: "SELECT id1 FROM src1 left join src2 on src1.id1 = src2.id2 cross join src3",
 			sql: "SELECT id1 FROM src1 left join src2 on src1.id1 = src2.id2 cross join src3",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -321,28 +321,28 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 2, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 2, "f3": "x1"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w1"}}, &xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 5, "f3": "x5"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 1, "f2": "w1"}}, &xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 5, "f3": "x5"}},
 						},
 						},
 					},
 					},
 
 
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 5, "f1": "v5"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 5, "f1": "v5"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 2, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 2, "f3": "x1"}},
 						},
 						},
 					},
 					},
 
 
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 5, "f1": "v5"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 5, "f1": "v5"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 5, "f3": "x5"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id3": 5, "f3": "x5"}},
 						},
 						},
@@ -352,7 +352,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 		}, {
 		}, {
 			sql: "SELECT id1 FROM src1 inner join src2 on src1.id = src2.id inner join src3 on src1.id = src3.id",
 			sql: "SELECT id1 FROM src1 inner join src2 on src1.id = src2.id inner join src3 on src1.id = src3.id",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -380,14 +380,14 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x1"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x3"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x3"}},
@@ -400,7 +400,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 		{ //9
 		{ //9
 			sql: "SELECT id1 FROM src1 inner join src2 on src1.id = src2.id right join src3 on src1.id = src3.id",
 			sql: "SELECT id1 FROM src1 inner join src2 on src1.id = src2.id right join src3 on src1.id = src3.id",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -430,21 +430,21 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x3"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x3"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 5, "f3": "x5"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 5, "f3": "x5"}},
 						},
 						},
 					},
 					},
@@ -455,7 +455,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 		{ //10
 		{ //10
 			sql: "SELECT id1 FROM src1 inner join src2 on src1.id * 10 = src2.id right join src3 on src1.id = src3.id",
 			sql: "SELECT id1 FROM src1 inner join src2 on src1.id * 10 = src2.id right join src3 on src1.id = src3.id",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -484,17 +484,17 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x1"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x3"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x3"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 5, "f3": "x5"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 5, "f3": "x5"}},
 						},
 						},
 					},
 					},
@@ -505,7 +505,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 		{ //11
 		{ //11
 			sql: "SELECT id1 FROM src1 full join src2 on src1.id = src2.id inner join src3 on src1.id = src3.id",
 			sql: "SELECT id1 FROM src1 full join src2 on src1.id = src2.id inner join src3 on src1.id = src3.id",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 					},
 					},
@@ -538,14 +538,14 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x1"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x3"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x3"}},
@@ -558,7 +558,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 		{ //12
 		{ //12
 			sql: "SELECT id1 FROM src1 full join src2 on src1.id = src2.id right join src3 on src1.id = src3.id",
 			sql: "SELECT id1 FROM src1 full join src2 on src1.id = src2.id right join src3 on src1.id = src3.id",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 					},
 					},
@@ -591,21 +591,21 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x3"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x3"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 5, "f3": "x5"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 5, "f3": "x5"}},
 						},
 						},
 					},
 					},
@@ -616,7 +616,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 		{ //13
 		{ //13
 			sql: "SELECT id1 FROM src1 full join src2 on src1.id = src2.id full join src3 on src1.id = src3.id",
 			sql: "SELECT id1 FROM src1 full join src2 on src1.id = src2.id full join src3 on src1.id = src3.id",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 					},
 					},
@@ -633,17 +633,17 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "f2": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "f2": "w2"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 5, "f3": "x5"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 5, "f3": "x5"}},
 						},
 						},
 					},
 					},
@@ -654,7 +654,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 		{ //14
 		{ //14
 			sql: "SELECT id1 FROM src1 right join src2 on src1.id = src2.id right join src3 on src1.id = src3.id",
 			sql: "SELECT id1 FROM src1 right join src2 on src1.id = src2.id right join src3 on src1.id = src3.id",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 					},
 					},
@@ -687,21 +687,21 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x3"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x3"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 5, "f3": "x5"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 5, "f3": "x5"}},
 						},
 						},
 					},
 					},
@@ -712,7 +712,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 		{ //15
 		{ //15
 			sql: "SELECT id1 FROM src1 right join src2 on src1.id = src2.id right join src3 on src1.id = src3.id",
 			sql: "SELECT id1 FROM src1 right join src2 on src1.id = src2.id right join src3 on src1.id = src3.id",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 					},
 					},
@@ -740,7 +740,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 		{ //16
 		{ //16
 			sql: "SELECT id1 FROM src1 right join src2 on src1.id = src2.id right join src3 on src1.id = src3.id right join src4 on src4.id = src3.id ",
 			sql: "SELECT id1 FROM src1 right join src2 on src1.id = src2.id right join src3 on src1.id = src3.id right join src4 on src4.id = src3.id ",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 					},
 					},
@@ -779,7 +779,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src4", Message: xsql.Message{"id": 1, "f4": "x4"}},
 							&xsql.Tuple{Emitter: "src4", Message: xsql.Message{"id": 1, "f4": "x4"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
@@ -787,7 +787,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src4", Message: xsql.Message{"id": 2, "f4": "x4"}},
 							&xsql.Tuple{Emitter: "src4", Message: xsql.Message{"id": 2, "f4": "x4"}},
 						},
 						},
 					},
 					},
@@ -798,7 +798,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 		{ //17
 		{ //17
 			sql: "SELECT id1 FROM src1 right join src2 on src1.id = src2.id right join src3 on src1.id = src3.id cross join src4",
 			sql: "SELECT id1 FROM src1 right join src2 on src1.id = src2.id right join src3 on src1.id = src3.id cross join src4",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 					},
 					},
@@ -833,7 +833,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 		{ //18
 		{ //18
 			sql: "SELECT id1 FROM src1 cross join src2 left join src3 on src1.id = src3.id",
 			sql: "SELECT id1 FROM src1 cross join src2 left join src3 on src1.id = src3.id",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src2",
 					&xsql.Tuple{Emitter: "src2",
 						Message: xsql.Message{"id": 1, "f2": "w1"},
 						Message: xsql.Message{"id": 1, "f2": "w1"},
 					},
 					},
@@ -858,7 +858,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 		{ //19
 		{ //19
 			sql: "SELECT id1 FROM src1 full join src2 on src1.id = src2.id full join src3 on src1.id = src3.id",
 			sql: "SELECT id1 FROM src1 full join src2 on src1.id = src2.id full join src3 on src1.id = src3.id",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 					},
 					},
@@ -875,7 +875,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x1"}},
@@ -887,7 +887,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 		{ //20
 		{ //20
 			sql: "SELECT id1 FROM src1 full join src2 on src1.id = src2.id full join src3 on src1.id = src3.id",
 			sql: "SELECT id1 FROM src1 full join src2 on src1.id = src2.id full join src3 on src1.id = src3.id",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src2",
 					&xsql.Tuple{Emitter: "src2",
 						Message: xsql.Message{"id": 1, "f2": "w1"},
 						Message: xsql.Message{"id": 1, "f2": "w1"},
 					},
 					},
@@ -900,12 +900,12 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x1"}},
 						},
 						},
 					},
 					},
@@ -915,7 +915,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 		{ //21
 		{ //21
 			sql: "SELECT id1 FROM src1 full join src2 on src1.id = src2.id full join src3 on src1.id = src3.id",
 			sql: "SELECT id1 FROM src1 full join src2 on src1.id = src2.id full join src3 on src1.id = src3.id",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 					},
 					},
@@ -928,7 +928,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "f2": "w1"}},
 						},
 						},
@@ -940,7 +940,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 		{ //22
 		{ //22
 			sql: "SELECT id1 FROM src1 full join src2 on src1.id = src2.id full join src3 on src1.id = src3.id",
 			sql: "SELECT id1 FROM src1 full join src2 on src1.id = src2.id full join src3 on src1.id = src3.id",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 						Message: xsql.Message{"id": 1, "f1": "v1"},
 					},
 					},
@@ -953,7 +953,7 @@ func TestMultiJoinPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x1"}},
 							&xsql.Tuple{Emitter: "src3", Message: xsql.Message{"id": 1, "f3": "x1"}},
 						},
 						},

+ 2 - 2
internal/topo/operator/join_operator.go

@@ -126,7 +126,7 @@ func (jp *JoinOp) evalSet(input xsql.MergedCollection, join ast.Join, fv *xsql.F
 		}
 		}
 	}
 	}
 
 
-	var lefts, rights []xsql.Row
+	var lefts, rights []xsql.TupleRow
 
 
 	lefts = input.GetBySrc(leftStream)
 	lefts = input.GetBySrc(leftStream)
 	rights = input.GetBySrc(rightStream)
 	rights = input.GetBySrc(rightStream)
@@ -218,7 +218,7 @@ func (jp *JoinOp) evalSetWithRightJoin(input xsql.MergedCollection, join ast.Joi
 	}
 	}
 	leftStream := streams[0]
 	leftStream := streams[0]
 	rightStream := streams[1]
 	rightStream := streams[1]
-	var lefts, rights []xsql.Row
+	var lefts, rights []xsql.TupleRow
 
 
 	lefts = input.GetBySrc(leftStream)
 	lefts = input.GetBySrc(leftStream)
 	rights = input.GetBySrc(rightStream)
 	rights = input.GetBySrc(rightStream)

文件差异内容过多而无法显示
+ 151 - 151
internal/topo/operator/join_test.go


+ 1 - 1
internal/topo/operator/misc_func_test.go

@@ -274,7 +274,7 @@ func TestMqttFunc_Apply2(t *testing.T) {
 			data: &xsql.JoinTuples{
 			data: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": "1", "f1": "v1"}, Metadata: xsql.Metadata{"topic": "devices/type1/device001"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": "1", "f1": "v1"}, Metadata: xsql.Metadata{"topic": "devices/type1/device001"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": "1", "f2": "w1"}, Metadata: xsql.Metadata{"topic": "devices/type2/device001"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": "1", "f2": "w1"}, Metadata: xsql.Metadata{"topic": "devices/type2/device001"}},
 						},
 						},

+ 1 - 1
internal/topo/operator/order_operator.go

@@ -36,7 +36,7 @@ func (p *OrderOp) Apply(ctx api.StreamContext, data interface{}, fv *xsql.Functi
 	switch input := data.(type) {
 	switch input := data.(type) {
 	case error:
 	case error:
 		return input
 		return input
-	case xsql.Valuer:
+	case xsql.TupleRow:
 		return input
 		return input
 	case xsql.SortingData:
 	case xsql.SortingData:
 		if err := sorter.Sort(input); err != nil {
 		if err := sorter.Sort(input); err != nil {

+ 43 - 43
internal/topo/operator/order_test.go

@@ -68,7 +68,7 @@ func TestOrderPlan_Apply(t *testing.T) {
 		{
 		{
 			sql: "SELECT id1 FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10) ORDER BY id1 DESC",
 			sql: "SELECT id1 FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10) ORDER BY id1 DESC",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -80,7 +80,7 @@ func TestOrderPlan_Apply(t *testing.T) {
 			},
 			},
 
 
 			result: &xsql.WindowTuples{
 			result: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 3, "f1": "v1"},
 						Message: xsql.Message{"id1": 3, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -95,7 +95,7 @@ func TestOrderPlan_Apply(t *testing.T) {
 		{
 		{
 			sql: "SELECT id1 FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10) ORDER BY id1 DESC",
 			sql: "SELECT id1 FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10) ORDER BY id1 DESC",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -107,7 +107,7 @@ func TestOrderPlan_Apply(t *testing.T) {
 				WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 				WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 			},
 			},
 			result: &xsql.WindowTuples{
 			result: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 3, "f1": "v1"},
 						Message: xsql.Message{"id1": 3, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -122,7 +122,7 @@ func TestOrderPlan_Apply(t *testing.T) {
 		{
 		{
 			sql: "SELECT id1 FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10) ORDER BY id1 DESC",
 			sql: "SELECT id1 FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10) ORDER BY id1 DESC",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -137,7 +137,7 @@ func TestOrderPlan_Apply(t *testing.T) {
 		{
 		{
 			sql: "SELECT * FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10) ORDER BY f1, id1 DESC",
 			sql: "SELECT * FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10) ORDER BY f1, id1 DESC",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -148,7 +148,7 @@ func TestOrderPlan_Apply(t *testing.T) {
 				},
 				},
 			},
 			},
 			result: &xsql.WindowTuples{
 			result: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 3, "f1": "v1"},
 						Message: xsql.Message{"id1": 3, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -162,7 +162,7 @@ func TestOrderPlan_Apply(t *testing.T) {
 		{
 		{
 			sql: "SELECT * FROM src1 GROUP BY TUMBLINGWINDOW(ss, 10) ORDER BY ts DESC",
 			sql: "SELECT * FROM src1 GROUP BY TUMBLINGWINDOW(ss, 10) ORDER BY ts DESC",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1", "ts": cast.TimeFromUnixMilli(1568854515000)},
 						Message: xsql.Message{"id1": 1, "f1": "v1", "ts": cast.TimeFromUnixMilli(1568854515000)},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -173,7 +173,7 @@ func TestOrderPlan_Apply(t *testing.T) {
 				},
 				},
 			},
 			},
 			result: &xsql.WindowTuples{
 			result: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 3, "f1": "v1", "ts": cast.TimeFromUnixMilli(1568854535000)},
 						Message: xsql.Message{"id1": 3, "f1": "v1", "ts": cast.TimeFromUnixMilli(1568854535000)},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -190,19 +190,19 @@ func TestOrderPlan_Apply(t *testing.T) {
 			data: &xsql.JoinTuples{
 			data: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 						},
 						},
 					},
 					},
@@ -211,18 +211,18 @@ func TestOrderPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 						},
 						},
@@ -235,19 +235,19 @@ func TestOrderPlan_Apply(t *testing.T) {
 			data: &xsql.JoinTuples{
 			data: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 						},
 						},
 					},
 					},
@@ -256,19 +256,19 @@ func TestOrderPlan_Apply(t *testing.T) {
 			result: &xsql.JoinTuples{
 			result: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 						},
 						},
 					},
 					},
@@ -281,7 +281,7 @@ func TestOrderPlan_Apply(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "tbl",
 								Emitter: "tbl",
 								Message: xsql.Message{
 								Message: xsql.Message{
@@ -296,7 +296,7 @@ func TestOrderPlan_Apply(t *testing.T) {
 			result: &xsql.GroupedTuplesSet{
 			result: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "tbl",
 								Emitter: "tbl",
 								Message: xsql.Message{
 								Message: xsql.Message{
@@ -314,7 +314,7 @@ func TestOrderPlan_Apply(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 1, "f1": "v1"},
 								Message: xsql.Message{"id1": 1, "f1": "v1"},
@@ -326,7 +326,7 @@ func TestOrderPlan_Apply(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 2, "f1": "v2"},
 								Message: xsql.Message{"id1": 2, "f1": "v2"},
@@ -338,7 +338,7 @@ func TestOrderPlan_Apply(t *testing.T) {
 			result: &xsql.GroupedTuplesSet{
 			result: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 2, "f1": "v2"},
 								Message: xsql.Message{"id1": 2, "f1": "v2"},
@@ -346,7 +346,7 @@ func TestOrderPlan_Apply(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 1, "f1": "v1"},
 								Message: xsql.Message{"id1": 1, "f1": "v1"},
@@ -365,7 +365,7 @@ func TestOrderPlan_Apply(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 1, "f1": "v1", "c": 2},
 								Message: xsql.Message{"id1": 1, "f1": "v1", "c": 2},
@@ -377,7 +377,7 @@ func TestOrderPlan_Apply(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 2, "f1": "v2", "c": 1},
 								Message: xsql.Message{"id1": 2, "f1": "v2", "c": 1},
@@ -389,7 +389,7 @@ func TestOrderPlan_Apply(t *testing.T) {
 			result: &xsql.GroupedTuplesSet{
 			result: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 2, "f1": "v2", "c": 1},
 								Message: xsql.Message{"id1": 2, "f1": "v2", "c": 1},
@@ -397,7 +397,7 @@ func TestOrderPlan_Apply(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{
 							&xsql.Tuple{
 								Emitter: "src1",
 								Emitter: "src1",
 								Message: xsql.Message{"id1": 1, "f1": "v1", "c": 2},
 								Message: xsql.Message{"id1": 1, "f1": "v1", "c": 2},
@@ -416,9 +416,9 @@ func TestOrderPlan_Apply(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 								},
 								},
@@ -427,9 +427,9 @@ func TestOrderPlan_Apply(t *testing.T) {
 						WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 						WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 								},
 								},
@@ -438,9 +438,9 @@ func TestOrderPlan_Apply(t *testing.T) {
 						WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 						WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 								},
 								},
 							},
 							},
@@ -452,9 +452,9 @@ func TestOrderPlan_Apply(t *testing.T) {
 			result: &xsql.GroupedTuplesSet{
 			result: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 								},
 								},
@@ -463,9 +463,9 @@ func TestOrderPlan_Apply(t *testing.T) {
 						WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 						WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 								},
 								},
@@ -474,9 +474,9 @@ func TestOrderPlan_Apply(t *testing.T) {
 						WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 						WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 								},
 								},
 							},
 							},

+ 19 - 9
internal/topo/operator/project_operator.go

@@ -49,11 +49,11 @@ func (pp *ProjectOp) Apply(ctx api.StreamContext, data interface{}, fv *xsql.Fun
 			}
 			}
 			results = append(results, r)
 			results = append(results, r)
 		}
 		}
-	case xsql.Collection:
+	case xsql.SingleCollection:
 		var err error
 		var err error
 		if pp.IsAggregate {
 		if pp.IsAggregate {
-			err = input.GroupRange(func(_ int, agg xsql.AggregateData, row xsql.Row) (bool, error) {
-				ve := pp.getVE(row, agg, input.GetWindowRange(), fv, afv)
+			err = input.GroupRange(func(_ int, aggRow xsql.CollectionRow) (bool, error) {
+				ve := pp.getVE(aggRow, aggRow, input.GetWindowRange(), fv, afv)
 				if r, err := project(pp.Fields, ve); err != nil {
 				if r, err := project(pp.Fields, ve); err != nil {
 					return false, fmt.Errorf("run Select error: %s", err)
 					return false, fmt.Errorf("run Select error: %s", err)
 				} else {
 				} else {
@@ -62,13 +62,10 @@ func (pp *ProjectOp) Apply(ctx api.StreamContext, data interface{}, fv *xsql.Fun
 				return true, nil
 				return true, nil
 			})
 			})
 		} else {
 		} else {
-			err = input.Range(func(_ int, row xsql.Row) (bool, error) {
-				aggData, ok := row.(xsql.AggregateData)
+			err = input.Range(func(_ int, row xsql.TupleRow) (bool, error) {
+				aggData, ok := input.(xsql.AggregateData)
 				if !ok {
 				if !ok {
-					aggData, ok = input.(xsql.AggregateData)
-					if !ok {
-						return false, fmt.Errorf("unexpected type, cannot find aggregate data")
-					}
+					return false, fmt.Errorf("unexpected type, cannot find aggregate data")
 				}
 				}
 				ve := pp.getVE(row, aggData, input.GetWindowRange(), fv, afv)
 				ve := pp.getVE(row, aggData, input.GetWindowRange(), fv, afv)
 				if r, err := project(pp.Fields, ve); err != nil {
 				if r, err := project(pp.Fields, ve); err != nil {
@@ -82,6 +79,19 @@ func (pp *ProjectOp) Apply(ctx api.StreamContext, data interface{}, fv *xsql.Fun
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
+	case xsql.GroupedCollection: // The order is important, because single collection usually is also a groupedCollection
+		err := input.GroupRange(func(_ int, aggRow xsql.CollectionRow) (bool, error) {
+			ve := pp.getVE(aggRow, aggRow, input.GetWindowRange(), fv, afv)
+			if r, err := project(pp.Fields, ve); err != nil {
+				return false, fmt.Errorf("run Select error: %s", err)
+			} else {
+				results = append(results, r)
+			}
+			return true, nil
+		})
+		if err != nil {
+			return err
+		}
 	default:
 	default:
 		return fmt.Errorf("run Select error: invalid input %[1]T(%[1]v)", input)
 		return fmt.Errorf("run Select error: invalid input %[1]T(%[1]v)", input)
 	}
 	}

+ 139 - 139
internal/topo/operator/project_test.go

@@ -600,7 +600,7 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 		{
 		{
 			sql: "SELECT id1 FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10)",
 			sql: "SELECT id1 FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -622,7 +622,7 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 		{
 		{
 			sql: "SELECT id1 FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10)",
 			sql: "SELECT id1 FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -643,7 +643,7 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 		{
 		{
 			sql: "SELECT * FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10)",
 			sql: "SELECT * FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -668,7 +668,7 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 		{
 		{
 			sql: "SELECT * FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10)",
 			sql: "SELECT * FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -693,7 +693,7 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 		{
 		{
 			sql: "SELECT src1.* FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10)",
 			sql: "SELECT src1.* FROM src1 WHERE f1 = \"v1\" GROUP BY TUMBLINGWINDOW(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 						Message: xsql.Message{"id1": 1, "f1": "v1"},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -720,19 +720,19 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 			data: &xsql.JoinTuples{
 			data: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 						},
 						},
 					},
 					},
@@ -752,19 +752,19 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 			data: &xsql.JoinTuples{
 			data: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id2": 3, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id2": 3, "f1": "v1"}},
 						},
 						},
 					},
 					},
@@ -782,7 +782,7 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "tbl",
 							&xsql.Tuple{Emitter: "tbl",
 								Message: xsql.Message{
 								Message: xsql.Message{
 									"abc": int64(6),
 									"abc": int64(6),
@@ -803,7 +803,7 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "tbl",
 							&xsql.Tuple{Emitter: "tbl",
 								Message: xsql.Message{
 								Message: xsql.Message{
 									"def": "hello",
 									"def": "hello",
@@ -821,7 +821,7 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1",
 							&xsql.Tuple{Emitter: "src1",
 								Message: xsql.Message{"id1": 1, "f1": "v1"},
 								Message: xsql.Message{"id1": 1, "f1": "v1"},
 							},
 							},
@@ -831,7 +831,7 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1",
 							&xsql.Tuple{Emitter: "src1",
 								Message: xsql.Message{"id1": 2, "f1": "v2"},
 								Message: xsql.Message{"id1": 2, "f1": "v2"},
 							},
 							},
@@ -851,7 +851,7 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1",
 							&xsql.Tuple{Emitter: "src1",
 								Message: xsql.Message{"id1": 1, "f1": "v1"},
 								Message: xsql.Message{"id1": 1, "f1": "v1"},
 							},
 							},
@@ -861,7 +861,7 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1",
 							&xsql.Tuple{Emitter: "src1",
 								Message: xsql.Message{"id2": 2, "f1": "v2"},
 								Message: xsql.Message{"id2": 2, "f1": "v2"},
 							},
 							},
@@ -879,9 +879,9 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 								},
 								},
@@ -889,9 +889,9 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 								},
 								},
@@ -899,9 +899,9 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 								},
 								},
 							},
 							},
@@ -921,19 +921,19 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 			data: &xsql.JoinTuples{
 			data: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 						},
 						},
 					},
 					},
@@ -958,19 +958,19 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 			data: &xsql.JoinTuples{
 			data: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 1, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "f2": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "f2": "w2"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 2, "f1": "v2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "f2": "w3"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "f2": "w3"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 3, "f1": "v1"}},
 							&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id": 3, "f1": "v1"}},
 						},
 						},
 					},
 					},
@@ -995,7 +995,7 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1",
 							&xsql.Tuple{Emitter: "src1",
 								Message: xsql.Message{"id1": 1, "f1": "v1"},
 								Message: xsql.Message{"id1": 1, "f1": "v1"},
 							},
 							},
@@ -1005,7 +1005,7 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "src1",
 							&xsql.Tuple{Emitter: "src1",
 								Message: xsql.Message{"id1": 2, "f1": "v2"},
 								Message: xsql.Message{"id1": 2, "f1": "v2"},
 							},
 							},
@@ -1027,9 +1027,9 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 								},
 								},
@@ -1037,9 +1037,9 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 								},
 								},
@@ -1047,9 +1047,9 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 								},
 								},
 							},
 							},
@@ -1076,9 +1076,9 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 1, "f1": "v1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 2, "f2": "w2"}},
 								},
 								},
@@ -1086,9 +1086,9 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 2, "f1": "v2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id2": 4, "f2": "w3"}},
 								},
 								},
@@ -1096,9 +1096,9 @@ func TestProjectPlan_MultiInput(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 									&xsql.Tuple{Emitter: "src1", Message: xsql.Message{"id1": 3, "f1": "v1"}},
 								},
 								},
 							},
 							},
@@ -1159,7 +1159,7 @@ func TestProjectPlan_Funcs(t *testing.T) {
 		{
 		{
 			sql: "SELECT round(a) as r FROM test GROUP BY TumblingWindow(ss, 10)",
 			sql: "SELECT round(a) as r FROM test GROUP BY TumblingWindow(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"a": 53.1},
 						Message: xsql.Message{"a": 53.1},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -1182,7 +1182,7 @@ func TestProjectPlan_Funcs(t *testing.T) {
 		{
 		{
 			sql: "SELECT round(a) as r FROM test GROUP BY TumblingWindow(ss, 10)",
 			sql: "SELECT round(a) as r FROM test GROUP BY TumblingWindow(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"a": 53.1},
 						Message: xsql.Message{"a": 53.1},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -1207,19 +1207,19 @@ func TestProjectPlan_Funcs(t *testing.T) {
 			data: &xsql.JoinTuples{
 			data: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 65.55}},
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 65.55}},
 							&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 1, "b": 12}},
 							&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 1, "b": 12}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 73.499}},
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 73.499}},
 							&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 2, "b": 34}},
 							&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 2, "b": 34}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 3, "a": 88.88}},
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 3, "a": 88.88}},
 							&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 3, "b": 6}},
 							&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 3, "b": 6}},
 						},
 						},
@@ -1240,19 +1240,19 @@ func TestProjectPlan_Funcs(t *testing.T) {
 			data: &xsql.JoinTuples{
 			data: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 65.55}},
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 65.55}},
 							&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 1, "b": 12}},
 							&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 1, "b": 12}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 73.499}},
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 73.499}},
 							&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 2, "b": 34}},
 							&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 2, "b": 34}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 3, "a": 88.88}},
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 3, "a": 88.88}},
 							&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 3, "b": 6}},
 							&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 3, "b": 6}},
 						},
 						},
@@ -1286,19 +1286,19 @@ func TestProjectPlan_Funcs(t *testing.T) {
 			data: &xsql.JoinTuples{
 			data: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 65.55}, Metadata: xsql.Metadata{"device": "devicea"}},
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 65.55}, Metadata: xsql.Metadata{"device": "devicea"}},
 							&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 1, "b": 12}},
 							&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 1, "b": 12}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 73.499}, Metadata: xsql.Metadata{"device": "deviceb"}},
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 73.499}, Metadata: xsql.Metadata{"device": "deviceb"}},
 							&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 2, "b": 34}},
 							&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 2, "b": 34}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 3, "a": 88.88}, Metadata: xsql.Metadata{"device": "devicec"}},
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 3, "a": 88.88}, Metadata: xsql.Metadata{"device": "devicec"}},
 							&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 3, "b": 6}},
 							&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 3, "b": 6}},
 						},
 						},
@@ -1343,15 +1343,15 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33, "c": 2, "r": 122}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33, "c": 2, "r": 122}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 								},
 								},
@@ -1360,15 +1360,15 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 						WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 						WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03, "c": 2, "r": 89}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03, "c": 2, "r": 89}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "color": "w1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "color": "w1"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 14.6}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 14.6}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "color": "w1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "color": "w1"}},
 								},
 								},
@@ -1396,15 +1396,15 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33, "c": 2, "r": 122}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33, "c": 2, "r": 122}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 								},
 								},
@@ -1412,15 +1412,15 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03, "c": 2, "r": 89}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03, "c": 2, "r": 89}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "color": "w1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "color": "w1"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 14.6}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 14.6}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "color": "w1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "color": "w1"}},
 								},
 								},
@@ -1449,27 +1449,27 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 68.54}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 68.54}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 98.31}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 98.31}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "color": "w2"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.54}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.54}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 								},
 								},
@@ -1477,15 +1477,15 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "color": "w1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "color": "w1"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 14.6}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 14.6}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "color": "w1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "color": "w1"}},
 								},
 								},
@@ -1506,21 +1506,21 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 68.55}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 68.55}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 								},
 								},
@@ -1528,15 +1528,15 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "color": "w1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "color": "w1"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 14.6}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 14.6}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "color": "w1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "color": "w1"}},
 								},
 								},
@@ -1557,19 +1557,19 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 			data: &xsql.JoinTuples{
 			data: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33}},
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 68.55}},
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 68.55}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 						},
 						},
@@ -1590,19 +1590,19 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 			data: &xsql.JoinTuples{
 			data: &xsql.JoinTuples{
 				Content: []*xsql.JoinTuple{
 				Content: []*xsql.JoinTuple{
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1}},
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 68.55}},
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 68.55}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 						},
 						},
 					},
 					},
 					{
 					{
-						Tuples: []xsql.Row{
+						Tuples: []xsql.TupleRow{
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 							&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 							&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 						},
 						},
@@ -1623,7 +1623,7 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 		{
 		{
 			sql: "SELECT sum(a), window_start() as ws, window_end() FROM test GROUP BY TumblingWindow(ss, 10)",
 			sql: "SELECT sum(a), window_start() as ws, window_end() FROM test GROUP BY TumblingWindow(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"a": 53},
 						Message: xsql.Message{"a": 53},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -1644,7 +1644,7 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 		{
 		{
 			sql: "SELECT sum(a) as s FROM test GROUP BY TumblingWindow(ss, 10)",
 			sql: "SELECT sum(a) as s FROM test GROUP BY TumblingWindow(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"a": 53, "s": 123203},
 						Message: xsql.Message{"a": 53, "s": 123203},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -1663,7 +1663,7 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 		{
 		{
 			sql: "SELECT sum(a) FROM test GROUP BY TumblingWindow(ss, 10)",
 			sql: "SELECT sum(a) FROM test GROUP BY TumblingWindow(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"a": 53},
 						Message: xsql.Message{"a": 53},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -1681,7 +1681,7 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 		{
 		{
 			sql: "SELECT count(*) as all, count(a) as c, avg(a) as a, sum(a) as s, min(a) as min, max(a) as max  FROM test GROUP BY TumblingWindow(ss, 10)",
 			sql: "SELECT count(*) as all, count(a) as c, avg(a) as a, sum(a) as s, min(a) as min, max(a) as max  FROM test GROUP BY TumblingWindow(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"a": 53},
 						Message: xsql.Message{"a": 53},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -1706,15 +1706,15 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33}},
 									&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 1, "color": "w2"}, Metadata: xsql.Metadata{"device": "devicea"}},
 									&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 1, "color": "w2"}, Metadata: xsql.Metadata{"device": "devicea"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 									&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 5, "color": "w2"}, Metadata: xsql.Metadata{"device": "deviceb"}},
 									&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 5, "color": "w2"}, Metadata: xsql.Metadata{"device": "deviceb"}},
 								},
 								},
@@ -1722,15 +1722,15 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03}},
 									&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 2, "color": "w1"}, Metadata: xsql.Metadata{"device": "devicec"}},
 									&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 2, "color": "w1"}, Metadata: xsql.Metadata{"device": "devicec"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 14.6}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 14.6}},
 									&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 4, "color": "w1"}, Metadata: xsql.Metadata{"device": "deviced"}},
 									&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 4, "color": "w1"}, Metadata: xsql.Metadata{"device": "deviced"}},
 								},
 								},
@@ -1753,15 +1753,15 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33, "c": 2, "d": "devicea"}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33, "c": 2, "d": "devicea"}},
 									&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 1, "color": "w2"}, Metadata: xsql.Metadata{"device": "devicea"}},
 									&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 1, "color": "w2"}, Metadata: xsql.Metadata{"device": "devicea"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 									&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 5, "color": "w2"}, Metadata: xsql.Metadata{"device": "deviceb"}},
 									&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 5, "color": "w2"}, Metadata: xsql.Metadata{"device": "deviceb"}},
 								},
 								},
@@ -1769,15 +1769,15 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03, "c": 2, "d": "devicec"}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03, "c": 2, "d": "devicec"}},
 									&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 2, "color": "w1"}, Metadata: xsql.Metadata{"device": "devicec"}},
 									&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 2, "color": "w1"}, Metadata: xsql.Metadata{"device": "devicec"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 14.6}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 14.6}},
 									&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 4, "color": "w1"}, Metadata: xsql.Metadata{"device": "deviced"}},
 									&xsql.Tuple{Emitter: "test1", Message: xsql.Message{"id": 4, "color": "w1"}, Metadata: xsql.Metadata{"device": "deviced"}},
 								},
 								},
@@ -1800,15 +1800,15 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33, "c": 2, "r": 122}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33, "c": 2, "r": 122}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 								},
 								},
@@ -1817,15 +1817,15 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 						WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 						WindowRange: xsql.NewWindowRange(1541152486013, 1541152487013),
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03, "c": 2, "r": 89}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03, "c": 2, "r": 89}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "color": "w1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "color": "w1"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 14.6}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 14.6}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "color": "w1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "color": "w1"}},
 								},
 								},
@@ -1855,15 +1855,15 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33, "c": 2, "r": 122}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33, "c": 2, "r": 122}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 								},
 								},
@@ -1871,15 +1871,15 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03, "c": 2, "r": 89}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03, "c": 2, "r": 89}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "color": "w1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "color": "w1"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 14.6}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 14.6}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "color": "w1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "color": "w1"}},
 								},
 								},
@@ -1896,7 +1896,7 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 		{
 		{
 			sql: "SELECT collect(*)[1] as c1 FROM test GROUP BY TumblingWindow(ss, 10)",
 			sql: "SELECT collect(*)[1] as c1 FROM test GROUP BY TumblingWindow(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"a": 53, "s": 123203},
 						Message: xsql.Message{"a": 53, "s": 123203},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -1918,7 +1918,7 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 		{
 		{
 			sql: "SELECT collect(*)[1]->a as c1 FROM test GROUP BY TumblingWindow(ss, 10)",
 			sql: "SELECT collect(*)[1]->a as c1 FROM test GROUP BY TumblingWindow(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"a": 53, "s": 123203},
 						Message: xsql.Message{"a": 53, "s": 123203},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -1937,7 +1937,7 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 		{
 		{
 			sql: "SELECT collect(*)[1]->sl[0] as c1 FROM test GROUP BY TumblingWindow(ss, 10)",
 			sql: "SELECT collect(*)[1]->sl[0] as c1 FROM test GROUP BY TumblingWindow(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"a": 53, "sl": []string{"hello", "world"}},
 						Message: xsql.Message{"a": 53, "sl": []string{"hello", "world"}},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -1958,15 +1958,15 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33, "c": 2, "r": 122}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33, "c": 2, "r": 122}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.51}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 								},
 								},
@@ -1974,15 +1974,15 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03, "c": 2, "r": 89}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03, "c": 2, "r": 89}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "color": "w1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "color": "w1"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 14.6}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 14.6}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "color": "w1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "color": "w1"}},
 								},
 								},
@@ -2007,7 +2007,7 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 		{
 		{
 			sql: "SELECT deduplicate(a, false)->a as c1 FROM test GROUP BY TumblingWindow(ss, 10)",
 			sql: "SELECT deduplicate(a, false)->a as c1 FROM test GROUP BY TumblingWindow(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"a": 53, "s": 123203},
 						Message: xsql.Message{"a": 53, "s": 123203},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -2026,7 +2026,7 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 		{
 		{
 			sql: "SELECT deduplicate(a, false) as c1 FROM test GROUP BY TumblingWindow(ss, 10)",
 			sql: "SELECT deduplicate(a, false) as c1 FROM test GROUP BY TumblingWindow(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"a": 53, "s": 123203},
 						Message: xsql.Message{"a": 53, "s": 123203},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -2043,7 +2043,7 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 		{
 		{
 			sql: "SELECT deduplicate(a, false) as c1 FROM test GROUP BY TumblingWindow(ss, 10)",
 			sql: "SELECT deduplicate(a, false) as c1 FROM test GROUP BY TumblingWindow(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"a": 53, "s": 123203},
 						Message: xsql.Message{"a": 53, "s": 123203},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",
@@ -2062,14 +2062,14 @@ func TestProjectPlan_AggFuncs(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "B", Message: xsql.Message{"module": 1, "topic": "moduleB topic", "value": 1}},
 									&xsql.Tuple{Emitter: "B", Message: xsql.Message{"module": 1, "topic": "moduleB topic", "value": 1}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "C", Message: xsql.Message{"module": 1, "topic": "moduleC topic", "value": 100}},
 									&xsql.Tuple{Emitter: "C", Message: xsql.Message{"module": 1, "topic": "moduleC topic", "value": 100}},
 								},
 								},
 							},
 							},
@@ -2163,27 +2163,27 @@ func TestProjectPlanError(t *testing.T) {
 			data: &xsql.GroupedTuplesSet{
 			data: &xsql.GroupedTuplesSet{
 				Groups: []*xsql.GroupedTuples{
 				Groups: []*xsql.GroupedTuples{
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 122.33}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 68.54}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 1, "a": 68.54}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 1, "color": "w2"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": "dde"}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": "dde"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "color": "w2"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.54}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 5, "a": 177.54}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 5, "color": "w2"}},
 								},
 								},
@@ -2191,15 +2191,15 @@ func TestProjectPlanError(t *testing.T) {
 						},
 						},
 					},
 					},
 					{
 					{
-						Content: []xsql.Row{
+						Content: []xsql.TupleRow{
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 2, "a": 89.03}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "color": "w1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 2, "color": "w1"}},
 								},
 								},
 							},
 							},
 							&xsql.JoinTuple{
 							&xsql.JoinTuple{
-								Tuples: []xsql.Row{
+								Tuples: []xsql.TupleRow{
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 14.6}},
 									&xsql.Tuple{Emitter: "test", Message: xsql.Message{"id": 4, "a": 14.6}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "color": "w1"}},
 									&xsql.Tuple{Emitter: "src2", Message: xsql.Message{"id": 4, "color": "w1"}},
 								},
 								},
@@ -2214,7 +2214,7 @@ func TestProjectPlanError(t *testing.T) {
 		{
 		{
 			sql: "SELECT sum(a) as sum FROM test GROUP BY TumblingWindow(ss, 10)",
 			sql: "SELECT sum(a) as sum FROM test GROUP BY TumblingWindow(ss, 10)",
 			data: &xsql.WindowTuples{
 			data: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{Emitter: "src1",
 					&xsql.Tuple{Emitter: "src1",
 						Message: xsql.Message{"a": 53},
 						Message: xsql.Message{"a": 53},
 					}, &xsql.Tuple{Emitter: "src1",
 					}, &xsql.Tuple{Emitter: "src1",

+ 6 - 7
internal/topo/operator/table_processor.go

@@ -50,10 +50,9 @@ func NewTableProcessor(isSchemaless bool, name string, fields []interface{}, opt
 	return p, nil
 	return p, nil
 }
 }
 
 
-/*
- *	input: *xsql.Tuple or BatchCount
- *	output: WindowTuples
- */
+// Apply
+//	input: *xsql.Tuple or BatchCount
+//	output: WindowTuples
 func (p *TableProcessor) Apply(ctx api.StreamContext, data interface{}, fv *xsql.FunctionValuer, _ *xsql.AggregateFunctionValuer) interface{} {
 func (p *TableProcessor) Apply(ctx api.StreamContext, data interface{}, fv *xsql.FunctionValuer, _ *xsql.AggregateFunctionValuer) interface{} {
 	logger := ctx.GetLogger()
 	logger := ctx.GetLogger()
 	tuple, ok := data.(*xsql.Tuple)
 	tuple, ok := data.(*xsql.Tuple)
@@ -63,7 +62,7 @@ func (p *TableProcessor) Apply(ctx api.StreamContext, data interface{}, fv *xsql
 	logger.Debugf("preprocessor receive %v", tuple)
 	logger.Debugf("preprocessor receive %v", tuple)
 	if p.batchEmitted {
 	if p.batchEmitted {
 		p.output = &xsql.WindowTuples{
 		p.output = &xsql.WindowTuples{
-			Content: make([]xsql.Row, 0),
+			Content: make([]xsql.TupleRow, 0),
 		}
 		}
 		p.batchEmitted = false
 		p.batchEmitted = false
 	}
 	}
@@ -75,8 +74,8 @@ func (p *TableProcessor) Apply(ctx api.StreamContext, data interface{}, fv *xsql
 			}
 			}
 			tuple.Message = result
 			tuple.Message = result
 		}
 		}
-		var newTuples []xsql.Row
-		_ = p.output.Range(func(i int, r xsql.Row) (bool, error) {
+		var newTuples []xsql.TupleRow
+		_ = p.output.Range(func(i int, r xsql.TupleRow) (bool, error) {
 			if p.retainSize > 0 && p.output.Len() == p.retainSize && i == 0 {
 			if p.retainSize > 0 && p.output.Len() == p.retainSize && i == 0 {
 				return true, nil
 				return true, nil
 			}
 			}

+ 3 - 3
internal/topo/operator/table_processor_test.go

@@ -47,7 +47,7 @@ func TestTableProcessor_Apply(t *testing.T) {
 			},
 			},
 			data: []byte(`[{"a": [{"b" : "hello1"}, {"b" : "hello2"}]},{"a": [{"b" : "hello2"}, {"b" : "hello3"}]},{"a": [{"b" : "hello3"}, {"b" : "hello4"}]}]`),
 			data: []byte(`[{"a": [{"b" : "hello1"}, {"b" : "hello2"}]},{"a": [{"b" : "hello2"}, {"b" : "hello3"}]},{"a": [{"b" : "hello3"}, {"b" : "hello4"}]}]`),
 			result: &xsql.WindowTuples{
 			result: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{
 					&xsql.Tuple{
 						Message: xsql.Message{
 						Message: xsql.Message{
 							"a": []map[string]interface{}{
 							"a": []map[string]interface{}{
@@ -84,7 +84,7 @@ func TestTableProcessor_Apply(t *testing.T) {
 			},
 			},
 			data: []byte(`[{"a": {"b" : "hello", "c": {"d": 35.2}}},{"a": {"b" : "world", "c": {"d": 65.2}}}]`),
 			data: []byte(`[{"a": {"b" : "hello", "c": {"d": 35.2}}},{"a": {"b" : "world", "c": {"d": 65.2}}}]`),
 			result: &xsql.WindowTuples{
 			result: &xsql.WindowTuples{
-				Content: []xsql.Row{
+				Content: []xsql.TupleRow{
 					&xsql.Tuple{
 					&xsql.Tuple{
 						Message: xsql.Message{
 						Message: xsql.Message{
 							"a": map[string]interface{}{
 							"a": map[string]interface{}{
@@ -120,7 +120,7 @@ func TestTableProcessor_Apply(t *testing.T) {
 		pp := &TableProcessor{isBatchInput: true, emitterName: "demo"}
 		pp := &TableProcessor{isBatchInput: true, emitterName: "demo"}
 		pp.streamFields = convertFields(tt.stmt.StreamFields)
 		pp.streamFields = convertFields(tt.stmt.StreamFields)
 		pp.output = &xsql.WindowTuples{
 		pp.output = &xsql.WindowTuples{
-			Content: make([]xsql.Row, 0),
+			Content: make([]xsql.TupleRow, 0),
 		}
 		}
 
 
 		var dm []map[string]interface{}
 		var dm []map[string]interface{}

+ 53 - 30
internal/xsql/collection.go

@@ -37,18 +37,26 @@ type SortingData interface {
 // Collection A collection of rows as a table. It is used for window, join, group by, etc.
 // Collection A collection of rows as a table. It is used for window, join, group by, etc.
 type Collection interface {
 type Collection interface {
 	SortingData
 	SortingData
-	// Range through each row. For grouped collection, each row is an aggregation of groups
-	Range(func(i int, r Row) (bool, error)) error
 	// GroupRange through each group. For non-grouped collection, the whole data is a single group
 	// GroupRange through each group. For non-grouped collection, the whole data is a single group
-	GroupRange(func(i int, rows AggregateData, firstRow Row) (bool, error)) error
+	GroupRange(func(i int, aggRow CollectionRow) (bool, error)) error
 	Filter(indexes []int) Collection
 	Filter(indexes []int) Collection
 	GetWindowRange() *WindowRange
 	GetWindowRange() *WindowRange
 }
 }
 
 
+type SingleCollection interface {
+	Collection
+	// Range through each row. For grouped collection, each row is an aggregation of groups
+	Range(func(i int, r TupleRow) (bool, error)) error
+}
+
+type GroupedCollection interface {
+	Collection
+}
+
 // MergedCollection is a collection of rows that are from different sources
 // MergedCollection is a collection of rows that are from different sources
 type MergedCollection interface {
 type MergedCollection interface {
 	Collection
 	Collection
-	GetBySrc(emitter string) []Row
+	GetBySrc(emitter string) []TupleRow
 }
 }
 
 
 /*
 /*
@@ -56,14 +64,17 @@ type MergedCollection interface {
  */
  */
 
 
 type WindowTuples struct {
 type WindowTuples struct {
-	Content []Row // immutable
+	Content []TupleRow // immutable
 	*WindowRange
 	*WindowRange
 	Alias
 	Alias
-	contentBySrc map[string][]Row // volatile, temporary cache
+	contentBySrc map[string][]TupleRow // volatile, temporary cache
 }
 }
 
 
 var _ MergedCollection = &WindowTuples{}
 var _ MergedCollection = &WindowTuples{}
 
 
+// Window Tuples is also an aggregate row
+var _ CollectionRow = &WindowTuples{}
+
 type JoinTuples struct {
 type JoinTuples struct {
 	Content []*JoinTuple
 	Content []*JoinTuple
 	*WindowRange
 	*WindowRange
@@ -71,6 +82,7 @@ type JoinTuples struct {
 }
 }
 
 
 var _ Collection = &JoinTuples{}
 var _ Collection = &JoinTuples{}
+var _ CollectionRow = &JoinTuples{}
 
 
 type GroupedTuplesSet struct {
 type GroupedTuplesSet struct {
 	Groups []*GroupedTuples
 	Groups []*GroupedTuples
@@ -95,13 +107,13 @@ func (w *WindowTuples) Swap(i, j int) {
 	w.Content[i], w.Content[j] = w.Content[j], w.Content[i]
 	w.Content[i], w.Content[j] = w.Content[j], w.Content[i]
 }
 }
 
 
-func (w *WindowTuples) GetBySrc(emitter string) []Row {
+func (w *WindowTuples) GetBySrc(emitter string) []TupleRow {
 	if w.contentBySrc == nil {
 	if w.contentBySrc == nil {
-		w.contentBySrc = make(map[string][]Row)
+		w.contentBySrc = make(map[string][]TupleRow)
 		for _, t := range w.Content {
 		for _, t := range w.Content {
 			e := t.GetEmitter()
 			e := t.GetEmitter()
 			if _, hasEmitter := w.contentBySrc[e]; !hasEmitter {
 			if _, hasEmitter := w.contentBySrc[e]; !hasEmitter {
-				w.contentBySrc[e] = make([]Row, 0)
+				w.contentBySrc[e] = make([]TupleRow, 0)
 			}
 			}
 			w.contentBySrc[e] = append(w.contentBySrc[e], t)
 			w.contentBySrc[e] = append(w.contentBySrc[e], t)
 		}
 		}
@@ -113,7 +125,7 @@ func (w *WindowTuples) GetWindowRange() *WindowRange {
 	return w.WindowRange
 	return w.WindowRange
 }
 }
 
 
-func (w *WindowTuples) Range(f func(i int, r Row) (bool, error)) error {
+func (w *WindowTuples) Range(f func(i int, r TupleRow) (bool, error)) error {
 	for i, r := range w.Content {
 	for i, r := range w.Content {
 		b, e := f(i, r)
 		b, e := f(i, r)
 		if e != nil {
 		if e != nil {
@@ -126,8 +138,8 @@ func (w *WindowTuples) Range(f func(i int, r Row) (bool, error)) error {
 	return nil
 	return nil
 }
 }
 
 
-func (w *WindowTuples) GroupRange(f func(i int, rows AggregateData, firstRow Row) (bool, error)) error {
-	_, err := f(0, w, w.Content[0])
+func (w *WindowTuples) GroupRange(f func(i int, aggRow CollectionRow) (bool, error)) error {
+	_, err := f(0, w)
 	return err
 	return err
 }
 }
 
 
@@ -153,7 +165,7 @@ func (w *WindowTuples) AggregateEval(expr ast.Expr, v CallValuer) []interface{}
 
 
 // Filter the tuples by the given predicate
 // Filter the tuples by the given predicate
 func (w *WindowTuples) Filter(indexes []int) Collection {
 func (w *WindowTuples) Filter(indexes []int) Collection {
-	newC := make([]Row, 0, len(indexes))
+	newC := make([]TupleRow, 0, len(indexes))
 	for _, i := range indexes {
 	for _, i := range indexes {
 		newC = append(newC, w.Content[i])
 		newC = append(newC, w.Content[i])
 	}
 	}
@@ -161,6 +173,18 @@ func (w *WindowTuples) Filter(indexes []int) Collection {
 	return w
 	return w
 }
 }
 
 
+func (w *WindowTuples) Value(key, table string) (interface{}, bool) {
+	return w.Content[0].Value(key, table)
+}
+
+func (w *WindowTuples) Meta(key, table string) (interface{}, bool) {
+	return w.Content[0].Meta(key, table)
+}
+
+func (w *WindowTuples) All(stream string) (Message, bool) {
+	return w.Content[0].All(stream)
+}
+
 func (s *JoinTuples) Len() int        { return len(s.Content) }
 func (s *JoinTuples) Len() int        { return len(s.Content) }
 func (s *JoinTuples) Swap(i, j int)   { s.Content[i], s.Content[j] = s.Content[j], s.Content[i] }
 func (s *JoinTuples) Swap(i, j int)   { s.Content[i], s.Content[j] = s.Content[j], s.Content[i] }
 func (s *JoinTuples) Index(i int) Row { return s.Content[i] }
 func (s *JoinTuples) Index(i int) Row { return s.Content[i] }
@@ -177,7 +201,7 @@ func (s *JoinTuples) GetWindowRange() *WindowRange {
 	return s.WindowRange
 	return s.WindowRange
 }
 }
 
 
-func (s *JoinTuples) Range(f func(i int, r Row) (bool, error)) error {
+func (s *JoinTuples) Range(f func(i int, r TupleRow) (bool, error)) error {
 	for i, r := range s.Content {
 	for i, r := range s.Content {
 		b, e := f(i, r)
 		b, e := f(i, r)
 		if e != nil {
 		if e != nil {
@@ -190,8 +214,8 @@ func (s *JoinTuples) Range(f func(i int, r Row) (bool, error)) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *JoinTuples) GroupRange(f func(i int, rows AggregateData, firstRow Row) (bool, error)) error {
-	_, err := f(0, s, s.Content[0])
+func (s *JoinTuples) GroupRange(f func(i int, aggRow CollectionRow) (bool, error)) error {
+	_, err := f(0, s)
 	return err
 	return err
 }
 }
 
 
@@ -205,6 +229,18 @@ func (s *JoinTuples) Filter(indexes []int) Collection {
 	return s
 	return s
 }
 }
 
 
+func (s *JoinTuples) Value(key, table string) (interface{}, bool) {
+	return s.Content[0].Value(key, table)
+}
+
+func (s *JoinTuples) Meta(key, table string) (interface{}, bool) {
+	return s.Content[0].Meta(key, table)
+}
+
+func (s *JoinTuples) All(stream string) (Message, bool) {
+	return s.Content[0].All(stream)
+}
+
 func (s *GroupedTuplesSet) Len() int        { return len(s.Groups) }
 func (s *GroupedTuplesSet) Len() int        { return len(s.Groups) }
 func (s *GroupedTuplesSet) Swap(i, j int)   { s.Groups[i], s.Groups[j] = s.Groups[j], s.Groups[i] }
 func (s *GroupedTuplesSet) Swap(i, j int)   { s.Groups[i], s.Groups[j] = s.Groups[j], s.Groups[i] }
 func (s *GroupedTuplesSet) Index(i int) Row { return s.Groups[i] }
 func (s *GroupedTuplesSet) Index(i int) Row { return s.Groups[i] }
@@ -213,7 +249,7 @@ func (s *GroupedTuplesSet) GetWindowRange() *WindowRange {
 	return s.WindowRange
 	return s.WindowRange
 }
 }
 
 
-func (s *GroupedTuplesSet) Range(f func(i int, r Row) (bool, error)) error {
+func (s *GroupedTuplesSet) GroupRange(f func(i int, aggRow CollectionRow) (bool, error)) error {
 	for i, r := range s.Groups {
 	for i, r := range s.Groups {
 		b, e := f(i, r)
 		b, e := f(i, r)
 		if e != nil {
 		if e != nil {
@@ -226,19 +262,6 @@ func (s *GroupedTuplesSet) Range(f func(i int, r Row) (bool, error)) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *GroupedTuplesSet) GroupRange(f func(i int, rows AggregateData, firstRow Row) (bool, error)) error {
-	for i, r := range s.Groups {
-		b, e := f(i, r, r)
-		if e != nil {
-			return e
-		}
-		if !b {
-			break
-		}
-	}
-	return nil
-}
-
 // Filter clone and return the filtered set
 // Filter clone and return the filtered set
 func (s *GroupedTuplesSet) Filter(groups []int) Collection {
 func (s *GroupedTuplesSet) Filter(groups []int) Collection {
 	newC := make([]*GroupedTuples, 0, len(groups))
 	newC := make([]*GroupedTuples, 0, len(groups))

+ 23 - 31
internal/xsql/row.go

@@ -39,16 +39,27 @@ type Row interface {
 	Valuer
 	Valuer
 	AliasValuer
 	AliasValuer
 	Wildcarder
 	Wildcarder
+}
+
+type TupleRow interface {
+	Row
 	// Set Only for some ops like functionOp
 	// Set Only for some ops like functionOp
 	Set(col string, value interface{})
 	Set(col string, value interface{})
 	// GetEmitter returns the emitter of the row
 	// GetEmitter returns the emitter of the row
 	GetEmitter() string
 	GetEmitter() string
 	// Clone when broadcast to make sure each row are dealt single threaded
 	// Clone when broadcast to make sure each row are dealt single threaded
-	Clone() Row
+	Clone() TupleRow
 	// ToMap converts the row to a map to export to other systems
 	// ToMap converts the row to a map to export to other systems
 	ToMap() map[string]interface{}
 	ToMap() map[string]interface{}
 }
 }
 
 
+// CollectionRow is the aggregation row of a non-grouped collection. Thinks of it as a single group.
+// The row data is immutable
+type CollectionRow interface {
+	Row
+	AggregateData
+}
+
 /*
 /*
  *  Message definition
  *  Message definition
  */
  */
@@ -78,24 +89,24 @@ type Tuple struct {
 	Alias
 	Alias
 }
 }
 
 
-var _ Row = &Tuple{}
+var _ TupleRow = &Tuple{}
 
 
 // JoinTuple is a row produced by a join operation
 // JoinTuple is a row produced by a join operation
 type JoinTuple struct {
 type JoinTuple struct {
-	Tuples []Row
+	Tuples []TupleRow
 	Alias
 	Alias
 }
 }
 
 
-var _ Row = &JoinTuple{}
+var _ TupleRow = &JoinTuple{}
 
 
 // GroupedTuples is a collection of tuples grouped by a key
 // GroupedTuples is a collection of tuples grouped by a key
 type GroupedTuples struct {
 type GroupedTuples struct {
-	Content []Row
+	Content []TupleRow
 	*WindowRange
 	*WindowRange
 	Alias
 	Alias
 }
 }
 
 
-var _ Row = &GroupedTuples{}
+var _ CollectionRow = &GroupedTuples{}
 
 
 /*
 /*
  *   Implementations
  *   Implementations
@@ -201,7 +212,7 @@ func (t *Tuple) Set(col string, value interface{}) {
 	panic("implement me")
 	panic("implement me")
 }
 }
 
 
-func (t *Tuple) Clone() Row {
+func (t *Tuple) Clone() TupleRow {
 	c := &Tuple{
 	c := &Tuple{
 		Emitter:   t.Emitter,
 		Emitter:   t.Emitter,
 		Timestamp: t.Timestamp,
 		Timestamp: t.Timestamp,
@@ -253,11 +264,11 @@ func (t *Tuple) IsWatermark() bool {
 
 
 // JoinTuple implementation
 // JoinTuple implementation
 
 
-func (jt *JoinTuple) AddTuple(tuple Row) {
+func (jt *JoinTuple) AddTuple(tuple TupleRow) {
 	jt.Tuples = append(jt.Tuples, tuple)
 	jt.Tuples = append(jt.Tuples, tuple)
 }
 }
 
 
-func (jt *JoinTuple) AddTuples(tuples []Row) {
+func (jt *JoinTuple) AddTuples(tuples []TupleRow) {
 	for _, t := range tuples {
 	for _, t := range tuples {
 		jt.Tuples = append(jt.Tuples, t)
 		jt.Tuples = append(jt.Tuples, t)
 	}
 	}
@@ -323,10 +334,10 @@ func (jt *JoinTuple) All(stream string) (Message, bool) {
 }
 }
 
 
 // TODO deal with cascade
 // TODO deal with cascade
-func (jt *JoinTuple) Clone() Row {
-	ts := make([]Row, len(jt.Tuples))
+func (jt *JoinTuple) Clone() TupleRow {
+	ts := make([]TupleRow, len(jt.Tuples))
 	for i, t := range jt.Tuples {
 	for i, t := range jt.Tuples {
-		ts[i] = t.Clone()
+		ts[i] = t.Clone().(TupleRow)
 	}
 	}
 	return &JoinTuple{Tuples: ts}
 	return &JoinTuple{Tuples: ts}
 }
 }
@@ -368,25 +379,6 @@ func (s *GroupedTuples) Meta(key, table string) (interface{}, bool) {
 	return s.Content[0].Meta(key, table)
 	return s.Content[0].Meta(key, table)
 }
 }
 
 
-func (s *GroupedTuples) Set(col string, value interface{}) {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (s *GroupedTuples) Clone() Row {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (s *GroupedTuples) ToMap() map[string]interface{} {
-	//TODO implement me
-	panic("implement me")
-}
-
 func (s *GroupedTuples) All(stream string) (Message, bool) {
 func (s *GroupedTuples) All(stream string) (Message, bool) {
 	return s.Content[0].All(stream)
 	return s.Content[0].All(stream)
 }
 }
-
-func (s *GroupedTuples) GetEmitter() string {
-	return "$$GROUP"
-}