@@ -32,6 +32,83 @@ typedef struct JsonbSubWorkspace
32
32
Datum * index ; /* Subscript values in Datum format */
33
33
} JsonbSubWorkspace ;
34
34
35
+ static Oid
36
+ jsonb_subscript_type (Node * expr )
37
+ {
38
+ if (expr && IsA (expr , String ))
39
+ return TEXTOID ;
40
+
41
+ return exprType (expr );
42
+ }
43
+
44
+ static Node *
45
+ coerce_jsonpath_subscript (ParseState * pstate , Node * subExpr , Oid numtype )
46
+ {
47
+ Oid subExprType = jsonb_subscript_type (subExpr );
48
+ Oid targetType = UNKNOWNOID ;
49
+
50
+ if (subExprType != UNKNOWNOID )
51
+ {
52
+ Oid targets [2 ] = {numtype , TEXTOID };
53
+
54
+ /*
55
+ * Jsonb can handle multiple subscript types, but cases when a
56
+ * subscript could be coerced to multiple target types must be
57
+ * avoided, similar to overloaded functions. It could be possibly
58
+ * extend with jsonpath in the future.
59
+ */
60
+ for (int i = 0 ; i < 2 ; i ++ )
61
+ {
62
+ if (can_coerce_type (1 , & subExprType , & targets [i ], COERCION_IMPLICIT ))
63
+ {
64
+ /*
65
+ * One type has already succeeded, it means there are two
66
+ * coercion targets possible, failure.
67
+ */
68
+ if (targetType != UNKNOWNOID )
69
+ ereport (ERROR ,
70
+ (errcode (ERRCODE_DATATYPE_MISMATCH ),
71
+ errmsg ("subscript type %s is not supported" , format_type_be (subExprType )),
72
+ errhint ("jsonb subscript must be coercible to only one type, integer or text." ),
73
+ parser_errposition (pstate , exprLocation (subExpr ))));
74
+
75
+ targetType = targets [i ];
76
+ }
77
+ }
78
+
79
+ /*
80
+ * No suitable types were found, failure.
81
+ */
82
+ if (targetType == UNKNOWNOID )
83
+ ereport (ERROR ,
84
+ (errcode (ERRCODE_DATATYPE_MISMATCH ),
85
+ errmsg ("subscript type %s is not supported" , format_type_be (subExprType )),
86
+ errhint ("jsonb subscript must be coercible to either integer or text." ),
87
+ parser_errposition (pstate , exprLocation (subExpr ))));
88
+ }
89
+ else
90
+ targetType = TEXTOID ;
91
+
92
+ /*
93
+ * We known from can_coerce_type that coercion will succeed, so
94
+ * coerce_type could be used. Note the implicit coercion context, which is
95
+ * required to handle subscripts of different types, similar to overloaded
96
+ * functions.
97
+ */
98
+ subExpr = coerce_type (pstate ,
99
+ subExpr , subExprType ,
100
+ targetType , -1 ,
101
+ COERCION_IMPLICIT ,
102
+ COERCE_IMPLICIT_CAST ,
103
+ -1 );
104
+ if (subExpr == NULL )
105
+ ereport (ERROR ,
106
+ (errcode (ERRCODE_DATATYPE_MISMATCH ),
107
+ errmsg ("jsonb subscript must have text type" ),
108
+ parser_errposition (pstate , exprLocation (subExpr ))));
109
+
110
+ return subExpr ;
111
+ }
35
112
36
113
/*
37
114
* Finish parse analysis of a SubscriptingRef expression for a jsonb.
@@ -75,71 +152,8 @@ jsonb_subscript_transform(SubscriptingRef *sbsref,
75
152
76
153
if (ai -> uidx )
77
154
{
78
- Oid subExprType = InvalidOid ,
79
- targetType = UNKNOWNOID ;
80
-
81
155
subExpr = transformExpr (pstate , ai -> uidx , pstate -> p_expr_kind );
82
- subExprType = exprType (subExpr );
83
-
84
- if (subExprType != UNKNOWNOID )
85
- {
86
- Oid targets [2 ] = {INT4OID , TEXTOID };
87
-
88
- /*
89
- * Jsonb can handle multiple subscript types, but cases when a
90
- * subscript could be coerced to multiple target types must be
91
- * avoided, similar to overloaded functions. It could be
92
- * possibly extend with jsonpath in the future.
93
- */
94
- for (int i = 0 ; i < 2 ; i ++ )
95
- {
96
- if (can_coerce_type (1 , & subExprType , & targets [i ], COERCION_IMPLICIT ))
97
- {
98
- /*
99
- * One type has already succeeded, it means there are
100
- * two coercion targets possible, failure.
101
- */
102
- if (targetType != UNKNOWNOID )
103
- ereport (ERROR ,
104
- (errcode (ERRCODE_DATATYPE_MISMATCH ),
105
- errmsg ("subscript type %s is not supported" , format_type_be (subExprType )),
106
- errhint ("jsonb subscript must be coercible to only one type, integer or text." ),
107
- parser_errposition (pstate , exprLocation (subExpr ))));
108
-
109
- targetType = targets [i ];
110
- }
111
- }
112
-
113
- /*
114
- * No suitable types were found, failure.
115
- */
116
- if (targetType == UNKNOWNOID )
117
- ereport (ERROR ,
118
- (errcode (ERRCODE_DATATYPE_MISMATCH ),
119
- errmsg ("subscript type %s is not supported" , format_type_be (subExprType )),
120
- errhint ("jsonb subscript must be coercible to either integer or text." ),
121
- parser_errposition (pstate , exprLocation (subExpr ))));
122
- }
123
- else
124
- targetType = TEXTOID ;
125
-
126
- /*
127
- * We known from can_coerce_type that coercion will succeed, so
128
- * coerce_type could be used. Note the implicit coercion context,
129
- * which is required to handle subscripts of different types,
130
- * similar to overloaded functions.
131
- */
132
- subExpr = coerce_type (pstate ,
133
- subExpr , subExprType ,
134
- targetType , -1 ,
135
- COERCION_IMPLICIT ,
136
- COERCE_IMPLICIT_CAST ,
137
- -1 );
138
- if (subExpr == NULL )
139
- ereport (ERROR ,
140
- (errcode (ERRCODE_DATATYPE_MISMATCH ),
141
- errmsg ("jsonb subscript must have text type" ),
142
- parser_errposition (pstate , exprLocation (subExpr ))));
156
+ subExpr = coerce_jsonpath_subscript (pstate , subExpr , INT4OID );
143
157
}
144
158
else
145
159
{
0 commit comments