From 073eccf8f9f8376ef62400a1eb1f7e0225fb5615 Mon Sep 17 00:00:00 2001
From: "Chao Li (Evan)" <lic@highgo.com>
Date: Tue, 23 Sep 2025 15:45:01 +0800
Subject: [PATCH v1] [PoC] Show JSON field name as it is instead of ?column?

This patch is not ready for review yet.

Author: <lic@highgo.com>
---
 src/backend/parser/parse_target.c | 58 ++++++++++++++++++++++++++++++-
 1 file changed, 57 insertions(+), 1 deletion(-)

diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 905c975d83b..0187378980d 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -26,6 +26,7 @@
 #include "parser/parse_target.h"
 #include "parser/parse_type.h"
 #include "parser/parsetree.h"
+#include "utils/array.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
 #include "utils/rel.h"
@@ -1803,12 +1804,67 @@ FigureColnameInternal(Node *node, char **name)
 			*name = strVal(llast(((FuncCall *) node)->funcname));
 			return 2;
 		case T_A_Expr:
-			if (((A_Expr *) node)->kind == AEXPR_NULLIF)
+			A_Expr	*i = (A_Expr *) node;
+			if (i->kind == AEXPR_NULLIF)
 			{
 				/* make nullif() act like a regular function */
 				*name = "nullif";
 				return 2;
 			}
+			else if (i->kind == AEXPR_OP &&
+			         list_length(i->name) == 1)
+			{
+				/* For json/jsonb operators, use the last part of the name.
+				 * The last part should be a Const or A_ArrayExpr node in rexpr.
+				 */
+				const char	*opname = strVal(linitial(i->name));
+				if ((strncmp(opname, "->", 2) == 0 ||
+					 strncmp(opname, "->>", 3) == 0) &&
+					IsA(i->rexpr, A_Const))
+				{
+					A_Const *c = (A_Const *) i->rexpr;
+					if (IsA(&c->val, String))
+					{
+						*name = strVal(&c->val);
+						return 2;
+					}
+				}
+				else if ((strncmp(opname, "#>", 2) == 0 ||
+				          strncmp(opname, "#>>", 3) == 0) &&
+						 (IsA(i->rexpr, A_Const) ||
+						  IsA(i->rexpr, A_ArrayExpr)))
+				{
+					if (IsA(i->rexpr, A_Const))
+					{
+						A_Const *c = (A_Const *) i->rexpr;
+						if (IsA(&c->val, String))
+						{
+							/* XXX: json/jsonb access path is a string like "{a, b, c}",
+							 * I don't have an existing function to parse it,
+							 * and I am not sure if I should do it here, so leave
+							 * it for now.
+							 */
+						}
+					}
+					else if (IsA(i->rexpr, A_ArrayExpr))
+					{
+						A_ArrayExpr *ae = (A_ArrayExpr *) i->rexpr;
+						if (list_length(ae->elements) > 0)
+						{
+							Node *last = (Node *) llast(ae->elements);
+							if (IsA(last, A_Const))
+							{
+								A_Const *c = (A_Const *) last;
+								if (IsA(&c->val, String))
+								{
+									*name = strVal(&c->val);
+									return 2;
+								}
+							}
+						}
+					}
+				}
+			}
 			break;
 		case T_TypeCast:
 			strength = FigureColnameInternal(((TypeCast *) node)->arg,
-- 
2.39.5 (Apple Git-154)

