pg.ddx.io  pgsql-general@postgresql.org mailing list archive  
help / color / mirror / Atom feed
From: Justin Pryzby <pryzby@telsasoft.com>
To: pgsql-general@postgresql.org
Subject: INSERT ON CONFLICT of "wide" table: target lists can have at most 1664 entries
Date: Sun, 4 Dec 2016 10:32:37 -0600
Message-ID: <20161204163237.GA8030@telsasoft.com> (raw)
List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-general>

Our application INSERTs data from external sources, and infrequently UPDATEs
the previously-inserted data (currently, it first SELECTs to determine whether
to UPDATE).

I'm implementing unique indices to allow "upsert" (and pg_repack and..), but
running into a problem when the table has >830 columns (we have some tables
which are at the 1600 column limit, and have previously worked around that
limit using arrays or multiple tables).

I tried to work around the upsert problem by using pygresql inline=True
(instead of default PREPAREd statements) but both have the same issue.

I created a test script which demonstrates the problem (attached).

It seems to me that there's currently no way to "upsert" such a wide table?

I see:
./src/include/access/htup_details.h:#define MaxTupleAttributeNumber 1664        /* 8 * 208 */

./src/backend/parser/parse_node.c-      /*
./src/backend/parser/parse_node.c-       * Check that we did not produce too many resnos; at the very least we
./src/backend/parser/parse_node.c-       * cannot allow more than 2^16, since that would exceed the range of a
./src/backend/parser/parse_node.c:       * AttrNumber. It seems safest to use MaxTupleAttributeNumber.
./src/backend/parser/parse_node.c-       */
./src/backend/parser/parse_node.c:      if (pstate->p_next_resno - 1 > MaxTupleAttributeNumber)
./src/backend/parser/parse_node.c-              ereport(ERROR,
./src/backend/parser/parse_node.c-                              (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
./src/backend/parser/parse_node.c:                               errmsg("target lists can have at most %d entries",
./src/backend/parser/parse_node.c:                                              MaxTupleAttributeNumber)));

Thanks in advance for any suggestions.

Justin
#! /bin/sh
set -e

n=831
t=wide_upsert

psql -c "DROP TABLE IF EXISTS $t"

cols='id int'
vals='0'
sets='id=0'
for a in `seq -w 0 $n`
do
	c="c$a int"
	cols="$cols, c$a int"

	vals="$vals, \$1"
	sets="$sets, c$a=\$1"
done

echo $cols
psql -c "CREATE TABLE $t ($cols, PRIMARY KEY (id))"

set -x
psql -c "PREPARE x AS INSERT INTO $t VALUES ($vals) ON CONFLICT (id) DO UPDATE SET $sets; EXECUTE x(0)"

-- 
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general

Attachments:

wide_upsert.txt (text/plain, 395B) download #! /bin/sh set -e n=831 t=wide_upsert psql -c "DROP TABLE IF EXISTS $t" cols='id int' vals='0' sets='id=0' for a in `seq -w 0 $n` do c="c$a int" cols="$cols, c$a int" vals="$vals, \$1" sets="$sets, c$a=\$1" done echo $cols psql -c "CREATE TABLE $t ($cols, PRIMARY KEY (id))" set -x psql -c "PREPARE x AS INSERT INTO $t VALUES ($vals) ON CONFLICT (id) DO UPDATE SET $sets; EXECUTE x(0)"

view thread (4+ messages)  latest in thread

Message-ID: <20161204163237.GA8030@telsasoft.com>
Permalink:  ../20161204163237.GA8030@telsasoft.com/
Also on:    postgresql.org/message-id/20161204163237.GA8030@telsasoft.com

 · 

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pgsql-general@postgresql.org
  Cc: pryzby@telsasoft.com
  Subject: Re: INSERT ON CONFLICT of "wide" table: target lists can have at most 1664 entries
  In-Reply-To: <20161204163237.GA8030@telsasoft.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

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