Hi I found some problem with PG_RETURN_TEXT_P. I have function for creating html list from table column (I use SPI). With small lists function works fine, but when items is more then 300 (returned text is great then 8K) For items < 200 is all ok. Increasing of page size helps.
Source code is in attachement. Function is registered create or replace function html_list (cstring, cstring, int, int) returns text as 'html_list.so', 'html_list' language 'C'; parameters is 1. SQL query 2. column's name 3. max items (0 - all) 4. page size SELECT html_list('select jmeno from jmena','jmeno',100,2000); -- ok SELECT length(html_list('select jmeno from jmena','jmeno',200,2000)); ok NOTICE: before alloc 4000 NOTICE: after alloc NOTICE: Alokovan 137108256 NOTICE: after memcpy NOTICE: befor pfree NOTICE: after pfree NOTICE: before alloc 6000 NOTICE: after alloc NOTICE: Alokovan 137114320 NOTICE: after memcpy NOTICE: befor pfree NOTICE: after pfree NOTICE: before alloc 8000 NOTICE: after alloc NOTICE: Alokovan 137124648 NOTICE: after memcpy NOTICE: befor pfree NOTICE: after pfree NOTICE: BEFORE finish NOTICE: AFTER FINISH length -------- 6674 (1 øádka) SELECT html_list('select jmeno from jmena','jmeno',0,2000); -- crash NOTICE: before alloc 4000 NOTICE: after alloc NOTICE: Alokovan 137067288 NOTICE: after memcpy NOTICE: befor pfree NOTICE: after pfree NOTICE: before alloc 6000 NOTICE: after alloc NOTICE: Alokovan 137073352 NOTICE: after memcpy NOTICE: befor pfree NOTICE: after pfree NOTICE: before alloc 8000 NOTICE: after alloc NOTICE: Alokovan 137083680 NOTICE: after memcpy NOTICE: befor pfree NOTICE: after pfree NOTICE: BEFORE finish NOTICE: AFTER FINISH LOG: server process (pid 6955) was terminated by signal 11 LOG: terminating any other active server processes WARNING: Message from PostgreSQL backend: The Postmaster has informed me that some other backend died abnormally and possibly corrupted shared memory. I have rolled back the current transaction and am going to terminate your database system connection and exit. Please reconnect to the database system and repeat your query. SELECT html_list('select jmeno from jmena','jmeno',0,8000); --ok Why? What is wrong in my code. Page size has importatnt only for speed, not for functionality (I think). I have RedHat 7.2, PostgreSQL 7.3b3 (in 7.3b1 is this problem too) Pavel Stehule
#include "executor/spi.h" #include "postgres.h" #include <string.h> text *sts_strcatex (char **str_pointer, char *str, text *txt, long *saved_chars, long *allocated_free, long page_size) { long l = strlen (str); if (l > page_size) elog (ERROR, "Retezec je vetsi nez velikost stranky"); if (*allocated_free < l) { text *txtn; long ma = ((*saved_chars + l) / page_size + 1) * page_size; elog (NOTICE, "before alloc %d", ma); txtn = (text *) palloc (ma); elog (NOTICE, "after alloc"); elog (NOTICE, "Alokovan %d", txtn); memcpy ((void *) VARDATA(txtn), (void *) VARDATA(txt), *saved_chars); elog (NOTICE, "after memcpy"); *allocated_free = ma - *saved_chars; *str_pointer = VARDATA(txtn) + *saved_chars; elog (NOTICE, "befor pfree"); pfree (txt); txt = txtn; elog (NOTICE, "after pfree"); } strcpy (*str_pointer, str); *str_pointer += l; *saved_chars += l; *allocated_free -= l; VARATT_SIZEP (txt) = *saved_chars + VARHDRSZ; return txt; } PG_FUNCTION_INFO_V1 (html_list); Datum html_list (PG_FUNCTION_ARGS) { long ret, sloupec, radek, saved_chars, allocated_free, page_size, max; char *str_pointer, *query, *column_name; text *txt; if (PG_ARGISNULL (0) | PG_ARGISNULL (1)) elog (ERROR, "Parametrs have'nt to be NULL"); if ((ret = SPI_connect()) < 0) elog (ERROR, "SPI_connect returned %d", ret); query = PG_GETARG_CSTRING (0); column_name = PG_GETARG_CSTRING (1); max = PG_GETARG_INT32 (2); page_size = PG_GETARG_INT32 (3); if ((ret = SPI_exec (query, max)) < 0) elog (ERROR, "SPI_exec returned %d", ret); sloupec = SPI_fnumber(SPI_tuptable->tupdesc, column_name); if (sloupec <= 0) elog (ERROR, "SPI_ERROR_NOATTRIBUTE"); saved_chars = 0; allocated_free = page_size; txt = (text*) palloc (VARHDRSZ + allocated_free); str_pointer = VARDATA(txt); txt = sts_strcatex (&str_pointer, "<ul>\n", txt, &saved_chars, &allocated_free, page_size); for (radek = 0; radek < SPI_processed; radek++) { txt = sts_strcatex (&str_pointer, "<li>", txt, &saved_chars, &allocated_free, page_size); txt = sts_strcatex (&str_pointer, SPI_getvalue (SPI_tuptable->vals[radek], SPI_tuptable->tupdesc, sloupec), txt, &saved_chars, &allocated_free, page_size); txt = sts_strcatex (&str_pointer, "</li>\n", txt, &saved_chars, &allocated_free, page_size); } txt = sts_strcatex (&str_pointer, "</ul>", txt, &saved_chars, &allocated_free, page_size); elog (NOTICE,"BEFORE finish"); SPI_finish (); elog (NOTICE, "AFTER FINISH"); PG_RETURN_TEXT_P(txt); }
---------------------------(end of broadcast)--------------------------- TIP 4: Don't 'kill -9' the postmaster