コード例 #1
0
ファイル: table.go プロジェクト: thebrandonstore/cockroach
func (p *planner) getTableNames(dbDesc *DatabaseDescriptor) (parser.QualifiedNames, *roachpb.Error) {
	prefix := MakeNameMetadataKey(dbDesc.ID, "")
	sr, pErr := p.txn.Scan(prefix, prefix.PrefixEnd(), 0)
	if pErr != nil {
		return nil, pErr
	}

	var qualifiedNames parser.QualifiedNames
	for _, row := range sr {
		_, tableName, err := encoding.DecodeStringAscending(
			bytes.TrimPrefix(row.Key, prefix), nil)
		if err != nil {
			return nil, roachpb.NewError(err)
		}
		qname := &parser.QualifiedName{
			Base:     parser.Name(dbDesc.Name),
			Indirect: parser.Indirection{parser.NameIndirection(tableName)},
		}
		if err := qname.NormalizeTableName(""); err != nil {
			return nil, roachpb.NewError(err)
		}
		qualifiedNames = append(qualifiedNames, qname)
	}
	return qualifiedNames, nil
}
コード例 #2
0
ファイル: dist_sender.go プロジェクト: chzyer-dev/cockroach
// 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(ctx context.Context, 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:         base.NetworkTimeout,
		Context:         ctx,
	}
	tracing.AnnotateTrace()
	defer tracing.AnnotateTrace()

	reply, err := ds.rpcSend(rpcOpts, replicas, ba, ds.rpcContext)
	if err != nil {
		return nil, roachpb.NewError(err)
	}
	return reply, nil
}
コード例 #3
0
ファイル: txn_test.go プロジェクト: steelglove/cockroach
// TestEndWriteRestartReadOnlyTransaction verifies that if
// a transaction writes, then restarts and turns read-only,
// an explicit EndTransaction call is still sent if retry-
// able didn't, regardless of whether there is an error
// or not.
func TestEndWriteRestartReadOnlyTransaction(t *testing.T) {
	defer leaktest.AfterTest(t)
	for _, success := range []bool{true, false} {
		expCalls := []roachpb.Method{roachpb.BeginTransaction, roachpb.Put, roachpb.EndTransaction}
		var calls []roachpb.Method
		db := newDB(newTestSender(func(ba roachpb.BatchRequest) (*roachpb.BatchResponse, *roachpb.Error) {
			calls = append(calls, ba.Methods()...)
			return ba.CreateReply(), nil
		}, nil))
		ok := false
		if pErr := db.Txn(func(txn *Txn) *roachpb.Error {
			if !ok {
				if pErr := txn.Put("consider", "phlebas"); pErr != nil {
					t.Fatal(pErr)
				}
				ok = true
				return roachpb.NewError(&roachpb.TransactionRetryError{}) // immediate txn retry
			}
			if !success {
				return roachpb.NewError(errors.New("aborting on purpose"))
			}
			return nil
		}); pErr == nil != success {
			t.Errorf("expected error: %t, got error: %v", !success, pErr)
		}
		if !reflect.DeepEqual(expCalls, calls) {
			t.Fatalf("expected %v, got %v", expCalls, calls)
		}
	}
}
コード例 #4
0
ファイル: store_test.go プロジェクト: GokulSrinivas/cockroach
// Send forwards the call to the single store. This is a poor man's
// version of kv.TxnCoordSender, but it serves the purposes of
// supporting tests in this package. Transactions are not supported.
// Since kv/ depends on storage/, we can't get access to a
// TxnCoordSender from here.
// TODO(tschottdorf): {kv->storage}.LocalSender
func (db *testSender) Send(ctx context.Context, ba roachpb.BatchRequest) (*roachpb.BatchResponse, *roachpb.Error) {
	if et, ok := ba.GetArg(roachpb.EndTransaction); ok {
		return nil, roachpb.NewError(util.Errorf("%s method not supported", et.Method()))
	}
	// Lookup range and direct request.
	key, endKey := keys.Range(ba)
	rng := db.store.LookupReplica(key, endKey)
	if rng == nil {
		return nil, roachpb.NewError(roachpb.NewRangeKeyMismatchError(key, endKey, nil))
	}
	ba.RangeID = rng.Desc().RangeID
	replica := rng.GetReplica()
	if replica == nil {
		return nil, roachpb.NewError(util.Errorf("own replica missing in range"))
	}
	ba.Replica = *replica
	br, pErr := db.store.Send(ctx, ba)
	if br != nil && br.Error != nil {
		panic(roachpb.ErrorUnexpectedlySet(db.store, br))
	}
	if pErr != nil {
		return nil, pErr
	}
	return br, nil
}
コード例 #5
0
ファイル: database.go プロジェクト: billhongs/cockroach
// getCachedDatabaseDesc looks up the database descriptor given its name in the
// descriptor cache.
func (p *planner) getCachedDatabaseDesc(name string) (*DatabaseDescriptor, *roachpb.Error) {
	if name == systemDB.Name {
		return &systemDB, nil
	}

	nameKey := databaseKey{name}
	nameVal := p.systemConfig.GetValue(nameKey.Key())
	if nameVal == nil {
		return nil, roachpb.NewUErrorf("database %q does not exist in system cache", name)
	}

	id, err := nameVal.GetInt()
	if err != nil {
		return nil, roachpb.NewError(err)
	}

	descKey := MakeDescMetadataKey(ID(id))
	descVal := p.systemConfig.GetValue(descKey)
	if descVal == nil {
		return nil, roachpb.NewUErrorf("database %q has name entry, but no descriptor in system cache", name)
	}

	desc := &Descriptor{}
	if err := descVal.GetProto(desc); err != nil {
		return nil, roachpb.NewError(err)
	}

	database := desc.GetDatabase()
	if database == nil {
		return nil, roachpb.NewErrorf("%q is not a database", name)
	}
	return database, roachpb.NewError(database.Validate())
}
コード例 #6
0
ファイル: descriptor.go プロジェクト: billhongs/cockroach
// getDescriptorFromTargetList examines a TargetList and fetches the
// appropriate descriptor.
// TODO(marc): support multiple targets.
func (p *planner) getDescriptorFromTargetList(targets parser.TargetList) (descriptorProto, *roachpb.Error) {
	if targets.Databases != nil {
		if len(targets.Databases) == 0 {
			return nil, roachpb.NewError(errNoDatabase)
		} else if len(targets.Databases) != 1 {
			return nil, roachpb.NewErrorf("TODO(marc): multiple targets not implemented")
		}
		descriptor, err := p.getDatabaseDesc(targets.Databases[0])
		if err != nil {
			return nil, err
		}
		return descriptor, nil
	}

	if len(targets.Tables) == 0 {
		return nil, roachpb.NewError(errNoTable)
	} else if len(targets.Tables) != 1 {
		return nil, roachpb.NewErrorf("TODO(marc): multiple targets not implemented")
	}
	descriptor, err := p.getTableDesc(targets.Tables[0])
	if err != nil {
		return nil, err
	}
	return descriptor, nil
}
コード例 #7
0
ファイル: executor.go プロジェクト: bogdanbatog/cockroach
// Prepare returns the result types of the given statement. Args may be a
// partially populated val args map. Prepare will populate the missing val
// args. The column result types are returned (or nil if there are no results).
func (e *Executor) Prepare(query string, session *Session, args parser.MapArgs) (
	[]ResultColumn, *roachpb.Error) {
	stmt, err := parser.ParseOne(query, parser.Syntax(session.Syntax))
	if err != nil {
		return nil, roachpb.NewError(err)
	}

	session.planner.resetForBatch(e)
	session.planner.evalCtx.Args = args
	session.planner.evalCtx.PrepareOnly = true

	// TODO(andrei): does the prepare phase really need a Txn?
	txn := client.NewTxn(*e.ctx.DB)
	txn.Proto.Isolation = session.DefaultIsolationLevel
	session.planner.setTxn(txn)
	defer session.planner.setTxn(nil)

	plan, pErr := session.planner.prepare(stmt)
	if pErr != nil {
		return nil, pErr
	}
	if plan == nil {
		return nil, nil
	}
	cols := plan.Columns()
	for _, c := range cols {
		if err := checkResultDatum(c.Typ); err != nil {
			return nil, roachpb.NewError(err)
		}
	}
	return cols, nil
}
コード例 #8
0
ファイル: set.go プロジェクト: welfeng2016/cockroach
func (p *planner) SetTimeZone(n *parser.SetTimeZone) (planNode, *roachpb.Error) {
	d, err := n.Value.Eval(p.evalCtx)
	if err != nil {
		return nil, roachpb.NewError(err)
	}
	var offset int64
	switch v := d.(type) {
	case parser.DString:
		location := string(v)
		if location == "DEFAULT" || location == "LOCAL" {
			location = "UTC"
		}
		if _, err := time.LoadLocation(location); err != nil {
			return nil, roachpb.NewError(err)
		}
		p.session.Timezone = &Session_Location{Location: location}

	case parser.DInterval:
		offset = int64(v.Duration / time.Second)

	case parser.DInt:
		offset = int64(v) * 60 * 60

	case parser.DFloat:
		offset = int64(float64(v) * 60.0 * 60.0)

	default:
		return nil, roachpb.NewUErrorf("bad time zone value: %v", n.Value)
	}
	if offset != 0 {
		p.session.Timezone = &Session_Offset{Offset: offset}
	}
	p.evalCtx.GetLocation = p.session.getLocation
	return &valuesNode{}, nil
}
コード例 #9
0
ファイル: executor.go プロジェクト: younggi/cockroach
// execStmtInAbortedTxn executes a statement in a txn that's in state
// Aborted or RestartWait.
// Everything but COMMIT/ROLLBACK/RESTART causes errors.
func (e *Executor) execStmtInAbortedTxn(
	stmt parser.Statement, txnState *txnState) (Result, *roachpb.Error) {
	if txnState.State != Aborted && txnState.State != RestartWait {
		panic("execStmtInAbortedTxn called outside of an aborted txn")
	}
	switch stmt.(type) {
	case *parser.CommitTransaction, *parser.RollbackTransaction:
		if txnState.State == RestartWait {
			if pErr := txnState.txn.Rollback(); pErr != nil {
				log.Errorf("failure rolling back transaction: %s", pErr)
			}
		}
		// Reset the state to allow new transactions to start.
		// Note: postgres replies to COMMIT of failed txn with "ROLLBACK" too.
		result := Result{PGTag: (*parser.RollbackTransaction)(nil).StatementTag()}
		txnState.resetStateAndTxn(NoTxn)
		return result, nil
	case *parser.RestartTransaction:
		if txnState.State == RestartWait {
			// Reset the state. Txn is Open again.
			txnState.State = Open
			// TODO(andrei/cdo): add a counter for user-directed retries.
			return Result{}, nil
		}
		pErr := roachpb.NewError(&roachpb.SqlTransactionAbortedError{
			CustomMsg: "RETRY INTENT has not been used or a non-retriable error was encountered."})
		return Result{PErr: pErr}, pErr
	default:
		pErr := roachpb.NewError(&roachpb.SqlTransactionAbortedError{})
		return Result{PErr: pErr}, pErr
	}
}
コード例 #10
0
ファイル: table.go プロジェクト: thebrandonstore/cockroach
// getTableID retrieves the table ID for the specified table. It uses the
// descriptor cache to perform lookups, falling back to the KV store when
// necessary.
func (p *planner) getTableID(qname *parser.QualifiedName) (ID, *roachpb.Error) {
	if err := qname.NormalizeTableName(p.session.Database); err != nil {
		return 0, roachpb.NewError(err)
	}

	dbID, pErr := p.getDatabaseID(qname.Database())
	if pErr != nil {
		return 0, pErr
	}

	// Lookup the ID of the table in the cache. The use of the cache might cause
	// the usage of a recently renamed table, but that's a race that could occur
	// anyways.
	nameKey := tableKey{dbID, qname.Table()}
	key := nameKey.Key()
	if nameVal := p.systemConfig.GetValue(key); nameVal != nil {
		id, err := nameVal.GetInt()
		return ID(id), roachpb.NewError(err)
	}

	gr, pErr := p.txn.Get(key)
	if pErr != nil {
		return 0, pErr
	}
	if !gr.Exists() {
		return 0, roachpb.NewErrorf("table %q does not exist", nameKey.Name())
	}
	return ID(gr.ValueInt()), nil
}
コード例 #11
0
ファイル: scan.go プロジェクト: surpass/cockroach
func (n *scanNode) initWhere(where *parser.Where) *roachpb.Error {
	if where == nil {
		return nil
	}
	n.filter, n.pErr = n.resolveQNames(where.Expr)
	if n.pErr == nil {
		var whereType parser.Datum
		var err error
		whereType, err = n.filter.TypeCheck(n.planner.evalCtx.Args)
		n.pErr = roachpb.NewError(err)
		if n.pErr == nil {
			if !(whereType == parser.DummyBool || whereType == parser.DNull) {
				n.pErr = roachpb.NewUErrorf("argument of WHERE must be type %s, not type %s", parser.DummyBool.Type(), whereType.Type())
			}
		}
	}
	if n.pErr == nil {
		// Normalize the expression (this will also evaluate any branches that are
		// constant).
		var err error
		n.filter, err = n.planner.parser.NormalizeExpr(n.planner.evalCtx, n.filter)
		n.pErr = roachpb.NewError(err)
	}
	if n.pErr == nil {
		n.filter, n.pErr = n.planner.expandSubqueries(n.filter, 1)
	}
	return n.pErr
}
コード例 #12
0
ファイル: rename.go プロジェクト: billhongs/cockroach
// RenameDatabase renames the database.
// Privileges: "root" user.
//   Notes: postgres requires superuser, db owner, or "CREATEDB".
//          mysql >= 5.1.23 does not allow database renames.
func (p *planner) RenameDatabase(n *parser.RenameDatabase) (planNode, *roachpb.Error) {
	if n.Name == "" || n.NewName == "" {
		return nil, roachpb.NewError(errEmptyDatabaseName)
	}

	if p.user != security.RootUser {
		return nil, roachpb.NewUErrorf("only %s is allowed to rename databases", security.RootUser)
	}

	dbDesc, pErr := p.getDatabaseDesc(string(n.Name))
	if pErr != nil {
		return nil, pErr
	}

	if n.Name == n.NewName {
		// Noop.
		return &valuesNode{}, nil
	}

	// Now update the nameMetadataKey and the descriptor.
	descKey := MakeDescMetadataKey(dbDesc.GetID())
	dbDesc.SetName(string(n.NewName))

	if err := dbDesc.Validate(); err != nil {
		return nil, roachpb.NewError(err)
	}

	newKey := databaseKey{string(n.NewName)}.Key()
	oldKey := databaseKey{string(n.Name)}.Key()
	descID := dbDesc.GetID()
	descDesc := wrapDescriptor(dbDesc)

	b := client.Batch{}
	b.CPut(newKey, descID, nil)
	b.Put(descKey, descDesc)
	b.Del(oldKey)

	if pErr := p.txn.Run(&b); pErr != nil {
		if _, ok := pErr.GoError().(*roachpb.ConditionFailedError); ok {
			return nil, roachpb.NewUErrorf("the new database name %q already exists", string(n.NewName))
		}
		return nil, pErr
	}

	p.testingVerifyMetadata = func(systemConfig config.SystemConfig) error {
		if err := expectDescriptorID(systemConfig, newKey, descID); err != nil {
			return err
		}
		if err := expectDescriptor(systemConfig, descKey, descDesc); err != nil {
			return err
		}
		return expectDeleted(systemConfig, oldKey)
	}

	return &valuesNode{}, nil
}
コード例 #13
0
ファイル: scan.go プロジェクト: liugangnhm/cockroach
// initScan initializes but does not perform the key-value scan.
func (n *scanNode) initScan() bool {
	// Initialize our key/values.
	if len(n.spans) == 0 {
		// If no spans were specified retrieve all of the keys that start with our
		// index key prefix.
		start := roachpb.Key(MakeIndexKeyPrefix(n.desc.ID, n.index.ID))
		n.spans = append(n.spans, span{
			start: start,
			end:   start.PrefixEnd(),
		})
	}

	if n.valTypes == nil {
		// Prepare our index key vals slice.
		var err error
		n.valTypes, err = makeKeyVals(&n.desc, n.columnIDs)
		n.pErr = roachpb.NewError(err)
		if n.pErr != nil {
			return false
		}
		n.vals = make([]parser.Datum, len(n.valTypes))

		if n.isSecondaryIndex && n.index.Unique {
			// Unique secondary indexes have a value that is the primary index
			// key. Prepare implicitVals for use in decoding this value.
			// Primary indexes only contain ascendingly-encoded values. If this
			// ever changes, we'll probably have to figure out the directions here too.
			var err error
			n.implicitValTypes, err = makeKeyVals(&n.desc, n.index.ImplicitColumnIDs)
			n.pErr = roachpb.NewError(err)
			if n.pErr != nil {
				return false
			}
			n.implicitVals = make([]parser.Datum, len(n.implicitValTypes))
		}
	}

	// If we have a limit hint, we limit the first batch size. Subsequent batches use the normal
	// size, to avoid making things too slow (e.g. in case we have a very restrictive filter and
	// actually have to retrieve a lot of rows).
	firstBatchLimit := n.limitHint
	if firstBatchLimit != 0 {
		// For a secondary index, we have one key per row.
		if !n.isSecondaryIndex {
			// We have a sentinel key per row plus at most one key per non-PK column. Of course, we
			// may have other keys due to a schema change, but this is only a hint.
			firstBatchLimit *= int64(1 + len(n.visibleCols) - len(n.index.ColumnIDs))
		}
		// We need an extra key to make sure we form the last row.
		firstBatchLimit++
	}

	n.fetcher = makeKVFetcher(n.txn, n.spans, n.reverse, firstBatchLimit)
	n.scanInitialized = true
	return true
}
コード例 #14
0
ファイル: rename.go プロジェクト: billhongs/cockroach
// RenameIndex renames the index.
// Privileges: CREATE on table.
//   notes: postgres requires CREATE on the table.
//          mysql requires ALTER, CREATE, INSERT on the table.
func (p *planner) RenameIndex(n *parser.RenameIndex) (planNode, *roachpb.Error) {
	newIdxName := string(n.NewName)
	if newIdxName == "" {
		return nil, roachpb.NewError(errEmptyIndexName)
	}

	if err := n.Name.NormalizeTableName(p.session.Database); err != nil {
		return nil, roachpb.NewError(err)
	}

	tableDesc, pErr := p.getTableDesc(n.Name)
	if pErr != nil {
		return nil, pErr
	}

	idxName := n.Name.Index()
	status, i, pErr := tableDesc.FindIndexByName(idxName)
	if pErr != nil {
		if n.IfExists {
			// Noop.
			return &valuesNode{}, nil
		}
		// Index does not exist, but we want it to: error out.
		return nil, pErr
	}

	if pErr := p.checkPrivilege(tableDesc, privilege.CREATE); pErr != nil {
		return nil, pErr
	}

	if equalName(idxName, newIdxName) {
		// Noop.
		return &valuesNode{}, nil
	}

	if _, _, err := tableDesc.FindIndexByName(newIdxName); err == nil {
		return nil, roachpb.NewUErrorf("index name %q already exists", n.NewName)
	}

	if status == DescriptorActive {
		tableDesc.Indexes[i].Name = newIdxName
	} else {
		tableDesc.Mutations[i].GetIndex().Name = newIdxName
	}

	tableDesc.UpVersion = true
	descKey := MakeDescMetadataKey(tableDesc.GetID())
	if err := tableDesc.Validate(); err != nil {
		return nil, roachpb.NewError(err)
	}
	if pErr := p.txn.Put(descKey, wrapDescriptor(tableDesc)); pErr != nil {
		return nil, pErr
	}
	p.notifySchemaChange(tableDesc.ID, invalidMutationID)
	return &valuesNode{}, nil
}
コード例 #15
0
ファイル: plan.go プロジェクト: l2x/cockroach
func (p *planner) query(sql string, args ...interface{}) (planNode, *roachpb.Error) {
	stmt, err := parser.ParseOneTraditional(sql)
	if err != nil {
		return nil, roachpb.NewError(err)
	}
	if err := parser.FillArgs(stmt, golangParameters(args)); err != nil {
		return nil, roachpb.NewError(err)
	}
	return p.makePlan(stmt, false)
}
コード例 #16
0
ファイル: scan.go プロジェクト: liugangnhm/cockroach
// Initializes a scanNode with a tableName. Returns the table or index name that can be used for
// fully-qualified columns if an alias is not specified.
func (n *scanNode) initTable(p *planner, tableName *parser.QualifiedName) (string, *roachpb.Error) {
	if n.desc, n.pErr = p.getTableLease(tableName); n.pErr != nil {
		return "", n.pErr
	}

	if err := p.checkPrivilege(&n.desc, privilege.SELECT); err != nil {
		return "", roachpb.NewError(err)
	}

	alias := n.desc.Name

	indexName := tableName.Index()
	if indexName != "" && !equalName(n.desc.PrimaryIndex.Name, indexName) {
		for i := range n.desc.Indexes {
			if equalName(n.desc.Indexes[i].Name, indexName) {
				// Remove all but the matching index from the descriptor.
				n.desc.Indexes = n.desc.Indexes[i : i+1]
				n.index = &n.desc.Indexes[0]
				break
			}
		}
		if n.index == nil {
			n.pErr = roachpb.NewUErrorf("index \"%s\" not found", indexName)
			return "", n.pErr
		}
		// Use the index name instead of the table name for fully-qualified columns in the
		// expression.
		alias = n.index.Name
		// Strip out any columns from the table that are not present in the
		// index.
		visibleCols := make([]ColumnDescriptor, 0, len(n.index.ColumnIDs)+len(n.index.ImplicitColumnIDs))
		for _, colID := range n.index.ColumnIDs {
			col, err := n.desc.FindColumnByID(colID)
			n.pErr = roachpb.NewError(err)
			if n.pErr != nil {
				return "", n.pErr
			}
			visibleCols = append(visibleCols, *col)
		}
		for _, colID := range n.index.ImplicitColumnIDs {
			col, err := n.desc.FindColumnByID(colID)
			n.pErr = roachpb.NewError(err)
			if n.pErr != nil {
				return "", n.pErr
			}
			visibleCols = append(visibleCols, *col)
		}
		n.isSecondaryIndex = true
		n.initVisibleCols(visibleCols, len(n.index.ImplicitColumnIDs))
	} else {
		n.initDescDefaults()
	}

	return alias, nil
}
コード例 #17
0
ファイル: select.go プロジェクト: bogdanbatog/cockroach
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
}
コード例 #18
0
ファイル: create.go プロジェクト: danieldeb/cockroach
// CreateTable creates a table.
// Privileges: CREATE on database.
//   Notes: postgres/mysql require CREATE on database.
func (p *planner) CreateTable(n *parser.CreateTable) (planNode, *roachpb.Error) {
	if err := n.Table.NormalizeTableName(p.session.Database); err != nil {
		return nil, roachpb.NewError(err)
	}

	dbDesc, pErr := p.getDatabaseDesc(n.Table.Database())
	if pErr != nil {
		return nil, pErr
	}

	if err := p.checkPrivilege(dbDesc, privilege.CREATE); err != nil {
		return nil, roachpb.NewError(err)
	}

	desc, pErr := makeTableDesc(n, dbDesc.ID)
	if pErr != nil {
		return nil, pErr
	}
	// Inherit permissions from the database descriptor.
	desc.Privileges = dbDesc.GetPrivileges()

	if len(desc.PrimaryIndex.ColumnNames) == 0 {
		// Ensure a Primary Key exists.
		s := "experimental_unique_int()"
		col := ColumnDescriptor{
			Name: "rowid",
			Type: ColumnType{
				Kind: ColumnType_INT,
			},
			DefaultExpr: &s,
			Hidden:      true,
			Nullable:    false,
		}
		desc.AddColumn(col)
		idx := IndexDescriptor{
			Unique:           true,
			ColumnNames:      []string{col.Name},
			ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC},
		}
		if err := desc.AddIndex(idx, true); err != nil {
			return nil, roachpb.NewError(err)
		}
	}

	if pErr := desc.AllocateIDs(); pErr != nil {
		return nil, pErr
	}

	if pErr := p.createDescriptor(tableKey{dbDesc.ID, n.Table.Table()}, &desc, n.IfNotExists); pErr != nil {
		return nil, pErr
	}
	return &emptyNode{}, nil
}
コード例 #19
0
ファイル: executor.go プロジェクト: cuongdo/cockroach
// execStmtInOpenTxn executes one statement in the context
// of the planner's transaction (which is assumed to exist).
// It handles statements that affect the transaction state (BEGIN, COMMIT)
// and delegates everything else to `execStmt`.
// It binds placeholders.
//
// The current transaction might be committed/rolled back when this returns.
//
// Args:
// abortedMode: if set, we're in a transaction that has encountered errors, so we
//  must reject the statement unless it's a COMMIT/ROLLBACK.
// implicitTxn: set if the current transaction was implicitly
//  created by the system (i.e. the client sent the statement outside of
//  a transaction).
//  COMMIT/ROLLBACK statements are rejected if set. Also, the transaction
//  might be auto-committed in this function.
// firstInTxn: set for the first statement in a transaction. Used
//  so that nested BEGIN statements are caught.
// stmtTimestamp: Used as the statement_timestamp().
//
// Returns:
// - a Result
// - an error, if any. In case of error, the result returned also reflects this error.
func (e *Executor) execStmtInOpenTxn(
	stmt parser.Statement, planMaker *planner,
	implicitTxn bool,
	firstInTxn bool,
	stmtTimestamp parser.DTimestamp,
	txnState *txnState) (Result, *roachpb.Error) {
	if txnState.state() != openTransaction {
		panic("execStmtInOpenTxn called outside of an open txn")
	}
	if planMaker.txn == nil {
		panic("execStmtInOpenTxn called with the a txn not set on the planner")
	}

	planMaker.evalCtx.StmtTimestamp = stmtTimestamp

	// TODO(cdo): Figure out how to not double count on retries.
	e.updateStmtCounts(stmt)
	switch stmt.(type) {
	case *parser.BeginTransaction:
		if !firstInTxn {
			txnState.aborted = true
			pErr := roachpb.NewError(errTransactionInProgress)
			return Result{PErr: pErr}, pErr
		}
	case *parser.CommitTransaction, *parser.RollbackTransaction, *parser.SetTransaction:
		if implicitTxn {
			txnState.aborted = true
			pErr := roachpb.NewError(errNoTransactionInProgress)
			return Result{PErr: pErr}, pErr
		}
	}

	// Bind all the placeholder variables in the stmt to actual values.
	stmt, err := parser.FillArgs(stmt, &planMaker.params)
	if err != nil {
		txnState.aborted = true
		pErr := roachpb.NewError(err)
		return Result{PErr: pErr}, pErr
	}

	result, pErr := e.execStmt(stmt, planMaker, timeutil.Now(),
		implicitTxn /* autoCommit */)
	txnDone := planMaker.txn == nil
	if pErr != nil {
		result = Result{PErr: pErr}
		txnState.aborted = true
	}
	if txnDone {
		txnState.aborted = false
		txnState.txn = nil
	}
	return result, pErr
}
コード例 #20
0
ファイル: stores.go プロジェクト: csdigi/cockroach
// Send implements the client.Sender interface. The store is looked up from the
// store map if specified by the request; otherwise, the command is being
// executed locally, and the replica is determined via lookup through each
// store's LookupRange method. The latter path is taken only by unit tests.
func (ls *Stores) Send(ctx context.Context, ba roachpb.BatchRequest) (*roachpb.BatchResponse, *roachpb.Error) {
	// If we aren't given a Replica, then a little bending over
	// backwards here. This case applies exclusively to unittests.
	if ba.RangeID == 0 || ba.Replica.StoreID == 0 {
		rs, err := keys.Range(ba)
		if err != nil {
			return nil, roachpb.NewError(err)
		}
		rangeID, repl, err := ls.lookupReplica(rs.Key, rs.EndKey)
		if err != nil {
			return nil, roachpb.NewError(err)
		}
		ba.RangeID = rangeID
		ba.Replica = *repl
	}

	ctx = log.Add(ctx,
		log.RangeID, ba.RangeID)

	store, err := ls.GetStore(ba.Replica.StoreID)
	if err != nil {
		return nil, roachpb.NewError(err)
	}

	if ba.Txn != nil {
		// For calls that read data within a txn, we keep track of timestamps
		// observed from the various participating nodes' HLC clocks. If we have
		// a timestamp on file for this Node which is smaller than MaxTimestamp,
		// we can lower MaxTimestamp accordingly. If MaxTimestamp drops below
		// OrigTimestamp, we effectively can't see uncertainty restarts any
		// more.
		// Note that it's not an issue if MaxTimestamp propagates back out to
		// the client via a returned Transaction update - when updating a Txn
		// from another, the larger MaxTimestamp wins.
		if maxTS, ok := ba.Txn.GetObservedTimestamp(ba.Replica.NodeID); ok && maxTS.Less(ba.Txn.MaxTimestamp) {
			// Copy-on-write to protect others we might be sharing the Txn with.
			shallowTxn := *ba.Txn
			// The uncertainty window is [OrigTimestamp, maxTS), so if that window
			// is empty, there won't be any uncertainty restarts.
			if !ba.Txn.OrigTimestamp.Less(maxTS) {
				log.Trace(ctx, "read has no clock uncertainty")
			}
			shallowTxn.MaxTimestamp.Backward(maxTS)
			ba.Txn = &shallowTxn
		}
	}
	br, pErr := store.Send(ctx, ba)
	if br != nil && br.Error != nil {
		panic(roachpb.ErrorUnexpectedlySet(store, br))
	}
	return br, pErr
}
コード例 #21
0
ファイル: drop.go プロジェクト: cuongdo/cockroach
// DropIndex drops an index.
// Privileges: CREATE on table.
//   Notes: postgres allows only the index owner to DROP an index.
//          mysql requires the INDEX privilege on the table.
func (p *planner) DropIndex(n *parser.DropIndex) (planNode, *roachpb.Error) {
	for _, indexQualifiedName := range n.Names {
		if err := indexQualifiedName.NormalizeTableName(p.session.Database); err != nil {
			return nil, roachpb.NewError(err)
		}

		tableDesc, pErr := p.getTableDesc(indexQualifiedName)
		if pErr != nil {
			return nil, pErr
		}

		if err := p.checkPrivilege(&tableDesc, privilege.CREATE); err != nil {
			return nil, roachpb.NewError(err)
		}
		idxName := indexQualifiedName.Index()
		status, i, err := tableDesc.FindIndexByName(idxName)
		if err != nil {
			if n.IfExists {
				// Noop.
				return &emptyNode{}, nil
			}
			// Index does not exist, but we want it to: error out.
			return nil, roachpb.NewError(err)
		}
		switch status {
		case DescriptorActive:
			tableDesc.addIndexMutation(tableDesc.Indexes[i], DescriptorMutation_DROP)
			tableDesc.Indexes = append(tableDesc.Indexes[:i], tableDesc.Indexes[i+1:]...)

		case DescriptorIncomplete:
			switch tableDesc.Mutations[i].Direction {
			case DescriptorMutation_ADD:
				return nil, roachpb.NewUErrorf("index %q in the middle of being added, try again later", idxName)

			case DescriptorMutation_DROP:
				return &emptyNode{}, nil
			}
		}
		tableDesc.UpVersion = true
		mutationID := tableDesc.NextMutationID
		tableDesc.NextMutationID++
		if err := tableDesc.Validate(); err != nil {
			return nil, roachpb.NewError(err)
		}

		if pErr := p.txn.Put(MakeDescMetadataKey(tableDesc.GetID()), wrapDescriptor(&tableDesc)); pErr != nil {
			return nil, pErr
		}
		p.notifySchemaChange(tableDesc.ID, mutationID)
	}
	return &emptyNode{}, nil
}
コード例 #22
0
ファイル: values.go プロジェクト: liugangnhm/cockroach
// Values constructs a valuesNode from a VALUES expression.
func (p *planner) Values(n *parser.Values) (planNode, *roachpb.Error) {
	v := &valuesNode{
		rows: make([]parser.DTuple, 0, len(n.Tuples)),
	}

	for num, tupleOrig := range n.Tuples {
		if num == 0 {
			v.columns = make([]ResultColumn, 0, len(tupleOrig.Exprs))
		} else if a, e := len(tupleOrig.Exprs), len(v.columns); a != e {
			return nil, roachpb.NewUErrorf("VALUES lists must all be the same length, %d for %d", a, e)
		}

		// We must not modify the Values node in-place (or the changes will leak if we retry this
		// transaction).
		tuple := parser.Tuple{Exprs: parser.Exprs(append([]parser.Expr(nil), tupleOrig.Exprs...))}

		for i := range tuple.Exprs {
			var pErr *roachpb.Error
			tuple.Exprs[i], pErr = p.expandSubqueries(tuple.Exprs[i], 1)
			if pErr != nil {
				return nil, pErr
			}
			var err error
			typ, err := tuple.Exprs[i].TypeCheck(p.evalCtx.Args)
			if err != nil {
				return nil, roachpb.NewError(err)
			}
			tuple.Exprs[i], err = p.parser.NormalizeExpr(p.evalCtx, tuple.Exprs[i])
			if err != nil {
				return nil, roachpb.NewError(err)
			}
			if num == 0 {
				v.columns = append(v.columns, ResultColumn{Name: "column" + strconv.Itoa(i+1), Typ: typ})
			} else if v.columns[i].Typ == parser.DNull {
				v.columns[i].Typ = typ
			} else if typ != parser.DNull && !typ.TypeEqual(v.columns[i].Typ) {
				return nil, roachpb.NewUErrorf("VALUES list type mismatch, %s for %s", typ.Type(), v.columns[i].Typ.Type())
			}
		}
		data, err := tuple.Eval(p.evalCtx)
		if err != nil {
			return nil, roachpb.NewError(err)
		}
		vals, ok := data.(parser.DTuple)
		if !ok {
			return nil, roachpb.NewUErrorf("expected a tuple, but found %T", data)
		}
		v.rows = append(v.rows, vals)
	}

	return v, nil
}
コード例 #23
0
ファイル: create.go プロジェクト: petermattis/cockroach
// CreateIndex creates an index.
// Privileges: CREATE on table.
//   notes: postgres requires CREATE on the table.
//          mysql requires INDEX on the table.
func (p *planner) CreateIndex(n *parser.CreateIndex) (planNode, *roachpb.Error) {
	tableDesc, pErr := p.getTableDesc(n.Table)
	if pErr != nil {
		return nil, pErr
	}

	status, i, err := tableDesc.FindIndexByName(string(n.Name))
	if err == nil {
		if status == DescriptorIncomplete {
			switch tableDesc.Mutations[i].Direction {
			case DescriptorMutation_DROP:
				return nil, roachpb.NewUErrorf("index %q being dropped, try again later", string(n.Name))

			case DescriptorMutation_ADD:
				// Noop, will fail in AllocateIDs below.
			}
		}
		if n.IfNotExists {
			// Noop.
			return &emptyNode{}, nil
		}
	}

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

	indexDesc := IndexDescriptor{
		Name:             string(n.Name),
		Unique:           n.Unique,
		StoreColumnNames: n.Storing,
	}
	if err := indexDesc.fillColumns(n.Columns); err != nil {
		return nil, roachpb.NewError(err)
	}

	tableDesc.addIndexMutation(indexDesc, DescriptorMutation_ADD)
	tableDesc.UpVersion = true
	mutationID := tableDesc.NextMutationID
	tableDesc.NextMutationID++
	if err := tableDesc.AllocateIDs(); err != nil {
		return nil, roachpb.NewError(err)
	}

	if pErr := p.txn.Put(MakeDescMetadataKey(tableDesc.GetID()), wrapDescriptor(&tableDesc)); pErr != nil {
		return nil, pErr
	}
	p.notifySchemaChange(tableDesc.ID, mutationID)

	return &emptyNode{}, nil
}
コード例 #24
0
ファイル: limit.go プロジェクト: billhongs/cockroach
// limit constructs a limitNode based on the LIMIT and OFFSET clauses.
func (p *planner) limit(n *parser.Select, plan planNode) (planNode, *roachpb.Error) {
	if n.Limit == nil {
		return plan, nil
	}

	var count, offset int64

	data := []struct {
		name       string
		src        parser.Expr
		dst        *int64
		defaultVal int64
	}{
		{"LIMIT", n.Limit.Count, &count, math.MaxInt64},
		{"OFFSET", n.Limit.Offset, &offset, 0},
	}

	for _, datum := range data {
		if datum.src == nil {
			*datum.dst = datum.defaultVal
		} else {
			if parser.ContainsVars(datum.src) {
				return nil, roachpb.NewUErrorf("argument of %s must not contain variables", datum.name)
			}

			normalized, err := p.parser.NormalizeExpr(p.evalCtx, datum.src)
			if err != nil {
				return nil, roachpb.NewError(err)
			}
			dstDatum, err := normalized.Eval(p.evalCtx)
			if err != nil {
				return nil, roachpb.NewError(err)
			}

			if dstDatum == parser.DNull {
				*datum.dst = datum.defaultVal
				continue
			}

			if dstDInt, ok := dstDatum.(parser.DInt); ok {
				*datum.dst = int64(dstDInt)
				continue
			}

			return nil, roachpb.NewUErrorf("argument of %s must be type %s, not type %s", datum.name, parser.DummyInt.Type(), dstDatum.Type())
		}
	}

	return &limitNode{planNode: plan, count: count, offset: offset}, nil
}
コード例 #25
0
ファイル: txn.go プロジェクト: nporsche/cockroach
// send runs the specified calls synchronously in a single batch and
// returns any errors. If the transaction is read-only or has already
// been successfully committed or aborted, a potential trailing
// EndTransaction call is silently dropped, allowing the caller to
// always commit or clean-up explicitly even when that may not be
// required (or even erroneous).
func (txn *Txn) send(reqs ...roachpb.Request) (*roachpb.BatchResponse, *roachpb.Error) {

	if txn.Proto.Status != roachpb.PENDING {
		return nil, roachpb.NewError(util.Errorf("attempting to use %s transaction", txn.Proto.Status))
	}

	lastIndex := len(reqs) - 1
	if lastIndex < 0 {
		return &roachpb.BatchResponse{}, nil
	}

	lastReq := reqs[lastIndex]
	// haveTxnWrite tracks intention to write. This is in contrast to
	// txn.Proto.Writing, which is set by the coordinator when the first
	// intent has been created, and which lives for the life of the
	// transaction.
	haveTxnWrite := roachpb.IsTransactionWrite(lastReq)

	for _, args := range reqs[:lastIndex] {
		if _, ok := args.(*roachpb.EndTransactionRequest); ok {
			return nil, roachpb.NewError(util.Errorf("%s sent as non-terminal call", args.Method()))
		}

		if !haveTxnWrite {
			haveTxnWrite = roachpb.IsTransactionWrite(args)
		}
	}

	endTxnRequest, haveEndTxn := lastReq.(*roachpb.EndTransactionRequest)
	needEndTxn := txn.Proto.Writing || haveTxnWrite
	elideEndTxn := haveEndTxn && !needEndTxn

	if elideEndTxn {
		reqs = reqs[:lastIndex]
	}

	br, pErr := txn.db.send(reqs...)
	if elideEndTxn && pErr == nil {
		// This normally happens on the server and sent back in response
		// headers, but this transaction was optimized away. The caller may
		// still inspect the transaction struct, so we manually update it
		// here to emulate a true transaction.
		if endTxnRequest.Commit {
			txn.Proto.Status = roachpb.COMMITTED
		} else {
			txn.Proto.Status = roachpb.ABORTED
		}
	}
	return br, pErr
}
コード例 #26
0
ファイル: values.go プロジェクト: welfeng2016/cockroach
// Values constructs a valuesNode from a VALUES expression.
func (p *planner) Values(n parser.Values) (planNode, *roachpb.Error) {
	v := &valuesNode{
		rows: make([]parser.DTuple, 0, len(n)),
	}

	for num, tuple := range n {
		if num == 0 {
			v.columns = make([]resultColumn, 0, len(tuple))
		} else if a, e := len(tuple), len(v.columns); a != e {
			return nil, roachpb.NewUErrorf("VALUES lists must all be the same length, %d for %d", a, e)
		}

		for i := range tuple {
			var pErr *roachpb.Error
			tuple[i], pErr = p.expandSubqueries(tuple[i], 1)
			if pErr != nil {
				return nil, pErr
			}
			var err error
			typ, err := tuple[i].TypeCheck(p.evalCtx.Args)
			if err != nil {
				return nil, roachpb.NewError(err)
			}
			tuple[i], err = p.parser.NormalizeExpr(p.evalCtx, tuple[i])
			if err != nil {
				return nil, roachpb.NewError(err)
			}
			if num == 0 {
				v.columns = append(v.columns, resultColumn{name: "column" + strconv.Itoa(i+1), typ: typ})
			} else if v.columns[i].typ == parser.DNull {
				v.columns[i].typ = typ
			} else if typ != parser.DNull && typ != v.columns[i].typ {
				return nil, roachpb.NewUErrorf("VALUES list type mismatch, %s for %s", typ.Type(), v.columns[i].typ.Type())
			}
		}
		data, err := tuple.Eval(p.evalCtx)
		if err != nil {
			return nil, roachpb.NewError(err)
		}
		vals, ok := data.(parser.DTuple)
		if !ok {
			return nil, roachpb.NewUErrorf("expected a tuple, but found %T", data)
		}
		v.rows = append(v.rows, vals)
	}

	return v, nil
}
コード例 #27
0
ファイル: table.go プロジェクト: xnyan/cockroach
// unmarshalColumnValue decodes the value from a key-value pair using the type
// expected by the column. An error is returned if the value's type does not
// match the column's type.
func unmarshalColumnValue(kind ColumnType_Kind, value *roachpb.Value) (parser.Datum, *roachpb.Error) {
	if value == nil {
		return parser.DNull, nil
	}

	switch kind {
	case ColumnType_BOOL:
		v, err := value.GetInt()
		if err != nil {
			return nil, roachpb.NewError(err)
		}
		return parser.DBool(v != 0), nil
	case ColumnType_INT:
		v, err := value.GetInt()
		if err != nil {
			return nil, roachpb.NewError(err)
		}
		return parser.DInt(v), nil
	case ColumnType_FLOAT:
		v, err := value.GetFloat()
		if err != nil {
			return nil, roachpb.NewError(err)
		}
		return parser.DFloat(v), nil
	case ColumnType_STRING:
		v, err := value.GetBytes()
		if err != nil {
			return nil, roachpb.NewError(err)
		}
		return parser.DString(v), nil
	case ColumnType_BYTES:
		v, err := value.GetBytes()
		if err != nil {
			return nil, roachpb.NewError(err)
		}
		return parser.DBytes(v), nil
	case ColumnType_DATE:
		v, err := value.GetInt()
		if err != nil {
			return nil, roachpb.NewError(err)
		}
		return parser.DDate(v), nil
	case ColumnType_TIMESTAMP:
		v, err := value.GetTime()
		if err != nil {
			return nil, roachpb.NewError(err)
		}
		return parser.DTimestamp{Time: v}, nil
	case ColumnType_INTERVAL:
		v, err := value.GetInt()
		if err != nil {
			return nil, roachpb.NewError(err)
		}
		return parser.DInterval{Duration: time.Duration(v)}, nil
	default:
		return nil, roachpb.NewErrorf("unsupported column type: %s", kind)
	}
}
コード例 #28
0
ファイル: create.go プロジェクト: petermattis/cockroach
// CreateDatabase creates a database.
// Privileges: security.RootUser user.
//   Notes: postgres requires superuser or "CREATEDB".
//          mysql uses the mysqladmin command.
func (p *planner) CreateDatabase(n *parser.CreateDatabase) (planNode, *roachpb.Error) {
	if n.Name == "" {
		return nil, roachpb.NewError(errEmptyDatabaseName)
	}

	if p.session.User != security.RootUser {
		return nil, roachpb.NewUErrorf("only %s is allowed to create databases", security.RootUser)
	}

	desc := makeDatabaseDesc(n)

	created, err := p.createDescriptor(databaseKey{string(n.Name)}, &desc, n.IfNotExists)
	if err != nil {
		return nil, err
	}
	if created {
		// Log Create Database event.
		if pErr := MakeEventLogger(p.leaseMgr).InsertEventRecord(p.txn,
			EventLogCreateDatabase,
			int32(desc.ID),
			int32(p.evalCtx.NodeID),
			struct {
				DatabaseName string
				Statement    string
				User         string
			}{n.Name.String(), n.String(), p.session.User},
		); pErr != nil {
			return nil, pErr
		}
	}
	return &emptyNode{}, nil
}
コード例 #29
0
ファイル: stores.go プロジェクト: xnyan/cockroach
// lookupReplica looks up replica by key [range]. Lookups are done
// by consulting each store in turn via Store.LookupRange(key).
// Returns RangeID and replica on success; RangeKeyMismatch error
// if not found.
// This is only for testing usage; performance doesn't matter.
func (ls *Stores) lookupReplica(start, end roachpb.RKey) (rangeID roachpb.RangeID, replica *roachpb.ReplicaDescriptor, pErr *roachpb.Error) {
	ls.mu.RLock()
	defer ls.mu.RUnlock()
	var rng *Replica
	for _, store := range ls.storeMap {
		rng = store.LookupReplica(start, end)
		if rng == nil {
			if tmpRng := store.LookupReplica(start, nil); tmpRng != nil {
				log.Warningf(fmt.Sprintf("range not contained in one range: [%s,%s), but have [%s,%s)", start, end, tmpRng.Desc().StartKey, tmpRng.Desc().EndKey))
			}
			continue
		}
		if replica == nil {
			rangeID = rng.RangeID
			replica = rng.GetReplica()
			continue
		}
		// Should never happen outside of tests.
		return 0, nil, roachpb.NewErrorf(
			"range %+v exists on additional store: %+v", rng, store)
	}
	if replica == nil {
		pErr = roachpb.NewError(roachpb.NewRangeKeyMismatchError(start.AsRawKey(), end.AsRawKey(), nil))
	}
	return rangeID, replica, pErr
}
コード例 #30
0
ファイル: txn.go プロジェクト: l2x/cockroach
// GetProto retrieves the value for a key and decodes the result as a proto
// message.
//
// key can be either a byte slice or a string.
func (txn *Txn) GetProto(key interface{}, msg proto.Message) *roachpb.Error {
	r, pErr := txn.Get(key)
	if pErr != nil {
		return pErr
	}
	return roachpb.NewError(r.ValueProto(msg))
}