Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1uwa8s-004pea-0w for pgsql-hackers@arkaria.postgresql.org; Thu, 11 Sep 2025 05:46:46 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1uwa8q-005cCL-7y for pgsql-hackers@arkaria.postgresql.org; Thu, 11 Sep 2025 05:46:44 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1uwa8p-005cCB-5j for pgsql-hackers@lists.postgresql.org; Thu, 11 Sep 2025 05:46:44 +0000 Received: from mail.clear-code.com ([2401:2500:102:3037:153:126:203:179]) by makus.postgresql.org with smtp (Exim 4.96) (envelope-from ) id 1uwa8l-001n2N-2E for pgsql-hackers@postgresql.org; Thu, 11 Sep 2025 05:46:41 +0000 Received: from localhost (unknown [IPv6:2404:7a80:9f01:f500:1788:74de:dc85:ea72]) by mail.clear-code.com (Postfix) with ESMTPSA id D1DC4586FA2; Thu, 11 Sep 2025 14:46:29 +0900 (JST) DKIM-Filter: OpenDKIM Filter v2.11.0 mail.clear-code.com D1DC4586FA2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=clear-code.com; s=default; t=1757569590; bh=yfjTHkXhF2rG2aF7OOmbEJrTwJ4hG8Vs63Cms7L5viY=; h=Date:To:Cc:Subject:From:In-Reply-To:References:From; b=oUCf+AgqIgzp4LvLxmnrYdtkd+XMprHIAqYyy4K4ZFtJF+y7ICss96elKS69fOb8d OcPB1RJinSRr3Ggrv1LXd22tOrsPJ9eTw4laYv0Tdp+lvxf2BYTxlzqGlkSbTmXSDk v2DWUTrHo95u5705Mtfx/l7RYNSnuBkBTEd/7C30= Date: Thu, 11 Sep 2025 14:46:27 +0900 (JST) Message-Id: <20250911.144627.1367548062212866518.kou@clear-code.com> To: sawada.mshk@gmail.com Cc: michael@paquier.xyz, david.g.johnston@gmail.com, tgl@sss.pgh.pa.us, zhjwpku@gmail.com, pgsql-hackers@postgresql.org Subject: Re: Make COPY format extendable: Extract COPY TO format implementations From: Sutou Kouhei In-Reply-To: References: <20250910.114058.944005985178219874.kou@clear-code.com> X-Mailer: Mew version 6.8 on Emacs 30.1 Mime-Version: 1.0 Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-Spamd-Result: default: False [2.90 / 999.00]; SUSPICIOUS_RECIPS(1.50)[]; MID_CONTAINS_FROM(1.00)[]; MV_CASE(0.50)[]; MIME_GOOD(-0.10)[text/plain]; TAGGED_RCPT(0.00)[]; ARC_NA(0.00)[]; ASN(0.00)[asn:2518, ipnet:2404:7a80::/29, country:JP]; RCVD_COUNT_ZERO(0.00)[0]; MIME_TRACE(0.00)[0:+]; FREEMAIL_TO(0.00)[gmail.com]; FREEMAIL_ENVRCPT(0.00)[gmail.com]; TO_MATCH_ENVRCPT_ALL(0.00)[]; FROM_HAS_DN(0.00)[]; FREEMAIL_CC(0.00)[paquier.xyz,gmail.com,sss.pgh.pa.us,postgresql.org]; FROM_EQ_ENVFROM(0.00)[]; TO_DN_NONE(0.00)[]; RCPT_COUNT_FIVE(0.00)[6] X-Rspamd-Server: mail.clear-code.com X-Rspamd-Action: no action X-Rspamd-Queue-Id: D1DC4586FA2 List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Hi, In "Re: Make COPY format extendable: Extract COPY TO format implementations" on Wed, 10 Sep 2025 00:36:38 -0700, Masahiko Sawada wrote: > How about another idea like we move format-specific data to another > struct that embeds CopyFrom/ToStateData at the first field and have > CopyFrom/ToStart callback return memory with the size of that > struct?It resolves the concerns about adding an extra indirection > layer and extensions doesn't need to allocate memory for unnecessary > fields (used only for built-in formats). While extensions can access > the internal fields I think we can live with that given that there are > some similar precedents such as table AM's scan descriptions. The another idea looks like the following, right? struct CopyToStateBuiltInData { struct CopyToStateData parent; /* Members for built-in formats */ ...; } typedef CopyToState *(*CopyToStart) (void); CopyToState BeginCopyTo(..., CopyToStart copy_to_start) { ...; /* Allocate workspace and zero all fields */ cstate = copy_to_start(); ...; } This idea will almost work. But we can't know which CopyToStart should be used before we parse "FORMAT" option of COPY. If we can iterate options twice in BeginCopy{To,From}(), we can know it. For example: BeginCopyTo(...) { ...; CopyToStart copy_to_start = NULL; foreach(option, options) { DefElem *defel = lfirst_node(DefElem, option); if (strcmp(defel->defname, "format") == 0) { char *fmt = defGetString(defel); if (strcmp(fmt, "text") == 0 || strcmp(fmt, "csv") == 0 || strcmp(fmt, "binary") == 0) { /* Use the builtin cstate */ } else { copy_to_start = /* Detect CopyToStart for custom format */; } } } if (copy_to_start) cstate = copy_to_start(); else cstate = (CopyToStateData *) palloc0(sizeof(CopyToStateBuiltInData)); ...; } (It may be better that we add Copy{To,From}Routine::Copy{To,From}Allocate() instead of CopyToStart callback.) I think that this is acceptable because this must be a light process. This must not have negative performance impact. Thanks, -- kou