public inbox for [email protected]  
help / color / mirror / Atom feed
[PATCH 1/3] bootstrap: convert Typ to a List*
4+ messages / 3 participants
[nested] [flat]

* [PATCH 1/3] bootstrap: convert Typ to a List*
@ 2020-11-20 02:48  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 4+ messages in thread

From: Justin Pryzby @ 2020-11-20 02:48 UTC (permalink / raw)

---
 src/backend/bootstrap/bootstrap.c | 69 ++++++++++++++-----------------
 1 file changed, 31 insertions(+), 38 deletions(-)

diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 6f615e6622..18eb62ca47 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -159,7 +159,7 @@ struct typmap
 	FormData_pg_type am_typ;
 };
 
-static struct typmap **Typ = NULL;
+static List *Typ = NIL; /* List of struct typmap* */
 static struct typmap *Ap = NULL;
 
 static Datum values[MAXATTR];	/* current row's attribute values */
@@ -597,7 +597,7 @@ boot_openrel(char *relname)
 	 * pg_type must be filled before any OPEN command is executed, hence we
 	 * can now populate the Typ array if we haven't yet.
 	 */
-	if (Typ == NULL)
+	if (Typ == NIL)
 		populate_typ_array();
 
 	if (boot_reldesc != NULL)
@@ -688,7 +688,7 @@ DefineAttr(char *name, char *type, int attnum, int nullness)
 
 	typeoid = gettype(type);
 
-	if (Typ != NULL)
+	if (Typ != NIL)
 	{
 		attrtypes[attnum]->atttypid = Ap->am_oid;
 		attrtypes[attnum]->attlen = Ap->am_typ.typlen;
@@ -877,36 +877,25 @@ populate_typ_array(void)
 	Relation	rel;
 	TableScanDesc scan;
 	HeapTuple	tup;
-	int			nalloc;
-	int			i;
-
-	Assert(Typ == NULL);
 
-	nalloc = 512;
-	Typ = (struct typmap **)
-		MemoryContextAlloc(TopMemoryContext, nalloc * sizeof(struct typmap *));
+	Assert(Typ == NIL);
 
 	rel = table_open(TypeRelationId, NoLock);
 	scan = table_beginscan_catalog(rel, 0, NULL);
-	i = 0;
 	while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		Form_pg_type typForm = (Form_pg_type) GETSTRUCT(tup);
+		struct typmap *newtyp;
+		MemoryContext old;
 
-		/* make sure there will be room for a trailing NULL pointer */
-		if (i >= nalloc - 1)
-		{
-			nalloc *= 2;
-			Typ = (struct typmap **)
-				repalloc(Typ, nalloc * sizeof(struct typmap *));
-		}
-		Typ[i] = (struct typmap *)
-			MemoryContextAlloc(TopMemoryContext, sizeof(struct typmap));
-		Typ[i]->am_oid = typForm->oid;
-		memcpy(&(Typ[i]->am_typ), typForm, sizeof(Typ[i]->am_typ));
-		i++;
+		old = MemoryContextSwitchTo(TopMemoryContext);
+		newtyp = (struct typmap *) palloc(sizeof(struct typmap));
+		Typ = lappend(Typ, newtyp);
+		MemoryContextSwitchTo(old);
+
+		newtyp->am_oid = typForm->oid;
+		memcpy(&newtyp->am_typ, typForm, sizeof(newtyp->am_typ));
 	}
-	Typ[i] = NULL;				/* Fill trailing NULL pointer */
 	table_endscan(scan);
 	table_close(rel, NoLock);
 }
