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 1qX4ZG-0053oX-QI for pgsql-hackers@arkaria.postgresql.org; Fri, 18 Aug 2023 18:51:31 +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 1qX4YF-00DDUj-Ci for pgsql-hackers@arkaria.postgresql.org; Fri, 18 Aug 2023 18:50:27 +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 1qX4YF-00DDUM-0F for pgsql-hackers@lists.postgresql.org; Fri, 18 Aug 2023 18:50:27 +0000 Received: from anastigmatix.net ([68.171.216.17]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1qX4Y7-000uKE-Je for pgsql-hackers@postgresql.org; Fri, 18 Aug 2023 18:50:26 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=anastigmatix.net; s=default; h=Content-Transfer-Encoding:Content-Type: Message-ID:References:In-Reply-To:Subject:Cc:To:From:Date:MIME-Version:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help: List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=s86S0lE8rI6N65iRsafrOq5eFIQScuiNxSc6Ao7zI4A=; b=lkZmCh3yPl5XeSgIxhWf9mSeGE SorhfM3qmJFbnXAEmPlkKuMBGhDzhhK3Q0d0iZkXkWXuRe9sRoRIFP8dXLItafGHXvLorvSflgq5h HATl++MNiJ+I+pkwvelqmD4qfn70gifXQheJhuYYtlvx2sZ08MGEyuqjxs4XCmf4GtnSrk3OLl+Aw D6kED7QNz3vnho7r2XVhjXPtwFH4dUiAI0aveYROsYZpfEkDoR+Vk3LT559kIvi6P3jEkd8Vra2h3 4SasB9v3Rskv4jupY4u216lAaO1q1XtkEyCObuTo7C9Xe8N2V+nLs9+i2U430YIJip1I+eu7fi00q aTwMIgTA==; Received: from [::1] (port=34136 helo=adam.ace-host.net) by adam.ace-host.net with esmtpa (Exim 4.96) (envelope-from ) id 1qX4Y3-000zXv-24; Fri, 18 Aug 2023 14:50:16 -0400 MIME-Version: 1.0 Date: Fri, 18 Aug 2023 14:50:15 -0400 From: Chapman Flack To: Andy Fan Cc: jian he , Pavel Stehule , Tom Lane , pgsql-hackers Subject: Re: Extract numeric filed in JSONB more effectively In-Reply-To: References: <3507485.1691090027@sss.pgh.pa.us> <900892914fdc3f477b101d699efb40e0@anastigmatix.net> <903341.1692022214@sss.pgh.pa.us> <4b97f1a1dd9b6e45443d24870d3be698@anastigmatix.net> User-Agent: Roundcube Webmail/1.6.0 Message-ID: <111272f2dc112c7becdd35ad89f6b935@anastigmatix.net> X-Sender: chap@anastigmatix.net Content-Type: text/plain; charset=US-ASCII; format=flowed Content-Transfer-Encoding: 7bit X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - adam.ace-host.net X-AntiAbuse: Original Domain - postgresql.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - anastigmatix.net X-Get-Message-Sender-Via: adam.ace-host.net: authenticated_id: chap@anastigmatix.net X-Authenticated-Sender: adam.ace-host.net: chap@anastigmatix.net X-Source: X-Source-Args: X-Source-Dir: X-From-Rewrite: unmodified, already matched List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On 2023-08-18 03:41, Andy Fan wrote: > I just have > a quick hack on this, and crash happens at the simplest case. If I build from this patch, this test: SELECT (test_json -> 0)::int4, test_json -> 0 FROM test_jsonb WHERE json_type = 'scalarint'; fails like this: Program received signal SIGSEGV, Segmentation fault. convert_saop_to_hashed_saop_walker (node=0x17, context=0x0) at /var/tmp/nohome/pgbuildh/../postgresql/src/backend/optimizer/util/clauses.c:2215 2215 if (IsA(node, ScalarArrayOpExpr)) (gdb) p node $1 = (Node *) 0x17 So the optimizer is looking at some node to see if it is a ScalarArrayOpExpr, but the node has some rather weird address. Or maybe it's not that weird. 0x17 is 23, and so is: select 'int4'::regtype::oid; oid ----- 23 See what happened? + int64 target_typ = fexpr->funcresulttype; ... + fexpr->args = list_insert_nth(fexpr->args, 0, (void *) target_typ); This is inserting the desired result type oid directly as the first thing in the list of fexpr's args. But at the time your support function is called, nothing is being evaluated yet. You are just manipulating a tree of expressions to be evaluated later, and you want fexpr's first arg to be an expression that will produce this type oid later, when it is evaluated. A constant would do nicely: + Const *target = makeConst( INTERNALOID, -1, InvalidOid, SIZEOF_DATUM, ObjectIdGetDatum(fexpr->funcresulttype), false, true); + fexpr->args = list_insert_nth(fexpr->args, 0, target); With that change, it doesn't segfault, but it does do this: ERROR: cast jsonb to type 0 is not allowed and that's because of this: + Oid targetOid = DatumGetObjectId(0); The DatumGetFoo(x) macros are for when you already have the Datum (it's x) and you know it's a Foo. So this is just setting targetOid to zero. When you want to get something from function argument 0 and you know that's a Foo, you use a PG_GETARG_FOO(argno) macro (which amounts to PG_GETARG_DATUM(argno) followed by DatumGetFoo. So, with + Oid targetOid = PG_GETARG_OID(0); SELECT (test_json -> 0)::int4, test_json -> 0 FROM test_jsonb WHERE json_type = 'scalarint'; int4 | ?column? ------+---------- 2 | 2 However, EXPLAIN is sad: ERROR: cannot display a value of type internal and that may be where this idea runs aground. Now, I was expecting something to complain about the result of jsonb_array_element_type, and that didn't happen. We rewrote a function that was supposed to be a cast to int4, and replaced it with a function returning internal, and evaluation happily just took that as the int4 that the next node expected. If something had complained about that, it might have been necessary to insert some new node above the internal-returning function to say the result was really int4. Notice there is a makeRelabelType() for that. (I had figured there probably was, but didn't know its exact name.) So it doesn't seem strictly necessary to do that, but it might make the EXPLAIN result look better (if EXPLAIN were made to work, of course). Now, my guess is EXPLAIN is complaining when it sees the Const of type internal, and doesn't know how to show that value. Perhaps makeRelabelType is the answer there, too: what if the Const has Oid type, so EXPLAIN can show it, and what's inserted as the function argument is a relabel node saying it's internal? Haven't tried that yet. Regards, -Chap