Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lHyZE-0008IT-QS for pgsql-hackers@arkaria.postgresql.org; Fri, 05 Mar 2021 00:43:45 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1lHyZD-00023S-G0 for pgsql-hackers@arkaria.postgresql.org; Fri, 05 Mar 2021 00:43:43 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lHyZD-00023L-0r for pgsql-hackers@lists.postgresql.org; Fri, 05 Mar 2021 00:43:43 +0000 Received: from mail-qv1-xf2f.google.com ([2607:f8b0:4864:20::f2f]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1lHyZ9-000184-NL for pgsql-hackers@postgresql.org; Fri, 05 Mar 2021 00:43:41 +0000 Received: by mail-qv1-xf2f.google.com with SMTP id s17so186254qvr.12 for ; Thu, 04 Mar 2021 16:43:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=telsasoft-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=/rBcYZv5W4ydgfNOVVyQelcc9GbHvTY83IPZz6jL6Yc=; b=Cu1vun55eShSEhnvLtYLYXP9p7W25aOMrp6rcIHg2jPA6hG8sIiqlaoyYq+cumfcSl 8F+YI6LkmcCt46FkM012giEqVhhNU7JSFtsPKIF7LDADrOpnEE7LVErzUq+eZiaBWsx+ FrDDWyzEEmyXs56jChxowwpQE9cJS5Cw5q84dX8AzRfs7z/CNpoy056S2lt+E32PfVFI A6/L69lIFWa8wsS74ZLXM2FXIaZOU21Guywbns+zZIDFVxrIaDtZyI1e/6Q4fy6elIPk IZadV/qqoyTDOExfWJ4P4dyarPN3mnqmkYP1lgcIF0YM4YNZaxdcV4EFifJ/jYsOhmn1 HjOA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=/rBcYZv5W4ydgfNOVVyQelcc9GbHvTY83IPZz6jL6Yc=; b=cb57iz5GWag5PU11N4B3HWQxUnCglstNi5rLvM/tR2PhUVxsuT6xyn+AfM2hBn6GcJ 9QLbhKH/uDeyK4AfVeyo97zxJHx3cbp+tB3E5aSBQXVJ5mJKG44qRGZI34LujiA7nxnl +uMSsWyzgXerf3r7djp9DfDuEphvbf7q21Gqbnfz6xSkAcG7bX32BI2uj2zC9hsYNgD9 yw4g2OddDf3GE+UMF8S15O9kvWhdyDfjfKctud+xt4fYtROKeviWNFNgD4yj65/H4lID P8+4xrybg4bgQZdLYNqIIbjRcnUwr76jn6UzYmy6xr/ym4zs+zsSgu7CZXZNAlskuuFi lQhw== X-Gm-Message-State: AOAM532GmRKe7V0z0IqyIaRNkBdtAcm/QC9nRWv3bmj12zvmbcvdL15I YqQqpWiWQ6zDhQpn4qwKTH6wOw== X-Google-Smtp-Source: ABdhPJyB6a7CgOUGSWGHus1yFZPW9Bp2zPqCMjZtp7J+tMD6FuxC67Lli8JpFhHaYVjUYRBDBuyQeg== X-Received: by 2002:a0c:b92f:: with SMTP id u47mr6663818qvf.8.1614905017396; Thu, 04 Mar 2021 16:43:37 -0800 (PST) Received: from pryzbyj.telsasoft (charmander.telsasoft.com. [50.244.222.1]) by smtp.gmail.com with ESMTPSA id m30sm885823qtd.30.2021.03.04.16.43.36 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 04 Mar 2021 16:43:36 -0800 (PST) Received: by pryzbyj.telsasoft (Postfix, from userid 1000) id 2BE2C8007F8; Thu, 4 Mar 2021 18:43:35 -0600 (CST) Date: Thu, 4 Mar 2021 18:43:35 -0600 From: Justin Pryzby To: Dean Rasheed Cc: Tomas Vondra , pgsql-hackers@postgresql.org Subject: Re: PoC/WIP: Extended statistics on expressions Message-ID: <20210305004334.GR29832@telsasoft.com> References: <6455e0ad-2a2e-bdb0-e1f8-fd4983d1c8aa@enterprisedb.com> <087086de-1384-8374-4efc-2e7915071d5c@enterprisedb.com> <4a2918bb-49b0-ccd5-3af7-f7795941a6ad@enterprisedb.com> <958870c8-65e0-31b1-4591-b0b10e807dd9@enterprisedb.com> <20210104154524.GE9712@telsasoft.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="yQbNiKLmgenwUfTN" Content-Disposition: inline In-Reply-To: <20210104154524.GE9712@telsasoft.com> User-Agent: Mutt/1.9.4 (2018-02-28) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --yQbNiKLmgenwUfTN Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Mon, Jan 04, 2021 at 09:45:24AM -0600, Justin Pryzby wrote: > On Mon, Jan 04, 2021 at 03:34:08PM +0000, Dean Rasheed wrote: > > * I'm not sure I understand the need for 0001. Wasn't there an earlier > > version of this patch that just did it by re-populating the type > > array, but which still had it as an array rather than turning it into > > a list? Making it a list falsifies some of the comments and > > function/variable name choices in that file. > > This part is from me. > > I can review the names if it's desired , but it'd be fine to fall back to the > earlier patch. I thought a pglist was cleaner, but it's not needed. This updates the preliminary patches to address the issues Dean raised. One advantage of using a pglist is that we can free it by calling list_free_deep(Typ), rather than looping to free each of its elements. But maybe for bootstrap.c it doesn't matter, and we can just write: | Typ = NULL; /* Leak the old Typ array */ -- Justin --yQbNiKLmgenwUfTN Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0001-bootstrap-convert-Typ-to-a-List.patchx" From 41ec12096cefc00484e7f2a0b3bfbc0f79cdd162 Mon Sep 17 00:00:00 2001 From: Justin Pryzby Date: Thu, 19 Nov 2020 20:48:48 -0600 Subject: [PATCH 1/2] bootstrap: convert Typ to a List* --- src/backend/bootstrap/bootstrap.c | 89 ++++++++++++++----------------- 1 file changed, 41 insertions(+), 48 deletions(-) diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 6f615e6622..1b940d9d27 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -58,7 +58,7 @@ static void BootstrapModeMain(void); static void bootstrap_signals(void); static void ShutdownAuxiliaryProcess(int code, Datum arg); static Form_pg_attribute AllocateAttribute(void); -static void populate_typ_array(void); +static void populate_typ(void); static Oid gettype(char *type); static void cleanup(void); @@ -159,7 +159,7 @@ struct typmap FormData_pg_type am_typ; }; -static struct typmap **Typ = NULL; +static List *Typ = NIL; /* List of struct typmap* */ static struct typmap *Ap = NULL; static Datum values[MAXATTR]; /* current row's attribute values */ @@ -595,10 +595,10 @@ boot_openrel(char *relname) /* * pg_type must be filled before any OPEN command is executed, hence we - * can now populate the Typ array if we haven't yet. + * can now populate Typ if we haven't yet. */ - if (Typ == NULL) - populate_typ_array(); + if (Typ == NIL) + populate_typ(); if (boot_reldesc != NULL) closerel(NULL); @@ -688,7 +688,7 @@ DefineAttr(char *name, char *type, int attnum, int nullness) typeoid = gettype(type); - if (Typ != NULL) + if (Typ != NIL) { attrtypes[attnum]->atttypid = Ap->am_oid; attrtypes[attnum]->attlen = Ap->am_typ.typlen; @@ -866,47 +866,36 @@ cleanup(void) } /* ---------------- - * populate_typ_array + * populate_typ * - * Load the Typ array by reading pg_type. + * Load Typ by reading pg_type. * ---------------- */ static void -populate_typ_array(void) +populate_typ(void) { Relation rel; TableScanDesc scan; HeapTuple tup; - int nalloc; - int i; - - Assert(Typ == NULL); + MemoryContext old; - nalloc = 512; - Typ = (struct typmap **) - MemoryContextAlloc(TopMemoryContext, nalloc * sizeof(struct typmap *)); + Assert(Typ == NIL); rel = table_open(TypeRelationId, NoLock); scan = table_beginscan_catalog(rel, 0, NULL); - i = 0; + old = MemoryContextSwitchTo(TopMemoryContext); while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL) { Form_pg_type typForm = (Form_pg_type) GETSTRUCT(tup); + struct typmap *newtyp; - /* make sure there will be room for a trailing NULL pointer */ - if (i >= nalloc - 1) - { - nalloc *= 2; - Typ = (struct typmap **) - repalloc(Typ, nalloc * sizeof(struct typmap *)); - } - Typ[i] = (struct typmap *) - MemoryContextAlloc(TopMemoryContext, sizeof(struct typmap)); - Typ[i]->am_oid = typForm->oid; - memcpy(&(Typ[i]->am_typ), typForm, sizeof(Typ[i]->am_typ)); - i++; + newtyp = (struct typmap *) palloc(sizeof(struct typmap)); + Typ = lappend(Typ, newtyp); + + newtyp->am_oid = typForm->oid; + memcpy(&newtyp->am_typ, typForm, sizeof(newtyp->am_typ)); } - Typ[i] = NULL; /* Fill trailing NULL pointer */ + MemoryContextSwitchTo(old); table_endscan(scan); table_close(rel, NoLock); } @@ -916,25 +905,26 @@ populate_typ_array(void) * * NB: this is really ugly; it will return an integer index into TypInfo[], * and not an OID at all, until the first reference to a type not known in - * TypInfo[]. At that point it will read and cache pg_type in the Typ array, + * TypInfo[]. At that point it will read and cache pg_type in Typ, * and subsequently return a real OID (and set the global pointer Ap to * point at the found row in Typ). So caller must check whether Typ is - * still NULL to determine what the return value is! + * still NIL to determine what the return value is! * ---------------- */ static Oid gettype(char *type) { - if (Typ != NULL) + if (Typ != NIL) { - struct typmap **app; + ListCell *lc; - for (app = Typ; *app != NULL; app++) + foreach (lc, Typ) { - if (strncmp(NameStr((*app)->am_typ.typname), type, NAMEDATALEN) == 0) + struct typmap *app = lfirst(lc); + if (strncmp(NameStr(app->am_typ.typname), type, NAMEDATALEN) == 0) { - Ap = *app; - return (*app)->am_oid; + Ap = app; + return app->am_oid; } } } @@ -949,7 +939,7 @@ gettype(char *type) } /* Not in TypInfo, so we'd better be able to read pg_type now */ elog(DEBUG4, "external type: %s", type); - populate_typ_array(); + populate_typ(); return gettype(type); } elog(ERROR, "unrecognized type \"%s\"", type); @@ -977,17 +967,20 @@ boot_get_type_io_data(Oid typid, Oid *typinput, Oid *typoutput) { - if (Typ != NULL) + if (Typ != NIL) { /* We have the boot-time contents of pg_type, so use it */ - struct typmap **app; - struct typmap *ap; - - app = Typ; - while (*app && (*app)->am_oid != typid) - ++app; - ap = *app; - if (ap == NULL) + struct typmap *ap = NULL; + ListCell *lc; + + foreach (lc, Typ) + { + ap = lfirst(lc); + if (ap->am_oid == typid) + break; + } + + if (!ap || ap->am_oid != typid) elog(ERROR, "type OID %u not found in Typ list", typid); *typlen = ap->am_typ.typlen; -- 2.17.0 --yQbNiKLmgenwUfTN Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0002-Allow-composite-types-in-bootstrap.patchx" From 25c8324e16ffdaa3ea4eedee95bb76257964a540 Mon Sep 17 00:00:00 2001 From: Justin Pryzby Date: Tue, 17 Nov 2020 09:28:33 -0600 Subject: [PATCH 2/2] Allow composite types in bootstrap --- src/backend/bootstrap/bootstrap.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 1b940d9d27..a0fcbb3d83 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -916,6 +916,7 @@ gettype(char *type) { if (Typ != NIL) { + static bool did_reread PG_USED_FOR_ASSERTS_ONLY = false; /* Already reread pg_types? */ ListCell *lc; foreach (lc, Typ) @@ -927,6 +928,33 @@ gettype(char *type) return app->am_oid; } } + + /* + * The type wasn't known; check again to handle composite + * types, added since first populating Typ. + */ + + /* + * Once all the types are populated and we handled composite + * types, shouldn't need to do that again. + */ + Assert(!did_reread); + did_reread = true; + + list_free_deep(Typ); + Typ = NIL; + populate_typ(); + + /* Need to avoid infinite recursion... */ + foreach (lc, Typ) + { + struct typmap *app = lfirst(lc); + if (strncmp(NameStr(app->am_typ.typname), type, NAMEDATALEN) == 0) + { + Ap = app; + return app->am_oid; + } + } } else { -- 2.17.0 --yQbNiKLmgenwUfTN--