pg_query 6.2.2 → 6.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +54 -1
- data/README.md +25 -2
- data/Rakefile +2 -2
- data/ext/pg_query/include/pg_query_fingerprint_defs.c +8 -0
- data/ext/pg_query/include/pg_query_outfuncs_defs.c +4 -0
- data/ext/pg_query/include/pg_query_readfuncs_defs.c +4 -0
- data/ext/pg_query/include/postgres/copyfuncs.funcs.c +4 -0
- data/ext/pg_query/include/postgres/equalfuncs.funcs.c +4 -0
- data/ext/pg_query/include/postgres/nodes/parsenodes.h +8 -0
- data/ext/pg_query/include/protobuf/pg_query.pb-c.h +282 -278
- data/ext/pg_query/pg_query.pb-c.c +64 -12
- data/ext/pg_query/pg_query_normalize.c +45 -47
- data/ext/pg_query/pg_query_readfuncs_protobuf.c +8 -5
- data/ext/pg_query/pg_query_ruby.c +41 -0
- data/ext/pg_query/postgres_deparse.c +234 -13
- data/ext/pg_query/src_backend_nodes_makefuncs.c +2 -0
- data/ext/pg_query/src_backend_parser_gram.c +30322 -30090
- data/lib/pg_query/fingerprint.rb +6 -0
- data/lib/pg_query/parse.rb +95 -1
- data/lib/pg_query/pg_query_pb.rb +1 -1
- data/lib/pg_query/summary.rb +145 -0
- data/lib/pg_query/version.rb +1 -1
- data/lib/pg_query.rb +1 -0
- metadata +6 -5
|
@@ -18,6 +18,96 @@
|
|
|
18
18
|
#include "utils/timestamp.h"
|
|
19
19
|
#include "utils/xml.h"
|
|
20
20
|
|
|
21
|
+
/*
|
|
22
|
+
* Strict structural checking of the input tree (on by default).
|
|
23
|
+
*
|
|
24
|
+
* The deparser receives its parse tree from the caller (in libpg_query, from
|
|
25
|
+
* an arbitrary protobuf), so the tree may not have the shape a given deparse
|
|
26
|
+
* path expects. The stock code documents those expectations with Assert(),
|
|
27
|
+
* which is a no-op in a release build, so a malformed tree instead triggers
|
|
28
|
+
* out-of-bounds reads that can leak adjacent heap memory or crash. Two cases:
|
|
29
|
+
*
|
|
30
|
+
* - A node's actual type not matching what a path expects. The stock
|
|
31
|
+
* castNode() is a bare cast with no runtime check, so intVal()/strVal()/
|
|
32
|
+
* boolVal()/floatVal() read the wrong union member.
|
|
33
|
+
*
|
|
34
|
+
* - A list being shorter than a path assumes. The stock linitial()/lsecond()/
|
|
35
|
+
* lthird()/lfourth()/llast() index past the end of the ListCell array.
|
|
36
|
+
*
|
|
37
|
+
* By default we redefine those macros here to check and raise a normal error
|
|
38
|
+
* on violation, caught by libpg_query's surrounding PG_TRY and returned as a
|
|
39
|
+
* PgQueryError. Redefining castNode() covers intVal()/strVal()/etc., since
|
|
40
|
+
* they are all defined in terms of it; redefining the positional list
|
|
41
|
+
* accessors covers every fixed-index access.
|
|
42
|
+
*
|
|
43
|
+
* Define PG_QUERY_DEPARSE_NO_STRICT_CHECKS to opt out and keep the stock
|
|
44
|
+
* unchecked macros -- e.g. if you feed the deparser only trees you have
|
|
45
|
+
* already validated and want to avoid the per-access checks.
|
|
46
|
+
*/
|
|
47
|
+
#ifndef PG_QUERY_DEPARSE_NO_STRICT_CHECKS
|
|
48
|
+
static inline void *
|
|
49
|
+
pg_query_strict_cast_node(NodeTag type, void *ptr, const char *file, int line)
|
|
50
|
+
{
|
|
51
|
+
if (ptr != NULL && nodeTag(ptr) != type)
|
|
52
|
+
elog(ERROR, "deparse: unexpected node type %d, expected %d (%s:%d)",
|
|
53
|
+
(int) nodeTag(ptr), (int) type, file, line);
|
|
54
|
+
return ptr;
|
|
55
|
+
}
|
|
56
|
+
#undef castNode
|
|
57
|
+
#define castNode(_type_, nodeptr) \
|
|
58
|
+
((_type_ *) pg_query_strict_cast_node(T_##_type_, (nodeptr), __FILE__, __LINE__))
|
|
59
|
+
|
|
60
|
+
/*
|
|
61
|
+
* intVal()/strVal()/boolVal()/floatVal() extract a scalar from a value node, so
|
|
62
|
+
* a NULL node is always a bug (a genuinely-absent value is handled by the
|
|
63
|
+
* caller before extraction, e.g. "PASSWORD NULL"). Reject NULL here rather than
|
|
64
|
+
* dereferencing it. castNode()'s own check then covers a wrong node type.
|
|
65
|
+
*/
|
|
66
|
+
static inline void *
|
|
67
|
+
pg_query_require_value_node(void *ptr, const char *file, int line)
|
|
68
|
+
{
|
|
69
|
+
if (ptr == NULL)
|
|
70
|
+
elog(ERROR, "deparse: value extraction from NULL node (%s:%d)", file, line);
|
|
71
|
+
return ptr;
|
|
72
|
+
}
|
|
73
|
+
#undef intVal
|
|
74
|
+
#undef floatVal
|
|
75
|
+
#undef boolVal
|
|
76
|
+
#undef strVal
|
|
77
|
+
#define intVal(v) (castNode(Integer, pg_query_require_value_node((v), __FILE__, __LINE__))->ival)
|
|
78
|
+
#define floatVal(v) atof(castNode(Float, pg_query_require_value_node((v), __FILE__, __LINE__))->fval)
|
|
79
|
+
#define boolVal(v) (castNode(Boolean, pg_query_require_value_node((v), __FILE__, __LINE__))->boolval)
|
|
80
|
+
#define strVal(v) (castNode(String, pg_query_require_value_node((v), __FILE__, __LINE__))->sval)
|
|
81
|
+
|
|
82
|
+
static inline void *
|
|
83
|
+
pg_query_checked_list_nth(const List *l, int n, const char *file, int line)
|
|
84
|
+
{
|
|
85
|
+
if (l == NIL || n < 0 || n >= list_length(l))
|
|
86
|
+
elog(ERROR, "deparse: list index %d out of range for length %d (%s:%d)",
|
|
87
|
+
n, list_length(l), file, line);
|
|
88
|
+
return list_nth(l, n);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
static inline void *
|
|
92
|
+
pg_query_checked_list_last(const List *l, const char *file, int line)
|
|
93
|
+
{
|
|
94
|
+
if (l == NIL)
|
|
95
|
+
elog(ERROR, "deparse: llast() on empty list (%s:%d)", file, line);
|
|
96
|
+
return list_nth(l, list_length(l) - 1);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
#undef linitial
|
|
100
|
+
#undef lsecond
|
|
101
|
+
#undef lthird
|
|
102
|
+
#undef lfourth
|
|
103
|
+
#undef llast
|
|
104
|
+
#define linitial(l) pg_query_checked_list_nth((l), 0, __FILE__, __LINE__)
|
|
105
|
+
#define lsecond(l) pg_query_checked_list_nth((l), 1, __FILE__, __LINE__)
|
|
106
|
+
#define lthird(l) pg_query_checked_list_nth((l), 2, __FILE__, __LINE__)
|
|
107
|
+
#define lfourth(l) pg_query_checked_list_nth((l), 3, __FILE__, __LINE__)
|
|
108
|
+
#define llast(l) pg_query_checked_list_last((l), __FILE__, __LINE__)
|
|
109
|
+
#endif
|
|
110
|
+
|
|
21
111
|
/*
|
|
22
112
|
* # Deparser overview
|
|
23
113
|
*
|
|
@@ -93,6 +183,7 @@ typedef enum DeparseNodeContext {
|
|
|
93
183
|
DEPARSE_NODE_CONTEXT_A_EXPR,
|
|
94
184
|
DEPARSE_NODE_CONTEXT_CREATE_TYPE,
|
|
95
185
|
DEPARSE_NODE_CONTEXT_ALTER_TYPE,
|
|
186
|
+
DEPARSE_NODE_CONTEXT_ALTER_DOMAIN,
|
|
96
187
|
DEPARSE_NODE_CONTEXT_SET_STATEMENT,
|
|
97
188
|
DEPARSE_NODE_CONTEXT_FUNC_EXPR,
|
|
98
189
|
DEPARSE_NODE_CONTEXT_SELECT_SETOP,
|
|
@@ -231,7 +322,7 @@ static void deparseJsonFuncExpr(DeparseState *state, JsonFuncExpr *json_func_exp
|
|
|
231
322
|
static void deparseJsonQuotesClauseOpt(DeparseState *state, JsonQuotes quotes);
|
|
232
323
|
static void deparseJsonOnErrorClauseOpt(DeparseState *state, JsonBehavior *behavior);
|
|
233
324
|
static void deparseJsonOnEmptyClauseOpt(DeparseState *state, JsonBehavior *behavior);
|
|
234
|
-
static void deparseConstraint(DeparseState *state, Constraint *constraint);
|
|
325
|
+
static void deparseConstraint(DeparseState *state, Constraint *constraint, DeparseNodeContext context);
|
|
235
326
|
static void deparseSchemaStmt(DeparseState *state, Node *node);
|
|
236
327
|
static void deparseExecuteStmt(DeparseState *state, ExecuteStmt *execute_stmt);
|
|
237
328
|
static void deparseTriggerTransition(DeparseState *state, TriggerTransition *trigger_transition);
|
|
@@ -735,6 +826,9 @@ static void deparseAnyNameSkipLast(DeparseState *state, List *parts)
|
|
|
735
826
|
// "func_expr" in gram.y
|
|
736
827
|
static void deparseFuncExpr(DeparseState *state, Node *node, DeparseNodeContext context)
|
|
737
828
|
{
|
|
829
|
+
if (node == NULL)
|
|
830
|
+
elog(ERROR, "deparse: unexpected NULL node");
|
|
831
|
+
|
|
738
832
|
switch (nodeTag(node))
|
|
739
833
|
{
|
|
740
834
|
case T_FuncCall:
|
|
@@ -784,6 +878,7 @@ static void deparseExpr(DeparseState *state, Node *node, DeparseNodeContext cont
|
|
|
784
878
|
{
|
|
785
879
|
if (node == NULL)
|
|
786
880
|
return;
|
|
881
|
+
|
|
787
882
|
switch (nodeTag(node))
|
|
788
883
|
{
|
|
789
884
|
case T_ColumnRef:
|
|
@@ -860,6 +955,9 @@ static void deparseExpr(DeparseState *state, Node *node, DeparseNodeContext cont
|
|
|
860
955
|
// "b_expr" in gram.y
|
|
861
956
|
static void deparseBExpr(DeparseState *state, Node *node)
|
|
862
957
|
{
|
|
958
|
+
if (node == NULL)
|
|
959
|
+
elog(ERROR, "deparse: unexpected NULL node in deparseBExpr");
|
|
960
|
+
|
|
863
961
|
if (IsA(node, XmlExpr)) {
|
|
864
962
|
deparseXmlExpr(state, castNode(XmlExpr, node), DEPARSE_NODE_CONTEXT_NONE);
|
|
865
963
|
return;
|
|
@@ -888,6 +986,9 @@ static void deparseBExpr(DeparseState *state, Node *node)
|
|
|
888
986
|
// "AexprConst" in gram.y
|
|
889
987
|
static void deparseAexprConst(DeparseState *state, Node *node)
|
|
890
988
|
{
|
|
989
|
+
if (node == NULL)
|
|
990
|
+
elog(ERROR, "deparse: unexpected NULL node");
|
|
991
|
+
|
|
891
992
|
switch (nodeTag(node))
|
|
892
993
|
{
|
|
893
994
|
case T_A_Const:
|
|
@@ -906,6 +1007,9 @@ static void deparseAexprConst(DeparseState *state, Node *node)
|
|
|
906
1007
|
// "c_expr" in gram.y
|
|
907
1008
|
static void deparseCExpr(DeparseState *state, Node *node)
|
|
908
1009
|
{
|
|
1010
|
+
if (node == NULL)
|
|
1011
|
+
elog(ERROR, "deparse: unexpected NULL node");
|
|
1012
|
+
|
|
909
1013
|
switch (nodeTag(node))
|
|
910
1014
|
{
|
|
911
1015
|
case T_ColumnRef:
|
|
@@ -1041,6 +1145,9 @@ static void deparseSimpleTypename(DeparseState *state, Node *node)
|
|
|
1041
1145
|
// "NumericOnly" in gram.y
|
|
1042
1146
|
static void deparseNumericOnly(DeparseState *state, union ValUnion *value)
|
|
1043
1147
|
{
|
|
1148
|
+
if (value == NULL)
|
|
1149
|
+
elog(ERROR, "deparse: unexpected NULL value in deparseNumericOnly");
|
|
1150
|
+
|
|
1044
1151
|
switch (nodeTag(value))
|
|
1045
1152
|
{
|
|
1046
1153
|
case T_Integer:
|
|
@@ -1422,7 +1529,7 @@ static void deparseCommonFuncOptItem(DeparseState *state, DefElem *def_elem)
|
|
|
1422
1529
|
deparseAppendStringInfoString(state, "SUPPORT ");
|
|
1423
1530
|
deparseAnyName(state, castNode(List, def_elem->arg));
|
|
1424
1531
|
}
|
|
1425
|
-
else if (strcmp(def_elem->defname, "set") == 0 && IsA(def_elem->arg, VariableSetStmt)) // FunctionSetResetClause
|
|
1532
|
+
else if (strcmp(def_elem->defname, "set") == 0 && def_elem->arg != NULL && IsA(def_elem->arg, VariableSetStmt)) // FunctionSetResetClause
|
|
1426
1533
|
{
|
|
1427
1534
|
deparseVariableSetStmt(state, castNode(VariableSetStmt, def_elem->arg));
|
|
1428
1535
|
}
|
|
@@ -1571,6 +1678,9 @@ static void deparseFuncName(DeparseState *state, List *func_name)
|
|
|
1571
1678
|
// "function_with_argtypes" in gram.y
|
|
1572
1679
|
static void deparseFunctionWithArgtypes(DeparseState *state, ObjectWithArgs *object_with_args)
|
|
1573
1680
|
{
|
|
1681
|
+
if (object_with_args == NULL)
|
|
1682
|
+
elog(ERROR, "deparse: unexpected NULL ObjectWithArgs");
|
|
1683
|
+
|
|
1574
1684
|
ListCell *lc;
|
|
1575
1685
|
deparseFuncName(state, object_with_args->objname);
|
|
1576
1686
|
|
|
@@ -1610,6 +1720,9 @@ static void deparseFunctionWithArgtypesList(DeparseState *state, List *l)
|
|
|
1610
1720
|
// "operator_with_argtypes" in gram.y
|
|
1611
1721
|
static void deparseOperatorWithArgtypes(DeparseState *state, ObjectWithArgs *object_with_args)
|
|
1612
1722
|
{
|
|
1723
|
+
if (object_with_args == NULL)
|
|
1724
|
+
elog(ERROR, "deparse: unexpected NULL ObjectWithArgs");
|
|
1725
|
+
|
|
1613
1726
|
deparseAnyOperator(state, object_with_args->objname);
|
|
1614
1727
|
|
|
1615
1728
|
Assert(list_length(object_with_args->objargs) == 2);
|
|
@@ -1672,6 +1785,9 @@ static void deparseAggrArgs(DeparseState *state, List *aggr_args)
|
|
|
1672
1785
|
// "aggregate_with_argtypes" in gram.y
|
|
1673
1786
|
static void deparseAggregateWithArgtypes(DeparseState *state, ObjectWithArgs *object_with_args)
|
|
1674
1787
|
{
|
|
1788
|
+
if (object_with_args == NULL)
|
|
1789
|
+
elog(ERROR, "deparse: unexpected NULL ObjectWithArgs");
|
|
1790
|
+
|
|
1675
1791
|
ListCell *lc = NULL;
|
|
1676
1792
|
|
|
1677
1793
|
deparseFuncName(state, object_with_args->objname);
|
|
@@ -2151,6 +2267,9 @@ static void deparseXmlNamespaceList(DeparseState *state, List *l)
|
|
|
2151
2267
|
// "table_ref" in gram.y
|
|
2152
2268
|
static void deparseTableRef(DeparseState *state, Node *node)
|
|
2153
2269
|
{
|
|
2270
|
+
if (node == NULL)
|
|
2271
|
+
elog(ERROR, "deparse: unexpected NULL node");
|
|
2272
|
+
|
|
2154
2273
|
switch (nodeTag(node))
|
|
2155
2274
|
{
|
|
2156
2275
|
case T_RangeVar:
|
|
@@ -2356,7 +2475,8 @@ static void deparseSetClauseList(DeparseState *state, List *target_list)
|
|
|
2356
2475
|
deparseAppendCommaAndPart(state);
|
|
2357
2476
|
|
|
2358
2477
|
ResTarget *res_target = castNode(ResTarget, lfirst(lc));
|
|
2359
|
-
|
|
2478
|
+
if (res_target->val == NULL)
|
|
2479
|
+
elog(ERROR, "deparse: unexpected NULL val in SET clause ResTarget");
|
|
2360
2480
|
|
|
2361
2481
|
if (IsA(res_target->val, MultiAssignRef))
|
|
2362
2482
|
{
|
|
@@ -2386,6 +2506,9 @@ static void deparseSetClauseList(DeparseState *state, List *target_list)
|
|
|
2386
2506
|
// "func_expr_windowless" in gram.y
|
|
2387
2507
|
static void deparseFuncExprWindowless(DeparseState *state, Node* node)
|
|
2388
2508
|
{
|
|
2509
|
+
if (node == NULL)
|
|
2510
|
+
elog(ERROR, "deparse: unexpected NULL node");
|
|
2511
|
+
|
|
2389
2512
|
switch (nodeTag(node))
|
|
2390
2513
|
{
|
|
2391
2514
|
case T_FuncCall:
|
|
@@ -2730,6 +2853,9 @@ static void deparseUtilityOptionList(DeparseState *state, List *options)
|
|
|
2730
2853
|
|
|
2731
2854
|
static void deparseSelectStmt(DeparseState *state, SelectStmt *stmt, DeparseNodeContext context)
|
|
2732
2855
|
{
|
|
2856
|
+
if (stmt == NULL)
|
|
2857
|
+
elog(ERROR, "deparse: unexpected NULL SelectStmt");
|
|
2858
|
+
|
|
2733
2859
|
const ListCell *lc = NULL;
|
|
2734
2860
|
const ListCell *lc2 = NULL;
|
|
2735
2861
|
bool need_parens = context == DEPARSE_NODE_CONTEXT_SELECT_SETOP && (
|
|
@@ -2798,6 +2924,8 @@ static void deparseSelectStmt(DeparseState *state, SelectStmt *stmt, DeparseNode
|
|
|
2798
2924
|
|
|
2799
2925
|
if (stmt->intoClause != NULL)
|
|
2800
2926
|
{
|
|
2927
|
+
if (stmt->intoClause->rel == NULL)
|
|
2928
|
+
elog(ERROR, "deparse: unexpected NULL rel in IntoClause");
|
|
2801
2929
|
deparseAppendPartGroup(state, "INTO", DEPARSE_PART_INDENT);
|
|
2802
2930
|
deparseOptTemp(state, stmt->intoClause->rel->relpersistence);
|
|
2803
2931
|
deparseIntoClause(state, stmt->intoClause);
|
|
@@ -2974,6 +3102,9 @@ static void deparseIntoClause(DeparseState *state, IntoClause *into_clause)
|
|
|
2974
3102
|
|
|
2975
3103
|
static void deparseRangeVar(DeparseState *state, RangeVar *range_var, DeparseNodeContext context)
|
|
2976
3104
|
{
|
|
3105
|
+
if (range_var == NULL)
|
|
3106
|
+
elog(ERROR, "deparse: unexpected NULL RangeVar");
|
|
3107
|
+
|
|
2977
3108
|
if (!range_var->inh && context != DEPARSE_NODE_CONTEXT_CREATE_TYPE && context != DEPARSE_NODE_CONTEXT_ALTER_TYPE)
|
|
2978
3109
|
deparseAppendStringInfoString(state, "ONLY ");
|
|
2979
3110
|
|
|
@@ -3073,6 +3204,9 @@ static void deparseAConst(DeparseState *state, A_Const *a_const)
|
|
|
3073
3204
|
|
|
3074
3205
|
static void deparseFuncCall(DeparseState *state, FuncCall *func_call, DeparseNodeContext context)
|
|
3075
3206
|
{
|
|
3207
|
+
if (func_call == NULL)
|
|
3208
|
+
elog(ERROR, "deparse: unexpected NULL FuncCall");
|
|
3209
|
+
|
|
3076
3210
|
const ListCell *lc = NULL;
|
|
3077
3211
|
|
|
3078
3212
|
Assert(list_length(func_call->funcname) > 0);
|
|
@@ -3606,6 +3740,9 @@ needsParensAsBExpr(Node *node)
|
|
|
3606
3740
|
// This handles "A_Expr" parse tree objects, which are a subset of the rules in "a_expr" (handled by deparseExpr)
|
|
3607
3741
|
static void deparseAExpr(DeparseState *state, A_Expr* a_expr, DeparseNodeContext context)
|
|
3608
3742
|
{
|
|
3743
|
+
if (a_expr->rexpr == NULL)
|
|
3744
|
+
elog(ERROR, "deparse: unexpected NULL rexpr in A_Expr");
|
|
3745
|
+
|
|
3609
3746
|
ListCell *lc;
|
|
3610
3747
|
char *name;
|
|
3611
3748
|
|
|
@@ -3997,6 +4134,9 @@ static void deparseWithClause(DeparseState *state, WithClause *with_clause)
|
|
|
3997
4134
|
// "joined_table" in gram.y
|
|
3998
4135
|
static void deparseJoinExpr(DeparseState *state, JoinExpr *join_expr)
|
|
3999
4136
|
{
|
|
4137
|
+
if (join_expr->larg == NULL || join_expr->rarg == NULL)
|
|
4138
|
+
elog(ERROR, "deparse: unexpected NULL larg/rarg in JoinExpr");
|
|
4139
|
+
|
|
4000
4140
|
ListCell *lc;
|
|
4001
4141
|
bool need_alias_parens = join_expr->alias != NULL;
|
|
4002
4142
|
bool need_rarg_parens = IsA(join_expr->rarg, JoinExpr) && castNode(JoinExpr, join_expr->rarg)->alias == NULL;
|
|
@@ -4272,9 +4412,12 @@ static void deparseRowExpr(DeparseState *state, RowExpr *row_expr)
|
|
|
4272
4412
|
|
|
4273
4413
|
static void deparseTypeCast(DeparseState *state, TypeCast *type_cast, DeparseNodeContext context)
|
|
4274
4414
|
{
|
|
4275
|
-
bool need_parens
|
|
4415
|
+
bool need_parens;
|
|
4276
4416
|
|
|
4277
|
-
|
|
4417
|
+
if (type_cast->arg == NULL || type_cast->typeName == NULL)
|
|
4418
|
+
elog(ERROR, "deparse: unexpected NULL arg/typeName in TypeCast");
|
|
4419
|
+
|
|
4420
|
+
need_parens = needsParensAsBExpr(type_cast->arg);
|
|
4278
4421
|
|
|
4279
4422
|
if (context == DEPARSE_NODE_CONTEXT_FUNC_EXPR)
|
|
4280
4423
|
{
|
|
@@ -4356,6 +4499,9 @@ static void deparseTypeCast(DeparseState *state, TypeCast *type_cast, DeparseNod
|
|
|
4356
4499
|
|
|
4357
4500
|
static void deparseTypeName(DeparseState *state, TypeName *type_name)
|
|
4358
4501
|
{
|
|
4502
|
+
if (type_name == NULL)
|
|
4503
|
+
elog(ERROR, "deparse: unexpected NULL TypeName");
|
|
4504
|
+
|
|
4359
4505
|
ListCell *lc;
|
|
4360
4506
|
bool skip_typmods = false;
|
|
4361
4507
|
|
|
@@ -4631,6 +4777,9 @@ static void deparseCaseWhen(DeparseState *state, CaseWhen *case_when)
|
|
|
4631
4777
|
|
|
4632
4778
|
static void deparseAIndirection(DeparseState *state, A_Indirection *a_indirection)
|
|
4633
4779
|
{
|
|
4780
|
+
if (a_indirection->arg == NULL)
|
|
4781
|
+
elog(ERROR, "deparse: unexpected NULL arg in A_Indirection");
|
|
4782
|
+
|
|
4634
4783
|
ListCell *lc;
|
|
4635
4784
|
bool need_parens =
|
|
4636
4785
|
IsA(a_indirection->arg, A_Indirection) ||
|
|
@@ -4638,6 +4787,7 @@ static void deparseAIndirection(DeparseState *state, A_Indirection *a_indirectio
|
|
|
4638
4787
|
IsA(a_indirection->arg, A_Expr) ||
|
|
4639
4788
|
IsA(a_indirection->arg, TypeCast) ||
|
|
4640
4789
|
IsA(a_indirection->arg, RowExpr) ||
|
|
4790
|
+
IsA(a_indirection->arg, A_ArrayExpr) ||
|
|
4641
4791
|
(IsA(a_indirection->arg, ColumnRef) && !IsA(linitial(a_indirection->indirection), A_Indices)) ||
|
|
4642
4792
|
IsA(a_indirection->arg, JsonFuncExpr);
|
|
4643
4793
|
|
|
@@ -4688,6 +4838,9 @@ static void deparseMinMaxExpr(DeparseState *state, MinMaxExpr *min_max_expr)
|
|
|
4688
4838
|
|
|
4689
4839
|
static void deparseBooleanTest(DeparseState *state, BooleanTest *boolean_test)
|
|
4690
4840
|
{
|
|
4841
|
+
if (boolean_test->arg == NULL)
|
|
4842
|
+
elog(ERROR, "deparse: unexpected NULL arg in BooleanTest");
|
|
4843
|
+
|
|
4691
4844
|
bool need_parens = IsA(boolean_test->arg, BoolExpr);
|
|
4692
4845
|
|
|
4693
4846
|
if (need_parens)
|
|
@@ -4726,6 +4879,9 @@ static void deparseBooleanTest(DeparseState *state, BooleanTest *boolean_test)
|
|
|
4726
4879
|
// "columnDef" and "alter_table_cmd" in gram.y
|
|
4727
4880
|
static void deparseColumnDef(DeparseState *state, ColumnDef *column_def)
|
|
4728
4881
|
{
|
|
4882
|
+
if (column_def == NULL)
|
|
4883
|
+
elog(ERROR, "deparse: unexpected NULL ColumnDef");
|
|
4884
|
+
|
|
4729
4885
|
ListCell *lc;
|
|
4730
4886
|
|
|
4731
4887
|
if (column_def->colname != NULL)
|
|
@@ -4769,7 +4925,7 @@ static void deparseColumnDef(DeparseState *state, ColumnDef *column_def)
|
|
|
4769
4925
|
|
|
4770
4926
|
foreach(lc, column_def->constraints)
|
|
4771
4927
|
{
|
|
4772
|
-
deparseConstraint(state, castNode(Constraint, lfirst(lc)));
|
|
4928
|
+
deparseConstraint(state, castNode(Constraint, lfirst(lc)), DEPARSE_NODE_CONTEXT_NONE);
|
|
4773
4929
|
deparseAppendStringInfoChar(state, ' ');
|
|
4774
4930
|
}
|
|
4775
4931
|
|
|
@@ -5332,7 +5488,7 @@ static void deparseCreateDomainStmt(DeparseState *state, CreateDomainStmt *creat
|
|
|
5332
5488
|
|
|
5333
5489
|
foreach(lc, create_domain_stmt->constraints)
|
|
5334
5490
|
{
|
|
5335
|
-
deparseConstraint(state, castNode(Constraint, lfirst(lc)));
|
|
5491
|
+
deparseConstraint(state, castNode(Constraint, lfirst(lc)), DEPARSE_NODE_CONTEXT_NONE);
|
|
5336
5492
|
deparseAppendStringInfoChar(state, ' ');
|
|
5337
5493
|
}
|
|
5338
5494
|
|
|
@@ -5381,8 +5537,11 @@ static void deparseCreateExtensionStmt(DeparseState *state, CreateExtensionStmt
|
|
|
5381
5537
|
}
|
|
5382
5538
|
|
|
5383
5539
|
// "ColConstraintElem" and "ConstraintElem" in gram.y
|
|
5384
|
-
static void deparseConstraint(DeparseState *state, Constraint *constraint)
|
|
5540
|
+
static void deparseConstraint(DeparseState *state, Constraint *constraint, DeparseNodeContext context)
|
|
5385
5541
|
{
|
|
5542
|
+
if (constraint == NULL)
|
|
5543
|
+
elog(ERROR, "deparse: unexpected NULL Constraint");
|
|
5544
|
+
|
|
5386
5545
|
ListCell *lc;
|
|
5387
5546
|
|
|
5388
5547
|
if (constraint->conname != NULL)
|
|
@@ -5487,7 +5646,7 @@ static void deparseConstraint(DeparseState *state, Constraint *constraint)
|
|
|
5487
5646
|
{
|
|
5488
5647
|
bool valueOnly = false;
|
|
5489
5648
|
|
|
5490
|
-
if (list_length(constraint->keys) == 1) {
|
|
5649
|
+
if (context == DEPARSE_NODE_CONTEXT_ALTER_DOMAIN && list_length(constraint->keys) == 1) {
|
|
5491
5650
|
Node* firstKey = constraint->keys->elements[0].ptr_value;
|
|
5492
5651
|
valueOnly = IsA(firstKey, String) && !strcmp("value", ((String*)firstKey)->sval);
|
|
5493
5652
|
}
|
|
@@ -5864,6 +6023,9 @@ static void deparseCreateConversionStmt(DeparseState *state, CreateConversionStm
|
|
|
5864
6023
|
|
|
5865
6024
|
static void deparseRoleSpec(DeparseState *state, RoleSpec *role_spec)
|
|
5866
6025
|
{
|
|
6026
|
+
if (role_spec == NULL)
|
|
6027
|
+
elog(ERROR, "deparse: unexpected NULL RoleSpec");
|
|
6028
|
+
|
|
5867
6029
|
switch (role_spec->roletype)
|
|
5868
6030
|
{
|
|
5869
6031
|
case ROLESPEC_CSTRING:
|
|
@@ -5974,6 +6136,9 @@ static void deparsePartitionBoundSpec(DeparseState *state, PartitionBoundSpec *p
|
|
|
5974
6136
|
|
|
5975
6137
|
static void deparsePartitionCmd(DeparseState *state, PartitionCmd *partition_cmd)
|
|
5976
6138
|
{
|
|
6139
|
+
if (partition_cmd == NULL)
|
|
6140
|
+
elog(ERROR, "deparse: unexpected NULL PartitionCmd");
|
|
6141
|
+
|
|
5977
6142
|
deparseRangeVar(state, partition_cmd->name, DEPARSE_NODE_CONTEXT_NONE);
|
|
5978
6143
|
|
|
5979
6144
|
if (partition_cmd->bound != NULL)
|
|
@@ -5988,6 +6153,9 @@ static void deparsePartitionCmd(DeparseState *state, PartitionCmd *partition_cmd
|
|
|
5988
6153
|
// "TableElement" in gram.y
|
|
5989
6154
|
static void deparseTableElement(DeparseState *state, Node *node)
|
|
5990
6155
|
{
|
|
6156
|
+
if (node == NULL)
|
|
6157
|
+
elog(ERROR, "deparse: unexpected NULL node");
|
|
6158
|
+
|
|
5991
6159
|
switch (nodeTag(node))
|
|
5992
6160
|
{
|
|
5993
6161
|
case T_ColumnDef:
|
|
@@ -5997,7 +6165,7 @@ static void deparseTableElement(DeparseState *state, Node *node)
|
|
|
5997
6165
|
deparseTableLikeClause(state, castNode(TableLikeClause, node));
|
|
5998
6166
|
break;
|
|
5999
6167
|
case T_Constraint:
|
|
6000
|
-
deparseConstraint(state, castNode(Constraint, node));
|
|
6168
|
+
deparseConstraint(state, castNode(Constraint, node), DEPARSE_NODE_CONTEXT_NONE);
|
|
6001
6169
|
break;
|
|
6002
6170
|
default:
|
|
6003
6171
|
Assert(false);
|
|
@@ -6006,6 +6174,9 @@ static void deparseTableElement(DeparseState *state, Node *node)
|
|
|
6006
6174
|
|
|
6007
6175
|
static void deparseCreateStmt(DeparseState *state, CreateStmt *create_stmt, bool is_foreign_table)
|
|
6008
6176
|
{
|
|
6177
|
+
if (create_stmt->relation == NULL)
|
|
6178
|
+
elog(ERROR, "deparse: unexpected NULL relation in CreateStmt");
|
|
6179
|
+
|
|
6009
6180
|
ListCell *lc;
|
|
6010
6181
|
|
|
6011
6182
|
deparseAppendStringInfoString(state, "CREATE ");
|
|
@@ -6429,6 +6600,10 @@ static void deparseImportForeignSchemaStmt(DeparseState *state, ImportForeignSch
|
|
|
6429
6600
|
|
|
6430
6601
|
static void deparseCreateTableAsStmt(DeparseState *state, CreateTableAsStmt *create_table_as_stmt)
|
|
6431
6602
|
{
|
|
6603
|
+
if (create_table_as_stmt->into == NULL || create_table_as_stmt->into->rel == NULL ||
|
|
6604
|
+
create_table_as_stmt->query == NULL)
|
|
6605
|
+
elog(ERROR, "deparse: unexpected NULL into/query in CreateTableAsStmt");
|
|
6606
|
+
|
|
6432
6607
|
ListCell *lc;
|
|
6433
6608
|
deparseAppendStringInfoString(state, "CREATE ");
|
|
6434
6609
|
|
|
@@ -6469,6 +6644,9 @@ static void deparseCreateTableAsStmt(DeparseState *state, CreateTableAsStmt *cre
|
|
|
6469
6644
|
|
|
6470
6645
|
static void deparseViewStmt(DeparseState *state, ViewStmt *view_stmt)
|
|
6471
6646
|
{
|
|
6647
|
+
if (view_stmt->view == NULL)
|
|
6648
|
+
elog(ERROR, "deparse: unexpected NULL view in ViewStmt");
|
|
6649
|
+
|
|
6472
6650
|
ListCell *lc;
|
|
6473
6651
|
|
|
6474
6652
|
deparseAppendStringInfoString(state, "CREATE ");
|
|
@@ -7286,7 +7464,7 @@ static void deparseAlterTableCmd(DeparseState *state, AlterTableCmd *alter_table
|
|
|
7286
7464
|
case AT_AddIdentity:
|
|
7287
7465
|
case AT_AddConstraint:
|
|
7288
7466
|
case AT_AlterConstraint:
|
|
7289
|
-
deparseConstraint(state, castNode(Constraint, alter_table_cmd->def));
|
|
7467
|
+
deparseConstraint(state, castNode(Constraint, alter_table_cmd->def), DEPARSE_NODE_CONTEXT_NONE);
|
|
7290
7468
|
deparseAppendStringInfoChar(state, ' ');
|
|
7291
7469
|
break;
|
|
7292
7470
|
case AT_SetIdentity:
|
|
@@ -7452,7 +7630,7 @@ static void deparseAlterDomainStmt(DeparseState *state, AlterDomainStmt *alter_d
|
|
|
7452
7630
|
break;
|
|
7453
7631
|
case 'C':
|
|
7454
7632
|
deparseAppendStringInfoString(state, "ADD ");
|
|
7455
|
-
deparseConstraint(state, castNode(Constraint, alter_domain_stmt->def));
|
|
7633
|
+
deparseConstraint(state, castNode(Constraint, alter_domain_stmt->def), DEPARSE_NODE_CONTEXT_ALTER_DOMAIN);
|
|
7456
7634
|
break;
|
|
7457
7635
|
case 'X':
|
|
7458
7636
|
deparseAppendStringInfoString(state, "DROP CONSTRAINT ");
|
|
@@ -7794,6 +7972,9 @@ static bool isSetTimeZoneInterval(VariableSetStmt* stmt)
|
|
|
7794
7972
|
|
|
7795
7973
|
static void deparseVariableSetStmt(DeparseState *state, VariableSetStmt* variable_set_stmt)
|
|
7796
7974
|
{
|
|
7975
|
+
if (variable_set_stmt == NULL)
|
|
7976
|
+
elog(ERROR, "deparse: unexpected NULL VariableSetStmt");
|
|
7977
|
+
|
|
7797
7978
|
ListCell *lc;
|
|
7798
7979
|
|
|
7799
7980
|
switch (variable_set_stmt->kind)
|
|
@@ -8186,6 +8367,8 @@ static void deparseCopyStmt(DeparseState *state, CopyStmt *copy_stmt)
|
|
|
8186
8367
|
else if (strcmp(def_elem->defname, "force_quote") == 0)
|
|
8187
8368
|
{
|
|
8188
8369
|
deparseAppendStringInfoString(state, "FORCE_QUOTE ");
|
|
8370
|
+
if (def_elem->arg == NULL)
|
|
8371
|
+
elog(ERROR, "deparse: unexpected NULL arg for FORCE_QUOTE");
|
|
8189
8372
|
if (IsA(def_elem->arg, A_Star))
|
|
8190
8373
|
{
|
|
8191
8374
|
deparseAppendStringInfoChar(state, '*');
|
|
@@ -8205,6 +8388,8 @@ static void deparseCopyStmt(DeparseState *state, CopyStmt *copy_stmt)
|
|
|
8205
8388
|
{
|
|
8206
8389
|
deparseAppendStringInfoString(state, "FORCE_NOT_NULL ");
|
|
8207
8390
|
|
|
8391
|
+
if (def_elem->arg == NULL)
|
|
8392
|
+
elog(ERROR, "deparse: unexpected NULL arg for FORCE_NOT_NULL");
|
|
8208
8393
|
if (IsA(def_elem->arg, A_Star))
|
|
8209
8394
|
deparseAStar(state, castNode(A_Star, def_elem->arg));
|
|
8210
8395
|
else
|
|
@@ -8218,6 +8403,8 @@ static void deparseCopyStmt(DeparseState *state, CopyStmt *copy_stmt)
|
|
|
8218
8403
|
{
|
|
8219
8404
|
deparseAppendStringInfoString(state, "FORCE_NULL ");
|
|
8220
8405
|
|
|
8406
|
+
if (def_elem->arg == NULL)
|
|
8407
|
+
elog(ERROR, "deparse: unexpected NULL arg for FORCE_NULL");
|
|
8221
8408
|
if (IsA(def_elem->arg, A_Star))
|
|
8222
8409
|
deparseAStar(state, castNode(A_Star, def_elem->arg));
|
|
8223
8410
|
else
|
|
@@ -8735,6 +8922,9 @@ static void deparseAccessPriv(DeparseState *state, AccessPriv *access_priv)
|
|
|
8735
8922
|
|
|
8736
8923
|
static void deparseGrantStmt(DeparseState *state, GrantStmt *grant_stmt)
|
|
8737
8924
|
{
|
|
8925
|
+
if (grant_stmt == NULL)
|
|
8926
|
+
elog(ERROR, "deparse: unexpected NULL GrantStmt");
|
|
8927
|
+
|
|
8738
8928
|
ListCell *lc;
|
|
8739
8929
|
if (grant_stmt->is_grant)
|
|
8740
8930
|
deparseAppendStringInfoString(state, "GRANT ");
|
|
@@ -8802,6 +8992,8 @@ static void deparseGrantRoleStmt(DeparseState *state, GrantRoleStmt *grant_role_
|
|
|
8802
8992
|
|
|
8803
8993
|
if (!grant_role_stmt->is_grant && list_length(grant_role_stmt->opt)) {
|
|
8804
8994
|
DefElem *defelem = castNode(DefElem, linitial(grant_role_stmt->opt));
|
|
8995
|
+
if (defelem->arg == NULL)
|
|
8996
|
+
elog(ERROR, "deparse: unexpected NULL arg in GRANT role option");
|
|
8805
8997
|
Assert(!castNode(Boolean, defelem->arg)->boolval);
|
|
8806
8998
|
|
|
8807
8999
|
if (strcmp("admin", defelem->defname) == 0) {
|
|
@@ -8838,6 +9030,8 @@ static void deparseGrantRoleStmt(DeparseState *state, GrantRoleStmt *grant_role_
|
|
|
8838
9030
|
|
|
8839
9031
|
foreach(lc, grant_role_stmt->opt) {
|
|
8840
9032
|
DefElem *defelem = castNode(DefElem, lfirst(lc));
|
|
9033
|
+
if (defelem->arg == NULL)
|
|
9034
|
+
elog(ERROR, "deparse: unexpected NULL arg in GRANT role option");
|
|
8841
9035
|
if (strcmp("admin", defelem->defname) == 0) {
|
|
8842
9036
|
deparseAppendStringInfoString(state, "ADMIN ");
|
|
8843
9037
|
deparseAppendStringInfoString(state, castNode(Boolean, defelem->arg)->boolval ? "OPTION" : "FALSE");
|
|
@@ -9500,6 +9694,9 @@ static void deparseUnlistenStmt(DeparseState *state, UnlistenStmt *unlisten_stmt
|
|
|
9500
9694
|
|
|
9501
9695
|
static void deparseCreateSeqStmt(DeparseState *state, CreateSeqStmt *create_seq_stmt)
|
|
9502
9696
|
{
|
|
9697
|
+
if (create_seq_stmt->sequence == NULL)
|
|
9698
|
+
elog(ERROR, "deparse: unexpected NULL sequence in CreateSeqStmt");
|
|
9699
|
+
|
|
9503
9700
|
ListCell *lc;
|
|
9504
9701
|
|
|
9505
9702
|
deparseAppendStringInfoString(state, "CREATE ");
|
|
@@ -9651,6 +9848,9 @@ static void deparseRefreshMatViewStmt(DeparseState *state, RefreshMatViewStmt *r
|
|
|
9651
9848
|
|
|
9652
9849
|
static void deparseReplicaIdentityStmt(DeparseState *state, ReplicaIdentityStmt *replica_identity_stmt)
|
|
9653
9850
|
{
|
|
9851
|
+
if (replica_identity_stmt == NULL)
|
|
9852
|
+
elog(ERROR, "deparse: unexpected NULL ReplicaIdentityStmt");
|
|
9853
|
+
|
|
9654
9854
|
switch (replica_identity_stmt->identity_type)
|
|
9655
9855
|
{
|
|
9656
9856
|
case REPLICA_IDENTITY_NOTHING:
|
|
@@ -9837,6 +10037,8 @@ static void deparsePublicationObjectList(DeparseState *state, List *pubobjects)
|
|
|
9837
10037
|
|
|
9838
10038
|
switch (obj->pubobjtype) {
|
|
9839
10039
|
case PUBLICATIONOBJ_TABLE:
|
|
10040
|
+
if (obj->pubtable == NULL)
|
|
10041
|
+
elog(ERROR, "deparse: unexpected NULL pubtable in PublicationObjSpec");
|
|
9840
10042
|
deparseAppendStringInfoString(state, "TABLE ");
|
|
9841
10043
|
deparseRangeVar(state, obj->pubtable->relation, DEPARSE_NODE_CONTEXT_NONE);
|
|
9842
10044
|
|
|
@@ -11061,6 +11263,9 @@ static void deparseJsonIsPredicate(DeparseState *state, JsonIsPredicate *j)
|
|
|
11061
11263
|
// "json_value_expr" in gram.y
|
|
11062
11264
|
static void deparseJsonValueExpr(DeparseState *state, JsonValueExpr *json_value_expr)
|
|
11063
11265
|
{
|
|
11266
|
+
if (json_value_expr == NULL)
|
|
11267
|
+
elog(ERROR, "deparse: unexpected NULL JsonValueExpr");
|
|
11268
|
+
|
|
11064
11269
|
deparseExpr(state, (Node *) json_value_expr->raw_expr, DEPARSE_NODE_CONTEXT_A_EXPR);
|
|
11065
11270
|
deparseAppendStringInfoChar(state, ' ');
|
|
11066
11271
|
deparseJsonFormat(state, json_value_expr->format);
|
|
@@ -11107,7 +11312,8 @@ static void deparseJsonOutput(DeparseState *state, JsonOutput *json_output)
|
|
|
11107
11312
|
if (json_output == NULL)
|
|
11108
11313
|
return;
|
|
11109
11314
|
|
|
11110
|
-
|
|
11315
|
+
if (json_output->returning == NULL)
|
|
11316
|
+
elog(ERROR, "deparse: unexpected NULL returning in JsonOutput");
|
|
11111
11317
|
|
|
11112
11318
|
deparseAppendStringInfoString(state, "RETURNING ");
|
|
11113
11319
|
deparseTypeName(state, json_output->typeName);
|
|
@@ -11610,6 +11816,9 @@ static void deparseValue(DeparseState *state, union ValUnion *value, DeparseNode
|
|
|
11610
11816
|
// "PrepareableStmt" in gram.y
|
|
11611
11817
|
static void deparsePreparableStmt(DeparseState *state, Node *node)
|
|
11612
11818
|
{
|
|
11819
|
+
if (node == NULL)
|
|
11820
|
+
elog(ERROR, "deparse: unexpected NULL node");
|
|
11821
|
+
|
|
11613
11822
|
switch (nodeTag(node))
|
|
11614
11823
|
{
|
|
11615
11824
|
case T_SelectStmt:
|
|
@@ -11635,6 +11844,9 @@ static void deparsePreparableStmt(DeparseState *state, Node *node)
|
|
|
11635
11844
|
// "RuleActionStmt" in gram.y
|
|
11636
11845
|
static void deparseRuleActionStmt(DeparseState *state, Node *node)
|
|
11637
11846
|
{
|
|
11847
|
+
if (node == NULL)
|
|
11848
|
+
elog(ERROR, "deparse: unexpected NULL node");
|
|
11849
|
+
|
|
11638
11850
|
switch (nodeTag(node))
|
|
11639
11851
|
{
|
|
11640
11852
|
case T_SelectStmt:
|
|
@@ -11660,6 +11872,9 @@ static void deparseRuleActionStmt(DeparseState *state, Node *node)
|
|
|
11660
11872
|
// "ExplainableStmt" in gram.y
|
|
11661
11873
|
static void deparseExplainableStmt(DeparseState *state, Node *node)
|
|
11662
11874
|
{
|
|
11875
|
+
if (node == NULL)
|
|
11876
|
+
elog(ERROR, "deparse: unexpected NULL node");
|
|
11877
|
+
|
|
11663
11878
|
switch (nodeTag(node))
|
|
11664
11879
|
{
|
|
11665
11880
|
case T_SelectStmt:
|
|
@@ -11697,6 +11912,9 @@ static void deparseExplainableStmt(DeparseState *state, Node *node)
|
|
|
11697
11912
|
// "schema_stmt" in gram.y
|
|
11698
11913
|
static void deparseSchemaStmt(DeparseState *state, Node *node)
|
|
11699
11914
|
{
|
|
11915
|
+
if (node == NULL)
|
|
11916
|
+
elog(ERROR, "deparse: unexpected NULL node");
|
|
11917
|
+
|
|
11700
11918
|
switch (nodeTag(node))
|
|
11701
11919
|
{
|
|
11702
11920
|
case T_CreateStmt:
|
|
@@ -11762,6 +11980,9 @@ static void deparseStmt(DeparseState *state, Node *node)
|
|
|
11762
11980
|
//
|
|
11763
11981
|
// And the following grammar names error out in the parser:
|
|
11764
11982
|
// - CreateAssertionStmt (not supported yet)
|
|
11983
|
+
if (node == NULL)
|
|
11984
|
+
elog(ERROR, "deparse: unexpected NULL node");
|
|
11985
|
+
|
|
11765
11986
|
switch (nodeTag(node))
|
|
11766
11987
|
{
|
|
11767
11988
|
case T_AlterEventTrigStmt:
|
|
@@ -302,6 +302,7 @@ makeDefElem(char *name, Node *arg, int location)
|
|
|
302
302
|
res->arg = arg;
|
|
303
303
|
res->defaction = DEFELEM_UNSPEC;
|
|
304
304
|
res->location = location;
|
|
305
|
+
res->arg_location = -1;
|
|
305
306
|
|
|
306
307
|
return res;
|
|
307
308
|
}
|
|
@@ -321,6 +322,7 @@ makeDefElemExtended(char *nameSpace, char *name, Node *arg,
|
|
|
321
322
|
res->arg = arg;
|
|
322
323
|
res->defaction = defaction;
|
|
323
324
|
res->location = location;
|
|
325
|
+
res->arg_location = -1;
|
|
324
326
|
|
|
325
327
|
return res;
|
|
326
328
|
}
|