@@ -93,21 +93,38 @@ type WindowV2Exec interface {
9393
9494type StateWindowOp struct {
9595 * WindowV2Operator
96- BeginCondition ast.Expr
97- EmitCondition ast.Expr
98- onBegin bool
99- stateFuncs []* ast.Call
96+ StartTime time.Time
97+ EndTime time.Time
98+ SingleCondition ast.Expr
99+ BeginCondition ast.Expr
100+ EmitCondition ast.Expr
101+ onBegin bool
102+ stateFuncs []* ast.Call
100103}
101104
102105func NewStateWindowOp (o * WindowV2Operator ) * StateWindowOp {
103106 return & StateWindowOp {
104107 WindowV2Operator : o ,
105108 BeginCondition : o .windowConfig .BeginCondition ,
106109 EmitCondition : o .windowConfig .EmitCondition ,
110+ SingleCondition : o .windowConfig .SingleCondition ,
107111 stateFuncs : o .windowConfig .StateFuncs ,
108112 }
109113}
110114
115+ func (s * StateWindowOp ) emit (ctx api.StreamContext , startTime , endTime time.Time ) {
116+ tuples := s .scanner .scanWindow (time.Time {}, InfTime )
117+ results := & xsql.WindowTuples {
118+ Content : make ([]xsql.Row , 0 ),
119+ }
120+ for _ , tuple := range tuples {
121+ results .Content = append (results .Content , tuple )
122+ }
123+ results .WindowRange = xsql .NewWindowRange (startTime .UnixMilli (), endTime .UnixMilli (), endTime .UnixMilli ())
124+ s .Broadcast (results )
125+ s .onSend (ctx , results )
126+ }
127+
111128func (s * StateWindowOp ) exec (ctx api.StreamContext , errCh chan <- error ) {
112129 fv , _ := xsql .NewFunctionValuersForOp (ctx )
113130 for {
@@ -122,27 +139,60 @@ func (s *StateWindowOp) exec(ctx api.StreamContext, errCh chan<- error) {
122139 s .onProcessStart (ctx , input )
123140 switch row := data .(type ) {
124141 case * xsql.Tuple :
125- if ! s .onBegin {
126- canBegin := isMatchCondition (ctx , s .BeginCondition , fv , row , s .stateFuncs )
127- if canBegin {
128- s .onBegin = true
129- s .scanner .addTuple (row )
130- }
131- } else {
132- s .scanner .addTuple (row )
133- canEmit := isMatchCondition (ctx , s .EmitCondition , fv , row , s .stateFuncs )
134- if canEmit {
135- s .emitWindow (ctx , time.Time {}, InfTime )
136- s .scanner .gc (InfTime )
137- s .onBegin = false
138- }
142+ if s .BeginCondition != nil && s .EmitCondition != nil {
143+ s .handleTupleWithBeginEmitCondition (ctx , fv , row )
144+ } else if s .SingleCondition != nil {
145+ s .handleTupleWithSingleCondition (ctx , fv , row )
139146 }
140147 }
141148 s .onProcessEnd (ctx )
142149 }
143150 }
144151}
145152
153+ func (s * StateWindowOp ) handleTupleWithBeginEmitCondition (ctx api.StreamContext , fv * xsql.FunctionValuer , row * xsql.Tuple ) {
154+ if ! s .onBegin {
155+ canBegin := isMatchCondition (ctx , s .BeginCondition , fv , row , s .stateFuncs )
156+ if canBegin {
157+ s .StartTime = row .Timestamp
158+ s .onBegin = true
159+ s .scanner .addTuple (row )
160+ }
161+ } else {
162+ s .scanner .addTuple (row )
163+ canEmit := isMatchCondition (ctx , s .EmitCondition , fv , row , s .stateFuncs )
164+ if canEmit {
165+ s .EndTime = row .Timestamp
166+ s .emit (ctx , s .StartTime , s .EndTime )
167+ s .scanner .gc (InfTime )
168+ s .onBegin = false
169+ }
170+ }
171+ }
172+
173+ func (s * StateWindowOp ) handleTupleWithSingleCondition (ctx api.StreamContext , fv * xsql.FunctionValuer , row * xsql.Tuple ) {
174+ if ! s .onBegin {
175+ canBegin := isMatchCondition (ctx , s .SingleCondition , fv , row , s .stateFuncs )
176+ if canBegin {
177+ s .StartTime = row .Timestamp
178+ s .onBegin = true
179+ s .scanner .addTuple (row )
180+ }
181+ } else {
182+ canEmit := isMatchCondition (ctx , s .SingleCondition , fv , row , s .stateFuncs )
183+ if canEmit {
184+ s .EndTime = row .Timestamp
185+ s .emit (ctx , s .StartTime , s .EndTime )
186+ s .scanner .gc (InfTime )
187+ s .onBegin = true
188+ s .scanner .addTuple (row )
189+ s .StartTime = row .Timestamp
190+ } else {
191+ s .scanner .addTuple (row )
192+ }
193+ }
194+ }
195+
146196type SlidingWindowOp struct {
147197 * WindowV2Operator
148198 Delay time.Duration
0 commit comments