func()

in query/aql_compiler.go [658:766]


func (qc *AQLQueryContext) matchPrefilters() {
	// Format of candidateFilters:
	// [tableID]map[columnID]{filterIDs for lower bound, upper bound, equality}
	// tableID is query scoped, while columnID is schema scoped.
	candidateFilters := make([]map[int][3]int, len(qc.TableScanners))
	for tableID := range qc.TableScanners {
		candidateFilters[tableID] = make(map[int][3]int)
	}

	// Index candidate filters by table/column
	for filterID, filter := range qc.Query.FiltersParsed {
		f, _ := filter.(*expr.BinaryExpr)
		if f == nil {
			switch f := filter.(type) {
			case *expr.VarRef:
				// Match `column` format
				if f.ExprType == expr.Boolean {
					candidateFilters[f.TableID][f.ColumnID] = [3]int{-1, -1, filterID}
				}
			case *expr.UnaryExpr:
				// Match `not column` format
				if f.Op == expr.NOT {
					f, _ := f.Expr.(*expr.VarRef)
					if f != nil && f.ExprType == expr.Boolean {
						candidateFilters[f.TableID][f.ColumnID] = [3]int{-1, -1, filterID}
					}
				}
				// TODO: IS_NULL can be matched as an equality filter.
				// TODO: IS_NOT_NULL can be matched as the final range filter.
			}
			continue
		}

		// Match `column op value` format, where op can be =, <, <=, >, >=.
		if f.Op < expr.EQ || f.Op > expr.GTE {
			continue
		}

		lhs, _ := f.LHS.(*expr.VarRef)
		if lhs == nil {
			continue
		}

		columnToFilterMap := candidateFilters[lhs.TableID]
		filters, exists := columnToFilterMap[lhs.ColumnID]
		if !exists {
			filters = [3]int{-1, -1, -1}
		}
		switch f.Op {
		case expr.GT, expr.GTE:
			filters[0] = filterID
		case expr.LT, expr.LTE:
			filters[1] = filterID
		case expr.EQ:
			filters[2] = filterID
		}
		columnToFilterMap[lhs.ColumnID] = filters
	}

	// Prefilter matching
	for tableID, scanner := range qc.TableScanners {
		// Match in archiving sort column order
		for _, columnID := range scanner.Schema.Schema.ArchivingSortColumns {
			filterIndex, exists := candidateFilters[tableID][columnID]
			if !exists {
				// Stop on first missing column
				break
			}
			// Equality
			if filterIndex[2] >= 0 {
				value, _, success := qc.extractFilter(filterIndex[2])
				if !success {
					// Stop if the value fails to be extracted
					break
				}
				scanner.EqualityPrefilterValues = append(
					scanner.EqualityPrefilterValues, value)
				qc.Prefilters = append(qc.Prefilters, filterIndex[2])
				scanner.ColumnUsages[columnID] |= columnUsedByPrefilter
				// Continue matching the next column
				continue
			}
			// Lower bound
			if filterIndex[0] >= 0 {
				value, boundaryType, success := qc.extractFilter(filterIndex[0])
				if success {
					scanner.RangePrefilterValues[0] = value
					scanner.RangePrefilterBoundaries[0] = boundaryType
					qc.Prefilters = append(qc.Prefilters, filterIndex[0])
					scanner.ColumnUsages[columnID] |= columnUsedByPrefilter
				}
			}
			// Upper bound
			if filterIndex[1] >= 0 {
				value, boundaryType, success := qc.extractFilter(filterIndex[1])
				if success {
					scanner.RangePrefilterValues[1] = value
					scanner.RangePrefilterBoundaries[1] = boundaryType
					qc.Prefilters = append(qc.Prefilters, filterIndex[1])
					scanner.ColumnUsages[columnID] |= columnUsedByPrefilter
				}
			}
			// Stop after the first range filter
			break
		}
	}

	sort.Ints(qc.Prefilters)
}