* buildACLQueries * * Build the subqueries to extract out the correct set of ACLs to be * GRANT'd and REVOKE'd for the specific kind of object, accounting for any * initial privileges (from pg_init_privs) and based on if we are in binary * upgrade mode or not. * * Also builds subqueries to extract out the set of ACLs to go from the object * default privileges to the privileges in pg_init_p
| 713 | * cluster before the regular privileges are added on top of those. |
| 714 | */ |
| 715 | void |
| 716 | buildACLQueries(PQExpBuffer acl_subquery, PQExpBuffer racl_subquery, |
| 717 | PQExpBuffer init_acl_subquery, PQExpBuffer init_racl_subquery, |
| 718 | const char *acl_column, const char *acl_owner, |
| 719 | const char *obj_kind, bool binary_upgrade) |
| 720 | { |
| 721 | /* |
| 722 | * To get the delta from what the permissions were at creation time |
| 723 | * (either initdb or CREATE EXTENSION) vs. what they are now, we have to |
| 724 | * look at two things: |
| 725 | * |
| 726 | * What privileges have been added, which we calculate by extracting all |
| 727 | * the current privileges (using the set of default privileges for the |
| 728 | * object type if current privileges are NULL) and then removing those |
| 729 | * which existed at creation time (again, using the set of default |
| 730 | * privileges for the object type if there were no creation time |
| 731 | * privileges). |
| 732 | * |
| 733 | * What privileges have been removed, which we calculate by extracting the |
| 734 | * privileges as they were at creation time (or the default privileges, as |
| 735 | * above), and then removing the current privileges (or the default |
| 736 | * privileges, if current privileges are NULL). |
| 737 | * |
| 738 | * As a good cross-check, both directions of these checks should result in |
| 739 | * the empty set if both the current ACL and the initial privs are NULL |
| 740 | * (meaning, in practice, that the default ACLs were there at init time |
| 741 | * and is what the current privileges are). |
| 742 | * |
| 743 | * We always perform this delta on all ACLs and expect that by the time |
| 744 | * these are run the initial privileges will be in place, even in a binary |
| 745 | * upgrade situation (see below). |
| 746 | * |
| 747 | * Finally, the order in which privileges are in the ACL string (the order |
| 748 | * they been GRANT'd in, which the backend maintains) must be preserved to |
| 749 | * ensure that GRANTs WITH GRANT OPTION and subsequent GRANTs based on |
| 750 | * those are dumped in the correct order. |
| 751 | */ |
| 752 | printfPQExpBuffer(acl_subquery, |
| 753 | "(SELECT pg_catalog.array_agg(acl ORDER BY row_n) FROM " |
| 754 | "(SELECT acl, row_n FROM " |
| 755 | "pg_catalog.unnest(coalesce(%s,pg_catalog.acldefault(%s,%s))) " |
| 756 | "WITH ORDINALITY AS perm(acl,row_n) " |
| 757 | "WHERE NOT EXISTS ( " |
| 758 | "SELECT 1 FROM " |
| 759 | "pg_catalog.unnest(coalesce(pip.initprivs,pg_catalog.acldefault(%s,%s))) " |
| 760 | "AS init(init_acl) WHERE acl = init_acl)) as foo)", |
| 761 | acl_column, |
| 762 | obj_kind, |
| 763 | acl_owner, |
| 764 | obj_kind, |
| 765 | acl_owner); |
| 766 | |
| 767 | printfPQExpBuffer(racl_subquery, |
| 768 | "(SELECT pg_catalog.array_agg(acl ORDER BY row_n) FROM " |
| 769 | "(SELECT acl, row_n FROM " |
| 770 | "pg_catalog.unnest(coalesce(pip.initprivs,pg_catalog.acldefault(%s,%s))) " |
| 771 | "WITH ORDINALITY AS initp(acl,row_n) " |
| 772 | "WHERE NOT EXISTS ( " |
no test coverage detected