getPolicies(Archive *fout, TableInfo tblinfo[], int numTables)
{
PQExpBuffer query;
+ PQExpBuffer tbloids;
PGresult *res;
PolicyInfo *polinfo;
int i_oid;
j,
ntups;
+ /* No policies before 9.5 */
if (fout->remoteVersion < 90500)
return;
query = createPQExpBuffer();
+ tbloids = createPQExpBuffer();
/*
- * First, check which tables have RLS enabled. We represent RLS being
- * enabled on a table by creating a PolicyInfo object with null polname.
+ * Identify tables of interest, and check which ones have RLS enabled.
*/
+ appendPQExpBufferChar(tbloids, '{');
for (i = 0; i < numTables; i++)
{
TableInfo *tbinfo = &tblinfo[i];
if (!(tbinfo->dobj.dump & DUMP_COMPONENT_POLICY))
continue;
+ /* It can't have RLS or policies if it's not a table */
+ if (tbinfo->relkind != RELKIND_RELATION &&
+ tbinfo->relkind != RELKIND_PARTITIONED_TABLE)
+ continue;
+
+ /* Add it to the list of table OIDs to be probed below */
+ if (tbloids->len > 1) /* do we have more than the '{'? */
+ appendPQExpBufferChar(tbloids, ',');
+ appendPQExpBuffer(tbloids, "%u", tbinfo->dobj.catId.oid);
+
+ /* Is RLS enabled? (That's separate from whether it has policies) */
if (tbinfo->rowsec)
{
/*
+ * We represent RLS being enabled on a table by creating a
+ * PolicyInfo object with null polname.
+ *
* Note: use tableoid 0 so that this object won't be mistaken for
* something that pg_depend entries apply to.
*/
polinfo->polwithcheck = NULL;
}
}
+ appendPQExpBufferChar(tbloids, '}');
/*
- * Now, read all RLS policies, and create PolicyInfo objects for all those
- * that are of interest.
+ * Now, read all RLS policies belonging to the tables of interest, and
+ * create PolicyInfo objects for them. (Note that we must filter the
+ * results server-side not locally, because we dare not apply pg_get_expr
+ * to tables we don't have lock on.)
*/
pg_log_info("reading row-level security policies");
printfPQExpBuffer(query,
- "SELECT oid, tableoid, pol.polrelid, pol.polname, pol.polcmd, ");
+ "SELECT pol.oid, pol.tableoid, pol.polrelid, pol.polname, pol.polcmd, ");
if (fout->remoteVersion >= 100000)
appendPQExpBuffer(query, "pol.polpermissive, ");
else
" pg_catalog.array_to_string(ARRAY(SELECT pg_catalog.quote_ident(rolname) from pg_catalog.pg_roles WHERE oid = ANY(pol.polroles)), ', ') END AS polroles, "
"pg_catalog.pg_get_expr(pol.polqual, pol.polrelid) AS polqual, "
"pg_catalog.pg_get_expr(pol.polwithcheck, pol.polrelid) AS polwithcheck "
- "FROM pg_catalog.pg_policy pol");
+ "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
+ "JOIN pg_catalog.pg_policy pol ON (src.tbloid = pol.polrelid)",
+ tbloids->data);
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
Oid polrelid = atooid(PQgetvalue(res, j, i_polrelid));
TableInfo *tbinfo = findTableByOid(polrelid);
- /*
- * Ignore row security on tables not to be dumped. (This will
- * result in some harmless wasted slots in polinfo[].)
- */
- if (!(tbinfo->dobj.dump & DUMP_COMPONENT_POLICY))
- continue;
-
polinfo[j].dobj.objType = DO_POLICY;
polinfo[j].dobj.catId.tableoid =
atooid(PQgetvalue(res, j, i_tableoid));
PQclear(res);
destroyPQExpBuffer(query);
+ destroyPQExpBuffer(tbloids);
}
/*