bug #1702: nested composite types in plpgsql

Started by Roman Neuhauserover 20 years ago3 messages
#1Roman Neuhauser
neuhauser@sigpipe.cz

Hello, I'm getting this error with the code below (on 8.0.3 like the
other guy in #1702. Is this a hard problem to fix?

Looking at src/pl/plpgsql/src/pl_exec.c for the first time, is it a problem
of make_tuple_from_row() not accounting for nested composite types?

test=# SELECT takes_ct2parts(1, ARRAY['ct2a'], ARRAY['ct1a'], ARRAY['ct1b']);
ERROR: row not compatible with its own tupdesc
CONTEXT: PL/pgSQL function "takes_ct2parts" line 18 at perform
test=# SELECT version();
version
----------------------------------------------------------------------
PostgreSQL 8.0.3 on i386-portbld-freebsd4.11, compiled by GCC 2.95.4
(1 row)

CREATE TYPE ct1 AS (
a text,
b text
);

CREATE TYPE ct2 AS (
a text,
b ct1
);

CREATE FUNCTION takes_ct2(ct2)
RETURNS BOOLEAN
RETURNS NULL ON NULL INPUT
VOLATILE
LANGUAGE plpgsql
AS '
BEGIN
RETURN TRUE;
END;
';

CREATE OR REPLACE FUNCTION takes_ct2parts(int4, text[], text[], text[])
RETURNS BOOLEAN
RETURNS NULL ON NULL INPUT
VOLATILE
LANGUAGE plpgsql
AS '
DECLARE
_sz ALIAS FOR $1;
_ct2a ALIAS FOR $2;
_ct1a ALIAS FOR $3;
_ct1b ALIAS FOR $4;
_ct1 ct1;
_ct2 ct2;
_cnt INTEGER DEFAULT 1;
BEGIN
WHILE _cnt <= _sz LOOP
_ct1.a := _ct1a[_sz];
_ct1.b := _ct1b[_sz];
_ct2.a := _ct2a[_sz];
_ct2.b := _ct1;
_cnt := _cnt + 1;
END LOOP;
PERFORM takes_ct2(_ct2);
RETURN TRUE;
END;
';

--
How many Vietnam vets does it take to screw in a light bulb?
You don't know, man. You don't KNOW.
Cause you weren't THERE. http://bash.org/?255991

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Roman Neuhauser (#1)
Re: bug #1702: nested composite types in plpgsql

Roman Neuhauser <neuhauser@sigpipe.cz> writes:

Looking at src/pl/plpgsql/src/pl_exec.c for the first time, is it a problem
of make_tuple_from_row() not accounting for nested composite types?

Looks that way. I've committed a fix to HEAD. I'm not sure how hard
it'd be to fix 8.0.

regards, tom lane

#3Roman Neuhauser
neuhauser@sigpipe.cz
In reply to: Tom Lane (#2)
1 attachment(s)
Re: bug #1702: nested composite types in plpgsql

# tgl@sss.pgh.pa.us / 2005-09-13 12:17:06 -0400:

Roman Neuhauser <neuhauser@sigpipe.cz> writes:

Looking at src/pl/plpgsql/src/pl_exec.c for the first time, is it a problem
of make_tuple_from_row() not accounting for nested composite types?

Looks that way. I've committed a fix to HEAD. I'm not sure how hard
it'd be to fix 8.0.

Thanks for the fast fix, it's really appreciated.

I tried to hammer[1]see attachment your patch[2]http://developer.postgresql.org/cvsweb.cgi/pgsql/src/pl/plpgsql/src/pl_exec.c.diff?r1=1.151;r2=1.152 onto the REL8_0_STABLE branch
(attached), but am getting

ERROR: out of memory
DETAIL: Failed on request of size 1073741823.
CONTEXT: PL/pgSQL function "breakme" while storing call arguments
into local variables

I'm sorry to be a nuisance, but is this interesting enough for
someone in the know that they'd backport the patch into 8.0?

[1]: see attachment
[2]: http://developer.postgresql.org/cvsweb.cgi/pgsql/src/pl/plpgsql/src/pl_exec.c.diff?r1=1.151;r2=1.152

--
How many Vietnam vets does it take to screw in a light bulb?
You don't know, man. You don't KNOW.
Cause you weren't THERE. http://bash.org/?255991

Attachments:

src:pl:plpgsql:src:pl_exec.c.REL8_0_STABLE,0.patchtext/plain; charset=us-asciiDownload
Index: src/pl/plpgsql/src/pl_exec.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v
retrieving revision 1.127.4.3
diff -u -r1.127.4.3 pl_exec.c
--- src/pl/plpgsql/src/pl_exec.c	20 Jun 2005 22:51:49 -0000	1.127.4.3
+++ src/pl/plpgsql/src/pl_exec.c	14 Sep 2005 13:04:13 -0000
@@ -3243,8 +3243,7 @@
  *
  * If expectedtypeid isn't InvalidOid, it is checked against the actual type.
  *
- * This obviously only handles scalar datums (not whole records or rows);
- * at present it doesn't need to handle PLpgSQL_expr datums, either.
+ * At present this doesn't handle PLpgSQL_expr or PLpgSQL_arrayelem datums.
  *
  * NOTE: caller must not modify the returned value, since it points right
  * at the stored value in the case of pass-by-reference datatypes.
@@ -3864,19 +3863,20 @@
 
 	for (i = 0; i < natts; i++)
 	{
-		PLpgSQL_var *var;
+		Oid			fieldtypeid;
 
 		if (tupdesc->attrs[i]->attisdropped)
-			continue;			/* leave the column as null */
+		{
+			nulls[i] = true;	/* leave the column as null */
+			continue;
+		}
 		if (row->varnos[i] < 0) /* should not happen */
 			elog(ERROR, "dropped rowtype entry for non-dropped column");
 
-		var = (PLpgSQL_var *) (estate->datums[row->varnos[i]]);
-		if (var->datatype->typoid != tupdesc->attrs[i]->atttypid)
+		exec_eval_datum(estate, estate->datums[row->varnos[i]],
+						InvalidOid, &fieldtypeid, &dvalues[i], &nulls[i]);
+		if (fieldtypeid != tupdesc->attrs[i]->atttypid)
 			return NULL;
-		dvalues[i] = var->value;
-		if (!var->isnull)
-			nulls[i] = ' ';
 	}
 
 	tuple = heap_formtuple(tupdesc, dvalues, nulls);