diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index fd7a9ed033..708831a5c3 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -2395,6 +2395,8 @@ OpenIntoRel(QueryDesc *queryDesc) Datum reloptions; Oid intoRelationId; DR_intorel *myState; + RangeTblEntry *rte; + AttrNumber attnum; static char *validnsps[] = HEAP_RELOPT_NAMESPACES; Assert(into); @@ -2516,6 +2518,21 @@ OpenIntoRel(QueryDesc *queryDesc) */ intoRelationDesc = heap_open(intoRelationId, AccessExclusiveLock); + /* + * check INSERT permission on the constructed table. + */ + rte = makeNode(RangeTblEntry); + rte->rtekind = RTE_RELATION; + rte->relid = intoRelationId; + rte->relkind = RELKIND_RELATION; + rte->requiredPerms = ACL_INSERT; + + for (attnum = 1; attnum <= queryDesc->tupDesc->natts; attnum++) + rte->modifiedCols = bms_add_member(rte->modifiedCols, + attnum - FirstLowInvalidHeapAttributeNumber); + + ExecCheckRTPerms(list_make1(rte), true); + /* * Now replace the query's DestReceiver with one for SELECT INTO */ diff --git a/src/test/regress/expected/select_into.out b/src/test/regress/expected/select_into.out index 503efe04fc..9ed4229b50 100644 --- a/src/test/regress/expected/select_into.out +++ b/src/test/regress/expected/select_into.out @@ -11,3 +11,42 @@ SELECT * FROM onek2 WHERE onek2.unique1 < 2; DROP TABLE tmp1; +-- +-- SELECT INTO and INSERT permission, if owner is not allowed to insert. +-- +CREATE SCHEMA selinto_schema; +CREATE USER selinto_user; +ALTER DEFAULT PRIVILEGES FOR ROLE selinto_user + REVOKE INSERT ON TABLES FROM selinto_user; +GRANT ALL ON SCHEMA selinto_schema TO public; +SET SESSION AUTHORIZATION selinto_user; +SELECT * INTO TABLE selinto_schema.tmp1 + FROM pg_class WHERE relname like '%a%'; -- Error +ERROR: permission denied for relation tmp1 +SELECT oid AS clsoid, relname, relnatts + 10 AS x + INTO selinto_schema.tmp2 + FROM pg_class WHERE relname like '%b%'; -- Error +ERROR: permission denied for relation tmp2 +CREATE TABLE selinto_schema.tmp3 (a,b,c) + AS SELECT oid,relname,relacl FROM pg_class + WHERE relname like '%c%'; -- Error +ERROR: permission denied for relation tmp3 +RESET SESSION AUTHORIZATION; +ALTER DEFAULT PRIVILEGES FOR ROLE selinto_user + GRANT INSERT ON TABLES TO selinto_user; +SET SESSION AUTHORIZATION selinto_user; +SELECT * INTO TABLE selinto_schema.tmp1 + FROM pg_class WHERE relname like '%a%'; -- OK +SELECT oid AS clsoid, relname, relnatts + 10 AS x + INTO selinto_schema.tmp2 + FROM pg_class WHERE relname like '%b%'; -- OK +CREATE TABLE selinto_schema.tmp3 (a,b,c) + AS SELECT oid,relname,relacl FROM pg_class + WHERE relname like '%c%'; -- OK +RESET SESSION AUTHORIZATION; +DROP SCHEMA selinto_schema CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to table selinto_schema.tmp1 +drop cascades to table selinto_schema.tmp2 +drop cascades to table selinto_schema.tmp3 +DROP USER selinto_user; diff --git a/src/test/regress/sql/select_into.sql b/src/test/regress/sql/select_into.sql index 2fa3d1e08e..039d35cd34 100644 --- a/src/test/regress/sql/select_into.sql +++ b/src/test/regress/sql/select_into.sql @@ -15,3 +15,40 @@ SELECT * WHERE onek2.unique1 < 2; DROP TABLE tmp1; + +-- +-- SELECT INTO and INSERT permission, if owner is not allowed to insert. +-- +CREATE SCHEMA selinto_schema; +CREATE USER selinto_user; +ALTER DEFAULT PRIVILEGES FOR ROLE selinto_user + REVOKE INSERT ON TABLES FROM selinto_user; +GRANT ALL ON SCHEMA selinto_schema TO public; + +SET SESSION AUTHORIZATION selinto_user; +SELECT * INTO TABLE selinto_schema.tmp1 + FROM pg_class WHERE relname like '%a%'; -- Error +SELECT oid AS clsoid, relname, relnatts + 10 AS x + INTO selinto_schema.tmp2 + FROM pg_class WHERE relname like '%b%'; -- Error +CREATE TABLE selinto_schema.tmp3 (a,b,c) + AS SELECT oid,relname,relacl FROM pg_class + WHERE relname like '%c%'; -- Error +RESET SESSION AUTHORIZATION; + +ALTER DEFAULT PRIVILEGES FOR ROLE selinto_user + GRANT INSERT ON TABLES TO selinto_user; + +SET SESSION AUTHORIZATION selinto_user; +SELECT * INTO TABLE selinto_schema.tmp1 + FROM pg_class WHERE relname like '%a%'; -- OK +SELECT oid AS clsoid, relname, relnatts + 10 AS x + INTO selinto_schema.tmp2 + FROM pg_class WHERE relname like '%b%'; -- OK +CREATE TABLE selinto_schema.tmp3 (a,b,c) + AS SELECT oid,relname,relacl FROM pg_class + WHERE relname like '%c%'; -- OK +RESET SESSION AUTHORIZATION; + +DROP SCHEMA selinto_schema CASCADE; +DROP USER selinto_user;