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 1tc63p-00FUlo-4c for pgsql-hackers@arkaria.postgresql.org; Sun, 26 Jan 2025 17:04:38 +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 1tc63o-007khl-6O for pgsql-hackers@arkaria.postgresql.org; Sun, 26 Jan 2025 17:04:36 +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 1tc63n-007khd-OT for pgsql-hackers@lists.postgresql.org; Sun, 26 Jan 2025 17:04:35 +0000 Received: from forwardcorp1d.mail.yandex.net ([178.154.239.200]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1tc63j-001coS-2c for pgsql-hackers@lists.postgresql.org; Sun, 26 Jan 2025 17:04:34 +0000 Received: from mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net [IPv6:2a02:6b8:c0c:b18c:0:640:3ae6:0]) by forwardcorp1d.mail.yandex.net (Yandex) with ESMTPS id 188C660907; Sun, 26 Jan 2025 20:04:27 +0300 (MSK) Received: from smtpclient.apple (unknown [2a02:6b8:b081:8909::1:b]) by mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id P4fu0h1Ik4Y0-Z1owSuQv; Sun, 26 Jan 2025 20:04:26 +0300 X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1737911066; bh=M078DHh6oSHqq2WJLAQxs5fn2e46S6aBNCutwmQ+xfQ=; h=Message-Id:To:Date:References:Cc:In-Reply-To:From:Subject; b=teWTcT6syuGcPk+oMT/BPMEHZ+d0lgi0sJrKhJLzKG9d7Mxda2ZUvS2xknvJZpCAw EJ1I3znYU+87KVINqu3VK919+Z9onqOxTevfmzsQaRkdXxsCmhBneosBNQ/Lygm4d6 HZUa9xVAvsiHntYlxVD1H5D55g4Shu9OpopXM7bk= Authentication-Results: mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3776.700.51.11.1\)) Subject: Re: Using Expanded Objects other than Arrays from plpgsql From: Andrey Borodin In-Reply-To: <931398.1737905825@sss.pgh.pa.us> Date: Sun, 26 Jan 2025 22:04:15 +0500 Cc: Michel Pelletier , Pavel Stehule , pgsql-hackers@lists.postgresql.org Content-Transfer-Encoding: quoted-printable Message-Id: <38A31221-C1C4-4846-9709-D66ACD76E87A@yandex-team.ru> References: <1342498.1729444411@sss.pgh.pa.us> <1445998.1729482404@sss.pgh.pa.us> <2062830.1729625620@sss.pgh.pa.us> <2265411.1729699470@sss.pgh.pa.us> <2354718.1729737539@sss.pgh.pa.us> <2581216.1729794746@sss.pgh.pa.us> <1948345.1730500073@sss.pgh.pa.us> <3797606.1732045516@sss.pgh.pa.us> <647219! ! .1736019347@sss.pgh.pa.us> <1417389.1736964543@sss.pgh.pa.us> <3363452.1737483125@sss.pgh.pa.us> <0AC229FA-A3F1-43FD-B0DC-A46A73FEAFF7@yandex-team.ru> <931398.1737905825@sss.pgh.pa.us> To: Tom Lane X-Mailer: Apple Mail (2.3776.700.51.11.1) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk > On 26 Jan 2025, at 20:37, Tom Lane wrote: >=20 >> And the coverage of newly invented mark_stmt() 42.37%. Some of = branches are easy noops, but some are not. >=20 > Yeah. I'm not too concerned about that because it's pretty much a > copy-and-paste of the adjacent code. Maybe we should think about > some way of refactoring pl_funcs.c to reduce duplication, but I > don't have any great ideas about how. OK, now I got it. The whole purpose of 2nd patch is to do if (expr->target_param >=3D 0) expr->target_is_local =3D = bms_is_member(expr->target_param, local_dnos); to local variables.=20 >=20 >> expr_is_assignment_source() is named like if it should return nool, = but it's void. >=20 > I've been less than satisfied with that name too. I intended it > as a statement of fact, "this expression has been found to be=20 > the source of an assignment". But it does seem confusing. > Maybe we should recast it as an action. What do you think of > "mark_expr_as_assignment_source"? Sounds better to me. I found no examples of similar functions nether in = pl_gram.y, nor in gram.y, so IMO mark_expr_as_assignment_source() is the = best candidate. >=20 >> I could not grasp from reading the code one generic question about = new optimization rule. What cost does checking for possible in-place = update incurs to code cannot have this optimization? Is it = O(numer_of_arguments) of for every assignment execution? >=20 > No, the extra effort is incurred at most once per assignment statement > per session. (Unless the plpgsql function's cache entry gets > invalidated, in which case we'd rebuild all of the function's data > structures and have to redo this work too.) OK, I think execution benefits justify this preparatory costs. > We set up the evaluation > function "paramfunc" as plpgsql_param_eval_var_check if we think we > might be able to apply this optimization, or plpgsql_param_eval_var_ro > if we don't think so but the variable is of varlena type. At runtime, > if the variable's current value is not actually expanded, then > plpgsql_param_eval_var_check falls through doing essentially the same > work as plpgsql_param_eval_var_ro, so there should be no added cost. > The first time we observe that the value *is* expanded, we incur the > cost to detect whether an optimization is really possible, and then > we change the "paramfunc" pointer to be the appropriate function > so as to apply the optimization or not without rechecking. So > generally speaking, if we're considering a variable of a type that > doesn't support expansion, there should be zero extra per-execution > cost. There is some extra cost at function compilation time to > determine which expressions are assignment sources (but we were doing > that already) and to discover whether those assignments are to > nonlocal variables (which is new work, but only needs to be done in > functions with exception blocks). Got it, many thanks for the explanation. But I've got some new questions: I'm lost in internals of ExprEvalStep. But void *paramarg and his friend = void *paramarg2 are cryptic. They always have same type and same = meaning, but have very generic names. I wonder if you plan similar optimizations for array_cat(), = array_remove() etc? + a :=3D a || a; -- not optimizable Why is it not optimizable? Because there is no support function, because = array_cat() has no support function, or something else? Besides this, the patch looks good to me. Best regards, Andrey Borodin.=