// nextRow processes table rows until it finds a row that passes the filter. // Returns a nil row when there are no more rows. func (tr *tableReader) nextRow() (sqlbase.EncDatumRow, error) { for { fetcherRow, err := tr.fetcher.NextRow() if err != nil || fetcherRow == nil { return nil, err } // TODO(radu): we are defeating the purpose of EncDatum here - we // should modify RowFetcher to return EncDatums directly and avoid // the cost of decoding/reencoding. for i := range fetcherRow { if fetcherRow[i] != nil { tr.row[i].SetDatum(tr.desc.Columns[i].Type.Kind, fetcherRow[i]) } } passesFilter, err := sqlbase.RunFilter(tr.filter, tr.evalCtx) if err != nil { return nil, err } if passesFilter { break } } // TODO(radu): investigate removing this allocation. We can't reuse the // same slice because it is being read asynchronously on the other side // of the channel. Perhaps streamMsg can store a few preallocated // elements to avoid allocation in most cases. outRow := make(sqlbase.EncDatumRow, len(tr.outputCols)) for i, col := range tr.outputCols { outRow[i] = tr.row[col] } return outRow, nil }
func (n *scanNode) Next() (bool, error) { tracing.AnnotateTrace() if !n.scanInitialized { if err := n.initScan(); err != nil { return false, nil } } if n.explain == explainDebug { return n.debugNext() } // We fetch one row at a time until we find one that passes the filter. for { var err error n.row, err = n.fetcher.NextRow() if err != nil || n.row == nil { return false, err } passesFilter, err := sqlbase.RunFilter(n.filter, n.p.evalCtx) if err != nil { return false, err } if passesFilter { return true, nil } } }
// debugNext is a helper function used by Next() when in explainDebug mode. func (n *scanNode) debugNext() (bool, error) { // In debug mode, we output a set of debug values for each key. n.debugVals.rowIdx = n.rowIndex var err error n.debugVals.key, n.debugVals.value, n.row, err = n.fetcher.NextKeyDebug() if err != nil || n.debugVals.key == "" { return false, err } if n.row != nil { passesFilter, err := sqlbase.RunFilter(n.filter, n.p.evalCtx) if err != nil { return false, err } if passesFilter { n.debugVals.output = debugValueRow } else { n.debugVals.output = debugValueFiltered } n.rowIndex++ } else { n.debugVals.output = debugValuePartial } return true, nil }
func (s *selectNode) Next() (bool, error) { for { if next, err := s.source.plan.Next(); !next { return false, err } if s.explain == explainDebug { s.debugVals = s.source.plan.DebugValues() if s.debugVals.output != debugValueRow { // Let the debug values pass through. return true, nil } } row := s.source.plan.Values() s.qvals.populateQVals(&s.source.info, row) passesFilter, err := sqlbase.RunFilter(s.filter, &s.planner.evalCtx) if err != nil { return false, err } if passesFilter { err := s.renderRow() return err == nil, err } else if s.explain == explainDebug { // Mark the row as filtered out. s.debugVals.output = debugValueFiltered return true, nil } // Row was filtered out; grab the next row. } }
// evalFilter is used for filter expressions; it evaluates the expression and // returns whether the filter passes. func (eh *exprHelper) evalFilter(row sqlbase.EncDatumRow) (bool, error) { eh.row = row return sqlbase.RunFilter(eh.expr, eh.evalCtx) }