Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hiyA0-0001sK-RW for pgsql-sql@arkaria.postgresql.org; Thu, 04 Jul 2019 09:36:13 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1hiy9y-0002Vs-3Y for pgsql-sql@arkaria.postgresql.org; Thu, 04 Jul 2019 09:36:10 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hiy9x-0002Vl-NE for pgsql-sql@lists.postgresql.org; Thu, 04 Jul 2019 09:36:09 +0000 Received: from mail-lj1-x241.google.com ([2a00:1450:4864:20::241]) by magus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hiy9r-0003G9-2M for pgsql-sql@postgresql.org; Thu, 04 Jul 2019 09:36:08 +0000 Received: by mail-lj1-x241.google.com with SMTP id p17so5523170ljg.1 for ; Thu, 04 Jul 2019 02:36:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cifrasoft-com.20150623.gappssmtp.com; s=20150623; h=date:from:organization:message-id:to:subject:mime-version :content-transfer-encoding; bh=63pnP7Df4xgGJZpbeD+2ZdZKIOSKJKr8qFfGwmnLhKg=; b=eMFxIQo1DMeXFa5/BfQlP87mWlddUqLdQG3l8I0yHqMFACnmS8y2kgLvb3nmvL9Cim efHOx4TD4Q73IPv+516FYhMGLoI4YczcLcWb8DPHNwjYQR9ZiGQQIO0SD1ix5MSl2YE8 4FDRxOfzMKGKwOOA25c/3PDVndDSr2ORb1YQRO0KqOGfUW5yBD6sR6sFubndk5Z1lmON QMBbtV97mHpHOggsV47k609C+HK5y8F+dNzM+iMuDzCJeBn7cYPhfN6fWdVHSQ1aJPws MpKXZ/E4ZQ7cQ02LUOrvuwrRNPWsHoqjFSPdH+xd/P94rP/BHO4v9e8bvBitsZKSDLxl pV6w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:organization:message-id:to:subject :mime-version:content-transfer-encoding; bh=63pnP7Df4xgGJZpbeD+2ZdZKIOSKJKr8qFfGwmnLhKg=; b=mgfYJQl3WRjD7EhBYJQT/JzrR6H8JPOBIDjcdEtPlgeW19gGCAsC/HL51zL0ooMk0f IcgLggQcvHmfBKCPO4D04xLuIyJ1H4uNF8/jGPbIX2EZhHKtXyqEiFaMAnNzcbHWiVpj 9xVE6LMTpwrFLj6Bs7j27ODO3L5MmLAUZWmzhOaU8zqFb+UvFhbjEc1c1Kz/RV7CYKQR aTk0DzdOgD8uVRzrQqst0gkUMnmCf/XUhnVg0/w8Ad2Y869gDhzWsKfL+GE+goAs0jZY upydigFoNgiGlF4B3z6C+3+GihYjjvTbUOG4AwM/1LpAqB4MYlGP/H9v4OupraNVsLt0 zR5g== X-Gm-Message-State: APjAAAWriDohL5tTC81vPYem+6mLwha89zvGz0rS+6r5TbeIQMBbRVcd NLY8MmI0iUxHkbTQjaXkKq5siz2SB3lXrw== X-Google-Smtp-Source: APXvYqwL2ZhWFSMJNJX8USr7xfU/R7q5499u7aEO9o7vBq4D+Dw8ltKvas+lZDQUDP9FSjToCrxvqg== X-Received: by 2002:a2e:96c3:: with SMTP id d3mr24023590ljj.68.1562232960237; Thu, 04 Jul 2019 02:36:00 -0700 (PDT) Received: from [192.168.67.102] ([84.201.247.191]) by smtp.gmail.com with ESMTPSA id p76sm1006055ljb.49.2019.07.04.02.35.59 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 04 Jul 2019 02:35:59 -0700 (PDT) Date: Thu, 4 Jul 2019 13:35:58 +0400 From: andrey.sychev@cifrasoft.com Organization: =?windows-1251?B?zs7OICLW6PTw4PHu9PIi?= X-Priority: 3 (Normal) Message-ID: <1208914147.20190704133558@cifrasoft.com> To: pgsql-sql@postgresql.org Subject: Error: rows returned by function are not all of the same row type MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk Hi, everyone, I have written C-language function that returns multiple composite rows. Generally function works as expected, but sometimes problem takes place. At rough guess the problem occurs when number of returning rows relatively large (more than 100K - 1M). I have added some checkpoints. P5 and P6 are present in snippet. The function always reaches checkpoint P5, but before P6 it returns error: "rows returned by function are not all of the same row type" Supposedly, at some iteration on SRF_RETURN_NEXT Any ideas? Below is a snippet of code: #include "postgres.h" #include "funcapi.h" #include "executor/spi.h" Datum my_func(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(show_eudc); Datum my_eudc(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; int call_cntr; int max_calls; TupleDesc tupleDesc; /* Build a tuple descriptor for our result type */ if(get_call_result_type(fcinfo, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Function returning record called in context that cannot accept type record"))); } if(SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); My_SPI_call_context ctx; memset(&ctx, 0, sizeof(My_SPI_call_context)); int ret; /* Connect to SPI manager */ if((ret = SPI_connect()) < 0) { /* internal error */ elog(ERROR, "spi_match: SPI_connect returned %d", ret); SPI_finish(); PG_RETURN_VOID(); } /* some setup code */ const char* stSQLDef_0[1] = { "CREATE TEMPORARY TABLE results (v1 BIGINT NOT NULL, v2 INTEGER NOT NULL)", }; for(int k=0; k<1; k++) { ret = SPI_exec(stSQLDef_0[k], 0); if(ret != SPI_OK_UTILITY) { elog(ERROR, "SPI_exec (0)-(%d) returned %d", k, ret); my_spi_free_context(&ctx); PG_RETURN_VOID(); } } /* many code */ const char* stSQLResultsInsert = "INSERT INTO results (v1, v2) VALUES (%ld, %d)"; for(int k=0; kmax_calls = 0; funcctx->user_fctx = NULL; if(proc <= 0) ereport(NOTICE, (errmsg("SPI_execute (10) returned %d", ret))); } else if(proc) { spi_tuptable = SPI_tuptable; funcctx->max_calls = proc; funcctx->user_fctx = spi_tuptable; } my_spi_free_context(&ctx); tupleDesc = BlessTupleDesc(tupleDesc); funcctx->tuple_desc = tupleDesc; MemoryContextSwitchTo(oldcontext); } funcctx = SRF_PERCALL_SETUP(); call_cntr = funcctx->call_cntr; max_calls = funcctx->max_calls; if(call_cntr < max_calls) { SPITupleTable* table = (SPITupleTable*)funcctx->user_fctx; Datum results; /* Results tuple */ Datum column[2]; bool isColumnNull[2]; HeapTuple tuple; int m; if(table) { for(m=0; m<2; m++) { column[m] = SPI_getbinval(table->vals[call_cntr], table->tupdesc, m+1, &isColumnNull[m]); } tuple = heap_form_tuple(funcctx->tuple_desc, column, isColumnNull); results = HeapTupleGetDatum(tuple); SRF_RETURN_NEXT(funcctx, results); } } else { int ret; SPITupleTable* table = (SPITupleTable*)funcctx->user_fctx; if(table) { SPI_freetuptable(table); } ereport(NOTICE, (errmsg("P6: [%s]-(%d)", (const char*)__FUNCTION__, max_calls))); ret = SPI_exec("DROP TABLE results", 0); if(ret != SPI_OK_UTILITY) { elog(ERROR, "spi_match: SPI_exec (20) returned %d", ret); } SPI_finish(); SRF_RETURN_DONE(funcctx); } PG_RETURN_VOID(); } -- Best regards, Andrey Sychev andrey.sychev@cifrasoft.com