示例#1
0
func (s *selectNode) ExplainTypes(regTypes func(string, string)) {
	if s.filter != nil {
		regTypes("filter", parser.AsStringWithFlags(s.filter, parser.FmtShowTypes))
	}
	for i, rexpr := range s.render {
		regTypes(fmt.Sprintf("render %d", i), parser.AsStringWithFlags(rexpr, parser.FmtShowTypes))
	}
}
示例#2
0
func (n *limitNode) ExplainTypes(regTypes func(string, string)) {
	if n.countExpr != nil {
		regTypes("count", parser.AsStringWithFlags(n.countExpr, parser.FmtShowTypes))
	}
	if n.offsetExpr != nil {
		regTypes("offset", parser.AsStringWithFlags(n.offsetExpr, parser.FmtShowTypes))
	}
}
示例#3
0
func (n *insertNode) ExplainTypes(regTypes func(string, string)) {
	for i, dexpr := range n.defaultExprs {
		regTypes(fmt.Sprintf("default %d", i), parser.AsStringWithFlags(dexpr, parser.FmtShowTypes))
	}
	for i, cexpr := range n.checkHelper.exprs {
		regTypes(fmt.Sprintf("check %d", i), parser.AsStringWithFlags(cexpr, parser.FmtShowTypes))
	}
	cols := n.rh.columns
	for i, rexpr := range n.rh.exprs {
		regTypes(fmt.Sprintf("returning %s", cols[i].Name), parser.AsStringWithFlags(rexpr, parser.FmtShowTypes))
	}
}
示例#4
0
// explain extract information from planNodes and produces the EXPLAIN
// output via the makeRow callback in the explainer.
func (e *explainer) explain(plan planNode) {
	if e.err != nil {
		return
	}

	name, description, children := plan.ExplainPlan(e.showMetadata)

	if name == "select" && !e.showSelectTop {
		e.explain(children[len(children)-1])
		return
	}

	e.node(name, description, plan)

	if e.showExprs {
		plan.explainExprs(func(elt string, expr parser.Expr) {
			if e.err != nil {
				return
			}
			if expr != nil {
				e.attr(name, elt, parser.AsStringWithFlags(expr, e.fmtFlags))
			}
		})
	}

	for _, child := range children {
		e.subnode(child)
	}
}
示例#5
0
// addOrMergeRenders adds the given result columns to the select
// render list and returns their column indices. If an expression is
// already rendered, and the reuse flag is true, no new render is
// added and the index of the existing column is returned instead.
func (s *selectNode) addOrMergeRenders(
	cols ResultColumns, exprs []parser.TypedExpr, reuseExistingRender bool,
) (colIdxs []int) {
	colIdxs = make([]int, len(cols))
	for i := range cols {
		index := -1

		if reuseExistingRender {
			// Now, try to find an equivalent render. We use the syntax
			// representation as approximation of equivalence.  At this
			// point the expressions must have underwent name resolution
			// already so that comparison occurs after replacing column names
			// to IndexedVars.
			exprStr := parser.AsStringWithFlags(exprs[i], parser.FmtSymbolicVars)
			for j := range s.render {
				if s.isRenderEquivalent(exprStr, j) {
					index = j
					break
				}
			}
		}

		if index == -1 {
			index = len(s.render)
			s.addRenderColumn(exprs[i], cols[i])
		}
		colIdxs[i] = index
	}

	return colIdxs
}
示例#6
0
// expr implements the planObserver interface.
func (e *explainer) expr(nodeName, fieldName string, n int, expr parser.Expr) {
	if e.showExprs && expr != nil {
		if nodeName == "join" {
			qualifySave := e.fmtFlags.ShowTableAliases
			e.fmtFlags.ShowTableAliases = true
			defer func() { e.fmtFlags.ShowTableAliases = qualifySave }()
		}
		if n >= 0 {
			fieldName = fmt.Sprintf("%s %d", fieldName, n)
		}
		e.attr(nodeName, fieldName,
			parser.AsStringWithFlags(expr, e.fmtFlags))
	}
}
示例#7
0
文件: update.go 项目: knz/cockroach
func (u *updateNode) ExplainTypes(regTypes func(string, string)) {
	cols := u.rh.columns
	for i, rexpr := range u.rh.exprs {
		regTypes(fmt.Sprintf("returning %s", cols[i].Name), parser.AsStringWithFlags(rexpr, parser.FmtShowTypes))
	}
}
示例#8
0
// orderBy constructs a sortNode based on the ORDER BY clause.
//
// In the general case (SELECT/UNION/VALUES), we can sort by a column index or a
// column name.
//
// However, for a SELECT, we can also sort by the pre-alias column name (SELECT
// a AS b ORDER BY b) as well as expressions (SELECT a, b, ORDER BY a+b). In
// this case, construction of the sortNode might adjust the number of render
// targets in the selectNode if any ordering expressions are specified.
//
// TODO(dan): SQL also allows sorting a VALUES or UNION by an expression.
// Support this. It will reduce some of the special casing below, but requires a
// generalization of how to add derived columns to a SelectStatement.
func (p *planner) orderBy(orderBy parser.OrderBy, n planNode) (*sortNode, error) {
	if orderBy == nil {
		return nil, nil
	}

	// Multiple tests below use selectNode as a special case.
	// So factor the cast.
	s, _ := n.(*selectNode)

	// We grab a copy of columns here because we might add new render targets
	// below. This is the set of columns requested by the query.
	columns := n.Columns()
	numOriginalCols := len(columns)
	if s != nil {
		numOriginalCols = s.numOriginalCols
	}
	var ordering sqlbase.ColumnOrdering

	for _, o := range orderBy {
		direction := encoding.Ascending
		if o.Direction == parser.Descending {
			direction = encoding.Descending
		}

		index := -1

		// Unwrap parenthesized expressions like "((a))" to "a".
		expr := parser.StripParens(o.Expr)

		// The logical data source for ORDER BY is the list of render
		// expressions for a SELECT, as specified in the input SQL text
		// (or an entire UNION or VALUES clause).  Alas, SQL has some
		// historical baggage and there are some special cases:
		//
		// 1) column ordinals. If a simple integer literal is used,
		//    optionally enclosed within parentheses but *not subject to
		//    any arithmetic*, then this refers to one of the columns of
		//    the data source. Then use the render expression at that
		//    ordinal position as sort key.
		//
		// 2) if the expression is the aliased (AS) name of a render
		//    expression in a SELECT clause, then use that
		//    render as sort key.
		//    e.g. SELECT a AS b, b AS c ORDER BY b
		//    this sorts on the first render.
		//
		// 3) otherwise, if the expression is already in the render list,
		//    then use that render as sort key.
		//    e.g. SELECT b AS c ORDER BY b
		//    this sorts on the first render.
		//    (this is an optimization)
		//
		// 4) if the sort key is not dependent on the data source (no
		//    IndexedVar) then simply do not sort. (this is an optimization)
		//
		// 5) otherwise, add a new render with the ORDER BY expression
		//    and use that as sort key.
		//    e.g. SELECT a FROM t ORDER by b
		//    e.g. SELECT a, b FROM t ORDER by a+b
		//
		// So first, deal with column ordinals.
		col, err := p.colIndex(numOriginalCols, expr, "ORDER BY")
		if err != nil {
			return nil, err
		}
		if col != -1 {
			index = col
		}

		// Now, deal with render aliases.
		if vBase, ok := expr.(parser.VarName); index == -1 && ok {
			v, err := vBase.NormalizeVarName()
			if err != nil {
				return nil, err
			}

			if c, ok := v.(*parser.ColumnItem); ok && c.TableName.Table() == "" {
				// Look for an output column that matches the name. This
				// handles cases like:
				//
				//   SELECT a AS b FROM t ORDER BY b
				target := c.ColumnName.Normalize()
				for j, col := range columns {
					if parser.ReNormalizeName(col.Name) == target {
						index = j
						break
					}
				}
			}
		}

		if s != nil {
			// Try to optimize constant sorts. For this we need to resolve
			// names to IndexedVars then see if there were any vars
			// substituted.
			sortExpr := expr
			if index != -1 {
				// We found a render above, so fetch it. This is needed
				// because if the sort expression is a reference to a render
				// alias, resolveNames below would be incorrect.
				sortExpr = s.render[index]
			}
			resolved, hasVars, err := p.resolveNames(sortExpr, s.sourceInfo, s.ivarHelper)
			if err != nil {
				return nil, err
			}
			if !hasVars {
				// No sorting needed!
				continue
			}

			// Now, try to find an equivalent render. We use the syntax
			// representation as approximation of equivalence.
			// We also use the expression after name resolution so
			// that comparison occurs after replacing ordinal references
			// to IndexedVars.
			if index == -1 {
				exprStr := parser.AsStringWithFlags(resolved, parser.FmtSymbolicVars)
				for j, render := range s.render {
					if parser.AsStringWithFlags(render, parser.FmtSymbolicVars) == exprStr {
						index = j
						break
					}
				}
			}
		}

		// Finally, if we haven't found anything so far, we really
		// need a new render.
		// TODO(knz/dan) currently this is only possible for selectNode.
		// If we are dealing with a UNION or something else we would need
		// to fabricate an intermediate selectNode to add the new render.
		if index == -1 && s != nil {
			// We need to add a new render, but let's be careful: if there's
			// a star in there, we're really adding multiple columns. These
			// all become sort columns! And if no columns are expanded, then
			// no columns become sort keys.
			nextRenderIdx := len(s.render)

			// TODO(knz) the optimizations above which reuse existing
			// renders and skip ordering for constant expressions are not
			// applied by addRender(). In other words, "ORDER BY foo.*" will
			// not be optimized as well as "ORDER BY foo.x, foo.y".  We
			// could do this either here or as a separate later
			// optimization.
			if err := s.addRender(parser.SelectExpr{Expr: expr}, nil); err != nil {
				return nil, err
			}

			for extraIdx := nextRenderIdx; extraIdx < len(s.render)-1; extraIdx++ {
				// If more than 1 column were expanded, turn them into sort columns too.
				// Except the last one, which will be added below.
				ordering = append(ordering,
					sqlbase.ColumnOrderInfo{ColIdx: extraIdx, Direction: direction})
			}
			if len(s.render) == nextRenderIdx {
				// Nothing was expanded! So there is no order here.
				continue
			}
			index = len(s.render) - 1
		}

		if index == -1 {
			return nil, errors.Errorf("column %s does not exist", expr)
		}
		ordering = append(ordering,
			sqlbase.ColumnOrderInfo{ColIdx: index, Direction: direction})
	}

	if ordering == nil {
		// All the sort expressions are constant. Simply drop the sort node.
		return nil, nil
	}
	return &sortNode{ctx: p.ctx(), p: p, columns: columns, ordering: ordering}, nil
}
示例#9
0
文件: join.go 项目: maxlang/cockroach
// ExplainTypes implements the planNode interface.
func (n *joinNode) ExplainTypes(regTypes func(string, string)) {
	if n.pred.filter != nil {
		regTypes("filter", parser.AsStringWithFlags(n.pred.filter, parser.FmtShowTypes))
	}
}
示例#10
0
// TestCopyRandom inserts 100 random rows using COPY and ensures the SELECT'd
// data is the same.
func TestCopyRandom(t *testing.T) {
	defer leaktest.AfterTest(t)()

	params, _ := createTestServerParams()
	s, db, _ := serverutils.StartServer(t, params)
	defer s.Stopper().Stop()

	if _, err := db.Exec(`
		CREATE DATABASE d;
		CREATE TABLE IF NOT EXISTS d.t (
			id INT PRIMARY KEY,
			n INTERVAL,
			o BOOL,
			i INT,
			f FLOAT,
			e DECIMAL,
			t TIMESTAMP,
			s STRING,
			b BYTES,
			tz TIMESTAMP WITH TIME ZONE
		);
	`); err != nil {
		t.Fatal(err)
	}

	txn, err := db.Begin()
	if err != nil {
		t.Fatal(err)
	}

	stmt, err := txn.Prepare(pq.CopyInSchema("d", "t", "id", "n", "o", "i", "f", "e", "t", "s", "b", "tz"))
	if err != nil {
		t.Fatal(err)
	}

	rng := rand.New(rand.NewSource(0))
	types := []sqlbase.ColumnType_Kind{
		sqlbase.ColumnType_BOOL,
		sqlbase.ColumnType_INT,
		sqlbase.ColumnType_FLOAT,
		sqlbase.ColumnType_DECIMAL,
		sqlbase.ColumnType_TIMESTAMP,
		sqlbase.ColumnType_STRING,
		sqlbase.ColumnType_BYTES,
		sqlbase.ColumnType_TIMESTAMPTZ,
	}

	var inputs [][]interface{}

	for i := 0; i < 100; i++ {
		row := make([]interface{}, len(types)+2)
		row[0] = strconv.Itoa(i)
		row[1] = time.Duration(rng.Int63()).String()
		for j, t := range types {
			d := sqlbase.RandDatum(rng, sqlbase.ColumnType{Kind: t}, false)
			ds := parser.AsStringWithFlags(d, parser.FmtBareStrings)
			switch t {
			case sqlbase.ColumnType_DECIMAL:
				// Trailing 0s aren't represented below, so truncate here.
				ds = strings.TrimRight(ds, "0")
			}
			row[j+2] = ds
		}
		_, err = stmt.Exec(row...)
		if err != nil {
			t.Fatal(err)
		}
		inputs = append(inputs, row)
	}

	err = stmt.Close()
	if err != nil {
		t.Fatal(err)
	}
	err = txn.Commit()
	if err != nil {
		t.Fatal(err)
	}

	rows, err := db.Query("SELECT * FROM d.t ORDER BY id")
	if err != nil {
		t.Fatal(err)
	}

	for row, in := range inputs {
		if !rows.Next() {
			t.Fatal("expected more results")
		}
		data := make([]interface{}, len(in))
		for i := range data {
			data[i] = new(interface{})
		}
		if err := rows.Scan(data...); err != nil {
			t.Fatal(err)
		}
		for i, d := range data {
			v := d.(*interface{})
			d := *v
			ds := fmt.Sprint(d)
			switch d := d.(type) {
			case []byte:
				ds = string(d)
			case time.Time:
				dt := parser.MakeDTimestamp(d, time.Microsecond)
				ds = parser.AsStringWithFlags(dt, parser.FmtBareStrings)
			}
			if !reflect.DeepEqual(in[i], ds) {
				t.Fatalf("row %v, col %v: got %#v (%T), expected %#v", row, i, ds, d, in[i])
			}
		}
	}
}
示例#11
0
// isRenderEquivalent is a helper function for equivalentRenders() and
// addOrMergeRenders(). Do not use directly.
func (s *selectNode) isRenderEquivalent(exprStr string, j int) bool {
	return parser.AsStringWithFlags(s.render[j], parser.FmtSymbolicVars) == exprStr
}
示例#12
0
// equivalentRenders returns true if and only if the two render expressions
// are equivalent.
func (s *selectNode) equivalentRenders(i, j int) bool {
	firstExprStr := parser.AsStringWithFlags(s.render[i], parser.FmtSymbolicVars)
	return s.isRenderEquivalent(firstExprStr, j)
}