Skip to content

Commit

Permalink
sql: fix error message for currval, nextval and setval for sequences
Browse files Browse the repository at this point in the history
Release note (sql change): Small fix to error messaging for
builtin functions for sequences.

Example: SELECT nextval('@#%@!324234') correctly returns
relation "@#%@!324234" does not exist (if the relation doesn't exist)
instead of a syntax error.

SELECT currval('') returns currval\(\): invalid table name: instead of
pq: currval(): syntax error at or near "to"
DETAIL: source SQL:
ALTER TABLE  RENAME TO x
                    ^
HINT: try \h ALTER TABLE
  • Loading branch information
RichardJCai committed Sep 22, 2021
1 parent 1f345ec commit bc13103
Show file tree
Hide file tree
Showing 6 changed files with 18 additions and 115 deletions.
21 changes: 0 additions & 21 deletions pkg/ccl/importccl/import_table_creation.go
Original file line number Diff line number Diff line change
Expand Up @@ -379,41 +379,20 @@ func (so *importSequenceOperators) HasPrivilege(
return false, errors.WithStack(errSequenceOperators)
}

// IncrementSequence implements the tree.SequenceOperators interface.
func (so *importSequenceOperators) IncrementSequence(
ctx context.Context, seqName *tree.TableName,
) (int64, error) {
return 0, errSequenceOperators
}

// IncrementSequenceByID implements the tree.SequenceOperators interface.
func (so *importSequenceOperators) IncrementSequenceByID(
ctx context.Context, seqID int64,
) (int64, error) {
return 0, errSequenceOperators
}

// GetLatestValueInSessionForSequence implements the tree.SequenceOperators interface.
func (so *importSequenceOperators) GetLatestValueInSessionForSequence(
ctx context.Context, seqName *tree.TableName,
) (int64, error) {
return 0, errSequenceOperators
}

// GetLatestValueInSessionForSequenceByID implements the tree.SequenceOperators interface.
func (so *importSequenceOperators) GetLatestValueInSessionForSequenceByID(
ctx context.Context, seqID int64,
) (int64, error) {
return 0, errSequenceOperators
}

// SetSequenceValue implements the tree.SequenceOperators interface.
func (so *importSequenceOperators) SetSequenceValue(
ctx context.Context, seqName *tree.TableName, newVal int64, isCalled bool,
) error {
return errSequenceOperators
}

// SetSequenceValueByID implements the tree.SequenceOperators interface.
func (so *importSequenceOperators) SetSequenceValueByID(
ctx context.Context, seqID int64, newVal int64, isCalled bool,
Expand Down
22 changes: 0 additions & 22 deletions pkg/sql/faketreeeval/evalctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,28 +89,13 @@ func (so *DummySequenceOperators) HasPrivilege(
return false, errors.WithStack(errEvalPlanner)
}

// IncrementSequence is part of the tree.SequenceOperators interface.
func (so *DummySequenceOperators) IncrementSequence(
ctx context.Context, seqName *tree.TableName,
) (int64, error) {
return 0, errors.WithStack(errSequenceOperators)
}

// IncrementSequenceByID is part of the tree.SequenceOperators interface.
func (so *DummySequenceOperators) IncrementSequenceByID(
ctx context.Context, seqID int64,
) (int64, error) {
return 0, errors.WithStack(errSequenceOperators)
}

// GetLatestValueInSessionForSequence implements the tree.SequenceOperators
// interface.
func (so *DummySequenceOperators) GetLatestValueInSessionForSequence(
ctx context.Context, seqName *tree.TableName,
) (int64, error) {
return 0, errors.WithStack(errSequenceOperators)
}

// GetLatestValueInSessionForSequenceByID implements the tree.SequenceOperators
// interface.
func (so *DummySequenceOperators) GetLatestValueInSessionForSequenceByID(
Expand All @@ -119,13 +104,6 @@ func (so *DummySequenceOperators) GetLatestValueInSessionForSequenceByID(
return 0, errors.WithStack(errSequenceOperators)
}

// SetSequenceValue implements the tree.SequenceOperators interface.
func (so *DummySequenceOperators) SetSequenceValue(
ctx context.Context, seqName *tree.TableName, newVal int64, isCalled bool,
) error {
return errors.WithStack(errSequenceOperators)
}

// SetSequenceValueByID implements the tree.SequenceOperators interface.
func (so *DummySequenceOperators) SetSequenceValueByID(
ctx context.Context, seqID int64, newVal int64, isCalled bool,
Expand Down
12 changes: 8 additions & 4 deletions pkg/sql/logictest/testdata/logic_test/sequences
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ SELECT foo from select_test

# USING THE `nextval` AND `currval` FUNCTIONS

statement error pgcode 55000 pq: currval\(\): currval of sequence "foo" is not yet defined in this session
statement error pgcode 55000 pq: currval\(\): currval of sequence "test.public.foo" is not yet defined in this session
SELECT currval('foo')

query I
Expand Down Expand Up @@ -350,11 +350,11 @@ SELECT nextval('spécial')
statement ok
CREATE TABLE kv (k bytes primary key, v bytes)

statement error pgcode 42809 "kv" is not a sequence
statement error pq: nextval\(\): "test.public.kv" is not a sequence
SELECT nextval('kv')

# Parse errors in the argument to nextval are handled.
statement error pq: nextval\(\): at or near "@": syntax error
# This matches PG's error.
statement error pq: nextval\(\): relation "@#%@!324234" does not exist
SELECT nextval('@#%@!324234')

# You can create and find sequences from other databases.
Expand Down Expand Up @@ -1816,3 +1816,7 @@ SELECT * FROM "".crdb_internal.cross_db_references;
db2 public seq db1 public t sequences owning table
db2 public seq2 db1 public t sequences owning table
test public tdb3ref db3 public s table column refers to sequence

# Testing parsing empty string for currval issue #34527.
statement error pq: currval\(\): invalid table name:
SELECT currval('')
21 changes: 10 additions & 11 deletions pkg/sql/sem/builtins/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -2026,11 +2026,11 @@ var builtins = map[string]builtinDefinition{
ReturnType: tree.FixedReturnType(types.Int),
Fn: func(evalCtx *tree.EvalContext, args tree.Datums) (tree.Datum, error) {
name := tree.MustBeDString(args[0])
qualifiedName, err := parser.ParseQualifiedTableName(string(name))
dOid, err := tree.ParseDOid(evalCtx, string(name), types.RegClass)
if err != nil {
return nil, err
}
res, err := evalCtx.Sequence.IncrementSequence(evalCtx.Ctx(), qualifiedName)
res, err := evalCtx.Sequence.IncrementSequenceByID(evalCtx.Ctx(), int64(dOid.DInt))
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -2066,11 +2066,11 @@ var builtins = map[string]builtinDefinition{
ReturnType: tree.FixedReturnType(types.Int),
Fn: func(evalCtx *tree.EvalContext, args tree.Datums) (tree.Datum, error) {
name := tree.MustBeDString(args[0])
qualifiedName, err := parser.ParseQualifiedTableName(string(name))
dOid, err := tree.ParseDOid(evalCtx, string(name), types.RegClass)
if err != nil {
return nil, err
}
res, err := evalCtx.Sequence.GetLatestValueInSessionForSequence(evalCtx.Ctx(), qualifiedName)
res, err := evalCtx.Sequence.GetLatestValueInSessionForSequenceByID(evalCtx.Ctx(), int64(dOid.DInt))
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -2127,14 +2127,14 @@ var builtins = map[string]builtinDefinition{
ReturnType: tree.FixedReturnType(types.Int),
Fn: func(evalCtx *tree.EvalContext, args tree.Datums) (tree.Datum, error) {
name := tree.MustBeDString(args[0])
qualifiedName, err := parser.ParseQualifiedTableName(string(name))
dOid, err := tree.ParseDOid(evalCtx, string(name), types.RegClass)
if err != nil {
return nil, err
}

newVal := tree.MustBeDInt(args[1])
if err := evalCtx.Sequence.SetSequenceValue(
evalCtx.Ctx(), qualifiedName, int64(newVal), true); err != nil {
if err := evalCtx.Sequence.SetSequenceValueByID(
evalCtx.Ctx(), int64(dOid.DInt), int64(newVal), true); err != nil {
return nil, err
}
return args[1], nil
Expand Down Expand Up @@ -2166,16 +2166,15 @@ var builtins = map[string]builtinDefinition{
ReturnType: tree.FixedReturnType(types.Int),
Fn: func(evalCtx *tree.EvalContext, args tree.Datums) (tree.Datum, error) {
name := tree.MustBeDString(args[0])
qualifiedName, err := parser.ParseQualifiedTableName(string(name))
dOid, err := tree.ParseDOid(evalCtx, string(name), types.RegClass)
if err != nil {
return nil, err
}

isCalled := bool(tree.MustBeDBool(args[2]))

newVal := tree.MustBeDInt(args[1])
if err := evalCtx.Sequence.SetSequenceValue(
evalCtx.Ctx(), qualifiedName, int64(newVal), isCalled); err != nil {
if err := evalCtx.Sequence.SetSequenceValueByID(
evalCtx.Ctx(), int64(dOid.DInt), int64(newVal), isCalled); err != nil {
return nil, err
}
return args[1], nil
Expand Down
15 changes: 0 additions & 15 deletions pkg/sql/sem/tree/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -3340,21 +3340,6 @@ type SequenceOperators interface {
// Returns an empty string if the sequence name does not exist.
GetSerialSequenceNameFromColumn(ctx context.Context, tableName *TableName, columnName Name) (*TableName, error)

// IncrementSequence increments the given sequence and returns the result.
// It returns an error if the given name is not a sequence.
// The caller must ensure that seqName is fully qualified already.
IncrementSequence(ctx context.Context, seqName *TableName) (int64, error)

// GetLatestValueInSessionForSequence returns the value most recently obtained by
// nextval() for the given sequence in this session.
GetLatestValueInSessionForSequence(ctx context.Context, seqName *TableName) (int64, error)

// SetSequenceValue sets the sequence's value.
// If isCalled is false, the sequence is set such that the next time nextval() is called,
// `newVal` is returned. Otherwise, the next call to nextval will return
// `newVal + seqOpts.Increment`.
SetSequenceValue(ctx context.Context, seqName *TableName, newVal int64, isCalled bool) error

// IncrementSequenceByID increments the given sequence and returns the result.
// It returns an error if the given ID is not a sequence.
// Takes in a sequence ID rather than a name, unlike IncrementSequence.
Expand Down
42 changes: 0 additions & 42 deletions pkg/sql/sequence.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,20 +73,6 @@ func (p *planner) GetSerialSequenceNameFromColumn(
return nil, colinfo.NewUndefinedColumnError(string(columnName))
}

// IncrementSequence implements the tree.SequenceOperators interface.
func (p *planner) IncrementSequence(ctx context.Context, seqName *tree.TableName) (int64, error) {
if p.EvalContext().TxnReadOnly {
return 0, readOnlyError("nextval()")
}

flags := tree.ObjectLookupFlagsWithRequiredTableKind(tree.ResolveRequireSequenceDesc)
_, descriptor, err := resolver.ResolveExistingTableObject(ctx, p, seqName, flags)
if err != nil {
return 0, err
}
return incrementSequenceHelper(ctx, p, descriptor)
}

// IncrementSequenceByID implements the tree.SequenceOperators interface.
func (p *planner) IncrementSequenceByID(ctx context.Context, seqID int64) (int64, error) {
if p.EvalContext().TxnReadOnly {
Expand Down Expand Up @@ -226,18 +212,6 @@ func boundsExceededError(descriptor catalog.TableDescriptor) error {
tree.ErrString((*tree.Name)(&name)), value)
}

// GetLatestValueInSessionForSequence implements the tree.SequenceOperators interface.
func (p *planner) GetLatestValueInSessionForSequence(
ctx context.Context, seqName *tree.TableName,
) (int64, error) {
flags := tree.ObjectLookupFlagsWithRequiredTableKind(tree.ResolveRequireSequenceDesc)
_, descriptor, err := resolver.ResolveExistingTableObject(ctx, p, seqName, flags)
if err != nil {
return 0, err
}
return getLatestValueInSessionForSequenceHelper(p, descriptor, seqName)
}

// GetLatestValueInSessionForSequenceByID implements the tree.SequenceOperators interface.
func (p *planner) GetLatestValueInSessionForSequenceByID(
ctx context.Context, seqID int64,
Expand Down Expand Up @@ -273,22 +247,6 @@ func getLatestValueInSessionForSequenceHelper(
return val, nil
}

// SetSequenceValue implements the tree.SequenceOperators interface.
func (p *planner) SetSequenceValue(
ctx context.Context, seqName *tree.TableName, newVal int64, isCalled bool,
) error {
if p.EvalContext().TxnReadOnly {
return readOnlyError("setval()")
}

flags := tree.ObjectLookupFlagsWithRequiredTableKind(tree.ResolveRequireSequenceDesc)
_, descriptor, err := resolver.ResolveExistingTableObject(ctx, p, seqName, flags)
if err != nil {
return err
}
return setSequenceValueHelper(ctx, p, descriptor, newVal, isCalled, seqName)
}

// SetSequenceValueByID implements the tree.SequenceOperators interface.
func (p *planner) SetSequenceValueByID(
ctx context.Context, seqID int64, newVal int64, isCalled bool,
Expand Down

0 comments on commit bc13103

Please sign in to comment.