Пример #1
0
func (c *checkHelper) check(ctx *parser.EvalContext) error {
	for _, expr := range c.exprs {
		if d, err := expr.Eval(ctx); err != nil {
			return err
		} else if res, err := parser.GetBool(d); err != nil {
			return err
		} else if !res && d != parser.DNull {
			// Failed to satisfy CHECK constraint.
			return fmt.Errorf("failed to satisfy CHECK constraint (%s)", expr.String())
		}
	}
	return nil
}
Пример #2
0
func (n *insertNode) Next() bool {
	if n.run.done || n.run.err != nil {
		return false
	}

	if !n.run.rows.Next() {
		// We're done. Finish the batch.
		n.run.err = n.tw.finalize()
		n.run.done = true
		return false
	}

	rowVals := n.run.rows.Values()

	// The values for the row may be shorter than the number of columns being
	// inserted into. Generate default values for those columns using the
	// default expressions.
	for i := len(rowVals); i < len(n.insertCols); i++ {
		if n.defaultExprs == nil {
			rowVals = append(rowVals, parser.DNull)
			continue
		}
		d, err := n.defaultExprs[i].Eval(n.p.evalCtx)
		if err != nil {
			n.run.err = err
			return false
		}
		rowVals = append(rowVals, d)
	}

	// Check to see if NULL is being inserted into any non-nullable column.
	for _, col := range n.tableDesc.Columns {
		if !col.Nullable {
			if i, ok := n.insertColIDtoRowIndex[col.ID]; !ok || rowVals[i] == parser.DNull {
				n.run.err = fmt.Errorf("null value in column %q violates not-null constraint", col.Name)
				return false
			}
		}
	}

	// Ensure that the values honor the specified column widths.
	for i := range rowVals {
		if err := sqlbase.CheckValueWidth(n.insertCols[i], rowVals[i]); err != nil {
			n.run.err = err
			return false
		}
	}

	if len(n.checkExprs) > 0 {
		// Populate qvals.
		for ref, qval := range n.qvals {
			// The colIdx is 0-based, we need to change it to 1-based.
			ri, has := n.insertColIDtoRowIndex[sqlbase.ColumnID(ref.colIdx+1)]
			if !has {
				n.run.err = fmt.Errorf("failed to to find column %d in row", sqlbase.ColumnID(ref.colIdx+1))
				return false
			}
			qval.datum = rowVals[ri]
		}
		for _, expr := range n.checkExprs {
			if d, err := expr.Eval(n.p.evalCtx); err != nil {
				n.run.err = err
				return false
			} else if res, err := parser.GetBool(d); err != nil {
				n.run.err = err
				return false
			} else if !res {
				// Failed to satisfy CHECK constraint.
				n.run.err = fmt.Errorf("failed to satisfy CHECK constraint (%s)", expr.String())
				return false
			}
		}
	}

	_, err := n.tw.row(rowVals)
	if err != nil {
		n.run.err = err
		return false
	}

	for i, val := range rowVals {
		if n.run.rowTemplate != nil {
			n.run.rowTemplate[n.run.rowIdxToRetIdx[i]] = val
		}
	}

	resultRow, err := n.rh.cookResultRow(n.run.rowTemplate)
	if err != nil {
		n.run.err = err
		return false
	}
	n.run.resultRow = resultRow

	return true
}
Пример #3
0
func (n *groupNode) computeAggregates() {
	var scratch []byte

	// Loop over the rows passing the values into the corresponding aggregation
	// functions.
	for n.plan.Next() {
		values := n.plan.Values()
		aggregatedValues, groupedValues := values[:len(n.funcs)], values[len(n.funcs):]

		// TODO(dt): optimization: skip buckets when underlying plan is ordered by grouped values.

		encoded, err := encodeDTuple(scratch, groupedValues)
		n.pErr = roachpb.NewError(err)
		if n.pErr != nil {
			return
		}

		n.buckets[string(encoded)] = struct{}{}

		// Feed the aggregateFuncs for this bucket the non-grouped values.
		for i, value := range aggregatedValues {
			if n.pErr = roachpb.NewError(n.funcs[i].add(encoded, value)); n.pErr != nil {
				return
			}
		}
		scratch = encoded[:0]
	}

	n.pErr = n.plan.PErr()
	if n.pErr != nil {
		return
	}

	if len(n.buckets) < 1 && n.addNullBucketIfEmpty {
		n.buckets[""] = struct{}{}
	}

	// Since this controls Eval behavior of aggregateFunc, it is not set until init is complete.
	n.populated = true

	// Render the results.
	n.values.rows = make([]parser.DTuple, 0, len(n.buckets))
	for k := range n.buckets {
		n.currentBucket = k

		if n.having != nil {
			res, err := n.having.Eval(n.planner.evalCtx)
			if err != nil {
				n.pErr = roachpb.NewError(err)
				return
			}
			if res, err := parser.GetBool(res); err != nil {
				n.pErr = roachpb.NewError(err)
				return
			} else if !res {
				continue
			}
		}

		row := make(parser.DTuple, 0, len(n.render))
		for _, r := range n.render {
			res, err := r.Eval(n.planner.evalCtx)
			if err != nil {
				n.pErr = roachpb.NewError(err)
				return
			}
			row = append(row, res)
		}

		n.values.rows = append(n.values.rows, row)
	}

}
Пример #4
0
// Insert inserts rows into the database.
// Privileges: INSERT on table
//   Notes: postgres requires INSERT. No "on duplicate key update" option.
//          mysql requires INSERT. Also requires UPDATE on "ON DUPLICATE KEY UPDATE".
func (p *planner) Insert(n *parser.Insert, autoCommit bool) (planNode, *roachpb.Error) {
	// TODO(marcb): We can't use the cached descriptor here because a recent
	// update of the schema (e.g. the addition of an index) might not be
	// reflected in the cached version (yet). Perhaps schema modification
	// routines such as CREATE INDEX should not return until the schema change
	// has been pushed everywhere.
	tableDesc, pErr := p.getTableLease(n.Table)
	if pErr != nil {
		return nil, pErr
	}

	if err := p.checkPrivilege(&tableDesc, privilege.INSERT); err != nil {
		return nil, roachpb.NewError(err)
	}

	var cols []ColumnDescriptor
	// Determine which columns we're inserting into.
	if n.DefaultValues() {
		cols = tableDesc.Columns
	} else {
		var err error
		if cols, err = p.processColumns(&tableDesc, n.Columns); err != nil {
			return nil, roachpb.NewError(err)
		}
	}
	// Number of columns expecting an input. This doesn't include the
	// columns receiving a default value.
	numInputColumns := len(cols)

	// Construct a map from column ID to the index the value appears at within a
	// row.
	colIDtoRowIndex := map[ColumnID]int{}
	for i, c := range cols {
		colIDtoRowIndex[c.ID] = i
	}

	// Add the column if it has a DEFAULT expression.
	addIfDefault := func(col ColumnDescriptor) {
		if col.DefaultExpr != nil {
			if _, ok := colIDtoRowIndex[col.ID]; !ok {
				colIDtoRowIndex[col.ID] = len(cols)
				cols = append(cols, col)
			}
		}
	}

	// Add any column that has a DEFAULT expression.
	for _, col := range tableDesc.Columns {
		addIfDefault(col)
	}
	// Also add any column in a mutation that is WRITE_ONLY and has
	// a DEFAULT expression.
	for _, m := range tableDesc.Mutations {
		if m.State != DescriptorMutation_WRITE_ONLY {
			continue
		}
		if col := m.GetColumn(); col != nil {
			addIfDefault(*col)
		}
	}

	// Verify we have at least the columns that are part of the primary key.
	primaryKeyCols := map[ColumnID]struct{}{}
	for i, id := range tableDesc.PrimaryIndex.ColumnIDs {
		if _, ok := colIDtoRowIndex[id]; !ok {
			return nil, roachpb.NewUErrorf("missing %q primary key column", tableDesc.PrimaryIndex.ColumnNames[i])
		}
		primaryKeyCols[id] = struct{}{}
	}

	// Construct the default expressions. The returned slice will be nil if no
	// column in the table has a default expression.
	defaultExprs, err := makeDefaultExprs(cols, &p.parser, p.evalCtx)
	if err != nil {
		return nil, roachpb.NewError(err)
	}

	// Replace any DEFAULT markers with the corresponding default expressions.
	insertRows := p.fillDefaults(defaultExprs, cols, n)

	// Construct the check expressions. The returned slice will be nil if no
	// column in the table has a check expression.
	checkExprs, err := p.makeCheckExprs(cols)
	if err != nil {
		return nil, roachpb.NewError(err)
	}

	// Prepare the check expressions.
	var qvals qvalMap
	if len(checkExprs) > 0 {
		qvals = make(qvalMap)
		table := tableInfo{
			columns: makeResultColumns(tableDesc.Columns),
		}
		for i := range checkExprs {
			expr, err := resolveQNames(checkExprs[i], &table, qvals, &p.qnameVisitor)
			if err != nil {
				return nil, roachpb.NewError(err)
			}
			checkExprs[i] = expr
		}
	}
	// Transform the values into a rows object. This expands SELECT statements or
	// generates rows from the values contained within the query.
	rows, pErr := p.makePlan(insertRows, false)
	if pErr != nil {
		return nil, pErr
	}

	if expressions := len(rows.Columns()); expressions > numInputColumns {
		return nil, roachpb.NewUErrorf("INSERT has more expressions than target columns: %d/%d", expressions, numInputColumns)
	}

	primaryIndex := tableDesc.PrimaryIndex
	primaryIndexKeyPrefix := MakeIndexKeyPrefix(tableDesc.ID, primaryIndex.ID)

	marshalled := make([]interface{}, len(cols))

	b := p.txn.NewBatch()
	rh, err := makeReturningHelper(p, n.Returning, tableDesc.Name, tableDesc.Columns)
	if err != nil {
		return nil, roachpb.NewError(err)
	}

	// Prepare structures for building values to pass to rh.
	var retVals parser.DTuple
	var rowIdxToRetIdx []int
	if rh.exprs != nil {
		// In some cases (e.g. `INSERT INTO t (a) ...`) rowVals does not contain all the table
		// columns. We need to pass values for all table columns to rh, in the correct order; we
		// will use retVals for this. We also need a table that maps row indices to retVals indices
		// to fill in the row values; any absent values will be NULLs.

		retVals = make(parser.DTuple, len(tableDesc.Columns))
		for i := range retVals {
			retVals[i] = parser.DNull
		}

		colIDToRetIndex := map[ColumnID]int{}
		for i, col := range tableDesc.Columns {
			colIDToRetIndex[col.ID] = i
		}

		rowIdxToRetIdx = make([]int, len(cols))
		for i, col := range cols {
			rowIdxToRetIdx[i] = colIDToRetIndex[col.ID]
		}
	}

	for rows.Next() {
		rowVals := rows.Values()

		// The values for the row may be shorter than the number of columns being
		// inserted into. Generate default values for those columns using the
		// default expressions.
		for i := len(rowVals); i < len(cols); i++ {
			if defaultExprs == nil {
				rowVals = append(rowVals, parser.DNull)
				continue
			}
			d, err := defaultExprs[i].Eval(p.evalCtx)
			if err != nil {
				return nil, roachpb.NewError(err)
			}
			rowVals = append(rowVals, d)
		}

		// Check to see if NULL is being inserted into any non-nullable column.
		for _, col := range tableDesc.Columns {
			if !col.Nullable {
				if i, ok := colIDtoRowIndex[col.ID]; !ok || rowVals[i] == parser.DNull {
					return nil, roachpb.NewUErrorf("null value in column %q violates not-null constraint", col.Name)
				}
			}
		}

		// Ensure that the values honor the specified column widths.
		for i := range rowVals {
			if err := checkValueWidth(cols[i], rowVals[i]); err != nil {
				return nil, roachpb.NewError(err)
			}
		}

		if len(checkExprs) > 0 {
			// Populate qvals.
			for ref, qval := range qvals {
				// The colIdx is 0-based, we need to change it to 1-based.
				ri, has := colIDtoRowIndex[ColumnID(ref.colIdx+1)]
				if !has {
					return nil, roachpb.NewUErrorf("failed to to find column %d in row", ColumnID(ref.colIdx+1))
				}
				qval.datum = rowVals[ri]
			}
			for _, expr := range checkExprs {
				if d, err := expr.Eval(p.evalCtx); err != nil {
					return nil, roachpb.NewError(err)
				} else if res, err := parser.GetBool(d); err != nil {
					return nil, roachpb.NewError(err)
				} else if !res {
					// Failed to satisfy CHECK constraint.
					return nil, roachpb.NewUErrorf("failed to satisfy CHECK constraint (%s)", expr.String())
				}
			}
		}

		// Check that the row value types match the column types. This needs to
		// happen before index encoding because certain datum types (i.e. tuple)
		// cannot be used as index values.
		for i, val := range rowVals {
			// Make sure the value can be written to the column before proceeding.
			var mErr error
			if marshalled[i], mErr = marshalColumnValue(cols[i], val, p.evalCtx.Args); mErr != nil {
				return nil, roachpb.NewError(mErr)
			}
		}

		if p.evalCtx.PrepareOnly {
			continue
		}

		primaryIndexKey, _, eErr := encodeIndexKey(
			&primaryIndex, colIDtoRowIndex, rowVals, primaryIndexKeyPrefix)
		if eErr != nil {
			return nil, roachpb.NewError(eErr)
		}

		// Write the row sentinel. We want to write the sentinel first in case
		// we are trying to insert a duplicate primary key: if we write the
		// secondary indexes first, we may get an error that looks like a
		// uniqueness violation on a non-unique index.
		sentinelKey := keys.MakeNonColumnKey(primaryIndexKey)
		if log.V(2) {
			log.Infof("CPut %s -> NULL", roachpb.Key(sentinelKey))
		}
		// This is subtle: An interface{}(nil) deletes the value, so we pass in
		// []byte{} as a non-nil value.
		b.CPut(sentinelKey, []byte{}, nil)

		// Write the secondary indexes.
		indexes := tableDesc.Indexes
		// Also include the secondary indexes in mutation state WRITE_ONLY.
		for _, m := range tableDesc.Mutations {
			if m.State == DescriptorMutation_WRITE_ONLY {
				if index := m.GetIndex(); index != nil {
					indexes = append(indexes, *index)
				}
			}
		}
		secondaryIndexEntries, eErr := encodeSecondaryIndexes(
			tableDesc.ID, indexes, colIDtoRowIndex, rowVals)
		if eErr != nil {
			return nil, roachpb.NewError(eErr)
		}

		for _, secondaryIndexEntry := range secondaryIndexEntries {
			if log.V(2) {
				log.Infof("CPut %s -> %v", secondaryIndexEntry.key,
					secondaryIndexEntry.value)
			}
			b.CPut(secondaryIndexEntry.key, secondaryIndexEntry.value, nil)
		}

		// Write the row columns.
		for i, val := range rowVals {
			col := cols[i]
			if retVals != nil {
				retVals[rowIdxToRetIdx[i]] = val
			}

			if _, ok := primaryKeyCols[col.ID]; ok {
				// Skip primary key columns as their values are encoded in the row
				// sentinel key which is guaranteed to exist for as long as the row
				// exists.
				continue
			}

			if marshalled[i] != nil {
				// We only output non-NULL values. Non-existent column keys are
				// considered NULL during scanning and the row sentinel ensures we know
				// the row exists.

				key := keys.MakeColumnKey(primaryIndexKey, uint32(col.ID))
				if log.V(2) {
					log.Infof("CPut %s -> %v", roachpb.Key(key), val)
				}

				b.CPut(key, marshalled[i], nil)
			}
		}

		if err := rh.append(retVals); err != nil {
			return nil, roachpb.NewError(err)
		}
	}
	if pErr := rows.PErr(); pErr != nil {
		return nil, pErr
	}

	if p.evalCtx.PrepareOnly {
		// Return the result column types.
		return rh.getResults()
	}

	if isSystemConfigID(tableDesc.GetID()) {
		// Mark transaction as operating on the system DB.
		p.txn.SetSystemConfigTrigger()
	}

	if autoCommit {
		// An auto-txn can commit the transaction with the batch. This is an
		// optimization to avoid an extra round-trip to the transaction
		// coordinator.
		pErr = p.txn.CommitInBatch(b)
	} else {
		pErr = p.txn.Run(b)
	}
	if pErr != nil {
		return nil, convertBatchError(&tableDesc, *b, pErr)
	}
	return rh.getResults()
}