1 /*-------------------------------------------------------------------------
2  *
3  * outfuncs.c
4  *	  Output functions for Postgres tree nodes.
5  *
6  * Portions Copyright (c) 2003-2019, PgPool Global Development Group
7  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  *
11  * IDENTIFICATION
12  *	  src/backend/nodes/outfuncs.c
13  *
14  * NOTES
15  *	  Every node type that can appear in stored rules' parsetrees *must*
16  *	  have an output function defined here (as well as an input function
17  *	  in readfuncs.c).	For use in debugging, we also provide output
18  *	  functions for nodes that appear in raw parsetrees, path, and plan trees.
19  *	  These nodes however need not have input functions.
20  *
21  *-------------------------------------------------------------------------
22  */
23 #include <string.h>
24 #include <limits.h>
25 #include "pool_type.h"
26 #include "utils/palloc.h"
27 #include "utils/elog.h"
28 #include "parser.h"
29 #include "extensible.h"
30 #include "pool_string.h"
31 #include "pg_list.h"
32 #include "parsenodes.h"
33 #include "pg_class.h"
34 #include "pg_trigger.h"
35 #include "value.h"
36 
37 #define booltostr(x)  ((x) ? "true" : "false")
38 
39 void		_outNode(String * str, void *obj);
40 
41 static void _outList(String * str, List *node);
42 static void _outIdList(String * str, List *node);
43 static void _outAlias(String * str, Alias *node);
44 static void _outRangeVar(String * str, RangeVar *node);
45 static void _outVar(String * str, Var *node);
46 static void _outConst(String * str, Const *node);
47 static void _outParam(String * str, Param *node);
48 static void _outAggref(String * str, Aggref *node);
49 static void _outGroupingFunc(String * str, GroupingFunc *node);
50 static void _outSubscriptingRef(String * str, SubscriptingRef *node);
51 static void _outFuncExpr(String * str, FuncExpr *node);
52 static void _outNamedArgExpr(String * str, NamedArgExpr *node);
53 static void _outOpExpr(String * str, OpExpr *node);
54 static void _outDistinctExpr(String * str, DistinctExpr *node);
55 static void _outScalarArrayOpExpr(String * str, ScalarArrayOpExpr *node);
56 static void _outBoolExpr(String * str, BoolExpr *node);
57 static void _outSubLink(String * str, SubLink *node);
58 static void _outSubPlan(String * str, SubPlan *node);
59 static void _outFieldSelect(String * str, FieldSelect *node);
60 static void _outFieldStore(String * str, FieldStore *node);
61 static void _outRelabelType(String * str, RelabelType *node);
62 static void _outConvertRowtypeExpr(String * str, ConvertRowtypeExpr *node);
63 static void _outCaseExpr(String * str, CaseExpr *node);
64 static void _outCaseWhen(String * str, CaseWhen *node);
65 static void _outCaseTestExpr(String * str, CaseTestExpr *node);
66 static void _outArrayExpr(String * str, ArrayExpr *node);
67 static void _outRowExpr(String * str, RowExpr *node);
68 static void _outCoalesceExpr(String * str, CoalesceExpr *node);
69 static void _outMinMaxExpr(String * str, MinMaxExpr *node);
70 static void _outNullIfExpr(String * str, NullIfExpr *node);
71 static void _outNullTest(String * str, NullTest *node);
72 static void _outBooleanTest(String * str, BooleanTest *node);
73 static void _outCoerceToDomain(String * str, CoerceToDomain *node);
74 static void _outCoerceToDomainValue(String * str, CoerceToDomainValue *node);
75 static void _outSetToDefault(String * str, SetToDefault *node);
76 static void _outCurrentOfExpr(String * str, CurrentOfExpr *node);
77 static void _outInferenceElem(String * str, InferenceElem *node);
78 static void _outTargetEntry(String * str, TargetEntry *node);
79 static void _outRangeTblRef(String * str, RangeTblRef *node);
80 static void _outJoinExpr(String * str, JoinExpr *node);
81 static void _outFromExpr(String * str, FromExpr *node);
82 static void _outCreateStmt(String * str, CreateStmt *node);
83 static void _outCreateTableAsStmt(String * str, CreateTableAsStmt *node);
84 static void _outCreateForeignTableStmt(String * str, CreateForeignTableStmt *node);
85 static void _outImportForeignSchemaStmt(String * str, ImportForeignSchemaStmt *node);
86 static void _outIndexStmt(String * str, IndexStmt *node);
87 static void _outNotifyStmt(String * str, NotifyStmt *node);
88 static void _outDeclareCursorStmt(String * str, DeclareCursorStmt *node);
89 static void _outSelectStmt(String * str, SelectStmt *node);
90 static void _outFuncCall(String * str, FuncCall *node);
91 static void _outDefElem(String * str, DefElem *node);
92 static void _outLockingClause(String * str, LockingClause *node);
93 static void _outColumnDef(String * str, ColumnDef *node);
94 static void _outTypeName(String * str, TypeName *node);
95 static void _outTypeCast(String * str, TypeCast *node);
96 static void _outIndexElem(String * str, IndexElem *node);
97 static void _outGroupingSet(String * str, GroupingSet *node);
98 static void _outWithClause(String * str, WithClause *node);
99 static void _outCommonTableExpr(String * str, CommonTableExpr *node);
100 static void _outSetOperationStmt(String * str, SetOperationStmt *node);
101 static void _outTableSampleClause(String * str, TableSampleClause *node);
102 static void _outAExpr(String * str, A_Expr *node);
103 static void _outValue(String * str, Value *value);
104 static void _outColumnRef(String * str, ColumnRef *node);
105 static void _outParamRef(String * str, ParamRef *node);
106 static void _outAConst(String * str, A_Const *node);
107 static void _outA_Indices(String * str, A_Indices *node);
108 static void _outA_Indirection(String * str, A_Indirection *node);
109 static void _outResTarget(String * str, ResTarget *node);
110 static void _outMultiAssignRef(String * str, MultiAssignRef *node);
111 static void _outA_ArrayExpr(String * str, A_ArrayExpr *node);
112 static void _outWindowDef(String * str, WindowDef *node);
113 static void _outConstraint(String * str, Constraint *node);
114 
115 static void _outSortBy(String * str, SortBy *node);
116 static void _outInsertStmt(String * str, InsertStmt *node);
117 static void _outSetClause(String * str, List *node);
118 static void _outUpdateStmt(String * str, UpdateStmt *node);
119 static void _outDeleteStmt(String * str, DeleteStmt *node);
120 static void _outTransactionStmt(String * str, TransactionStmt *node);
121 static void _outTruncateStmt(String * str, TruncateStmt *node);
122 static void _outVacuumStmt(String * str, VacuumStmt *node);
123 static void _outExplainStmt(String * str, ExplainStmt *node);
124 static void _outClusterStmt(String * str, ClusterStmt *node);
125 static void _outCheckPointStmt(String * str, CheckPointStmt *node);
126 static void _outClosePortalStmt(String * str, ClosePortalStmt *node);
127 static void _outListenStmt(String * str, ListenStmt *node);
128 static void _outUnlistenStmt(String * str, UnlistenStmt *node);
129 static void _outLoadStmt(String * str, LoadStmt *node);
130 static void _outCopyStmt(String * str, CopyStmt *node);
131 static void _outDeallocateStmt(String * str, DeallocateStmt *node);
132 static void _outRenameStmt(String * str, RenameStmt *node);
133 static void _outCreateRoleStmt(String * str, CreateRoleStmt *node);
134 static void _outAlterRoleStmt(String * str, AlterRoleStmt *node);
135 static void _outDropRoleStmt(String * str, DropRoleStmt *node);
136 static void _outCreateSchemaStmt(String * str, CreateSchemaStmt *node);
137 static void _outVariableSetStmt(String * str, VariableSetStmt *node);
138 static void _outVariableShowStmt(String * str, VariableShowStmt *node);
139 static void _outConstraintsSetStmt(String * str, ConstraintsSetStmt *node);
140 static void _outAlterTableStmt(String * str, AlterTableStmt *node);
141 static void _outCreateSeqStmt(String * str, CreateSeqStmt *node);
142 static void _outAlterSeqStmt(String * str, AlterSeqStmt *node);
143 static void _outCreatePLangStmt(String * str, CreatePLangStmt *node);
144 static void _outCreateTableSpaceStmt(String * str, CreateTableSpaceStmt *node);
145 static void _outDropTableSpaceStmt(String * str, DropTableSpaceStmt *node);
146 static void _outCreateTrigStmt(String * str, CreateTrigStmt *node);
147 static void _outDefineStmt(String * str, DefineStmt *node);
148 static void _outCreateOpClassStmt(String * str, CreateOpClassStmt *node);
149 static void _outDropStmt(String * str, DropStmt *node);
150 static void _outFetchStmt(String * str, FetchStmt *node);
151 static void _outGrantStmt(String * str, GrantStmt *node);
152 static void _outGrantRoleStmt(String * str, GrantRoleStmt *node);
153 static void _outCreateFunctionStmt(String * str, CreateFunctionStmt *node);
154 static void _outAlterFunctionStmt(String * str, AlterFunctionStmt *node);
155 static void _outCreateCastStmt(String * str, CreateCastStmt *node);
156 static void _outReindexStmt(String * str, ReindexStmt *node);
157 static void _outRuleStmt(String * str, RuleStmt *node);
158 static void _outViewStmt(String * str, ViewStmt *node);
159 static void _outCreatedbStmt(String * str, CreatedbStmt *node);
160 static void _outAlterDatabaseStmt(String * str, AlterDatabaseStmt *node);
161 static void _outAlterDatabaseSetStmt(String * str, AlterDatabaseSetStmt *node);
162 static void _outDropdbStmt(String * str, DropdbStmt *node);
163 static void _outCreateDomainStmt(String * str, CreateDomainStmt *node);
164 static void _outAlterDomainStmt(String * str, AlterDomainStmt *node);
165 static void _outCreateConversionStmt(String * str, CreateConversionStmt *node);
166 static void _outPrepareStmt(String * str, PrepareStmt *node);
167 static void _outExecuteStmt(String * str, ExecuteStmt *node);
168 static void _outLockStmt(String * str, LockStmt *node);
169 static void _outCommentStmt(String * str, CommentStmt *node);
170 static void _outDiscardStmt(String * str, DiscardStmt *node);
171 static void _outCreateOpFamilyStmt(String * str, CreateOpFamilyStmt *node);
172 static void _outAlterOpFamilyStmt(String * str, AlterOpFamilyStmt *node);
173 static void _outCreateEnumStmt(String * str, CreateEnumStmt *node);
174 static void _outDropOwnedStmt(String * str, DropOwnedStmt *node);
175 static void _outReassignOwnedStmt(String * str, ReassignOwnedStmt *node);
176 static void _outAlterTSDictionaryStmt(String * str, AlterTSDictionaryStmt *node);
177 static void _outAlterTSConfigurationStmt(String * str, AlterTSConfigurationStmt *node);
178 static void _outXmlExpr(String * str, XmlExpr *node);
179 static void _outXmlSerialize(String * str, XmlSerialize *node);
180 
181 static void _outFuncName(String * str, List *func_name);
182 static void _outSetRest(String * str, VariableSetStmt *node);
183 static void _outSetTransactionModeList(String * str, List *list);
184 static void _outAlterTableCmd(String * str, AlterTableCmd *node);
185 static void _outOptSeqList(String * str, List *options);
186 static void _outObjectWithArgs(String * str, ObjectWithArgs *node);
187 static void _outFunctionParameter(String * str, FunctionParameter *node);
188 static void _outPrivilegeList(String * str, List *list);
189 static void _outFuncOptList(String * str, List *list);
190 static void _outCreatedbOptList(String * str, List *options);
191 static void _outOperatorArgTypes(String * str, List *args);
192 static void _outRangeFunction(String * str, RangeFunction *node);
193 static void _outRangeTableSample(String * str, RangeTableSample *node);
194 static void _outWithDefinition(String * str, List *def_list);
195 static void _outOnConflictClause(String * str, OnConflictClause *node);
196 
197 
198 /*
199  * Borrowed from backend/catalog/namespace.c
200  * NameListToString
201  *      Utility routine to convert a qualified-name list into a string.
202  *
203  * This is used primarily to form error messages, and so we do not quote
204  * the list elements, for the sake of legibility.
205  *
206  * In most scenarios the list elements should always be Value strings,
207  * but we also allow A_Star for the convenience of ColumnRef processing.
208  */
209 char *
NameListToString(List * names)210 NameListToString(List *names)
211 {
212 	StringInfoData string;
213 	ListCell   *l;
214 
215 	initStringInfo(&string);
216 
217 	foreach(l, names)
218 	{
219 		Node	   *name = (Node *) lfirst(l);
220 
221 		if (l != list_head(names))
222 			appendStringInfoChar(&string, '.');
223 
224 		if (IsA(name, String))
225 			appendStringInfoString(&string, strVal(name));
226 		else if (IsA(name, A_Star))
227 			appendStringInfoString(&string, "*");
228 		else
229 			elog(ERROR, "unexpected node type in name list: %d",
230 				 (int) nodeTag(name));
231 	}
232 
233 	return string.data;
234 }
235 
236 
237 static char *
escape_string(char * str)238 escape_string(char *str)
239 {
240 	int			len = strlen(str),
241 				i,
242 				j;
243 	char	   *es = palloc0(len * 2 + 1);
244 
245 	if (es == NULL)
246 	{
247 		return NULL;
248 	}
249 
250 	for (i = 0, j = 0; i < len; i++, j++)
251 	{
252 		if (str[i] == '\'')
253 		{
254 			es[j++] = '\'';
255 		}
256 		else if (str[i] == '\\')
257 		{
258 			if (!standard_conforming_strings)
259 				es[j++] = '\\';
260 		}
261 		es[j] = str[i];
262 	}
263 
264 	return es;
265 }
266 
267 static void
_outIdList(String * str,List * node)268 _outIdList(String * str, List *node)
269 {
270 	ListCell   *lc;
271 	char		first = 0;
272 
273 	foreach(lc, node)
274 	{
275 		Value	   *v = lfirst(lc);
276 
277 		if (first == 0)
278 			first = 1;
279 		else
280 			string_append_char(str, ", ");
281 
282 		string_append_char(str, "\"");
283 		string_append_char(str, v->val.str);
284 		string_append_char(str, "\"");
285 	}
286 }
287 
288 static void
_outListWith(String * str,List * node,char * op)289 _outListWith(String * str, List *node, char *op)
290 {
291 	ListCell   *lc;
292 	char		first = 0;
293 
294 	foreach(lc, node)
295 	{
296 		if (first == 0)
297 			first = 1;
298 		else
299 		{
300 			if (lfirst(lc) != NIL && !IsA(lfirst(lc), A_Indices))
301 				string_append_char(str, op);
302 		}
303 		_outNode(str, lfirst(lc));
304 	}
305 }
306 
307 static void
_outList(String * str,List * node)308 _outList(String * str, List *node)
309 {
310 	_outListWith(str, node, ",");
311 }
312 
313 
314 
315 /*****************************************************************************
316  *
317  *	Stuff from primnodes.h.
318  *
319  *****************************************************************************/
320 
321 #ifdef NOT_USED_IN_PGPOOL
322 /* for use by extensions which define extensible nodes */
323 void
outToken(StringInfo str,const char * s)324 outToken(StringInfo str, const char *s)
325 {
326 	_outToken(str, s);
327 }
328 #endif
329 
330 static void
_outAlias(String * str,Alias * node)331 _outAlias(String * str, Alias *node)
332 {
333 	string_append_char(str, " AS \"");
334 	string_append_char(str, node->aliasname);
335 	string_append_char(str, "\"");
336 
337 	if (node->colnames)
338 	{
339 		string_append_char(str, "(");
340 		_outNode(str, node->colnames);
341 		string_append_char(str, ")");
342 	}
343 }
344 
345 static void
_outRangeVar(String * str,RangeVar * node)346 _outRangeVar(String * str, RangeVar *node)
347 {
348 	if (node->catalogname)
349 	{
350 		string_append_char(str, "\"");
351 		string_append_char(str, node->catalogname);
352 		string_append_char(str, "\".");
353 	}
354 
355 	if (node->schemaname)
356 	{
357 		string_append_char(str, "\"");
358 		string_append_char(str, node->schemaname);
359 		string_append_char(str, "\".");
360 	}
361 
362 	string_append_char(str, "\"");
363 	string_append_char(str, node->relname);
364 	string_append_char(str, "\"");
365 
366 	if (node->alias)
367 		_outNode(str, node->alias);
368 }
369 
370 static void
_outVar(String * str,Var * node)371 _outVar(String * str, Var *node)
372 {
373 
374 }
375 
376 static void
_outConst(String * str,Const * node)377 _outConst(String * str, Const *node)
378 {
379 
380 }
381 
382 static void
_outParam(String * str,Param * node)383 _outParam(String * str, Param *node)
384 {
385 
386 }
387 
388 static void
_outAggref(String * str,Aggref * node)389 _outAggref(String * str, Aggref *node)
390 {
391 
392 }
393 
394 static void
_outGroupingFunc(String * str,GroupingFunc * node)395 _outGroupingFunc(String * str, GroupingFunc *node)
396 {
397 	string_append_char(str, "GROUPING (");
398 	_outNode(str, node->args);
399 	string_append_char(str, ")");
400 
401 }
402 
403 static void
_outSubscriptingRef(String * str,SubscriptingRef * node)404 _outSubscriptingRef(String * str, SubscriptingRef *node)
405 {
406 
407 }
408 
409 static void
_outFuncExpr(String * str,FuncExpr * node)410 _outFuncExpr(String * str, FuncExpr *node)
411 {
412 
413 }
414 
415 static void
_outNamedArgExpr(String * str,NamedArgExpr * node)416 _outNamedArgExpr(String * str, NamedArgExpr *node)
417 {
418 	string_append_char(str, node->name);
419 	string_append_char(str, " := ");
420 	_outNode(str, node->arg);
421 }
422 
423 static void
_outOpExpr(String * str,OpExpr * node)424 _outOpExpr(String * str, OpExpr *node)
425 {
426 
427 }
428 
429 static void
_outDistinctExpr(String * str,DistinctExpr * node)430 _outDistinctExpr(String * str, DistinctExpr *node)
431 {
432 
433 }
434 
435 static void
_outScalarArrayOpExpr(String * str,ScalarArrayOpExpr * node)436 _outScalarArrayOpExpr(String * str, ScalarArrayOpExpr *node)
437 {
438 
439 }
440 
441 static void
_outBoolExpr(String * str,BoolExpr * node)442 _outBoolExpr(String * str, BoolExpr *node)
443 {
444 	switch (node->boolop)
445 	{
446 		case AND_EXPR:
447 			string_append_char(str, " (");
448 			_outListWith(str, node->args, " AND ");
449 			string_append_char(str, ")");
450 			break;
451 
452 		case OR_EXPR:
453 			string_append_char(str, " (");
454 			_outListWith(str, node->args, " OR ");
455 			string_append_char(str, ")");
456 			break;
457 
458 		case NOT_EXPR:
459 			string_append_char(str, " (NOT ");
460 			_outList(str, node->args);
461 			string_append_char(str, ")");
462 			break;
463 	}
464 }
465 
466 static void
_outSubLink(String * str,SubLink * node)467 _outSubLink(String * str, SubLink *node)
468 {
469 	_outNode(str, node->testexpr);
470 
471 	/*
472 	 * If the source was "x IN (select)", convert to "x = ANY (select)".
473 	 */
474 	if (node->subLinkType == ANY_SUBLINK && node->operName == NIL)
475 		node->operName = list_make1(makeString("="));
476 
477 	if (node->operName != NIL)
478 	{
479 		Value	   *v = linitial(node->operName);
480 
481 		if (strcmp(v->val.str, "=") == 0)
482 			string_append_char(str, " IN ");
483 		else
484 		{
485 			string_append_char(str, v->val.str);
486 		}
487 	}
488 
489 	switch (node->subLinkType)
490 	{
491 		case EXISTS_SUBLINK:
492 			string_append_char(str, " EXISTS ");
493 			break;
494 
495 		case ARRAY_SUBLINK:
496 			string_append_char(str, " ARRAY ");
497 			break;
498 
499 		case ANY_SUBLINK:
500 			if (node->operName != NIL)
501 			{
502 				Value	   *v = linitial(node->operName);
503 
504 				if (strcmp(v->val.str, "=") != 0)
505 				{
506 					string_append_char(str, v->val.str);
507 					string_append_char(str, " ANY ");
508 				}
509 			}
510 			break;
511 
512 		case ALL_SUBLINK:
513 			string_append_char(str, " ALL ");
514 			break;
515 
516 		default:
517 			break;
518 	}
519 
520 
521 	if (node->subselect)
522 	{
523 		string_append_char(str, "(");
524 		_outNode(str, node->subselect);
525 		string_append_char(str, ")");
526 	}
527 }
528 
529 static void
_outSubPlan(String * str,SubPlan * node)530 _outSubPlan(String * str, SubPlan *node)
531 {
532 
533 }
534 
535 static void
_outFieldSelect(String * str,FieldSelect * node)536 _outFieldSelect(String * str, FieldSelect *node)
537 {
538 
539 }
540 
541 static void
_outFieldStore(String * str,FieldStore * node)542 _outFieldStore(String * str, FieldStore *node)
543 {
544 
545 }
546 
547 static void
_outRelabelType(String * str,RelabelType * node)548 _outRelabelType(String * str, RelabelType *node)
549 {
550 
551 }
552 
553 static void
_outConvertRowtypeExpr(String * str,ConvertRowtypeExpr * node)554 _outConvertRowtypeExpr(String * str, ConvertRowtypeExpr *node)
555 {
556 
557 }
558 
559 static void
_outCaseExpr(String * str,CaseExpr * node)560 _outCaseExpr(String * str, CaseExpr *node)
561 {
562 	ListCell   *lc;
563 
564 	string_append_char(str, "CASE ");
565 	if (node->arg)
566 		_outNode(str, node->arg);
567 
568 	foreach(lc, node->args)
569 	{
570 		_outNode(str, lfirst(lc));
571 	}
572 
573 	if (node->defresult)
574 	{
575 		string_append_char(str, " ELSE ");
576 		_outNode(str, node->defresult);
577 	}
578 
579 	string_append_char(str, " END");
580 }
581 
582 static void
_outCaseWhen(String * str,CaseWhen * node)583 _outCaseWhen(String * str, CaseWhen *node)
584 {
585 	string_append_char(str, " WHEN ");
586 	_outNode(str, node->expr);
587 	string_append_char(str, " THEN ");
588 	_outNode(str, node->result);
589 }
590 
591 static void
_outCaseTestExpr(String * str,CaseTestExpr * node)592 _outCaseTestExpr(String * str, CaseTestExpr *node)
593 {
594 
595 }
596 
597 static void
_outArrayExpr(String * str,ArrayExpr * node)598 _outArrayExpr(String * str, ArrayExpr *node)
599 {
600 	string_append_char(str, "[");
601 	_outNode(str, node->elements);
602 	string_append_char(str, "]");
603 }
604 
605 static void
_outRowExpr(String * str,RowExpr * node)606 _outRowExpr(String * str, RowExpr *node)
607 {
608 	if (node->row_format == COERCE_EXPLICIT_CAST)
609 		string_append_char(str, "ROW (");
610 	else
611 		string_append_char(str, "(");
612 
613 	if (node->args != NIL)
614 		_outNode(str, node->args);
615 
616 	string_append_char(str, ")");
617 }
618 
619 static void
_outCoalesceExpr(String * str,CoalesceExpr * node)620 _outCoalesceExpr(String * str, CoalesceExpr *node)
621 {
622 	string_append_char(str, "COALESCE (");
623 	_outNode(str, node->args);
624 	string_append_char(str, ")");
625 }
626 
627 static void
_outMinMaxExpr(String * str,MinMaxExpr * node)628 _outMinMaxExpr(String * str, MinMaxExpr *node)
629 {
630 	if (node->op == IS_GREATEST)
631 	{
632 		string_append_char(str, "GREATEST (");
633 		_outNode(str, node->args);
634 		string_append_char(str, ")");
635 	}
636 	else if (node->op == IS_LEAST)
637 	{
638 		string_append_char(str, "LEAST (");
639 		_outNode(str, node->args);
640 		string_append_char(str, ")");
641 	}
642 }
643 
644 static void
_outNullIfExpr(String * str,NullIfExpr * node)645 _outNullIfExpr(String * str, NullIfExpr *node)
646 {
647 
648 }
649 
650 static void
_outNullTest(String * str,NullTest * node)651 _outNullTest(String * str, NullTest *node)
652 {
653 	_outNode(str, node->arg);
654 	if (node->nulltesttype == IS_NOT_NULL)
655 		string_append_char(str, " IS NOT NULL");
656 	else
657 		string_append_char(str, " IS NULL");
658 }
659 
660 static void
_outBooleanTest(String * str,BooleanTest * node)661 _outBooleanTest(String * str, BooleanTest *node)
662 {
663 	_outNode(str, node->arg);
664 
665 	switch (node->booltesttype)
666 	{
667 		case IS_TRUE:
668 			string_append_char(str, " IS TRUE");
669 			break;
670 
671 		case IS_NOT_TRUE:
672 			string_append_char(str, " IS NOT TRUE");
673 			break;
674 
675 		case IS_FALSE:
676 			string_append_char(str, " IS FALSE");
677 			break;
678 
679 		case IS_NOT_FALSE:
680 			string_append_char(str, " IS NOT FALSE");
681 			break;
682 
683 		case IS_UNKNOWN:
684 			string_append_char(str, " IS UNKNOWN");
685 			break;
686 
687 		case IS_NOT_UNKNOWN:
688 			string_append_char(str, " IS NOT UNKNOWN");
689 			break;
690 	}
691 }
692 
693 static void
_outCoerceToDomain(String * str,CoerceToDomain * node)694 _outCoerceToDomain(String * str, CoerceToDomain *node)
695 {
696 
697 }
698 
699 static void
_outCoerceToDomainValue(String * str,CoerceToDomainValue * node)700 _outCoerceToDomainValue(String * str, CoerceToDomainValue *node)
701 {
702 
703 }
704 
705 static void
_outSetToDefault(String * str,SetToDefault * node)706 _outSetToDefault(String * str, SetToDefault *node)
707 {
708 	string_append_char(str, "DEFAULT");
709 }
710 
711 static void
_outCurrentOfExpr(String * str,CurrentOfExpr * node)712 _outCurrentOfExpr(String * str, CurrentOfExpr *node)
713 {
714 	string_append_char(str, "CURRENT OF ");
715 	if (node->cursor_name == NULL)
716 	{
717 		char		n[10];
718 
719 		snprintf(n, sizeof(n), "$%d", node->cursor_param);
720 		string_append_char(str, n);
721 	}
722 	else
723 		string_append_char(str, node->cursor_name);
724 }
725 
726 static void
_outInferenceElem(String * str,InferenceElem * node)727 _outInferenceElem(String * str, InferenceElem *node)
728 {
729 
730 }
731 
732 static void
_outTargetEntry(String * str,TargetEntry * node)733 _outTargetEntry(String * str, TargetEntry *node)
734 {
735 
736 }
737 
738 static void
_outRangeTblRef(String * str,RangeTblRef * node)739 _outRangeTblRef(String * str, RangeTblRef *node)
740 {
741 
742 }
743 
744 static void
_outJoinExpr(String * str,JoinExpr * node)745 _outJoinExpr(String * str, JoinExpr *node)
746 {
747 	_outNode(str, node->larg);
748 
749 	if (node->isNatural == TRUE)
750 		string_append_char(str, " NATURAL");
751 
752 	if (node->jointype == JOIN_INNER)
753 	{
754 		if (node->usingClause == NIL && node->quals == NULL && !node->isNatural)
755 			string_append_char(str, " CROSS JOIN ");
756 		else
757 			string_append_char(str, " JOIN ");
758 	}
759 	else if (node->jointype == JOIN_INNER)
760 		string_append_char(str, " JOIN ");
761 	else if (node->jointype == JOIN_LEFT)
762 		string_append_char(str, " LEFT OUTER JOIN ");
763 	else if (node->jointype == JOIN_FULL)
764 		string_append_char(str, " FULL OUTER JOIN ");
765 	else if (node->jointype == JOIN_RIGHT)
766 		string_append_char(str, " RIGHT OUTER JOIN ");
767 
768 	_outNode(str, node->rarg);
769 
770 	if (node->usingClause != NIL && IsA(node->usingClause, List))
771 	{
772 		ListCell   *lc;
773 		char		comma = 0;
774 
775 		string_append_char(str, " USING(");
776 
777 		foreach(lc, node->usingClause)
778 		{
779 			Value	   *value;
780 
781 			if (comma == 0)
782 				comma = 1;
783 			else
784 				string_append_char(str, ",");
785 
786 			value = lfirst(lc);
787 			string_append_char(str, "\"");
788 			string_append_char(str, value->val.str);
789 			string_append_char(str, "\"");
790 		}
791 
792 		string_append_char(str, ")");
793 	}
794 
795 	if (node->quals)
796 	{
797 		string_append_char(str, " ON ");
798 		_outNode(str, node->quals);
799 	}
800 }
801 
802 static void
_outFromExpr(String * str,FromExpr * node)803 _outFromExpr(String * str, FromExpr *node)
804 {
805 
806 }
807 
808 static void
_outOnConflictExpr(String * str,const OnConflictExpr * node)809 _outOnConflictExpr(String * str, const OnConflictExpr *node)
810 {
811 
812 }
813 
814 #ifdef NOT_USED
815 /*****************************************************************************
816  *
817  *	Stuff from extensible.h
818  *
819  *****************************************************************************/
820 
821 static void
_outExtensibleNode(StringInfo str,const ExtensibleNode * node)822 _outExtensibleNode(StringInfo str, const ExtensibleNode *node)
823 {
824 	const ExtensibleNodeMethods *methods;
825 
826 	methods = GetExtensibleNodeMethods(node->extnodename, false);
827 
828 	WRITE_NODE_TYPE("EXTENSIBLENODE");
829 
830 	WRITE_STRING_FIELD(extnodename);
831 
832 	/* serialize the private fields */
833 	methods->nodeOut(str, node);
834 }
835 #endif
836 
837 /*****************************************************************************
838  *
839  *	Stuff from parsenodes.h.
840  *
841  *****************************************************************************/
842 
843 static void
_outCreateStmt(String * str,CreateStmt * node)844 _outCreateStmt(String * str, CreateStmt *node)
845 {
846 	string_append_char(str, "CREATE ");
847 	if (node->relation->relpersistence == RELPERSISTENCE_TEMP)
848 		string_append_char(str, "TEMP ");
849 	string_append_char(str, "TABLE ");
850 	_outNode(str, node->relation);
851 	string_append_char(str, " (");
852 	_outNode(str, node->tableElts);
853 	string_append_char(str, ") ");
854 
855 	if (node->inhRelations != NIL)
856 	{
857 		string_append_char(str, "INHERITS (");
858 		_outNode(str, node->inhRelations);
859 		string_append_char(str, ")");
860 	}
861 
862 	if (node->options)
863 		_outWithDefinition(str, node->options);
864 
865 	switch (node->oncommit)
866 	{
867 		case ONCOMMIT_DROP:
868 			string_append_char(str, " ON COMMIT DROP");
869 			break;
870 
871 		case ONCOMMIT_DELETE_ROWS:
872 			string_append_char(str, " ON COMMIT DELETE ROWS");
873 			break;
874 
875 		case ONCOMMIT_PRESERVE_ROWS:
876 			string_append_char(str, " ON COMMIT PRESERVE ROWS");
877 			break;
878 
879 		default:
880 			break;
881 	}
882 
883 	if (node->tablespacename)
884 	{
885 		string_append_char(str, " TABLESPACE \"");
886 		string_append_char(str, node->tablespacename);
887 		string_append_char(str, "\"");
888 	}
889 }
890 
891 static void
_outCreateTableAsStmt(String * str,CreateTableAsStmt * node)892 _outCreateTableAsStmt(String * str, CreateTableAsStmt *node)
893 {
894 	string_append_char(str, "CREATE ");
895 	if (node->into->rel->relpersistence == RELPERSISTENCE_TEMP)
896 		string_append_char(str, "TEMP ");
897 	string_append_char(str, "TABLE ");
898 	_outNode(str, node->into->rel);
899 
900 	if (node->into->colNames)
901 	{
902 		string_append_char(str, " (");
903 		_outIdList(str, node->into->colNames);
904 		string_append_char(str, ") ");
905 	}
906 
907 	if (node->into->options)
908 		_outWithDefinition(str, node->into->options);
909 
910 	switch (node->into->onCommit)
911 	{
912 		case ONCOMMIT_DROP:
913 			string_append_char(str, " ON COMMIT DROP");
914 			break;
915 
916 		case ONCOMMIT_DELETE_ROWS:
917 			string_append_char(str, " ON COMMIT DELETE ROWS");
918 			break;
919 
920 		case ONCOMMIT_PRESERVE_ROWS:
921 			string_append_char(str, " ON COMMIT PRESERVE ROWS");
922 			break;
923 
924 		default:
925 			break;
926 	}
927 
928 	if (node->into->tableSpaceName)
929 	{
930 		string_append_char(str, " TABLESPACE \"");
931 		string_append_char(str, node->into->tableSpaceName);
932 		string_append_char(str, "\"");
933 	}
934 
935 	if (node->query)
936 	{
937 		string_append_char(str, " AS");
938 		_outSelectStmt(str, (SelectStmt *) node->query);
939 	}
940 }
941 
942 static void
_outCreateForeignTableStmt(String * str,CreateForeignTableStmt * node)943 _outCreateForeignTableStmt(String * str, CreateForeignTableStmt *node)
944 {
945 
946 }
947 
948 static void
_outImportForeignSchemaStmt(String * str,ImportForeignSchemaStmt * node)949 _outImportForeignSchemaStmt(String * str, ImportForeignSchemaStmt *node)
950 {
951 
952 }
953 
954 static void
_outIndexStmt(String * str,IndexStmt * node)955 _outIndexStmt(String * str, IndexStmt *node)
956 {
957 	string_append_char(str, "CREATE ");
958 
959 	if (node->unique == TRUE)
960 		string_append_char(str, "UNIQUE ");
961 
962 	if (node->concurrent == true)
963 		string_append_char(str, "INDEX CONCURRENTLY ");
964 	else
965 		string_append_char(str, "INDEX ");
966 	if (node->idxname)
967 	{
968 		string_append_char(str, "\"");
969 		string_append_char(str, node->idxname);
970 		string_append_char(str, "\" ");
971 	}
972 	string_append_char(str, "ON ");
973 	_outNode(str, node->relation);
974 
975 	if (strcmp(node->accessMethod, DEFAULT_INDEX_TYPE))
976 	{
977 		string_append_char(str, " USING ");
978 		string_append_char(str, node->accessMethod);
979 	}
980 
981 	string_append_char(str, "(");
982 	_outNode(str, node->indexParams);
983 	string_append_char(str, ")");
984 
985 	if (node->tableSpace)
986 	{
987 		string_append_char(str, " TABLESPACE \"");
988 		string_append_char(str, node->tableSpace);
989 		string_append_char(str, "\"");
990 	}
991 
992 	if (node->whereClause)
993 	{
994 		string_append_char(str, " WHERE ");
995 		_outNode(str, node->whereClause);
996 	}
997 }
998 
999 static void
_outCreateStatsStmt(String * str,CreateStatsStmt * node)1000 _outCreateStatsStmt(String * str, CreateStatsStmt *node)
1001 {
1002 }
1003 
1004 static void
_outNotifyStmt(String * str,NotifyStmt * node)1005 _outNotifyStmt(String * str, NotifyStmt *node)
1006 {
1007 	string_append_char(str, "NOTIFY ");
1008 	string_append_char(str, "\"");
1009 	string_append_char(str, node->conditionname);
1010 	string_append_char(str, "\"");
1011 }
1012 
1013 static void
_outDeclareCursorStmt(String * str,DeclareCursorStmt * node)1014 _outDeclareCursorStmt(String * str, DeclareCursorStmt *node)
1015 {
1016 	string_append_char(str, "DECLARE \"");
1017 	string_append_char(str, node->portalname);
1018 	string_append_char(str, "\" ");
1019 
1020 	if (node->options & CURSOR_OPT_SCROLL)
1021 		string_append_char(str, "SCROLL ");
1022 	if (node->options & CURSOR_OPT_BINARY)
1023 		string_append_char(str, "BINARY ");
1024 	if (node->options & CURSOR_OPT_INSENSITIVE)
1025 		string_append_char(str, "INSENSITIVE ");
1026 
1027 	string_append_char(str, "CURSOR ");
1028 	if (node->options & CURSOR_OPT_HOLD)
1029 		string_append_char(str, "WITH HOLD ");
1030 	string_append_char(str, "FOR");
1031 	_outNode(str, node->query);
1032 }
1033 
1034 static void
_outSelectStmt(String * str,SelectStmt * node)1035 _outSelectStmt(String * str, SelectStmt *node)
1036 {
1037 	if (node->larg)				/* SETOP */
1038 	{
1039 		string_append_char(str, "(");
1040 		_outNode(str, node->larg);
1041 		string_append_char(str, ") ");
1042 
1043 		switch (node->op)
1044 		{
1045 			case SETOP_UNION:
1046 				string_append_char(str, " UNION ");
1047 				break;
1048 
1049 			case SETOP_INTERSECT:
1050 				string_append_char(str, " INTERSECT ");
1051 				break;
1052 
1053 			case SETOP_EXCEPT:
1054 				string_append_char(str, " EXCEPT ");
1055 
1056 			default:
1057 				break;
1058 		}
1059 
1060 		if (node->all)
1061 			string_append_char(str, "ALL ");
1062 
1063 		if (node->rarg)
1064 		{
1065 			string_append_char(str, "(");
1066 			_outNode(str, node->rarg);
1067 			string_append_char(str, ") ");
1068 		}
1069 	}
1070 	else if (node->valuesLists) /* VALUES ... */
1071 	{
1072 		ListCell   *lc;
1073 		int			comma = 0;
1074 
1075 		string_append_char(str, " VALUES");
1076 		foreach(lc, node->valuesLists)
1077 		{
1078 			if (comma == 0)
1079 				comma = 1;
1080 			else
1081 				string_append_char(str, ",");
1082 
1083 			string_append_char(str, " (");
1084 			_outNode(str, lfirst(lc));
1085 			string_append_char(str, ")");
1086 		}
1087 	}
1088 	else
1089 	{
1090 		if (node->intoClause)
1091 		{
1092 			IntoClause *into = (IntoClause *) node->intoClause;
1093 			RangeVar   *rel = (RangeVar *) into->rel;
1094 
1095 			string_append_char(str, "CREATE ");
1096 			if (rel->relpersistence == RELPERSISTENCE_TEMP)
1097 				string_append_char(str, "TEMP ");
1098 			string_append_char(str, "TABLE ");
1099 			_outNode(str, into->rel);
1100 
1101 			if (into->colNames)
1102 			{
1103 				string_append_char(str, " (");
1104 				_outNode(str, into->colNames);
1105 				string_append_char(str, ") ");
1106 			}
1107 
1108 			if (into->options)
1109 				_outWithDefinition(str, into->options);
1110 
1111 			switch (into->onCommit)
1112 			{
1113 				case ONCOMMIT_DROP:
1114 					string_append_char(str, " ON COMMIT DROP");
1115 					break;
1116 
1117 				case ONCOMMIT_DELETE_ROWS:
1118 					string_append_char(str, " ON COMMIT DELETE ROWS");
1119 					break;
1120 
1121 				case ONCOMMIT_PRESERVE_ROWS:
1122 					string_append_char(str, " ON COMMIT PRESERVE ROWS");
1123 					break;
1124 
1125 				default:
1126 					break;
1127 			}
1128 
1129 			string_append_char(str, " AS");
1130 		}
1131 
1132 		if (node->withClause)
1133 			_outWithClause(str, node->withClause);
1134 
1135 		string_append_char(str, " SELECT ");
1136 
1137 		if (node->distinctClause)
1138 		{
1139 			string_append_char(str, "DISTINCT ");
1140 			if (lfirst(list_head(node->distinctClause)) != NIL)
1141 			{
1142 				string_append_char(str, "ON (");
1143 				_outNode(str, node->distinctClause);
1144 				string_append_char(str, " ) ");
1145 			}
1146 		}
1147 
1148 		_outNode(str, node->targetList);
1149 
1150 		if (node->fromClause)
1151 		{
1152 			string_append_char(str, " FROM ");
1153 			_outNode(str, node->fromClause);
1154 		}
1155 
1156 		if (node->whereClause)
1157 		{
1158 			string_append_char(str, " WHERE ");
1159 			_outNode(str, node->whereClause);
1160 		}
1161 
1162 		if (node->groupClause)
1163 		{
1164 			string_append_char(str, " GROUP BY ");
1165 			_outNode(str, node->groupClause);
1166 		}
1167 
1168 		if (node->havingClause)
1169 		{
1170 			string_append_char(str, " HAVING ");
1171 			_outNode(str, node->havingClause);
1172 		}
1173 
1174 		if (node->windowClause)
1175 		{
1176 			string_append_char(str, " WINDOW ");
1177 			_outNode(str, node->windowClause);
1178 		}
1179 	}
1180 
1181 	if (node->sortClause)
1182 	{
1183 		string_append_char(str, " ORDER BY ");
1184 		_outNode(str, node->sortClause);
1185 	}
1186 
1187 	if (node->limitOffset)
1188 	{
1189 		string_append_char(str, " OFFSET ");
1190 		_outNode(str, node->limitOffset);
1191 	}
1192 
1193 	if (node->limitCount)
1194 	{
1195 		string_append_char(str, " LIMIT ");
1196 		if (IsA(node->limitCount, A_Const) &&
1197 			((A_Const *) node->limitCount)->val.type == T_Null)
1198 		{
1199 			string_append_char(str, "ALL ");
1200 		}
1201 		else
1202 		{
1203 			_outNode(str, node->limitCount);
1204 		}
1205 	}
1206 
1207 	_outNode(str, node->lockingClause);
1208 }
1209 
1210 static void
_outFuncCall(String * str,FuncCall * node)1211 _outFuncCall(String * str, FuncCall *node)
1212 {
1213 	char	   *funcname;
1214 
1215 	_outFuncName(str, node->funcname);
1216 
1217 	funcname = strVal(lfirst(list_head(node->funcname)));
1218 
1219 	if (strcmp(funcname, "user") == 0 ||
1220 		strcmp(funcname, "current_user") == 0 ||
1221 		strcmp(funcname, "session_user") == 0 ||
1222 		strcmp(funcname, "current_role") == 0)
1223 		return;
1224 
1225 	string_append_char(str, "(");
1226 
1227 	if (node->func_variadic == TRUE)
1228 		string_append_char(str, "VARIADIC ");
1229 
1230 	if (node->agg_distinct == TRUE)
1231 		string_append_char(str, "DISTINCT ");
1232 
1233 	if (node->agg_star == TRUE)
1234 		string_append_char(str, "*");
1235 	else
1236 		_outNode(str, node->args);
1237 
1238 	if (node->agg_order != NIL)
1239 	{
1240 		string_append_char(str, " ORDER BY ");
1241 		_outNode(str, node->agg_order);
1242 	}
1243 
1244 	string_append_char(str, ")");
1245 
1246 	if (node->over)
1247 	{
1248 		string_append_char(str, " OVER ");
1249 		if (node->over->name)
1250 		{
1251 			string_append_char(str, "\"");
1252 			string_append_char(str, node->over->name);
1253 			string_append_char(str, "\"");
1254 		}
1255 		else
1256 			_outWindowDef(str, node->over);
1257 	}
1258 }
1259 
1260 static void
_outDefElem(String * str,DefElem * node)1261 _outDefElem(String * str, DefElem *node)
1262 {
1263 
1264 }
1265 
1266 static void
_outLockingClause(String * str,LockingClause * node)1267 _outLockingClause(String * str, LockingClause *node)
1268 {
1269 	if (node == NULL)
1270 		return;
1271 
1272 	switch (node->strength)
1273 	{
1274 		case LCS_FORKEYSHARE:
1275 			string_append_char(str, " FOR KEY SHARE");
1276 			break;
1277 		case LCS_FORSHARE:
1278 			string_append_char(str, " FOR SHARE");
1279 			break;
1280 		case LCS_FORNOKEYUPDATE:
1281 			string_append_char(str, " FOR NO KEY UPDATE");
1282 			break;
1283 		case LCS_FORUPDATE:
1284 			string_append_char(str, " FOR UPDATE");
1285 			break;
1286 		case LCS_NONE:
1287 			break;
1288 	}
1289 
1290 	if (node->lockedRels)
1291 	{
1292 		string_append_char(str, " OF ");
1293 		_outNode(str, node->lockedRels);
1294 	}
1295 
1296 	switch (node->waitPolicy)
1297 	{
1298 		case LockWaitError:
1299 			string_append_char(str, " NOWAIT");
1300 			break;
1301 		case LockWaitSkip:
1302 			string_append_char(str, " SKIP LOCKED");
1303 			break;
1304 		case LockWaitBlock:
1305 			break;
1306 	}
1307 }
1308 
1309 static void
_outTriggerTransition(String * str,TriggerTransition * node)1310 _outTriggerTransition(String * str, TriggerTransition *node)
1311 {
1312 }
1313 
1314 static void
_outColumnDef(String * str,ColumnDef * node)1315 _outColumnDef(String * str, ColumnDef *node)
1316 {
1317 	string_append_char(str, "\"");
1318 	string_append_char(str, node->colname);
1319 	string_append_char(str, "\" ");
1320 	_outNode(str, node->typeName);
1321 	_outNode(str, node->constraints);
1322 }
1323 
1324 static void
_outTypeName(String * str,TypeName * node)1325 _outTypeName(String * str, TypeName *node)
1326 {
1327 
1328 	/*
1329 	 * don't quote SystemType name, because 1. char is not "char". 2. in 8.4,
1330 	 * interval with fields cause error. =# SELECT '1'::"interval" year;
1331 	 * ERROR:  syntax error at or near "year" LINE 1: SELECT '1'::"interval"
1332 	 * year;
1333 	 */
1334 	if (list_length(node->names) == 2 &&
1335 		strcmp("pg_catalog", strVal(linitial(node->names))) == 0)
1336 	{
1337 		string_append_char(str, strVal(lsecond(node->names)));
1338 
1339 		if (strcmp("interval", strVal(lsecond(node->names))) == 0)
1340 		{
1341 			if (node->typmods != NIL)
1342 			{
1343 				A_Const    *v = (A_Const *) linitial(node->typmods);
1344 				int			mask = v->val.val.ival;
1345 
1346 				/*
1347 				 * precision for SECOND field. backword comaptibility. use
1348 				 * `'1.2 second'::interval(0) second' not `'1.2
1349 				 * second'::interval second(0)'(standarad for 8.4).
1350 				 */
1351 				if ((INTERVAL_MASK(SECOND) & mask) &&
1352 					list_length(node->typmods) == 2)
1353 				{
1354 					string_append_char(str, "(");
1355 					_outAConst(str, lsecond(node->typmods));
1356 					string_append_char(str, ")");
1357 				}
1358 
1359 				/* optional fields */
1360 				if (mask == INTERVAL_MASK(YEAR))
1361 					string_append_char(str, " YEAR");
1362 				else if (mask == INTERVAL_MASK(MONTH))
1363 					string_append_char(str, " MONTH");
1364 				else if (mask == INTERVAL_MASK(DAY))
1365 					string_append_char(str, " DAY");
1366 				else if (mask == INTERVAL_MASK(HOUR))
1367 					string_append_char(str, " HOUR");
1368 				else if (mask == INTERVAL_MASK(MINUTE))
1369 					string_append_char(str, " MINUTE");
1370 				else if (mask == INTERVAL_MASK(SECOND))
1371 					string_append_char(str, " SECOND");
1372 				else if (mask == (INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH)))
1373 					string_append_char(str, " YEAR TO MONTH");
1374 				else if (mask == (INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR)))
1375 					string_append_char(str, " DAY TO HOUR");
1376 				else if (mask == (INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) |
1377 								  INTERVAL_MASK(MINUTE)))
1378 					string_append_char(str, " DAY TO MINUTE");
1379 				else if (mask == (INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) |
1380 								  INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND)))
1381 					string_append_char(str, " DAY TO SECOND");
1382 				else if (mask == (INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE)))
1383 					string_append_char(str, " HOUR TO MINUTE");
1384 				else if (mask == (INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) |
1385 								  INTERVAL_MASK(SECOND)))
1386 					string_append_char(str, " HOUR TO SECOND");
1387 				else if (mask == (INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND)))
1388 					string_append_char(str, " MINUTE TO SECOND");
1389 			}
1390 
1391 			return;
1392 		}
1393 	}
1394 	else
1395 	{
1396 		ListCell   *lc;
1397 		char		dot = 0;
1398 
1399 		foreach(lc, node->names)
1400 		{
1401 			Value	   *v = (Value *) lfirst(lc);
1402 			char	   *typename = v->val.str;
1403 
1404 			if (dot == 0)
1405 				dot = 1;
1406 			else
1407 				string_append_char(str, ".");
1408 			if (node->typemod < 0)
1409 			{
1410 				string_append_char(str, "\"");
1411 				string_append_char(str, typename);
1412 				string_append_char(str, "\"");
1413 			}
1414 			else
1415 				string_append_char(str, typename);
1416 		}
1417 	}
1418 
1419 	/* precisions */
1420 	if (node->typmods)
1421 	{
1422 		string_append_char(str, "(");
1423 		_outList(str, node->typmods);
1424 		string_append_char(str, ")");
1425 	}
1426 
1427 	if (node->arrayBounds != NIL)
1428 	{
1429 		ListCell   *lc;
1430 
1431 		foreach(lc, node->arrayBounds)
1432 		{
1433 			if (intVal(lfirst(lc)) == -1)
1434 				string_append_char(str, "[]");
1435 			else
1436 			{
1437 				string_append_char(str, "[");
1438 				_outNode(str, lfirst(lc));
1439 				string_append_char(str, "]");
1440 			}
1441 		}
1442 	}
1443 }
1444 
1445 static void
_outTypeCast(String * str,TypeCast * node)1446 _outTypeCast(String * str, TypeCast *node)
1447 {
1448 	_outNode(str, node->arg);
1449 	string_append_char(str, "::");
1450 	_outNode(str, node->typeName);
1451 
1452 }
1453 
1454 static void
_outCollateClause(String * str,const CollateClause * node)1455 _outCollateClause(String * str, const CollateClause *node)
1456 {
1457 	if (node->arg)
1458 		_outNode(str, node->arg);
1459 	string_append_char(str, " COLLATE ");
1460 	string_append_char(str, "\"");
1461 	string_append_char(str, ((Value *) linitial(node->collname))->val.str);
1462 	string_append_char(str, "\"");
1463 }
1464 
1465 static void
_outIndexElem(String * str,IndexElem * node)1466 _outIndexElem(String * str, IndexElem *node)
1467 {
1468 	if (node->name)
1469 	{
1470 		string_append_char(str, "\"");
1471 		string_append_char(str, node->name);
1472 		string_append_char(str, "\"");
1473 		if (node->opclass != NIL)
1474 			_outNode(str, node->opclass);
1475 	}
1476 	else
1477 	{
1478 		string_append_char(str, "(");
1479 		_outNode(str, node->expr);
1480 		string_append_char(str, ")");
1481 		if (node->opclass != NIL)
1482 			_outNode(str, node->opclass);
1483 	}
1484 }
1485 
1486 static void
_outGroupingSet(String * str,GroupingSet * node)1487 _outGroupingSet(String * str, GroupingSet *node)
1488 {
1489 	switch (node->kind)
1490 	{
1491 		case GROUPING_SET_EMPTY:
1492 			string_append_char(str, " (");
1493 			break;
1494 		case GROUPING_SET_ROLLUP:
1495 			string_append_char(str, " ROLLUP (");
1496 			_outNode(str, node->content);
1497 			break;
1498 		case GROUPING_SET_CUBE:
1499 			string_append_char(str, " CUBE (");
1500 			_outNode(str, node->content);
1501 			break;
1502 		case GROUPING_SET_SETS:
1503 			string_append_char(str, " GROUPING SETS (");
1504 			_outNode(str, node->content);
1505 			break;
1506 		default:
1507 			break;
1508 	}
1509 
1510 	string_append_char(str, " )");
1511 
1512 }
1513 
1514 static void
_outWithClause(String * str,WithClause * node)1515 _outWithClause(String * str, WithClause *node)
1516 {
1517 	string_append_char(str, " WITH ");
1518 	if (node->recursive)
1519 		string_append_char(str, "RECURSIVE ");
1520 
1521 	_outList(str, node->ctes);
1522 }
1523 
1524 static void
_outCommonTableExpr(String * str,CommonTableExpr * node)1525 _outCommonTableExpr(String * str, CommonTableExpr *node)
1526 {
1527 	string_append_char(str, "\"");
1528 	string_append_char(str, node->ctename);
1529 	string_append_char(str, "\" ");
1530 
1531 	if (node->aliascolnames)
1532 	{
1533 		string_append_char(str, "(");
1534 		_outIdList(str, node->aliascolnames);
1535 		string_append_char(str, ") ");
1536 	}
1537 
1538 	string_append_char(str, "AS ");
1539 
1540 	if (node->ctematerialized & CTEMaterializeAlways)
1541 		string_append_char(str, "MATERIALIZED ");
1542 	else if (node->ctematerialized & CTEMaterializeNever)
1543 		string_append_char(str, "NOT MATERIALIZED ");
1544 
1545 	string_append_char(str, "(");
1546 	_outNode(str, node->ctequery);
1547 	string_append_char(str, ")");
1548 }
1549 
1550 static void
_outSetOperationStmt(String * str,SetOperationStmt * node)1551 _outSetOperationStmt(String * str, SetOperationStmt *node)
1552 {
1553 
1554 }
1555 
1556 
1557 static void
_outTableSampleClause(String * str,TableSampleClause * node)1558 _outTableSampleClause(String * str, TableSampleClause *node)
1559 {
1560 
1561 }
1562 
1563 static void
_outAExpr(String * str,A_Expr * node)1564 _outAExpr(String * str, A_Expr *node)
1565 {
1566 	Value	   *v;
1567 
1568 	switch (node->kind)
1569 	{
1570 		case AEXPR_OP:
1571 			if (list_length(node->name) == 1)
1572 			{
1573 				Value	   *op = (Value *) lfirst(list_head(node->name));
1574 
1575 				string_append_char(str, " (");
1576 				_outNode(str, node->lexpr);
1577 				string_append_char(str, op->val.str);
1578 				_outNode(str, node->rexpr);
1579 				string_append_char(str, " )");
1580 			}
1581 			break;
1582 
1583 		case AEXPR_OP_ANY:
1584 			_outNode(str, node->lexpr);
1585 			v = linitial(node->name);
1586 			string_append_char(str, v->val.str);
1587 			string_append_char(str, "ANY(");
1588 			_outNode(str, node->rexpr);
1589 			string_append_char(str, ")");
1590 			break;
1591 
1592 		case AEXPR_OP_ALL:
1593 			_outNode(str, node->lexpr);
1594 			v = linitial(node->name);
1595 			string_append_char(str, v->val.str);
1596 			string_append_char(str, "ALL(");
1597 			_outNode(str, node->rexpr);
1598 			string_append_char(str, ")");
1599 			break;
1600 
1601 		case AEXPR_DISTINCT:
1602 			string_append_char(str, " (");
1603 			_outNode(str, node->lexpr);
1604 			string_append_char(str, " IS DISTINCT FROM ");
1605 			_outNode(str, node->rexpr);
1606 			string_append_char(str, ")");
1607 			break;
1608 
1609 		case AEXPR_NOT_DISTINCT:
1610 			string_append_char(str, " (");
1611 			_outNode(str, node->lexpr);
1612 			string_append_char(str, " IS NOT DISTINCT FROM ");
1613 			_outNode(str, node->rexpr);
1614 			string_append_char(str, ")");
1615 			break;
1616 
1617 		case AEXPR_NULLIF:
1618 			string_append_char(str, " NULLIF(");
1619 			_outNode(str, node->lexpr);
1620 			string_append_char(str, ", ");
1621 			_outNode(str, node->rexpr);
1622 			string_append_char(str, ")");
1623 			break;
1624 
1625 		case AEXPR_OF:
1626 			_outNode(str, node->lexpr);
1627 			v = linitial(node->name);
1628 			if (v->val.str[0] == '!')
1629 				string_append_char(str, " IS NOT OF (");
1630 			else
1631 				string_append_char(str, " IS OF (");
1632 			_outNode(str, node->rexpr);
1633 			string_append_char(str, ")");
1634 			break;
1635 
1636 		case AEXPR_IN:
1637 			_outNode(str, node->lexpr);
1638 			v = (Value *) lfirst(list_head(node->name));
1639 			if (v->val.str[0] == '=')
1640 				string_append_char(str, " IN (");
1641 			else
1642 				string_append_char(str, " NOT IN (");
1643 			_outNode(str, node->rexpr);
1644 			string_append_char(str, ")");
1645 			break;
1646 
1647 		case AEXPR_LIKE:
1648 			_outNode(str, node->lexpr);
1649 			v = (Value *) lfirst(list_head(node->name));
1650 			if (!strcmp(v->val.str, "~~"))
1651 				string_append_char(str, " LIKE ");
1652 			else
1653 				string_append_char(str, " NOT LIKE ");
1654 			if (IsA(node->rexpr, FuncCall))
1655 			{
1656 				FuncCall   *rexpr = (FuncCall *) node->rexpr;
1657 
1658 				_outNode(str, linitial(rexpr->args));
1659 				string_append_char(str, " ESCAPE ");
1660 				_outNode(str, lsecond(rexpr->args));
1661 			}
1662 			else
1663 				_outNode(str, node->rexpr);
1664 			break;
1665 
1666 		case AEXPR_ILIKE:
1667 			_outNode(str, node->lexpr);
1668 			v = (Value *) lfirst(list_head(node->name));
1669 			if (!strcmp(v->val.str, "~~*"))
1670 				string_append_char(str, " ILIKE ");
1671 			else
1672 				string_append_char(str, " NOT ILIKE ");
1673 			if (IsA(node->rexpr, FuncCall))
1674 			{
1675 				FuncCall   *rexpr = (FuncCall *) node->rexpr;
1676 
1677 				_outNode(str, linitial(rexpr->args));
1678 				string_append_char(str, " ESCAPE ");
1679 				_outNode(str, lsecond(rexpr->args));
1680 			}
1681 			else
1682 				_outNode(str, node->rexpr);
1683 			break;
1684 
1685 		case AEXPR_SIMILAR:
1686 			_outNode(str, node->lexpr);
1687 			v = (Value *) lfirst(list_head(node->name));
1688 			if (!strcmp(v->val.str, "~"))
1689 				string_append_char(str, " SIMILAR TO ");
1690 			else
1691 				string_append_char(str, " NOT SIMILAR TO ");
1692 			if (IsA(node->rexpr, FuncCall))
1693 			{
1694 				FuncCall   *rexpr = (FuncCall *) node->rexpr;
1695 
1696 				_outNode(str, linitial(rexpr->args));
1697 				string_append_char(str, " ESCAPE ");
1698 				_outNode(str, lsecond(rexpr->args));
1699 			}
1700 			else
1701 				_outNode(str, node->rexpr);
1702 			break;
1703 
1704 		case AEXPR_BETWEEN:
1705 			_outNode(str, node->lexpr);
1706 			string_append_char(str, " BETWEEN ");
1707 			_outNode(str, linitial((List *) node->rexpr));
1708 			string_append_char(str, " AND ");
1709 			_outNode(str, lsecond((List *) node->rexpr));
1710 			break;
1711 
1712 		case AEXPR_NOT_BETWEEN:
1713 			_outNode(str, node->lexpr);
1714 			string_append_char(str, " NOT BETWEEN ");
1715 			_outNode(str, linitial((List *) node->rexpr));
1716 			string_append_char(str, " AND ");
1717 			_outNode(str, lsecond((List *) node->rexpr));
1718 			break;
1719 
1720 		case AEXPR_BETWEEN_SYM:
1721 			_outNode(str, node->lexpr);
1722 			string_append_char(str, " BETWEEN SYMMETRIC ");
1723 			_outNode(str, linitial((List *) node->rexpr));
1724 			string_append_char(str, " AND ");
1725 			_outNode(str, lsecond((List *) node->rexpr));
1726 			break;
1727 
1728 		case AEXPR_NOT_BETWEEN_SYM:
1729 			_outNode(str, node->lexpr);
1730 			string_append_char(str, " NOT BETWEEN SYMMETRIC ");
1731 			_outNode(str, linitial((List *) node->rexpr));
1732 			string_append_char(str, " AND ");
1733 			_outNode(str, lsecond((List *) node->rexpr));
1734 			break;
1735 
1736 		case AEXPR_PAREN:
1737 			string_append_char(str, " ( ");
1738 			_outNode(str, node->lexpr);
1739 			string_append_char(str, " ) ");
1740 			break;
1741 
1742 		default:
1743 			break;
1744 	}
1745 }
1746 
1747 /*
1748  * Node types found in raw parse trees (supported for debug purposes)
1749  */
1750 
1751 static void
_outRawStmt(String * str,const RawStmt * node)1752 _outRawStmt(String * str, const RawStmt *node)
1753 {
1754 }
1755 
1756 static void
_outValue(String * str,Value * value)1757 _outValue(String * str, Value *value)
1758 {
1759 	char		buf[16];
1760 	char		*p;
1761 
1762 	switch (value->type)
1763 	{
1764 		case T_Integer:
1765 			sprintf(buf, "%d", value->val.ival);
1766 			string_append_char(str, buf);
1767 			break;
1768 
1769 		case T_Float:
1770 			string_append_char(str, value->val.str);
1771 			break;
1772 
1773 		case T_String:
1774 			string_append_char(str, "'");
1775 			p = escape_string(value->val.str);
1776 			string_append_char(str, p);
1777 			pfree(p);
1778 			string_append_char(str, "'");
1779 			break;
1780 
1781 		case T_Null:
1782 			string_append_char(str, "NULL");
1783 			break;
1784 
1785 		default:
1786 			break;
1787 	}
1788 }
1789 
1790 static void
_outColumnRef(String * str,ColumnRef * node)1791 _outColumnRef(String * str, ColumnRef *node)
1792 {
1793 	ListCell   *c;
1794 	char		first = 0;
1795 
1796 	foreach(c, node->fields)
1797 	{
1798 		Node	   *n = (Node *) lfirst(c);
1799 
1800 		if (IsA(n, String))
1801 		{
1802 			Value	   *v = (Value *) lfirst(c);
1803 
1804 			if (first == 0)
1805 				first = 1;
1806 			else
1807 				string_append_char(str, ".");
1808 
1809 			string_append_char(str, "\"");
1810 			string_append_char(str, v->val.str);
1811 			string_append_char(str, "\"");
1812 		}
1813 		else if (IsA(n, A_Star))
1814 		{
1815 			if (first == 0)
1816 				first = 1;
1817 			else
1818 				string_append_char(str, ".");
1819 
1820 			string_append_char(str, "*");
1821 		}
1822 	}
1823 }
1824 
1825 static void
_outParamRef(String * str,ParamRef * node)1826 _outParamRef(String * str, ParamRef *node)
1827 {
1828 	char		buf[16];
1829 
1830 	snprintf(buf, 16, "%d", node->number);
1831 	string_append_char(str, "$");
1832 	string_append_char(str, buf);
1833 }
1834 
1835 static void
_outAConst(String * str,A_Const * node)1836 _outAConst(String * str, A_Const *node)
1837 {
1838 	char		buf[16];
1839 	char		*p;
1840 
1841 	switch (node->val.type)
1842 	{
1843 		case T_Integer:
1844 			sprintf(buf, "%d", node->val.val.ival);
1845 			string_append_char(str, buf);
1846 			break;
1847 
1848 		case T_Float:
1849 			string_append_char(str, node->val.val.str);
1850 			break;
1851 
1852 		case T_String:
1853 			string_append_char(str, "'");
1854 			p = escape_string(node->val.val.str);
1855 			string_append_char(str, p);
1856 			pfree(p);
1857 			string_append_char(str, "'");
1858 			break;
1859 
1860 		case T_Null:
1861 			string_append_char(str, "NULL");
1862 			break;
1863 
1864 		default:
1865 			break;
1866 	}
1867 }
1868 
1869 static void
_outA_Indices(String * str,A_Indices * node)1870 _outA_Indices(String * str, A_Indices *node)
1871 {
1872 	string_append_char(str, "[");
1873 	if (node->lidx)
1874 	{
1875 		_outNode(str, node->lidx);
1876 		string_append_char(str, ":");
1877 	}
1878 	_outNode(str, node->uidx);
1879 	string_append_char(str, "]");
1880 }
1881 
1882 static void
_outA_Indirection(String * str,A_Indirection * node)1883 _outA_Indirection(String * str, A_Indirection *node)
1884 {
1885 	ListCell   *lc;
1886 
1887 	if (node->indirection != NIL)
1888 	{
1889 		if (IsA(node->arg, ParamRef))
1890 			/* "$1[1]" OR "$1.foo" */
1891 			_outParamRef(str, (ParamRef *) node->arg);
1892 		else
1893 		{
1894 			/* "(ARRAY[1])[1]" */
1895 			string_append_char(str, "(");
1896 			_outNode(str, node->arg);
1897 			string_append_char(str, ")");
1898 		}
1899 
1900 		foreach(lc, node->indirection)
1901 		{
1902 			Node	   *ind = lfirst(lc);
1903 
1904 			if (IsA(ind, A_Star))
1905 				/* foo.* */
1906 				string_append_char(str, ".*");
1907 			else if (IsA(ind, String))
1908 			{
1909 				/* foo.bar */
1910 				string_append_char(str, ".\"");
1911 				string_append_char(str, strVal(ind));
1912 				string_append_char(str, "\"");
1913 			}
1914 			else
1915 				/* foo[1] (A_Indices) */
1916 				_outNode(str, ind);
1917 		}
1918 	}
1919 }
1920 
1921 static void
_outA_ArrayExpr(String * str,A_ArrayExpr * node)1922 _outA_ArrayExpr(String * str, A_ArrayExpr *node)
1923 {
1924 	string_append_char(str, "ARRAY [");
1925 	_outNode(str, node->elements);
1926 	string_append_char(str, "]");
1927 }
1928 
1929 static void
_outResTarget(String * str,ResTarget * node)1930 _outResTarget(String * str, ResTarget *node)
1931 {
1932 	if (node->indirection != NIL)
1933 	{
1934 		string_append_char(str, "\"");
1935 		string_append_char(str, node->name);
1936 		string_append_char(str, "\"=");
1937 		_outNode(str, node->val);
1938 	}
1939 	else
1940 	{
1941 		_outNode(str, node->val);
1942 
1943 		if (node->name)
1944 		{
1945 			string_append_char(str, " AS ");
1946 			string_append_char(str, "\"");
1947 			string_append_char(str, node->name);
1948 			string_append_char(str, "\" ");
1949 		}
1950 	}
1951 }
1952 
1953 
1954 static void
_outMultiAssignRef(String * str,MultiAssignRef * node)1955 _outMultiAssignRef(String * str, MultiAssignRef *node)
1956 {
1957 	_outNode(str, node->source);
1958 }
1959 
1960 static void
_outWindowDef(String * str,WindowDef * node)1961 _outWindowDef(String * str, WindowDef *node)
1962 {
1963 	if (node->name)
1964 	{
1965 		string_append_char(str, "\"");
1966 		string_append_char(str, node->name);
1967 		string_append_char(str, "\" AS ");
1968 	}
1969 	string_append_char(str, "(");
1970 
1971 	if (node->refname)
1972 	{
1973 		string_append_char(str, "\"");
1974 		string_append_char(str, node->refname);
1975 		string_append_char(str, "\" ");
1976 	}
1977 
1978 	if (node->partitionClause)
1979 	{
1980 		string_append_char(str, " PARTITION BY ");
1981 		_outNode(str, node->partitionClause);
1982 	}
1983 
1984 	if (node->orderClause)
1985 	{
1986 		string_append_char(str, " ORDER BY ");
1987 		_outNode(str, node->orderClause);
1988 	}
1989 
1990 	if (node->frameOptions != FRAMEOPTION_DEFAULTS)
1991 	{
1992 		if (node->frameOptions & FRAMEOPTION_RANGE)
1993 			string_append_char(str, " RANGE");
1994 		else if (node->frameOptions & FRAMEOPTION_ROWS)
1995 			string_append_char(str, " ROWS");
1996 		else if (node->frameOptions & FRAMEOPTION_GROUPS)
1997 			string_append_char(str, " GROUPS");
1998 
1999 		if (node->frameOptions & FRAMEOPTION_BETWEEN)
2000 			string_append_char(str, " BETWEEN");
2001 
2002 		if (node->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
2003 			string_append_char(str, " UNBOUNDED PRECEDING");
2004 		else if (node->frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING)
2005 			string_append_char(str, " UNBOUNDED FOLLOWING");
2006 		else if (node->frameOptions & FRAMEOPTION_START_CURRENT_ROW)
2007 			string_append_char(str, " UNBOUNDED CURRENT ROW");
2008 		else if (node->frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING)
2009 		{
2010 			string_append_char(str, " ");
2011 			_outNode(str, node->startOffset);
2012 			string_append_char(str, " PRECEDING");
2013 		}
2014 		else if (node->frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING)
2015 		{
2016 			string_append_char(str, " ");
2017 			_outNode(str, node->startOffset);
2018 			string_append_char(str, " FOLLOWING");
2019 		}
2020 
2021 		if (node->frameOptions & FRAMEOPTION_BETWEEN)
2022 		{
2023 			string_append_char(str, " AND");
2024 			if (node->frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING)
2025 				string_append_char(str, " UNBOUNDED PRECEDING");
2026 			else if (node->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
2027 				string_append_char(str, " UNBOUNDED FOLLOWING");
2028 			else if (node->frameOptions & FRAMEOPTION_END_CURRENT_ROW)
2029 				string_append_char(str, " UNBOUNDED CURRENT ROW");
2030 			else if (node->frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING)
2031 			{
2032 				string_append_char(str, " ");
2033 				_outNode(str, node->endOffset);
2034 				string_append_char(str, " PRECEDING");
2035 			}
2036 			else if (node->frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING)
2037 			{
2038 				string_append_char(str, " ");
2039 				_outNode(str, node->endOffset);
2040 				string_append_char(str, " FOLLOWING");
2041 			}
2042 		}
2043 
2044 		if (node->frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW)
2045 		{
2046 			string_append_char(str, " EXCLUDE CURRENT ROW");
2047 		}
2048 		else if (node->frameOptions & FRAMEOPTION_EXCLUDE_GROUP)
2049 		{
2050 			string_append_char(str, " EXCLUDE GROUP");
2051 		}
2052 		else if (node->frameOptions & FRAMEOPTION_EXCLUDE_TIES)
2053 		{
2054 			string_append_char(str, " EXCLUDE TIES");
2055 		}
2056 	}
2057 	string_append_char(str, ")");
2058 }
2059 
2060 static void
_outConstraint(String * str,Constraint * node)2061 _outConstraint(String * str, Constraint *node)
2062 {
2063 	if (node->conname)
2064 	{
2065 		string_append_char(str, "CONSTRAINT \"");
2066 		string_append_char(str, node->conname);
2067 		string_append_char(str, "\"");
2068 	}
2069 
2070 	switch (node->contype)
2071 	{
2072 		case CONSTR_CHECK:
2073 			string_append_char(str, " CHECK (");
2074 			_outNode(str, node->raw_expr);
2075 			string_append_char(str, ")");
2076 			break;
2077 
2078 		case CONSTR_UNIQUE:
2079 			string_append_char(str, " UNIQUE");
2080 			if (node->keys)
2081 			{
2082 				string_append_char(str, "(");
2083 				_outIdList(str, node->keys);
2084 				string_append_char(str, ")");
2085 			}
2086 
2087 			if (node->options)
2088 			{
2089 				_outWithDefinition(str, node->options);
2090 			}
2091 
2092 			if (node->indexspace)
2093 			{
2094 				string_append_char(str, " USING INDEX TABLESPACE \"");
2095 				string_append_char(str, node->indexspace);
2096 				string_append_char(str, "\"");
2097 			}
2098 			break;
2099 
2100 		case CONSTR_PRIMARY:
2101 			string_append_char(str, " PRIMARY KEY");
2102 			if (node->keys)
2103 			{
2104 				string_append_char(str, "(");
2105 				_outIdList(str, node->keys);
2106 				string_append_char(str, ")");
2107 			}
2108 			if (node->options)
2109 				;
2110 
2111 			if (node->indexspace)
2112 			{
2113 				string_append_char(str, " USING INDEX TABLESPACE \"");
2114 				string_append_char(str, node->indexspace);
2115 				string_append_char(str, "\"");
2116 			}
2117 			break;
2118 
2119 		case CONSTR_FOREIGN:
2120 			if (node->fk_attrs != NIL)
2121 			{
2122 				string_append_char(str, " FOREIGN KEY(");
2123 				_outIdList(str, node->fk_attrs);
2124 				string_append_char(str, ")");
2125 			}
2126 
2127 			string_append_char(str, " REFERENCES ");
2128 			_outNode(str, node->pktable);
2129 
2130 			if (node->pk_attrs != NIL)
2131 			{
2132 				string_append_char(str, "(");
2133 				_outIdList(str, node->pk_attrs);
2134 				string_append_char(str, ")");
2135 			}
2136 
2137 			switch (node->fk_matchtype)
2138 			{
2139 				case FKCONSTR_MATCH_FULL:
2140 					string_append_char(str, " MATCH FULL");
2141 					break;
2142 
2143 				case FKCONSTR_MATCH_PARTIAL:
2144 					string_append_char(str, " MATCH PARTIAL");
2145 					break;
2146 
2147 				default:
2148 					break;
2149 			}
2150 
2151 			switch (node->fk_upd_action)
2152 			{
2153 				case FKCONSTR_ACTION_RESTRICT:
2154 					string_append_char(str, " ON UPDATE RESTRICT");
2155 					break;
2156 
2157 				case FKCONSTR_ACTION_CASCADE:
2158 					string_append_char(str, " ON UPDATE CASCADE");
2159 					break;
2160 
2161 				case FKCONSTR_ACTION_SETNULL:
2162 					string_append_char(str, " ON UPDATE SET NULL");
2163 					break;
2164 
2165 				case FKCONSTR_ACTION_SETDEFAULT:
2166 					string_append_char(str, " ON UPDATE SET DEFAULT");
2167 					break;
2168 
2169 				default:
2170 					break;
2171 			}
2172 
2173 			switch (node->fk_del_action)
2174 			{
2175 				case FKCONSTR_ACTION_RESTRICT:
2176 					string_append_char(str, " ON DELETE RESTRICT");
2177 					break;
2178 
2179 				case FKCONSTR_ACTION_CASCADE:
2180 					string_append_char(str, " ON DELETE CASCADE");
2181 					break;
2182 
2183 				case FKCONSTR_ACTION_SETNULL:
2184 					string_append_char(str, " ON DELETE SET NULL");
2185 					break;
2186 
2187 				case FKCONSTR_ACTION_SETDEFAULT:
2188 					string_append_char(str, " ON DELETE SET DEFAULT");
2189 					break;
2190 
2191 				default:
2192 					break;
2193 			}
2194 
2195 			if (node->deferrable)
2196 				string_append_char(str, " DEFERRABLE");
2197 
2198 			if (node->initdeferred)
2199 				string_append_char(str, " INITIALLY DEFERRED");
2200 			break;
2201 
2202 		case CONSTR_NOTNULL:
2203 			string_append_char(str, " NOT NULL");
2204 			break;
2205 
2206 		case CONSTR_NULL:
2207 			string_append_char(str, " NULL");
2208 			break;
2209 
2210 		case CONSTR_DEFAULT:
2211 			string_append_char(str, "DEFAULT ");
2212 			_outNode(str, node->raw_expr);
2213 			break;
2214 
2215 		default:
2216 			break;
2217 	}
2218 }
2219 
2220 
2221 static void
_outSortBy(String * str,SortBy * node)2222 _outSortBy(String * str, SortBy *node)
2223 {
2224 	_outNode(str, node->node);
2225 
2226 	if (node->sortby_dir == SORTBY_USING)
2227 	{
2228 		string_append_char(str, " USING ");
2229 		_outNode(str, node->useOp);
2230 	}
2231 	else if (node->sortby_dir == SORTBY_DESC)
2232 		string_append_char(str, " DESC ");
2233 
2234 	if (node->sortby_nulls == SORTBY_NULLS_FIRST)
2235 		string_append_char(str, " NULLS FIRST ");
2236 	else if (node->sortby_nulls == SORTBY_NULLS_LAST)
2237 		string_append_char(str, " NULLS LAST ");
2238 }
2239 
2240 static void
_outInsertStmt(String * str,InsertStmt * node)2241 _outInsertStmt(String * str, InsertStmt *node)
2242 {
2243 	if (node->withClause)
2244 		_outWithClause(str, node->withClause);
2245 
2246 	string_append_char(str, "INSERT INTO ");
2247 	_outNode(str, node->relation);
2248 
2249 	if (node->cols == NIL && node->selectStmt == NULL)
2250 		string_append_char(str, " DEFAULT VALUES");
2251 
2252 	if (node->cols)
2253 	{
2254 		char		comma = 0;
2255 		ListCell   *lc;
2256 
2257 		string_append_char(str, "(");
2258 
2259 		foreach(lc, node->cols)
2260 		{
2261 			ResTarget  *node = lfirst(lc);
2262 			ListCell   *lc_ind;
2263 
2264 			if (comma == 0)
2265 				comma = 1;
2266 			else
2267 				string_append_char(str, ", ");
2268 
2269 			string_append_char(str, "\"");
2270 			string_append_char(str, node->name);
2271 			string_append_char(str, "\"");
2272 
2273 			foreach(lc_ind, node->indirection)
2274 			{
2275 				Node	   *ind = lfirst(lc_ind);
2276 
2277 				if (IsA(ind, String))
2278 				{
2279 					/* foo.bar */
2280 					string_append_char(str, ".\"");
2281 					string_append_char(str, strVal(ind));
2282 					string_append_char(str, "\"");
2283 				}
2284 				else
2285 					/* foo[1] (A_Indices) */
2286 					_outNode(str, ind);
2287 			}
2288 		}
2289 		string_append_char(str, ")");
2290 	}
2291 
2292 	if (node->selectStmt)
2293 	{
2294 		_outNode(str, node->selectStmt);
2295 	}
2296 
2297 	if (node->onConflictClause)
2298 	{
2299 		_outOnConflictClause(str, node->onConflictClause);
2300 	}
2301 
2302 	if (node->returningList)
2303 	{
2304 		string_append_char(str, " RETURNING ");
2305 		_outNode(str, node->returningList);
2306 	}
2307 }
2308 
2309 static void
_outSetClause(String * str,List * node)2310 _outSetClause(String * str, List *node)
2311 {
2312 	ListCell   *lc;
2313 	char		comma = 0;
2314 
2315 	ResTarget  *first = linitial(node);
2316 
2317 	string_append_char(str, " SET ");
2318 
2319 	if (IsA(first->val, MultiAssignRef))
2320 	{
2321 		string_append_char(str, "(");
2322 		foreach(lc, node)
2323 		{
2324 			ResTarget  *node = lfirst(lc);
2325 			ListCell   *lc_ind;
2326 
2327 			if (comma == 0)
2328 				comma = 1;
2329 			else
2330 				string_append_char(str, ", ");
2331 
2332 			string_append_char(str, "\"");
2333 			string_append_char(str, node->name);
2334 			string_append_char(str, "\"");
2335 
2336 			foreach(lc_ind, node->indirection)
2337 			{
2338 				Node	   *ind = lfirst(lc_ind);
2339 
2340 				if (IsA(ind, String))
2341 				{
2342 					string_append_char(str, ".\"");
2343 					string_append_char(str, strVal(ind));
2344 					string_append_char(str, "\"");
2345 				}
2346 				else
2347 					/* foo[1] (A_Indices) */
2348 					_outNode(str, ind);
2349 			}
2350 		}
2351 		string_append_char(str, ") = ");
2352 
2353 		_outNode(str, first->val);
2354 
2355 	}
2356 	else
2357 	{
2358 		foreach(lc, node)
2359 		{
2360 			ResTarget  *node = lfirst(lc);
2361 			ListCell   *lc_ind;
2362 
2363 			if (comma == 0)
2364 				comma = 1;
2365 			else
2366 				string_append_char(str, ", ");
2367 
2368 			string_append_char(str, "\"");
2369 			string_append_char(str, node->name);
2370 			string_append_char(str, "\"");
2371 
2372 			foreach(lc_ind, node->indirection)
2373 			{
2374 				Node	   *ind = lfirst(lc_ind);
2375 
2376 				if (IsA(ind, String))
2377 				{
2378 					string_append_char(str, ".\"");
2379 					string_append_char(str, strVal(ind));
2380 					string_append_char(str, "\"");
2381 				}
2382 				else
2383 					/* foo[1] (A_Indices) */
2384 					_outNode(str, ind);
2385 			}
2386 
2387 			string_append_char(str, " = ");
2388 			_outNode(str, node->val);
2389 		}
2390 	}
2391 }
2392 
2393 static void
_outUpdateStmt(String * str,UpdateStmt * node)2394 _outUpdateStmt(String * str, UpdateStmt *node)
2395 {
2396 	if (node->withClause)
2397 		_outWithClause(str, node->withClause);
2398 
2399 	string_append_char(str, "UPDATE ");
2400 
2401 	_outNode(str, node->relation);
2402 
2403 	_outSetClause(str, node->targetList);
2404 
2405 	if (node->fromClause)
2406 	{
2407 		string_append_char(str, " FROM ");
2408 		_outNode(str, node->fromClause);
2409 	}
2410 
2411 	if (node->whereClause)
2412 	{
2413 		string_append_char(str, " WHERE ");
2414 		_outNode(str, node->whereClause);
2415 	}
2416 
2417 	if (node->returningList)
2418 	{
2419 		string_append_char(str, " RETURNING ");
2420 		_outNode(str, node->returningList);
2421 	}
2422 }
2423 
2424 static void
_outDeleteStmt(String * str,DeleteStmt * node)2425 _outDeleteStmt(String * str, DeleteStmt *node)
2426 {
2427 	if (node->withClause)
2428 		_outWithClause(str, node->withClause);
2429 
2430 	string_append_char(str, "DELETE FROM ");
2431 
2432 	_outNode(str, node->relation);
2433 
2434 	if (node->usingClause)
2435 	{
2436 		string_append_char(str, " USING ");
2437 		_outNode(str, node->usingClause);
2438 	}
2439 
2440 	if (node->whereClause)
2441 	{
2442 		string_append_char(str, " WHERE ");
2443 		_outNode(str, node->whereClause);
2444 	}
2445 
2446 	if (node->returningList)
2447 	{
2448 		string_append_char(str, " RETURNING ");
2449 		_outNode(str, node->returningList);
2450 	}
2451 }
2452 
2453 static void
_outTransactionStmt(String * str,TransactionStmt * node)2454 _outTransactionStmt(String * str, TransactionStmt *node)
2455 {
2456 	switch (node->kind)
2457 	{
2458 		case TRANS_STMT_BEGIN:
2459 			string_append_char(str, "BEGIN ");
2460 			break;
2461 
2462 		case TRANS_STMT_START:
2463 			string_append_char(str, "START TRANSACTION ");
2464 			break;
2465 
2466 		case TRANS_STMT_COMMIT:
2467 			string_append_char(str, "COMMIT ");
2468 			break;
2469 
2470 		case TRANS_STMT_ROLLBACK:
2471 			string_append_char(str, "ABORT ");
2472 			break;
2473 
2474 		case TRANS_STMT_SAVEPOINT:
2475 			string_append_char(str, "SAVEPOINT ");
2476 			break;
2477 
2478 		case TRANS_STMT_RELEASE:
2479 			string_append_char(str, "RELEASE ");
2480 			break;
2481 
2482 		case TRANS_STMT_ROLLBACK_TO:
2483 			string_append_char(str, "ROLLBACK TO ");
2484 			break;
2485 
2486 		case TRANS_STMT_PREPARE:
2487 			string_append_char(str, "PREPARE TRANSACTION ");
2488 			break;
2489 
2490 		case TRANS_STMT_COMMIT_PREPARED:
2491 			string_append_char(str, "COMMIT PREPARED ");
2492 			break;
2493 
2494 		case TRANS_STMT_ROLLBACK_PREPARED:
2495 			string_append_char(str, "ROLLBACK PREPARED ");
2496 			break;
2497 
2498 		default:
2499 			break;
2500 	}
2501 
2502 	if (node->options)
2503 		_outSetTransactionModeList(str, node->options);
2504 
2505 	if (node->gid)
2506 		string_append_char(str, node->gid);
2507 }
2508 
2509 
2510 static void
_outTruncateStmt(String * str,TruncateStmt * node)2511 _outTruncateStmt(String * str, TruncateStmt *node)
2512 {
2513 	string_append_char(str, "TRUNCATE ");
2514 	_outNode(str, node->relations);
2515 }
2516 
2517 static void
_outVacuumStmt(String * str,VacuumStmt * node)2518 _outVacuumStmt(String * str, VacuumStmt *node)
2519 {
2520 
2521 	VacuumParams params;
2522 	params.options = node->is_vacuumcmd ? VACOPT_VACUUM : VACOPT_ANALYZE;
2523 
2524 	if (params.options & VACOPT_VACUUM)
2525 		string_append_char(str, "VACUUM ");
2526 	else
2527 		string_append_char(str, "ANALYZE ");
2528 
2529 	if (params.options & VACOPT_FULL)
2530 		string_append_char(str, "FULL ");
2531 
2532 	if (params.options & VACOPT_FREEZE)
2533 		string_append_char(str, "FREEZE ");
2534 
2535 	if (params.options & VACOPT_VERBOSE)
2536 		string_append_char(str, "VERBOSE ");
2537 
2538 	if (params.options & VACOPT_VACUUM && params.options & VACOPT_ANALYZE)
2539 		string_append_char(str, "ANALYZE ");
2540 
2541 	if (params.options & VACOPT_DISABLE_PAGE_SKIPPING)
2542 		string_append_char(str, "DISABLE_PAGE_SKIPPING ");
2543 
2544 	if (params.options & VACOPT_SKIP_LOCKED)
2545 		string_append_char(str, "SKIP_LOCKED ");
2546 
2547 	ListCell   *lc;
2548 	foreach(lc, node->rels)
2549 	{
2550 		VacuumRelation *vrel = lfirst_node(VacuumRelation, lc);
2551 
2552 		_outNode(str, vrel->relation);
2553 		if (vrel->va_cols)
2554 		{
2555 			string_append_char(str, "(");
2556 			_outIdList(str, vrel->va_cols);
2557 			string_append_char(str, ") ");
2558 		}
2559 	}
2560 }
2561 
2562 static void
_outExplainStmt(String * str,ExplainStmt * node)2563 _outExplainStmt(String * str, ExplainStmt *node)
2564 {
2565 	ListCell   *lc;
2566 
2567 	string_append_char(str, "EXPLAIN ");
2568 
2569 	if (server_version_num < 90000)
2570 	{
2571 		foreach(lc, node->options)
2572 		{
2573 			DefElem    *opt = (DefElem *) lfirst(lc);
2574 
2575 			if (strcmp(opt->defname, "analyze") == 0)
2576 				string_append_char(str, "ANALYZE ");
2577 			else if (strcmp(opt->defname, "verbose") == 0)
2578 				string_append_char(str, "VERBOSE ");
2579 		}
2580 	}
2581 	else
2582 	{
2583 		if (node->options)
2584 		{
2585 			string_append_char(str, "(");
2586 			foreach(lc, node->options)
2587 			{
2588 				DefElem    *opt = (DefElem *) lfirst(lc);
2589 
2590 				if (list_head(node->options) != lc)
2591 					string_append_char(str, ", ");
2592 
2593 				string_append_char(str, opt->defname);
2594 				string_append_char(str, " ");
2595 				if (opt->arg)
2596 					_outValue(str, (Value *) opt->arg);
2597 			}
2598 			string_append_char(str, ")");
2599 		}
2600 	}
2601 
2602 	_outNode(str, node->query);
2603 }
2604 
2605 static void
_outClusterStmt(String * str,ClusterStmt * node)2606 _outClusterStmt(String * str, ClusterStmt *node)
2607 {
2608 	string_append_char(str, "CLUSTER ");
2609 
2610 	if (node->indexname)
2611 	{
2612 		string_append_char(str, "\"");
2613 		string_append_char(str, node->indexname);
2614 		string_append_char(str, "\" ON ");
2615 	}
2616 	if (node->relation)
2617 		_outNode(str, node->relation);
2618 }
2619 
2620 static void
_outCheckPointStmt(String * str,CheckPointStmt * node)2621 _outCheckPointStmt(String * str, CheckPointStmt *node)
2622 {
2623 	string_append_char(str, "CHECKPOINT");
2624 }
2625 
2626 static void
_outClosePortalStmt(String * str,ClosePortalStmt * node)2627 _outClosePortalStmt(String * str, ClosePortalStmt *node)
2628 {
2629 	string_append_char(str, "CLOSE ");
2630 	string_append_char(str, "\"");
2631 	string_append_char(str, node->portalname);
2632 	string_append_char(str, "\"");
2633 }
2634 
2635 static void
_outListenStmt(String * str,ListenStmt * node)2636 _outListenStmt(String * str, ListenStmt *node)
2637 {
2638 	string_append_char(str, "LISTEN ");
2639 	string_append_char(str, "\"");
2640 	string_append_char(str, node->conditionname);
2641 	string_append_char(str, "\"");
2642 }
2643 
2644 static void
_outUnlistenStmt(String * str,UnlistenStmt * node)2645 _outUnlistenStmt(String * str, UnlistenStmt *node)
2646 {
2647 	string_append_char(str, "UNLISTEN ");
2648 	if (node->conditionname == NULL)
2649 		string_append_char(str, "*");
2650 	else
2651 	{
2652 		string_append_char(str, "\"");
2653 		string_append_char(str, node->conditionname);
2654 		string_append_char(str, "\"");
2655 	}
2656 }
2657 
2658 static void
_outLoadStmt(String * str,LoadStmt * node)2659 _outLoadStmt(String * str, LoadStmt *node)
2660 {
2661 	string_append_char(str, "LOAD '");
2662 	string_append_char(str, node->filename);
2663 	string_append_char(str, "'");
2664 }
2665 
2666 static void
_outCopyStmt(String * str,CopyStmt * node)2667 _outCopyStmt(String * str, CopyStmt *node)
2668 {
2669 	ListCell   *lc;
2670 
2671 	string_append_char(str, "COPY ");
2672 
2673 	if (node->query)
2674 	{
2675 		string_append_char(str, "(");
2676 		_outNode(str, node->query);
2677 		string_append_char(str, ")");
2678 	}
2679 
2680 	_outNode(str, node->relation);
2681 
2682 	if (node->attlist)
2683 	{
2684 		string_append_char(str, "(");
2685 		_outIdList(str, node->attlist);
2686 		string_append_char(str, ")");
2687 	}
2688 
2689 	if (node->is_from == TRUE)
2690 		string_append_char(str, " FROM ");
2691 	else
2692 		string_append_char(str, " TO ");
2693 
2694 	if (node->filename)
2695 	{
2696 		string_append_char(str, "'");
2697 		string_append_char(str, node->filename);
2698 		string_append_char(str, "' ");
2699 	}
2700 	else
2701 		string_append_char(str, node->is_from == TRUE ? "STDIN " : "STDOUT ");
2702 
2703 	if (server_version_num < 90000)
2704 	{
2705 		foreach(lc, node->options)
2706 		{
2707 			DefElem    *e = lfirst(lc);
2708 
2709 			if (strcmp(e->defname, "format") == 0)
2710 			{
2711 				char	   *fmt = strVal(e->arg);
2712 
2713 				if (strcmp(fmt, "text") == 0)
2714 					;
2715 				else if (strcmp(fmt, "binary") == 0)
2716 					string_append_char(str, "BINARY ");
2717 				else if (strcmp(fmt, "csv") == 0)
2718 					string_append_char(str, "CSV ");
2719 			}
2720 			else if (strcmp(e->defname, "oids") == 0)
2721 				string_append_char(str, "OIDS ");
2722 			else if (strcmp(e->defname, "delimiter") == 0)
2723 			{
2724 				string_append_char(str, "DELIMITERS ");
2725 				_outValue(str, (Value *) e->arg);
2726 				string_append_char(str, " ");
2727 			}
2728 			else if (strcmp(e->defname, "null") == 0)
2729 			{
2730 				string_append_char(str, "NULL ");
2731 				_outValue(str, (Value *) e->arg);
2732 				string_append_char(str, " ");
2733 			}
2734 			else if (strcmp(e->defname, "header") == 0)
2735 				string_append_char(str, "HEADER ");
2736 			else if (strcmp(e->defname, "quote") == 0)
2737 			{
2738 				string_append_char(str, "QUOTE ");
2739 				_outValue(str, (Value *) e->arg);
2740 				string_append_char(str, " ");
2741 			}
2742 			else if (strcmp(e->defname, "escape") == 0)
2743 			{
2744 				string_append_char(str, "ESCAPE ");
2745 				_outValue(str, (Value *) e->arg);
2746 				string_append_char(str, " ");
2747 			}
2748 			else if (strcmp(e->defname, "force_quote") == 0)
2749 			{
2750 				string_append_char(str, "FORCE QUOTE ");
2751 				_outIdList(str, (List *) e->arg);
2752 			}
2753 			else if (strcmp(e->defname, "force_not_null") == 0)
2754 			{
2755 				string_append_char(str, "FORCE NOT NULL ");
2756 				_outIdList(str, (List *) e->arg);
2757 			}
2758 		}
2759 	}
2760 	else
2761 	{
2762 		/* version_num >= 90000 */
2763 		if (node->options)
2764 		{
2765 			string_append_char(str, "(");
2766 
2767 			foreach(lc, node->options)
2768 			{
2769 				DefElem    *e = lfirst(lc);
2770 
2771 				if (list_head(node->options) != lc)
2772 					string_append_char(str, ", ");
2773 
2774 				string_append_char(str, e->defname);
2775 				string_append_char(str, " ");
2776 
2777 				if (strcmp(e->defname, "format") == 0
2778 					|| strcmp(e->defname, "oids") == 0
2779 					|| strcmp(e->defname, "delimiter") == 0
2780 					|| strcmp(e->defname, "null") == 0
2781 					|| strcmp(e->defname, "header") == 0
2782 					|| strcmp(e->defname, "quote") == 0
2783 					|| strcmp(e->defname, "escape") == 0)
2784 					_outValue(str, (Value *) e->arg);
2785 				else if (strcmp(e->defname, "force_not_null") == 0)
2786 				{
2787 					string_append_char(str, "(");
2788 					_outIdList(str, (List *) e->arg);
2789 					string_append_char(str, ")");
2790 				}
2791 				else if (strcmp(e->defname, "force_quote") == 0)
2792 				{
2793 					if (IsA(e->arg, A_Star))
2794 						string_append_char(str, "*");
2795 					else if (IsA(e->arg, List))
2796 					{
2797 						string_append_char(str, "(");
2798 						_outIdList(str, (List *) e->arg);
2799 						string_append_char(str, ")");
2800 					}
2801 				}
2802 			}
2803 			string_append_char(str, ")");
2804 		}
2805 	}
2806 
2807 	if (node->whereClause)
2808 	{
2809 		string_append_char(str, " WHERE ");
2810 		_outNode(str, node->whereClause);
2811 	}
2812 }
2813 
2814 static void
_outDeallocateStmt(String * str,DeallocateStmt * node)2815 _outDeallocateStmt(String * str, DeallocateStmt *node)
2816 {
2817 	string_append_char(str, "DEALLOCATE \"");
2818 	string_append_char(str, node->name);
2819 	string_append_char(str, "\"");
2820 }
2821 
2822 static void
_outRenameStmt(String * str,RenameStmt * node)2823 _outRenameStmt(String * str, RenameStmt *node)
2824 {
2825 	ListCell   *lc;
2826 	char		comma = 0;
2827 
2828 	string_append_char(str, "ALTER ");
2829 
2830 	switch (node->renameType)
2831 	{
2832 		case OBJECT_AGGREGATE:
2833 			string_append_char(str, "AGGREGATE ");
2834 			_outNode(str, node->object);
2835 			string_append_char(str, " (");
2836 			string_append_char(str, ") RENAME TO \"");
2837 			string_append_char(str, node->newname);
2838 			string_append_char(str, "\"");
2839 			break;
2840 
2841 		case OBJECT_CONVERSION:
2842 			string_append_char(str, "CONVERSION ");
2843 			_outNode(str, node->object);
2844 			string_append_char(str, " RENAME TO \"");
2845 			string_append_char(str, node->newname);
2846 			string_append_char(str, "\"");
2847 			break;
2848 
2849 		case OBJECT_DATABASE:
2850 			string_append_char(str, "DATABASE \"");
2851 			string_append_char(str, node->subname);
2852 			string_append_char(str, "\" RENAME TO \"");
2853 			string_append_char(str, node->newname);
2854 			string_append_char(str, "\"");
2855 			break;
2856 
2857 		case OBJECT_FUNCTION:
2858 			string_append_char(str, "FUNCTION ");
2859 
2860 			foreach(lc, castNode(List, node->object))
2861 			{
2862 				Node	   *n = lfirst(lc);
2863 
2864 				if (IsA(n, String))
2865 				{
2866 					Value	   *value = (Value *) n;
2867 
2868 					if (comma == 0)
2869 						comma = 1;
2870 					else
2871 						string_append_char(str, ".");
2872 					string_append_char(str, "\"");
2873 					string_append_char(str, value->val.str);
2874 					string_append_char(str, "\"");
2875 				}
2876 				else
2877 					_outNode(str, n);
2878 			}
2879 
2880 			string_append_char(str, "(");
2881 			string_append_char(str, ")");
2882 			string_append_char(str, " RENAME TO \"");
2883 			string_append_char(str, node->newname);
2884 			string_append_char(str, "\"");
2885 			break;
2886 
2887 		case OBJECT_ROLE:
2888 			string_append_char(str, "ROLE \"");
2889 			string_append_char(str, node->subname);
2890 			string_append_char(str, "\" RENAME TO \"");
2891 			string_append_char(str, node->newname);
2892 			string_append_char(str, "\"");
2893 			break;
2894 
2895 		case OBJECT_LANGUAGE:
2896 			string_append_char(str, "LANGUAGE \"");
2897 			string_append_char(str, node->subname);
2898 			string_append_char(str, "\" RENAME TO \"");
2899 			string_append_char(str, node->newname);
2900 			string_append_char(str, "\"");
2901 			break;
2902 
2903 		case OBJECT_OPCLASS:
2904 			string_append_char(str, "OPERATOR CLASS ");
2905 			_outNode(str, node->object);
2906 			string_append_char(str, " USING ");
2907 			string_append_char(str, node->subname);
2908 			string_append_char(str, " RENAME TO \"");
2909 			string_append_char(str, node->newname);
2910 			string_append_char(str, "\"");
2911 			break;
2912 
2913 		case OBJECT_SCHEMA:
2914 			string_append_char(str, "SCHEMA \"");
2915 			string_append_char(str, node->subname);
2916 			string_append_char(str, "\" RENAME TO \"");
2917 			string_append_char(str, node->newname);
2918 			string_append_char(str, "\"");
2919 			break;
2920 
2921 		case OBJECT_TABLE:
2922 			string_append_char(str, "TABLE ");
2923 			_outNode(str, node->relation);
2924 			string_append_char(str, " RENAME TO \"");
2925 			string_append_char(str, node->newname);
2926 			string_append_char(str, "\"");
2927 			break;
2928 
2929 		case OBJECT_INDEX:
2930 			string_append_char(str, "INDEX ");
2931 			_outNode(str, node->relation);
2932 			string_append_char(str, " RENAME TO \"");
2933 			string_append_char(str, node->newname);
2934 			string_append_char(str, "\"");
2935 			break;
2936 
2937 		case OBJECT_COLUMN:
2938 			string_append_char(str, "TABLE ");
2939 			_outNode(str, node->relation);
2940 			string_append_char(str, " RENAME \"");
2941 			string_append_char(str, node->subname);
2942 			string_append_char(str, "\" TO \"");
2943 			string_append_char(str, node->newname);
2944 			string_append_char(str, "\"");
2945 			break;
2946 
2947 		case OBJECT_TRIGGER:
2948 			string_append_char(str, "TRIGGER \"");
2949 			string_append_char(str, node->subname);
2950 			string_append_char(str, "\" ON ");
2951 			_outNode(str, node->relation);
2952 			string_append_char(str, " RENAME TO \"");
2953 			string_append_char(str, node->newname);
2954 			string_append_char(str, "\"");
2955 			break;
2956 
2957 		case OBJECT_TABLESPACE:
2958 			string_append_char(str, "TABLESPACE \"");
2959 			string_append_char(str, node->subname);
2960 			string_append_char(str, "\" RENAME TO \"");
2961 			string_append_char(str, node->newname);
2962 			string_append_char(str, "\"");
2963 			break;
2964 
2965 		default:
2966 			break;
2967 	}
2968 }
2969 
2970 static void
_outOptRoleList(String * str,List * options)2971 _outOptRoleList(String * str, List *options)
2972 {
2973 	ListCell   *lc;
2974 
2975 	foreach(lc, options)
2976 	{
2977 		DefElem    *elem = lfirst(lc);
2978 		Value	   *value = (Value *) elem->arg;
2979 
2980 		if (strcmp(elem->defname, "password") == 0)
2981 		{
2982 			if (value == NULL)
2983 				string_append_char(str, " PASSWORD NULL");
2984 			else
2985 			{
2986 				string_append_char(str, " PASSWORD '");
2987 				string_append_char(str, value->val.str);
2988 				string_append_char(str, "'");
2989 			}
2990 		}
2991 		else if (strcmp(elem->defname, "encryptedPassword") == 0)
2992 		{
2993 			string_append_char(str, " ENCRYPTED PASSWORD '");
2994 			string_append_char(str, value->val.str);
2995 			string_append_char(str, "'");
2996 		}
2997 		else if (strcmp(elem->defname, "unencryptedPassword") == 0)
2998 		{
2999 			string_append_char(str, " UNENCRYPTED PASSWORD '");
3000 			string_append_char(str, value->val.str);
3001 			string_append_char(str, "'");
3002 		}
3003 		else if (strcmp(elem->defname, "superuser") == 0)
3004 		{
3005 			if (value->val.ival == TRUE)
3006 				string_append_char(str, " SUPERUSER");
3007 			else
3008 				string_append_char(str, " NOSUPERUSER");
3009 		}
3010 		else if (strcmp(elem->defname, "inherit") == 0)
3011 		{
3012 			if (value->val.ival == TRUE)
3013 				string_append_char(str, " INHERIT");
3014 			else
3015 				string_append_char(str, " NOINHERIT");
3016 		}
3017 		else if (strcmp(elem->defname, "createdb") == 0)
3018 		{
3019 			if (value->val.ival == TRUE)
3020 				string_append_char(str, " CREATEDB");
3021 			else
3022 				string_append_char(str, " NOCREATEDB");
3023 		}
3024 		else if (strcmp(elem->defname, "createrole") == 0)
3025 		{
3026 			if (value->val.ival == TRUE)
3027 				string_append_char(str, " CREATEROLE");
3028 			else
3029 				string_append_char(str, " NOCREATEROLE");
3030 		}
3031 		else if (strcmp(elem->defname, "canlogin") == 0)
3032 		{
3033 			if (value->val.ival == TRUE)
3034 				string_append_char(str, " LOGIN");
3035 			else
3036 				string_append_char(str, " NOLOGIN");
3037 		}
3038 		else if (strcmp(elem->defname, "connectionlimit") == 0)
3039 		{
3040 			char		buf[16];
3041 
3042 			string_append_char(str, " CONNECTION LIMIT ");
3043 			snprintf(buf, 16, "%d", value->val.ival);
3044 			string_append_char(str, buf);
3045 		}
3046 		else if (strcmp(elem->defname, "validUntil") == 0)
3047 		{
3048 			string_append_char(str, " VALID UNTIL '");
3049 			string_append_char(str, value->val.str);
3050 			string_append_char(str, "'");
3051 		}
3052 		else if (strcmp(elem->defname, "rolemembers") == 0)
3053 		{
3054 			string_append_char(str, " ROLE ");
3055 			_outIdList(str, (List *) elem->arg);
3056 		}
3057 		else if (strcmp(elem->defname, "sysid") == 0)
3058 		{
3059 			char		buf[16];
3060 
3061 			string_append_char(str, " SYSID ");
3062 			snprintf(buf, 16, "%d", value->val.ival);
3063 			string_append_char(str, buf);
3064 		}
3065 		else if (strcmp(elem->defname, "adminmembers") == 0)
3066 		{
3067 			string_append_char(str, " ADMIN ");
3068 			_outIdList(str, (List *) elem->arg);
3069 		}
3070 		else if (strcmp(elem->defname, "addroleto") == 0)
3071 		{
3072 			string_append_char(str, " IN ROLE ");
3073 			_outIdList(str, (List *) elem->arg);
3074 		}
3075 	}
3076 }
3077 
3078 static void
_outCreateRoleStmt(String * str,CreateRoleStmt * node)3079 _outCreateRoleStmt(String * str, CreateRoleStmt *node)
3080 {
3081 	string_append_char(str, "CREATE ");
3082 	switch (node->stmt_type)
3083 	{
3084 		case ROLESTMT_ROLE:
3085 			string_append_char(str, "ROLE \"");
3086 			break;
3087 
3088 		case ROLESTMT_USER:
3089 			string_append_char(str, "USER \"");
3090 			break;
3091 
3092 		case ROLESTMT_GROUP:
3093 			string_append_char(str, "GROUP \"");
3094 			break;
3095 	}
3096 	_outNode(str, node->role);
3097 	string_append_char(str, "\"");
3098 
3099 	_outOptRoleList(str, node->options);
3100 }
3101 
3102 static void
_outAlterRoleStmt(String * str,AlterRoleStmt * node)3103 _outAlterRoleStmt(String * str, AlterRoleStmt *node)
3104 {
3105 	string_append_char(str, "ALTER ROLE \"");
3106 	_outNode(str, node->role);
3107 	string_append_char(str, "\"");
3108 
3109 	if (node->options)
3110 		_outOptRoleList(str, node->options);
3111 }
3112 
3113 static void
_outAlterRoleSetStmt(String * str,AlterRoleSetStmt * node)3114 _outAlterRoleSetStmt(String * str, AlterRoleSetStmt *node)
3115 {
3116 	string_append_char(str, "ALTER ROLE \"");
3117 	_outNode(str, node->role);
3118 	string_append_char(str, "\" ");
3119 
3120 	if (node->setstmt)
3121 	{
3122 		_outNode(str, node->setstmt);
3123 	}
3124 }
3125 static void
_outRoleSpec(String * str,RoleSpec * node)3126 _outRoleSpec(String * str, RoleSpec *node)
3127 {
3128 	string_append_char(str, node->rolename);
3129 }
3130 
3131 static void
_outSetTransactionModeList(String * str,List * list)3132 _outSetTransactionModeList(String * str, List *list)
3133 {
3134 	ListCell   *lc;
3135 	char		comma = 0;
3136 
3137 	foreach(lc, list)
3138 	{
3139 		DefElem    *elem = lfirst(lc);
3140 
3141 		if (comma == 0)
3142 			comma = 1;
3143 		else
3144 			string_append_char(str, ",");
3145 
3146 		if (strcmp(elem->defname, "transaction_isolation") == 0)
3147 		{
3148 			A_Const    *v = (A_Const *) elem->arg;
3149 
3150 			string_append_char(str, " ISOLATION LEVEL ");
3151 			string_append_char(str, v->val.val.str);
3152 		}
3153 		else if (strcmp(elem->defname, "transaction_read_only") == 0)
3154 		{
3155 			A_Const    *n = (A_Const *) elem->arg;
3156 
3157 			if (n->val.val.ival == TRUE)
3158 				string_append_char(str, "READ ONLY ");
3159 			else
3160 				string_append_char(str, "READ WRITE ");
3161 		}
3162 	}
3163 }
3164 
3165 
3166 static void
_outSetRest(String * str,VariableSetStmt * node)3167 _outSetRest(String * str, VariableSetStmt *node)
3168 {
3169 	if (strcmp(node->name, "timezone") == 0)
3170 	{
3171 		string_append_char(str, "TIME ZONE ");
3172 		if (node->kind != VAR_RESET)
3173 			_outNode(str, node->args);
3174 	}
3175 	else if (strcmp(node->name, "TRANSACTION") == 0)
3176 	{
3177 		string_append_char(str, "TRANSACTION ");
3178 		_outSetTransactionModeList(str, node->args);
3179 	}
3180 	else if (strcmp(node->name, "SESSION CHARACTERISTICS") == 0)
3181 	{
3182 		string_append_char(str, "SESSION CHARACTERISTICS AS TRANSACTION ");
3183 		_outSetTransactionModeList(str, node->args);
3184 	}
3185 	else if (strcmp(node->name, "role") == 0)
3186 	{
3187 		string_append_char(str, "ROLE ");
3188 		if (node->kind != VAR_RESET)
3189 			_outNode(str, node->args);
3190 	}
3191 	else if (strcmp(node->name, "session_authorization") == 0)
3192 	{
3193 		string_append_char(str, "SESSION AUTHORIZATION ");
3194 		if (node->args == NIL && node->kind != VAR_RESET)
3195 			string_append_char(str, "DEFAULT");
3196 		else
3197 			_outNode(str, node->args);
3198 	}
3199 	else if (strcmp(node->name, "transaction_isolation") == 0)
3200 	{
3201 		string_append_char(str, "TRANSACTION ISOLATION LEVEL");
3202 		if (node->kind != VAR_RESET)
3203 			_outSetTransactionModeList(str, node->args);
3204 	}
3205 	else if (strcmp(node->name, "xmloption") == 0)
3206 	{
3207 		A_Const    *v = linitial(node->args);
3208 
3209 		string_append_char(str, "XML OPTOIN ");
3210 		string_append_char(str, v->val.val.str);
3211 	}
3212 	else
3213 	{
3214 		string_append_char(str, node->name);
3215 		if (node->kind != VAR_RESET)
3216 		{
3217 			if (node->kind == VAR_SET_CURRENT)
3218 			{
3219 				string_append_char(str, " FROM CURRENT");
3220 			}
3221 			else
3222 			{
3223 				string_append_char(str, " TO ");
3224 				if (node->args == NULL)
3225 				{
3226 					string_append_char(str, "DEFAULT");
3227 				}
3228 				else
3229 					_outNode(str, node->args);
3230 			}
3231 		}
3232 	}
3233 }
3234 
3235 static void
_outDropRoleStmt(String * str,DropRoleStmt * node)3236 _outDropRoleStmt(String * str, DropRoleStmt *node)
3237 {
3238 	string_append_char(str, "DROP ROLE ");
3239 	if (node->missing_ok == TRUE)
3240 		string_append_char(str, "IF EXISTS ");
3241 	_outIdList(str, node->roles);
3242 }
3243 
3244 static void
_outCreateSchemaStmt(String * str,CreateSchemaStmt * node)3245 _outCreateSchemaStmt(String * str, CreateSchemaStmt *node)
3246 {
3247 	string_append_char(str, "CREATE SCHEMA \"");
3248 	string_append_char(str, node->schemaname);
3249 	string_append_char(str, "\"");
3250 	if (node->authrole)
3251 	{
3252 		string_append_char(str, "AUTHORIZATION \"");
3253 		_outNode(str, node->authrole);
3254 		string_append_char(str, "\" ");
3255 	}
3256 	_outNode(str, node->schemaElts);
3257 }
3258 
3259 static void
_outVariableSetStmt(String * str,VariableSetStmt * node)3260 _outVariableSetStmt(String * str, VariableSetStmt *node)
3261 {
3262 	if (node->kind == VAR_RESET_ALL)
3263 	{
3264 		string_append_char(str, "RESET ALL");
3265 		return;
3266 	}
3267 
3268 	if (node->kind == VAR_RESET)
3269 		string_append_char(str, "RESET ");
3270 	else
3271 		string_append_char(str, "SET ");
3272 
3273 	if (node->is_local)
3274 		string_append_char(str, "LOCAL ");
3275 
3276 	_outSetRest(str, node);
3277 }
3278 
3279 static void
_outVariableShowStmt(String * str,VariableShowStmt * node)3280 _outVariableShowStmt(String * str, VariableShowStmt *node)
3281 {
3282 	if (strcmp(node->name, "timezone") == 0)
3283 		string_append_char(str, "SHOW TIME ZONE");
3284 	else if (strcmp(node->name, "transaction_isolation") == 0)
3285 		string_append_char(str, "SHOW TRANSACTION ISOLATION LEVEL");
3286 	else if (strcmp(node->name, "session_authorization") == 0)
3287 		string_append_char(str, "SHOW SESSION AUTHORIZATION");
3288 	else if (strcmp(node->name, "all") == 0)
3289 		string_append_char(str, "SHOW ALL");
3290 	else
3291 	{
3292 		string_append_char(str, "SHOW ");
3293 		string_append_char(str, node->name);
3294 	}
3295 }
3296 
3297 static void
_outConstraintsSetStmt(String * str,ConstraintsSetStmt * node)3298 _outConstraintsSetStmt(String * str, ConstraintsSetStmt *node)
3299 {
3300 	string_append_char(str, "SET CONSTRAINTS ");
3301 
3302 	if (node->constraints == NIL)
3303 		string_append_char(str, "ALL");
3304 	else
3305 		_outNode(str, node->constraints);
3306 
3307 	string_append_char(str, node->deferred == TRUE ? " DEFERRED" : " IMMEDIATE");
3308 }
3309 
3310 static void
_outAlterTableCmd(String * str,AlterTableCmd * node)3311 _outAlterTableCmd(String * str, AlterTableCmd *node)
3312 {
3313 	char		buf[16];
3314 
3315 	switch (node->subtype)
3316 	{
3317 		case AT_AddColumn:
3318 			string_append_char(str, "ADD ");
3319 			_outNode(str, node->def);
3320 			break;
3321 
3322 		case AT_ColumnDefault:
3323 			string_append_char(str, "ALTER \"");
3324 			string_append_char(str, node->name);
3325 			string_append_char(str, "\" ");
3326 			if (node->def == NULL)
3327 				string_append_char(str, "DROP DEFAULT");
3328 			else
3329 			{
3330 				string_append_char(str, "SET DEFAULT ");
3331 				_outNode(str, node->def);
3332 			}
3333 			break;
3334 
3335 		case AT_DropNotNull:
3336 			string_append_char(str, "ALTER \"");
3337 			string_append_char(str, node->name);
3338 			string_append_char(str, "\" DROP NOT NULL");
3339 			break;
3340 
3341 		case AT_SetNotNull:
3342 			string_append_char(str, "ALTER \"");
3343 			string_append_char(str, node->name);
3344 			string_append_char(str, "\" SET NOT NULL");
3345 			break;
3346 
3347 		case AT_SetStatistics:
3348 			string_append_char(str, "ALTER \"");
3349 			string_append_char(str, node->name);
3350 			string_append_char(str, "\" SET STATISTICS ");
3351 			snprintf(buf, 16, "%d", ((Value *) node->def)->val.ival);
3352 			string_append_char(str, buf);
3353 			break;
3354 
3355 		case AT_SetStorage:
3356 			string_append_char(str, "ALTER \"");
3357 			string_append_char(str, node->name);
3358 			string_append_char(str, "\" SET STORAGE ");
3359 			string_append_char(str, ((Value *) node->def)->val.str);
3360 			break;
3361 
3362 		case AT_DropColumn:
3363 			string_append_char(str, "DROP \"");
3364 			string_append_char(str, node->name);
3365 			string_append_char(str, "\" ");
3366 			if (node->behavior == DROP_CASCADE)
3367 				string_append_char(str, "CASCADE");
3368 			break;
3369 
3370 		case AT_AlterColumnType:
3371 			string_append_char(str, "ALTER \"");
3372 			string_append_char(str, node->name);
3373 			string_append_char(str, "\" TYPE ");
3374 			_outNode(str, node->def);
3375 			break;
3376 
3377 		case AT_AddConstraint:
3378 			string_append_char(str, "ADD ");
3379 			_outNode(str, node->def);
3380 			break;
3381 
3382 		case AT_DropConstraint:
3383 			string_append_char(str, "DROP CONSTRAINT \"");
3384 			string_append_char(str, node->name);
3385 			string_append_char(str, "\"");
3386 			if (node->behavior == DROP_CASCADE)
3387 				string_append_char(str, " CASCADE");
3388 			break;
3389 
3390 		case AT_DropOids:
3391 			string_append_char(str, "SET WITHOUT OIDS");
3392 			break;
3393 
3394 		case AT_ClusterOn:
3395 			string_append_char(str, "CLUSTER ON \"");
3396 			string_append_char(str, node->name);
3397 			string_append_char(str, "\"");
3398 			break;
3399 
3400 		case AT_DropCluster:
3401 			string_append_char(str, "SET WITHOUT CLUSTER");
3402 			break;
3403 
3404 		case AT_EnableTrig:
3405 			string_append_char(str, "ENABLE TRIGGER \"");
3406 			string_append_char(str, node->name);
3407 			string_append_char(str, "\"");
3408 			break;
3409 
3410 		case AT_EnableAlwaysTrig:
3411 			/* not implemented */
3412 			break;
3413 
3414 		case AT_EnableReplicaTrig:
3415 			/* not implemented */
3416 			break;
3417 
3418 		case AT_EnableTrigAll:
3419 			string_append_char(str, "ENABLE TRIGGER ALL");
3420 			break;
3421 
3422 		case AT_EnableTrigUser:
3423 			string_append_char(str, "ENABLE TRIGGER USER");
3424 			break;
3425 
3426 		case AT_DisableTrig:
3427 			string_append_char(str, "DISABLE TRIGGER \"");
3428 			string_append_char(str, node->name);
3429 			string_append_char(str, "\"");
3430 			break;
3431 
3432 		case AT_DisableTrigAll:
3433 			string_append_char(str, "DISABLE TRIGGER ALL");
3434 			break;
3435 
3436 		case AT_DisableTrigUser:
3437 			string_append_char(str, "DISABLE TRIGGER USER");
3438 			break;
3439 
3440 		case AT_EnableRule:
3441 			/* not implemented */
3442 			break;
3443 
3444 		case AT_EnableReplicaRule:
3445 			/* not implemented */
3446 			break;
3447 
3448 		case AT_EnableAlwaysRule:
3449 			/* not implemented */
3450 			break;
3451 
3452 		case AT_DisableRule:
3453 			/* not implemented */
3454 			break;
3455 
3456 		case AT_AddInherit:
3457 			/* not implemented */
3458 			break;
3459 
3460 		case AT_ChangeOwner:
3461 			string_append_char(str, "OWNER TO \"");
3462 			string_append_char(str, node->name);
3463 			string_append_char(str, "\"");
3464 			break;
3465 
3466 		case AT_SetTableSpace:
3467 			string_append_char(str, "SET TABLESPACE \"");
3468 			string_append_char(str, node->name);
3469 			string_append_char(str, "\"");
3470 			break;
3471 
3472 		case AT_SetRelOptions:
3473 			/* not implemented */
3474 			break;
3475 
3476 		case AT_ResetRelOptions:
3477 			/* not implemented */
3478 			break;
3479 
3480 		default:
3481 			break;
3482 	}
3483 }
3484 
3485 static void
_outAlterTableStmt(String * str,AlterTableStmt * node)3486 _outAlterTableStmt(String * str, AlterTableStmt *node)
3487 {
3488 	if (node->relkind == OBJECT_TABLE)
3489 		string_append_char(str, "ALTER TABLE ");
3490 	else
3491 		string_append_char(str, "ALTER INDEX ");
3492 
3493 	_outNode(str, node->relation);
3494 	string_append_char(str, " ");
3495 	_outNode(str, node->cmds);
3496 }
3497 
3498 static void
_outOptSeqList(String * str,List * options)3499 _outOptSeqList(String * str, List *options)
3500 {
3501 	ListCell   *lc;
3502 
3503 	foreach(lc, options)
3504 	{
3505 		DefElem    *e = lfirst(lc);
3506 		Value	   *v = (Value *) e->arg;
3507 		char		buf[16];
3508 
3509 		if (strcmp(e->defname, "cycle") == 0)
3510 		{
3511 			if (v->val.ival == TRUE)
3512 				string_append_char(str, " CYCLE");
3513 			else
3514 				string_append_char(str, " NO CYCLE");
3515 		}
3516 		else if (strcmp(e->defname, "minvalue") == 0 && !v)
3517 			string_append_char(str, " NO MINVALUE");
3518 		else if (strcmp(e->defname, "maxvalue") == 0 && !v)
3519 			string_append_char(str, " NO MAXVALUE");
3520 		else if (strcmp(e->defname, "owned_by") == 0)
3521 		{
3522 			string_append_char(str, " OWNED BY ");
3523 			_outIdList(str, (List *) e->arg);
3524 		}
3525 		else
3526 		{
3527 			if (strcmp(e->defname, "cache") == 0)
3528 				string_append_char(str, " CACHE ");
3529 			else if (strcmp(e->defname, "increment") == 0)
3530 				string_append_char(str, " INCREMENT ");
3531 			else if (strcmp(e->defname, "maxvalue") == 0 && v)
3532 				string_append_char(str, " MAXVALUE ");
3533 			else if (strcmp(e->defname, "minvalue") == 0 && v)
3534 				string_append_char(str, " MINVALUE ");
3535 			else if (strcmp(e->defname, "start") == 0)
3536 				string_append_char(str, " START ");
3537 			else if (strcmp(e->defname, "restart") == 0)
3538 				string_append_char(str, " RESTART ");
3539 
3540 			if (IsA(e->arg, String))
3541 				string_append_char(str, v->val.str);
3542 			else
3543 			{
3544 				snprintf(buf, 16, "%d", v->val.ival);
3545 				string_append_char(str, buf);
3546 			}
3547 		}
3548 	}
3549 }
3550 
3551 static void
_outCreateSeqStmt(String * str,CreateSeqStmt * node)3552 _outCreateSeqStmt(String * str, CreateSeqStmt *node)
3553 {
3554 	string_append_char(str, "CREATE ");
3555 	if (node->sequence->relpersistence == RELPERSISTENCE_TEMP)
3556 		string_append_char(str, "TEMP ");
3557 	string_append_char(str, "SEQUENCE ");
3558 	_outNode(str, node->sequence);
3559 
3560 	_outOptSeqList(str, node->options);
3561 }
3562 
3563 static void
_outAlterSeqStmt(String * str,AlterSeqStmt * node)3564 _outAlterSeqStmt(String * str, AlterSeqStmt *node)
3565 {
3566 	string_append_char(str, "ALTER SEQUENCE ");
3567 	_outNode(str, node->sequence);
3568 	_outOptSeqList(str, node->options);
3569 }
3570 
3571 static void
_outCreatePLangStmt(String * str,CreatePLangStmt * node)3572 _outCreatePLangStmt(String * str, CreatePLangStmt *node)
3573 {
3574 	string_append_char(str, "CREATE ");
3575 	if (node->pltrusted == true)
3576 		string_append_char(str, "TRUSTED ");
3577 	string_append_char(str, "LANGUAGE \"");
3578 	string_append_char(str, node->plname);
3579 	string_append_char(str, "\"");
3580 
3581 	if (node->plhandler != NIL)
3582 	{
3583 		ListCell   *lc;
3584 		char		dot = 0;
3585 
3586 		string_append_char(str, " HANDLER ");
3587 		foreach(lc, node->plhandler)
3588 		{
3589 			Value	   *v = lfirst(lc);
3590 
3591 			if (dot == 0)
3592 				dot = 1;
3593 			else
3594 				string_append_char(str, ".");
3595 
3596 			string_append_char(str, "\"");
3597 			string_append_char(str, v->val.str);
3598 			string_append_char(str, "\"");
3599 		}
3600 	}
3601 
3602 	if (node->plvalidator != NIL)
3603 	{
3604 		ListCell   *lc;
3605 		char		dot = 0;
3606 
3607 		string_append_char(str, " VALIDATOR ");
3608 		foreach(lc, node->plvalidator)
3609 		{
3610 			Value	   *v = lfirst(lc);
3611 
3612 			if (dot == 0)
3613 				dot = 1;
3614 			else
3615 				string_append_char(str, ".");
3616 
3617 			string_append_char(str, "\"");
3618 			string_append_char(str, v->val.str);
3619 			string_append_char(str, "\"");
3620 		}
3621 	}
3622 }
3623 
3624 
3625 static void
_outCreateTableSpaceStmt(String * str,CreateTableSpaceStmt * node)3626 _outCreateTableSpaceStmt(String * str, CreateTableSpaceStmt *node)
3627 {
3628 	string_append_char(str, "CREATE TABLESPACE \"");
3629 	string_append_char(str, node->tablespacename);
3630 	string_append_char(str, "\" ");
3631 
3632 	if (node->owner)
3633 	{
3634 		string_append_char(str, "OWNER \"");
3635 		_outNode(str, node->owner);
3636 		string_append_char(str, "\" ");
3637 	}
3638 
3639 	string_append_char(str, "LOCATION '");
3640 	string_append_char(str, node->location);
3641 	string_append_char(str, "'");
3642 }
3643 
3644 static void
_outDropTableSpaceStmt(String * str,DropTableSpaceStmt * node)3645 _outDropTableSpaceStmt(String * str, DropTableSpaceStmt *node)
3646 {
3647 	string_append_char(str, "DROP TABLESPACE \"");
3648 	string_append_char(str, node->tablespacename);
3649 	string_append_char(str, "\"");
3650 }
3651 
3652 static void
_outFuncName(String * str,List * func_name)3653 _outFuncName(String * str, List *func_name)
3654 {
3655 	ListCell   *lc;
3656 	Value	   *v;
3657 	char		dot = 0;
3658 
3659 	if (func_name == NULL)
3660 		return;
3661 
3662 	foreach(lc, func_name)
3663 	{
3664 		v = (Value *) lfirst(lc);
3665 
3666 		if (dot == 0)
3667 			dot = 1;
3668 		else
3669 			string_append_char(str, ".");
3670 
3671 		if (IsA(v, String))
3672 		{
3673 			string_append_char(str, "\"");
3674 			string_append_char(str, v->val.str);
3675 			string_append_char(str, "\"");
3676 		}
3677 		else
3678 		{
3679 			_outNode(str, v);
3680 		}
3681 	}
3682 }
3683 
3684 static void
_outCreateTrigStmt(String * str,CreateTrigStmt * node)3685 _outCreateTrigStmt(String * str, CreateTrigStmt *node)
3686 {
3687 	bool		has_events = false;
3688 
3689 	if (node->isconstraint == TRUE)
3690 		string_append_char(str, "CREATE CONSTRAINT TRIGGER \"");
3691 	else
3692 		string_append_char(str, "CREATE TRIGGER \"");
3693 	string_append_char(str, node->trigname);
3694 	string_append_char(str, "\" ");
3695 
3696 	if (TRIGGER_FOR_BEFORE(node->timing))
3697 		string_append_char(str, "BEFORE ");
3698 	if (TRIGGER_FOR_AFTER(node->timing))
3699 		string_append_char(str, "AFTER ");
3700 
3701 	if (node->events & TRIGGER_TYPE_INSERT)
3702 	{
3703 		string_append_char(str, "INSERT ");
3704 		has_events = true;
3705 	}
3706 	if (node->events & TRIGGER_TYPE_DELETE)
3707 	{
3708 		if (has_events)
3709 			string_append_char(str, "OR ");
3710 		string_append_char(str, "DELETE ");
3711 		has_events = true;
3712 	}
3713 	if (node->events & TRIGGER_TYPE_UPDATE)
3714 	{
3715 		if (has_events)
3716 			string_append_char(str, "OR ");
3717 		string_append_char(str, "UPDATE ");
3718 		has_events = true;
3719 	}
3720 	if (node->events & TRIGGER_TYPE_TRUNCATE)
3721 	{
3722 		if (has_events)
3723 			string_append_char(str, "OR ");
3724 		string_append_char(str, "TRUNCATE ");
3725 		has_events = true;
3726 	}
3727 
3728 	string_append_char(str, "ON ");
3729 	_outNode(str, node->relation);
3730 
3731 	if (node->constrrel)
3732 	{
3733 		string_append_char(str, " FROM ");
3734 		_outNode(str, node->constrrel);
3735 	}
3736 
3737 	if (node->deferrable)
3738 		string_append_char(str, " DEFERRABLE");
3739 	if (node->initdeferred)
3740 		string_append_char(str, " INITIALLY DEFERRED");
3741 
3742 	if (node->row == TRUE)
3743 		string_append_char(str, " FOR EACH ROW ");
3744 	else
3745 		string_append_char(str, " FOR EACH STATEMENT ");
3746 
3747 	string_append_char(str, "EXECUTE PROCEDURE ");
3748 
3749 	_outFuncName(str, node->funcname);
3750 	string_append_char(str, "(");
3751 	_outNode(str, node->args);
3752 	string_append_char(str, ")");
3753 }
3754 
3755 static void
_outDefinition(String * str,List * definition)3756 _outDefinition(String * str, List *definition)
3757 {
3758 	ListCell   *lc;
3759 	char		comma = 0;
3760 
3761 	if (definition == NIL)
3762 		return;
3763 
3764 	string_append_char(str, "(");
3765 	foreach(lc, definition)
3766 	{
3767 		DefElem    *e = lfirst(lc);
3768 
3769 		if (comma == 0)
3770 			comma = 1;
3771 		else
3772 			string_append_char(str, ", ");
3773 
3774 		string_append_char(str, "\"");
3775 		string_append_char(str, e->defname);
3776 		string_append_char(str, "\"");
3777 
3778 		if (e->arg)
3779 		{
3780 			string_append_char(str, "=");
3781 			_outNode(str, e->arg);
3782 		}
3783 	}
3784 	string_append_char(str, ")");
3785 }
3786 
3787 static void
_outDefineStmt(String * str,DefineStmt * node)3788 _outDefineStmt(String * str, DefineStmt *node)
3789 {
3790 	ListCell   *lc;
3791 	char		dot = 0;
3792 
3793 	switch (node->kind)
3794 	{
3795 		case OBJECT_AGGREGATE:
3796 			string_append_char(str, "CREATE AGGREGATE ");
3797 			_outFuncName(str, node->defnames);
3798 			string_append_char(str, " ");
3799 			_outDefinition(str, node->definition);
3800 			break;
3801 
3802 		case OBJECT_OPERATOR:
3803 			string_append_char(str, "CREATE OPERATOR ");
3804 
3805 			foreach(lc, node->defnames)
3806 			{
3807 				Value	   *v = lfirst(lc);
3808 
3809 				if (dot == 0)
3810 					dot = 1;
3811 				else
3812 					string_append_char(str, ".");
3813 
3814 				string_append_char(str, v->val.str);
3815 			}
3816 
3817 			string_append_char(str, " ");
3818 			_outDefinition(str, node->definition);
3819 			break;
3820 
3821 		case OBJECT_TYPE:
3822 			string_append_char(str, "CREATE TYPE");
3823 			_outFuncName(str, node->defnames);
3824 			string_append_char(str, " ");
3825 			_outDefinition(str, node->definition);
3826 			break;
3827 
3828 		case OBJECT_TSPARSER:
3829 			string_append_char(str, "CREATE TEXT SEARCH PARSER ");
3830 			_outIdList(str, node->defnames);
3831 			_outDefinition(str, node->definition);
3832 			break;
3833 
3834 		case OBJECT_TSDICTIONARY:
3835 			string_append_char(str, "CREATE TEXT SEARCH DICTIONARY ");
3836 			_outIdList(str, node->defnames);
3837 			_outDefinition(str, node->definition);
3838 			break;
3839 
3840 		case OBJECT_TSTEMPLATE:
3841 			string_append_char(str, "CREATE TEXT SEARCH TEMPLATE ");
3842 			_outIdList(str, node->defnames);
3843 			_outDefinition(str, node->definition);
3844 			break;
3845 
3846 		case OBJECT_TSCONFIGURATION:
3847 			string_append_char(str, "CREATE TEXT SEARCH CONFIGURATION ");
3848 			_outIdList(str, node->defnames);
3849 			_outDefinition(str, node->definition);
3850 			break;
3851 
3852 		default:
3853 			break;
3854 	}
3855 }
3856 
3857 static void
_outOperatorName(String * str,List * list)3858 _outOperatorName(String * str, List *list)
3859 {
3860 	char		dot = 0;
3861 	ListCell   *lc;
3862 
3863 	foreach(lc, list)
3864 	{
3865 		Value	   *v = lfirst(lc);
3866 
3867 		if (dot == 0)
3868 			dot = 1;
3869 		else
3870 			string_append_char(str, ".");
3871 
3872 		string_append_char(str, v->val.str);
3873 	}
3874 }
3875 
3876 static void
_outCreateOpClassItem(String * str,CreateOpClassItem * node)3877 _outCreateOpClassItem(String * str, CreateOpClassItem *node)
3878 {
3879 	char		buf[16];
3880 
3881 	switch (node->itemtype)
3882 	{
3883 		case OPCLASS_ITEM_OPERATOR:
3884 			string_append_char(str, "OPERATOR ");
3885 			snprintf(buf, 16, "%d", node->number);
3886 			string_append_char(str, buf);
3887 			string_append_char(str, " ");
3888 			_outOperatorName(str, node->name->objname);
3889 
3890 			if (node->name->objname != NIL)
3891 			{
3892 				string_append_char(str, "(");
3893 				_outNode(str, node->name->objname);
3894 				string_append_char(str, ")");
3895 			}
3896 
3897 			/*
3898 			 * if (node->recheck == TRUE) string_append_char(str, " RECHECK");
3899 			 */
3900 			break;
3901 
3902 		case OPCLASS_ITEM_FUNCTION:
3903 			string_append_char(str, "FUNCTION ");
3904 			snprintf(buf, 16, "%d", node->number);
3905 			string_append_char(str, buf);
3906 			string_append_char(str, " ");
3907 			_outFuncName(str, node->name->objname);
3908 			string_append_char(str, "(");
3909 			_outNode(str, node->name->objname);
3910 			string_append_char(str, ")");
3911 			break;
3912 
3913 		case OPCLASS_ITEM_STORAGETYPE:
3914 			string_append_char(str, "STORAGE ");
3915 			_outNode(str, node->storedtype);
3916 			break;
3917 
3918 		default:
3919 			break;
3920 	}
3921 
3922 }
3923 
3924 static void
_outCreateOpClassStmt(String * str,CreateOpClassStmt * node)3925 _outCreateOpClassStmt(String * str, CreateOpClassStmt *node)
3926 {
3927 	string_append_char(str, "CREATE OPERATOR CLASS ");
3928 	_outFuncName(str, node->opclassname);
3929 
3930 	if (node->isDefault == TRUE)
3931 		string_append_char(str, " DEFAULT");
3932 
3933 	string_append_char(str, " FOR TYPE ");
3934 	_outNode(str, node->datatype);
3935 	string_append_char(str, " USING ");
3936 	string_append_char(str, node->amname);
3937 	string_append_char(str, " AS ");
3938 	_outNode(str, node->items);
3939 }
3940 
3941 /*
3942  * Handle drop satements. As of pgpool-II 3.3(derived parser from
3943  * PostgreSQL 9.2), following types are supported:
3944  *
3945  * DROP TABLE, DROP SEQUENCE, DROP VIEW, DROP INDEX, DROP FOREIGN
3946  * TABLE, DROP TYPE, DROP DOMAIN, DROP COLLATION, DROP CONVERSION,
3947  * DROP SCHEMA, DROP TEXT SEARCH PARSER, DROP TEXT SEARCH DICTIONARY,
3948  * DROP TEXT SEARCH CONFIGURATION, DROP LANGUAGE, DROP RULE, DROP
3949  * OPERATOR, DROP OPERATOR CLASS
3950  */
3951 
3952 static void
add_function_like_objs(String * str,DropStmt * node)3953 add_function_like_objs(String * str, DropStmt *node)
3954 {
3955 	ListCell   *lc;
3956 	char		comma = 0;
3957 
3958 	if (node->concurrent)
3959 		string_append_char(str, "CONCURRENTLY ");
3960 	if (node->missing_ok)
3961 		string_append_char(str, "IF EXISTS ");
3962 
3963 	foreach(lc, node->objects)
3964 	{
3965 		if (comma == 0)
3966 			comma = 1;
3967 		else
3968 			string_append_char(str, ", ");
3969 		_outFuncName(str, lfirst(lc));
3970 	}
3971 }
3972 
3973 static void
_outDropStmt(String * str,DropStmt * node)3974 _outDropStmt(String * str, DropStmt *node)
3975 {
3976 	List	   *objname;
3977 	char		*p;
3978 	char		*p1;
3979 	List		*l;
3980 
3981 	string_append_char(str, "DROP ");
3982 	switch (node->removeType)
3983 	{
3984 		case OBJECT_TABLE:
3985 			string_append_char(str, "TABLE ");
3986 			add_function_like_objs(str, node);
3987 			break;
3988 
3989 		case OBJECT_SEQUENCE:
3990 			string_append_char(str, "SEQUENCE ");
3991 			add_function_like_objs(str, node);
3992 			break;
3993 
3994 		case OBJECT_VIEW:
3995 			string_append_char(str, "VIEW ");
3996 			add_function_like_objs(str, node);
3997 			break;
3998 
3999 		case OBJECT_INDEX:
4000 			string_append_char(str, "INDEX ");
4001 			add_function_like_objs(str, node);
4002 			break;
4003 
4004 		case OBJECT_FOREIGN_TABLE:
4005 			string_append_char(str, "FOREIGN TABLE ");
4006 			add_function_like_objs(str, node);
4007 			break;
4008 
4009 		case OBJECT_FDW:
4010 			string_append_char(str, "FOREIGN DATA WRAPPER ");
4011 			add_function_like_objs(str, node);
4012 			break;
4013 
4014 		case OBJECT_TYPE:
4015 			string_append_char(str, "TYPE ");
4016 			add_function_like_objs(str, node);
4017 			break;
4018 
4019 		case OBJECT_DOMAIN:
4020 			string_append_char(str, "DOMAIN ");
4021 			add_function_like_objs(str, node);
4022 			break;
4023 
4024 		case OBJECT_COLLATION:
4025 			string_append_char(str, "COLLATION ");
4026 			add_function_like_objs(str, node);
4027 			break;
4028 
4029 		case OBJECT_CONVERSION:
4030 			string_append_char(str, "CONVERSION ");
4031 			add_function_like_objs(str, node);
4032 			break;
4033 
4034 		case OBJECT_SCHEMA:
4035 			string_append_char(str, "SCHEMA ");
4036 			add_function_like_objs(str, node);
4037 			break;
4038 
4039 		case OBJECT_EXTENSION:
4040 			string_append_char(str, "EXTENSION ");
4041 			add_function_like_objs(str, node);
4042 			break;
4043 
4044 		case OBJECT_TSPARSER:
4045 			string_append_char(str, "TEXT SEARCH PARSER ");
4046 			add_function_like_objs(str, node);
4047 			break;
4048 
4049 		case OBJECT_TSDICTIONARY:
4050 			string_append_char(str, "TEXT SEARCH DICTIONARY ");
4051 			add_function_like_objs(str, node);
4052 			break;
4053 
4054 		case OBJECT_TSTEMPLATE:
4055 			string_append_char(str, "TEXT SEARCH TEMPLATE ");
4056 			add_function_like_objs(str, node);
4057 			break;
4058 
4059 		case OBJECT_TSCONFIGURATION:
4060 			string_append_char(str, "TEXT SEARCH CONFIGURATION ");
4061 			add_function_like_objs(str, node);
4062 			break;
4063 
4064 		case OBJECT_LANGUAGE:
4065 			string_append_char(str, "PROCEDURAL LANGUAGE ");
4066 			add_function_like_objs(str, node);
4067 			break;
4068 
4069 		case OBJECT_RULE:
4070 			string_append_char(str, "DROP RULE ");
4071 			if (node->missing_ok)
4072 				string_append_char(str, "IF EXISTS ");
4073 			objname = lfirst(list_head(node->objects));
4074 			string_append_char(str, strVal(llast(objname)));
4075 			string_append_char(str, " ON ");
4076 			l = list_truncate(list_copy(objname),
4077 							  list_length(objname) - 1);
4078 			p = NameListToString(l);
4079 			string_append_char(str, p);
4080 			pfree(p);
4081 			list_free(l);
4082 			break;
4083 
4084 		case OBJECT_OPERATOR:
4085 			string_append_char(str, "OPERATOR ");
4086 			add_function_like_objs(str, node);
4087 			break;
4088 
4089 		case OBJECT_OPCLASS:
4090 			string_append_char(str, "DROP OPERATOR CLASS ");
4091 			if (node->missing_ok)
4092 				string_append_char(str, "IF EXISTS ");
4093 			objname = lfirst(list_head(node->objects));
4094 			string_append_char(str, strVal(llast(objname)));
4095 			string_append_char(str, " USING ");
4096 			string_append_char(str, "'");
4097 			l = list_truncate(list_copy(objname),
4098 							  list_length(objname) - 1);
4099 			p = NameListToString(l);
4100 			p1 = escape_string(p);
4101 			string_append_char(str, p1);
4102 			pfree(p1);
4103 			pfree(p);
4104 			list_free(l);
4105 			string_append_char(str, "'");
4106 			break;
4107 
4108 		case OBJECT_CAST:
4109 			string_append_char(str, "DROP CAST ");
4110 			if (node->missing_ok)
4111 				string_append_char(str, "IF EXISTS ");
4112 			string_append_char(str, "(");
4113 			objname = linitial(node->objects);
4114 			_outNode(str, linitial(objname));
4115 			string_append_char(str, " AS ");
4116 			_outNode(str, linitial(objname));
4117 			string_append_char(str, ")");
4118 			break;
4119 
4120 		case OBJECT_OPFAMILY:
4121 			string_append_char(str, "OPERATOR FAMILY ");
4122 			if (node->missing_ok)
4123 				string_append_char(str, "IF EXISTS ");
4124 			objname = linitial(node->objects);
4125 			_outIdList(str, objname);
4126 			string_append_char(str, " USING ");
4127 			_outIdList(str, objname);
4128 			break;
4129 
4130 		default:
4131 			break;
4132 	}
4133 
4134 	if (node->behavior == DROP_CASCADE)
4135 		string_append_char(str, " CASCADE");
4136 }
4137 
4138 static void
_outFetchStmt(String * str,FetchStmt * node)4139 _outFetchStmt(String * str, FetchStmt *node)
4140 {
4141 	char		buf[16];
4142 
4143 	snprintf(buf, 16, "%ld", node->howMany);
4144 
4145 	if (node->ismove == TRUE)
4146 		string_append_char(str, "MOVE ");
4147 	else
4148 		string_append_char(str, "FETCH ");
4149 
4150 	switch (node->direction)
4151 	{
4152 		case FETCH_FORWARD:
4153 			string_append_char(str, "FORWARD ");
4154 			if (node->howMany == FETCH_ALL)
4155 				string_append_char(str, "ALL ");
4156 			else
4157 			{
4158 				string_append_char(str, buf);
4159 				string_append_char(str, " ");
4160 			}
4161 			break;
4162 
4163 		case FETCH_BACKWARD:
4164 			string_append_char(str, "BACKWARD ");
4165 			if (node->howMany == FETCH_ALL)
4166 				string_append_char(str, "ALL ");
4167 			else
4168 			{
4169 				string_append_char(str, buf);
4170 				string_append_char(str, " ");
4171 			}
4172 			break;
4173 
4174 		case FETCH_ABSOLUTE:
4175 			if (node->howMany == 1)
4176 				string_append_char(str, "FIRST ");
4177 			else if (node->howMany == -1)
4178 				string_append_char(str, "LAST ");
4179 			else
4180 			{
4181 				string_append_char(str, "ABSOLUTE ");
4182 				string_append_char(str, buf);
4183 				string_append_char(str, " ");
4184 			}
4185 			break;
4186 
4187 		case FETCH_RELATIVE:
4188 			string_append_char(str, "RELATIVE ");
4189 			string_append_char(str, buf);
4190 			string_append_char(str, " ");
4191 			break;
4192 	}
4193 
4194 	string_append_char(str, "IN \"");
4195 	string_append_char(str, node->portalname);
4196 	string_append_char(str, "\"");
4197 }
4198 
4199 static void
_outPrivilegeList(String * str,List * list)4200 _outPrivilegeList(String * str, List *list)
4201 {
4202 	ListCell   *lc;
4203 	char		comma = 0;
4204 
4205 	if (list == NIL)
4206 		string_append_char(str, "ALL");
4207 	else
4208 	{
4209 		foreach(lc, list)
4210 		{
4211 			Value	   *v = lfirst(lc);
4212 
4213 			if (comma == 0)
4214 				comma = 1;
4215 			else
4216 				string_append_char(str, ", ");
4217 
4218 			string_append_char(str, v->val.str);
4219 		}
4220 	}
4221 }
4222 
4223 static void
_outFunctionParameter(String * str,FunctionParameter * node)4224 _outFunctionParameter(String * str, FunctionParameter *node)
4225 {
4226 	switch (node->mode)
4227 	{
4228 		case FUNC_PARAM_OUT:
4229 			string_append_char(str, "OUT ");
4230 			break;
4231 
4232 		case FUNC_PARAM_INOUT:
4233 			string_append_char(str, "INOUT ");
4234 			break;
4235 
4236 		default:
4237 			break;
4238 	}
4239 
4240 	/* function name */
4241 	if (node->name)
4242 	{
4243 		string_append_char(str, "\"");
4244 		string_append_char(str, node->name);
4245 		string_append_char(str, "\" ");
4246 	}
4247 
4248 	_outNode(str, node->argType);
4249 }
4250 
4251 static void
_outObjectWithArgs(String * str,ObjectWithArgs * node)4252 _outObjectWithArgs(String * str, ObjectWithArgs *node)
4253 {
4254 	_outFuncName(str, node->objname);
4255 	string_append_char(str, "(");
4256 	_outNode(str, node->objargs);
4257 	string_append_char(str, ")");
4258 }
4259 
4260 static void
_outGrantStmt(String * str,GrantStmt * node)4261 _outGrantStmt(String * str, GrantStmt *node)
4262 {
4263 	if (node->is_grant == true)
4264 		string_append_char(str, "GRANT ");
4265 	else
4266 	{
4267 		string_append_char(str, "REVOKE ");
4268 		if (node->grant_option == true)
4269 			string_append_char(str, "GRANT OPTION FOR ");
4270 	}
4271 
4272 	_outPrivilegeList(str, node->privileges);
4273 
4274 	string_append_char(str, " ON ");
4275 
4276 	switch (node->objtype)
4277 	{
4278 		case OBJECT_TABLE:
4279 			_outNode(str, node->objects);
4280 			break;
4281 
4282 		case OBJECT_SEQUENCE:
4283 			string_append_char(str, "SEQUENCE ");
4284 			_outNode(str, node->objects);
4285 			break;
4286 
4287 		case OBJECT_FUNCTION:
4288 			string_append_char(str, "FUNCTION ");
4289 			_outNode(str, node->objects);
4290 			break;
4291 
4292 		case OBJECT_DATABASE:
4293 			string_append_char(str, "DATABASE ");
4294 			_outIdList(str, node->objects);
4295 			break;
4296 
4297 		case OBJECT_LANGUAGE:
4298 			string_append_char(str, "LANGUAGE ");
4299 			_outIdList(str, node->objects);
4300 			break;
4301 
4302 		case OBJECT_SCHEMA:
4303 			string_append_char(str, "SCHEMA ");
4304 			_outIdList(str, node->objects);
4305 			break;
4306 
4307 		case OBJECT_TABLESPACE:
4308 			string_append_char(str, "TABLESPACE ");
4309 			_outIdList(str, node->objects);
4310 			break;
4311 
4312 		case OBJECT_FDW:
4313 			string_append_char(str, "FOREIGN DATA WRAPPER ");
4314 			_outIdList(str, node->objects);
4315 			break;
4316 
4317 		case OBJECT_FOREIGN_SERVER:
4318 			string_append_char(str, "FOREIGN SERVER ");
4319 			_outIdList(str, node->objects);
4320 			break;
4321 
4322 		case OBJECT_COLUMN:
4323 		case OBJECT_DOMAIN:
4324 		case OBJECT_LARGEOBJECT:
4325 		case OBJECT_TYPE:
4326 		case OBJECT_ACCESS_METHOD:
4327 		case OBJECT_AGGREGATE:
4328 		case OBJECT_AMOP:
4329 		case OBJECT_AMPROC:
4330 		case OBJECT_ATTRIBUTE:
4331 		case OBJECT_CAST:
4332 		case OBJECT_COLLATION:
4333 		case OBJECT_CONVERSION:
4334 		case OBJECT_DEFAULT:
4335 		case OBJECT_DEFACL:
4336 		case OBJECT_DOMCONSTRAINT:
4337 		case OBJECT_EVENT_TRIGGER:
4338 		case OBJECT_EXTENSION:
4339 		case OBJECT_FOREIGN_TABLE:
4340 		case OBJECT_INDEX:
4341 		case OBJECT_MATVIEW:
4342 		case OBJECT_OPCLASS:
4343 		case OBJECT_OPERATOR:
4344 		case OBJECT_OPFAMILY:
4345 		case OBJECT_POLICY:
4346 		case OBJECT_PROCEDURE:
4347 		case OBJECT_PUBLICATION:
4348 		case OBJECT_PUBLICATION_REL:
4349 		case OBJECT_ROLE:
4350 		case OBJECT_ROUTINE:
4351 		case OBJECT_RULE:
4352 		case OBJECT_SUBSCRIPTION:
4353 		case OBJECT_STATISTIC_EXT:
4354 		case OBJECT_TABCONSTRAINT:
4355 		case OBJECT_TRANSFORM:
4356 		case OBJECT_TRIGGER:
4357 		case OBJECT_TSCONFIGURATION:
4358 		case OBJECT_TSDICTIONARY:
4359 		case OBJECT_TSPARSER:
4360 		case OBJECT_TSTEMPLATE:
4361 		case OBJECT_USER_MAPPING:
4362 		case OBJECT_VIEW:
4363 			break;
4364 	}
4365 
4366 	if (node->is_grant == true)
4367 		string_append_char(str, " TO ");
4368 	else
4369 		string_append_char(str, " FROM ");
4370 	_outNode(str, node->grantees);
4371 
4372 	if (node->is_grant == true && node->grant_option == TRUE)
4373 		string_append_char(str, " WITH GRANT OPTION");
4374 
4375 	if (node->behavior == DROP_CASCADE)
4376 		string_append_char(str, " CASCADE");
4377 }
4378 
4379 static void
_outGrantRoleStmt(String * str,GrantRoleStmt * node)4380 _outGrantRoleStmt(String * str, GrantRoleStmt *node)
4381 {
4382 	if (node->is_grant == true)
4383 		string_append_char(str, "GRANT ");
4384 	else
4385 	{
4386 		string_append_char(str, "REVOKE ");
4387 		if (node->admin_opt == true)
4388 			string_append_char(str, "ADMIN OPTION FOR ");
4389 	}
4390 
4391 	_outIdList(str, node->granted_roles);
4392 
4393 	string_append_char(str, node->is_grant == true ? " TO " : " FROM ");
4394 
4395 	_outIdList(str, node->grantee_roles);
4396 
4397 	if (node->admin_opt == true && node->is_grant == true)
4398 		string_append_char(str, "  WITH ADMIN OPTION");
4399 
4400 	if (node->grantor != NULL)
4401 	{
4402 		string_append_char(str, " GRANTED BY \"");
4403 		_outNode(str, node->grantor);
4404 		string_append_char(str, "\"");
4405 	}
4406 
4407 	if (node->behavior == DROP_CASCADE)
4408 		string_append_char(str, " CASCADE");
4409 }
4410 
4411 static void
_outFuncOptList(String * str,List * list)4412 _outFuncOptList(String * str, List *list)
4413 {
4414 	ListCell   *lc;
4415 
4416 	foreach(lc, list)
4417 	{
4418 		DefElem    *e = lfirst(lc);
4419 		Value	   *v = (Value *) e->arg;
4420 
4421 		if (strcmp(e->defname, "strict") == 0)
4422 		{
4423 			if (v->val.ival == TRUE)
4424 				string_append_char(str, " STRICT");
4425 			else
4426 				string_append_char(str, " CALLED ON NULL INPUT");
4427 		}
4428 		else if (strcmp(e->defname, "volatility") == 0)
4429 		{
4430 			char	   *s = v->val.str;
4431 
4432 			if (strcmp(s, "immutable") == 0)
4433 				string_append_char(str, " IMMUTABLE");
4434 			else if (strcmp(s, "stable") == 0)
4435 				string_append_char(str, " STABLE");
4436 			else if (strcmp(s, "volatile") == 0)
4437 				string_append_char(str, " VOLATILE");
4438 		}
4439 		else if (strcmp(e->defname, "security") == 0)
4440 		{
4441 			if (v->val.ival == TRUE)
4442 				string_append_char(str, " SECURITY DEFINER");
4443 			else
4444 				string_append_char(str, " SECURITY INVOKER");
4445 		}
4446 		else if (strcmp(e->defname, "as") == 0)
4447 		{
4448 			string_append_char(str, " AS ");
4449 			_outNode(str, e->arg);
4450 		}
4451 		else if (strcmp(e->defname, "language") == 0)
4452 		{
4453 			string_append_char(str, " LANGUAGE '");
4454 			string_append_char(str, v->val.str);
4455 			string_append_char(str, "'");
4456 		}
4457 	}
4458 }
4459 
4460 static void
_outCreateFunctionStmt(String * str,CreateFunctionStmt * node)4461 _outCreateFunctionStmt(String * str, CreateFunctionStmt *node)
4462 {
4463 	string_append_char(str, "CREATE ");
4464 	if (node->replace == true)
4465 		string_append_char(str, "OR REPLACE ");
4466 	string_append_char(str, "FUNCTION ");
4467 
4468 	_outFuncName(str, node->funcname);
4469 
4470 	string_append_char(str, " (");
4471 	_outNode(str, node->parameters);
4472 	string_append_char(str, ")");
4473 
4474 	if (node->returnType)
4475 	{
4476 		string_append_char(str, " RETURNS ");
4477 		_outNode(str, node->returnType);
4478 	}
4479 
4480 	_outFuncOptList(str, node->options);
4481 }
4482 
4483 static void
_outAlterFunctionStmt(String * str,AlterFunctionStmt * node)4484 _outAlterFunctionStmt(String * str, AlterFunctionStmt *node)
4485 {
4486 	string_append_char(str, "ALTER FUNCTION ");
4487 	_outNode(str, node->func);
4488 	_outFuncOptList(str, node->actions);
4489 }
4490 
4491 
4492 static void
_outCreateCastStmt(String * str,CreateCastStmt * node)4493 _outCreateCastStmt(String * str, CreateCastStmt *node)
4494 {
4495 	string_append_char(str, "CREATE CAST (");
4496 	_outNode(str, node->sourcetype);
4497 	string_append_char(str, " AS ");
4498 	_outNode(str, node->targettype);
4499 	string_append_char(str, ") WITH FUNCTION ");
4500 	_outNode(str, node->func);
4501 
4502 	switch (node->context)
4503 	{
4504 		case COERCION_IMPLICIT:
4505 			string_append_char(str, " AS IMPLICIT");
4506 			break;
4507 
4508 		case COERCION_ASSIGNMENT:
4509 			string_append_char(str, " AS ASSIGNMENT");
4510 			break;
4511 
4512 		default:
4513 			break;
4514 	}
4515 }
4516 
4517 static void
_outReindexStmt(String * str,ReindexStmt * node)4518 _outReindexStmt(String * str, ReindexStmt *node)
4519 {
4520 	string_append_char(str, "REINDEX ");
4521 
4522 	switch (node->kind)
4523 	{
4524 		case REINDEX_OBJECT_SYSTEM:
4525 			string_append_char(str, "SYSTEM ");
4526 			break;
4527 
4528 		case REINDEX_OBJECT_DATABASE:
4529 			string_append_char(str, "DATABASE ");
4530 			break;
4531 
4532 		case REINDEX_OBJECT_INDEX:
4533 			string_append_char(str, "INDEX ");
4534 			break;
4535 
4536 		case REINDEX_OBJECT_TABLE:
4537 			string_append_char(str, "TABLE ");
4538 			break;
4539 
4540 		default:
4541 			break;
4542 	}
4543 
4544 	if (node->relation)
4545 		_outNode(str, node->relation);
4546 
4547 	if (node->name)
4548 	{
4549 		string_append_char(str, "\"");
4550 		string_append_char(str, (char *) node->name);
4551 		string_append_char(str, "\"");
4552 	}
4553 }
4554 
4555 static void
_outAlterObjectSchemaStmt(String * str,AlterObjectSchemaStmt * node)4556 _outAlterObjectSchemaStmt(String * str, AlterObjectSchemaStmt *node)
4557 {
4558 	string_append_char(str, "ALTER ");
4559 
4560 	ObjectWithArgs *owa = castNode(ObjectWithArgs, node);
4561 
4562 	switch (node->objectType)
4563 	{
4564 		case OBJECT_AGGREGATE:
4565 			string_append_char(str, "AGGREGATE ");
4566 			_outFuncName(str, owa->objname);
4567 			string_append_char(str, "(");
4568 			if (lfirst(list_head(owa->objargs)) == NULL)
4569 				string_append_char(str, "*");
4570 			else
4571 				_outNode(str, lfirst(list_head(owa->objargs)));
4572 			string_append_char(str, ") SET SCHAME \"");
4573 			string_append_char(str, node->newschema);
4574 			string_append_char(str, "\"");
4575 			break;
4576 
4577 		case OBJECT_DOMAIN:
4578 			string_append_char(str, "DOMAIN ");
4579 			_outFuncName(str, owa->objname);
4580 			string_append_char(str, " SET SCHEMA \"");
4581 			string_append_char(str, node->newschema);
4582 			string_append_char(str, "\"");
4583 			break;
4584 
4585 		case OBJECT_FUNCTION:
4586 			string_append_char(str, "FUNCTION ");
4587 			_outFuncName(str, owa->objname);
4588 			string_append_char(str, "(");
4589 			string_append_char(str, ") SET SCHEMA \"");
4590 			string_append_char(str, node->newschema);
4591 			string_append_char(str, "\"");
4592 			break;
4593 
4594 		case OBJECT_SEQUENCE:
4595 			string_append_char(str, "SEQUENCE ");
4596 			_outNode(str, node->relation);
4597 			string_append_char(str, " SET SCHEMA \"");
4598 			string_append_char(str, node->newschema);
4599 			string_append_char(str, "\"");
4600 			break;
4601 
4602 		case OBJECT_TABLE:
4603 			string_append_char(str, "TABLE ");
4604 			_outNode(str, node->relation);
4605 			string_append_char(str, " SET SCHEMA \"");
4606 			string_append_char(str, node->newschema);
4607 			string_append_char(str, "\"");
4608 			break;
4609 
4610 		case OBJECT_TYPE:
4611 			string_append_char(str, "TYPE ");
4612 			_outFuncName(str, owa->objname);
4613 			string_append_char(str, " SET SCHEMA \"");
4614 			string_append_char(str, node->newschema);
4615 			string_append_char(str, "\"");
4616 			break;
4617 
4618 		default:
4619 			break;
4620 	}
4621 }
4622 
4623 static void
_outAlterOwnerStmt(String * str,AlterOwnerStmt * node)4624 _outAlterOwnerStmt(String * str, AlterOwnerStmt *node)
4625 {
4626 	string_append_char(str, "ALTER ");
4627 
4628 	ObjectWithArgs *owa = castNode(ObjectWithArgs, node);
4629 
4630 	switch (node->objectType)
4631 	{
4632 		case OBJECT_AGGREGATE:
4633 			string_append_char(str, "AGGREGATE ");
4634 			_outFuncName(str, owa->objname);
4635 			string_append_char(str, "(");
4636 			if (lfirst(list_head(owa->objargs)) == NULL)
4637 				string_append_char(str, "*");
4638 			else
4639 				_outNode(str, lfirst(list_head(owa->objargs)));
4640 			string_append_char(str, ") OWNER TO \"");
4641 			_outNode(str, node->newowner);
4642 			string_append_char(str, "\"");
4643 			break;
4644 
4645 		case OBJECT_CONVERSION:
4646 			string_append_char(str, "CONVERSION \"");
4647 			string_append_char(str, strVal(linitial(owa->objname)));
4648 			string_append_char(str, "\" OWNER TO \"");
4649 			_outNode(str, node->newowner);
4650 			string_append_char(str, "\"");
4651 			break;
4652 
4653 		case OBJECT_DATABASE:
4654 			string_append_char(str, "DATABASE \"");
4655 			string_append_char(str, strVal(linitial(owa->objname)));
4656 			string_append_char(str, "\" OWNER TO \"");
4657 			_outNode(str, node->newowner);
4658 			string_append_char(str, "\"");
4659 			break;
4660 
4661 		case OBJECT_DOMAIN:
4662 			string_append_char(str, "DOMAIN \"");
4663 			string_append_char(str, strVal(linitial(owa->objname)));
4664 			string_append_char(str, "\" OWNER TO \"");
4665 			_outNode(str, node->newowner);
4666 			string_append_char(str, "\"");
4667 			break;
4668 
4669 		case OBJECT_FUNCTION:
4670 			string_append_char(str, "FUNCTION ");
4671 			_outFuncName(str, owa->objname);
4672 			string_append_char(str, "(");
4673 			_outNode(str, owa->objargs);
4674 			string_append_char(str, ") OWNER TO \"");
4675 			_outNode(str, node->newowner);
4676 			string_append_char(str, "\"");
4677 			break;
4678 
4679 		case OBJECT_LANGUAGE:
4680 			string_append_char(str, "LANGUAGE \"");
4681 			string_append_char(str, strVal(linitial(owa->objname)));
4682 			string_append_char(str, "\" OWNER TO \"");
4683 			_outNode(str, node->newowner);
4684 			string_append_char(str, "\"");
4685 			break;
4686 
4687 		case OBJECT_OPERATOR:
4688 			string_append_char(str, "OPERATOR ");
4689 			_outOperatorName(str, owa->objname);
4690 			string_append_char(str, "(");
4691 			string_append_char(str, ") OWNER TO \"");
4692 			_outNode(str, node->newowner);
4693 			string_append_char(str, "\"");
4694 			break;
4695 
4696 		case OBJECT_OPCLASS:
4697 			string_append_char(str, "OPERATOR CLASS ");
4698 			_outFuncName(str, owa->objname);
4699 			string_append_char(str, " USING ");
4700 			string_append_char(str, strVal(linitial(owa->objargs)));
4701 			string_append_char(str, " OWNER TO \"");
4702 			_outNode(str, node->newowner);
4703 			string_append_char(str, "\"");
4704 			break;
4705 
4706 		case OBJECT_OPFAMILY:
4707 			string_append_char(str, "OPERATOR FAMILY ");
4708 			_outFuncName(str, owa->objname);
4709 			string_append_char(str, " USING ");
4710 			string_append_char(str, strVal(linitial(owa->objargs)));
4711 			string_append_char(str, " OWNER TO \"");
4712 			_outNode(str, node->newowner);
4713 			string_append_char(str, "\"");
4714 			break;
4715 
4716 		case OBJECT_SCHEMA:
4717 			string_append_char(str, "SCHEMA \"");
4718 			string_append_char(str, strVal(linitial(owa->objname)));
4719 			string_append_char(str, "\" OWNER TO \"");
4720 			_outNode(str, node->newowner);
4721 			string_append_char(str, "\"");
4722 			break;
4723 
4724 		case OBJECT_TYPE:
4725 			string_append_char(str, "TYPE \"");
4726 			string_append_char(str, strVal(linitial(owa->objname)));
4727 			string_append_char(str, "\" OWNER TO \"");
4728 			_outNode(str, node->newowner);
4729 			string_append_char(str, "\"");
4730 			break;
4731 
4732 		case OBJECT_TABLESPACE:
4733 			string_append_char(str, "TABLESPACE \"");
4734 			string_append_char(str, strVal(linitial(owa->objname)));
4735 			string_append_char(str, "\" OWNER TO \"");
4736 			_outNode(str, node->newowner);
4737 			string_append_char(str, "\"");
4738 			break;
4739 
4740 		case OBJECT_TSDICTIONARY:
4741 			string_append_char(str, "TEXT SEARCH DICTIONARY \"");
4742 			string_append_char(str, strVal(linitial(owa->objname)));
4743 			string_append_char(str, "\" OWNER TO \"");
4744 			_outNode(str, node->newowner);
4745 			string_append_char(str, "\"");
4746 			break;
4747 
4748 		case OBJECT_TSCONFIGURATION:
4749 			string_append_char(str, "TEXT SEARCH CONFIGURATION \"");
4750 			string_append_char(str, strVal(linitial(owa->objname)));
4751 			string_append_char(str, "\" OWNER TO \"");
4752 			_outNode(str, node->newowner);
4753 			string_append_char(str, "\"");
4754 			break;
4755 
4756 		case OBJECT_FDW:
4757 			string_append_char(str, "FOREIGN DATA WRAPPER \"");
4758 			string_append_char(str, strVal(linitial(owa->objname)));
4759 			string_append_char(str, "\" OWNER TO \"");
4760 			_outNode(str, node->newowner);
4761 			string_append_char(str, "\"");
4762 			break;
4763 
4764 		case OBJECT_FOREIGN_SERVER:
4765 			string_append_char(str, "SERVER \"");
4766 			string_append_char(str, strVal(linitial(owa->objname)));
4767 			string_append_char(str, "\" OWNER TO \"");
4768 			_outNode(str, node->newowner);
4769 			string_append_char(str, "\"");
4770 			break;
4771 
4772 		default:
4773 			break;
4774 	}
4775 }
4776 
4777 static void
_outRuleStmt(String * str,RuleStmt * node)4778 _outRuleStmt(String * str, RuleStmt *node)
4779 {
4780 	string_append_char(str, "CREATE ");
4781 	if (node->replace)
4782 		string_append_char(str, "OR REPLACE ");
4783 	string_append_char(str, "RULE \"");
4784 	string_append_char(str, node->rulename);
4785 	string_append_char(str, "\" AS ON ");
4786 
4787 	switch (node->event)
4788 	{
4789 		case CMD_SELECT:
4790 			string_append_char(str, "SELECT");
4791 			break;
4792 
4793 		case CMD_UPDATE:
4794 			string_append_char(str, "UPDATE");
4795 			break;
4796 
4797 		case CMD_DELETE:
4798 			string_append_char(str, "DELETE");
4799 			break;
4800 
4801 		case CMD_INSERT:
4802 			string_append_char(str, "INSERT");
4803 			break;
4804 
4805 		default:
4806 			break;
4807 	}
4808 
4809 	string_append_char(str, " TO ");
4810 	_outNode(str, node->relation);
4811 
4812 	if (node->whereClause)
4813 	{
4814 		string_append_char(str, " WHERE ");
4815 		_outNode(str, node->whereClause);
4816 	}
4817 
4818 	string_append_char(str, " DO ");
4819 
4820 	if (node->instead)
4821 		string_append_char(str, "INSTEAD ");
4822 
4823 	if (node->actions == NIL)
4824 		string_append_char(str, "NOTHING");
4825 	else if (list_length(node->actions) == 1)
4826 		_outNode(str, linitial(node->actions));
4827 	else
4828 	{
4829 		ListCell   *lc;
4830 		char		semi = 0;
4831 
4832 		string_append_char(str, "(");
4833 
4834 		foreach(lc, node->actions)
4835 		{
4836 			if (semi == 0)
4837 				semi = 1;
4838 			else
4839 				string_append_char(str, ";");
4840 
4841 			_outNode(str, lfirst(lc));
4842 		}
4843 
4844 		string_append_char(str, ")");
4845 	}
4846 }
4847 
4848 static void
_outViewStmt(String * str,ViewStmt * node)4849 _outViewStmt(String * str, ViewStmt *node)
4850 {
4851 	if (node->replace)
4852 		string_append_char(str, "CREATE OR REPLACE ");
4853 	else
4854 		string_append_char(str, "CREATE ");
4855 
4856 	if (node->view->relpersistence == RELPERSISTENCE_TEMP)
4857 		string_append_char(str, "TEMP ");
4858 
4859 	string_append_char(str, "VIEW ");
4860 	_outNode(str, node->view);
4861 
4862 	if (node->aliases)
4863 	{
4864 		string_append_char(str, "(");
4865 		_outIdList(str, node->aliases);
4866 		string_append_char(str, ")");
4867 	}
4868 
4869 	string_append_char(str, " AS");
4870 	_outNode(str, node->query);
4871 }
4872 
4873 static void
_outCreatedbOptList(String * str,List * options)4874 _outCreatedbOptList(String * str, List *options)
4875 {
4876 	ListCell   *lc;
4877 
4878 	foreach(lc, options)
4879 	{
4880 		DefElem    *e = lfirst(lc);
4881 		Value	   *v = (Value *) e->arg;
4882 
4883 		/* keyword */
4884 		if (strcmp(e->defname, "template") == 0)
4885 			string_append_char(str, " TEMPLATE ");
4886 		else if (strcmp(e->defname, "location") == 0)
4887 		{
4888 			string_append_char(str, " LOCATION ");
4889 		}
4890 		else if (strcmp(e->defname, "tablespace") == 0)
4891 			string_append_char(str, " TABLESPACE ");
4892 		else if (strcmp(e->defname, "encoding") == 0)
4893 		{
4894 			string_append_char(str, " ENCODING ");
4895 		}
4896 		else if (strcmp(e->defname, "owner") == 0)
4897 			string_append_char(str, " OWNER ");
4898 		else if (strcmp(e->defname, "connectionlimit") == 0)
4899 			string_append_char(str, " CONNECTION LIMIT ");
4900 
4901 		/* value */
4902 		if (v == NULL)
4903 			string_append_char(str, "DEFAULT");
4904 		else if (IsA((Node *) v, String))
4905 		{
4906 			string_append_char(str, "'");
4907 			string_append_char(str, v->val.str);
4908 			string_append_char(str, "'");
4909 		}
4910 		else
4911 		{
4912 			char		buf[16];
4913 
4914 			snprintf(buf, sizeof(buf), "%d", v->val.ival);
4915 			string_append_char(str, buf);
4916 		}
4917 	}
4918 }
4919 
4920 static void
_outCreatedbStmt(String * str,CreatedbStmt * node)4921 _outCreatedbStmt(String * str, CreatedbStmt *node)
4922 {
4923 	string_append_char(str, "CREATE DATABASE \"");
4924 	string_append_char(str, node->dbname);
4925 	string_append_char(str, "\"");
4926 
4927 	_outCreatedbOptList(str, node->options);
4928 }
4929 
4930 static void
_outAlterDatabaseStmt(String * str,AlterDatabaseStmt * node)4931 _outAlterDatabaseStmt(String * str, AlterDatabaseStmt *node)
4932 {
4933 	string_append_char(str, "ALTER DATABASE \"");
4934 	string_append_char(str, node->dbname);
4935 	string_append_char(str, "\" ");
4936 
4937 	_outCreatedbOptList(str, node->options);
4938 }
4939 
4940 static void
_outAlterDatabaseSetStmt(String * str,AlterDatabaseSetStmt * node)4941 _outAlterDatabaseSetStmt(String * str, AlterDatabaseSetStmt *node)
4942 {
4943 	string_append_char(str, "ALTER DATABASE \"");
4944 	string_append_char(str, node->dbname);
4945 	string_append_char(str, "\" ");
4946 
4947 	_outNode(str, node->setstmt);
4948 }
4949 
4950 static void
_outDropdbStmt(String * str,DropdbStmt * node)4951 _outDropdbStmt(String * str, DropdbStmt *node)
4952 {
4953 	string_append_char(str, "DROP DATABASE \"");
4954 	string_append_char(str, node->dbname);
4955 	string_append_char(str, "\"");
4956 }
4957 
4958 static void
_outCreateDomainStmt(String * str,CreateDomainStmt * node)4959 _outCreateDomainStmt(String * str, CreateDomainStmt *node)
4960 {
4961 	ListCell   *lc;
4962 
4963 	string_append_char(str, "CREATE DOMAIN ");
4964 	_outFuncName(str, node->domainname);
4965 	string_append_char(str, " ");
4966 	_outNode(str, node->typeName);
4967 
4968 
4969 	foreach(lc, node->constraints)
4970 	{
4971 		string_append_char(str, " ");
4972 		_outNode(str, lfirst(lc));
4973 	}
4974 }
4975 
4976 static void
_outAlterDomainStmt(String * str,AlterDomainStmt * node)4977 _outAlterDomainStmt(String * str, AlterDomainStmt *node)
4978 {
4979 	string_append_char(str, "ALTER DOMAIN ");
4980 	_outFuncName(str, node->typeName);
4981 
4982 	switch (node->subtype)
4983 	{
4984 		case 'T':
4985 			if (node->def)
4986 			{
4987 				string_append_char(str, " SET DEFAULT ");
4988 				_outNode(str, node->def);
4989 			}
4990 			else
4991 				string_append_char(str, " DROP DEFAULT");
4992 			break;
4993 
4994 		case 'N':
4995 			string_append_char(str, " DROP NOT NULL");
4996 			break;
4997 
4998 		case 'O':
4999 			string_append_char(str, " SET NOT NULL");
5000 			break;
5001 
5002 		case 'C':
5003 			string_append_char(str, " ADD ");
5004 			_outNode(str, node->def);
5005 			break;
5006 
5007 		case 'X':
5008 			string_append_char(str, " DROP CONSTRAINT \"");
5009 			string_append_char(str, node->name);
5010 			string_append_char(str, "\"");
5011 			if (node->behavior == DROP_CASCADE)
5012 				string_append_char(str, " CASCADE");
5013 			break;
5014 	}
5015 }
5016 
5017 static void
_outCreateConversionStmt(String * str,CreateConversionStmt * node)5018 _outCreateConversionStmt(String * str, CreateConversionStmt *node)
5019 {
5020 	string_append_char(str, "CREATE ");
5021 
5022 	if (node->def == TRUE)
5023 		string_append_char(str, "DEFAULT ");
5024 
5025 	string_append_char(str, "CONVERSION ");
5026 
5027 	_outFuncName(str, node->conversion_name);
5028 
5029 	string_append_char(str, " FOR '");
5030 	string_append_char(str, node->for_encoding_name);
5031 	string_append_char(str, "' TO '");
5032 	string_append_char(str, node->to_encoding_name);
5033 	string_append_char(str, " FROM ");
5034 	_outFuncName(str, node->func_name);
5035 }
5036 
5037 static void
_outPrepareStmt(String * str,PrepareStmt * node)5038 _outPrepareStmt(String * str, PrepareStmt *node)
5039 {
5040 	string_append_char(str, "PREPARE \"");
5041 	string_append_char(str, node->name);
5042 	string_append_char(str, "\" ");
5043 
5044 	if (node->argtypes != NIL)
5045 	{
5046 		string_append_char(str, "(");
5047 		_outNode(str, node->argtypes);
5048 		string_append_char(str, ") ");
5049 	}
5050 
5051 	string_append_char(str, "AS ");
5052 	_outNode(str, node->query);
5053 }
5054 
5055 static void
_outExecuteStmt(String * str,ExecuteStmt * node)5056 _outExecuteStmt(String * str, ExecuteStmt *node)
5057 {
5058 	string_append_char(str, "EXECUTE \"");
5059 	string_append_char(str, node->name);
5060 	string_append_char(str, "\" ");
5061 
5062 	if (node->params != NIL)
5063 	{
5064 		string_append_char(str, "(");
5065 		_outNode(str, node->params);
5066 		string_append_char(str, ")");
5067 	}
5068 }
5069 
5070 static void
_outLockStmt(String * str,LockStmt * node)5071 _outLockStmt(String * str, LockStmt *node)
5072 {
5073 	string_append_char(str, "LOCK TABLE ");
5074 	_outNode(str, node->relations);
5075 
5076 	string_append_char(str, " IN ");
5077 	switch (node->mode)
5078 	{
5079 		case AccessShareLock:
5080 			string_append_char(str, "ACCESS SHARE ");
5081 			break;
5082 
5083 		case RowShareLock:
5084 			string_append_char(str, "ROW SHARE ");
5085 			break;
5086 
5087 		case RowExclusiveLock:
5088 			string_append_char(str, "ROW EXCLUSIVE ");
5089 			break;
5090 
5091 		case ShareUpdateExclusiveLock:
5092 			string_append_char(str, "SHARE UPDATE EXCLUSIVE ");
5093 			break;
5094 
5095 		case ShareLock:
5096 			string_append_char(str, "SHARE ");
5097 			break;
5098 
5099 		case ShareRowExclusiveLock:
5100 			string_append_char(str, "SHARE ROW EXCLUSIVE ");
5101 			break;
5102 
5103 		case ExclusiveLock:
5104 			string_append_char(str, "EXCLUSIVE ");
5105 			break;
5106 
5107 		case AccessExclusiveLock:
5108 			string_append_char(str, "ACCESS EXCLUSIVE ");
5109 			break;
5110 	}
5111 	string_append_char(str, "MODE");
5112 
5113 	if (node->nowait == TRUE)
5114 		string_append_char(str, " NOWAIT");
5115 }
5116 
5117 static void
_outOperatorArgTypes(String * str,List * args)5118 _outOperatorArgTypes(String * str, List *args)
5119 {
5120 	TypeName   *left,
5121 			   *right;
5122 
5123 	left = linitial(args);
5124 	right = lsecond(args);
5125 
5126 	if (left)
5127 		_outNode(str, left);
5128 	else
5129 		string_append_char(str, "NONE");
5130 	string_append_char(str, ", ");
5131 	if (right)
5132 		_outNode(str, right);
5133 	else
5134 		string_append_char(str, "NONE");
5135 }
5136 
5137 static void
_outCommentStmt(String * str,CommentStmt * node)5138 _outCommentStmt(String * str, CommentStmt *node)
5139 {
5140 	TypeName   *t;
5141 	Value	   *v;
5142 	char		buf[16];
5143 
5144 	string_append_char(str, "COMMENT ON ");
5145 
5146 	ObjectWithArgs *owa = castNode(ObjectWithArgs, node);
5147 
5148 	switch (node->objtype)
5149 	{
5150 		case OBJECT_AGGREGATE:
5151 			string_append_char(str, "AGGREGATE ");
5152 			_outFuncName(str, owa->objname);
5153 			string_append_char(str, "(");
5154 
5155 			t = linitial(owa->objargs);
5156 			if (t)
5157 				_outNode(str, t);
5158 			else
5159 				string_append_char(str, "*");
5160 			string_append_char(str, ")");
5161 			break;
5162 
5163 		case OBJECT_FUNCTION:
5164 			string_append_char(str, "FUNCTION ");
5165 			_outFuncName(str, owa->objname);
5166 			string_append_char(str, "(");
5167 			_outNode(str, owa->objargs);
5168 			string_append_char(str, ")");
5169 			break;
5170 
5171 		case OBJECT_OPERATOR:
5172 			string_append_char(str, "OPERATOR ");
5173 			_outOperatorName(str, owa->objname);
5174 			string_append_char(str, "(");
5175 			_outOperatorArgTypes(str, owa->objargs);
5176 			string_append_char(str, ")");
5177 			break;
5178 
5179 		case OBJECT_TABCONSTRAINT:
5180 		case OBJECT_DOMCONSTRAINT:
5181 			string_append_char(str, "CONSTRAINT \"");
5182 			v = lsecond(owa->objname);
5183 			string_append_char(str, v->val.str);
5184 			string_append_char(str, "\" ON ");
5185 			_outFuncName(str, linitial(owa->objargs));
5186 			break;
5187 
5188 		case OBJECT_RULE:
5189 			string_append_char(str, "RULE \"");
5190 			v = lsecond(owa->objname);
5191 			string_append_char(str, v->val.str);
5192 			string_append_char(str, "\" ON ");
5193 			_outFuncName(str, linitial(owa->objargs));
5194 			break;
5195 
5196 		case OBJECT_TRIGGER:
5197 			string_append_char(str, "TRIGGER \"");
5198 			v = lsecond(owa->objname);
5199 			string_append_char(str, v->val.str);
5200 			string_append_char(str, "\" ON ");
5201 			_outFuncName(str, linitial(owa->objargs));
5202 			break;
5203 
5204 		case OBJECT_OPCLASS:
5205 			string_append_char(str, "OPERATOR CLASS ");
5206 			_outFuncName(str, owa->objname);
5207 			string_append_char(str, " USING ");
5208 			v = linitial(owa->objargs);
5209 			string_append_char(str, v->val.str);
5210 			break;
5211 
5212 		case OBJECT_LARGEOBJECT:
5213 			string_append_char(str, "LARGE OBJECT ");
5214 			v = linitial(owa->objname);
5215 			if (IsA(v, String))
5216 				string_append_char(str, v->val.str);
5217 			else if (IsA(v, Integer))
5218 			{
5219 				snprintf(buf, 16, "%d", v->val.ival);
5220 				string_append_char(str, buf);
5221 			}
5222 			break;
5223 
5224 		case OBJECT_CAST:
5225 			string_append_char(str, "CAST (");
5226 			_outNode(str, linitial(owa->objname));
5227 			string_append_char(str, " AS ");
5228 			_outNode(str, linitial(owa->objargs));
5229 			string_append_char(str, ")");
5230 			break;
5231 
5232 		case OBJECT_LANGUAGE:
5233 			string_append_char(str, "LANGUAGE ");
5234 			_outFuncName(str, owa->objname);
5235 			break;
5236 
5237 		default:
5238 			switch (node->objtype)
5239 			{
5240 				case OBJECT_COLUMN:
5241 					string_append_char(str, "COLUMN ");
5242 					break;
5243 				case OBJECT_DATABASE:
5244 					string_append_char(str, "DATABASE ");
5245 					break;
5246 				case OBJECT_SCHEMA:
5247 					string_append_char(str, "SCHEMA ");
5248 					break;
5249 				case OBJECT_INDEX:
5250 					string_append_char(str, "INDEX ");
5251 					break;
5252 				case OBJECT_SEQUENCE:
5253 					string_append_char(str, "SEQUENCE ");
5254 					break;
5255 				case OBJECT_TABLE:
5256 					string_append_char(str, "TABLE ");
5257 					break;
5258 				case OBJECT_DOMAIN:
5259 					string_append_char(str, "DOMAIN ");
5260 					break;
5261 				case OBJECT_TYPE:
5262 					string_append_char(str, "TYPE ");
5263 					break;
5264 				case OBJECT_VIEW:
5265 					string_append_char(str, "VIEW ");
5266 					break;
5267 				default:
5268 					break;
5269 			}
5270 			_outFuncName(str, owa->objname);
5271 			break;
5272 	}
5273 
5274 	string_append_char(str, " IS ");
5275 	if (node->comment)
5276 	{
5277 		string_append_char(str, "'");
5278 		string_append_char(str, node->comment);
5279 		string_append_char(str, "'");
5280 	}
5281 	else
5282 		string_append_char(str, "NULL");
5283 }
5284 
5285 static void
_outRangeSubselect(String * str,RangeSubselect * node)5286 _outRangeSubselect(String * str, RangeSubselect *node)
5287 {
5288 	string_append_char(str, "(");
5289 	_outNode(str, node->subquery);
5290 	string_append_char(str, ")");
5291 
5292 	_outNode(str, node->alias);
5293 }
5294 
5295 /*TODO*/
5296 static void
_outRangeFunction(String * str,RangeFunction * node)5297 _outRangeFunction(String * str, RangeFunction *node)
5298 {
5299 	_outNode(str, node->functions);
5300 	//TODO
5301 		if (node->alias)
5302 	{
5303 		_outNode(str, node->alias);
5304 	}
5305 
5306 	if (node->coldeflist)
5307 	{
5308 		string_append_char(str, " (");
5309 		_outNode(str, node->coldeflist);
5310 		string_append_char(str, ")");
5311 	}
5312 }
5313 
5314 static void
_outRangeTableSample(String * str,RangeTableSample * node)5315 _outRangeTableSample(String * str, RangeTableSample *node)
5316 {
5317 	_outNode(str, node->relation);
5318 	string_append_char(str, " TABLESAMPLE ");
5319 	_outFuncName(str, node->method);
5320 	string_append_char(str, " (");
5321 	_outNode(str, node->args);
5322 	string_append_char(str, ")");
5323 
5324 	if (node->repeatable)
5325 	{
5326 		string_append_char(str, " REPEATABLE (");
5327 		_outNode(str, node->repeatable);
5328 		string_append_char(str, ")");
5329 	}
5330 }
5331 
5332 static void
_outRangeTableFunc(String * str,RangeTableFunc * node)5333 _outRangeTableFunc(String * str, RangeTableFunc *node)
5334 {
5335 }
5336 
5337 static void
_outRangeTableFuncCol(String * str,RangeTableFuncCol * node)5338 _outRangeTableFuncCol(String * str, RangeTableFuncCol *node)
5339 {
5340 }
5341 
5342 static void
_outDiscardStmt(String * str,DiscardStmt * node)5343 _outDiscardStmt(String * str, DiscardStmt *node)
5344 {
5345 	switch (node->target)
5346 	{
5347 		case DISCARD_ALL:
5348 			string_append_char(str, "DISCARD ALL");
5349 			break;
5350 
5351 		case DISCARD_TEMP:
5352 			string_append_char(str, "DISCARD TEMP");
5353 			break;
5354 
5355 		case DISCARD_PLANS:
5356 			string_append_char(str, "DISCARD PLANS");
5357 			break;
5358 
5359 		default:
5360 			break;
5361 	}
5362 }
5363 
5364 static void
_outCreateOpFamilyStmt(String * str,CreateOpFamilyStmt * node)5365 _outCreateOpFamilyStmt(String * str, CreateOpFamilyStmt *node)
5366 {
5367 	string_append_char(str, "CREATE OPERATOR FAMILY ");
5368 	_outIdList(str, node->opfamilyname);
5369 	string_append_char(str, " USING \"");
5370 	string_append_char(str, node->amname);
5371 	string_append_char(str, "\"");
5372 }
5373 
5374 static void
_outAlterOpFamilyStmt(String * str,AlterOpFamilyStmt * node)5375 _outAlterOpFamilyStmt(String * str, AlterOpFamilyStmt *node)
5376 {
5377 }
5378 
5379 static void
_outCreateEnumStmt(String * str,CreateEnumStmt * node)5380 _outCreateEnumStmt(String * str, CreateEnumStmt *node)
5381 {
5382 	string_append_char(str, "CREATE TYPE ");
5383 	_outIdList(str, node->typeName);
5384 	string_append_char(str, " AS ENUM (");
5385 	_outNode(str, node->vals);
5386 	string_append_char(str, ")");
5387 }
5388 
5389 static void
_outDropOwnedStmt(String * str,DropOwnedStmt * node)5390 _outDropOwnedStmt(String * str, DropOwnedStmt *node)
5391 {
5392 	string_append_char(str, "DROP OWNED BY ");
5393 	_outIdList(str, node->roles);
5394 	if (node->behavior == DROP_CASCADE)
5395 		string_append_char(str, " CASCADE");
5396 }
5397 
5398 static void
_outReassignOwnedStmt(String * str,ReassignOwnedStmt * node)5399 _outReassignOwnedStmt(String * str, ReassignOwnedStmt *node)
5400 {
5401 	string_append_char(str, "REASSIGN OWNED BY ");
5402 	_outIdList(str, node->roles);
5403 	string_append_char(str, " TO \"");
5404 	_outNode(str, node->newrole);
5405 	string_append_char(str, "\"");
5406 }
5407 
5408 static void
_outAlterTSDictionaryStmt(String * str,AlterTSDictionaryStmt * node)5409 _outAlterTSDictionaryStmt(String * str, AlterTSDictionaryStmt *node)
5410 {
5411 	string_append_char(str, "ALTER TEXT SEARCH DICTIONARY ");
5412 	_outIdList(str, node->dictname);
5413 	string_append_char(str, "(");
5414 	_outNode(str, node->options);
5415 	string_append_char(str, ")");
5416 }
5417 
5418 static void
_outAlterTSConfigurationStmt(String * str,AlterTSConfigurationStmt * node)5419 _outAlterTSConfigurationStmt(String * str, AlterTSConfigurationStmt *node)
5420 {
5421 	string_append_char(str, "ALTER TEXT SEARCH CONFIGURATION ");
5422 	_outIdList(str, node->cfgname);
5423 	if (node->override == false && node->replace == false)
5424 	{
5425 		string_append_char(str, "ADD MAPPING FOR ");
5426 		_outIdList(str, node->tokentype);
5427 		string_append_char(str, " WITH ");
5428 		_outIdList(str, node->dicts);
5429 	}
5430 	else if (node->override == true && node->replace == false)
5431 	{
5432 		string_append_char(str, "ALTER MAPPING FOR ");
5433 		_outIdList(str, node->tokentype);
5434 		string_append_char(str, " WITH ");
5435 		_outIdList(str, node->dicts);
5436 	}
5437 	else if (node->override == false && node->replace == true)
5438 	{
5439 		if (node->tokentype == NIL)
5440 			string_append_char(str, "ALTER MAPPING ");
5441 		else
5442 		{
5443 			string_append_char(str, "ALTER MAPPING FOR ");
5444 			_outIdList(str, node->tokentype);
5445 		}
5446 		string_append_char(str, "REPLACE ");
5447 		_outNode(str, linitial(node->dicts));
5448 		string_append_char(str, " WITH ");
5449 		_outNode(str, lsecond(node->dicts));
5450 	}
5451 	else if (node->missing_ok == false)
5452 	{
5453 		string_append_char(str, " DROP MAPPING FOR ");
5454 		_outIdList(str, node->tokentype);
5455 	}
5456 	else if (node->missing_ok == true)
5457 	{
5458 		string_append_char(str, " DROP MAPPING IF EXISTS FOR ");
5459 		_outIdList(str, node->tokentype);
5460 	}
5461 }
5462 
5463 static void
_outXmlExpr(String * str,XmlExpr * node)5464 _outXmlExpr(String * str, XmlExpr *node)
5465 {
5466 	A_Const    *n;
5467 
5468 	switch (node->op)
5469 	{
5470 		case IS_DOCUMENT:
5471 			_outNode(str, node->args);
5472 			string_append_char(str, " IS DOCUMENT");
5473 			break;
5474 
5475 		case IS_XMLCONCAT:
5476 			string_append_char(str, "XMLCONCAT (");
5477 			_outNode(str, node->args);
5478 			string_append_char(str, ")");
5479 			break;
5480 
5481 		case IS_XMLELEMENT:
5482 			string_append_char(str, "XMLELEMENT (");
5483 			if (node->name)
5484 			{
5485 				string_append_char(str, "NAME \"");
5486 				string_append_char(str, node->name);
5487 				string_append_char(str, "\"");
5488 				if (node->named_args != NIL)
5489 				{
5490 					string_append_char(str, ",");
5491 					_outIdList(str, node->named_args);
5492 				}
5493 			}
5494 			if (node->args != NIL)
5495 			{
5496 				string_append_char(str, ",");
5497 				_outNode(str, node->args);
5498 			}
5499 			string_append_char(str, ")");
5500 			break;
5501 
5502 		case IS_XMLFOREST:
5503 			string_append_char(str, "XMLFOREST (");
5504 			_outNode(str, node->named_args);
5505 			string_append_char(str, ")");
5506 			break;
5507 
5508 		case IS_XMLPARSE:
5509 			string_append_char(str, "XMLPARSE (");
5510 			if (node->xmloption == XMLOPTION_DOCUMENT)
5511 				string_append_char(str, "DOCUMENT ");
5512 			else
5513 				string_append_char(str, "CONTENT ");
5514 
5515 			_outNode(str, linitial(node->args));
5516 			n = lsecond(node->args);
5517 			{
5518 				Node	   *arg = ((TypeCast *) n)->arg;
5519 
5520 				if (((A_Const *) arg)->val.val.str[0] == 't')
5521 					string_append_char(str, " PRESERVE WHITESPACE");
5522 			}
5523 
5524 			string_append_char(str, ")");
5525 			break;
5526 
5527 
5528 		default:
5529 			break;
5530 	}
5531 }
5532 
5533 static void
_outXmlSerialize(String * str,XmlSerialize * node)5534 _outXmlSerialize(String * str, XmlSerialize *node)
5535 {
5536 
5537 }
5538 
5539 static void
_outWithDefinition(String * str,List * def_list)5540 _outWithDefinition(String * str, List *def_list)
5541 {
5542 	int			oid = 0;
5543 
5544 	if (list_length(def_list) == 1)
5545 	{
5546 		DefElem    *elem;
5547 
5548 		elem = linitial(def_list);
5549 		if (strcmp(elem->defname, "oids") == 0)
5550 		{
5551 			Value	   *v = (Value *) elem->arg;
5552 
5553 			if (v->val.ival == 1)
5554 				string_append_char(str, " WITH OIDS ");
5555 			else
5556 				string_append_char(str, " WITHOUT OIDS ");
5557 			oid = 1;
5558 		}
5559 	}
5560 
5561 	if (oid == 1)
5562 		return;
5563 
5564 	string_append_char(str, " WITH ");
5565 	_outDefinition(str, def_list);
5566 }
5567 
5568 static void
_outOnConflictClause(String * str,OnConflictClause * node)5569 _outOnConflictClause(String * str, OnConflictClause *node)
5570 {
5571 	string_append_char(str, " ON CONFLICT ");
5572 
5573 	if (node->infer)
5574 	{
5575 		if (node->infer->indexElems != NIL)
5576 		{
5577 			string_append_char(str, " ( ");
5578 			_outList(str, node->infer->indexElems);
5579 			string_append_char(str, " ) ");
5580 
5581 			if (node->infer->whereClause)
5582 			{
5583 				string_append_char(str, " WHERE ");
5584 				_outNode(str, node->infer->whereClause);
5585 			}
5586 		}
5587 		else
5588 		{
5589 			string_append_char(str, " ON CONSTRAINT ");
5590 			string_append_char(str, node->infer->conname);
5591 		}
5592 	}
5593 
5594 	switch (node->action)
5595 	{
5596 		case ONCONFLICT_UPDATE:
5597 			string_append_char(str, " DO UPDATE ");
5598 			break;
5599 
5600 		case ONCONFLICT_NOTHING:
5601 			string_append_char(str, " DO NOTHING ");
5602 			break;
5603 
5604 		default:
5605 			break;
5606 	}
5607 
5608 	if (node->targetList)
5609 	{
5610 		_outSetClause(str, node->targetList);
5611 	}
5612 
5613 	if (node->whereClause)
5614 	{
5615 		string_append_char(str, " WHERE ");
5616 		_outNode(str, node->whereClause);
5617 	}
5618 }
5619 
5620 static void
_outPartitionElem(String * str,PartitionElem * node)5621 _outPartitionElem(String * str, PartitionElem *node)
5622 {
5623 }
5624 
5625 static void
_outPartitionSpec(String * str,PartitionSpec * node)5626 _outPartitionSpec(String * str, PartitionSpec *node)
5627 {
5628 }
5629 
5630 static void
_outPartitionBoundSpec(String * str,PartitionBoundSpec * node)5631 _outPartitionBoundSpec(String * str, PartitionBoundSpec *node)
5632 {
5633 }
5634 
5635 static void
_outPartitionRangeDatum(String * str,PartitionRangeDatum * node)5636 _outPartitionRangeDatum(String * str, PartitionRangeDatum *node)
5637 {
5638 }
5639 
5640 /*
5641  * _outNode -
5642  *	  converts a Node into ascii string and append it to 'str'
5643  */
5644 void
_outNode(String * str,void * obj)5645 _outNode(String * str, void *obj)
5646 {
5647 	/* Guard against stack overflow due to overly complex expressions */
5648 	/*
5649 	 * check_stack_depth();
5650 	 */
5651 
5652 	if (obj == NULL)
5653 		return;
5654 	else if (IsA(obj, List) ||IsA(obj, IntList) || IsA(obj, OidList))
5655 		_outList(str, obj);
5656 	else if (IsA(obj, Integer) ||
5657 			 IsA(obj, Float) ||
5658 			 IsA(obj, String) ||
5659 			 IsA(obj, BitString))
5660 	{
5661 		/* nodeRead does not want to see { } around these! */
5662 		_outValue(str, obj);
5663 	}
5664 	else
5665 	{
5666 		switch (nodeTag(obj))
5667 		{
5668 			case T_Alias:
5669 				_outAlias(str, obj);
5670 				break;
5671 			case T_RangeVar:
5672 				_outRangeVar(str, obj);
5673 				break;
5674 
5675 				/*
5676 				 * case T_IntoClause: _outIntoClause(str, obj); break;
5677 				 */
5678 			case T_Var:
5679 				_outVar(str, obj);
5680 				break;
5681 			case T_Const:
5682 				_outConst(str, obj);
5683 				break;
5684 			case T_Param:
5685 				_outParam(str, obj);
5686 				break;
5687 			case T_Aggref:
5688 				_outAggref(str, obj);
5689 				break;
5690 			case T_GroupingFunc:
5691 				_outGroupingFunc(str, obj);
5692 				break;
5693 
5694 				/*
5695 				 * case T_WindowFunc: _outWindowFunc(str, obj); break;
5696 				 */
5697 			case T_SubscriptingRef:
5698 				_outSubscriptingRef(str, obj);
5699 				break;
5700 			case T_FuncExpr:
5701 				_outFuncExpr(str, obj);
5702 				break;
5703 			case T_NamedArgExpr:
5704 				_outNamedArgExpr(str, obj);
5705 				break;
5706 			case T_OpExpr:
5707 				_outOpExpr(str, obj);
5708 				break;
5709 			case T_DistinctExpr:
5710 				_outDistinctExpr(str, obj);
5711 				break;
5712 			case T_NullIfExpr:
5713 				_outNullIfExpr(str, obj);
5714 				break;
5715 			case T_ScalarArrayOpExpr:
5716 				_outScalarArrayOpExpr(str, obj);
5717 				break;
5718 			case T_BoolExpr:
5719 				_outBoolExpr(str, obj);
5720 				break;
5721 			case T_SubLink:
5722 				_outSubLink(str, obj);
5723 				break;
5724 			case T_SubPlan:
5725 				_outSubPlan(str, obj);
5726 				break;
5727 
5728 				/*
5729 				 * case T_AlternativeSubPlan: _outAlternativeSubPlan(str,
5730 				 * obj); break;
5731 				 */
5732 			case T_FieldSelect:
5733 				_outFieldSelect(str, obj);
5734 				break;
5735 			case T_FieldStore:
5736 				_outFieldStore(str, obj);
5737 				break;
5738 			case T_RelabelType:
5739 				_outRelabelType(str, obj);
5740 				break;
5741 
5742 				/*
5743 				 * case T_CoerceViaIO: _outCoerceViaIO(str, obj); break; case
5744 				 * T_ArrayCoerceExpr: _outArrayCoerceExpr(str, obj); break;
5745 				 */
5746 			case T_ConvertRowtypeExpr:
5747 				_outConvertRowtypeExpr(str, obj);
5748 				break;
5749 
5750 				/*
5751 				 * case T_CollateExpr: _outCollateExpr(str, obj); break;
5752 				 */
5753 			case T_CaseExpr:
5754 				_outCaseExpr(str, obj);
5755 				break;
5756 			case T_CaseWhen:
5757 				_outCaseWhen(str, obj);
5758 				break;
5759 			case T_CaseTestExpr:
5760 				_outCaseTestExpr(str, obj);
5761 				break;
5762 			case T_ArrayExpr:
5763 				_outArrayExpr(str, obj);
5764 				break;
5765 			case T_RowExpr:
5766 				_outRowExpr(str, obj);
5767 				break;
5768 
5769 				/*
5770 				 * case T_RowCompareExpr: _outRowCompareExpr(str, obj); break;
5771 				 */
5772 			case T_CoalesceExpr:
5773 				_outCoalesceExpr(str, obj);
5774 				break;
5775 			case T_MinMaxExpr:
5776 				_outMinMaxExpr(str, obj);
5777 				break;
5778 
5779 				/*
5780 				 * case T_SQLValueFunction: _outSQLValueFunction(str, obj);
5781 				 */
5782 				break;
5783 			case T_XmlExpr:
5784 				_outXmlExpr(str, obj);
5785 				break;
5786 			case T_NullTest:
5787 				_outNullTest(str, obj);
5788 				break;
5789 			case T_BooleanTest:
5790 				_outBooleanTest(str, obj);
5791 				break;
5792 			case T_CoerceToDomain:
5793 				_outCoerceToDomain(str, obj);
5794 				break;
5795 			case T_CoerceToDomainValue:
5796 				_outCoerceToDomainValue(str, obj);
5797 				break;
5798 			case T_SetToDefault:
5799 				_outSetToDefault(str, obj);
5800 				break;
5801 			case T_CurrentOfExpr:
5802 				_outCurrentOfExpr(str, obj);
5803 				break;
5804 
5805 				/*
5806 				 * case T_NextValueExpr: _outNextValueExpr(str, obj); break;
5807 				 */
5808 			case T_InferenceElem:
5809 				_outInferenceElem(str, obj);
5810 				break;
5811 			case T_TargetEntry:
5812 				_outTargetEntry(str, obj);
5813 				break;
5814 			case T_RangeTblRef:
5815 				_outRangeTblRef(str, obj);
5816 				break;
5817 			case T_JoinExpr:
5818 				_outJoinExpr(str, obj);
5819 				break;
5820 			case T_FromExpr:
5821 				_outFromExpr(str, obj);
5822 				break;
5823 			case T_OnConflictExpr:
5824 				_outOnConflictExpr(str, obj);
5825 				break;
5826 #ifdef NOT_USED
5827 			case T_ExtensibleNode:
5828 				_outExtensibleNode(str, obj);
5829 				break;
5830 #endif
5831 			case T_CreateStmt:
5832 				_outCreateStmt(str, obj);
5833 				break;
5834 			case T_CreateTableAsStmt:
5835 				_outCreateTableAsStmt(str, obj);
5836 				break;
5837 			case T_CreateForeignTableStmt:
5838 				_outCreateForeignTableStmt(str, obj);
5839 				break;
5840 			case T_ImportForeignSchemaStmt:
5841 				_outImportForeignSchemaStmt(str, obj);
5842 				break;
5843 			case T_IndexStmt:
5844 				_outIndexStmt(str, obj);
5845 				break;
5846 			case T_CreateStatsStmt:
5847 				_outCreateStatsStmt(str, obj);
5848 				break;
5849 			case T_NotifyStmt:
5850 				_outNotifyStmt(str, obj);
5851 				break;
5852 			case T_DeclareCursorStmt:
5853 				_outDeclareCursorStmt(str, obj);
5854 				break;
5855 			case T_SelectStmt:
5856 				_outSelectStmt(str, obj);
5857 				break;
5858 			case T_ColumnDef:
5859 				_outColumnDef(str, obj);
5860 				break;
5861 			case T_TypeName:
5862 				_outTypeName(str, obj);
5863 				break;
5864 			case T_TypeCast:
5865 				_outTypeCast(str, obj);
5866 				break;
5867 			case T_CollateClause:
5868 				_outCollateClause(str, obj);
5869 				break;
5870 			case T_IndexElem:
5871 				_outIndexElem(str, obj);
5872 				break;
5873 
5874 				/*
5875 				 * case T_Query: _outQuery(str, obj); break; case
5876 				 * T_WithCheckOption: _outWithCheckOption(str, obj); break;
5877 				 * case T_SortGroupClause: _outSortGroupClause(str, obj);
5878 				 * break;
5879 				 */
5880 			case T_GroupingSet:
5881 				_outGroupingSet(str, obj);
5882 				break;
5883 
5884 				/*
5885 				 * case T_WindowClause: _outWindowClause(str, obj); break;
5886 				 * case T_RowMarkClause: _outRowMarkClause(str, obj); break;
5887 				 */
5888 			case T_WithClause:
5889 				_outWithClause(str, obj);
5890 				break;
5891 			case T_CommonTableExpr:
5892 				_outCommonTableExpr(str, obj);
5893 				break;
5894 			case T_SetOperationStmt:
5895 				_outSetOperationStmt(str, obj);
5896 				break;
5897 
5898 				/*
5899 				 * case T_RangeTblEntry: _outRangeTblEntry(str, obj); break;
5900 				 */
5901 			case T_TableSampleClause:
5902 				_outTableSampleClause(str, obj);
5903 				break;
5904 			case T_A_Expr:
5905 				_outAExpr(str, obj);
5906 				break;
5907 			case T_ColumnRef:
5908 				_outColumnRef(str, obj);
5909 				break;
5910 			case T_ParamRef:
5911 				_outParamRef(str, obj);
5912 				break;
5913 			case T_RawStmt:
5914 				_outRawStmt(str, obj);
5915 				break;
5916 			case T_A_Const:
5917 				_outAConst(str, obj);
5918 				break;
5919 
5920 				/*
5921 				 * case T_A_Star: _outA_Star(str, obj); break;
5922 				 */
5923 			case T_A_Indices:
5924 				_outA_Indices(str, obj);
5925 				break;
5926 			case T_A_Indirection:
5927 				_outA_Indirection(str, obj);
5928 				break;
5929 			case T_A_ArrayExpr:
5930 				_outA_ArrayExpr(str, obj);
5931 				break;
5932 			case T_ResTarget:
5933 				_outResTarget(str, obj);
5934 				break;
5935 			case T_MultiAssignRef:
5936 				_outMultiAssignRef(str, obj);
5937 				break;
5938 			case T_SortBy:
5939 				_outSortBy(str, obj);
5940 				break;
5941 			case T_WindowDef:
5942 				_outWindowDef(str, obj);
5943 				break;
5944 			case T_RangeSubselect:
5945 				_outRangeSubselect(str, obj);
5946 				break;
5947 			case T_RangeFunction:
5948 				_outRangeFunction(str, obj);
5949 				break;
5950 			case T_RangeTableSample:
5951 				_outRangeTableSample(str, obj);
5952 				break;
5953 			case T_RangeTableFunc:
5954 				_outRangeTableFunc(str, obj);
5955 				break;
5956 			case T_RangeTableFuncCol:
5957 				_outRangeTableFuncCol(str, obj);
5958 				break;
5959 			case T_Constraint:
5960 				_outConstraint(str, obj);
5961 				break;
5962 			case T_FuncCall:
5963 				_outFuncCall(str, obj);
5964 				break;
5965 			case T_DefElem:
5966 				_outDefElem(str, obj);
5967 				break;
5968 
5969 				/*
5970 				 * case T_TableLikeClause: _outTableLikeClause(str, obj);
5971 				 * break;
5972 				 */
5973 			case T_LockingClause:
5974 				_outLockingClause(str, obj);
5975 				break;
5976 			case T_XmlSerialize:
5977 				_outXmlSerialize(str, obj);
5978 				break;
5979 			case T_TriggerTransition:
5980 				_outTriggerTransition(str, obj);
5981 				break;
5982 			case T_PartitionElem:
5983 				_outPartitionElem(str, obj);
5984 				break;
5985 			case T_PartitionSpec:
5986 				_outPartitionSpec(str, obj);
5987 				break;
5988 			case T_PartitionBoundSpec:
5989 				_outPartitionBoundSpec(str, obj);
5990 				break;
5991 			case T_PartitionRangeDatum:
5992 				_outPartitionRangeDatum(str, obj);
5993 				break;
5994 
5995 			case T_InsertStmt:
5996 				_outInsertStmt(str, obj);
5997 				break;
5998 
5999 			case T_DeleteStmt:
6000 				_outDeleteStmt(str, obj);
6001 				break;
6002 
6003 			case T_UpdateStmt:
6004 				_outUpdateStmt(str, obj);
6005 				break;
6006 
6007 			case T_TransactionStmt:
6008 				_outTransactionStmt(str, obj);
6009 				break;
6010 
6011 			case T_TruncateStmt:
6012 				_outTruncateStmt(str, obj);
6013 				break;
6014 
6015 			case T_VacuumStmt:
6016 				_outVacuumStmt(str, obj);
6017 				break;
6018 
6019 			case T_ExplainStmt:
6020 				_outExplainStmt(str, obj);
6021 				break;
6022 
6023 			case T_ClusterStmt:
6024 				_outClusterStmt(str, obj);
6025 				break;
6026 
6027 			case T_CheckPointStmt:
6028 				_outCheckPointStmt(str, obj);
6029 				break;
6030 
6031 			case T_ClosePortalStmt:
6032 				_outClosePortalStmt(str, obj);
6033 				break;
6034 
6035 			case T_ListenStmt:
6036 				_outListenStmt(str, obj);
6037 				break;
6038 
6039 			case T_UnlistenStmt:
6040 				_outUnlistenStmt(str, obj);
6041 				break;
6042 
6043 			case T_LoadStmt:
6044 				_outLoadStmt(str, obj);
6045 				break;
6046 
6047 			case T_CopyStmt:
6048 				_outCopyStmt(str, obj);
6049 				break;
6050 
6051 			case T_DeallocateStmt:
6052 				_outDeallocateStmt(str, obj);
6053 				break;
6054 
6055 			case T_RenameStmt:
6056 				_outRenameStmt(str, obj);
6057 				break;
6058 
6059 			case T_CreateRoleStmt:
6060 				_outCreateRoleStmt(str, obj);
6061 				break;
6062 
6063 			case T_AlterRoleStmt:
6064 				_outAlterRoleStmt(str, obj);
6065 				break;
6066 
6067 			case T_AlterRoleSetStmt:
6068 				_outAlterRoleSetStmt(str, obj);
6069 				break;
6070 
6071 			case T_RoleSpec:
6072 				_outRoleSpec(str, obj);
6073 				break;
6074 
6075 			case T_DropRoleStmt:
6076 				_outDropRoleStmt(str, obj);
6077 				break;
6078 
6079 			case T_CreateSchemaStmt:
6080 				_outCreateSchemaStmt(str, obj);
6081 				break;
6082 
6083 			case T_VariableSetStmt:
6084 				_outVariableSetStmt(str, obj);
6085 				break;
6086 
6087 			case T_VariableShowStmt:
6088 				_outVariableShowStmt(str, obj);
6089 				break;
6090 
6091 			case T_ConstraintsSetStmt:
6092 				_outConstraintsSetStmt(str, obj);
6093 				break;
6094 
6095 			case T_AlterTableStmt:
6096 				_outAlterTableStmt(str, obj);
6097 				break;
6098 
6099 			case T_AlterTableCmd:
6100 				_outAlterTableCmd(str, obj);
6101 				break;
6102 
6103 			case T_CreateSeqStmt:
6104 				_outCreateSeqStmt(str, obj);
6105 				break;
6106 
6107 			case T_AlterSeqStmt:
6108 				_outAlterSeqStmt(str, obj);
6109 				break;
6110 
6111 			case T_CreatePLangStmt:
6112 				_outCreatePLangStmt(str, obj);
6113 				break;
6114 
6115 			case T_CreateTableSpaceStmt:
6116 				_outCreateTableSpaceStmt(str, obj);
6117 				break;
6118 
6119 			case T_DropTableSpaceStmt:
6120 				_outDropTableSpaceStmt(str, obj);
6121 				break;
6122 
6123 			case T_CreateTrigStmt:
6124 				_outCreateTrigStmt(str, obj);
6125 				break;
6126 
6127 			case T_DefineStmt:
6128 				_outDefineStmt(str, obj);
6129 				break;
6130 
6131 			case T_CreateOpClassStmt:
6132 				_outCreateOpClassStmt(str, obj);
6133 				break;
6134 
6135 			case T_CreateOpClassItem:
6136 				_outCreateOpClassItem(str, obj);
6137 				break;
6138 
6139 			case T_DropStmt:
6140 				_outDropStmt(str, obj);
6141 				break;
6142 
6143 			case T_FetchStmt:
6144 				_outFetchStmt(str, obj);
6145 				break;
6146 
6147 			case T_GrantStmt:
6148 				_outGrantStmt(str, obj);
6149 				break;
6150 
6151 			case T_ObjectWithArgs:
6152 				_outObjectWithArgs(str, obj);
6153 				break;
6154 
6155 			case T_FunctionParameter:
6156 				_outFunctionParameter(str, obj);
6157 				break;
6158 
6159 			case T_GrantRoleStmt:
6160 				_outGrantRoleStmt(str, obj);
6161 				break;
6162 
6163 			case T_CreateFunctionStmt:
6164 				_outCreateFunctionStmt(str, obj);
6165 				break;
6166 
6167 			case T_AlterFunctionStmt:
6168 				_outAlterFunctionStmt(str, obj);
6169 				break;
6170 
6171 			case T_CreateCastStmt:
6172 				_outCreateCastStmt(str, obj);
6173 				break;
6174 
6175 			case T_ReindexStmt:
6176 				_outReindexStmt(str, obj);
6177 				break;
6178 
6179 			case T_AlterObjectSchemaStmt:
6180 				_outAlterObjectSchemaStmt(str, obj);
6181 				break;
6182 
6183 			case T_AlterOwnerStmt:
6184 				_outAlterOwnerStmt(str, obj);
6185 				break;
6186 
6187 			case T_RuleStmt:
6188 				_outRuleStmt(str, obj);
6189 				break;
6190 
6191 			case T_ViewStmt:
6192 				_outViewStmt(str, obj);
6193 				break;
6194 
6195 			case T_CreatedbStmt:
6196 				_outCreatedbStmt(str, obj);
6197 				break;
6198 
6199 			case T_AlterDatabaseStmt:
6200 				_outAlterDatabaseStmt(str, obj);
6201 				break;
6202 
6203 			case T_AlterDatabaseSetStmt:
6204 				_outAlterDatabaseSetStmt(str, obj);
6205 				break;
6206 
6207 			case T_DropdbStmt:
6208 				_outDropdbStmt(str, obj);
6209 				break;
6210 
6211 			case T_CreateDomainStmt:
6212 				_outCreateDomainStmt(str, obj);
6213 				break;
6214 
6215 			case T_AlterDomainStmt:
6216 				_outAlterDomainStmt(str, obj);
6217 				break;
6218 
6219 			case T_CreateConversionStmt:
6220 				_outCreateConversionStmt(str, obj);
6221 				break;
6222 
6223 			case T_PrepareStmt:
6224 				_outPrepareStmt(str, obj);
6225 				break;
6226 
6227 			case T_ExecuteStmt:
6228 				_outExecuteStmt(str, obj);
6229 				break;
6230 
6231 			case T_LockStmt:
6232 				_outLockStmt(str, obj);
6233 				break;
6234 
6235 			case T_CommentStmt:
6236 				_outCommentStmt(str, obj);
6237 				break;
6238 
6239 			case T_DiscardStmt:
6240 				_outDiscardStmt(str, obj);
6241 				break;
6242 
6243 			case T_CreateOpFamilyStmt:
6244 				_outCreateOpFamilyStmt(str, obj);
6245 				break;
6246 
6247 			case T_AlterOpFamilyStmt:
6248 				_outAlterOpFamilyStmt(str, obj);
6249 				break;
6250 
6251 			case T_CreateEnumStmt:
6252 				_outCreateEnumStmt(str, obj);
6253 				break;
6254 
6255 			case T_DropOwnedStmt:
6256 				_outDropOwnedStmt(str, obj);
6257 				break;
6258 
6259 			case T_ReassignOwnedStmt:
6260 				_outReassignOwnedStmt(str, obj);
6261 				break;
6262 
6263 			case T_AlterTSDictionaryStmt:
6264 				_outAlterTSDictionaryStmt(str, obj);
6265 				break;
6266 
6267 			case T_AlterTSConfigurationStmt:
6268 				_outAlterTSConfigurationStmt(str, obj);
6269 				break;
6270 
6271 			case T_OnConflictClause:
6272 				_outOnConflictClause(str, obj);
6273 				break;
6274 
6275 			default:
6276 				break;
6277 		}
6278 	}
6279 }
6280 
6281 /*
6282  * nodeToString -
6283  *	   returns the ascii representation of the Node as a palloc'd string
6284  */
6285 char *
nodeToString(const void * obj)6286 nodeToString(const void *obj)
6287 {
6288 	String	   *str;
6289 	char	   *p;
6290 
6291 	str = init_string("");
6292 	_outNode(str, (void *) obj);
6293 	p = palloc(str->len + 1);
6294 	memcpy(p, str->data, str->len);
6295 	*(p + str->len) = '\0';
6296 
6297 	free_string(str);
6298 
6299 	return p;
6300 }
6301