// Select selects rows from a single table. Select is the workhorse of the SQL // statements. In the slowest and most general case, select must perform full // table scans across multiple tables and sort and join the resulting rows on // arbitrary columns. Full table scans can be avoided when indexes can be used // to satisfy the where-clause. // // Privileges: SELECT on table // Notes: postgres requires SELECT. Also requires UPDATE on "FOR UPDATE". // mysql requires SELECT. func (p *planner) Select(n *parser.Select) (planNode, error) { scan := &scanNode{txn: p.txn} if err := scan.initFrom(p, n.From); err != nil { return nil, err } if err := scan.initWhere(n.Where); err != nil { return nil, err } if err := scan.initTargets(n.Exprs); err != nil { return nil, err } group, err := p.groupBy(n, scan) if err != nil { return nil, err } if group != nil && n.OrderBy != nil { // TODO(pmattis): orderBy currently uses deep knowledge of the // scanNode. Need to lift that out or make orderBy compatible with // groupNode as well. return nil, fmt.Errorf("TODO(pmattis): unimplemented ORDER BY with GROUP BY/aggregation") } sort, err := p.orderBy(n, scan) if err != nil { return nil, err } // TODO(pmattis): Consider aggregation functions during index // selection. Specifically, MIN(k) and MAX(k) where k is the first column in // an index can be satisfied with a single read. plan, err := p.selectIndex(scan, sort.Ordering()) if err != nil { return nil, err } return sort.wrap(group.wrap(plan)), nil }
func (p *planner) initSelect(s *selectNode, parsed *parser.Select) (planNode, *roachpb.Error) { if pErr := s.initFrom(p, parsed); pErr != nil { return nil, pErr } // TODO(radu): for now we assume from is always a scanNode scan := s.from.(*scanNode) // NB: both orderBy and groupBy are passed and can modify `scan` but orderBy must do so first. sort, pErr := p.orderBy(parsed, scan) if pErr != nil { return nil, pErr } group, pErr := p.groupBy(parsed, scan) if pErr != nil { return nil, pErr } if scan.filter != nil && group != nil { // Allow the group-by to add an implicit "IS NOT NULL" filter. scan.filter = group.isNotNullFilter(scan.filter) } // Get the ordering for index selection (if any). var ordering []int var grouping bool if group != nil { ordering = group.desiredOrdering grouping = true } else if sort != nil { ordering, _ = sort.Ordering() } plan, pErr := p.selectIndex(scan, ordering, grouping) if pErr != nil { return nil, pErr } // Update s.from with the new plan. s.from = plan // Wrap this node as necessary. limit, pErr := p.limit(parsed, p.distinct(parsed, sort.wrap(group.wrap(s)))) if pErr != nil { return nil, pErr } return limit, nil }
// Select selects rows from a single table. Select is the workhorse of the SQL // statements. In the slowest and most general case, select must perform full // table scans across multiple tables and sort and join the resulting rows on // arbitrary columns. Full table scans can be avoided when indexes can be used // to satisfy the where-clause. // // Privileges: SELECT on table // Notes: postgres requires SELECT. Also requires UPDATE on "FOR UPDATE". // mysql requires SELECT. func (p *planner) Select(n *parser.Select) (planNode, error) { scan := &scanNode{planner: p, txn: p.txn} if err := scan.initFrom(p, n.From); err != nil { return nil, err } if err := scan.initWhere(n.Where); err != nil { return nil, err } if err := scan.initTargets(n.Exprs); err != nil { return nil, err } group, err := p.groupBy(n, scan) if err != nil { return nil, err } if group != nil && n.OrderBy != nil { // TODO(pmattis): orderBy currently uses deep knowledge of the // scanNode. Need to lift that out or make orderBy compatible with // groupNode as well. return nil, util.Errorf("TODO(pmattis): unimplemented ORDER BY with GROUP BY/aggregation") } sort, err := p.orderBy(n, scan) if err != nil { return nil, err } var ordering []int if group != nil { ordering = group.desiredOrdering } else if sort != nil { ordering, _ = sort.Ordering() } plan, err := p.selectIndex(scan, ordering) if err != nil { return nil, err } limit, err := p.limit(n, p.distinct(n, sort.wrap(group.wrap(plan)))) if err != nil { return nil, err } return limit, nil }
// Select selects rows from a single table. Select is the workhorse of the SQL // statements. In the slowest and most general case, select must perform full // table scans across multiple tables and sort and join the resulting rows on // arbitrary columns. Full table scans can be avoided when indexes can be used // to satisfy the where-clause. // // Privileges: SELECT on table // Notes: postgres requires SELECT. Also requires UPDATE on "FOR UPDATE". // mysql requires SELECT. func (p *planner) Select(n *parser.Select) (planNode, error) { scan := &scanNode{txn: p.txn} if err := scan.initFrom(p, n.From); err != nil { return nil, err } if err := scan.initWhere(n.Where); err != nil { return nil, err } if err := scan.initTargets(n.Exprs); err != nil { return nil, err } sort, err := p.orderBy(n, scan) if err != nil { return nil, err } plan, err := p.selectIndex(scan, sort.Ordering()) if err != nil { return nil, err } return sort.wrap(plan), nil }