Example #1
0
func (s *selectNode) addRender(target parser.SelectExpr) *roachpb.Error {
	// outputName will be empty if the target is not aliased.
	outputName := string(target.As)

	if isStar, cols, exprs, err := checkRenderStar(target, &s.table, s.qvals); err != nil {
		s.pErr = roachpb.NewError(err)
		return s.pErr
	} else if isStar {
		s.columns = append(s.columns, cols...)
		s.render = append(s.render, exprs...)
		return nil
	}

	// When generating an output column name it should exactly match the original
	// expression, so determine the output column name before we perform any
	// manipulations to the expression.
	outputName = getRenderColName(target)

	// Resolve qualified names. This has the side-effect of normalizing any
	// qualified name found.
	var resolved parser.Expr
	var err error
	if resolved, err = s.resolveQNames(target.Expr); err != nil {
		s.pErr = roachpb.NewError(err)
		return s.pErr
	}
	if resolved, s.pErr = s.planner.expandSubqueries(resolved, 1); s.pErr != nil {
		return s.pErr
	}
	var typ parser.Datum
	typ, err = resolved.TypeCheck(s.planner.evalCtx.Args)
	s.pErr = roachpb.NewError(err)
	if s.pErr != nil {
		return s.pErr
	}
	var normalized parser.Expr
	normalized, err = s.planner.parser.NormalizeExpr(s.planner.evalCtx, resolved)
	s.pErr = roachpb.NewError(err)
	if s.pErr != nil {
		return s.pErr
	}
	s.render = append(s.render, normalized)

	if target.As == "" {
		switch t := target.Expr.(type) {
		case *parser.QualifiedName:
			// If the expression is a qualified name, use the column name, not the
			// full qualification as the column name to return.
			outputName = t.Column()
		}
	}
	s.columns = append(s.columns, ResultColumn{Name: outputName, Typ: typ})
	return nil
}
Example #2
0
func sameTypeExprs(left, right parser.Expr) (bool, error) {
	dummyLeft, err := left.TypeCheck(nil)
	if err != nil || dummyLeft == parser.DNull {
		return false, err
	}
	dummyRight, err := right.TypeCheck(nil)
	if err != nil || dummyRight == parser.DNull {
		return false, err
	}
	return !dummyLeft.TypeEqual(dummyRight), nil
}
Example #3
0
func (n *scanNode) addRender(target parser.SelectExpr) *roachpb.Error {
	// When generating an output column name it should exactly match the original
	// expression, so determine the output column name before we perform any
	// manipulations to the expression (such as star expansion).
	var outputName string
	if target.As != "" {
		outputName = string(target.As)
	} else {
		outputName = target.Expr.String()
	}

	// If a QualifiedName has a StarIndirection suffix we need to match the
	// prefix of the qualified name to one of the tables in the query and
	// then expand the "*" into a list of columns.
	if qname, ok := target.Expr.(*parser.QualifiedName); ok {
		if n.pErr = roachpb.NewError(qname.NormalizeColumnName()); n.pErr != nil {
			return n.pErr
		}
		if qname.IsStar() {
			if n.desc == nil {
				return roachpb.NewUErrorf("\"%s\" with no tables specified is not valid", qname)
			}
			if target.As != "" {
				return roachpb.NewUErrorf("\"%s\" cannot be aliased", qname)
			}
			tableName := qname.Table()
			if tableName != "" && !equalName(n.desc.Alias, tableName) {
				return roachpb.NewUErrorf("table \"%s\" not found", tableName)
			}

			if n.isSecondaryIndex {
				for _, id := range n.index.ColumnIDs {
					var col *ColumnDescriptor
					if col, n.pErr = n.desc.FindColumnByID(id); n.pErr != nil {
						return n.pErr
					}
					qval := n.getQVal(*col)
					n.columns = append(n.columns, resultColumn{name: col.Name, typ: qval.datum})
					n.render = append(n.render, qval)
				}
			} else {
				for _, col := range n.desc.VisibleColumns() {
					qval := n.getQVal(col)
					n.columns = append(n.columns, resultColumn{name: col.Name, typ: qval.datum})
					n.render = append(n.render, qval)
				}
			}
			return nil
		}
	}

	// Resolve qualified names. This has the side-effect of normalizing any
	// qualified name found.
	var resolved parser.Expr
	if resolved, n.pErr = n.resolveQNames(target.Expr); n.pErr != nil {
		return n.pErr
	}
	if resolved, n.pErr = n.planner.expandSubqueries(resolved, 1); n.pErr != nil {
		return n.pErr
	}
	var typ parser.Datum
	var err error
	typ, err = resolved.TypeCheck(n.planner.evalCtx.Args)
	n.pErr = roachpb.NewError(err)
	if n.pErr != nil {
		return n.pErr
	}
	var normalized parser.Expr
	normalized, err = n.planner.parser.NormalizeExpr(n.planner.evalCtx, resolved)
	n.pErr = roachpb.NewError(err)
	if n.pErr != nil {
		return n.pErr
	}
	n.render = append(n.render, normalized)

	if target.As == "" {
		switch t := target.Expr.(type) {
		case *parser.QualifiedName:
			// If the expression is a qualified name, use the column name, not the
			// full qualification as the column name to return.
			outputName = t.Column()
		}
	}
	n.columns = append(n.columns, resultColumn{name: outputName, typ: typ})
	return nil
}