Skip to content

Commit

Permalink
sql: allow procedures to call other procedures
Browse files Browse the repository at this point in the history
Release note (sql change): Stored procedures can now invoke other
stored procedures via `CALL` statements.
  • Loading branch information
mgartner committed Mar 20, 2024
1 parent a2baac9 commit a5954ad
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 11 deletions.
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.

92 changes: 92 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/proc_invokes_proc
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# LogicTest: !local-mixed-23.1 !local-mixed-23.2

statement ok
CREATE PROCEDURE a() LANGUAGE SQL AS $$
SELECT 1;
$$

statement ok
CREATE PROCEDURE b() LANGUAGE SQL AS $$
CALL a();
$$

# Mutual recursion is not currently allowed.
statement error pgcode 42P13 cannot add dependency from descriptor \d+ to function b \(\d+\) because there will be a dependency cycle
CREATE OR REPLACE PROCEDURE a() LANGUAGE SQL AS $$
CALL b();
$$

statement error pgcode 2BP01 cannot drop function \"a\" because other objects \(\[test.public.b\]\) still depend on it
DROP PROCEDURE a

statement ok
DROP PROCEDURE b;
DROP PROCEDURE a;

statement ok
CREATE TYPE e AS ENUM ('foo', 'bar');

statement ok
CREATE PROCEDURE a() LANGUAGE SQL AS $$
SELECT 'foo'::e;
$$

statement ok
CREATE PROCEDURE b() LANGUAGE SQL AS $$
CALL a();
$$

statement error pgcode 2BP01 cannot drop type \"e\" because other objects \(\[test.public.a\]\) still depend on it
DROP TYPE e

statement ok
DROP PROCEDURE b;
DROP PROCEDURE a;
DROP TYPE e;

statement ok
CREATE TABLE ab (
a INT PRIMARY KEY,
b INT
)

statement ok
CREATE PROCEDURE ins_ab(new_a INT, new_b INT) LANGUAGE SQL AS $$
INSERT INTO ab VALUES (new_a, new_b);
$$

statement ok
CREATE PROCEDURE ins3() LANGUAGE SQL AS $$
CALL ins_ab(1, 10);
CALL ins_ab(2, 20);
CALL ins_ab(3, 30);
$$

statement ok
CALL ins_ab(4, 40)

statement ok
CALL ins3()

statement error pgcode 23505 duplicate key value violates unique constraint \"ab_pkey\"
CALL ins3()

query II rowsort
SELECT * FROM ab
----
1 10
2 20
3 30
4 40

# TODO(#102771): Add dependency tracking that causes this to error.
# statement error pgcode 2BP01 cannot drop table ab because other objects depend on it
# DROP TABLE ab;

statement error pgcode 2BP01 cannot drop function \"ins_ab\" because other objects \(\[test.public.ins3\]\) still depend on it
DROP PROCEDURE ins_ab

statement ok
DROP PROCEDURE ins3;
DROP PROCEDURE ins_ab;
DROP TABLE ab;
9 changes: 0 additions & 9 deletions pkg/sql/logictest/testdata/logic_test/procedure
Original file line number Diff line number Diff line change
Expand Up @@ -112,18 +112,9 @@ CALL p(foo())
statement error pgcode 42723 function "p" already exists with same argument types
CREATE FUNCTION p() RETURNS VOID LANGUAGE SQL AS ''

# TODO(mgartner): The error should state "procedure definition" too.
statement error pgcode 0A000 unimplemented: CALL usage inside a function definition
CREATE OR REPLACE PROCEDURE p2() LANGUAGE SQL AS $$
CALL p();
$$

statement error pgcode 42809 p\(\) is a procedure
CREATE FUNCTION err(i INT) RETURNS VOID LANGUAGE SQL AS 'SELECT p()'

statement error pgcode 0A000 unimplemented: CALL usage inside a function definition
CREATE FUNCTION err(i INT) RETURNS VOID LANGUAGE SQL AS 'CALL p()'

statement error pgcode 42809 p\(\) is a procedure\nHINT: To call a procedure, use CALL.
CREATE TABLE err (i INT DEFAULT p())

Expand Down
7 changes: 7 additions & 0 deletions pkg/sql/logictest/tests/fakedist-disk/generated_test.go

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

7 changes: 7 additions & 0 deletions pkg/sql/logictest/tests/fakedist-vec-off/generated_test.go

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

7 changes: 7 additions & 0 deletions pkg/sql/logictest/tests/fakedist/generated_test.go

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

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

7 changes: 7 additions & 0 deletions pkg/sql/logictest/tests/local-vec-off/generated_test.go

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

7 changes: 7 additions & 0 deletions pkg/sql/logictest/tests/local/generated_test.go

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

9 changes: 7 additions & 2 deletions pkg/sql/opt/optbuilder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,11 @@ func (b *Builder) buildStmt(
if !activeVersion.IsActive(clusterversion.V23_2) {
panic(unimplemented.Newf("user-defined functions", "%s usage inside a function definition is not supported until version 23.2", stmt.StatementTag()))
}
case *tree.Call:
activeVersion := b.evalCtx.Settings.Version.ActiveVersion(b.ctx)
if !activeVersion.IsActive(clusterversion.V24_1) {
panic(unimplemented.Newf("stored procedures", "%s usage inside a routine definition is not supported until version 24.1", stmt.StatementTag()))
}
default:
panic(unimplemented.Newf("user-defined functions", "%s usage inside a function definition", stmt.StatementTag()))
}
Expand Down Expand Up @@ -494,7 +499,7 @@ func (b *Builder) trackReferencedColumnForViews(col *scopeColumn) {

func (b *Builder) maybeTrackRegclassDependenciesForViews(texpr tree.TypedExpr) {
if b.trackSchemaDeps {
if texpr.ResolvedType().Identical(types.RegClass) {
if texpr != nil && texpr.ResolvedType().Identical(types.RegClass) {
// We do not add a dependency if the RegClass Expr contains variables,
// we cannot resolve the variables in this context. This matches Postgres
// behavior.
Expand Down Expand Up @@ -528,7 +533,7 @@ func (b *Builder) maybeTrackRegclassDependenciesForViews(texpr tree.TypedExpr) {

func (b *Builder) maybeTrackUserDefinedTypeDepsForViews(texpr tree.TypedExpr) {
if b.trackSchemaDeps {
if texpr.ResolvedType().UserDefined() {
if texpr != nil && texpr.ResolvedType().UserDefined() {
typedesc.GetTypeDescriptorClosure(texpr.ResolvedType()).ForEach(func(id descpb.ID) {
b.schemaTypeDeps.Add(int(id))
})
Expand Down
5 changes: 5 additions & 0 deletions pkg/sql/schemachanger/comparator_generated_test.go

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

0 comments on commit a5954ad

Please sign in to comment.