github.com/influxdata/influxdb/v2@v2.7.6/influxql/query/iterator.go (about) 1 package query 2 3 import ( 4 "context" 5 "encoding/binary" 6 "errors" 7 "fmt" 8 "io" 9 "regexp" 10 "time" 11 12 internal "github.com/influxdata/influxdb/v2/influxql/query/internal" 13 "github.com/influxdata/influxdb/v2/kit/platform" 14 "github.com/influxdata/influxql" 15 "google.golang.org/protobuf/proto" 16 ) 17 18 // ErrUnknownCall is returned when operating on an unknown function call. 19 var ErrUnknownCall = errors.New("unknown call") 20 21 const ( 22 // secToNs is the number of nanoseconds in a second. 23 secToNs = int64(time.Second) 24 ) 25 26 // Iterator represents a generic interface for all Iterators. 27 // Most iterator operations are done on the typed sub-interfaces. 28 type Iterator interface { 29 Stats() IteratorStats 30 Close() error 31 } 32 33 // Iterators represents a list of iterators. 34 type Iterators []Iterator 35 36 // Stats returns the aggregation of all iterator stats. 37 func (a Iterators) Stats() IteratorStats { 38 var stats IteratorStats 39 for _, itr := range a { 40 stats.Add(itr.Stats()) 41 } 42 return stats 43 } 44 45 // Close closes all iterators. 46 // We are seeing an occasional panic in this function 47 // which looks like a nil reference from one 48 // itr.Close() call, thus we check for nil elements 49 // in the slice a. This is often called as error 50 // clean-up, so the state of the iterators may be 51 // unhappy. 52 func (a Iterators) Close() (err error) { 53 err = nil 54 for _, itr := range a { 55 if itr != nil { 56 if e := itr.Close(); e != nil && err == nil { 57 err = e 58 } 59 } 60 } 61 return err 62 } 63 64 // filterNonNil returns a slice of iterators that removes all nil iterators. 65 func (a Iterators) filterNonNil() []Iterator { 66 other := make([]Iterator, 0, len(a)) 67 for _, itr := range a { 68 if itr == nil { 69 continue 70 } 71 other = append(other, itr) 72 } 73 return other 74 } 75 76 // dataType determines what slice type this set of iterators should be. 77 // An iterator type is chosen by looking at the first element in the slice 78 // and then returning the data type for that iterator. 79 func (a Iterators) dataType() influxql.DataType { 80 if len(a) == 0 { 81 return influxql.Unknown 82 } 83 84 switch a[0].(type) { 85 case FloatIterator: 86 return influxql.Float 87 case IntegerIterator: 88 return influxql.Integer 89 case UnsignedIterator: 90 return influxql.Unsigned 91 case StringIterator: 92 return influxql.String 93 case BooleanIterator: 94 return influxql.Boolean 95 default: 96 return influxql.Unknown 97 } 98 } 99 100 // coerce forces an array of iterators to be a single type. 101 // Iterators that are not of the same type as the first element in the slice 102 // will be closed and dropped. 103 func (a Iterators) coerce() interface{} { 104 typ := a.dataType() 105 switch typ { 106 case influxql.Float: 107 return newFloatIterators(a) 108 case influxql.Integer: 109 return newIntegerIterators(a) 110 case influxql.Unsigned: 111 return newUnsignedIterators(a) 112 case influxql.String: 113 return newStringIterators(a) 114 case influxql.Boolean: 115 return newBooleanIterators(a) 116 } 117 return a 118 } 119 120 // Merge combines all iterators into a single iterator. 121 // A sorted merge iterator or a merge iterator can be used based on opt. 122 func (a Iterators) Merge(opt IteratorOptions) (Iterator, error) { 123 // Check if this is a call expression. 124 call, ok := opt.Expr.(*influxql.Call) 125 126 // Merge into a single iterator. 127 if !ok && opt.MergeSorted() { 128 itr := NewSortedMergeIterator(a, opt) 129 if itr != nil && opt.InterruptCh != nil { 130 itr = NewInterruptIterator(itr, opt.InterruptCh) 131 } 132 return itr, nil 133 } 134 135 // We do not need an ordered output so use a merge iterator. 136 itr := NewMergeIterator(a, opt) 137 if itr == nil { 138 return nil, nil 139 } 140 141 if opt.InterruptCh != nil { 142 itr = NewInterruptIterator(itr, opt.InterruptCh) 143 } 144 145 if !ok { 146 // This is not a call expression so do not use a call iterator. 147 return itr, nil 148 } 149 150 // When merging the count() function, use sum() to sum the counted points. 151 if call.Name == "count" { 152 opt.Expr = &influxql.Call{ 153 Name: "sum", 154 Args: call.Args, 155 } 156 } 157 // When merging the sum_hll() function, use merge_hll() to sum the counted points. 158 if call.Name == "sum_hll" { 159 opt.Expr = &influxql.Call{ 160 Name: "merge_hll", 161 Args: call.Args, 162 } 163 } 164 return NewCallIterator(itr, opt) 165 } 166 167 // NewMergeIterator returns an iterator to merge itrs into one. 168 // Inputs must either be merge iterators or only contain a single name/tag in 169 // sorted order. The iterator will output all points by window, name/tag, then 170 // time. This iterator is useful when you need all of the points for an 171 // interval. 172 func NewMergeIterator(inputs []Iterator, opt IteratorOptions) Iterator { 173 inputs = Iterators(inputs).filterNonNil() 174 if n := len(inputs); n == 0 { 175 return nil 176 } else if n == 1 { 177 return inputs[0] 178 } 179 180 // Aggregate functions can use a more relaxed sorting so that points 181 // within a window are grouped. This is much more efficient. 182 switch inputs := Iterators(inputs).coerce().(type) { 183 case []FloatIterator: 184 return newFloatMergeIterator(inputs, opt) 185 case []IntegerIterator: 186 return newIntegerMergeIterator(inputs, opt) 187 case []UnsignedIterator: 188 return newUnsignedMergeIterator(inputs, opt) 189 case []StringIterator: 190 return newStringMergeIterator(inputs, opt) 191 case []BooleanIterator: 192 return newBooleanMergeIterator(inputs, opt) 193 default: 194 panic(fmt.Sprintf("unsupported merge iterator type: %T", inputs)) 195 } 196 } 197 198 // NewParallelMergeIterator returns an iterator that breaks input iterators 199 // into groups and processes them in parallel. 200 func NewParallelMergeIterator(inputs []Iterator, opt IteratorOptions, parallelism int) Iterator { 201 inputs = Iterators(inputs).filterNonNil() 202 if len(inputs) == 0 { 203 return nil 204 } else if len(inputs) == 1 { 205 return inputs[0] 206 } 207 208 // Limit parallelism to the number of inputs. 209 if len(inputs) < parallelism { 210 parallelism = len(inputs) 211 } 212 213 // Determine the number of inputs per output iterator. 214 n := len(inputs) / parallelism 215 216 // Group iterators together. 217 outputs := make([]Iterator, parallelism) 218 for i := range outputs { 219 var slice []Iterator 220 if i < len(outputs)-1 { 221 slice = inputs[i*n : (i+1)*n] 222 } else { 223 slice = inputs[i*n:] 224 } 225 226 outputs[i] = newParallelIterator(NewMergeIterator(slice, opt)) 227 } 228 229 // Merge all groups together. 230 return NewMergeIterator(outputs, opt) 231 } 232 233 // NewSortedMergeIterator returns an iterator to merge itrs into one. 234 // Inputs must either be sorted merge iterators or only contain a single 235 // name/tag in sorted order. The iterator will output all points by name/tag, 236 // then time. This iterator is useful when you need all points for a name/tag 237 // to be in order. 238 func NewSortedMergeIterator(inputs []Iterator, opt IteratorOptions) Iterator { 239 inputs = Iterators(inputs).filterNonNil() 240 if len(inputs) == 0 { 241 return nil 242 } else if len(inputs) == 1 { 243 return inputs[0] 244 } 245 246 switch inputs := Iterators(inputs).coerce().(type) { 247 case []FloatIterator: 248 return newFloatSortedMergeIterator(inputs, opt) 249 case []IntegerIterator: 250 return newIntegerSortedMergeIterator(inputs, opt) 251 case []UnsignedIterator: 252 return newUnsignedSortedMergeIterator(inputs, opt) 253 case []StringIterator: 254 return newStringSortedMergeIterator(inputs, opt) 255 case []BooleanIterator: 256 return newBooleanSortedMergeIterator(inputs, opt) 257 default: 258 panic(fmt.Sprintf("unsupported sorted merge iterator type: %T", inputs)) 259 } 260 } 261 262 // newParallelIterator returns an iterator that runs in a separate goroutine. 263 func newParallelIterator(input Iterator) Iterator { 264 if input == nil { 265 return nil 266 } 267 268 switch itr := input.(type) { 269 case FloatIterator: 270 return newFloatParallelIterator(itr) 271 case IntegerIterator: 272 return newIntegerParallelIterator(itr) 273 case UnsignedIterator: 274 return newUnsignedParallelIterator(itr) 275 case StringIterator: 276 return newStringParallelIterator(itr) 277 case BooleanIterator: 278 return newBooleanParallelIterator(itr) 279 default: 280 panic(fmt.Sprintf("unsupported parallel iterator type: %T", itr)) 281 } 282 } 283 284 // NewLimitIterator returns an iterator that limits the number of points per grouping. 285 func NewLimitIterator(input Iterator, opt IteratorOptions) Iterator { 286 switch input := input.(type) { 287 case FloatIterator: 288 return newFloatLimitIterator(input, opt) 289 case IntegerIterator: 290 return newIntegerLimitIterator(input, opt) 291 case UnsignedIterator: 292 return newUnsignedLimitIterator(input, opt) 293 case StringIterator: 294 return newStringLimitIterator(input, opt) 295 case BooleanIterator: 296 return newBooleanLimitIterator(input, opt) 297 default: 298 panic(fmt.Sprintf("unsupported limit iterator type: %T", input)) 299 } 300 } 301 302 // NewFilterIterator returns an iterator that filters the points based on the 303 // condition. This iterator is not nearly as efficient as filtering points 304 // within the query engine and is only used when filtering subqueries. 305 func NewFilterIterator(input Iterator, cond influxql.Expr, opt IteratorOptions) Iterator { 306 if input == nil { 307 return nil 308 } 309 310 switch input := input.(type) { 311 case FloatIterator: 312 return newFloatFilterIterator(input, cond, opt) 313 case IntegerIterator: 314 return newIntegerFilterIterator(input, cond, opt) 315 case UnsignedIterator: 316 return newUnsignedFilterIterator(input, cond, opt) 317 case StringIterator: 318 return newStringFilterIterator(input, cond, opt) 319 case BooleanIterator: 320 return newBooleanFilterIterator(input, cond, opt) 321 default: 322 panic(fmt.Sprintf("unsupported filter iterator type: %T", input)) 323 } 324 } 325 326 // NewTagSubsetIterator will strip each of the points to a subset of the tag key values 327 // for each point it processes. 328 func NewTagSubsetIterator(input Iterator, opt IteratorOptions) Iterator { 329 if input == nil { 330 return nil 331 } 332 333 switch input := input.(type) { 334 case FloatIterator: 335 return newFloatTagSubsetIterator(input, opt) 336 case IntegerIterator: 337 return newIntegerTagSubsetIterator(input, opt) 338 case UnsignedIterator: 339 return newUnsignedTagSubsetIterator(input, opt) 340 case StringIterator: 341 return newStringTagSubsetIterator(input, opt) 342 case BooleanIterator: 343 return newBooleanTagSubsetIterator(input, opt) 344 default: 345 panic(fmt.Sprintf("unsupported tag subset iterator type: %T", input)) 346 } 347 } 348 349 // NewDedupeIterator returns an iterator that only outputs unique points. 350 // This iterator maintains a serialized copy of each row so it is inefficient 351 // to use on large datasets. It is intended for small datasets such as meta queries. 352 func NewDedupeIterator(input Iterator) Iterator { 353 if input == nil { 354 return nil 355 } 356 357 switch input := input.(type) { 358 case FloatIterator: 359 return newFloatDedupeIterator(input) 360 case IntegerIterator: 361 return newIntegerDedupeIterator(input) 362 case UnsignedIterator: 363 return newUnsignedDedupeIterator(input) 364 case StringIterator: 365 return newStringDedupeIterator(input) 366 case BooleanIterator: 367 return newBooleanDedupeIterator(input) 368 default: 369 panic(fmt.Sprintf("unsupported dedupe iterator type: %T", input)) 370 } 371 } 372 373 // NewFillIterator returns an iterator that fills in missing points in an aggregate. 374 func NewFillIterator(input Iterator, expr influxql.Expr, opt IteratorOptions) Iterator { 375 switch input := input.(type) { 376 case FloatIterator: 377 return newFloatFillIterator(input, expr, opt) 378 case IntegerIterator: 379 return newIntegerFillIterator(input, expr, opt) 380 case UnsignedIterator: 381 return newUnsignedFillIterator(input, expr, opt) 382 case StringIterator: 383 return newStringFillIterator(input, expr, opt) 384 case BooleanIterator: 385 return newBooleanFillIterator(input, expr, opt) 386 default: 387 panic(fmt.Sprintf("unsupported fill iterator type: %T", input)) 388 } 389 } 390 391 // NewIntervalIterator returns an iterator that sets the time on each point to the interval. 392 func NewIntervalIterator(input Iterator, opt IteratorOptions) Iterator { 393 switch input := input.(type) { 394 case FloatIterator: 395 return newFloatIntervalIterator(input, opt) 396 case IntegerIterator: 397 return newIntegerIntervalIterator(input, opt) 398 case UnsignedIterator: 399 return newUnsignedIntervalIterator(input, opt) 400 case StringIterator: 401 return newStringIntervalIterator(input, opt) 402 case BooleanIterator: 403 return newBooleanIntervalIterator(input, opt) 404 default: 405 panic(fmt.Sprintf("unsupported interval iterator type: %T", input)) 406 } 407 } 408 409 // NewInterruptIterator returns an iterator that will stop producing output 410 // when the passed-in channel is closed. 411 func NewInterruptIterator(input Iterator, closing <-chan struct{}) Iterator { 412 switch input := input.(type) { 413 case FloatIterator: 414 return newFloatInterruptIterator(input, closing) 415 case IntegerIterator: 416 return newIntegerInterruptIterator(input, closing) 417 case UnsignedIterator: 418 return newUnsignedInterruptIterator(input, closing) 419 case StringIterator: 420 return newStringInterruptIterator(input, closing) 421 case BooleanIterator: 422 return newBooleanInterruptIterator(input, closing) 423 default: 424 panic(fmt.Sprintf("unsupported interrupt iterator type: %T", input)) 425 } 426 } 427 428 // IteratorScanner is used to scan the results of an iterator into a map. 429 type IteratorScanner interface { 430 // Peek retrieves information about the next point. It returns a timestamp, the name, and the tags. 431 Peek() (int64, string, Tags) 432 433 // ScanAt will take a time, name, and tags and scan the point that matches those into the map. 434 ScanAt(ts int64, name string, tags Tags, values map[string]interface{}) 435 436 // Stats returns the IteratorStats from the Iterator. 437 Stats() IteratorStats 438 439 // Err returns an error that was encountered while scanning. 440 Err() error 441 442 io.Closer 443 } 444 445 // SkipDefault is a sentinel value to tell the IteratorScanner to skip setting the 446 // default value if none was present. This causes the map to use the previous value 447 // if it was previously set. 448 var SkipDefault = interface{}(0) 449 450 // NewIteratorScanner produces an IteratorScanner for the Iterator. 451 func NewIteratorScanner(input Iterator, keys []influxql.VarRef, defaultValue interface{}) IteratorScanner { 452 switch input := input.(type) { 453 case FloatIterator: 454 return newFloatIteratorScanner(input, keys, defaultValue) 455 case IntegerIterator: 456 return newIntegerIteratorScanner(input, keys, defaultValue) 457 case UnsignedIterator: 458 return newUnsignedIteratorScanner(input, keys, defaultValue) 459 case StringIterator: 460 return newStringIteratorScanner(input, keys, defaultValue) 461 case BooleanIterator: 462 return newBooleanIteratorScanner(input, keys, defaultValue) 463 default: 464 panic(fmt.Sprintf("unsupported type for iterator scanner: %T", input)) 465 } 466 } 467 468 // DrainIterator reads and discards all points from itr. 469 func DrainIterator(itr Iterator) { 470 defer itr.Close() 471 switch itr := itr.(type) { 472 case FloatIterator: 473 for p, _ := itr.Next(); p != nil; p, _ = itr.Next() { 474 } 475 case IntegerIterator: 476 for p, _ := itr.Next(); p != nil; p, _ = itr.Next() { 477 } 478 case UnsignedIterator: 479 for p, _ := itr.Next(); p != nil; p, _ = itr.Next() { 480 } 481 case StringIterator: 482 for p, _ := itr.Next(); p != nil; p, _ = itr.Next() { 483 } 484 case BooleanIterator: 485 for p, _ := itr.Next(); p != nil; p, _ = itr.Next() { 486 } 487 default: 488 panic(fmt.Sprintf("unsupported iterator type for draining: %T", itr)) 489 } 490 } 491 492 // DrainIterators reads and discards all points from itrs. 493 func DrainIterators(itrs []Iterator) { 494 defer Iterators(itrs).Close() 495 for { 496 var hasData bool 497 498 for _, itr := range itrs { 499 switch itr := itr.(type) { 500 case FloatIterator: 501 if p, _ := itr.Next(); p != nil { 502 hasData = true 503 } 504 case IntegerIterator: 505 if p, _ := itr.Next(); p != nil { 506 hasData = true 507 } 508 case UnsignedIterator: 509 if p, _ := itr.Next(); p != nil { 510 hasData = true 511 } 512 case StringIterator: 513 if p, _ := itr.Next(); p != nil { 514 hasData = true 515 } 516 case BooleanIterator: 517 if p, _ := itr.Next(); p != nil { 518 hasData = true 519 } 520 default: 521 panic(fmt.Sprintf("unsupported iterator type for draining: %T", itr)) 522 } 523 } 524 525 // Exit once all iterators return a nil point. 526 if !hasData { 527 break 528 } 529 } 530 } 531 532 // NewReaderIterator returns an iterator that streams from a reader. 533 func NewReaderIterator(ctx context.Context, r io.Reader, typ influxql.DataType, stats IteratorStats) Iterator { 534 switch typ { 535 case influxql.Float: 536 return newFloatReaderIterator(ctx, r, stats) 537 case influxql.Integer: 538 return newIntegerReaderIterator(ctx, r, stats) 539 case influxql.Unsigned: 540 return newUnsignedReaderIterator(ctx, r, stats) 541 case influxql.String: 542 return newStringReaderIterator(ctx, r, stats) 543 case influxql.Boolean: 544 return newBooleanReaderIterator(ctx, r, stats) 545 default: 546 return &nilFloatReaderIterator{r: r} 547 } 548 } 549 550 // IteratorCreator is an interface to create Iterators. 551 type IteratorCreator interface { 552 // Creates a simple iterator for use in an InfluxQL query. 553 CreateIterator(ctx context.Context, source *influxql.Measurement, opt IteratorOptions) (Iterator, error) 554 555 // Determines the potential cost for creating an iterator. 556 IteratorCost(ctx context.Context, source *influxql.Measurement, opt IteratorOptions) (IteratorCost, error) 557 } 558 559 // IteratorOptions is an object passed to CreateIterator to specify creation options. 560 type IteratorOptions struct { 561 // OrgID is the organization for which this query is being executed. 562 OrgID platform.ID 563 564 // Expression to iterate for. 565 // This can be VarRef or a Call. 566 Expr influxql.Expr 567 568 // Auxiliary tags or values to also retrieve for the point. 569 Aux []influxql.VarRef 570 571 // Data sources from which to receive data. This is only used for encoding 572 // measurements over RPC and is no longer used in the open source version. 573 Sources []influxql.Source 574 575 // Group by interval and tags. 576 Interval Interval 577 Dimensions []string // The final dimensions of the query (stays the same even in subqueries). 578 GroupBy map[string]struct{} // Dimensions to group points by in intermediate iterators. 579 Location *time.Location 580 581 // Fill options. 582 Fill influxql.FillOption 583 FillValue interface{} 584 585 // Condition to filter by. 586 Condition influxql.Expr 587 588 // Time range for the iterator. 589 StartTime int64 590 EndTime int64 591 592 // Sorted in time ascending order if true. 593 Ascending bool 594 595 // Limits the number of points per series. 596 Limit, Offset int 597 598 // Limits the number of series. 599 SLimit, SOffset int 600 601 // Removes the measurement name. Useful for meta queries. 602 StripName bool 603 604 // Removes duplicate rows from raw queries. 605 Dedupe bool 606 607 // Determines if this is a query for raw data or an aggregate/selector. 608 Ordered bool 609 610 // Limits on the creation of iterators. 611 MaxSeriesN int 612 613 // If this channel is set and is closed, the iterator should try to exit 614 // and close as soon as possible. 615 InterruptCh <-chan struct{} 616 617 // Authorizer can limit access to data 618 Authorizer Authorizer 619 } 620 621 // newIteratorOptionsStmt creates the iterator options from stmt. 622 func newIteratorOptionsStmt(stmt *influxql.SelectStatement, sopt SelectOptions) (opt IteratorOptions, err error) { 623 // Determine time range from the condition. 624 valuer := &influxql.NowValuer{Location: stmt.Location} 625 condition, timeRange, err := influxql.ConditionExpr(stmt.Condition, valuer) 626 if err != nil { 627 return IteratorOptions{}, err 628 } 629 630 if !timeRange.Min.IsZero() { 631 opt.StartTime = timeRange.Min.UnixNano() 632 } else { 633 opt.StartTime = influxql.MinTime 634 } 635 if !timeRange.Max.IsZero() { 636 opt.EndTime = timeRange.Max.UnixNano() 637 } else { 638 opt.EndTime = influxql.MaxTime 639 } 640 opt.Location = stmt.Location 641 642 // Determine group by interval. 643 interval, err := stmt.GroupByInterval() 644 if err != nil { 645 return opt, err 646 } 647 // Set duration to zero if a negative interval has been used. 648 if interval < 0 { 649 interval = 0 650 } else if interval > 0 { 651 opt.Interval.Offset, err = stmt.GroupByOffset() 652 if err != nil { 653 return opt, err 654 } 655 } 656 opt.Interval.Duration = interval 657 658 // Always request an ordered output for the top level iterators. 659 // The emitter will always emit points as ordered. 660 opt.Ordered = true 661 662 // Determine dimensions. 663 opt.GroupBy = make(map[string]struct{}, len(opt.Dimensions)) 664 for _, d := range stmt.Dimensions { 665 if d, ok := d.Expr.(*influxql.VarRef); ok { 666 opt.Dimensions = append(opt.Dimensions, d.Val) 667 opt.GroupBy[d.Val] = struct{}{} 668 } 669 } 670 671 opt.Condition = condition 672 opt.Ascending = stmt.TimeAscending() 673 opt.Dedupe = stmt.Dedupe 674 opt.StripName = stmt.StripName 675 676 opt.Fill, opt.FillValue = stmt.Fill, stmt.FillValue 677 if opt.Fill == influxql.NullFill && stmt.Target != nil { 678 // Set the fill option to none if a target has been given. 679 // Null values will get ignored when being written to the target 680 // so fill(null) wouldn't write any null values to begin with. 681 opt.Fill = influxql.NoFill 682 } 683 opt.Limit, opt.Offset = stmt.Limit, stmt.Offset 684 opt.SLimit, opt.SOffset = stmt.SLimit, stmt.SOffset 685 opt.MaxSeriesN = sopt.MaxSeriesN 686 opt.OrgID = sopt.OrgID 687 688 return opt, nil 689 } 690 691 func newIteratorOptionsSubstatement(ctx context.Context, stmt *influxql.SelectStatement, opt IteratorOptions) (IteratorOptions, error) { 692 subOpt, err := newIteratorOptionsStmt(stmt, SelectOptions{ 693 OrgID: opt.OrgID, 694 MaxSeriesN: opt.MaxSeriesN, 695 }) 696 if err != nil { 697 return IteratorOptions{}, err 698 } 699 700 if subOpt.StartTime < opt.StartTime { 701 subOpt.StartTime = opt.StartTime 702 } 703 if subOpt.EndTime > opt.EndTime { 704 subOpt.EndTime = opt.EndTime 705 } 706 if !subOpt.Interval.IsZero() && subOpt.EndTime == influxql.MaxTime { 707 if now := ctx.Value(nowKey); now != nil { 708 subOpt.EndTime = now.(time.Time).UnixNano() 709 } 710 } 711 // Propagate the dimensions to the inner subquery. 712 subOpt.Dimensions = opt.Dimensions 713 for d := range opt.GroupBy { 714 subOpt.GroupBy[d] = struct{}{} 715 } 716 subOpt.InterruptCh = opt.InterruptCh 717 718 // Extract the time range and condition from the condition. 719 valuer := &influxql.NowValuer{Location: stmt.Location} 720 cond, t, err := influxql.ConditionExpr(stmt.Condition, valuer) 721 if err != nil { 722 return IteratorOptions{}, err 723 } 724 subOpt.Condition = cond 725 // If the time range is more constrained, use it instead. A less constrained time 726 // range should be ignored. 727 if !t.Min.IsZero() && t.MinTimeNano() > opt.StartTime { 728 subOpt.StartTime = t.MinTimeNano() 729 } 730 if !t.Max.IsZero() && t.MaxTimeNano() < opt.EndTime { 731 subOpt.EndTime = t.MaxTimeNano() 732 } 733 734 // Propagate the SLIMIT and SOFFSET from the outer query. 735 subOpt.SLimit += opt.SLimit 736 subOpt.SOffset += opt.SOffset 737 738 // Propagate the ordering from the parent query. 739 subOpt.Ascending = opt.Ascending 740 741 // If the inner query uses a null fill option and is not a raw query, 742 // switch it to none so we don't hit an unnecessary penalty from the 743 // fill iterator. Null values will end up getting stripped by an outer 744 // query anyway so there's no point in having them here. We still need 745 // all other types of fill iterators because they can affect the result 746 // of the outer query. We also do not do this for raw queries because 747 // there is no fill iterator for them and fill(none) doesn't work with 748 // raw queries. 749 if !stmt.IsRawQuery && subOpt.Fill == influxql.NullFill { 750 subOpt.Fill = influxql.NoFill 751 } 752 753 // Inherit the ordering method from the outer query. 754 subOpt.Ordered = opt.Ordered 755 756 // If there is no interval for this subquery, but the outer query has an 757 // interval, inherit the parent interval. 758 interval, err := stmt.GroupByInterval() 759 if err != nil { 760 return IteratorOptions{}, err 761 } else if interval == 0 { 762 subOpt.Interval = opt.Interval 763 } 764 return subOpt, nil 765 } 766 767 // MergeSorted returns true if the options require a sorted merge. 768 func (opt IteratorOptions) MergeSorted() bool { 769 return opt.Ordered 770 } 771 772 // SeekTime returns the time the iterator should start from. 773 // For ascending iterators this is the start time, for descending iterators it's the end time. 774 func (opt IteratorOptions) SeekTime() int64 { 775 if opt.Ascending { 776 return opt.StartTime 777 } 778 return opt.EndTime 779 } 780 781 // StopTime returns the time the iterator should end at. 782 // For ascending iterators this is the end time, for descending iterators it's the start time. 783 func (opt IteratorOptions) StopTime() int64 { 784 if opt.Ascending { 785 return opt.EndTime 786 } 787 return opt.StartTime 788 } 789 790 // Window returns the time window [start,end) that t falls within. 791 func (opt IteratorOptions) Window(t int64) (start, end int64) { 792 if opt.Interval.IsZero() { 793 return opt.StartTime, opt.EndTime + 1 794 } 795 796 // Subtract the offset to the time so we calculate the correct base interval. 797 t -= int64(opt.Interval.Offset) 798 799 // Retrieve the zone offset for the start time. 800 var zone int64 801 if opt.Location != nil { 802 _, zone = opt.Zone(t) 803 } 804 805 // Truncate time by duration. 806 dt := (t + zone) % int64(opt.Interval.Duration) 807 if dt < 0 { 808 // Negative modulo rounds up instead of down, so offset 809 // with the duration. 810 dt += int64(opt.Interval.Duration) 811 } 812 813 // Find the start time. 814 if influxql.MinTime+dt >= t { 815 start = influxql.MinTime 816 } else { 817 start = t - dt 818 } 819 820 start += int64(opt.Interval.Offset) 821 822 // Look for the start offset again because the first time may have been 823 // after the offset switch. Now that we are at midnight in UTC, we can 824 // lookup the zone offset again to get the real starting offset. 825 if opt.Location != nil { 826 _, startOffset := opt.Zone(start) 827 // Do not adjust the offset if the offset change is greater than or 828 // equal to the duration. 829 if o := zone - startOffset; o != 0 && abs(o) < int64(opt.Interval.Duration) { 830 start += o 831 } 832 } 833 834 // Find the end time. 835 if dt := int64(opt.Interval.Duration) - dt; influxql.MaxTime-dt <= t { 836 end = influxql.MaxTime 837 } else { 838 end = t + dt 839 } 840 841 // Retrieve the zone offset for the end time. 842 if opt.Location != nil { 843 _, endOffset := opt.Zone(end) 844 // Adjust the end time if the offset is different from the start offset. 845 // Only apply the offset if it is smaller than the duration. 846 // This prevents going back in time and creating time windows 847 // that don't make any sense. 848 if o := zone - endOffset; o != 0 && abs(o) < int64(opt.Interval.Duration) { 849 // If the offset is greater than 0, that means we are adding time. 850 // Added time goes into the previous interval because the clocks 851 // move backwards. If the offset is less than 0, then we are skipping 852 // time. Skipped time comes after the switch so if we have a time 853 // interval that lands on the switch, it comes from the next 854 // interval and not the current one. For this reason, we need to know 855 // when the actual switch happens by seeing if the time switch is within 856 // the current interval. We calculate the zone offset with the offset 857 // and see if the value is the same. If it is, we apply the 858 // offset. 859 if o > 0 { 860 end += o 861 } else if _, z := opt.Zone(end + o); z == endOffset { 862 end += o 863 } 864 } 865 } 866 end += int64(opt.Interval.Offset) 867 return 868 } 869 870 // DerivativeInterval returns the time interval for the derivative function. 871 func (opt IteratorOptions) DerivativeInterval() Interval { 872 // Use the interval on the derivative() call, if specified. 873 if expr, ok := opt.Expr.(*influxql.Call); ok && len(expr.Args) == 2 { 874 return Interval{Duration: expr.Args[1].(*influxql.DurationLiteral).Val} 875 } 876 877 // Otherwise use the group by interval, if specified. 878 if opt.Interval.Duration > 0 { 879 return Interval{Duration: opt.Interval.Duration} 880 } 881 882 return Interval{Duration: time.Second} 883 } 884 885 // ElapsedInterval returns the time interval for the elapsed function. 886 func (opt IteratorOptions) ElapsedInterval() Interval { 887 // Use the interval on the elapsed() call, if specified. 888 if expr, ok := opt.Expr.(*influxql.Call); ok && len(expr.Args) == 2 { 889 return Interval{Duration: expr.Args[1].(*influxql.DurationLiteral).Val} 890 } 891 892 return Interval{Duration: time.Nanosecond} 893 } 894 895 // IntegralInterval returns the time interval for the integral function. 896 func (opt IteratorOptions) IntegralInterval() Interval { 897 // Use the interval on the integral() call, if specified. 898 if expr, ok := opt.Expr.(*influxql.Call); ok && len(expr.Args) == 2 { 899 return Interval{Duration: expr.Args[1].(*influxql.DurationLiteral).Val} 900 } 901 902 return Interval{Duration: time.Second} 903 } 904 905 // GetDimensions retrieves the dimensions for this query. 906 func (opt IteratorOptions) GetDimensions() []string { 907 if len(opt.GroupBy) > 0 { 908 dimensions := make([]string, 0, len(opt.GroupBy)) 909 for dim := range opt.GroupBy { 910 dimensions = append(dimensions, dim) 911 } 912 return dimensions 913 } 914 return opt.Dimensions 915 } 916 917 // Zone returns the zone information for the given time. The offset is in nanoseconds. 918 func (opt *IteratorOptions) Zone(ns int64) (string, int64) { 919 if opt.Location == nil { 920 return "", 0 921 } 922 923 t := time.Unix(0, ns).In(opt.Location) 924 name, offset := t.Zone() 925 return name, secToNs * int64(offset) 926 } 927 928 // MarshalBinary encodes opt into a binary format. 929 func (opt *IteratorOptions) MarshalBinary() ([]byte, error) { 930 return proto.Marshal(encodeIteratorOptions(opt)) 931 } 932 933 // UnmarshalBinary decodes from a binary format in to opt. 934 func (opt *IteratorOptions) UnmarshalBinary(buf []byte) error { 935 var pb internal.IteratorOptions 936 if err := proto.Unmarshal(buf, &pb); err != nil { 937 return err 938 } 939 940 other, err := decodeIteratorOptions(&pb) 941 if err != nil { 942 return err 943 } 944 *opt = *other 945 946 return nil 947 } 948 949 func encodeIteratorOptions(opt *IteratorOptions) *internal.IteratorOptions { 950 pb := &internal.IteratorOptions{ 951 Interval: encodeInterval(opt.Interval), 952 Dimensions: opt.Dimensions, 953 Fill: proto.Int32(int32(opt.Fill)), 954 StartTime: proto.Int64(opt.StartTime), 955 EndTime: proto.Int64(opt.EndTime), 956 Ascending: proto.Bool(opt.Ascending), 957 Limit: proto.Int64(int64(opt.Limit)), 958 Offset: proto.Int64(int64(opt.Offset)), 959 SLimit: proto.Int64(int64(opt.SLimit)), 960 SOffset: proto.Int64(int64(opt.SOffset)), 961 StripName: proto.Bool(opt.StripName), 962 Dedupe: proto.Bool(opt.Dedupe), 963 MaxSeriesN: proto.Int64(int64(opt.MaxSeriesN)), 964 Ordered: proto.Bool(opt.Ordered), 965 } 966 967 // Set expression, if set. 968 if opt.Expr != nil { 969 pb.Expr = proto.String(opt.Expr.String()) 970 } 971 972 // Set the location, if set. 973 if opt.Location != nil { 974 pb.Location = proto.String(opt.Location.String()) 975 } 976 977 // Convert and encode aux fields as variable references. 978 if opt.Aux != nil { 979 pb.Fields = make([]*internal.VarRef, len(opt.Aux)) 980 pb.Aux = make([]string, len(opt.Aux)) 981 for i, ref := range opt.Aux { 982 pb.Fields[i] = encodeVarRef(ref) 983 pb.Aux[i] = ref.Val 984 } 985 } 986 987 // Encode group by dimensions from a map. 988 if opt.GroupBy != nil { 989 dimensions := make([]string, 0, len(opt.GroupBy)) 990 for dim := range opt.GroupBy { 991 dimensions = append(dimensions, dim) 992 } 993 pb.GroupBy = dimensions 994 } 995 996 // Convert and encode sources to measurements. 997 if opt.Sources != nil { 998 sources := make([]*internal.Measurement, len(opt.Sources)) 999 for i, source := range opt.Sources { 1000 mm := source.(*influxql.Measurement) 1001 sources[i] = encodeMeasurement(mm) 1002 } 1003 pb.Sources = sources 1004 } 1005 1006 // Fill value can only be a number. Set it if available. 1007 if v, ok := opt.FillValue.(float64); ok { 1008 pb.FillValue = proto.Float64(v) 1009 } 1010 1011 // Set condition, if set. 1012 if opt.Condition != nil { 1013 pb.Condition = proto.String(opt.Condition.String()) 1014 } 1015 1016 return pb 1017 } 1018 1019 func decodeIteratorOptions(pb *internal.IteratorOptions) (*IteratorOptions, error) { 1020 opt := &IteratorOptions{ 1021 Interval: decodeInterval(pb.GetInterval()), 1022 Dimensions: pb.GetDimensions(), 1023 Fill: influxql.FillOption(pb.GetFill()), 1024 StartTime: pb.GetStartTime(), 1025 EndTime: pb.GetEndTime(), 1026 Ascending: pb.GetAscending(), 1027 Limit: int(pb.GetLimit()), 1028 Offset: int(pb.GetOffset()), 1029 SLimit: int(pb.GetSLimit()), 1030 SOffset: int(pb.GetSOffset()), 1031 StripName: pb.GetStripName(), 1032 Dedupe: pb.GetDedupe(), 1033 MaxSeriesN: int(pb.GetMaxSeriesN()), 1034 Ordered: pb.GetOrdered(), 1035 } 1036 1037 // Set expression, if set. 1038 if pb.Expr != nil { 1039 expr, err := influxql.ParseExpr(pb.GetExpr()) 1040 if err != nil { 1041 return nil, err 1042 } 1043 opt.Expr = expr 1044 } 1045 1046 if pb.Location != nil { 1047 loc, err := time.LoadLocation(pb.GetLocation()) 1048 if err != nil { 1049 return nil, err 1050 } 1051 opt.Location = loc 1052 } 1053 1054 // Convert and decode variable references. 1055 if fields := pb.GetFields(); fields != nil { 1056 opt.Aux = make([]influxql.VarRef, len(fields)) 1057 for i, ref := range fields { 1058 opt.Aux[i] = decodeVarRef(ref) 1059 } 1060 } else if aux := pb.GetAux(); aux != nil { 1061 opt.Aux = make([]influxql.VarRef, len(aux)) 1062 for i, name := range aux { 1063 opt.Aux[i] = influxql.VarRef{Val: name} 1064 } 1065 } 1066 1067 // Convert and decode sources to measurements. 1068 if pb.Sources != nil { 1069 sources := make([]influxql.Source, len(pb.GetSources())) 1070 for i, source := range pb.GetSources() { 1071 mm, err := decodeMeasurement(source) 1072 if err != nil { 1073 return nil, err 1074 } 1075 sources[i] = mm 1076 } 1077 opt.Sources = sources 1078 } 1079 1080 // Convert group by dimensions to a map. 1081 if pb.GroupBy != nil { 1082 dimensions := make(map[string]struct{}, len(pb.GroupBy)) 1083 for _, dim := range pb.GetGroupBy() { 1084 dimensions[dim] = struct{}{} 1085 } 1086 opt.GroupBy = dimensions 1087 } 1088 1089 // Set the fill value, if set. 1090 if pb.FillValue != nil { 1091 opt.FillValue = pb.GetFillValue() 1092 } 1093 1094 // Set condition, if set. 1095 if pb.Condition != nil { 1096 expr, err := influxql.ParseExpr(pb.GetCondition()) 1097 if err != nil { 1098 return nil, err 1099 } 1100 opt.Condition = expr 1101 } 1102 1103 return opt, nil 1104 } 1105 1106 func encodeMeasurement(mm *influxql.Measurement) *internal.Measurement { 1107 pb := &internal.Measurement{ 1108 Database: proto.String(mm.Database), 1109 RetentionPolicy: proto.String(mm.RetentionPolicy), 1110 Name: proto.String(mm.Name), 1111 SystemIterator: proto.String(mm.SystemIterator), 1112 IsTarget: proto.Bool(mm.IsTarget), 1113 } 1114 if mm.Regex != nil { 1115 pb.Regex = proto.String(mm.Regex.Val.String()) 1116 } 1117 return pb 1118 } 1119 1120 func decodeMeasurement(pb *internal.Measurement) (*influxql.Measurement, error) { 1121 mm := &influxql.Measurement{ 1122 Database: pb.GetDatabase(), 1123 RetentionPolicy: pb.GetRetentionPolicy(), 1124 Name: pb.GetName(), 1125 SystemIterator: pb.GetSystemIterator(), 1126 IsTarget: pb.GetIsTarget(), 1127 } 1128 1129 if pb.Regex != nil { 1130 regex, err := regexp.Compile(pb.GetRegex()) 1131 if err != nil { 1132 return nil, fmt.Errorf("invalid binary measurement regex: value=%q, err=%s", pb.GetRegex(), err) 1133 } 1134 mm.Regex = &influxql.RegexLiteral{Val: regex} 1135 } 1136 1137 return mm, nil 1138 } 1139 1140 // Interval represents a repeating interval for a query. 1141 type Interval struct { 1142 Duration time.Duration 1143 Offset time.Duration 1144 } 1145 1146 // IsZero returns true if the interval has no duration. 1147 func (i Interval) IsZero() bool { return i.Duration == 0 } 1148 1149 func encodeInterval(i Interval) *internal.Interval { 1150 return &internal.Interval{ 1151 Duration: proto.Int64(i.Duration.Nanoseconds()), 1152 Offset: proto.Int64(i.Offset.Nanoseconds()), 1153 } 1154 } 1155 1156 func decodeInterval(pb *internal.Interval) Interval { 1157 return Interval{ 1158 Duration: time.Duration(pb.GetDuration()), 1159 Offset: time.Duration(pb.GetOffset()), 1160 } 1161 } 1162 1163 func encodeVarRef(ref influxql.VarRef) *internal.VarRef { 1164 return &internal.VarRef{ 1165 Val: proto.String(ref.Val), 1166 Type: proto.Int32(int32(ref.Type)), 1167 } 1168 } 1169 1170 func decodeVarRef(pb *internal.VarRef) influxql.VarRef { 1171 return influxql.VarRef{ 1172 Val: pb.GetVal(), 1173 Type: influxql.DataType(pb.GetType()), 1174 } 1175 } 1176 1177 type nilFloatIterator struct{} 1178 1179 func (*nilFloatIterator) Stats() IteratorStats { return IteratorStats{} } 1180 func (*nilFloatIterator) Close() error { return nil } 1181 func (*nilFloatIterator) Next() (*FloatPoint, error) { return nil, nil } 1182 1183 type nilFloatReaderIterator struct { 1184 r io.Reader 1185 } 1186 1187 func (*nilFloatReaderIterator) Stats() IteratorStats { return IteratorStats{} } 1188 func (itr *nilFloatReaderIterator) Close() error { 1189 if r, ok := itr.r.(io.ReadCloser); ok { 1190 itr.r = nil 1191 return r.Close() 1192 } 1193 return nil 1194 } 1195 func (*nilFloatReaderIterator) Next() (*FloatPoint, error) { return nil, nil } 1196 1197 // IteratorStats represents statistics about an iterator. 1198 // Some statistics are available immediately upon iterator creation while 1199 // some are derived as the iterator processes data. 1200 type IteratorStats struct { 1201 SeriesN int // series represented 1202 PointN int // points returned 1203 } 1204 1205 // Add aggregates fields from s and other together. Overwrites s. 1206 func (s *IteratorStats) Add(other IteratorStats) { 1207 s.SeriesN += other.SeriesN 1208 s.PointN += other.PointN 1209 } 1210 1211 func encodeIteratorStats(stats *IteratorStats) *internal.IteratorStats { 1212 return &internal.IteratorStats{ 1213 SeriesN: proto.Int64(int64(stats.SeriesN)), 1214 PointN: proto.Int64(int64(stats.PointN)), 1215 } 1216 } 1217 1218 func decodeIteratorStats(pb *internal.IteratorStats) IteratorStats { 1219 return IteratorStats{ 1220 SeriesN: int(pb.GetSeriesN()), 1221 PointN: int(pb.GetPointN()), 1222 } 1223 } 1224 1225 // IteratorCost contains statistics retrieved for explaining what potential 1226 // cost may be incurred by instantiating an iterator. 1227 type IteratorCost struct { 1228 // The total number of shards that are touched by this query. 1229 NumShards int64 1230 1231 // The total number of non-unique series that are accessed by this query. 1232 // This number matches the number of cursors created by the query since 1233 // one cursor is created for every series. 1234 NumSeries int64 1235 1236 // CachedValues returns the number of cached values that may be read by this 1237 // query. 1238 CachedValues int64 1239 1240 // The total number of non-unique files that may be accessed by this query. 1241 // This will count the number of files accessed by each series so files 1242 // will likely be double counted. 1243 NumFiles int64 1244 1245 // The number of blocks that had the potential to be accessed. 1246 BlocksRead int64 1247 1248 // The amount of data that can be potentially read. 1249 BlockSize int64 1250 } 1251 1252 // Combine combines the results of two IteratorCost structures into one. 1253 func (c IteratorCost) Combine(other IteratorCost) IteratorCost { 1254 return IteratorCost{ 1255 NumShards: c.NumShards + other.NumShards, 1256 NumSeries: c.NumSeries + other.NumSeries, 1257 CachedValues: c.CachedValues + other.CachedValues, 1258 NumFiles: c.NumFiles + other.NumFiles, 1259 BlocksRead: c.BlocksRead + other.BlocksRead, 1260 BlockSize: c.BlockSize + other.BlockSize, 1261 } 1262 } 1263 1264 // floatFastDedupeIterator outputs unique points where the point has a single aux field. 1265 type floatFastDedupeIterator struct { 1266 input FloatIterator 1267 m map[fastDedupeKey]struct{} // lookup of points already sent 1268 } 1269 1270 // newFloatFastDedupeIterator returns a new instance of floatFastDedupeIterator. 1271 func newFloatFastDedupeIterator(input FloatIterator) *floatFastDedupeIterator { 1272 return &floatFastDedupeIterator{ 1273 input: input, 1274 m: make(map[fastDedupeKey]struct{}), 1275 } 1276 } 1277 1278 // Stats returns stats from the input iterator. 1279 func (itr *floatFastDedupeIterator) Stats() IteratorStats { return itr.input.Stats() } 1280 1281 // Close closes the iterator and all child iterators. 1282 func (itr *floatFastDedupeIterator) Close() error { return itr.input.Close() } 1283 1284 // Next returns the next unique point from the input iterator. 1285 func (itr *floatFastDedupeIterator) Next() (*FloatPoint, error) { 1286 for { 1287 // Read next point. 1288 // Skip if there are not any aux fields. 1289 p, err := itr.input.Next() 1290 if p == nil || err != nil { 1291 return nil, err 1292 } else if len(p.Aux) == 0 { 1293 continue 1294 } 1295 1296 // If the point has already been output then move to the next point. 1297 key := fastDedupeKey{name: p.Name} 1298 key.values[0] = p.Aux[0] 1299 if len(p.Aux) > 1 { 1300 key.values[1] = p.Aux[1] 1301 } 1302 if _, ok := itr.m[key]; ok { 1303 continue 1304 } 1305 1306 // Otherwise mark it as emitted and return point. 1307 itr.m[key] = struct{}{} 1308 return p, nil 1309 } 1310 } 1311 1312 type fastDedupeKey struct { 1313 name string 1314 values [2]interface{} 1315 } 1316 1317 func abs(v int64) int64 { 1318 sign := v >> 63 1319 return (v ^ sign) - sign 1320 } 1321 1322 // IteratorEncoder is an encoder for encoding an iterator's points to w. 1323 type IteratorEncoder struct { 1324 w io.Writer 1325 1326 // Frequency with which stats are emitted. 1327 StatsInterval time.Duration 1328 } 1329 1330 // NewIteratorEncoder encodes an iterator's points to w. 1331 func NewIteratorEncoder(w io.Writer) *IteratorEncoder { 1332 return &IteratorEncoder{ 1333 w: w, 1334 1335 StatsInterval: DefaultStatsInterval, 1336 } 1337 } 1338 1339 // EncodeIterator encodes and writes all of itr's points to the underlying writer. 1340 func (enc *IteratorEncoder) EncodeIterator(itr Iterator) error { 1341 switch itr := itr.(type) { 1342 case FloatIterator: 1343 return enc.encodeFloatIterator(itr) 1344 case IntegerIterator: 1345 return enc.encodeIntegerIterator(itr) 1346 case StringIterator: 1347 return enc.encodeStringIterator(itr) 1348 case BooleanIterator: 1349 return enc.encodeBooleanIterator(itr) 1350 default: 1351 panic(fmt.Sprintf("unsupported iterator for encoder: %T", itr)) 1352 } 1353 } 1354 1355 // encode a stats object in the point stream. 1356 func (enc *IteratorEncoder) encodeStats(stats IteratorStats) error { 1357 buf, err := proto.Marshal(&internal.Point{ 1358 Name: proto.String(""), 1359 Tags: proto.String(""), 1360 Time: proto.Int64(0), 1361 Nil: proto.Bool(false), 1362 1363 Stats: encodeIteratorStats(&stats), 1364 }) 1365 if err != nil { 1366 return err 1367 } 1368 1369 if err = binary.Write(enc.w, binary.BigEndian, uint32(len(buf))); err != nil { 1370 return err 1371 } 1372 if _, err = enc.w.Write(buf); err != nil { 1373 return err 1374 } 1375 return nil 1376 }