Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plpgsql: implement RAISE statements #106351

Merged
merged 3 commits into from
Jul 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions pkg/ccl/logictestccl/tests/3node-tenant/generated_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions pkg/sql/conn_io.go
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,9 @@ type RestrictedCommandResult interface {
// This gets flushed only when the CommandResult is closed.
BufferNotice(notice pgnotice.Notice)

// SendNotice immediately flushes a notice to the client.
SendNotice(ctx context.Context, notice pgnotice.Notice) error

// SetColumns informs the client about the schema of the result. The columns
// can be nil.
//
Expand Down Expand Up @@ -1079,6 +1082,12 @@ func (r *streamingCommandResult) BufferNotice(notice pgnotice.Notice) {
// Unimplemented: the internal executor does not support notices.
}

// SendNotice is part of the RestrictedCommandResult interface.
func (r *streamingCommandResult) SendNotice(ctx context.Context, notice pgnotice.Notice) error {
// Unimplemented: the internal executor does not support notices.
return nil
}

// ResetStmtType is part of the RestrictedCommandResult interface.
func (r *streamingCommandResult) ResetStmtType(stmt tree.Statement) {
panic("unimplemented")
Expand Down
5 changes: 5 additions & 0 deletions pkg/sql/faketreeeval/evalctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,11 @@ var _ eval.ClientNoticeSender = &DummyClientNoticeSender{}
// BufferClientNotice is part of the eval.ClientNoticeSender interface.
func (c *DummyClientNoticeSender) BufferClientNotice(context.Context, pgnotice.Notice) {}

// SendClientNotice is part of the eval.ClientNoticeSender interface.
func (c *DummyClientNoticeSender) SendClientNotice(context.Context, pgnotice.Notice) error {
return nil
}

// DummyTenantOperator implements the tree.TenantOperator interface.
type DummyTenantOperator struct{}

Expand Down
3 changes: 3 additions & 0 deletions pkg/sql/logictest/logic.go
Original file line number Diff line number Diff line change
Expand Up @@ -1248,6 +1248,9 @@ func (t *logicTest) openDB(pgURL url.URL) *gosql.DB {
if notice.Hint != "" {
t.noticeBuffer = append(t.noticeBuffer, "HINT: "+notice.Hint)
}
if notice.Code != "" && notice.Code != "00000" {
t.noticeBuffer = append(t.noticeBuffer, "SQLSTATE: "+string(notice.Code))
}
})

return gosql.OpenDB(connector)
Expand Down
3 changes: 2 additions & 1 deletion pkg/sql/logictest/testdata/logic_test/notice
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,5 @@ UNLISTEN temp
----
NOTICE: unimplemented: CRDB does not support LISTEN, making UNLISTEN a no-op
HINT: You have attempted to use a feature that is not yet implemented.
See: https://go.crdb.dev/issue-v/41522/*
See: https://go.crdb.dev/issue-v/41522/v23.2
SQLSTATE: 0A000
166 changes: 166 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/raise
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
# Test different log levels.
query T noticetrace
SELECT crdb_internal.plpgsql_raise('DEBUG1', 'foo', '', '', '');
----

query T noticetrace
SELECT crdb_internal.plpgsql_raise('LOG', 'foo', '', '', '');
----

query T noticetrace
SELECT crdb_internal.plpgsql_raise('INFO', 'foo', '', '', '');
----
INFO: foo
SQLSTATE: XXUUU

query T noticetrace
SELECT crdb_internal.plpgsql_raise('NOTICE', 'foo', '', '', '');
----
NOTICE: foo
SQLSTATE: XXUUU

query T noticetrace
SELECT crdb_internal.plpgsql_raise('WARNING', 'foo', '', '', '');
----
WARNING: foo
SQLSTATE: XXUUU

statement ok
SET client_min_messages = 'debug1';

query T noticetrace
SELECT crdb_internal.plpgsql_raise('DEBUG1', 'foo', '', '', '');
----
DEBUG1: foo
SQLSTATE: XXUUU

query T noticetrace
SELECT crdb_internal.plpgsql_raise('LOG', 'foo', '', '', '');
----
LOG: foo
SQLSTATE: XXUUU

query T noticetrace
SELECT crdb_internal.plpgsql_raise('INFO', 'foo', '', '', '');
----
INFO: foo
SQLSTATE: XXUUU

query T noticetrace
SELECT crdb_internal.plpgsql_raise('NOTICE', 'foo', '', '', '');
----
NOTICE: foo
SQLSTATE: XXUUU

query T noticetrace
SELECT crdb_internal.plpgsql_raise('WARNING', 'foo', '', '', '');
----
WARNING: foo
SQLSTATE: XXUUU

statement ok
SET client_min_messages = 'WARNING';

query T noticetrace
SELECT crdb_internal.plpgsql_raise('DEBUG1', 'foo', '', '', '');
----

query T noticetrace
SELECT crdb_internal.plpgsql_raise('LOG', 'foo', '', '', '');
----

# INFO-level notices are always sent to the client.
query T noticetrace
SELECT crdb_internal.plpgsql_raise('INFO', 'foo', '', '', '');
----
INFO: foo
SQLSTATE: XXUUU

query T noticetrace
SELECT crdb_internal.plpgsql_raise('NOTICE', 'foo', '', '', '');
----

query T noticetrace
SELECT crdb_internal.plpgsql_raise('WARNING', 'foo', '', '', '');
----
WARNING: foo
SQLSTATE: XXUUU

statement ok
RESET client_min_messages;

# Test RAISE options.
query T noticetrace
SELECT crdb_internal.plpgsql_raise('NOTICE', 'bar', 'this is a detail', '', '');
----
NOTICE: bar
DETAIL: this is a detail
SQLSTATE: XXUUU

query T noticetrace
SELECT crdb_internal.plpgsql_raise('NOTICE', 'baz', '', 'this is a hint', '');
----
NOTICE: baz
HINT: this is a hint
SQLSTATE: XXUUU

query T noticetrace
SELECT crdb_internal.plpgsql_raise('NOTICE', 'division by zero', '', '', '22012');
----
NOTICE: division by zero
SQLSTATE: 22012

query T noticetrace
SELECT crdb_internal.plpgsql_raise('WARNING', 'invalid password', '', '', '28P01');
----
WARNING: invalid password
SQLSTATE: 28P01

query T noticetrace
SELECT crdb_internal.plpgsql_raise('NOTICE', 'this is a message', 'this is a detail', 'this is a hint', 'P0001');
----
NOTICE: this is a message
DETAIL: this is a detail
HINT: this is a hint
SQLSTATE: P0001

query T noticetrace
SELECT crdb_internal.plpgsql_raise('NOTICE', 'division by zero msg', '', '', 'division_by_zero');
----
NOTICE: division by zero msg
SQLSTATE: 22012

query T noticetrace
SELECT crdb_internal.plpgsql_raise('NOTICE', '', 'message is empty', '', 'P0001');
----
NOTICE:
DETAIL: message is empty
SQLSTATE: P0001

query T noticetrace
SELECT crdb_internal.plpgsql_raise('NOTICE', '', '', '', '');
----
NOTICE:
SQLSTATE: XXUUU

query error pgcode 42704 pq: unrecognized exception condition: \"this_is_not_valid\"
SELECT crdb_internal.plpgsql_raise('NOTICE', '', '', '', 'this_is_not_valid');

query error pgcode 42704 pq: unrecognized exception condition: \"-50\"
SELECT crdb_internal.plpgsql_raise('NOTICE', '', '', '', '-50');

query error pgcode 22023 pq: severity NOTE is invalid
SELECT crdb_internal.plpgsql_raise('NOTE', '', '', '', '-50');

# Test severity ERROR.
query error pgcode XXUUU pq: foo
SELECT crdb_internal.plpgsql_raise('ERROR', 'foo', '', '', '');

query error pgcode 12345 pq: foo
SELECT crdb_internal.plpgsql_raise('ERROR', 'foo', '', '', '12345');

query error pgcode 12345 pq: msg\nHINT: hint\nDETAIL: detail
SELECT crdb_internal.plpgsql_raise('ERROR', 'msg', 'detail', 'hint', '12345');

query error pgcode XXUUU pq:
SELECT crdb_internal.plpgsql_raise('ERROR', '', '', '', '');
Loading