Tom Lane wrote:
Joe Conway <[EMAIL PROTECTED]> writes:Actually, adding a "pfree(oneres);" to the end of that for loop plugs the memory leak and allows me to see the error message:
On second look, you can't pfree oneres at the bottom of gen_cross_product() because it's part of the returned data structure --- note the assignment *iter++ = oneres;
Yup, I see that now ;-)
I think the bug here is that gen_cross_product should be ignoring argument positions that have nsupers == 0; those should always be assigned the same type as the input, since the regular type resolution algorithm is responsible for dealing with 'em.
It might work to get rid of the "wild card" case (line 1115), which'd reduce the number of outputs to product(nsupers+1). I doubt we really want any wild cards in there anymore.
The above didn't work, but if I understand correctly what that function is intended to do, it seemed very broken. Basically this code:
nanswers = 1; for (i = 0; i < nargs; i++) { nanswers *= (arginh[i].nsupers + 2); cur[i] = 0; }
for 24 arguments means 2^24 answers, even when there are no superclasses.
In that case (no arguments with superclasses), we ought to get:
nanswers = 1 iter should be sized at 1(all arginh[i].self) + 1(all wildcard) + 1 (null terminator)
The attached patch fixes this issue, but I'm still not entirely sure I understand what the function was supposed to be doing, so please check over my logic. Here's how I tested (after `make installcheck`)
CREATE OR REPLACE FUNCTION inhtest (d, integer, stud_emp, integer) returns text as 'select ''OK''::text' language 'sql';
CREATE OR REPLACE FUNCTION get_d() returns d as 'select * from d limit 1' language 'sql';
CREATE OR REPLACE FUNCTION get_stud_emp() returns stud_emp as 'select * from stud_emp limit 1' language 'sql';
select inhtest(get_d(), 'a'::text, get_stud_emp(), 1);
During testing, I had an elog(NOTICE,...) in there, and got the following (reformatted) results:
arg num = 3 2 1 0 iter[j] NOTICE: j = 0 23 1764386 25 1881220 NOTICE: j = 1 23 1764391 25 1881220 NOTICE: j = 2 23 1764381 25 1881220 NOTICE: j = 3 23 1764386 25 1881225 NOTICE: j = 4 23 1764391 25 1881225 NOTICE: j = 5 23 1764381 25 1881225 NOTICE: j = 6 23 1764386 25 1881215 NOTICE: j = 7 23 1764391 25 1881215 NOTICE: j = 8 23 1764381 25 1881215
Seems correct to me.
Passes all regression tests.
Joe
Index: src/backend/parser/parse_func.c =================================================================== RCS file: /opt/src/cvs/pgsql-server/src/backend/parser/parse_func.c,v retrieving revision 1.149 diff -c -r1.149 parse_func.c *** src/backend/parser/parse_func.c 6 Jun 2003 15:04:02 -0000 1.149 --- src/backend/parser/parse_func.c 24 Jun 2003 23:33:50 -0000 *************** *** 1075,1124 **** **iter; Oid *oneres; int i, ! j; ! int cur[FUNC_MAX_ARGS]; nanswers = 1; for (i = 0; i < nargs; i++) { ! nanswers *= (arginh[i].nsupers + 2); ! cur[i] = 0; } ! iter = result = (Oid **) palloc(sizeof(Oid *) * nanswers); /* compute the cross product from right to left */ ! for (;;) { oneres = (Oid *) palloc0(FUNC_MAX_ARGS * sizeof(Oid)); ! for (i = nargs - 1; i >= 0 && cur[i] > arginh[i].nsupers; i--) ! continue; ! ! /* if we're done, terminate with NULL pointer */ ! if (i < 0) ! { ! *iter = NULL; ! return result; ! } ! ! /* no, increment this column and zero the ones after it */ ! cur[i] = cur[i] + 1; ! for (j = nargs - 1; j > i; j--) ! cur[j] = 0; ! ! for (i = 0; i < nargs; i++) { ! if (cur[i] == 0) ! oneres[i] = arginh[i].self; ! else if (cur[i] > arginh[i].nsupers) ! oneres[i] = 0; /* wild card */ else ! oneres[i] = arginh[i].supervec[cur[i] - 1]; } ! ! *iter++ = oneres; } } --- 1076,1117 ---- **iter; Oid *oneres; int i, ! j, ! cum; nanswers = 1; for (i = 0; i < nargs; i++) { ! if (arginh[i].nsupers) ! nanswers *= arginh[i].nsupers; } ! /* need room for wildcard vector and null terminator */ ! iter = result = (Oid **) palloc(sizeof(Oid *) * (nanswers + 2)); /* compute the cross product from right to left */ ! for (j = 0; j < nanswers; j++) { oneres = (Oid *) palloc0(FUNC_MAX_ARGS * sizeof(Oid)); + cum = 1; ! for (i = nargs - 1; i >= 0; i--) { ! if (arginh[i].nsupers) ! { ! oneres[i] = arginh[i].supervec[(j / cum) % arginh[i].nsupers]; ! cum *= arginh[i].nsupers; ! } else ! oneres[i] = arginh[i].self; } ! iter[j] = oneres; } + oneres = (Oid *) palloc0(FUNC_MAX_ARGS * sizeof(Oid)); + iter[nanswers] = oneres; + iter[nanswers + 1] = NULL; + + return result; }
---------------------------(end of broadcast)--------------------------- TIP 9: the planner will ignore your desire to choose an index scan if your joining column's datatypes do not match