github.com/influxdata/influxdb/v2@v2.7.6/influxql/query/select.go (about) 1 package query 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 "sort" 8 "sync" 9 "time" 10 11 iql "github.com/influxdata/influxdb/v2/influxql" 12 "github.com/influxdata/influxdb/v2/influxql/query/internal/gota" 13 "github.com/influxdata/influxdb/v2/kit/platform" 14 "github.com/influxdata/influxql" 15 "golang.org/x/sync/errgroup" 16 ) 17 18 var DefaultTypeMapper = influxql.MultiTypeMapper( 19 FunctionTypeMapper{}, 20 MathTypeMapper{}, 21 ) 22 23 // SelectOptions are options that customize the select call. 24 type SelectOptions struct { 25 // OrgID is the organization for which this query is being executed. 26 OrgID platform.ID 27 28 // Node to exclusively read from. 29 // If zero, all nodes are used. 30 NodeID uint64 31 32 // Maximum number of concurrent series. 33 MaxSeriesN int 34 35 // Maximum number of points to read from the query. 36 // This requires the passed in context to have a Monitor that is 37 // created using WithMonitor. 38 MaxPointN int 39 40 // Maximum number of buckets for a statement. 41 MaxBucketsN int 42 43 // StatisticsGatherer gathers metrics about the execution of the query. 44 StatisticsGatherer *iql.StatisticsGatherer 45 } 46 47 // ShardMapper retrieves and maps shards into an IteratorCreator that can later be 48 // used for executing queries. 49 type ShardMapper interface { 50 MapShards(ctx context.Context, sources influxql.Sources, t influxql.TimeRange, opt SelectOptions) (ShardGroup, error) 51 } 52 53 // TypeMapper maps a data type to the measurement and field. 54 type TypeMapper interface { 55 MapType(ctx context.Context, m *influxql.Measurement, field string) influxql.DataType 56 } 57 58 // FieldMapper returns the data type for the field inside of the measurement. 59 type FieldMapper interface { 60 TypeMapper 61 FieldDimensions(ctx context.Context, m *influxql.Measurement) (fields map[string]influxql.DataType, dimensions map[string]struct{}, err error) 62 } 63 64 // contextFieldMapper adapts a FieldMapper to an influxql.FieldMapper as 65 // FieldMapper requires a context.Context and orgID 66 type fieldMapperAdapter struct { 67 fm FieldMapper 68 ctx context.Context 69 } 70 71 func newFieldMapperAdapter(fm FieldMapper, ctx context.Context) *fieldMapperAdapter { 72 return &fieldMapperAdapter{fm: fm, ctx: ctx} 73 } 74 75 func (c *fieldMapperAdapter) FieldDimensions(m *influxql.Measurement) (fields map[string]influxql.DataType, dimensions map[string]struct{}, err error) { 76 return c.fm.FieldDimensions(c.ctx, m) 77 } 78 79 func (c *fieldMapperAdapter) MapType(measurement *influxql.Measurement, field string) influxql.DataType { 80 return c.fm.MapType(c.ctx, measurement, field) 81 } 82 83 // ShardGroup represents a shard or a collection of shards that can be accessed 84 // for creating iterators. 85 // When creating iterators, the resource used for reading the iterators should be 86 // separate from the resource used to map the shards. When the ShardGroup is closed, 87 // it should not close any resources associated with the created Iterator. Those 88 // resources belong to the Iterator and will be closed when the Iterator itself is 89 // closed. 90 // The query engine operates under this assumption and will close the shard group 91 // after creating the iterators, but before the iterators are actually read. 92 type ShardGroup interface { 93 IteratorCreator 94 FieldMapper 95 io.Closer 96 } 97 98 // Select is a prepared statement that is ready to be executed. 99 type PreparedStatement interface { 100 // Select creates the Iterators that will be used to read the query. 101 Select(ctx context.Context) (Cursor, error) 102 103 // Explain outputs the explain plan for this statement. 104 Explain(ctx context.Context) (string, error) 105 106 // Close closes the resources associated with this prepared statement. 107 // This must be called as the mapped shards may hold open resources such 108 // as network connections. 109 Close() error 110 } 111 112 // Prepare will compile the statement with the default compile options and 113 // then prepare the query. 114 func Prepare(ctx context.Context, stmt *influxql.SelectStatement, shardMapper ShardMapper, opt SelectOptions) (PreparedStatement, error) { 115 c, err := Compile(stmt, CompileOptions{}) 116 if err != nil { 117 return nil, err 118 } 119 return c.Prepare(ctx, shardMapper, opt) 120 } 121 122 // Select compiles, prepares, and then initiates execution of the query using the 123 // default compile options. 124 func Select(ctx context.Context, stmt *influxql.SelectStatement, shardMapper ShardMapper, opt SelectOptions) (Cursor, error) { 125 s, err := Prepare(ctx, stmt, shardMapper, opt) 126 if err != nil { 127 return nil, err 128 } 129 // Must be deferred so it runs after Select. 130 defer s.Close() 131 return s.Select(ctx) 132 } 133 134 type preparedStatement struct { 135 stmt *influxql.SelectStatement 136 opt IteratorOptions 137 ic interface { 138 IteratorCreator 139 io.Closer 140 } 141 columns []string 142 maxPointN int 143 now time.Time 144 } 145 146 type contextKey string 147 148 const nowKey contextKey = "now" 149 150 func (p *preparedStatement) Select(ctx context.Context) (Cursor, error) { 151 // TODO(jsternberg): Remove this hacky method of propagating now. 152 // Each level of the query should use a time range discovered during 153 // compilation, but that requires too large of a refactor at the moment. 154 ctx = context.WithValue(ctx, nowKey, p.now) 155 156 opt := p.opt 157 opt.InterruptCh = ctx.Done() 158 cur, err := buildCursor(ctx, p.stmt, p.ic, opt) 159 if err != nil { 160 return nil, err 161 } 162 163 return cur, nil 164 } 165 166 func (p *preparedStatement) Close() error { 167 return p.ic.Close() 168 } 169 170 // buildExprIterator creates an iterator for an expression. 171 func buildExprIterator(ctx context.Context, expr influxql.Expr, ic IteratorCreator, sources influxql.Sources, opt IteratorOptions, selector, writeMode bool) (Iterator, error) { 172 opt.Expr = expr 173 b := exprIteratorBuilder{ 174 ic: ic, 175 sources: sources, 176 opt: opt, 177 selector: selector, 178 writeMode: writeMode, 179 } 180 181 switch expr := expr.(type) { 182 case *influxql.VarRef: 183 return b.buildVarRefIterator(ctx, expr) 184 case *influxql.Call: 185 return b.buildCallIterator(ctx, expr) 186 default: 187 return nil, fmt.Errorf("invalid expression type: %T", expr) 188 } 189 } 190 191 type exprIteratorBuilder struct { 192 ic IteratorCreator 193 sources influxql.Sources 194 opt IteratorOptions 195 selector bool 196 writeMode bool 197 } 198 199 func (b *exprIteratorBuilder) buildVarRefIterator(ctx context.Context, expr *influxql.VarRef) (Iterator, error) { 200 inputs := make([]Iterator, 0, len(b.sources)) 201 if err := func() error { 202 for _, source := range b.sources { 203 switch source := source.(type) { 204 case *influxql.Measurement: 205 input, err := b.ic.CreateIterator(ctx, source, b.opt) 206 if err != nil { 207 return err 208 } 209 inputs = append(inputs, input) 210 case *influxql.SubQuery: 211 subquery := subqueryBuilder{ 212 ic: b.ic, 213 stmt: source.Statement, 214 } 215 216 input, err := subquery.buildVarRefIterator(ctx, expr, b.opt) 217 if err != nil { 218 return err 219 } else if input != nil { 220 inputs = append(inputs, input) 221 } 222 } 223 } 224 return nil 225 }(); err != nil { 226 Iterators(inputs).Close() 227 return nil, err 228 } 229 230 // Variable references in this section will always go into some call 231 // iterator. Combine it with a merge iterator. 232 itr := NewMergeIterator(inputs, b.opt) 233 if itr == nil { 234 itr = &nilFloatIterator{} 235 } 236 237 if b.opt.InterruptCh != nil { 238 itr = NewInterruptIterator(itr, b.opt.InterruptCh) 239 } 240 return itr, nil 241 } 242 243 func (b *exprIteratorBuilder) buildCallIterator(ctx context.Context, expr *influxql.Call) (Iterator, error) { 244 // TODO(jsternberg): Refactor this. This section needs to die in a fire. 245 opt := b.opt 246 // Eliminate limits and offsets if they were previously set. These are handled by the caller. 247 opt.Limit, opt.Offset = 0, 0 248 switch expr.Name { 249 case "distinct": 250 opt.Ordered = true 251 input, err := buildExprIterator(ctx, expr.Args[0].(*influxql.VarRef), b.ic, b.sources, opt, b.selector, false) 252 if err != nil { 253 return nil, err 254 } 255 input, err = NewDistinctIterator(input, opt) 256 if err != nil { 257 return nil, err 258 } 259 return NewIntervalIterator(input, opt), nil 260 case "sample": 261 opt.Ordered = true 262 input, err := buildExprIterator(ctx, expr.Args[0], b.ic, b.sources, opt, b.selector, false) 263 if err != nil { 264 return nil, err 265 } 266 size := expr.Args[1].(*influxql.IntegerLiteral) 267 268 return newSampleIterator(input, opt, int(size.Val)) 269 case "holt_winters", "holt_winters_with_fit": 270 opt.Ordered = true 271 input, err := buildExprIterator(ctx, expr.Args[0], b.ic, b.sources, opt, b.selector, false) 272 if err != nil { 273 return nil, err 274 } 275 h := expr.Args[1].(*influxql.IntegerLiteral) 276 m := expr.Args[2].(*influxql.IntegerLiteral) 277 278 includeFitData := expr.Name == "holt_winters_with_fit" 279 280 interval := opt.Interval.Duration 281 // Redefine interval to be unbounded to capture all aggregate results 282 opt.StartTime = influxql.MinTime 283 opt.EndTime = influxql.MaxTime 284 opt.Interval = Interval{} 285 286 return newHoltWintersIterator(input, opt, int(h.Val), int(m.Val), includeFitData, interval) 287 case "count_hll", "derivative", "non_negative_derivative", "difference", "non_negative_difference", "moving_average", "exponential_moving_average", "double_exponential_moving_average", "triple_exponential_moving_average", "relative_strength_index", "triple_exponential_derivative", "kaufmans_efficiency_ratio", "kaufmans_adaptive_moving_average", "chande_momentum_oscillator", "elapsed": 288 if !opt.Interval.IsZero() { 289 if opt.Ascending { 290 opt.StartTime -= int64(opt.Interval.Duration) 291 } else { 292 opt.EndTime += int64(opt.Interval.Duration) 293 } 294 } 295 opt.Ordered = true 296 297 input, err := buildExprIterator(ctx, expr.Args[0], b.ic, b.sources, opt, b.selector, false) 298 if err != nil { 299 return nil, err 300 } 301 302 switch expr.Name { 303 case "count_hll": 304 return NewCountHllIterator(input, opt) 305 case "derivative", "non_negative_derivative": 306 interval := opt.DerivativeInterval() 307 isNonNegative := (expr.Name == "non_negative_derivative") 308 return newDerivativeIterator(input, opt, interval, isNonNegative) 309 case "elapsed": 310 interval := opt.ElapsedInterval() 311 return newElapsedIterator(input, opt, interval) 312 case "difference", "non_negative_difference": 313 isNonNegative := (expr.Name == "non_negative_difference") 314 return newDifferenceIterator(input, opt, isNonNegative) 315 case "moving_average": 316 n := expr.Args[1].(*influxql.IntegerLiteral) 317 if n.Val > 1 && !opt.Interval.IsZero() { 318 if opt.Ascending { 319 opt.StartTime -= int64(opt.Interval.Duration) * (n.Val - 1) 320 } else { 321 opt.EndTime += int64(opt.Interval.Duration) * (n.Val - 1) 322 } 323 } 324 return newMovingAverageIterator(input, int(n.Val), opt) 325 case "exponential_moving_average", "double_exponential_moving_average", "triple_exponential_moving_average", "relative_strength_index", "triple_exponential_derivative": 326 n := expr.Args[1].(*influxql.IntegerLiteral) 327 if n.Val > 1 && !opt.Interval.IsZero() { 328 if opt.Ascending { 329 opt.StartTime -= int64(opt.Interval.Duration) * (n.Val - 1) 330 } else { 331 opt.EndTime += int64(opt.Interval.Duration) * (n.Val - 1) 332 } 333 } 334 335 nHold := -1 336 if len(expr.Args) >= 3 { 337 nHold = int(expr.Args[2].(*influxql.IntegerLiteral).Val) 338 } 339 340 warmupType := gota.WarmEMA 341 if len(expr.Args) >= 4 { 342 if warmupType, err = gota.ParseWarmupType(expr.Args[3].(*influxql.StringLiteral).Val); err != nil { 343 return nil, err 344 } 345 } 346 347 switch expr.Name { 348 case "exponential_moving_average": 349 return newExponentialMovingAverageIterator(input, int(n.Val), nHold, warmupType, opt) 350 case "double_exponential_moving_average": 351 return newDoubleExponentialMovingAverageIterator(input, int(n.Val), nHold, warmupType, opt) 352 case "triple_exponential_moving_average": 353 return newTripleExponentialMovingAverageIterator(input, int(n.Val), nHold, warmupType, opt) 354 case "relative_strength_index": 355 return newRelativeStrengthIndexIterator(input, int(n.Val), nHold, warmupType, opt) 356 case "triple_exponential_derivative": 357 return newTripleExponentialDerivativeIterator(input, int(n.Val), nHold, warmupType, opt) 358 } 359 case "kaufmans_efficiency_ratio", "kaufmans_adaptive_moving_average": 360 n := expr.Args[1].(*influxql.IntegerLiteral) 361 if n.Val > 1 && !opt.Interval.IsZero() { 362 if opt.Ascending { 363 opt.StartTime -= int64(opt.Interval.Duration) * (n.Val - 1) 364 } else { 365 opt.EndTime += int64(opt.Interval.Duration) * (n.Val - 1) 366 } 367 } 368 369 nHold := -1 370 if len(expr.Args) >= 3 { 371 nHold = int(expr.Args[2].(*influxql.IntegerLiteral).Val) 372 } 373 374 switch expr.Name { 375 case "kaufmans_efficiency_ratio": 376 return newKaufmansEfficiencyRatioIterator(input, int(n.Val), nHold, opt) 377 case "kaufmans_adaptive_moving_average": 378 return newKaufmansAdaptiveMovingAverageIterator(input, int(n.Val), nHold, opt) 379 } 380 case "chande_momentum_oscillator": 381 n := expr.Args[1].(*influxql.IntegerLiteral) 382 if n.Val > 1 && !opt.Interval.IsZero() { 383 if opt.Ascending { 384 opt.StartTime -= int64(opt.Interval.Duration) * (n.Val - 1) 385 } else { 386 opt.EndTime += int64(opt.Interval.Duration) * (n.Val - 1) 387 } 388 } 389 390 nHold := -1 391 if len(expr.Args) >= 3 { 392 nHold = int(expr.Args[2].(*influxql.IntegerLiteral).Val) 393 } 394 395 warmupType := gota.WarmupType(-1) 396 if len(expr.Args) >= 4 { 397 wt := expr.Args[3].(*influxql.StringLiteral).Val 398 if wt != "none" { 399 if warmupType, err = gota.ParseWarmupType(wt); err != nil { 400 return nil, err 401 } 402 } 403 } 404 405 return newChandeMomentumOscillatorIterator(input, int(n.Val), nHold, warmupType, opt) 406 } 407 panic(fmt.Sprintf("invalid series aggregate function: %s", expr.Name)) 408 case "cumulative_sum": 409 opt.Ordered = true 410 input, err := buildExprIterator(ctx, expr.Args[0], b.ic, b.sources, opt, b.selector, false) 411 if err != nil { 412 return nil, err 413 } 414 return newCumulativeSumIterator(input, opt) 415 case "integral": 416 opt.Ordered = true 417 input, err := buildExprIterator(ctx, expr.Args[0].(*influxql.VarRef), b.ic, b.sources, opt, false, false) 418 if err != nil { 419 return nil, err 420 } 421 interval := opt.IntegralInterval() 422 return newIntegralIterator(input, opt, interval) 423 case "top": 424 if len(expr.Args) < 2 { 425 return nil, fmt.Errorf("top() requires 2 or more arguments, got %d", len(expr.Args)) 426 } 427 428 var input Iterator 429 if len(expr.Args) > 2 { 430 // Create a max iterator using the groupings in the arguments. 431 dims := make(map[string]struct{}, len(expr.Args)-2+len(opt.GroupBy)) 432 for i := 1; i < len(expr.Args)-1; i++ { 433 ref := expr.Args[i].(*influxql.VarRef) 434 dims[ref.Val] = struct{}{} 435 } 436 for dim := range opt.GroupBy { 437 dims[dim] = struct{}{} 438 } 439 440 call := &influxql.Call{ 441 Name: "max", 442 Args: expr.Args[:1], 443 } 444 callOpt := opt 445 callOpt.Expr = call 446 callOpt.GroupBy = dims 447 callOpt.Fill = influxql.NoFill 448 449 builder := *b 450 builder.opt = callOpt 451 builder.selector = true 452 builder.writeMode = false 453 454 i, err := builder.callIterator(ctx, call, callOpt) 455 if err != nil { 456 return nil, err 457 } 458 input = i 459 } else { 460 // There are no arguments so do not organize the points by tags. 461 builder := *b 462 builder.opt.Expr = expr.Args[0] 463 builder.selector = true 464 builder.writeMode = false 465 466 ref := expr.Args[0].(*influxql.VarRef) 467 i, err := builder.buildVarRefIterator(ctx, ref) 468 if err != nil { 469 return nil, err 470 } 471 input = i 472 } 473 474 n := expr.Args[len(expr.Args)-1].(*influxql.IntegerLiteral) 475 return newTopIterator(input, opt, int(n.Val), b.writeMode) 476 case "bottom": 477 if len(expr.Args) < 2 { 478 return nil, fmt.Errorf("bottom() requires 2 or more arguments, got %d", len(expr.Args)) 479 } 480 481 var input Iterator 482 if len(expr.Args) > 2 { 483 // Create a max iterator using the groupings in the arguments. 484 dims := make(map[string]struct{}, len(expr.Args)-2) 485 for i := 1; i < len(expr.Args)-1; i++ { 486 ref := expr.Args[i].(*influxql.VarRef) 487 dims[ref.Val] = struct{}{} 488 } 489 for dim := range opt.GroupBy { 490 dims[dim] = struct{}{} 491 } 492 493 call := &influxql.Call{ 494 Name: "min", 495 Args: expr.Args[:1], 496 } 497 callOpt := opt 498 callOpt.Expr = call 499 callOpt.GroupBy = dims 500 callOpt.Fill = influxql.NoFill 501 502 builder := *b 503 builder.opt = callOpt 504 builder.selector = true 505 builder.writeMode = false 506 507 i, err := builder.callIterator(ctx, call, callOpt) 508 if err != nil { 509 return nil, err 510 } 511 input = i 512 } else { 513 // There are no arguments so do not organize the points by tags. 514 builder := *b 515 builder.opt.Expr = expr.Args[0] 516 builder.selector = true 517 builder.writeMode = false 518 519 ref := expr.Args[0].(*influxql.VarRef) 520 i, err := builder.buildVarRefIterator(ctx, ref) 521 if err != nil { 522 return nil, err 523 } 524 input = i 525 } 526 527 n := expr.Args[len(expr.Args)-1].(*influxql.IntegerLiteral) 528 return newBottomIterator(input, b.opt, int(n.Val), b.writeMode) 529 } 530 531 itr, err := func() (Iterator, error) { 532 switch expr.Name { 533 case "count": 534 switch arg0 := expr.Args[0].(type) { 535 case *influxql.Call: 536 if arg0.Name == "distinct" { 537 input, err := buildExprIterator(ctx, arg0, b.ic, b.sources, opt, b.selector, false) 538 if err != nil { 539 return nil, err 540 } 541 return newCountIterator(input, opt) 542 } 543 } 544 fallthrough 545 case "min", "max", "sum", "first", "last", "mean", "sum_hll", "merge_hll": 546 return b.callIterator(ctx, expr, opt) 547 case "median": 548 opt.Ordered = true 549 input, err := buildExprIterator(ctx, expr.Args[0].(*influxql.VarRef), b.ic, b.sources, opt, false, false) 550 if err != nil { 551 return nil, err 552 } 553 return newMedianIterator(input, opt) 554 case "mode": 555 input, err := buildExprIterator(ctx, expr.Args[0].(*influxql.VarRef), b.ic, b.sources, opt, false, false) 556 if err != nil { 557 return nil, err 558 } 559 return NewModeIterator(input, opt) 560 case "stddev": 561 input, err := buildExprIterator(ctx, expr.Args[0].(*influxql.VarRef), b.ic, b.sources, opt, false, false) 562 if err != nil { 563 return nil, err 564 } 565 return newStddevIterator(input, opt) 566 case "spread": 567 // OPTIMIZE(benbjohnson): convert to map/reduce 568 input, err := buildExprIterator(ctx, expr.Args[0].(*influxql.VarRef), b.ic, b.sources, opt, false, false) 569 if err != nil { 570 return nil, err 571 } 572 return newSpreadIterator(input, opt) 573 case "percentile": 574 opt.Ordered = true 575 input, err := buildExprIterator(ctx, expr.Args[0].(*influxql.VarRef), b.ic, b.sources, opt, false, false) 576 if err != nil { 577 return nil, err 578 } 579 var percentile float64 580 switch arg := expr.Args[1].(type) { 581 case *influxql.NumberLiteral: 582 percentile = arg.Val 583 case *influxql.IntegerLiteral: 584 percentile = float64(arg.Val) 585 } 586 return newPercentileIterator(input, opt, percentile) 587 default: 588 return nil, fmt.Errorf("unsupported call: %s", expr.Name) 589 } 590 }() 591 592 if err != nil { 593 return nil, err 594 } 595 596 if !b.selector || !opt.Interval.IsZero() { 597 itr = NewIntervalIterator(itr, opt) 598 if !opt.Interval.IsZero() && opt.Fill != influxql.NoFill { 599 itr = NewFillIterator(itr, expr, opt) 600 } 601 } 602 if opt.InterruptCh != nil { 603 itr = NewInterruptIterator(itr, opt.InterruptCh) 604 } 605 return itr, nil 606 } 607 608 func (b *exprIteratorBuilder) callIterator(ctx context.Context, expr *influxql.Call, opt IteratorOptions) (Iterator, error) { 609 inputs := make([]Iterator, 0, len(b.sources)) 610 if err := func() error { 611 for _, source := range b.sources { 612 switch source := source.(type) { 613 case *influxql.Measurement: 614 input, err := b.ic.CreateIterator(ctx, source, opt) 615 if err != nil { 616 return err 617 } 618 inputs = append(inputs, input) 619 case *influxql.SubQuery: 620 // Identify the name of the field we are using. 621 arg0 := expr.Args[0].(*influxql.VarRef) 622 623 opt.Ordered = false 624 input, err := buildExprIterator(ctx, arg0, b.ic, []influxql.Source{source}, opt, b.selector, false) 625 if err != nil { 626 return err 627 } 628 629 // Wrap the result in a call iterator. 630 i, err := NewCallIterator(input, opt) 631 if err != nil { 632 input.Close() 633 return err 634 } 635 inputs = append(inputs, i) 636 } 637 } 638 return nil 639 }(); err != nil { 640 Iterators(inputs).Close() 641 return nil, err 642 } 643 644 itr, err := Iterators(inputs).Merge(opt) 645 if err != nil { 646 Iterators(inputs).Close() 647 return nil, err 648 } else if itr == nil { 649 itr = &nilFloatIterator{} 650 } 651 return itr, nil 652 } 653 654 func buildCursor(ctx context.Context, stmt *influxql.SelectStatement, ic IteratorCreator, opt IteratorOptions) (Cursor, error) { 655 switch opt.Fill { 656 case influxql.NumberFill: 657 if v, ok := opt.FillValue.(int); ok { 658 opt.FillValue = int64(v) 659 } 660 case influxql.PreviousFill: 661 opt.FillValue = SkipDefault 662 } 663 664 fields := make([]*influxql.Field, 0, len(stmt.Fields)+1) 665 if !stmt.OmitTime { 666 // Add a field with the variable "time" if we have not omitted time. 667 fields = append(fields, &influxql.Field{ 668 Expr: &influxql.VarRef{ 669 Val: "time", 670 Type: influxql.Time, 671 }, 672 }) 673 } 674 675 // Iterate through each of the fields to add them to the value mapper. 676 valueMapper := newValueMapper() 677 for _, f := range stmt.Fields { 678 fields = append(fields, valueMapper.Map(f)) 679 680 // If the field is a top() or bottom() call, we need to also add 681 // the extra variables if we are not writing into a target. 682 if stmt.Target != nil { 683 continue 684 } 685 686 switch expr := f.Expr.(type) { 687 case *influxql.Call: 688 if expr.Name == "top" || expr.Name == "bottom" { 689 for i := 1; i < len(expr.Args)-1; i++ { 690 nf := influxql.Field{Expr: expr.Args[i]} 691 fields = append(fields, valueMapper.Map(&nf)) 692 } 693 } 694 } 695 } 696 697 // Set the aliases on each of the columns to what the final name should be. 698 columns := stmt.ColumnNames() 699 for i, f := range fields { 700 f.Alias = columns[i] 701 } 702 703 // Retrieve the refs to retrieve the auxiliary fields. 704 var auxKeys []influxql.VarRef 705 if len(valueMapper.refs) > 0 { 706 opt.Aux = make([]influxql.VarRef, 0, len(valueMapper.refs)) 707 for ref := range valueMapper.refs { 708 opt.Aux = append(opt.Aux, *ref) 709 } 710 sort.Sort(influxql.VarRefs(opt.Aux)) 711 712 auxKeys = make([]influxql.VarRef, len(opt.Aux)) 713 for i, ref := range opt.Aux { 714 auxKeys[i] = valueMapper.symbols[ref.String()] 715 } 716 } 717 718 // If there are no calls, then produce an auxiliary cursor. 719 if len(valueMapper.calls) == 0 { 720 // If all of the auxiliary keys are of an unknown type, 721 // do not construct the iterator and return a null cursor. 722 if !hasValidType(auxKeys) { 723 return newNullCursor(fields), nil 724 } 725 726 itr, err := buildAuxIterator(ctx, ic, stmt.Sources, opt) 727 if err != nil { 728 return nil, err 729 } 730 731 // Create a slice with an empty first element. 732 keys := []influxql.VarRef{{}} 733 keys = append(keys, auxKeys...) 734 735 scanner := NewIteratorScanner(itr, keys, opt.FillValue) 736 return newScannerCursor(scanner, fields, opt), nil 737 } 738 739 // Check to see if this is a selector statement. 740 // It is a selector if it is the only selector call and the call itself 741 // is a selector. 742 selector := len(valueMapper.calls) == 1 743 if selector { 744 for call := range valueMapper.calls { 745 if !influxql.IsSelector(call) { 746 selector = false 747 } 748 } 749 } 750 751 // Produce an iterator for every single call and create an iterator scanner 752 // associated with it. 753 var g errgroup.Group 754 var mu sync.Mutex 755 scanners := make([]IteratorScanner, 0, len(valueMapper.calls)) 756 for call := range valueMapper.calls { 757 call := call 758 759 driver := valueMapper.table[call] 760 if driver.Type == influxql.Unknown { 761 // The primary driver of this call is of unknown type, so skip this. 762 continue 763 } 764 765 g.Go(func() error { 766 itr, err := buildFieldIterator(ctx, call, ic, stmt.Sources, opt, selector, stmt.Target != nil) 767 if err != nil { 768 return err 769 } 770 771 keys := make([]influxql.VarRef, 0, len(auxKeys)+1) 772 keys = append(keys, driver) 773 keys = append(keys, auxKeys...) 774 775 scanner := NewIteratorScanner(itr, keys, opt.FillValue) 776 777 mu.Lock() 778 scanners = append(scanners, scanner) 779 mu.Unlock() 780 781 return nil 782 }) 783 } 784 785 // Close all scanners if any iterator fails. 786 if err := g.Wait(); err != nil { 787 for _, s := range scanners { 788 s.Close() 789 } 790 return nil, err 791 } 792 793 if len(scanners) == 0 { 794 return newNullCursor(fields), nil 795 } else if len(scanners) == 1 { 796 return newScannerCursor(scanners[0], fields, opt), nil 797 } 798 return newMultiScannerCursor(scanners, fields, opt), nil 799 } 800 801 func buildAuxIterator(ctx context.Context, ic IteratorCreator, sources influxql.Sources, opt IteratorOptions) (Iterator, error) { 802 inputs := make([]Iterator, 0, len(sources)) 803 if err := func() error { 804 for _, source := range sources { 805 switch source := source.(type) { 806 case *influxql.Measurement: 807 input, err := ic.CreateIterator(ctx, source, opt) 808 if err != nil { 809 return err 810 } 811 inputs = append(inputs, input) 812 case *influxql.SubQuery: 813 b := subqueryBuilder{ 814 ic: ic, 815 stmt: source.Statement, 816 } 817 818 input, err := b.buildAuxIterator(ctx, opt) 819 if err != nil { 820 return err 821 } else if input != nil { 822 inputs = append(inputs, input) 823 } 824 } 825 } 826 return nil 827 }(); err != nil { 828 Iterators(inputs).Close() 829 return nil, err 830 } 831 832 // Merge iterators to read auxiliary fields. 833 input, err := Iterators(inputs).Merge(opt) 834 if err != nil { 835 Iterators(inputs).Close() 836 return nil, err 837 } else if input == nil { 838 input = &nilFloatIterator{} 839 } 840 841 // Filter out duplicate rows, if required. 842 if opt.Dedupe { 843 // If there is no group by and it is a float iterator, see if we can use a fast dedupe. 844 if itr, ok := input.(FloatIterator); ok && len(opt.Dimensions) == 0 { 845 if sz := len(opt.Aux); sz > 0 && sz < 3 { 846 input = newFloatFastDedupeIterator(itr) 847 } else { 848 input = NewDedupeIterator(itr) 849 } 850 } else { 851 input = NewDedupeIterator(input) 852 } 853 } 854 // Apply limit & offset. 855 if opt.Limit > 0 || opt.Offset > 0 { 856 input = NewLimitIterator(input, opt) 857 } 858 return input, nil 859 } 860 861 func buildFieldIterator(ctx context.Context, expr influxql.Expr, ic IteratorCreator, sources influxql.Sources, opt IteratorOptions, selector, writeMode bool) (Iterator, error) { 862 input, err := buildExprIterator(ctx, expr, ic, sources, opt, selector, writeMode) 863 if err != nil { 864 return nil, err 865 } 866 867 // Apply limit & offset. 868 if opt.Limit > 0 || opt.Offset > 0 { 869 input = NewLimitIterator(input, opt) 870 } 871 return input, nil 872 } 873 874 type valueMapper struct { 875 // An index that maps a node's string output to its symbol so that all 876 // nodes with the same signature are mapped the same. 877 symbols map[string]influxql.VarRef 878 // An index that maps a specific expression to a symbol. This ensures that 879 // only expressions that were mapped get symbolized. 880 table map[influxql.Expr]influxql.VarRef 881 // A collection of all of the calls in the table. 882 calls map[*influxql.Call]struct{} 883 // A collection of all of the calls in the table. 884 refs map[*influxql.VarRef]struct{} 885 i int 886 } 887 888 func newValueMapper() *valueMapper { 889 return &valueMapper{ 890 symbols: make(map[string]influxql.VarRef), 891 table: make(map[influxql.Expr]influxql.VarRef), 892 calls: make(map[*influxql.Call]struct{}), 893 refs: make(map[*influxql.VarRef]struct{}), 894 } 895 } 896 897 func (v *valueMapper) Map(field *influxql.Field) *influxql.Field { 898 clone := *field 899 clone.Expr = influxql.CloneExpr(field.Expr) 900 901 influxql.Walk(v, clone.Expr) 902 clone.Expr = influxql.RewriteExpr(clone.Expr, v.rewriteExpr) 903 return &clone 904 } 905 906 func (v *valueMapper) Visit(n influxql.Node) influxql.Visitor { 907 expr, ok := n.(influxql.Expr) 908 if !ok { 909 return v 910 } 911 912 key := expr.String() 913 symbol, ok := v.symbols[key] 914 if !ok { 915 // This symbol has not been assigned yet. 916 // If this is a call or expression, mark the node 917 // as stored in the symbol table. 918 switch n := n.(type) { 919 case *influxql.Call: 920 if isMathFunction(n) { 921 return v 922 } 923 v.calls[n] = struct{}{} 924 case *influxql.VarRef: 925 v.refs[n] = struct{}{} 926 default: 927 return v 928 } 929 930 // Determine the symbol name and the symbol type. 931 symbolName := fmt.Sprintf("val%d", v.i) 932 valuer := influxql.TypeValuerEval{ 933 TypeMapper: DefaultTypeMapper, 934 } 935 typ, _ := valuer.EvalType(expr) 936 937 symbol = influxql.VarRef{ 938 Val: symbolName, 939 Type: typ, 940 } 941 942 // Assign this symbol to the symbol table if it is not presently there 943 // and increment the value index number. 944 v.symbols[key] = symbol 945 v.i++ 946 } 947 // Store the symbol for this expression so we can later rewrite 948 // the query correctly. 949 v.table[expr] = symbol 950 return nil 951 } 952 953 func (v *valueMapper) rewriteExpr(expr influxql.Expr) influxql.Expr { 954 symbol, ok := v.table[expr] 955 if !ok { 956 return expr 957 } 958 return &symbol 959 } 960 961 func validateTypes(stmt *influxql.SelectStatement) error { 962 valuer := influxql.TypeValuerEval{ 963 TypeMapper: influxql.MultiTypeMapper( 964 FunctionTypeMapper{}, 965 MathTypeMapper{}, 966 ), 967 } 968 for _, f := range stmt.Fields { 969 if _, err := valuer.EvalType(f.Expr); err != nil { 970 return err 971 } 972 } 973 return nil 974 } 975 976 // hasValidType returns true if there is at least one non-unknown type 977 // in the slice. 978 func hasValidType(refs []influxql.VarRef) bool { 979 for _, ref := range refs { 980 if ref.Type != influxql.Unknown { 981 return true 982 } 983 } 984 return false 985 }