@@ -925,16 +914,17 @@ populate_typ_array(void)
 static Oid
 gettype(char *type)
 {
-	if (Typ != NULL)
+	if (Typ != NIL)
 	{
-		struct typmap **app;
+		ListCell *lc;
 
-		for (app = Typ; *app != NULL; app++)
+		foreach (lc, Typ)
 		{
-			if (strncmp(NameStr((*app)->am_typ.typname), type, NAMEDATALEN) == 0)
+			struct typmap *app = lfirst(lc);
+			if (strncmp(NameStr(app->am_typ.typname), type, NAMEDATALEN) == 0)
 			{
-				Ap = *app;
-				return (*app)->am_oid;
+				Ap = app;
+				return app->am_oid;
 			}
 		}
 	}
@@ -980,14 +970,17 @@ boot_get_type_io_data(Oid typid,
 	if (Typ != NULL)
 	{
 		/* We have the boot-time contents of pg_type, so use it */
-		struct typmap **app;
-		struct typmap *ap;
-
-		app = Typ;
-		while (*app && (*app)->am_oid != typid)
-			++app;
-		ap = *app;
-		if (ap == NULL)
+		struct typmap *ap = NULL;
+		ListCell *lc;
+
+		foreach (lc, Typ)
+		{
+			ap = lfirst(lc);
+			if (ap->am_oid == typid)
+				break;
+		}
+
+		if (!ap || ap->am_oid != typid)
 			elog(ERROR, "type OID %u not found in Typ list", typid);
 
 		*typlen = ap->am_typ.typlen;
-- 
2.26.2


--------------76B8D0DC8AE327D516738282
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Allow-composite-types-in-bootstrap-20210108.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="0002-Allow-composite-types-in-bootstrap-20210108.patch"



^ permalink  raw  reply  [nested|flat] 4+ messages in thread

* Re: COPY FROM with RLS
@ 2026-05-25 04:50  solai v <[email protected]>
  2 siblings, 0 replies; 4+ messages in thread

From: solai v @ 2026-05-25 04:50 UTC (permalink / raw)
  To: jian he <[email protected]>; +Cc: pgsql-hackers

Hi jian,
I tested the v2 patch for COPY FROM with RLS.
Before applying the patch, I was able to reproduce the issue where
\copy bypassed the RLS INSERT policy and allowed invalid rows to be
inserted.
After applying the patch and retesting, rows violating the policy were
correctly rejected during \copy, while valid rows were inserted
successfully. The behavior is now consistent with normal INSERT.
The error context reporting during COPY was also clear and helpful
while testing.

Regards,
Solai






^ permalink  raw  reply  [nested|flat] 4+ messages in thread

* Re:Re: COPY FROM with RLS
@ 2026-06-29 10:13  Yilin Zhang <[email protected]>
  2 siblings, 0 replies; 4+ messages in thread

From: Yilin Zhang @ 2026-06-29 10:13 UTC (permalink / raw)
  To: jian he <[email protected]>; +Cc: pgsql-hackers

At 2026-05-10 14:23:26, "jian he" <[email protected]> wrote:
>Hi. I implemented a hack to make it work with RLS policies that
>contain subqueries; I'm not sure how valid it is.
>
>IF  (check_enable_rls(RelationGetRelid(cstate->rel), InvalidOid,
>false) == RLS_ENABLED)
>is true, then we construct a dummy query string:
>
>INSERT INTO "%s"."%s" DEFAULT VALUES
>
>(where %s.%s is replaced by the schema-qualified relation name) and
>then run it through the following pipeline:
>pg_analyze_and_rewrite_fixedparams()
>pg_plan_query()
>CreateQueryDesc()
>ExecutorStart()
>
>Obviously, ExecutorRun() cannot be used because the data source for COPY FROM is
>an external file rather than a normal query execution.
>
>The main hack is to bypass ExecutorRun() completely and only use ExecutorStart()
>to initialize the required executor structures (EState, PlanState,
>ResultRelInfo, etc.) for ExecWithCheckOptions (which is part of
>ExecutorRun normally).
>
>In DoCopy we did converting COPY (REL) TO,to a SelectStmt  when REL have RLS.

Hi, I've gone through your v2 patch and there’s an issue I’d like to point out.
In src/test/regress/expected/rowsecurity.out:


+-- COPY FROM should also apply INSERT CHECK policy clause
+COPY rls_test_tgt FROM STDIN WITH (DELIMITER ',');
+ERROR:  missing data for column "c"
+CONTEXT:  COPY rls_test_tgt, line 1: "1,tgt a"


This "missing data for column c" error is actually a COPY formatting error, not an RLS policy violation.




Best regards,

--

Yilin Zhang





^ permalink  raw  reply  [nested|flat] 4+ messages in thread

* Re:Re: COPY FROM with RLS
@ 2026-06-30 01:20  Yilin Zhang <[email protected]>
  2 siblings, 0 replies; 4+ messages in thread

From: Yilin Zhang @ 2026-06-30 01:20 UTC (permalink / raw)
  To: jian he <[email protected]>; +Cc: pgsql-hackers

At 2026-05-10 14:23:26, "jian he" <[email protected]> wrote:
>Hi. I implemented a hack to make it work with RLS policies that
>contain subqueries; I'm not sure how valid it is.
>
>IF  (check_enable_rls(RelationGetRelid(cstate->rel), InvalidOid,
>false) == RLS_ENABLED)
>is true, then we construct a dummy query string:
>
>INSERT INTO "%s"."%s" DEFAULT VALUES
>
>(where %s.%s is replaced by the schema-qualified relation name) and
>then run it through the following pipeline:
>pg_analyze_and_rewrite_fixedparams()
>pg_plan_query()
>CreateQueryDesc()
>ExecutorStart()
>
>Obviously, ExecutorRun() cannot be used because the data source for COPY FROM is
>an external file rather than a normal query execution.
>
>The main hack is to bypass ExecutorRun() completely and only use ExecutorStart()
>to initialize the required executor structures (EState, PlanState,
>ResultRelInfo, etc.) for ExecWithCheckOptions (which is part of
>ExecutorRun normally).
>
>In DoCopy we did converting COPY (REL) TO,to a SelectStmt  when REL have RLS.



Hi, I found another issue with the v2 patch.
When running COPY FROM against a partitioned table with RLS enabled, ExecSetupPartitionTupleRouting gets invoked twice, 
which creates two separate sets of PartitionTupleRouting structures.
One of these sets never gets cleaned up, and PostgreSQL’s ResourceOwner mechanism catches this and emits the following warnings:


  WARNING:  resource was not closed: relation "rls_part_1"
  WARNING:  resource was not closed: relation "rls_part_2"


Best regards,

--

Yilin Zhang

^ permalink  raw  reply  [nested|flat] 4+ messages in thread


end of thread, other threads:[~2026-06-30 01:20 UTC | newest]

Thread overview: 4+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2020-11-20 02:48 [PATCH 1/3] bootstrap: convert Typ to a List* Justin Pryzby <[email protected]>
2026-05-25 04:50 ` Re: COPY FROM with RLS solai v <[email protected]>
2026-06-29 10:13 ` Re:Re: COPY FROM with RLS Yilin Zhang <[email protected]>
2026-06-30 01:20 ` Re:Re: COPY FROM with RLS Yilin Zhang <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox