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