// sendRPC sends one or more RPCs to replicas from the supplied roachpb.Replica // slice. Returns an RPC error if the request could not be sent. Note // that the reply may contain a higher level error and must be checked in // addition to the RPC error. // The replicas are assume to have been ordered by preference, closer ones (if // any) at the front. func (ds *DistSender) sendRPC( ctx context.Context, rangeID roachpb.RangeID, replicas ReplicaSlice, ba roachpb.BatchRequest, ) (*roachpb.BatchResponse, error) { if len(replicas) == 0 { return nil, noNodeAddrsAvailError{} } // TODO(pmattis): This needs to be tested. If it isn't set we'll // still route the request appropriately by key, but won't receive // RangeNotFoundErrors. ba.RangeID = rangeID // Set RPC opts with stipulation that one of N RPCs must succeed. rpcOpts := SendOptions{ SendNextTimeout: ds.sendNextTimeout, Timeout: base.NetworkTimeout, Context: ctx, transportFactory: ds.transportFactory, } tracing.AnnotateTrace() defer tracing.AnnotateTrace() reply, err := ds.sendToReplicas(rpcOpts, rangeID, replicas, ba, ds.rpcContext) if err != nil { return nil, err } return reply, nil }
// sendRPC sends one or more RPCs to replicas from the supplied roachpb.Replica // slice. First, replicas which have gossiped addresses are corralled (and // rearranged depending on proximity and whether the request needs to go to a // leader) and then sent via Send, with requirement that one RPC to a server // must succeed. Returns an RPC error if the request could not be sent. Note // that the reply may contain a higher level error and must be checked in // addition to the RPC error. func (ds *DistSender) sendRPC(trace opentracing.Span, rangeID roachpb.RangeID, replicas ReplicaSlice, order orderingPolicy, ba roachpb.BatchRequest) (*roachpb.BatchResponse, *roachpb.Error) { if len(replicas) == 0 { return nil, roachpb.NewError(noNodeAddrsAvailError{}) } // TODO(pmattis): This needs to be tested. If it isn't set we'll // still route the request appropriately by key, but won't receive // RangeNotFoundErrors. ba.RangeID = rangeID // Set RPC opts with stipulation that one of N RPCs must succeed. rpcOpts := SendOptions{ Ordering: order, SendNextTimeout: defaultSendNextTimeout, Timeout: rpc.DefaultRPCTimeout, Trace: trace, } tracing.AnnotateTrace() defer tracing.AnnotateTrace() reply, err := ds.rpcSend(rpcOpts, replicas, ba, ds.rpcContext) if err != nil { return nil, roachpb.NewError(err) } return reply.(*roachpb.BatchResponse), nil }
// Run implements Runner.Run(). See comments there. func (txn *Txn) Run(b *Batch) error { tracing.AnnotateTrace() defer tracing.AnnotateTrace() if err := b.prepare(); err != nil { return err } return sendAndFill(txn.send, b) }
// RunWithResponse is a version of Run that returns the BatchResponse. func (txn *Txn) RunWithResponse(b *Batch) (*roachpb.BatchResponse, *roachpb.Error) { tracing.AnnotateTrace() defer tracing.AnnotateTrace() if pErr := b.prepare(); pErr != nil { return nil, pErr } return sendAndFill(txn.send, b) }
func (c *v3Conn) executeStatements(stmts string, params []parser.Datum, formatCodes []formatCode, sendDescription bool, limit int32) error { tracing.AnnotateTrace() results := c.executor.ExecuteStatements(c.session, stmts, params) tracing.AnnotateTrace() if results.Empty { // Skip executor and just send EmptyQueryResponse. c.writeBuf.initMsg(serverMsgEmptyQuery) return c.writeBuf.finishMsg(c.wr) } return c.sendResponse(results.ResultList, formatCodes, sendDescription, limit) }
func (c *v3Conn) executeStatements(stmts string, params []parser.Datum, formatCodes []formatCode, sendDescription bool) error { tracing.AnnotateTrace() c.session.Database = c.opts.database // TODO(dt): this is a clumsy check better left to the actual parser. #3852 if len(strings.TrimSpace(stmts)) == 0 { // Skip executor and just send EmptyQueryResponse. c.writeBuf.initMsg(serverMsgEmptyQuery) return c.writeBuf.finishMsg(c.wr) } resp, _, err := c.executor.ExecuteStatements(c.opts.user, c.session, stmts, params) if err != nil { return c.sendError(err.Error()) } c.session.Reset() if err := c.session.Unmarshal(resp.Session); err != nil { return err } c.opts.database = c.session.Database return c.sendResponse(resp, formatCodes, sendDescription) }
func (n *scanNode) Next() bool { tracing.AnnotateTrace() if n.pErr != nil { return false } if n.kvs == nil { if !n.initScan() { return false } } // All of the columns for a particular row will be grouped together. We loop // over the key/value pairs and decode the key to extract the columns encoded // within the key and the column ID. We use the column ID to lookup the // column and decode the value. All of these values go into a map keyed by // column name. When the index key changes we output a row containing the // current values. for { if n.maybeOutputRow() { return n.pErr == nil } if n.kvIndex == len(n.kvs) { return false } if !n.processKV(n.kvs[n.kvIndex]) { return false } n.kvIndex++ } }
// send runs the specified calls synchronously in a single batch and returns // any errors. Returns a nil response for empty input (no requests). func (db *DB) send(maxScanResults int64, reqs ...roachpb.Request) ( *roachpb.BatchResponse, *roachpb.Error) { if len(reqs) == 0 { return nil, nil } ba := roachpb.BatchRequest{} ba.Add(reqs...) ba.MaxScanResults = maxScanResults if db.userPriority != 1 { ba.UserPriority = db.userPriority } tracing.AnnotateTrace() br, pErr := db.sender.Send(context.TODO(), ba) if pErr != nil { if log.V(1) { log.Infof("failed batch: %s", pErr) } return nil, pErr } return br, nil }
func (n *scanNode) Next() bool { tracing.AnnotateTrace() if n.err != nil { return false } if !n.scanInitialized && !n.initScan() { // Hit error during initScan return false } if n.explain == explainDebug { return n.debugNext() } // We fetch one row at a time until we find one that passes the filter. for { n.row, n.err = n.fetcher.NextRow() if n.err != nil || n.row == nil { return false } passesFilter, err := runFilter(n.filter, n.planner.evalCtx) if err != nil { n.err = err return false } if passesFilter { return true } } }
// send runs the specified calls synchronously in a single batch and returns // any errors. Returns a nil response for empty input (no requests). func (db *DB) send(maxScanResults int64, readConsistency roachpb.ReadConsistencyType, reqs ...roachpb.Request) (*roachpb.BatchResponse, *roachpb.Error) { if len(reqs) == 0 { return nil, nil } if readConsistency == roachpb.INCONSISTENT { for _, req := range reqs { if req.Method() != roachpb.Get && req.Method() != roachpb.Scan && req.Method() != roachpb.ReverseScan { return nil, roachpb.NewErrorf("method %s not allowed with INCONSISTENT batch", req.Method) } } } ba := roachpb.BatchRequest{} ba.Add(reqs...) ba.MaxScanResults = maxScanResults if db.userPriority != 1 { ba.UserPriority = db.userPriority } ba.ReadConsistency = readConsistency tracing.AnnotateTrace() br, pErr := db.sender.Send(context.TODO(), ba) if pErr != nil { if log.V(1) { log.Infof("failed batch: %s", pErr) } return nil, pErr } return br, nil }
// send runs the specified calls synchronously in a single batch and returns // any errors. Returns (nil, nil) for an empty batch. func (db *DB) send(ba roachpb.BatchRequest) (*roachpb.BatchResponse, *roachpb.Error) { if len(ba.Requests) == 0 { return nil, nil } if ba.ReadConsistency == roachpb.INCONSISTENT { for _, ru := range ba.Requests { req := ru.GetInner() if req.Method() != roachpb.Get && req.Method() != roachpb.Scan && req.Method() != roachpb.ReverseScan { return nil, roachpb.NewErrorf("method %s not allowed with INCONSISTENT batch", req.Method) } } } if db.ctx.UserPriority != 1 { ba.UserPriority = db.ctx.UserPriority } tracing.AnnotateTrace() br, pErr := db.sender.Send(context.TODO(), ba) if pErr != nil { if log.V(1) { log.Infof("failed batch: %s", pErr) } return nil, pErr } return br, 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 } } }
func (u *updateNode) Next() (bool, error) { next, err := u.run.rows.Next() if !next { if err == nil { // We're done. Finish the batch. err = u.tw.finalize() } return false, err } if u.run.explain == explainDebug { return true, nil } tracing.AnnotateTrace() oldValues := u.run.rows.Values() // Our updated value expressions occur immediately after the plain // columns in the output. updateValues := oldValues[len(u.tw.ru.fetchCols):] oldValues = oldValues[:len(u.tw.ru.fetchCols)] u.checkHelper.loadRow(u.tw.ru.fetchColIDtoRowIndex, oldValues, false) u.checkHelper.loadRow(u.updateColsIdx, updateValues, true) if err := u.checkHelper.check(&u.p.evalCtx); err != nil { return false, err } // Ensure that the values honor the specified column widths. for i := range updateValues { if err := sqlbase.CheckValueWidth(u.tw.ru.updateCols[i], updateValues[i]); err != nil { return false, err } } // Update the row values. for i, col := range u.tw.ru.updateCols { val := updateValues[i] if !col.Nullable && val == parser.DNull { return false, sqlbase.NewNonNullViolationError(col.Name) } } newValues, err := u.tw.row(append(oldValues, updateValues...)) if err != nil { return false, err } resultRow, err := u.rh.cookResultRow(newValues) if err != nil { return false, err } u.run.resultRow = resultRow return true, nil }
func (c *v3Conn) executeStatements( ctx context.Context, stmts string, pinfo *parser.PlaceholderInfo, formatCodes []formatCode, sendDescription bool, limit int, ) error { tracing.AnnotateTrace() results := c.executor.ExecuteStatements(ctx, c.session, stmts, pinfo) tracing.AnnotateTrace() if results.Empty { // Skip executor and just send EmptyQueryResponse. c.writeBuf.initMsg(serverMsgEmptyQuery) return c.writeBuf.finishMsg(c.wr) } return c.sendResponse(results.ResultList, formatCodes, sendDescription, limit) }
func (u *updateNode) Next() bool { if u.run.done || u.run.err != nil { return false } if !u.run.rows.Next() { // We're done. Finish the batch. err := u.tw.finalize() u.run.err = err u.run.done = true return false } tracing.AnnotateTrace() oldValues := u.run.rows.Values() // Our updated value expressions occur immediately after the plain // columns in the output. updateValues := oldValues[len(u.tableDesc.Columns):] oldValues = oldValues[:len(u.tableDesc.Columns)] // Ensure that the values honor the specified column widths. for i := range updateValues { if err := sqlbase.CheckValueWidth(u.updateCols[i], updateValues[i]); err != nil { u.run.err = err return false } } // Update the row values. for i, col := range u.updateCols { val := updateValues[i] if !col.Nullable && val == parser.DNull { u.run.err = fmt.Errorf("null value in column %q violates not-null constraint", col.Name) return false } } newValues, err := u.tw.row(append(oldValues, updateValues...)) if err != nil { u.run.err = err return false } resultRow, err := u.rh.cookResultRow(newValues) if err != nil { u.run.err = err return false } u.run.resultRow = resultRow return true }
// Update updates columns for a selection of rows from a table. // Privileges: UPDATE and SELECT on table. We currently always use a select statement. // Notes: postgres requires UPDATE. Requires SELECT with WHERE clause with table. // mysql requires UPDATE. Also requires SELECT with WHERE clause with table. // TODO(guanqun): need to support CHECK in UPDATE func (p *planner) Update(n *parser.Update, desiredTypes []parser.Datum, autoCommit bool) (planNode, error) { tracing.AnnotateTrace() en, err := p.makeEditNode(n.Table, n.Returning, desiredTypes, autoCommit, privilege.UPDATE) if err != nil { return nil, err } exprs := make([]*parser.UpdateExpr, len(n.Exprs)) for i, expr := range n.Exprs { // Replace the sub-query nodes. newExpr, err := p.replaceSubqueries(expr.Expr, len(expr.Names)) if err != nil { return nil, err } exprs[i] = &parser.UpdateExpr{Tuple: expr.Tuple, Expr: newExpr, Names: expr.Names} } // Determine which columns we're inserting into. names, err := p.namesForExprs(exprs) if err != nil { return nil, err } updateCols, err := p.processColumns(en.tableDesc, names) if err != nil { return nil, err } defaultExprs, err := makeDefaultExprs(updateCols, &p.parser, p.evalCtx) if err != nil { return nil, err } var requestedCols []sqlbase.ColumnDescriptor if len(en.rh.exprs) > 0 || len(en.tableDesc.Checks) > 0 { // TODO(dan): This could be made tighter, just the rows needed for RETURNING // exprs. requestedCols = en.tableDesc.Columns } ru, err := makeRowUpdater(en.tableDesc, updateCols, requestedCols) if err != nil { return nil, err } tw := tableUpdater{ru: ru, autoCommit: autoCommit} tracing.AnnotateTrace() // Generate the list of select targets. We need to select all of the columns // plus we select all of the update expressions in case those expressions // reference columns (e.g. "UPDATE t SET v = v + 1"). Note that we flatten // expressions for tuple assignments just as we flattened the column names // above. So "UPDATE t SET (a, b) = (1, 2)" translates into select targets of // "*, 1, 2", not "*, (1, 2)". targets := sqlbase.ColumnsSelectors(ru.fetchCols) i := 0 // Remember the index where the targets for exprs start. exprTargetIdx := len(targets) desiredTypesFromSelect := make([]parser.Datum, len(targets), len(targets)+len(exprs)) for _, expr := range exprs { if expr.Tuple { switch t := expr.Expr.(type) { case (*parser.Tuple): for _, e := range t.Exprs { typ := updateCols[i].Type.ToDatumType() e := fillDefault(e, typ, i, defaultExprs) targets = append(targets, parser.SelectExpr{Expr: e}) desiredTypesFromSelect = append(desiredTypesFromSelect, typ) i++ } default: return nil, fmt.Errorf("cannot use this expression to assign multiple columns: %s", expr.Expr) } } else { typ := updateCols[i].Type.ToDatumType() e := fillDefault(expr.Expr, typ, i, defaultExprs) targets = append(targets, parser.SelectExpr{Expr: e}) desiredTypesFromSelect = append(desiredTypesFromSelect, typ) i++ } } rows, err := p.SelectClause(&parser.SelectClause{ Exprs: targets, From: []parser.TableExpr{n.Table}, Where: n.Where, }, nil, nil, desiredTypesFromSelect) if err != nil { return nil, err } // ValArgs have their types populated in the above Select if they are part // of an expression ("SET a = 2 + $1") in the type check step where those // types are inferred. For the simpler case ("SET a = $1"), populate them // using checkColumnType. This step also verifies that the expression // types match the column types. sel := rows.(*selectTopNode).source.(*selectNode) for i, target := range sel.render[exprTargetIdx:] { // DefaultVal doesn't implement TypeCheck if _, ok := target.(parser.DefaultVal); ok { continue } // TODO(nvanbenschoten) isn't this TypeCheck redundant with the call to SelectClause? typedTarget, err := parser.TypeCheck(target, &p.semaCtx, updateCols[i].Type.ToDatumType()) if err != nil { return nil, err } err = sqlbase.CheckColumnType(updateCols[i], typedTarget.ReturnType(), p.semaCtx.Args) if err != nil { return nil, err } } if err := en.rh.TypeCheck(); err != nil { return nil, err } updateColsIdx := make(map[sqlbase.ColumnID]int, len(ru.updateCols)) for i, col := range ru.updateCols { updateColsIdx[col.ID] = i } un := &updateNode{ n: n, editNodeBase: en, updateCols: ru.updateCols, updateColsIdx: updateColsIdx, tw: tw, } if err := un.checkHelper.init(p, en.tableDesc); err != nil { return nil, err } un.run.initEditNode(rows) return un, nil }
// Update updates columns for a selection of rows from a table. // Privileges: UPDATE and SELECT on table. We currently always use a select statement. // Notes: postgres requires UPDATE. Requires SELECT with WHERE clause with table. // mysql requires UPDATE. Also requires SELECT with WHERE clause with table. // TODO(guanqun): need to support CHECK in UPDATE func (p *planner) Update(n *parser.Update, autoCommit bool) (planNode, *roachpb.Error) { tracing.AnnotateTrace() tableDesc, pErr := p.getAliasedTableLease(n.Table) if pErr != nil { return nil, pErr } if err := p.checkPrivilege(tableDesc, privilege.UPDATE); err != nil { return nil, roachpb.NewError(err) } // TODO(dan): Consider caching this on the TableDescriptor. primaryKeyCols := map[ColumnID]struct{}{} for _, id := range tableDesc.PrimaryIndex.ColumnIDs { primaryKeyCols[id] = struct{}{} } exprs := make([]parser.UpdateExpr, len(n.Exprs)) for i, expr := range n.Exprs { exprs[i] = *expr } // Determine which columns we're inserting into. var names parser.QualifiedNames for i, expr := range exprs { newExpr, epErr := p.expandSubqueries(expr.Expr, len(expr.Names)) if epErr != nil { return nil, epErr } exprs[i].Expr = newExpr if expr.Tuple { // TODO(pmattis): The distinction between Tuple and DTuple here is // irritating. We'll see a DTuple if the expression was a subquery that // has been evaluated. We'll see a Tuple in other cases. n := 0 switch t := newExpr.(type) { case *parser.Tuple: n = len(t.Exprs) case parser.DTuple: n = len(t) default: return nil, roachpb.NewErrorf("unsupported tuple assignment: %T", newExpr) } if len(expr.Names) != n { return nil, roachpb.NewUErrorf("number of columns (%d) does not match number of values (%d)", len(expr.Names), n) } } names = append(names, expr.Names...) } cols, err := p.processColumns(tableDesc, names) if err != nil { return nil, roachpb.NewError(err) } // Set of columns being updated var primaryKeyColChange bool colIDSet := map[ColumnID]struct{}{} for _, c := range cols { colIDSet[c.ID] = struct{}{} if _, ok := primaryKeyCols[c.ID]; ok { primaryKeyColChange = true } } defaultExprs, err := makeDefaultExprs(cols, &p.parser, p.evalCtx) if err != nil { return nil, roachpb.NewError(err) } // Generate the list of select targets. We need to select all of the columns // plus we select all of the update expressions in case those expressions // reference columns (e.g. "UPDATE t SET v = v + 1"). Note that we flatten // expressions for tuple assignments just as we flattened the column names // above. So "UPDATE t SET (a, b) = (1, 2)" translates into select targets of // "*, 1, 2", not "*, (1, 2)". // TODO(radu): we only need to select columns necessary to generate primary and // secondary indexes keys, and columns needed by returningHelper. targets := tableDesc.allColumnsSelector() i := 0 // Remember the index where the targets for exprs start. exprTargetIdx := len(targets) for _, expr := range exprs { if expr.Tuple { switch t := expr.Expr.(type) { case *parser.Tuple: for _, e := range t.Exprs { e = fillDefault(e, i, defaultExprs) targets = append(targets, parser.SelectExpr{Expr: e}) i++ } case parser.DTuple: for _, e := range t { targets = append(targets, parser.SelectExpr{Expr: e}) i++ } } } else { e := fillDefault(expr.Expr, i, defaultExprs) targets = append(targets, parser.SelectExpr{Expr: e}) i++ } } tracing.AnnotateTrace() // Query the rows that need updating. rows, pErr := p.SelectClause(&parser.SelectClause{ Exprs: targets, From: []parser.TableExpr{n.Table}, Where: n.Where, }) if pErr != nil { return nil, pErr } rh, err := makeReturningHelper(p, n.Returning, tableDesc.Name, tableDesc.Columns) if err != nil { return nil, roachpb.NewError(err) } // ValArgs have their types populated in the above Select if they are part // of an expression ("SET a = 2 + $1") in the type check step where those // types are inferred. For the simpler case ("SET a = $1"), populate them // using marshalColumnValue. This step also verifies that the expression // types match the column types. if p.evalCtx.PrepareOnly { for i, target := range rows.(*selectNode).render[exprTargetIdx:] { // DefaultVal doesn't implement TypeCheck if _, ok := target.(parser.DefaultVal); ok { continue } d, err := target.TypeCheck(p.evalCtx.Args) if err != nil { return nil, roachpb.NewError(err) } if _, err := marshalColumnValue(cols[i], d, p.evalCtx.Args); err != nil { return nil, roachpb.NewError(err) } } // Return the result column types. return rh.getResults() } // Construct a map from column ID to the index the value appears at within a // row. colIDtoRowIndex := map[ColumnID]int{} for i, col := range tableDesc.Columns { colIDtoRowIndex[col.ID] = i } primaryIndex := tableDesc.PrimaryIndex primaryIndexKeyPrefix := MakeIndexKeyPrefix(tableDesc.ID, primaryIndex.ID) // Secondary indexes needing updating. needsUpdate := func(index IndexDescriptor) bool { // If the primary key changed, we need to update all of them. if primaryKeyColChange { return true } for _, id := range index.ColumnIDs { if _, ok := colIDSet[id]; ok { return true } } return false } indexes := make([]IndexDescriptor, 0, len(tableDesc.Indexes)+len(tableDesc.Mutations)) var deleteOnlyIndex map[int]struct{} for _, index := range tableDesc.Indexes { if needsUpdate(index) { indexes = append(indexes, index) } } for _, m := range tableDesc.Mutations { if index := m.GetIndex(); index != nil { if needsUpdate(*index) { indexes = append(indexes, *index) switch m.State { case DescriptorMutation_DELETE_ONLY: if deleteOnlyIndex == nil { // Allocate at most once. deleteOnlyIndex = make(map[int]struct{}, len(tableDesc.Mutations)) } deleteOnlyIndex[len(indexes)-1] = struct{}{} case DescriptorMutation_WRITE_ONLY: } } } } marshalled := make([]interface{}, len(cols)) b := p.txn.NewBatch() tracing.AnnotateTrace() for rows.Next() { tracing.AnnotateTrace() rowVals := rows.Values() primaryIndexKey, _, err := encodeIndexKey( &primaryIndex, colIDtoRowIndex, rowVals, primaryIndexKeyPrefix) if err != nil { return nil, roachpb.NewError(err) } // Compute the current secondary index key:value pairs for this row. secondaryIndexEntries, err := encodeSecondaryIndexes( tableDesc.ID, indexes, colIDtoRowIndex, rowVals) if err != nil { return nil, roachpb.NewError(err) } // Our updated value expressions occur immediately after the plain // columns in the output. newVals := rowVals[len(tableDesc.Columns):] // Ensure that the values honor the specified column widths. for i := range newVals { if err := checkValueWidth(cols[i], newVals[i]); err != nil { return nil, roachpb.NewError(err) } } // Update the row values. for i, col := range cols { val := newVals[i] if !col.Nullable && val == parser.DNull { return nil, roachpb.NewUErrorf("null value in column %q violates not-null constraint", col.Name) } rowVals[colIDtoRowIndex[col.ID]] = val } // Check that the new 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 newVals { var mErr error if marshalled[i], mErr = marshalColumnValue(cols[i], val, p.evalCtx.Args); mErr != nil { return nil, roachpb.NewError(mErr) } } // Compute the new primary index key for this row. newPrimaryIndexKey := primaryIndexKey var rowPrimaryKeyChanged bool if primaryKeyColChange { newPrimaryIndexKey, _, err = encodeIndexKey( &primaryIndex, colIDtoRowIndex, rowVals, primaryIndexKeyPrefix) if err != nil { return nil, roachpb.NewError(err) } // Note that even if primaryIndexColChange is true, it's possible that // primary key fields in this particular row didn't change. rowPrimaryKeyChanged = !bytes.Equal(primaryIndexKey, newPrimaryIndexKey) } // Compute the new secondary index key:value pairs for this row. newSecondaryIndexEntries, eErr := encodeSecondaryIndexes( tableDesc.ID, indexes, colIDtoRowIndex, rowVals) if eErr != nil { return nil, roachpb.NewError(eErr) } if rowPrimaryKeyChanged { // Delete all the data stored under the old primary key. rowStartKey := roachpb.Key(primaryIndexKey) rowEndKey := rowStartKey.PrefixEnd() if log.V(2) { log.Infof("DelRange %s - %s", rowStartKey, rowEndKey) } b.DelRange(rowStartKey, rowEndKey, false) // Delete all the old secondary indexes. for _, secondaryIndexEntry := range secondaryIndexEntries { if log.V(2) { log.Infof("Del %s", secondaryIndexEntry.key) } b.Del(secondaryIndexEntry.key) } // Write the new 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(newPrimaryIndexKey) 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 any fields from the old row that were not modified by the UPDATE. for i, col := range tableDesc.Columns { if _, ok := colIDSet[col.ID]; ok { continue } if _, ok := primaryKeyCols[col.ID]; ok { continue } key := keys.MakeColumnKey(newPrimaryIndexKey, uint32(col.ID)) val := rowVals[i] marshalledVal, mErr := marshalColumnValue(col, val, p.evalCtx.Args) if mErr != nil { return nil, roachpb.NewError(mErr) } if log.V(2) { log.Infof("Put %s -> %v", roachpb.Key(key), val) } b.Put(key, marshalledVal) } // At this point, we've deleted the old row and associated index data and // written the sentinel keys and column keys for non-updated columns. Fall // through to below where the index keys and updated column keys will be // written. } // Update secondary indexes. for i, newSecondaryIndexEntry := range newSecondaryIndexEntries { secondaryIndexEntry := secondaryIndexEntries[i] secondaryKeyChanged := !bytes.Equal(newSecondaryIndexEntry.key, secondaryIndexEntry.key) if secondaryKeyChanged { if log.V(2) { log.Infof("Del %s", secondaryIndexEntry.key) } b.Del(secondaryIndexEntry.key) } if rowPrimaryKeyChanged || secondaryKeyChanged { // Do not update Indexes in the DELETE_ONLY state. if _, ok := deleteOnlyIndex[i]; !ok { if log.V(2) { log.Infof("CPut %s -> %v", newSecondaryIndexEntry.key, newSecondaryIndexEntry.value) } b.CPut(newSecondaryIndexEntry.key, newSecondaryIndexEntry.value, nil) } } } // Add the new values. for i, val := range newVals { col := cols[i] 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 } key := keys.MakeColumnKey(newPrimaryIndexKey, uint32(col.ID)) 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. if log.V(2) { log.Infof("Put %s -> %v", roachpb.Key(key), val) } b.Put(key, marshalled[i]) } else { // The column might have already existed but is being set to NULL, so // delete it. if log.V(2) { log.Infof("Del %s", key) } b.Del(key) } } // rowVals[:len(tableDesc.Columns)] have been updated with the new values above. if err := rh.append(rowVals[:len(tableDesc.Columns)]); err != nil { return nil, roachpb.NewError(err) } } tracing.AnnotateTrace() if pErr := rows.PErr(); pErr != nil { return nil, pErr } 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) } tracing.AnnotateTrace() return rh.getResults() }
// Send implements the batch.Sender interface. It subdivides // the Batch into batches admissible for sending (preventing certain // illegal mixtures of requests), executes each individual part // (which may span multiple ranges), and recombines the response. // When the request spans ranges, it is split up and the corresponding // ranges queried serially, in ascending order. // In particular, the first write in a transaction may not be part of the first // request sent. This is relevant since the first write is a BeginTransaction // request, thus opening up a window of time during which there may be intents // of a transaction, but no entry. Pushing such a transaction will succeed, and // may lead to the transaction being aborted early. func (ds *DistSender) Send(ctx context.Context, ba roachpb.BatchRequest) (*roachpb.BatchResponse, *roachpb.Error) { tracing.AnnotateTrace() // In the event that timestamp isn't set and read consistency isn't // required, set the timestamp using the local clock. if ba.ReadConsistency == roachpb.INCONSISTENT && ba.Timestamp.Equal(roachpb.ZeroTimestamp) { ba.Timestamp = ds.clock.Now() } if ba.Txn != nil && len(ba.Txn.CertainNodes.Nodes) == 0 { // Ensure the local NodeID is marked as free from clock offset; // the transaction's timestamp was taken off the local clock. if nDesc := ds.getNodeDescriptor(); nDesc != nil { // TODO(tschottdorf): future refactoring should move this to txn // creation in TxnCoordSender, which is currently unaware of the // NodeID (and wraps *DistSender through client.Sender since it // also needs test compatibility with *LocalSender). // // Taking care below to not modify any memory referenced from // our BatchRequest which may be shared with others. // First, get a shallow clone of our txn (since that holds the // NodeList struct). txnShallow := *ba.Txn // Next, zero out the NodeList pointer. That makes sure that // if we had something of size zero but with capacity, we don't // re-use the existing space (which others may also use). txnShallow.CertainNodes.Nodes = nil txnShallow.CertainNodes.Add(nDesc.NodeID) ba.Txn = &txnShallow } } if len(ba.Requests) < 1 { panic("empty batch") } var rplChunks []*roachpb.BatchResponse parts := ba.Split(false /* don't split ET */) for len(parts) > 0 { part := parts[0] ba.Requests = part rpl, pErr, shouldSplitET := ds.sendChunk(ctx, ba) if shouldSplitET { // If we tried to send a single round-trip EndTransaction but // it looks like it's going to hit multiple ranges, split it // here and try again. if len(parts) != 1 { panic("EndTransaction not in last chunk of batch") } parts = ba.Split(true /* split ET */) if len(parts) != 2 { panic("split of final EndTransaction chunk resulted in != 2 parts") } continue } if pErr != nil { return nil, pErr } // Propagate transaction from last reply to next request. The final // update is taken and put into the response's main header. ba.Txn.Update(rpl.Header().Txn) rplChunks = append(rplChunks, rpl) parts = parts[1:] } reply := rplChunks[0] for _, rpl := range rplChunks[1:] { reply.Responses = append(reply.Responses, rpl.Responses...) } *reply.Header() = rplChunks[len(rplChunks)-1].BatchResponse_Header return reply, nil }
// makePlan creates the query plan for a single SQL statement. The returned // plan needs to be iterated over using planNode.Next() and planNode.Values() // in order to retrieve matching rows. If autoCommit is true, the plan is // allowed (but not required) to commit the transaction along with other KV // operations. // // Note: The autoCommit parameter enables operations to enable the 1PC // optimization. This is a bit hackish/preliminary at present. func (p *planner) makePlan(stmt parser.Statement, autoCommit bool) (planNode, *roachpb.Error) { tracing.AnnotateTrace() // This will set the system DB trigger for transactions containing // DDL statements that have no effect, such as // `BEGIN; INSERT INTO ...; CREATE TABLE IF NOT EXISTS ...; COMMIT;` // where the table already exists. This will generate some false // refreshes, but that's expected to be quite rare in practice. if stmt.StatementType() == parser.DDL { p.txn.SetSystemConfigTrigger() } switch n := stmt.(type) { case *parser.AlterTable: return p.AlterTable(n) case *parser.BeginTransaction: pNode, err := p.BeginTransaction(n) return pNode, roachpb.NewError(err) case *parser.CommitTransaction: return p.CommitTransaction(n) case *parser.CreateDatabase: return p.CreateDatabase(n) case *parser.CreateIndex: return p.CreateIndex(n) case *parser.CreateTable: return p.CreateTable(n) case *parser.Delete: return p.Delete(n) case *parser.DropDatabase: return p.DropDatabase(n) case *parser.DropIndex: return p.DropIndex(n) case *parser.DropTable: return p.DropTable(n) case *parser.Explain: return p.Explain(n) case *parser.Grant: return p.Grant(n) case *parser.Insert: return p.Insert(n, autoCommit) case *parser.ParenSelect: return p.makePlan(n.Select, autoCommit) case *parser.RenameColumn: return p.RenameColumn(n) case *parser.RenameDatabase: return p.RenameDatabase(n) case *parser.RenameIndex: return p.RenameIndex(n) case *parser.RenameTable: return p.RenameTable(n) case *parser.Revoke: return p.Revoke(n) case *parser.RollbackTransaction: return p.RollbackTransaction(n) case *parser.Select: return p.Select(n) case *parser.Set: return p.Set(n) case *parser.SetTimeZone: return p.SetTimeZone(n) case *parser.SetTransaction: pNode, err := p.SetTransaction(n) return pNode, roachpb.NewError(err) case *parser.Show: return p.Show(n) case *parser.ShowColumns: return p.ShowColumns(n) case *parser.ShowDatabases: return p.ShowDatabases(n) case *parser.ShowGrants: return p.ShowGrants(n) case *parser.ShowIndex: return p.ShowIndex(n) case *parser.ShowTables: return p.ShowTables(n) case *parser.Truncate: return p.Truncate(n) case *parser.Update: return p.Update(n) case parser.Values: return p.Values(n) default: return nil, roachpb.NewErrorf("unknown statement type: %T", stmt) } }
// Update updates columns for a selection of rows from a table. // Privileges: UPDATE and SELECT on table. We currently always use a select statement. // Notes: postgres requires UPDATE. Requires SELECT with WHERE clause with table. // mysql requires UPDATE. Also requires SELECT with WHERE clause with table. func (p *planner) Update(n *parser.Update, autoCommit bool) (planNode, *roachpb.Error) { tracing.AnnotateTrace() tableDesc, pErr := p.getAliasedTableLease(n.Table) if pErr != nil { return nil, pErr } if err := p.checkPrivilege(tableDesc, privilege.UPDATE); err != nil { return nil, roachpb.NewError(err) } // Determine which columns we're inserting into. var names parser.QualifiedNames for _, expr := range n.Exprs { var epErr *roachpb.Error expr.Expr, epErr = p.expandSubqueries(expr.Expr, len(expr.Names)) if epErr != nil { return nil, epErr } if expr.Tuple { // TODO(pmattis): The distinction between Tuple and DTuple here is // irritating. We'll see a DTuple if the expression was a subquery that // has been evaluated. We'll see a Tuple in other cases. n := 0 switch t := expr.Expr.(type) { case parser.Tuple: n = len(t) case parser.DTuple: n = len(t) default: return nil, roachpb.NewErrorf("unsupported tuple assignment: %T", expr.Expr) } if len(expr.Names) != n { return nil, roachpb.NewUErrorf("number of columns (%d) does not match number of values (%d)", len(expr.Names), n) } } names = append(names, expr.Names...) } cols, err := p.processColumns(tableDesc, names) if err != nil { return nil, roachpb.NewError(err) } // Set of columns being updated colIDSet := map[ColumnID]struct{}{} for _, c := range cols { colIDSet[c.ID] = struct{}{} } // Don't allow updating any column that is part of the primary key. for i, id := range tableDesc.PrimaryIndex.ColumnIDs { if _, ok := colIDSet[id]; ok { return nil, roachpb.NewUErrorf("primary key column %q cannot be updated", tableDesc.PrimaryIndex.ColumnNames[i]) } } defaultExprs, err := p.makeDefaultExprs(cols) if err != nil { return nil, roachpb.NewError(err) } // Generate the list of select targets. We need to select all of the columns // plus we select all of the update expressions in case those expressions // reference columns (e.g. "UPDATE t SET v = v + 1"). Note that we flatten // expressions for tuple assignments just as we flattened the column names // above. So "UPDATE t SET (a, b) = (1, 2)" translates into select targets of // "*, 1, 2", not "*, (1, 2)". targets := tableDesc.allColumnsSelector() i := 0 for _, expr := range n.Exprs { if expr.Tuple { switch t := expr.Expr.(type) { case parser.Tuple: for _, e := range t { e = fillDefault(e, i, defaultExprs) targets = append(targets, parser.SelectExpr{Expr: e}) i++ } case parser.DTuple: for _, e := range t { targets = append(targets, parser.SelectExpr{Expr: e}) i++ } } } else { e := fillDefault(expr.Expr, i, defaultExprs) targets = append(targets, parser.SelectExpr{Expr: e}) i++ } } tracing.AnnotateTrace() // Query the rows that need updating. rows, pErr := p.Select(&parser.Select{ Exprs: targets, From: parser.TableExprs{n.Table}, Where: n.Where, }) if pErr != nil { return nil, pErr } // ValArgs have their types populated in the above Select if they are part // of an expression ("SET a = 2 + $1") in the type check step where those // types are inferred. For the simpler case ("SET a = $1"), populate them // using marshalColumnValue. This step also verifies that the expression // types match the column types. if p.prepareOnly { i := 0 f := func(expr parser.Expr) *roachpb.Error { idx := i i++ // DefaultVal doesn't implement TypeCheck if _, ok := expr.(parser.DefaultVal); ok { return nil } d, err := expr.TypeCheck(p.evalCtx.Args) if err != nil { return roachpb.NewError(err) } if _, err := marshalColumnValue(cols[idx], d, p.evalCtx.Args); err != nil { return roachpb.NewError(err) } return nil } for _, expr := range n.Exprs { if expr.Tuple { switch t := expr.Expr.(type) { case parser.Tuple: for _, e := range t { if err := f(e); err != nil { return nil, err } } case parser.DTuple: for _, e := range t { if err := f(e); err != nil { return nil, err } } } } else { if err := f(expr.Expr); err != nil { return nil, err } } } return nil, nil } // Construct a map from column ID to the index the value appears at within a // row. colIDtoRowIndex := map[ColumnID]int{} for i, col := range tableDesc.Columns { colIDtoRowIndex[col.ID] = i } primaryIndex := tableDesc.PrimaryIndex primaryIndexKeyPrefix := MakeIndexKeyPrefix(tableDesc.ID, primaryIndex.ID) // Secondary indexes needing updating. needsUpdate := func(index IndexDescriptor) bool { for _, id := range index.ColumnIDs { if _, ok := colIDSet[id]; ok { return true } } return false } indexes := make([]IndexDescriptor, 0, len(tableDesc.Indexes)+len(tableDesc.Mutations)) var deleteOnlyIndex map[int]struct{} for _, index := range tableDesc.Indexes { if needsUpdate(index) { indexes = append(indexes, index) } } for _, m := range tableDesc.Mutations { if index := m.GetIndex(); index != nil { if needsUpdate(*index) { indexes = append(indexes, *index) switch m.State { case DescriptorMutation_DELETE_ONLY: if deleteOnlyIndex == nil { // Allocate at most once. deleteOnlyIndex = make(map[int]struct{}, len(tableDesc.Mutations)) } deleteOnlyIndex[len(indexes)-1] = struct{}{} case DescriptorMutation_WRITE_ONLY: } } } } marshalled := make([]interface{}, len(cols)) b := p.txn.NewBatch() result := &valuesNode{} tracing.AnnotateTrace() for rows.Next() { tracing.AnnotateTrace() rowVals := rows.Values() result.rows = append(result.rows, parser.DTuple(nil)) primaryIndexKey, _, err := encodeIndexKey( &primaryIndex, colIDtoRowIndex, rowVals, primaryIndexKeyPrefix) if err != nil { return nil, roachpb.NewError(err) } // Compute the current secondary index key:value pairs for this row. secondaryIndexEntries, err := encodeSecondaryIndexes( tableDesc.ID, indexes, colIDtoRowIndex, rowVals) if err != nil { return nil, roachpb.NewError(err) } // Our updated value expressions occur immediately after the plain // columns in the output. newVals := rowVals[len(tableDesc.Columns):] // Update the row values. for i, col := range cols { val := newVals[i] if !col.Nullable && val == parser.DNull { return nil, roachpb.NewUErrorf("null value in column %q violates not-null constraint", col.Name) } rowVals[colIDtoRowIndex[col.ID]] = val } // Check that the new 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 newVals { var mErr error if marshalled[i], mErr = marshalColumnValue(cols[i], val, p.evalCtx.Args); mErr != nil { return nil, roachpb.NewError(mErr) } } // Compute the new secondary index key:value pairs for this row. newSecondaryIndexEntries, eErr := encodeSecondaryIndexes( tableDesc.ID, indexes, colIDtoRowIndex, rowVals) if eErr != nil { return nil, roachpb.NewError(eErr) } // Update secondary indexes. for i, newSecondaryIndexEntry := range newSecondaryIndexEntries { secondaryIndexEntry := secondaryIndexEntries[i] if !bytes.Equal(newSecondaryIndexEntry.key, secondaryIndexEntry.key) { // Do not update Indexes in the DELETE_ONLY state. if _, ok := deleteOnlyIndex[i]; !ok { if log.V(2) { log.Infof("CPut %s -> %v", newSecondaryIndexEntry.key, newSecondaryIndexEntry.value) } b.CPut(newSecondaryIndexEntry.key, newSecondaryIndexEntry.value, nil) } if log.V(2) { log.Infof("Del %s", secondaryIndexEntry.key) } b.Del(secondaryIndexEntry.key) } } // Add the new values. for i, val := range newVals { col := cols[i] key := keys.MakeColumnKey(primaryIndexKey, uint32(col.ID)) 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. if log.V(2) { log.Infof("Put %s -> %v", key, val) } b.Put(key, marshalled[i]) } else { // The column might have already existed but is being set to NULL, so // delete it. if log.V(2) { log.Infof("Del %s", key) } b.Del(key) } } } tracing.AnnotateTrace() if pErr := rows.PErr(); pErr != nil { return nil, pErr } 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) } tracing.AnnotateTrace() return result, nil }
// Send implements the batch.Sender interface. It subdivides // the Batch into batches admissible for sending (preventing certain // illegal mixtures of requests), executes each individual part // (which may span multiple ranges), and recombines the response. // When the request spans ranges, it is split up and the corresponding // ranges queried serially, in ascending order. // In particular, the first write in a transaction may not be part of the first // request sent. This is relevant since the first write is a BeginTransaction // request, thus opening up a window of time during which there may be intents // of a transaction, but no entry. Pushing such a transaction will succeed, and // may lead to the transaction being aborted early. func (ds *DistSender) Send(ctx context.Context, ba roachpb.BatchRequest) (*roachpb.BatchResponse, *roachpb.Error) { tracing.AnnotateTrace() // In the event that timestamp isn't set and read consistency isn't // required, set the timestamp using the local clock. if ba.ReadConsistency == roachpb.INCONSISTENT && ba.Timestamp.Equal(hlc.ZeroTimestamp) { ba.Timestamp = ds.clock.Now() } if ba.Txn != nil { // Make a copy here since the code below modifies it in different places. // TODO(tschottdorf): be smarter about this - no need to do it for // requests that don't get split. txnClone := ba.Txn.Clone() ba.Txn = &txnClone if len(ba.Txn.ObservedTimestamps) == 0 { // Ensure the local NodeID is marked as free from clock offset; // the transaction's timestamp was taken off the local clock. if nDesc := ds.getNodeDescriptor(); nDesc != nil { // TODO(tschottdorf): future refactoring should move this to txn // creation in TxnCoordSender, which is currently unaware of the // NodeID (and wraps *DistSender through client.Sender since it // also needs test compatibility with *LocalSender). // // Taking care below to not modify any memory referenced from // our BatchRequest which may be shared with others. // // We already have a clone of our txn (see above), so we can // modify it freely. // // Zero the existing data. That makes sure that if we had // something of size zero but with capacity, we don't re-use the // existing space (which others may also use). This is just to // satisfy paranoia/OCD and not expected to matter in practice. ba.Txn.ResetObservedTimestamps() // OrigTimestamp is the HLC timestamp at which the Txn started, so // this effectively means no more uncertainty on this node. ba.Txn.UpdateObservedTimestamp(nDesc.NodeID, ba.Txn.OrigTimestamp) } } } if len(ba.Requests) < 1 { panic("empty batch") } if ba.MaxSpanRequestKeys != 0 { // Verify that the batch contains only specific range requests or the // Begin/EndTransactionRequest. Verify that a batch with a ReverseScan // only contains ReverseScan range requests. isReverse := ba.IsReverse() for _, req := range ba.Requests { inner := req.GetInner() switch inner.(type) { case *roachpb.ScanRequest, *roachpb.DeleteRangeRequest: // Accepted range requests. All other range requests are still // not supported. // TODO(vivek): don't enumerate all range requests. if isReverse { return nil, roachpb.NewErrorf("batch with limit contains both forward and reverse scans") } case *roachpb.BeginTransactionRequest, *roachpb.EndTransactionRequest, *roachpb.ReverseScanRequest: continue default: return nil, roachpb.NewErrorf("batch with limit contains %T request", inner) } } } var rplChunks []*roachpb.BatchResponse parts := ba.Split(false /* don't split ET */) if len(parts) > 1 && ba.MaxSpanRequestKeys != 0 { // We already verified above that the batch contains only scan requests of the same type. // Such a batch should never need splitting. panic("batch with MaxSpanRequestKeys needs splitting") } for len(parts) > 0 { part := parts[0] ba.Requests = part rpl, pErr, shouldSplitET := ds.sendChunk(ctx, ba) if shouldSplitET { // If we tried to send a single round-trip EndTransaction but // it looks like it's going to hit multiple ranges, split it // here and try again. if len(parts) != 1 { panic("EndTransaction not in last chunk of batch") } parts = ba.Split(true /* split ET */) if len(parts) != 2 { panic("split of final EndTransaction chunk resulted in != 2 parts") } continue } if pErr != nil { return nil, pErr } // Propagate transaction from last reply to next request. The final // update is taken and put into the response's main header. ba.UpdateTxn(rpl.Txn) rplChunks = append(rplChunks, rpl) parts = parts[1:] } reply := rplChunks[0] for _, rpl := range rplChunks[1:] { reply.Responses = append(reply.Responses, rpl.Responses...) reply.CollectedSpans = append(reply.CollectedSpans, rpl.CollectedSpans...) } reply.BatchResponse_Header = rplChunks[len(rplChunks)-1].BatchResponse_Header return reply, nil }
// Update updates columns for a selection of rows from a table. // Privileges: UPDATE and SELECT on table. We currently always use a select statement. // Notes: postgres requires UPDATE. Requires SELECT with WHERE clause with table. // mysql requires UPDATE. Also requires SELECT with WHERE clause with table. // TODO(guanqun): need to support CHECK in UPDATE func (p *planner) Update(n *parser.Update, desiredTypes []parser.Datum, autoCommit bool) (planNode, error) { tracing.AnnotateTrace() en, err := p.makeEditNode(n.Table, n.Returning, desiredTypes, autoCommit, privilege.UPDATE) if err != nil { return nil, err } exprs := make([]parser.UpdateExpr, len(n.Exprs)) for i, expr := range n.Exprs { exprs[i] = *expr } // Determine which columns we're inserting into. var names parser.QualifiedNames for _, expr := range n.Exprs { // TODO(knz): We need to (attempt to) expand subqueries here already // so that it retrieves the column names. But then we need to do // it again when the placeholder values are known below. newExpr, eErr := p.expandSubqueries(expr.Expr, len(expr.Names)) if eErr != nil { return nil, eErr } if expr.Tuple { n := 0 switch t := newExpr.(type) { case *parser.Tuple: n = len(t.Exprs) case *parser.DTuple: n = len(*t) default: return nil, util.Errorf("unsupported tuple assignment: %T", newExpr) } if len(expr.Names) != n { return nil, fmt.Errorf("number of columns (%d) does not match number of values (%d)", len(expr.Names), n) } } names = append(names, expr.Names...) } updateCols, err := p.processColumns(en.tableDesc, names) if err != nil { return nil, err } defaultExprs, err := makeDefaultExprs(updateCols, &p.parser, p.evalCtx) if err != nil { return nil, err } ru, err := makeRowUpdater(en.tableDesc, updateCols) if err != nil { return nil, err } // TODO(dan): Use ru.fetchCols to compute the fetch selectors. tw := tableUpdater{ru: ru, autoCommit: autoCommit} tracing.AnnotateTrace() // Generate the list of select targets. We need to select all of the columns // plus we select all of the update expressions in case those expressions // reference columns (e.g. "UPDATE t SET v = v + 1"). Note that we flatten // expressions for tuple assignments just as we flattened the column names // above. So "UPDATE t SET (a, b) = (1, 2)" translates into select targets of // "*, 1, 2", not "*, (1, 2)". // TODO(radu): we only need to select columns necessary to generate primary and // secondary indexes keys, and columns needed by returningHelper. targets := en.tableDesc.AllColumnsSelector() i := 0 // Remember the index where the targets for exprs start. exprTargetIdx := len(targets) desiredTypesFromSelect := make([]parser.Datum, len(targets), len(targets)+len(exprs)) for _, expr := range n.Exprs { if expr.Tuple { if t, ok := expr.Expr.(*parser.Tuple); ok { for _, e := range t.Exprs { typ := updateCols[i].Type.ToDatumType() e := fillDefault(e, typ, i, defaultExprs) targets = append(targets, parser.SelectExpr{Expr: e}) desiredTypesFromSelect = append(desiredTypesFromSelect, typ) i++ } } } else { typ := updateCols[i].Type.ToDatumType() e := fillDefault(expr.Expr, typ, i, defaultExprs) targets = append(targets, parser.SelectExpr{Expr: e}) desiredTypesFromSelect = append(desiredTypesFromSelect, typ) i++ } } // TODO(knz): Until we split the creation of the node from Start() // for the SelectClause too, we cannot cache this. This is because // this node's initSelect() method both does type checking and also // performs index selection. We cannot perform index selection // properly until the placeholder values are known. rows, err := p.SelectClause(&parser.SelectClause{ Exprs: targets, From: []parser.TableExpr{n.Table}, Where: n.Where, }, desiredTypesFromSelect) if err != nil { return nil, err } // ValArgs have their types populated in the above Select if they are part // of an expression ("SET a = 2 + $1") in the type check step where those // types are inferred. For the simpler case ("SET a = $1"), populate them // using checkColumnType. This step also verifies that the expression // types match the column types. for i, target := range rows.(*selectNode).render[exprTargetIdx:] { // DefaultVal doesn't implement TypeCheck if _, ok := target.(parser.DefaultVal); ok { continue } typedTarget, err := parser.TypeCheck(target, p.evalCtx.Args, updateCols[i].Type.ToDatumType()) if err != nil { return nil, err } err = sqlbase.CheckColumnType(updateCols[i], typedTarget.ReturnType(), p.evalCtx.Args) if err != nil { return nil, err } } if err := en.rh.TypeCheck(); err != nil { return nil, err } un := &updateNode{ n: n, editNodeBase: en, desiredTypes: desiredTypesFromSelect, defaultExprs: defaultExprs, updateCols: ru.updateCols, tw: tw, } return un, nil }