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 1tTK7I-004l3P-R3 for pgsql-general@arkaria.postgresql.org; Thu, 02 Jan 2025 12:15:57 +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 1tTK7H-00EukE-Tl for pgsql-general@arkaria.postgresql.org; Thu, 02 Jan 2025 12:15:55 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1tTK7H-00EujA-IP for pgsql-general@lists.postgresql.org; Thu, 02 Jan 2025 12:15:55 +0000 Received: from gaoxing.magnetkern.de ([167.235.225.147]) by magus.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1tTK7A-002p3c-QF for pgsql-general@lists.postgresql.org; Thu, 02 Jan 2025 12:15:54 +0000 Received: from titanium.fritz.box (p200300c26f20ef00264bfefffe54b09c.dip0.t-ipconnect.de [IPv6:2003:c2:6f20:ef00:264b:feff:fe54:b09c]) by gaoxing.magnetkern.de (Postfix) with ESMTPSA id 9B30A73314; Thu, 02 Jan 2025 13:17:01 +0100 (CET) Date: Thu, 2 Jan 2025 13:15:47 +0100 From: Jan Behrens To: Pavel Stehule Cc: "David G. Johnston" , "pgsql-general@lists.postgresql.org" Subject: Re: search_path for PL/pgSQL functions partially cached? Message-Id: <20250102131547.f47d7eeb27c7a8256a8cd189@magnetkern.de> In-Reply-To: References: <20241227205025.1d059f72c7c08d23c9648c26@magnetkern.de> <20241228004009.267f21b78394c934f27f9974@magnetkern.de> <20250101185504.3d50c571c3448512e94288e8@magnetkern.de> <20250102113727.1574b14fd677d164c32160bc@magnetkern.de> X-Mailer: Sylpheed 3.7.0 (GTK+ 2.24.33; amd64-portbld-freebsd14.1) 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: Archived-At: Precedence: bulk On Thu, 2 Jan 2025 12:40:59 +0100 Pavel Stehule wrote: > How can you identify unwanted usage of non qualified identifiers from > wanted usage of non qualified identifiers? It is a common pattern for > sharding. Using not qualified identifiers of operators, functions is common > when you are using orafce extensions, etc. I don't fully understand the use-case. Could you elaborate? As I understand, even if identifiers are not fully-qualified, it is forbidden to use the search_path to refer to different database entities at run-time (as David pointed out). So I don't understand how a dynamic "search_path" could be used in any scenario within functions except when EXECUTE is involved. > > Using qualified identifiers everywhere strongly reduces readability. There > are no aliases to the schema, so aliases cannot help. Yes, I agree on that. Using "SET search_path" in the function's definition fixes that problem, but it's easy to miss how important this is from reading the documentation: The manual regarding "CREATE FUNCTION" refers to "search_path" only within the "Writing SECURITY DEFINER Functions Safely" section. It's easy to skip that part unless you use that feature. Moreover, that section alone doesn't explain the weird behavior of four different outcomes of a function with only two schemas involved which I brought up in the beginning of this thread. The part on "SET configuration_parameter" part in the "CREATE FUNCTION" documentation doesn't mention the search_path or schemas. And I don't think you can expect every programmer will read the "Plan Caching" subsection in the "PL/pgSQL under the Hood" section. But even then, the information is just provided indirectly. Searching for "schema" in "CREATE FUNCTION"'s documentation doesn't give any hint either. I think (assuming that the behavior isn't fixed) that some slighly more prominent warning would be reasonable. > > you can identify the functions where search_path is not explicitly assigned > > select oid::regprocedure > from pg_proc > where pronamespace::regnamespace not in ('pg_catalog', > 'information_schema') > and not exists(select 1 from unnest(proconfig) g(v) where v ~ > '^search_path'); > > > Regards > > Pavel Kind regards, Jan