diff --git a/pkg/sql/information_schema.go b/pkg/sql/information_schema.go index 2b393314ec69..550a56acd86b 100644 --- a/pkg/sql/information_schema.go +++ b/pkg/sql/information_schema.go @@ -31,6 +31,8 @@ import ( "github.com/cockroachdb/cockroach/pkg/sql/catalog/schemaexpr" "github.com/cockroachdb/cockroach/pkg/sql/catalog/tabledesc" "github.com/cockroachdb/cockroach/pkg/sql/privilege" + "github.com/cockroachdb/cockroach/pkg/sql/sem/builtins" + "github.com/cockroachdb/cockroach/pkg/sql/sem/builtins/builtinsregistry" "github.com/cockroachdb/cockroach/pkg/sql/sem/catconstants" "github.com/cockroachdb/cockroach/pkg/sql/sem/catid" "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" @@ -1603,7 +1605,6 @@ var informationSchemaRoutinePrivilegesTable = virtualSchemaTable{ } var informationSchemaRoleRoutineGrantsTable = virtualSchemaTable{ - // TODO(chengxiong): add builtin function privileges as well. comment: "privileges granted on functions (incomplete; only contains privileges of user-defined functions)", schema: vtable.InformationSchemaRoleRoutineGrants, populate: func(ctx context.Context, p *planner, db catalog.DatabaseDescriptor, addRow func(...tree.Datum) error) error { @@ -1618,6 +1619,54 @@ var informationSchemaRoleRoutineGrantsTable = virtualSchemaTable{ dbDescs = append(dbDescs, db) } for _, db := range dbDescs { + dbNameStr := tree.NewDString(db.GetName()) + exPriv := tree.NewDString(privilege.EXECUTE.String()) + roleNameForBuiltins := []*tree.DString{ + tree.NewDString(username.RootUser), + tree.NewDString(username.PublicRole), + } + for _, name := range builtins.AllBuiltinNames() { + parts := strings.Split(name, ".") + if len(parts) > 2 || len(parts) == 0 { + // This shouldn't happen in theory. + return errors.AssertionFailedf("invalid builtin function name: %s", name) + } + + var fnNameStr string + var fnName *tree.DString + var scNameStr *tree.DString + if len(parts) == 2 { + scNameStr = tree.NewDString(parts[0]) + fnNameStr = parts[1] + fnName = tree.NewDString(fnNameStr) + } else { + scNameStr = tree.NewDString(catconstants.PgCatalogName) + fnNameStr = name + fnName = tree.NewDString(fnNameStr) + } + + _, overloads := builtinsregistry.GetBuiltinProperties(name) + for _, o := range overloads { + fnSpecificName := tree.NewDString(fmt.Sprintf("%s_%d", fnNameStr, o.Oid)) + for _, grantee := range roleNameForBuiltins { + if err := addRow( + tree.DNull, // grantor + grantee, + dbNameStr, // specific_catalog + scNameStr, // specific_schema + fnSpecificName, // specific_name + dbNameStr, // routine_catalog + scNameStr, // routine_schema + fnName, // routine_name + exPriv, // privilege_type + noString, // is_grantable + ); err != nil { + return err + } + } + } + } + err := db.ForEachSchema(func(id descpb.ID, name string) error { sc, err := p.Descriptors().GetImmutableSchemaByID(ctx, p.txn, id, tree.SchemaLookupFlags{Required: true}) if err != nil { @@ -1629,12 +1678,10 @@ var informationSchemaRoleRoutineGrantsTable = virtualSchemaTable{ return err } privs := fn.GetPrivileges() - dbNameStr := tree.NewDString(db.GetName()) scNameStr := tree.NewDString(sc.GetName()) fnSpecificName := tree.NewDString(fmt.Sprintf("%s_%d", fn.GetName(), catid.FuncIDToOID(fn.GetID()))) fnName := tree.NewDString(fn.GetName()) // EXECUTE is the only privilege kind relevant to functions. - exPriv := tree.NewDString(privilege.EXECUTE.String()) if err := addRow( tree.DNull, // grantor tree.NewDString(privs.Owner().Normalized()), // grantee diff --git a/pkg/sql/logictest/testdata/logic_test/information_schema b/pkg/sql/logictest/testdata/logic_test/information_schema index f2b730d0f9c0..4f3fdec8ee03 100644 --- a/pkg/sql/logictest/testdata/logic_test/information_schema +++ b/pkg/sql/logictest/testdata/logic_test/information_schema @@ -5140,3 +5140,110 @@ i NEVER x NEVER y NEVER z ALWAYS + +subtest role_routine_grants + +query TTTTTTTTTT colnames +SELECT * FROM information_schema.role_routine_grants +WHERE reverse(split_part(reverse(specific_name), '_', 1))::INT < 50 +ORDER BY specific_name, grantee; +---- +grantor grantee specific_catalog specific_schema specific_name routine_catalog routine_schema routine_name privilege_type is_grantable +NULL public test pg_catalog array_agg_1 test pg_catalog array_agg EXECUTE NO +NULL root test pg_catalog array_agg_1 test pg_catalog array_agg EXECUTE NO +NULL public test pg_catalog array_agg_10 test pg_catalog array_agg EXECUTE NO +NULL root test pg_catalog array_agg_10 test pg_catalog array_agg EXECUTE NO +NULL public test pg_catalog array_agg_11 test pg_catalog array_agg EXECUTE NO +NULL root test pg_catalog array_agg_11 test pg_catalog array_agg EXECUTE NO +NULL public test pg_catalog array_agg_12 test pg_catalog array_agg EXECUTE NO +NULL root test pg_catalog array_agg_12 test pg_catalog array_agg EXECUTE NO +NULL public test pg_catalog array_agg_13 test pg_catalog array_agg EXECUTE NO +NULL root test pg_catalog array_agg_13 test pg_catalog array_agg EXECUTE NO +NULL public test pg_catalog array_agg_14 test pg_catalog array_agg EXECUTE NO +NULL root test pg_catalog array_agg_14 test pg_catalog array_agg EXECUTE NO +NULL public test pg_catalog array_agg_15 test pg_catalog array_agg EXECUTE NO +NULL root test pg_catalog array_agg_15 test pg_catalog array_agg EXECUTE NO +NULL public test pg_catalog array_agg_16 test pg_catalog array_agg EXECUTE NO +NULL root test pg_catalog array_agg_16 test pg_catalog array_agg EXECUTE NO +NULL public test pg_catalog array_agg_17 test pg_catalog array_agg EXECUTE NO +NULL root test pg_catalog array_agg_17 test pg_catalog array_agg EXECUTE NO +NULL public test pg_catalog array_agg_18 test pg_catalog array_agg EXECUTE NO +NULL root test pg_catalog array_agg_18 test pg_catalog array_agg EXECUTE NO +NULL public test pg_catalog array_agg_19 test pg_catalog array_agg EXECUTE NO +NULL root test pg_catalog array_agg_19 test pg_catalog array_agg EXECUTE NO +NULL public test pg_catalog array_agg_2 test pg_catalog array_agg EXECUTE NO +NULL root test pg_catalog array_agg_2 test pg_catalog array_agg EXECUTE NO +NULL public test pg_catalog array_agg_20 test pg_catalog array_agg EXECUTE NO +NULL root test pg_catalog array_agg_20 test pg_catalog array_agg EXECUTE NO +NULL public test pg_catalog array_agg_21 test pg_catalog array_agg EXECUTE NO +NULL root test pg_catalog array_agg_21 test pg_catalog array_agg EXECUTE NO +NULL public test pg_catalog array_agg_22 test pg_catalog array_agg EXECUTE NO +NULL root test pg_catalog array_agg_22 test pg_catalog array_agg EXECUTE NO +NULL public test pg_catalog array_agg_3 test pg_catalog array_agg EXECUTE NO +NULL root test pg_catalog array_agg_3 test pg_catalog array_agg EXECUTE NO +NULL public test pg_catalog array_agg_4 test pg_catalog array_agg EXECUTE NO +NULL root test pg_catalog array_agg_4 test pg_catalog array_agg EXECUTE NO +NULL public test pg_catalog array_agg_5 test pg_catalog array_agg EXECUTE NO +NULL root test pg_catalog array_agg_5 test pg_catalog array_agg EXECUTE NO +NULL public test pg_catalog array_agg_6 test pg_catalog array_agg EXECUTE NO +NULL root test pg_catalog array_agg_6 test pg_catalog array_agg EXECUTE NO +NULL public test pg_catalog array_agg_7 test pg_catalog array_agg EXECUTE NO +NULL root test pg_catalog array_agg_7 test pg_catalog array_agg EXECUTE NO +NULL public test pg_catalog array_agg_8 test pg_catalog array_agg EXECUTE NO +NULL root test pg_catalog array_agg_8 test pg_catalog array_agg EXECUTE NO +NULL public test pg_catalog array_agg_9 test pg_catalog array_agg EXECUTE NO +NULL root test pg_catalog array_agg_9 test pg_catalog array_agg EXECUTE NO +NULL public test pg_catalog avg_23 test pg_catalog avg EXECUTE NO +NULL root test pg_catalog avg_23 test pg_catalog avg EXECUTE NO +NULL public test pg_catalog avg_24 test pg_catalog avg EXECUTE NO +NULL root test pg_catalog avg_24 test pg_catalog avg EXECUTE NO +NULL public test pg_catalog avg_25 test pg_catalog avg EXECUTE NO +NULL root test pg_catalog avg_25 test pg_catalog avg EXECUTE NO +NULL public test pg_catalog avg_26 test pg_catalog avg EXECUTE NO +NULL root test pg_catalog avg_26 test pg_catalog avg EXECUTE NO +NULL public test pg_catalog bit_and_27 test pg_catalog bit_and EXECUTE NO +NULL root test pg_catalog bit_and_27 test pg_catalog bit_and EXECUTE NO +NULL public test pg_catalog bit_and_28 test pg_catalog bit_and EXECUTE NO +NULL root test pg_catalog bit_and_28 test pg_catalog bit_and EXECUTE NO +NULL public test pg_catalog bit_or_29 test pg_catalog bit_or EXECUTE NO +NULL root test pg_catalog bit_or_29 test pg_catalog bit_or EXECUTE NO +NULL public test pg_catalog bit_or_30 test pg_catalog bit_or EXECUTE NO +NULL root test pg_catalog bit_or_30 test pg_catalog bit_or EXECUTE NO +NULL public test pg_catalog bool_and_31 test pg_catalog bool_and EXECUTE NO +NULL root test pg_catalog bool_and_31 test pg_catalog bool_and EXECUTE NO +NULL public test pg_catalog bool_or_32 test pg_catalog bool_or EXECUTE NO +NULL root test pg_catalog bool_or_32 test pg_catalog bool_or EXECUTE NO +NULL public test pg_catalog concat_agg_33 test pg_catalog concat_agg EXECUTE NO +NULL root test pg_catalog concat_agg_33 test pg_catalog concat_agg EXECUTE NO +NULL public test pg_catalog concat_agg_34 test pg_catalog concat_agg EXECUTE NO +NULL root test pg_catalog concat_agg_34 test pg_catalog concat_agg EXECUTE NO +NULL public test pg_catalog corr_35 test pg_catalog corr EXECUTE NO +NULL root test pg_catalog corr_35 test pg_catalog corr EXECUTE NO +NULL public test pg_catalog corr_36 test pg_catalog corr EXECUTE NO +NULL root test pg_catalog corr_36 test pg_catalog corr EXECUTE NO +NULL public test pg_catalog corr_37 test pg_catalog corr EXECUTE NO +NULL root test pg_catalog corr_37 test pg_catalog corr EXECUTE NO +NULL public test pg_catalog corr_38 test pg_catalog corr EXECUTE NO +NULL root test pg_catalog corr_38 test pg_catalog corr EXECUTE NO +NULL public test pg_catalog corr_39 test pg_catalog corr EXECUTE NO +NULL root test pg_catalog corr_39 test pg_catalog corr EXECUTE NO +NULL public test pg_catalog corr_40 test pg_catalog corr EXECUTE NO +NULL root test pg_catalog corr_40 test pg_catalog corr EXECUTE NO +NULL public test pg_catalog corr_41 test pg_catalog corr EXECUTE NO +NULL root test pg_catalog corr_41 test pg_catalog corr EXECUTE NO +NULL public test pg_catalog corr_42 test pg_catalog corr EXECUTE NO +NULL root test pg_catalog corr_42 test pg_catalog corr EXECUTE NO +NULL public test pg_catalog corr_43 test pg_catalog corr EXECUTE NO +NULL root test pg_catalog corr_43 test pg_catalog corr EXECUTE NO +NULL public test pg_catalog covar_pop_44 test pg_catalog covar_pop EXECUTE NO +NULL root test pg_catalog covar_pop_44 test pg_catalog covar_pop EXECUTE NO +NULL public test pg_catalog covar_pop_45 test pg_catalog covar_pop EXECUTE NO +NULL root test pg_catalog covar_pop_45 test pg_catalog covar_pop EXECUTE NO +NULL public test pg_catalog covar_pop_46 test pg_catalog covar_pop EXECUTE NO +NULL root test pg_catalog covar_pop_46 test pg_catalog covar_pop EXECUTE NO +NULL public test pg_catalog covar_pop_47 test pg_catalog covar_pop EXECUTE NO +NULL root test pg_catalog covar_pop_47 test pg_catalog covar_pop EXECUTE NO +NULL public test pg_catalog covar_pop_48 test pg_catalog covar_pop EXECUTE NO +NULL root test pg_catalog covar_pop_48 test pg_catalog covar_pop EXECUTE NO +NULL public test pg_catalog covar_pop_49 test pg_catalog covar_pop EXECUTE NO +NULL root test pg_catalog covar_pop_49 test pg_catalog covar_pop EXECUTE NO