]> git.8kb.co.uk Git - pgpool-ii/pgpool-ii_2.2.5/blob - parser/outfuncs.c
Attempt to send a proper failure message to frontend when authentication
[pgpool-ii/pgpool-ii_2.2.5] / parser / outfuncs.c
1 /*-------------------------------------------------------------------------
2  *
3  * outfuncs.c
4  *        Output functions for Postgres tree nodes.
5  *
6  * Portions Copyright (c) 2003-2008, PgPool Global Development Group
7  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  *
11  * IDENTIFICATION
12  *        $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.261.2.1 2005/11/14 23:54:34 tgl Exp $
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
26 #include "pool_memory.h"
27 #include "parser.h"
28 #include "pool_string.h"
29 #include "pg_list.h"
30 #include "parsenodes.h"
31
32 #define booltostr(x)  ((x) ? "true" : "false")
33
34 void _outNode(String *str, void *obj);
35 static void _outList(String *str, List *node);
36 static void _outIdList(String *str, List *node);
37 static void _outAlias(String *str, Alias *node);
38 static void _outRangeVar(String *str, RangeVar *node);
39 static void _outVar(String *str, Var *node);
40 static void _outConst(String *str, Const *node);
41 static void _outParam(String *str, Param *node);
42 static void _outAggref(String *str, Aggref *node);
43 static void _outArrayRef(String *str, ArrayRef *node);
44 static void _outFuncExpr(String *str, FuncExpr *node);
45 static void _outOpExpr(String *str, OpExpr *node);
46 static void _outDistinctExpr(String *str, DistinctExpr *node);
47 static void _outScalarArrayOpExpr(String *str, ScalarArrayOpExpr *node);
48 static void _outBoolExpr(String *str, BoolExpr *node);
49 static void _outSubLink(String *str, SubLink *node);
50 static void _outSubPlan(String *str, SubPlan *node);
51 static void _outFieldSelect(String *str, FieldSelect *node);
52 static void _outFieldStore(String *str, FieldStore *node);
53 static void _outRelabelType(String *str, RelabelType *node);
54 static void _outConvertRowtypeExpr(String *str, ConvertRowtypeExpr *node);
55 static void _outCaseExpr(String *str, CaseExpr *node);
56 static void _outCaseWhen(String *str, CaseWhen *node);
57 static void _outCaseTestExpr(String *str, CaseTestExpr *node);
58 static void _outArrayExpr(String *str, ArrayExpr *node);
59 static void _outRowExpr(String *str, RowExpr *node);
60 static void _outCoalesceExpr(String *str, CoalesceExpr *node);
61 static void _outMinMaxExpr(String *str, MinMaxExpr *node);
62 static void _outNullIfExpr(String *str, NullIfExpr *node);
63 static void _outNullTest(String *str, NullTest *node);
64 static void _outBooleanTest(String *str, BooleanTest *node);
65 static void _outCoerceToDomain(String *str, CoerceToDomain *node);
66 static void _outCoerceToDomainValue(String *str, CoerceToDomainValue *node);
67 static void _outSetToDefault(String *str, SetToDefault *node);
68 static void _outTargetEntry(String *str, TargetEntry *node);
69 static void _outRangeTblRef(String *str, RangeTblRef *node);
70 static void _outJoinExpr(String *str, JoinExpr *node);
71 static void _outFromExpr(String *str, FromExpr *node);
72 static void _outCreateStmt(String *str, CreateStmt *node);
73 static void _outIndexStmt(String *str, IndexStmt *node);
74 static void _outNotifyStmt(String *str, NotifyStmt *node);
75 static void _outDeclareCursorStmt(String *str, DeclareCursorStmt *node);
76 static void _outSelectStmt(String *str, SelectStmt *node);
77 static void _outFuncCall(String *str, FuncCall *node);
78 static void _outDefElem(String *str, DefElem *node);
79 static void _outLockingClause(String *str, LockingClause *node);
80 static void _outColumnDef(String *str, ColumnDef *node);
81 static void _outTypeName(String *str, TypeName *node);
82 static void _outTypeCast(String *str, TypeCast *node);
83 static void _outIndexElem(String *str, IndexElem *node);
84 static void _outSortClause(String *str, SortClause *node);
85 static void _outGroupClause(String *str, GroupClause *node);
86 static void _outSetOperationStmt(String *str, SetOperationStmt *node);
87 static void _outAExpr(String *str, A_Expr *node);
88 static void _outValue(String *str, Value *value);
89 static void _outColumnRef(String *str, ColumnRef *node);
90 static void _outParamRef(String *str, ParamRef *node);
91 static void _outAConst(String *str, A_Const *node);
92 static void _outA_Indices(String *str, A_Indices *node);
93 static void _outA_Indirection(String *str, A_Indirection *node);
94 static void _outResTarget(String *str, ResTarget *node);
95 static void _outConstraint(String *str, Constraint *node);
96 static void _outFkConstraint(String *str, FkConstraint *node);
97
98 static void _outSortBy(String *str, SortBy *node);
99 static void _outInsertStmt(String *str, InsertStmt *node);
100 static void _outUpdateStmt(String *str, UpdateStmt *node);
101 static void _outDeleteStmt(String *str, DeleteStmt *node);
102 static void _outTransactionStmt(String *str, TransactionStmt *node);
103 static void _outTruncateStmt(String *str, TruncateStmt *node);
104 static void _outVacuumStmt(String *str, VacuumStmt *node);
105 static void _outExplainStmt(String *str, ExplainStmt *node);
106 static void _outClusterStmt(String *str, ClusterStmt *node);
107 static void _outCheckPointStmt(String *str, CheckPointStmt *node);
108 static void _outClosePortalStmt(String *str, ClosePortalStmt *node);
109 static void _outListenStmt(String *str, ListenStmt *node);
110 static void _outUnlistenStmt(String *str, UnlistenStmt *node);
111 static void _outLoadStmt(String *str, LoadStmt *node);
112 static void _outCopyStmt(String *str, CopyStmt *node);
113 static void _outDeallocateStmt(String *str, DeallocateStmt *node);
114 static void _outRenameStmt(String *str, RenameStmt *node);
115 static void _outCreateRoleStmt(String *str, CreateRoleStmt *node);
116 static void _outAlterRoleStmt(String *str, AlterRoleStmt *node);
117 static void _outDropRoleStmt(String *str, DropRoleStmt *node);
118 static void _outCreateSchemaStmt(String *str, CreateSchemaStmt *node);
119 static void _outVariableSetStmt(String *str, VariableSetStmt *node);
120 static void _outVariableShowStmt(String *str, VariableShowStmt *node);
121 static void _outConstraintsSetStmt(String *str, ConstraintsSetStmt *node);
122 static void _outAlterTableStmt(String *str, AlterTableStmt *node);
123 static void _outCreateSeqStmt(String *str, CreateSeqStmt *node);
124 static void _outAlterSeqStmt(String *str, AlterSeqStmt *node);
125 static void _outCreatePLangStmt(String *str, CreatePLangStmt *node);
126 static void _outDropPLangStmt(String *str, DropPLangStmt *node);
127 static void _outCreateTableSpaceStmt(String *str, CreateTableSpaceStmt *node);
128 static void _outDropTableSpaceStmt(String *str, DropTableSpaceStmt *node);
129 static void _outCreateTrigStmt(String *str, CreateTrigStmt *node);
130 static void _outDropPropertyStmt(String *str, DropPropertyStmt *node);
131 static void _outDefineStmt(String *str, DefineStmt *node);
132 static void _outCreateOpClassStmt(String *str, CreateOpClassStmt *node);
133 static void _outRemoveOpClassStmt(String *str, RemoveOpClassStmt *node);
134 static void _outDropStmt(String *str, DropStmt *node);
135 static void _outFetchStmt(String *str, FetchStmt *node);
136 static void _outGrantStmt(String *str, GrantStmt *node);
137 static void _outGrantRoleStmt(String *str, GrantRoleStmt *node);
138 static void _outCreateFunctionStmt(String *str, CreateFunctionStmt *node);
139 static void _outAlterFunctionStmt(String *str, AlterFunctionStmt *node);
140 static void _outCreateCastStmt(String *str, CreateCastStmt *node);
141 static void _outDropCastStmt(String *str, DropCastStmt *node);
142 static void _outReindexStmt(String *str, ReindexStmt *node);
143 static void _outRuleStmt(String *str, RuleStmt *node);
144 static void _outViewStmt(String *str, ViewStmt *node);
145 static void _outCreatedbStmt(String *str, CreatedbStmt *node);
146 static void _outAlterDatabaseStmt(String *str, AlterDatabaseStmt *node);
147 static void _outAlterDatabaseSetStmt(String *str, AlterDatabaseSetStmt *node);
148 static void _outDropdbStmt(String *str, DropdbStmt *node);
149 static void _outCreateDomainStmt(String *str, CreateDomainStmt *node);
150 static void _outAlterDomainStmt(String *str, AlterDomainStmt *node);
151 static void _outCreateConversionStmt(String *str, CreateConversionStmt *node);
152 static void _outPrepareStmt(String *str, PrepareStmt *node);
153 static void _outExecuteStmt(String *str, ExecuteStmt *node);
154 static void _outLockStmt(String *str, LockStmt *node);
155 static void _outCommentStmt(String *str, CommentStmt *node);
156 static void _outDiscardStmt(String *str, DiscardStmt *node);
157 static void _outCreateOpFamilyStmt(String *str, CreateOpFamilyStmt *node);
158 static void _outAlterOpFamilyStmt(String *str, AlterOpFamilyStmt *node);
159 static void _outRemoveOpFamilyStmt(String *str, RemoveOpFamilyStmt *node);
160 static void _outCreateEnumStmt(String *str, CreateEnumStmt *node);
161 static void _outDropOwnedStmt(String *str, DropOwnedStmt *node);
162 static void _outReassignOwnedStmt(String *str, ReassignOwnedStmt *node);
163 static void _outAlterTSDictionaryStmt(String *str, AlterTSDictionaryStmt *node);
164 static void _outAlterTSConfigurationStmt(String *str, AlterTSConfigurationStmt *node);
165 static void _outXmlExpr(String *str, XmlExpr *node);
166 static void _outXmlSerialize(String *str, XmlSerialize *node);
167
168 static void _outFuncName(String *str, List *func_name);
169 static void _outSetRest(String *str, VariableSetStmt *node);
170 static void _outSetTransactionModeList(String *str, List *list);
171 static void _outAlterTableCmd(String *str, AlterTableCmd *node);
172 static void _outOptSeqList(String *str, List *options);
173 static void _outPrivGrantee(String *str, PrivGrantee *node);
174 static void _outPrivTarget(String *str, PrivTarget *node);
175 static void _outFuncWithArgs(String *str, FuncWithArgs *node);
176 static void _outFunctionParameter(String *str, FunctionParameter *node);
177 static void _outPrivilegeList(String *str, List *list);
178 static void _outFuncOptList(String *str, List *list);
179 static void _outCreatedbOptList(String *str, List *options);
180 static void _outOperatorArgTypes(String *str, List *args);
181 static void _outRangeFunction(String *str, RangeFunction *node);
182 static void _outInhRelation(String *str, InhRelation *node);
183 static void _outWithDefinition(String *str, List *def_list);
184 static void _outCurrentOfExpr(String *str, CurrentOfExpr *node);
185
186 static char *escape_string(char *str)
187 {
188         int len = strlen(str), i, j;
189         char *es = palloc0(len * 2 + 1);
190         
191         if (es == NULL)
192         {
193                 return NULL;
194         }
195
196         for (i = 0, j = 0; i < len; i++, j++)
197         {
198                 if (str[i] == '\'')
199                 {
200                         es[j++] = '\'';
201                 }
202                 else if (str[i] == '\\')
203                 {
204                         es[j++] = '\\';
205                 }
206                 es[j] = str[i];
207         }
208
209         return es;
210 }
211
212 static void _outIdList(String *str, List *node)
213 {
214         ListCell   *lc;
215         char first = 0;
216
217         foreach(lc, node)
218         {
219                 Value *v = lfirst(lc);
220
221                 if (first == 0)
222                         first = 1;
223                 else
224                         string_append_char(str, ", ");
225
226                 string_append_char(str, "\"");
227                 string_append_char(str, v->val.str);
228                 string_append_char(str, "\"");
229         }
230 }
231
232 static void _outList(String *str, List *node)
233 {
234         ListCell   *lc;
235         char first = 0;
236
237         foreach(lc, node)
238         {
239                 if (first == 0)
240                         first = 1;
241                 else
242                 {       
243                         if (!IsA(lfirst(lc), A_Indices))
244                                 string_append_char(str, ",");
245                 }
246                 _outNode(str, lfirst(lc));
247         }
248 }
249
250
251
252 /*****************************************************************************
253  *
254  *      Stuff from primnodes.h.
255  *
256  *****************************************************************************/
257
258 static void
259 _outAlias(String *str, Alias *node)
260 {
261         string_append_char(str, " AS \"");
262         string_append_char(str, node->aliasname);
263         string_append_char(str, "\"");
264         
265         if (node->colnames)
266         {
267                 string_append_char(str, "(");
268                 _outNode(str, node->colnames);
269                 string_append_char(str, ")");
270         }
271 }
272
273 static void
274 _outRangeVar(String *str, RangeVar *node)
275 {
276         if (node->catalogname)
277         {
278                 string_append_char(str, "\"");
279                 string_append_char(str, node->catalogname);
280                 string_append_char(str, "\".");
281         }
282
283         if (node->schemaname)
284         {
285                 string_append_char(str, "\"");
286                 string_append_char(str, node->schemaname);
287                 string_append_char(str, "\".");
288         }
289
290         string_append_char(str, "\"");
291         string_append_char(str, node->relname);
292         string_append_char(str, "\"");
293
294         if (node->alias)
295                 _outNode(str, node->alias);
296
297         if (node->inhOpt == INH_YES)
298         {
299                 string_append_char(str, " * ");
300         }
301 }
302
303 static void
304 _outVar(String *str, Var *node)
305 {
306
307 }
308
309 static void
310 _outConst(String *str, Const *node)
311 {
312
313 }
314
315 static void
316 _outParam(String *str, Param *node)
317 {
318
319 }
320
321 static void
322 _outAggref(String *str, Aggref *node)
323 {
324
325 }
326
327 static void
328 _outArrayRef(String *str, ArrayRef *node)
329 {
330 }
331
332 static void
333 _outFuncExpr(String *str, FuncExpr *node)
334 {
335
336 }
337
338 static void
339 _outOpExpr(String *str, OpExpr *node)
340 {
341
342 }
343
344 static void
345 _outDistinctExpr(String *str, DistinctExpr *node)
346 {
347
348 }
349
350 static void
351 _outScalarArrayOpExpr(String *str, ScalarArrayOpExpr *node)
352 {
353
354 }
355
356 static void
357 _outBoolExpr(String *str, BoolExpr *node)
358 {
359
360 }
361
362 static void
363 _outSubLink(String *str, SubLink *node)
364 {
365         _outNode(str, node->testexpr);
366
367         if (node->operName != NIL)
368         {
369                 Value *v = linitial(node->operName);
370                 if (strcmp(v->val.str, "=") == 0)
371                         string_append_char(str, " IN ");
372                 else
373                 {
374                         string_append_char(str, v->val.str);
375                 }
376         }
377
378         switch (node->subLinkType)
379         {
380                 case EXISTS_SUBLINK:
381                         string_append_char(str, " EXISTS ");
382                         break;
383
384                 case ARRAY_SUBLINK:
385                         string_append_char(str, " ARRAY ");
386                         break;
387
388                 case ANY_SUBLINK:
389                         if (node->operName != NIL)
390                         {
391                                 Value *v = linitial(node->operName);
392                                 if (strcmp(v->val.str, "=") != 0)
393                                 {
394                                         string_append_char(str, v->val.str);
395                                         string_append_char(str, " ANY ");
396                                 }
397                         }
398                         break;
399
400                 case ALL_SUBLINK:
401                         string_append_char(str, " ALL ");
402                         break;
403
404                 default:
405                         break;
406         }
407
408
409         if (node->subselect)
410         {
411                 string_append_char(str, "(");
412                 _outNode(str, node->subselect);
413                 string_append_char(str, ")");
414         }
415 }
416
417 static void
418 _outSubPlan(String *str, SubPlan *node)
419 {
420
421 }
422
423 static void
424 _outFieldSelect(String *str, FieldSelect *node)
425 {
426
427 }
428
429 static void
430 _outFieldStore(String *str, FieldStore *node)
431 {
432
433 }
434
435 static void
436 _outRelabelType(String *str, RelabelType *node)
437 {
438
439 }
440
441 static void
442 _outConvertRowtypeExpr(String *str, ConvertRowtypeExpr *node)
443 {
444
445 }
446
447 static void
448 _outCaseExpr(String *str, CaseExpr *node)
449 {
450         ListCell *lc;
451
452         string_append_char(str, "CASE ");
453         if (node->arg)
454                 _outNode(str, node->arg);
455
456         foreach (lc, node->args)
457         {
458                 _outNode(str, lfirst(lc));
459         }
460
461         if (node->defresult)
462         {
463                 string_append_char(str, " ELSE ");
464                 _outNode(str, node->defresult);
465         }
466
467         string_append_char(str, " END");
468 }
469
470 static void
471 _outCaseWhen(String *str, CaseWhen *node)
472 {
473         string_append_char(str, " WHEN ");
474         _outNode(str, node->expr);
475         string_append_char(str, " THEN ");
476         _outNode(str, node->result);
477 }
478
479 static void
480 _outCaseTestExpr(String *str, CaseTestExpr *node)
481 {
482
483 }
484
485 static void
486 _outArrayExpr(String *str, ArrayExpr *node)
487 {
488         string_append_char(str, "[");
489         _outNode(str, node->elements);
490         string_append_char(str, "]");
491 }
492
493 static void
494 _outRowExpr(String *str, RowExpr *node)
495 {
496         if (node->args == NIL)
497                 string_append_char(str, "ROW ()");
498         else
499         {
500                 string_append_char(str, "ROW (");
501                 _outNode(str, node->args);
502                 string_append_char(str, ")");
503         }
504 }
505
506 static void
507 _outCoalesceExpr(String *str, CoalesceExpr *node)
508 {
509         string_append_char(str, "COALESCE (");
510         _outNode(str, node->args);
511         string_append_char(str, ")");
512 }
513
514 static void
515 _outMinMaxExpr(String *str, MinMaxExpr *node)
516 {
517         if (node->op == IS_GREATEST)
518         {
519                 string_append_char(str, "GREATEST (");
520                 _outNode(str, node->args);
521                 string_append_char(str, ")");
522         }
523         else if (node->op == IS_LEAST)
524         {
525                 string_append_char(str, "LEAST (");
526                 _outNode(str, node->args);
527                 string_append_char(str, ")");
528         }
529 }
530
531 static void
532 _outNullIfExpr(String *str, NullIfExpr *node)
533 {
534
535 }
536
537 static void
538 _outNullTest(String *str, NullTest *node)
539 {
540         _outNode(str, node->arg);
541         if (node->nulltesttype == IS_NOT_NULL)
542                 string_append_char(str, " IS NOT NULL");
543         else
544                 string_append_char(str, " IS NULL");
545 }
546
547 static void
548 _outBooleanTest(String *str, BooleanTest *node)
549 {
550         _outNode(str, node->arg);
551
552         switch (node->booltesttype)
553         {
554                 case IS_TRUE:
555                         string_append_char(str, " IS TRUE");
556                         break;
557
558                 case IS_NOT_TRUE:
559                         string_append_char(str, " IS NOT TRUE");
560                         break;
561
562                 case IS_FALSE:
563                         string_append_char(str, " IS FALSE");
564                         break;
565
566                 case IS_NOT_FALSE:
567                         string_append_char(str, " IS NOT FALSE");
568                         break;
569
570                 case IS_UNKNOWN:
571                         string_append_char(str, " IS UNKNOWN");
572                         break;
573
574                 case IS_NOT_UNKNOWN:
575                         string_append_char(str, " IS NOT UNKNOWN");
576                         break;
577         }
578 }
579
580 static void
581 _outCoerceToDomain(String *str, CoerceToDomain *node)
582 {
583
584 }
585
586 static void
587 _outCoerceToDomainValue(String *str, CoerceToDomainValue *node)
588 {
589
590 }
591
592 static void
593 _outSetToDefault(String *str, SetToDefault *node)
594 {
595         string_append_char(str, "DEFAULT");
596 }
597
598 static void
599 _outTargetEntry(String *str, TargetEntry *node)
600 {
601
602 }
603
604 static void
605 _outRangeTblRef(String *str, RangeTblRef *node)
606 {
607
608 }
609
610 static void
611 _outJoinExpr(String *str, JoinExpr *node)
612 {
613         _outNode(str, node->larg);
614
615         if (node->isNatural == TRUE)
616                 string_append_char(str, " NATURAL");
617
618         if (node->jointype == JOIN_INNER)
619         {
620                 if (node->using == NIL && node->quals == NULL && !node->isNatural)
621                         string_append_char(str, " CROSS JOIN ");
622                 else
623                         string_append_char(str, " JOIN ");
624         }
625         else if (node->jointype == JOIN_INNER)
626                 string_append_char(str, " JOIN ");
627         else if (node->jointype == JOIN_LEFT)
628                 string_append_char(str, " LEFT OUTER JOIN ");
629         else if (node->jointype == JOIN_FULL)
630                 string_append_char(str, " FULL OUTER JOIN ");
631         else if (node->jointype == JOIN_RIGHT)
632                 string_append_char(str, " RIGHT OUTER JOIN ");
633
634         _outNode(str, node->rarg);
635
636         if (node->using != NIL && IsA(node->using, List))
637         {
638                 ListCell *lc;
639                 char comma = 0;
640
641                 string_append_char(str, " USING(");
642
643                 foreach (lc, node->using)
644                 {
645                         Value *value;
646
647                         if (comma == 0)
648                                 comma = 1;
649                         else
650                                 string_append_char(str, ",");
651                         
652                         value = lfirst(lc);
653                         string_append_char(str, "\"");
654                         string_append_char(str, value->val.str);
655                         string_append_char(str, "\"");
656                 }
657                 
658                 string_append_char(str, ")");
659         }
660
661         if (node->quals)
662         {
663                 string_append_char(str, " ON ");
664                 _outNode(str, node->quals);
665         }
666 }
667
668 static void
669 _outFromExpr(String *str, FromExpr *node)
670 {
671
672 }
673
674 /*****************************************************************************
675  *
676  *      Stuff from parsenodes.h.
677  *
678  *****************************************************************************/
679
680 static void
681 _outCreateStmt(String *str, CreateStmt *node)
682 {
683         string_append_char(str, "CREATE ");
684         if (node->relation->istemp)
685                 string_append_char(str, "TEMP ");
686         string_append_char(str, "TABLE ");
687         _outNode(str, node->relation);
688         string_append_char(str, " (");
689         _outNode(str, node->tableElts);
690         string_append_char(str, ") ");
691
692         if (node->inhRelations != NIL)
693         {
694                 string_append_char(str, "INHERITS (");
695                 _outNode(str, node->inhRelations);
696                 string_append_char(str, ")");
697         }
698
699         if (node->options)
700                 _outWithDefinition(str, node->options);
701
702         switch (node->oncommit)
703         {
704                 case ONCOMMIT_DROP:
705                         string_append_char(str, " ON COMMIT DROP");
706                         break;
707
708                 case ONCOMMIT_DELETE_ROWS:
709                         string_append_char(str, " ON COMMIT DELETE ROWS");
710                         break;
711
712                 case ONCOMMIT_PRESERVE_ROWS:
713                         string_append_char(str, " ON COMMIT PRESERVE ROWS");
714                         break;
715
716                 default:
717                         break;
718         }
719
720         if (node->tablespacename)
721         {
722                 string_append_char(str, " TABLESPACE \"");
723                 string_append_char(str, node->tablespacename);
724                 string_append_char(str, "\"");
725         }
726 }
727
728 static void
729 _outIndexStmt(String *str, IndexStmt *node)
730 {
731         string_append_char(str, "CREATE ");
732
733         if (node->unique == TRUE)
734                 string_append_char(str, "UNIQUE ");
735
736         if (node->concurrent == true)
737                 string_append_char(str, "INDEX CONCURRENTLY \"");
738         else
739                 string_append_char(str, "INDEX \"");            
740         string_append_char(str, node->idxname);
741         string_append_char(str, "\" ON ");
742         _outNode(str, node->relation);
743         
744         if (strcmp(node->accessMethod, DEFAULT_INDEX_TYPE))
745         {
746                 string_append_char(str, " USING ");
747                 string_append_char(str, node->accessMethod);
748         }
749
750         string_append_char(str, "(");
751         _outNode(str, node->indexParams);
752         string_append_char(str, ")");
753
754         if (node->tableSpace)
755         {
756                 string_append_char(str, " TABLESPACE \"");
757                 string_append_char(str, node->tableSpace);
758                 string_append_char(str, "\"");
759         }
760
761         if (node->whereClause)
762         {
763                 string_append_char(str, " WHERE ");
764                 _outNode(str, node->whereClause);
765         }
766 }
767
768 static void
769 _outNotifyStmt(String *str, NotifyStmt *node)
770 {
771         string_append_char(str, "NOTIFY ");
772         _outNode(str, node->relation);
773 }
774
775 static void
776 _outDeclareCursorStmt(String *str, DeclareCursorStmt *node)
777 {
778         string_append_char(str, "DECLARE \"");
779         string_append_char(str, node->portalname);
780         string_append_char(str, "\" ");
781
782         if (node->options & CURSOR_OPT_SCROLL)
783                 string_append_char(str, "SCROLL ");
784         if (node->options & CURSOR_OPT_BINARY)
785                 string_append_char(str, "BINARY ");
786         if (node->options & CURSOR_OPT_INSENSITIVE)
787                 string_append_char(str, "INSENSITIVE ");
788
789         string_append_char(str, "CURSOR ");
790         if (node->options & CURSOR_OPT_HOLD)
791                 string_append_char(str, "WITH HOLD ");
792         string_append_char(str, "FOR");
793         _outNode(str, node->query);
794 }
795
796 static void
797 _outSelectStmt(String *str, SelectStmt *node)
798 {
799         if (node->larg) /* SETOP */
800         {
801                 string_append_char(str, "(");
802                 _outNode(str, node->larg);
803                 string_append_char(str, ") ");
804
805                 switch (node->op)
806                 {
807                         case SETOP_UNION:
808                                 string_append_char(str, " UNION ");
809                                 break;
810                                 
811                         case SETOP_INTERSECT:
812                                 string_append_char(str, " INTERSECT ");
813                                 break;
814                                 
815                         case SETOP_EXCEPT:
816                                 string_append_char(str, " EXCEPT ");
817                                 
818                         default:
819                                 break;
820                 }
821
822                 if (node->all)
823                         string_append_char(str, "ALL ");
824
825                 if (node->rarg)
826                 {
827                         string_append_char(str, "(");
828                         _outNode(str, node->rarg);
829                         string_append_char(str, ") ");
830                 }
831         }
832         else if (node->valuesLists) /* VALUES ... */
833         {
834                 ListCell *lc;
835                 int comma = 0;
836
837                 foreach (lc, node->valuesLists)
838                 {
839                         if (comma == 0)
840                                 comma = 1;
841                         else
842                                 string_append_char(str, ",");
843
844                         string_append_char(str, " VALUES (");
845                         _outNode(str, lfirst(lc));
846                         string_append_char(str, ")");
847                 }
848         }
849         else
850         {
851                 if (node->intoClause)
852                 {
853                         IntoClause *into = (IntoClause *)node->intoClause;
854                         RangeVar *rel = (RangeVar *)into->rel;
855
856                         string_append_char(str, "CREATE ");
857                         if (rel->istemp == true)
858                                 string_append_char(str, "TEMP ");
859                         string_append_char(str, "TABLE ");
860                         _outNode(str, into->rel);
861
862                         if (into->colNames)
863                         {
864                                 string_append_char(str, " (");
865                                 _outNode(str, into->colNames);
866                                 string_append_char(str, ") ");
867                         }
868                         
869                         if (into->options)
870                                 _outWithDefinition(str, into->options);
871
872                         switch (into->onCommit)
873                         {
874                                 case ONCOMMIT_DROP:
875                                         string_append_char(str, " ON COMMIT DROP");
876                                         break;
877
878                                 case ONCOMMIT_DELETE_ROWS:
879                                         string_append_char(str, " ON COMMIT DELETE ROWS");
880                                         break;
881
882                                 case ONCOMMIT_PRESERVE_ROWS:
883                                         string_append_char(str, " ON COMMIT PRESERVE ROWS");
884                                         break;
885
886                                 default:
887                                         break;
888                         }
889
890                         string_append_char(str, " AS");
891                 }
892
893                 string_append_char(str, " SELECT ");
894
895                 if (node->distinctClause)
896                 {
897                         string_append_char(str, "DISTINCT ");
898                         if (lfirst(list_head(node->distinctClause)) != NIL)
899                         {
900                                 string_append_char(str, "ON (");
901                                 _outNode(str, node->distinctClause);
902                                 string_append_char(str, " ) ");
903                         }
904                 }
905
906                 _outNode(str, node->targetList);
907
908                 if (node->fromClause)
909                 {
910                         string_append_char(str, " FROM ");
911                         _outNode(str, node->fromClause);
912                 }
913
914                 if (node->whereClause)
915                 {
916                         string_append_char(str, " WHERE ");
917                         _outNode(str, node->whereClause);
918                 }
919
920                 if (node->groupClause)
921                 {
922                         string_append_char(str, " GROUP BY ");
923                         _outNode(str, node->groupClause);
924                 }
925
926                 if (node->havingClause)
927                 {
928                         string_append_char(str, " HAVING ");
929                         _outNode(str, node->havingClause);
930                 }
931         }
932
933         if (node->sortClause)
934         {
935                 string_append_char(str, " ORDER BY ");
936                 _outNode(str, node->sortClause);
937         }
938
939         if (node->limitOffset)
940         {
941                 string_append_char(str, " OFFSET ");
942                 _outNode(str, node->limitOffset);
943         }
944
945         if (node->limitCount)
946         {
947                 string_append_char(str, " LIMIT ");
948                 if (IsA(node->limitCount, A_Const) &&
949                         ((A_Const *)node->limitCount)->val.type == T_Null)
950                 {
951                         string_append_char(str, "ALL ");
952                 }
953                 else
954                 {
955                         _outNode(str, node->limitCount);
956                 }
957         }
958
959         _outNode(str, node->lockingClause);
960 }
961
962 static void
963 _outFuncCall(String *str, FuncCall *node)
964 {
965         char *funcname;
966         _outFuncName(str, node->funcname);
967
968         funcname = strVal(lfirst(list_head(node->funcname)));
969
970     if(strcmp(funcname,"user") == 0 ||
971        strcmp(funcname,"current_user") == 0 ||
972        strcmp(funcname,"session_user") == 0 ||
973        strcmp(funcname,"current_role") == 0)
974         return ;
975
976         string_append_char(str, "(");
977
978         if (node->agg_distinct == TRUE)
979                 string_append_char(str, "DISTINCT ");
980
981         if (node->agg_star == TRUE)
982                 string_append_char(str, "*");
983         else
984                 _outNode(str, node->args);
985
986         string_append_char(str, ")");
987 }
988
989 static void
990 _outDefElem(String *str, DefElem *node)
991 {
992
993 }
994
995 static void
996 _outLockingClause(String *str, LockingClause *node)
997 {
998         if (node == NULL)
999                 return;
1000
1001         if (node->forUpdate == TRUE)
1002                 string_append_char(str, " FOR UPDATE");
1003         else
1004                 string_append_char(str, " FOR SHARED");
1005
1006         _outNode(str, node->lockedRels);
1007
1008         if (node->noWait == TRUE)
1009                 string_append_char(str, " NOWAIT ");
1010 }
1011
1012 static void
1013 _outColumnDef(String *str, ColumnDef *node)
1014 {
1015         string_append_char(str, "\"");
1016         string_append_char(str, node->colname);
1017         string_append_char(str, "\" ");
1018         _outNode(str, node->typename);
1019         _outNode(str, node->constraints);
1020 }
1021
1022 static void
1023 _outTypeName(String *str, TypeName *node)
1024 {
1025         ListCell *lc;
1026         char dot = 0;
1027
1028         foreach (lc, node->names)
1029         {
1030                 Value *v = (Value *) lfirst(lc);
1031                 char *typename = v->val.str;
1032
1033                 if (dot == 0)
1034                         dot = 1;
1035                 else
1036                         string_append_char(str, ".");
1037                 if(node->typemod < 0)
1038                 {
1039                         string_append_char(str, "\"");
1040                         string_append_char(str, typename);
1041                         string_append_char(str, "\"");
1042                 } else 
1043                         string_append_char(str, typename);
1044         }
1045         
1046         if (node->typemod > 0)
1047         {
1048         int lower;
1049         char buf[16];
1050         string_append_char(str, "(");
1051         snprintf(buf, 16, "%d", ((node->typemod - VARHDRSZ) >> 16) & 0x00FF);
1052         string_append_char(str, buf);
1053         lower = (node->typemod-VARHDRSZ) & 0x00FF;
1054
1055         if(lower != 0)
1056         {
1057             char buf2[16];
1058             string_append_char(str, ",");
1059             snprintf(buf2, 16, "%d",lower);
1060             string_append_char(str, buf2);
1061         }
1062
1063         string_append_char(str, ")");
1064         }
1065 }
1066
1067 static void
1068 _outTypeCast(String *str, TypeCast *node)
1069 {
1070         _outNode(str, node->arg);
1071         string_append_char(str, "::");
1072         _outNode(str, node->typename);
1073
1074 }
1075
1076 static void
1077 _outIndexElem(String *str, IndexElem *node)
1078 {
1079         if (node->name)
1080         {
1081                 string_append_char(str, "\"");
1082                 string_append_char(str, node->name);
1083                 string_append_char(str, "\"");
1084                 if (node->opclass != NIL)
1085                         _outNode(str, node->opclass);
1086         }
1087         else
1088         {
1089                 string_append_char(str, "(");
1090                 _outNode(str, node->expr);
1091                 string_append_char(str, ")");
1092                 if (node->opclass != NIL)
1093                         _outNode(str, node->opclass);
1094         }
1095 }
1096
1097
1098 static void
1099 _outSortClause(String *str, SortClause *node)
1100 {
1101
1102 }
1103
1104 static void
1105 _outGroupClause(String *str, GroupClause *node)
1106 {
1107
1108 }
1109
1110 static void
1111 _outSetOperationStmt(String *str, SetOperationStmt *node)
1112 {
1113
1114 }
1115
1116
1117 static void
1118 _outAExpr(String *str, A_Expr *node)
1119 {
1120         Value *v;
1121
1122         switch (node->kind)
1123         {
1124                 case AEXPR_OP:
1125                         if (list_length(node->name) == 1)
1126                         {
1127                                 Value *op = (Value *) lfirst(list_head(node->name));
1128
1129                                 string_append_char(str, " (");
1130                                 _outNode(str, node->lexpr);
1131                                 string_append_char(str, op->val.str);
1132                                 _outNode(str, node->rexpr);
1133                                 string_append_char(str, " )");
1134                         }
1135                         break;
1136
1137                 case AEXPR_AND:
1138                         string_append_char(str, " (");
1139                         _outNode(str, node->lexpr);
1140                         string_append_char(str, " AND ");
1141                         _outNode(str, node->rexpr);
1142                         string_append_char(str, ")");
1143                         break;
1144                                 
1145                 case AEXPR_OR:
1146                         string_append_char(str, " (");
1147                         _outNode(str, node->lexpr);
1148                         string_append_char(str, " OR ");
1149                         _outNode(str, node->rexpr);
1150                         string_append_char(str, ")");
1151                         break;
1152
1153                 case AEXPR_NOT:
1154                         string_append_char(str, " (NOT ");
1155                         _outNode(str, node->rexpr);
1156                         string_append_char(str, ")");
1157                         break;
1158
1159                 case AEXPR_OP_ANY:
1160                         _outNode(str, node->lexpr);
1161                         v = linitial(node->name);
1162                         string_append_char(str, v->val.str);
1163                         string_append_char(str, "ANY(");
1164                         _outNode(str, node->rexpr);
1165                         string_append_char(str, ")");
1166                         break;
1167
1168                 case AEXPR_OP_ALL:
1169                         _outNode(str, node->lexpr);
1170                         v = linitial(node->name);
1171                         string_append_char(str, v->val.str);
1172                         string_append_char(str, "ALL(");
1173                         _outNode(str, node->rexpr);
1174                         string_append_char(str, ")");
1175                         break;
1176
1177                 case AEXPR_DISTINCT:
1178                         string_append_char(str, " (");
1179                         _outNode(str, node->lexpr);
1180                         string_append_char(str, " IS DISTINCT FROM ");
1181                         _outNode(str, node->rexpr);
1182                         string_append_char(str, ")");                           
1183                         break;
1184
1185                 case AEXPR_NULLIF:
1186                         string_append_char(str, " NULLIF(");
1187                         _outNode(str, node->lexpr);
1188                         string_append_char(str, ", ");
1189                         _outNode(str, node->rexpr);
1190                         string_append_char(str, ")");
1191                         break;
1192
1193                 case AEXPR_OF:
1194                         _outNode(str, node->lexpr);
1195                         v = linitial(node->name);
1196                         if (v->val.str[0] == '!')
1197                                 string_append_char(str, " IS NOT OF (");
1198                         else
1199                                 string_append_char(str, " IS OF (");
1200                         _outNode(str, node->rexpr);
1201                         string_append_char(str, ")");
1202                         break;
1203
1204                 case AEXPR_IN:
1205                         _outNode(str, node->lexpr);
1206                         v = (Value *)lfirst(list_head(node->name));
1207                         if (v->val.str[0] == '=')
1208                                 string_append_char(str, " IN (");
1209                         else
1210                                 string_append_char(str, " NOT IN (");
1211                         _outNode(str, node->rexpr);
1212                         string_append_char(str, ")");
1213                         break;
1214
1215                 default:
1216                         break;
1217         }
1218 }
1219
1220 static void
1221 _outValue(String *str, Value *value)
1222 {
1223         char buf[16];
1224
1225         switch (value->type)
1226         {
1227                 case T_Integer:
1228                         sprintf(buf, "%ld", value->val.ival);
1229                         string_append_char(str, buf);
1230                         break;
1231
1232                 case T_Float:
1233                         string_append_char(str, value->val.str);
1234                         break;
1235
1236                 case T_String:
1237                         string_append_char(str, "'");
1238                         string_append_char(str, escape_string(value->val.str));
1239                         string_append_char(str, "'");
1240                         break;
1241
1242                 case T_Null:
1243                         string_append_char(str, "NULL");
1244                         break;
1245
1246                 default:
1247                         break;
1248         }
1249 }
1250
1251 static void
1252 _outColumnRef(String *str, ColumnRef *node)
1253 {
1254         ListCell *c;
1255         char first = 0;
1256
1257         foreach (c, node->fields)
1258         {
1259                 Node *n = (Node *) lfirst(c);
1260
1261                 if (IsA(n, String))
1262                 {
1263                         Value *v = (Value *) lfirst(c);
1264
1265                         if (first == 0)
1266                                 first = 1;
1267                         else
1268                                 string_append_char(str, ".");
1269
1270                         string_append_char(str, "\"");
1271                         string_append_char(str, v->val.str);
1272                         string_append_char(str, "\"");
1273                 }
1274         }
1275 }
1276
1277 static void
1278 _outParamRef(String *str, ParamRef *node)
1279 {
1280         char buf[16];
1281
1282         snprintf(buf, 16, "%d", node->number);
1283         string_append_char(str, "$");
1284         string_append_char(str, buf);
1285 }
1286
1287 static void
1288 _outAConst(String *str, A_Const *node)
1289 {
1290         char buf[16];
1291         char *name = NULL;
1292
1293         if (node->typename)
1294         {
1295                 Value *v = linitial(node->typename->names);
1296                 name = v->val.str;
1297                 _outNode(str, node->typename);
1298                 string_append_char(str, " ");
1299         }
1300
1301         switch (node->val.type)
1302         {
1303                 case T_Integer:
1304                         sprintf(buf, "%ld", node->val.val.ival);
1305                         string_append_char(str, buf);
1306                         break;
1307
1308                 case T_Float:
1309                         string_append_char(str, node->val.val.str);
1310                         break;
1311
1312                 case T_String:
1313                         string_append_char(str, "'");
1314                         string_append_char(str, escape_string(node->val.val.str));
1315                         string_append_char(str, "'");
1316                         break;
1317
1318                 case T_Null:
1319                         string_append_char(str, "NULL");
1320                         break;
1321
1322                 default:
1323                         break;
1324         }
1325
1326         if (name && (strcmp(name, "interval") == 0) &&
1327                 node->typename->typmods)
1328         {
1329                 A_Const *v = linitial(node->typename->typmods);
1330                 int mask = v->val.val.ival;
1331
1332                 if (mask == INTERVAL_MASK(YEAR))
1333                         string_append_char(str, " YEAR");
1334                 else if (mask == INTERVAL_MASK(MONTH))
1335                         string_append_char(str, " MONTH");
1336                 else if (mask == INTERVAL_MASK(DAY))
1337                         string_append_char(str, " DAY");
1338                 else if (mask == INTERVAL_MASK(HOUR))
1339                         string_append_char(str, " HOUR");
1340                 else if (mask == INTERVAL_MASK(MINUTE))
1341                         string_append_char(str, " MINUTE");
1342                 else if (mask == INTERVAL_MASK(SECOND))
1343                         string_append_char(str, " SECOND");
1344                 else if (mask == (INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH)))
1345                         string_append_char(str, " YEAR TO MONTH");
1346                 else if (mask == (INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR)))
1347                         string_append_char(str, " DAY TO HOUR");
1348                 else if (mask == (INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) |
1349                                                   INTERVAL_MASK(MINUTE)))
1350                         string_append_char(str, " DAY TO MINUTE");
1351                 else if (mask == (INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) |
1352                                                   INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND)))
1353                         string_append_char(str, " DAY TO SECOND");
1354                 else if (mask == (INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE)))
1355                         string_append_char(str, " HOUR TO MINUTE");
1356                 else if (mask == (INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) |
1357                                                   INTERVAL_MASK(SECOND)))
1358                         string_append_char(str, " HOUR TO SECOND");
1359         }
1360 }
1361
1362 static void
1363 _outA_Indices(String *str, A_Indices *node)
1364 {
1365         string_append_char(str, "[");
1366         if (node->lidx)
1367         {
1368                 _outNode(str, node->lidx);
1369                 string_append_char(str, ":");
1370         }
1371         _outNode(str, node->uidx);
1372         string_append_char(str, "]");
1373 }
1374
1375 static void
1376 _outA_Indirection(String *str, A_Indirection *node)
1377 {
1378         _outNode(str, node->arg);
1379         _outNode(str, node->indirection);
1380 }
1381
1382 static void
1383 _outResTarget(String *str, ResTarget *node)
1384 {
1385         if (node->indirection != NIL)
1386         {
1387                 string_append_char(str, "\"");
1388                 string_append_char(str, node->name);
1389                 string_append_char(str, "\"=");
1390                 _outNode(str, node->val);
1391         }
1392         else
1393         {
1394                 _outNode(str, node->val);
1395
1396                 if (node->name)
1397                 {
1398                         string_append_char(str, " AS ");
1399                         string_append_char(str, "\"");
1400                         string_append_char(str, node->name);
1401                         string_append_char(str, "\" ");
1402                 }
1403         }
1404 }
1405
1406 static void
1407 _outConstraint(String *str, Constraint *node)
1408 {
1409         if (node->name)
1410         {
1411                 string_append_char(str, "CONSTRAINT \"");
1412                 string_append_char(str, node->name);
1413                 string_append_char(str, "\"");
1414         }
1415
1416         switch (node->contype)
1417         {
1418                 case CONSTR_CHECK:
1419                         string_append_char(str, " CHECK (");
1420                         _outNode(str, node->raw_expr);
1421                         string_append_char(str, ")");
1422                         break;
1423
1424                 case CONSTR_UNIQUE:
1425                         string_append_char(str, " UNIQUE");
1426                         if (node->keys)
1427                         {
1428                                 string_append_char(str, "(");
1429                                 _outIdList(str, node->keys);
1430                                 string_append_char(str, ")");
1431                         }
1432
1433                         if (node->options)
1434                         {
1435                                 _outWithDefinition(str, node->options);
1436                         }
1437                         
1438                         if (node->indexspace)
1439                         {
1440                                 string_append_char(str, " USING INDEX TABLESPACE \"");
1441                                 string_append_char(str, node->indexspace);
1442                                 string_append_char(str, "\"");
1443                         }
1444                         break;
1445
1446                 case CONSTR_PRIMARY:
1447                         string_append_char(str, " PRIMARY KEY");
1448                         if (node->keys)
1449                         {
1450                                 string_append_char(str, "(");
1451                                 _outIdList(str, node->keys);
1452                                 string_append_char(str, ")");
1453                         }
1454                         if (node->options)
1455                                 ;
1456
1457                         if (node->indexspace)
1458                         {
1459                                 string_append_char(str, " USING INDEX TABLESPACE \"");
1460                                 string_append_char(str, node->indexspace);
1461                                 string_append_char(str, "\"");
1462                         }
1463                         break;
1464
1465                 case CONSTR_NOTNULL:
1466                         string_append_char(str, " NOT NULL");
1467                         break;
1468
1469                 case CONSTR_NULL:
1470                         string_append_char(str, " NULL");
1471                         break;
1472
1473                 case CONSTR_DEFAULT:
1474                         string_append_char(str, "DEFAULT ");
1475                         _outNode(str, node->raw_expr);
1476                         break;
1477
1478                 default:
1479                         break;
1480         }
1481 }
1482
1483 static void
1484 _outFkConstraint(String *str, FkConstraint *node)
1485 {
1486         if (node->constr_name)
1487         {
1488                 string_append_char(str, "CONSTRAINT \"");
1489                 string_append_char(str, node->constr_name);
1490                 string_append_char(str, "\"");
1491         }
1492
1493         if (node->fk_attrs != NIL)
1494         {
1495                 string_append_char(str, " FOREIGN KEY (");
1496                 _outIdList(str, node->fk_attrs);
1497                 string_append_char(str, ")" );
1498         }
1499
1500         string_append_char(str, " REFERENCES ");
1501         _outNode(str, node->pktable);
1502
1503         if (node->pk_attrs != NIL)
1504         {
1505                 string_append_char(str, "(");
1506                 _outIdList(str, node->pk_attrs);
1507                 string_append_char(str, ")");
1508         }
1509
1510         switch (node->fk_matchtype)
1511         {
1512                 case FKCONSTR_MATCH_FULL:
1513                         string_append_char(str, " MATCH FULL");
1514                         break;
1515
1516                 case FKCONSTR_MATCH_PARTIAL:
1517                         string_append_char(str, " MATCH PARTIAL");
1518                         break;
1519
1520                 default:
1521                         break;
1522         }
1523
1524         switch (node->fk_upd_action)
1525         {
1526                 case FKCONSTR_ACTION_RESTRICT:
1527                         string_append_char(str, " ON UPDATE RESTRICT");
1528                         break;
1529
1530                 case FKCONSTR_ACTION_CASCADE:
1531                         string_append_char(str, " ON UPDATE CASCADE");
1532                         break;
1533
1534                 case FKCONSTR_ACTION_SETNULL:
1535                         string_append_char(str, " ON UPDATE SET NULL");
1536                         break;
1537
1538                 case FKCONSTR_ACTION_SETDEFAULT:
1539                         string_append_char(str, " ON UPDATE SET DEFAULT");
1540                         break;
1541
1542                 default:
1543                         break;
1544         }
1545
1546         switch (node->fk_del_action)
1547         {
1548                 case FKCONSTR_ACTION_RESTRICT:
1549                         string_append_char(str, " ON DELETE RESTRICT");
1550                         break;
1551
1552                 case FKCONSTR_ACTION_CASCADE:
1553                         string_append_char(str, " ON DELETE CASCADE");
1554                         break;
1555
1556                 case FKCONSTR_ACTION_SETNULL:
1557                         string_append_char(str, " ON DELETE SET NULL");
1558                         break;
1559
1560                 case FKCONSTR_ACTION_SETDEFAULT:
1561                         string_append_char(str, " ON DELETE SET DEFAULT");
1562                         break;
1563
1564                 default:
1565                         break;
1566         }
1567
1568         if (node->deferrable)
1569                 string_append_char(str, " DEFERRABLE");
1570
1571         if (node->initdeferred)
1572                 string_append_char(str, " INITIALLY DEFERRED");
1573 }
1574
1575
1576 static void
1577 _outSortBy(String *str, SortBy *node)
1578 {
1579         _outNode(str, node->node);
1580         
1581         if (node->sortby_dir == SORTBY_USING)
1582         {
1583                 string_append_char(str, " USING ");
1584                 _outNode(str, node->useOp);
1585         }
1586         else if (node->sortby_dir == SORTBY_DESC)
1587                 string_append_char(str, " DESC ");
1588
1589         if (node->sortby_nulls == SORTBY_NULLS_FIRST)
1590                 string_append_char(str, " NULLS FIRST ");
1591         else if (node->sortby_nulls == SORTBY_NULLS_LAST)
1592                 string_append_char(str, " NULLS LAST ");
1593 }
1594
1595 static void _outInsertStmt(String *str, InsertStmt *node)
1596 {
1597         string_append_char(str, "INSERT INTO ");
1598         _outNode(str, node->relation);
1599
1600         if (node->cols == NIL && node->selectStmt == NULL)
1601                 string_append_char(str, " DEFAULT VALUES");
1602
1603         if (node->cols)
1604         {
1605                 char comma = 0;
1606                 ListCell *lc;
1607
1608                 string_append_char(str, "(");
1609
1610                 foreach (lc, node->cols)
1611                 {
1612                         ResTarget *node = lfirst(lc);
1613                         if (comma == 0)
1614                                 comma = 1;
1615                         else
1616                                 string_append_char(str, ", ");
1617
1618                         string_append_char(str, "\"");
1619                         string_append_char(str, node->name);
1620                         string_append_char(str, "\"");
1621                 }
1622                 string_append_char(str, ")");
1623         }
1624
1625         if (node->selectStmt)
1626         {
1627                 _outNode(str, node->selectStmt);
1628         }
1629
1630         if (node->returningList)
1631         {
1632                 string_append_char(str, " RETURNING ");
1633                 _outNode(str, node->returningList);
1634         }
1635 }
1636
1637 static void _outUpdateStmt(String *str, UpdateStmt *node)
1638 {
1639         ListCell *lc;
1640         char comma = 0;
1641
1642         string_append_char(str, "UPDATE ");
1643
1644         _outNode(str, node->relation);
1645
1646         string_append_char(str, " SET ");
1647         foreach (lc, node->targetList)
1648         {
1649                 ResTarget *node = lfirst(lc);
1650                 if (comma == 0)
1651                         comma = 1;
1652                 else
1653                         string_append_char(str, ", ");
1654
1655                 string_append_char(str, "\"");
1656                 string_append_char(str, node->name);
1657                 string_append_char(str, "\" = ");
1658                 _outNode(str, node->val);
1659         }
1660
1661         if (node->fromClause)
1662         {
1663                 string_append_char(str, " FROM ");
1664                 _outNode(str, node->fromClause);
1665         }
1666
1667         if (node->whereClause)
1668         {
1669                 string_append_char(str, " WHERE ");
1670                 _outNode(str, node->whereClause);
1671         }
1672
1673         if (node->returningList)
1674         {
1675                 string_append_char(str, " RETURNING ");
1676                 _outNode(str, node->returningList);
1677         }
1678 }
1679
1680 static void _outDeleteStmt(String *str, DeleteStmt *node)
1681 {
1682         string_append_char(str, "DELETE FROM ");
1683
1684         _outNode(str, node->relation);
1685
1686         if (node->usingClause)
1687         {
1688                 string_append_char(str, " USING ");
1689                 _outNode(str, node->usingClause);
1690         }
1691
1692         if (node->whereClause)
1693         {
1694                 string_append_char(str, " WHERE ");
1695                 _outNode(str, node->whereClause);
1696         }
1697
1698         if (node->returningList)
1699         {
1700                 string_append_char(str, " RETURNING ");
1701                 _outNode(str, node->returningList);
1702         }
1703 }
1704
1705 static void _outTransactionStmt(String *str, TransactionStmt *node)
1706 {
1707         switch (node->kind)
1708         {
1709                 case TRANS_STMT_BEGIN:
1710                         string_append_char(str, "BEGIN ");
1711                         break;
1712
1713                 case TRANS_STMT_START:
1714                         string_append_char(str, "START TRANSACTION ");
1715                         break;
1716
1717                 case TRANS_STMT_COMMIT:
1718                         string_append_char(str, "COMMIT ");
1719                         break;
1720
1721                 case TRANS_STMT_ROLLBACK:
1722                         string_append_char(str, "ABORT ");
1723                         break;
1724
1725                 case TRANS_STMT_SAVEPOINT:
1726                         string_append_char(str, "SAVEPOINT ");
1727                         break;
1728
1729                 case TRANS_STMT_RELEASE:
1730                         string_append_char(str, "RELEASE ");
1731                         break;
1732
1733                 case TRANS_STMT_ROLLBACK_TO:
1734                         string_append_char(str, "ROLLBACK TO ");
1735                         break;
1736
1737                 case TRANS_STMT_PREPARE:
1738                         string_append_char(str, "PREPARE TRANSACTION ");
1739                         break;
1740
1741                 case TRANS_STMT_COMMIT_PREPARED:
1742                         string_append_char(str, "COMMIT PREPARED ");
1743                         break;
1744
1745                 case TRANS_STMT_ROLLBACK_PREPARED:
1746                         string_append_char(str, "ROLLBACK PREPARED ");
1747                         break;
1748
1749                 default:
1750                         break;
1751         }
1752
1753         if (node->options)
1754                 _outSetTransactionModeList(str, node->options);
1755
1756         if (node->gid)
1757                 string_append_char(str, node->gid);
1758 }
1759
1760
1761 static void _outTruncateStmt(String *str, TruncateStmt *node)
1762 {
1763         string_append_char(str, "TRUNCATE ");
1764         _outNode(str, node->relations);
1765 }
1766
1767 static void _outVacuumStmt(String *str, VacuumStmt *node)
1768 {
1769         if (node->vacuum == true)
1770                 string_append_char(str, "VACUUM ");
1771         else
1772                 string_append_char(str, "ANALYZE ");
1773
1774         if (node->full == TRUE)
1775                 string_append_char(str, "FULL ");
1776         
1777         if (node->freeze_min_age == 0)
1778                 string_append_char(str, "FREEZE ");
1779
1780         if (node->verbose == TRUE)
1781                 string_append_char(str, "VERBOSE ");
1782
1783         if (node->analyze)
1784                 string_append_char(str, "ANALYZE ");
1785
1786         _outNode(str, node->relation);
1787         if (node->va_cols)
1788         {
1789                 string_append_char(str, "(");
1790                 _outIdList(str, node->va_cols);
1791                 string_append_char(str, ") ");
1792         }
1793 }
1794
1795 static void _outExplainStmt(String *str, ExplainStmt *node)
1796 {
1797         string_append_char(str, "EXPLAIN ");
1798         
1799         if (node->analyze == TRUE)
1800                 string_append_char(str, "ANALYZE ");
1801         if (node->verbose == TRUE)
1802                 string_append_char(str, "VERBOSE ");
1803
1804         _outNode(str, node->query);
1805 }
1806
1807 static void _outClusterStmt(String *str, ClusterStmt *node)
1808 {
1809         string_append_char(str, "CLUSTER ");
1810         
1811         if (node->indexname)
1812         {
1813                 string_append_char(str, "\"");
1814                 string_append_char(str, node->indexname);
1815                 string_append_char(str, "\" ON ");
1816         }
1817         if (node->relation)
1818                 _outNode(str, node->relation);
1819 }
1820
1821 static void _outCheckPointStmt(String *str, CheckPointStmt *node)
1822 {
1823         string_append_char(str, "CHECKPOINT");
1824 }
1825
1826 static void _outClosePortalStmt(String *str, ClosePortalStmt *node)
1827 {
1828         string_append_char(str, "CLOSE ");
1829         string_append_char(str, "\"");
1830         string_append_char(str, node->portalname);
1831         string_append_char(str, "\"");
1832 }
1833
1834 static void _outListenStmt(String *str, ListenStmt *node)
1835 {
1836         string_append_char(str, "LISTEN ");
1837         _outNode(str, node->relation);
1838 }
1839
1840 static void _outUnlistenStmt(String *str, UnlistenStmt *node)
1841 {
1842         string_append_char(str, "UNLISTEN ");
1843         _outNode(str, node->relation);
1844 }
1845
1846 static void _outLoadStmt(String *str, LoadStmt *node)
1847 {
1848         string_append_char(str, "LOAD '");
1849         string_append_char(str, node->filename);
1850         string_append_char(str, "'");
1851 }
1852
1853 static void _outCopyStmt(String *str, CopyStmt *node)
1854 {
1855         int binary = FALSE;
1856         int oids = FALSE;
1857         char *delimiter = NULL;
1858         char *null = NULL;
1859         int csv = FALSE;
1860         int header = FALSE;
1861         char *quote = NULL;
1862         char *escape = NULL;
1863         Node *force_quote = NULL;
1864         Node *force_notnull = NULL;
1865         ListCell *lc;
1866
1867         foreach (lc, node->options)
1868         {
1869                 DefElem *e = lfirst(lc);
1870
1871                 if (strcmp(e->defname, "binary") == 0)
1872                         binary = TRUE;
1873                 else if (strcmp(e->defname, "oids") == 0)
1874                         oids = TRUE;
1875                 else if (strcmp(e->defname, "delimiter") == 0)
1876                         delimiter = ((Value *) e->arg)->val.str;
1877                 else if (strcmp(e->defname, "null") == 0)
1878                         null = ((Value *) e->arg)->val.str;
1879                 else if (strcmp(e->defname, "csv") == 0)
1880                         csv = TRUE;
1881                 else if (strcmp(e->defname, "header") == 0)
1882                         header = TRUE;
1883                 else if (strcmp(e->defname, "quote") == 0)
1884                         quote = ((Value *) e->arg)->val.str;
1885                 else if (strcmp(e->defname, "escape") == 0)
1886                         escape = ((Value *) e->arg)->val.str;
1887                 else if (strcmp(e->defname, "force_quote") == 0)
1888                         force_quote = e->arg;
1889                 else if (strcmp(e->defname, "force_notnull") == 0)
1890                         force_notnull = e->arg;
1891         }
1892
1893         string_append_char(str, "COPY ");
1894
1895         if (node->query)
1896         {
1897                 string_append_char(str, "(");
1898                 _outNode(str, node->query);
1899                 string_append_char(str, ")");
1900         }
1901
1902         _outNode(str, node->relation);
1903
1904         if (node->attlist)
1905         {
1906                 string_append_char(str, "(");
1907                 _outIdList(str, node->attlist);
1908                 string_append_char(str, ") ");
1909         }
1910
1911         if (node->is_from == TRUE)
1912                 string_append_char(str, " FROM ");
1913         else
1914                 string_append_char(str, " TO ");
1915
1916         if (node->filename)
1917         {
1918                 string_append_char(str, "'");
1919                 string_append_char(str, node->filename);
1920                 string_append_char(str, "'");
1921         }
1922         else
1923                 string_append_char(str, node->is_from == TRUE ? "STDIN" : "STDOUT");
1924
1925         if (binary == TRUE)
1926                 string_append_char(str, " BINARY ");
1927
1928         if (oids == TRUE)
1929                 string_append_char(str, " OIDS ");
1930
1931         if (delimiter)
1932         {
1933                 string_append_char(str, " DELIMITERS '");
1934                 string_append_char(str, delimiter);
1935                 string_append_char(str, "'");
1936         }
1937
1938         if (null)
1939         {
1940                 string_append_char(str, " NULL '");
1941                 string_append_char(str, null);
1942                 string_append_char(str, "' ");
1943         }
1944
1945         if (csv == TRUE)
1946                 string_append_char(str, "CSV ");
1947
1948         if (header == TRUE)
1949                 string_append_char(str, "HEADER ");
1950
1951         if (quote)
1952         {
1953                 string_append_char(str, "QUOTE '");
1954                 string_append_char(str, quote);
1955                 string_append_char(str, "' ");
1956         }
1957
1958         if (escape)
1959         {
1960                 string_append_char(str, "ESCAPE '");
1961                 string_append_char(str, escape);
1962                 string_append_char(str, "' ");
1963         }
1964
1965         if (force_quote)
1966         {
1967                 string_append_char(str, "FORCE QUOTE ");
1968                 _outNode(str, force_quote);
1969         }
1970
1971         if (force_notnull)
1972         {
1973                 string_append_char(str, " FORCE NOT NULL ");
1974                 _outNode(str, force_notnull);
1975         }
1976 }
1977
1978 static void _outDeallocateStmt(String *str, DeallocateStmt *node)
1979 {
1980         string_append_char(str, "DEALLOCATE \"");
1981         string_append_char(str, node->name);
1982         string_append_char(str, "\"");
1983 }
1984
1985 static void _outRenameStmt(String *str, RenameStmt *node)
1986 {
1987         ListCell *lc;
1988         char comma = 0;
1989         
1990         string_append_char(str, "ALTER ");
1991
1992         switch (node->renameType)
1993         {
1994                 case OBJECT_AGGREGATE:
1995                         string_append_char(str, "AGGREGATE ");
1996                         _outNode(str, node->object);
1997                         string_append_char(str, " (");
1998                         string_append_char(str, ") RENAME TO \"");
1999                         string_append_char(str, node->newname);
2000                         string_append_char(str, "\"");
2001                         break;
2002
2003                 case OBJECT_CONVERSION:
2004                         string_append_char(str, "CONVERSION ");
2005                         _outNode(str, node->object);
2006                         string_append_char(str, " RENAME TO \"");
2007                         string_append_char(str, node->newname);
2008                         string_append_char(str, "\"");
2009                         break;
2010
2011                 case OBJECT_DATABASE:
2012                         string_append_char(str, "DATABASE \"");
2013                         string_append_char(str, node->subname);
2014                         string_append_char(str, "\" RENAME TO \"");
2015                         string_append_char(str, node->newname);
2016                         string_append_char(str, "\"");
2017                         break;
2018
2019                 case OBJECT_FUNCTION:
2020                         string_append_char(str, "FUNCTION ");
2021
2022                         foreach (lc, node->object)
2023                         {
2024                                 Node *n = lfirst(lc);
2025                                 if (IsA(n, String))
2026                                 {
2027                                         Value *value = (Value *) n;
2028                                         if (comma == 0)
2029                                                 comma = 1;
2030                                         else
2031                                                 string_append_char(str, ".");
2032                                         string_append_char(str, "\"");
2033                                         string_append_char(str, value->val.str);
2034                                         string_append_char(str, "\"");
2035                                 }
2036                                 else
2037                                         _outNode(str, n);
2038                         }
2039
2040                         string_append_char(str, "(");
2041                         _outNode(str, node->objarg);
2042                         string_append_char(str, ")");
2043                         string_append_char(str, " RENAME TO \"");
2044                         string_append_char(str, node->newname);
2045                         string_append_char(str, "\"");
2046                         break;
2047
2048                 case OBJECT_ROLE:
2049                         string_append_char(str, "ROLE \"");
2050                         string_append_char(str, node->subname);
2051                         string_append_char(str, "\" RENAME TO \"");
2052                         string_append_char(str, node->newname);
2053                         string_append_char(str, "\"");
2054                         break;
2055
2056                 case OBJECT_LANGUAGE:
2057                         string_append_char(str, "LANGUAGE \"");
2058                         string_append_char(str, node->subname);
2059                         string_append_char(str, "\" RENAME TO \"");
2060                         string_append_char(str, node->newname);
2061                         string_append_char(str, "\"");
2062                         break;
2063
2064                 case OBJECT_OPCLASS:
2065                         string_append_char(str, "OPERATOR CLASS ");
2066                         _outNode(str, node->object);
2067                         string_append_char(str, " USING ");
2068                         string_append_char(str, node->subname);
2069                         string_append_char(str, " RENAME TO \"");
2070                         string_append_char(str, node->newname);
2071                         string_append_char(str, "\"");
2072                         break;
2073
2074                 case OBJECT_SCHEMA:
2075                         string_append_char(str, "SCHEMA \"");
2076                         string_append_char(str, node->subname);
2077                         string_append_char(str, "\" RENAME TO \"");
2078                         string_append_char(str, node->newname);
2079                         string_append_char(str, "\"");
2080                         break;
2081
2082                 case OBJECT_TABLE:
2083                         string_append_char(str, "TABLE ");
2084                         _outNode(str, node->relation);
2085                         string_append_char(str, " RENAME TO \"");
2086                         string_append_char(str, node->newname);
2087                         string_append_char(str, "\"");
2088                         break;
2089                 
2090                 case OBJECT_INDEX:
2091                         string_append_char(str, "INDEX ");
2092                         _outNode(str, node->relation);
2093                         string_append_char(str, " RENAME TO \"");
2094                         string_append_char(str, node->newname);
2095                         string_append_char(str, "\"");
2096                         break;
2097
2098                 case OBJECT_COLUMN:
2099                         string_append_char(str, "TABLE ");
2100                         _outNode(str, node->relation);
2101                         string_append_char(str, " RENAME \"");
2102                         string_append_char(str, node->subname);
2103                         string_append_char(str, "\" TO \"");
2104                         string_append_char(str, node->newname);
2105                         string_append_char(str, "\"");
2106                         break;
2107
2108                 case OBJECT_TRIGGER:
2109                         string_append_char(str, "TRIGGER \"");
2110                         string_append_char(str, node->subname);
2111                         string_append_char(str, "\" ON ");
2112                         _outNode(str, node->relation);
2113                         string_append_char(str, " RENAME TO \"");
2114                         string_append_char(str, node->newname);
2115                         string_append_char(str, "\"");
2116                         break;
2117
2118                 case OBJECT_TABLESPACE:
2119                         string_append_char(str, "TABLESPACE \"");
2120                         string_append_char(str, node->subname);
2121                         string_append_char(str, "\" RENAME TO \"");
2122                         string_append_char(str, node->newname);
2123                         string_append_char(str, "\"");
2124                         break;
2125
2126                 default:
2127                         break;
2128         }
2129 }
2130
2131 static void
2132 _outOptRoleList(String *str, List *options)
2133 {
2134         ListCell *lc;
2135         
2136         foreach (lc, options)
2137         {
2138                 DefElem *elem = lfirst(lc);
2139                 Value *value = (Value *) elem->arg;
2140
2141                 if (strcmp(elem->defname, "password") == 0)
2142                 {
2143                         if (value == NULL)
2144                                 string_append_char(str, " PASSWORD NULL");
2145                         else
2146                         {
2147                                 string_append_char(str, " PASSWORD '");
2148                                 string_append_char(str, value->val.str);
2149                                 string_append_char(str, "'");
2150                         }
2151                 }
2152                 else if (strcmp(elem->defname, "encryptedPassword") == 0)
2153                 {
2154                         string_append_char(str, " ENCRYPTED PASSWORD '");
2155                         string_append_char(str, value->val.str);
2156                         string_append_char(str, "'");
2157                 }
2158                 else if (strcmp(elem->defname, "unencryptedPassword") == 0)
2159                 {
2160                         string_append_char(str, " UNENCRYPTED PASSWORD '");
2161                         string_append_char(str, value->val.str);
2162                         string_append_char(str, "'");
2163                 }
2164                 else if (strcmp(elem->defname, "superuser") == 0)
2165                 {
2166                         if (value->val.ival == TRUE)
2167                                 string_append_char(str, " SUPERUSER");
2168                         else
2169                                 string_append_char(str, " NOSUPERUSER");
2170                 }
2171                 else if (strcmp(elem->defname, "inherit") == 0)
2172                 {
2173                         if (value->val.ival == TRUE)
2174                                 string_append_char(str, " INHERIT");
2175                         else
2176                                 string_append_char(str, " NOINHERIT");
2177                 }
2178                 else if (strcmp(elem->defname, "createdb") == 0)
2179                 {
2180                         if (value->val.ival == TRUE)
2181                                 string_append_char(str, " CREATEDB");
2182                         else
2183                                 string_append_char(str, " NOCREATEDB");
2184                 }
2185                 else if (strcmp(elem->defname, "createrole") == 0)
2186                 {
2187                         if (value->val.ival == TRUE)
2188                                 string_append_char(str, " CREATEROLE");
2189                         else
2190                                 string_append_char(str, " NOCREATEROLE");
2191                 }
2192                 else if (strcmp(elem->defname, "canlogin") == 0)
2193                 {
2194                         if (value->val.ival == TRUE)
2195                                 string_append_char(str, " LOGIN");
2196                         else
2197                                 string_append_char(str, " NOLOGIN");
2198                 }
2199                 else if (strcmp(elem->defname, "connectionlimit") == 0)
2200                 {
2201                         char buf[16];
2202                         
2203                         string_append_char(str, " CONNECTION LIMIT ");
2204                         snprintf(buf, 16, "%ld", value->val.ival);
2205                         string_append_char(str, buf);
2206                 }
2207                 else if (strcmp(elem->defname, "validUntil") == 0)
2208                 {
2209                         string_append_char(str, " VALID UNTIL '");
2210                         string_append_char(str, value->val.str);
2211                         string_append_char(str, "'");
2212                 }
2213                 else if (strcmp(elem->defname, "rolemembers") == 0)
2214                 {
2215                         string_append_char(str, " ROLE ");
2216                         _outIdList(str, (List *) elem->arg);
2217                 }
2218                 else if (strcmp(elem->defname, "sysid") == 0)
2219                 {
2220                         char buf[16];
2221                         
2222                         string_append_char(str, " SYSID ");
2223                         snprintf(buf, 16, "%ld", value->val.ival);
2224                         string_append_char(str, buf);
2225                 }
2226                 else if (strcmp(elem->defname, "adminmembers") == 0)
2227                 {
2228                         string_append_char(str, " ADMIN ");
2229                         _outIdList(str, (List *) elem->arg);
2230                 }
2231                 else if (strcmp(elem->defname, "addroleto") == 0)
2232                 {
2233                         string_append_char(str, " IN ROLE ");
2234                         _outIdList(str, (List *) elem->arg);
2235                 }
2236         }
2237 }
2238
2239 static void
2240 _outCreateRoleStmt(String *str, CreateRoleStmt *node)
2241 {
2242         string_append_char(str, "CREATE ");
2243         switch (node->stmt_type)
2244         {
2245                 case ROLESTMT_ROLE:
2246                         string_append_char(str, "ROLE \"");
2247                         break;
2248
2249                 case ROLESTMT_USER:
2250                         string_append_char(str, "USER \"");
2251                         break;
2252
2253                 case ROLESTMT_GROUP:
2254                         string_append_char(str, "GROUP \"");
2255                         break;
2256         }
2257         string_append_char(str, node->role);
2258         string_append_char(str, "\"");
2259
2260         _outOptRoleList(str, node->options);
2261 }
2262
2263 static void
2264 _outAlterRoleStmt(String *str, AlterRoleStmt *node)
2265 {
2266         string_append_char(str, "ALTER ROLE \"");
2267         string_append_char(str, node->role);
2268         string_append_char(str, "\"");
2269
2270         if (node->options)
2271                 _outOptRoleList(str, node->options);
2272 }
2273
2274 static void
2275 _outAlterRoleSetStmt(String *str, AlterRoleSetStmt *node)
2276 {
2277         string_append_char(str, "ALTER ROLE \"");
2278         string_append_char(str, node->role);
2279         string_append_char(str, "\" ");
2280
2281         if (node->setstmt)
2282         {
2283                 _outNode(str, node->setstmt);
2284         }
2285 }
2286
2287
2288 static void
2289 _outSetTransactionModeList(String *str, List *list)
2290 {
2291         ListCell *lc;
2292         char comma = 0;
2293
2294         foreach (lc, list)
2295         {
2296                 DefElem *elem = lfirst(lc);
2297
2298                 if (comma == 0)
2299                         comma = 1;
2300                 else
2301                         string_append_char(str, ",");
2302
2303                 if (strcmp(elem->defname, "transaction_isolation") == 0)
2304                 {
2305                         A_Const *v = (A_Const *) elem->arg;
2306                         string_append_char(str, " ISOLATION LEVEL ");
2307                         string_append_char(str, v->val.val.str);
2308                 }
2309                 else if (strcmp(elem->defname, "transaction_read_only") == 0)
2310                 {
2311                         A_Const *n = (A_Const *) elem->arg;
2312                         if (n->val.val.ival == TRUE)
2313                                 string_append_char(str, "READ ONLY ");
2314                         else
2315                                 string_append_char(str, "READ WRITE ");
2316                 }
2317         }
2318 }
2319
2320
2321 static void
2322 _outSetRest(String *str, VariableSetStmt *node)
2323 {
2324         if (strcmp(node->name, "timezone") == 0)
2325         {
2326                 string_append_char(str, "TIME ZONE ");
2327                 if (node->kind != VAR_RESET)
2328                         _outNode(str, node->args);
2329         }
2330         else if (strcmp(node->name, "TRANSACTION") == 0)
2331         {
2332                 string_append_char(str, "TRANSACTION ");
2333                 _outSetTransactionModeList(str, node->args);
2334         }
2335         else if (strcmp(node->name, "SESSION CHARACTERISTICS") == 0)
2336         {
2337                 string_append_char(str, "SESSION CHARACTERISTICS AS TRANSACTION ");
2338                 _outSetTransactionModeList(str, node->args);
2339         }
2340         else if (strcmp(node->name, "role") == 0)
2341         {
2342                 string_append_char(str, "ROLE ");
2343                 if (node->kind != VAR_RESET)
2344                         _outNode(str, node->args);
2345         }
2346         else if (strcmp(node->name, "session_authorization") == 0)
2347         {
2348                 string_append_char(str, "SESSION AUTHORIZATION ");
2349                 if (node->args == NIL && node->kind != VAR_RESET)
2350                         string_append_char(str, "DEFAULT");
2351                 else
2352                         _outNode(str, node->args);
2353         }
2354         else if (strcmp(node->name, "transaction_isolation") == 0)
2355         {
2356                 string_append_char(str, "TRANSACTION ISOLATION LEVEL");
2357                 if (node->kind != VAR_RESET)
2358                         _outSetTransactionModeList(str, node->args);
2359         }
2360         else if (strcmp(node->name, "xmloption") == 0)
2361         {
2362                 A_Const *v = linitial(node->args);
2363                 string_append_char(str, "XML OPTOIN ");
2364                 string_append_char(str, v->val.val.str);
2365         }
2366         else
2367         {
2368                 string_append_char(str, node->name);
2369                 if (node->kind != VAR_RESET)
2370                 {
2371                         if (node->kind == VAR_SET_CURRENT)
2372                         {
2373                                 string_append_char(str, " FROM CURRENT");
2374                         }
2375                         else
2376                         {
2377                                 string_append_char(str, " TO ");
2378                                 if (node->args == NULL)
2379                                 {
2380                                         string_append_char(str, "DEFAULT");
2381                                 }
2382                                 else
2383                                         _outNode(str, node->args);
2384                         }
2385                 }
2386         }
2387 }
2388
2389 static void
2390 _outDropRoleStmt(String *str, DropRoleStmt *node)
2391 {
2392         string_append_char(str, "DROP ROLE ");
2393         if (node->missing_ok == TRUE)
2394                 string_append_char(str, "IF EXISTS ");
2395         _outIdList(str, node->roles);
2396 }
2397
2398 static void
2399 _outCreateSchemaStmt(String *str, CreateSchemaStmt *node)
2400 {
2401         string_append_char(str, "CREATE SCHEMA \"");
2402         string_append_char(str, node->schemaname);
2403         string_append_char(str, "\"");
2404         if (node->authid)
2405         {
2406                 string_append_char(str, "AUTHORIZATION \"");
2407                 string_append_char(str, node->authid);
2408                 string_append_char(str, "\" ");
2409         }
2410         _outNode(str, node->schemaElts);
2411 }
2412
2413 static void
2414 _outVariableSetStmt(String *str, VariableSetStmt *node)
2415 {
2416         if (node->kind == VAR_RESET_ALL)
2417         {
2418                 string_append_char(str, "RESET ALL");
2419                 return;
2420         }
2421
2422         if (node->kind == VAR_RESET)
2423                 string_append_char(str, "RESET ");
2424         else
2425                 string_append_char(str, "SET ");
2426
2427         if (node->is_local)
2428                 string_append_char(str, "LOCAL ");
2429         
2430         _outSetRest(str, node);
2431 }
2432
2433 static void
2434 _outVariableShowStmt(String *str, VariableShowStmt *node)
2435 {
2436         if (strcmp(node->name, "timezone") == 0)
2437                 string_append_char(str, "SHOW TIME ZONE");
2438         else if (strcmp(node->name, "transaction_isolation") == 0)
2439                 string_append_char(str, "SHOW TRANSACTION ISOLATION LEVEL");
2440         else if (strcmp(node->name, "session_authorization") == 0)
2441                 string_append_char(str, "SHOW SESSION AUTHORIZATION");
2442         else if (strcmp(node->name, "all") == 0)
2443                 string_append_char(str, "SHOW ALL");
2444         else
2445         {
2446                 string_append_char(str, "SHOW ");
2447                 string_append_char(str, node->name);
2448         }
2449 }
2450
2451 static void
2452 _outConstraintsSetStmt(String *str, ConstraintsSetStmt *node)
2453 {
2454         string_append_char(str, "SET CONSTRAINTS ");
2455
2456         if (node->constraints == NIL)
2457                 string_append_char(str, "ALL");
2458         else
2459                 _outNode(str, node->constraints);
2460
2461         string_append_char(str, node->deferred == TRUE ? " DEFERRED" : " IMMEDIATE");
2462 }
2463
2464 static void
2465 _outAlterTableCmd(String *str, AlterTableCmd *node)
2466 {
2467         char buf[16];
2468         
2469         switch (node->subtype)
2470         {
2471                 case AT_AddColumn:
2472                         string_append_char(str, "ADD ");
2473                         _outNode(str, node->def);
2474                         break;
2475
2476                 case AT_ColumnDefault:
2477                         string_append_char(str, "ALTER \"");
2478                         string_append_char(str, node->name);
2479                         string_append_char(str, "\" ");
2480                         if (node->def == NULL)
2481                                 string_append_char(str, "DROP DEFAULT");
2482                         else
2483                         {
2484                                 string_append_char(str, "SET DEFAULT ");
2485                                 _outNode(str, node->def);
2486                         }
2487                         break;
2488
2489                 case AT_DropNotNull:
2490                         string_append_char(str, "ALTER \"");
2491                         string_append_char(str, node->name);
2492                         string_append_char(str, "\" DROP NOT NULL");
2493                         break;
2494
2495                 case AT_SetNotNull:
2496                         string_append_char(str, "ALTER \"");
2497                         string_append_char(str, node->name);
2498                         string_append_char(str, "\" SET NOT NULL");
2499                         break;
2500
2501                 case AT_SetStatistics:
2502                         string_append_char(str, "ALTER \"");
2503                         string_append_char(str, node->name);
2504                         string_append_char(str, "\" SET STATISTICS ");
2505                         snprintf(buf, 16, "%ld", ((Value *) node->def)->val.ival);
2506                         string_append_char(str, buf);
2507                         break;
2508
2509                 case AT_SetStorage:
2510                         string_append_char(str, "ALTER \"");
2511                         string_append_char(str, node->name);
2512                         string_append_char(str, "\" SET STORAGE ");
2513                         string_append_char(str, ((Value *) node->def)->val.str);
2514                         break;
2515
2516                 case AT_DropColumn:
2517                         string_append_char(str, "DROP \"");
2518                         string_append_char(str, node->name);
2519                         string_append_char(str, "\" ");
2520                         if (node->behavior == DROP_CASCADE)
2521                                 string_append_char(str, "CASCADE");
2522                         break;
2523
2524                 case AT_AlterColumnType:
2525                         string_append_char(str, "ALTER \"");
2526                         string_append_char(str, node->name);
2527                         string_append_char(str, "\" TYPE ");
2528                         _outNode(str, node->def);
2529                         if (node->transform)
2530                         {
2531                                 string_append_char(str, " USING ");
2532                                 _outNode(str, node->transform);
2533                         }
2534                         break;
2535
2536                 case AT_AddConstraint:
2537                         string_append_char(str, "ADD ");
2538                         _outNode(str, node->def);
2539                         break;
2540
2541                 case AT_DropConstraint:
2542                         string_append_char(str, "DROP CONSTRAINT \"");
2543                         string_append_char(str, node->name);
2544                         string_append_char(str, "\"");
2545                         if (node->behavior == DROP_CASCADE)
2546                                 string_append_char(str, " CASCADE");
2547                         break;
2548
2549                 case AT_DropOids:
2550                         string_append_char(str, "SET WITHOUT OIDS");
2551                         break;
2552
2553                 case AT_ClusterOn:
2554                         string_append_char(str, "CLUSTER ON \"");
2555                         string_append_char(str, node->name);
2556                         string_append_char(str, "\"");
2557                         break;
2558
2559                 case AT_DropCluster:
2560                         string_append_char(str, "SET WITHOUT CLUSTER");
2561                         break;
2562
2563                 case AT_EnableTrig:
2564                         string_append_char(str, "ENABLE TRIGGER \"");
2565                         string_append_char(str, node->name);
2566                         string_append_char(str, "\"");
2567                         break;
2568
2569                 case AT_EnableAlwaysTrig:
2570                         /* not implemented */
2571                         break;
2572
2573                 case AT_EnableReplicaTrig:
2574                         /* not implemented */
2575                         break;
2576
2577                 case AT_EnableTrigAll:
2578                         string_append_char(str, "ENABLE TRIGGER ALL");
2579                         break;
2580
2581                 case AT_EnableTrigUser:
2582                         string_append_char(str, "ENABLE TRIGGER USER");
2583                         break;
2584
2585                 case AT_DisableTrig:
2586                         string_append_char(str, "DISABLE TRIGGER \"");
2587                         string_append_char(str, node->name);
2588                         string_append_char(str, "\"");
2589                         break;
2590
2591                 case AT_DisableTrigAll:
2592                         string_append_char(str, "DISABLE TRIGGER ALL");
2593                         break;
2594
2595                 case AT_DisableTrigUser:
2596                         string_append_char(str, "DISABLE TRIGGER USER");
2597                         break;
2598
2599                 case AT_EnableRule:
2600                         /* not implemented */
2601                         break;
2602
2603                 case AT_EnableReplicaRule:
2604                         /* not implemented */
2605                         break;
2606
2607                 case AT_EnableAlwaysRule:
2608                         /* not implemented */
2609                         break;
2610
2611                 case AT_DisableRule:
2612                         /* not implemented */
2613                         break;
2614
2615                 case AT_AddInherit:
2616                         /* not implemented */
2617                         break;
2618
2619                 case AT_ChangeOwner:
2620                         string_append_char(str, "OWNER TO \"");
2621                         string_append_char(str, node->name);
2622                         string_append_char(str, "\"");
2623                         break;
2624
2625                 case AT_SetTableSpace:
2626                         string_append_char(str, "SET TABLESPACE \"");
2627                         string_append_char(str, node->name);
2628                         string_append_char(str, "\"");
2629                         break;
2630
2631                 case AT_SetRelOptions:
2632                         /* not implemented */
2633                         break;
2634
2635                 case AT_ResetRelOptions:
2636                         /* not implemented */
2637                         break;
2638
2639                 default:
2640                         break;
2641         }
2642 }
2643
2644 static void
2645 _outAlterTableStmt(String *str, AlterTableStmt *node)
2646 {
2647         if (node->relkind == OBJECT_TABLE)
2648                 string_append_char(str, "ALTER TABLE ");
2649         else
2650                 string_append_char(str, "ALTER INDEX ");
2651
2652         _outNode(str, node->relation);
2653         string_append_char(str, " ");
2654         _outNode(str, node->cmds);
2655 }
2656
2657 static void
2658 _outOptSeqList(String *str, List *options)
2659 {
2660         ListCell *lc;
2661
2662         foreach (lc, options)
2663         {
2664                 DefElem *e = lfirst(lc);
2665                 Value *v = (Value *)e->arg;
2666                 char buf[16];
2667
2668                 if (strcmp(e->defname, "cycle") == 0)
2669                 {
2670                         if (v->val.ival == TRUE)
2671                                 string_append_char(str, " CYCLE");
2672                         else
2673                                 string_append_char(str, " NO CYCLE");
2674                 }
2675                 else if (strcmp(e->defname, "minvalue") == 0 && !v)
2676                         string_append_char(str, " NO MINVALUE");
2677                 else if (strcmp(e->defname, "maxvalue") == 0 && !v)
2678                         string_append_char(str, " NO MAXVALUE");
2679                 else if (strcmp(e->defname, "owned_by") == 0)
2680                 {
2681                         string_append_char(str, " OWNED BY ");
2682                         _outIdList(str, (List *)e->arg);
2683                 }
2684                 else
2685                 {
2686                         if (strcmp(e->defname, "cache") == 0)
2687                                 string_append_char(str, " CACHE ");
2688                         else if (strcmp(e->defname, "increment") == 0)
2689                                 string_append_char(str, " INCREMENT ");
2690                         else if (strcmp(e->defname, "maxvalue") == 0 && v)
2691                                 string_append_char(str, " MAXVALUE ");
2692                         else if (strcmp(e->defname, "minvalue") == 0 && v)
2693                                 string_append_char(str, " MINVALUE ");
2694                         else if (strcmp(e->defname, "start") == 0)
2695                                 string_append_char(str, " START ");
2696                         else if (strcmp(e->defname, "restart") == 0)
2697                                 string_append_char(str, " RESTART ");
2698                         
2699                         if (IsA(e->arg, String))
2700                                 string_append_char(str, v->val.str);
2701                         else
2702                         {
2703                                 snprintf(buf, 16, "%ld", v->val.ival);
2704                                 string_append_char(str, buf);
2705                         }
2706                 }
2707         }
2708 }
2709
2710 static void
2711 _outCreateSeqStmt(String *str, CreateSeqStmt *node)
2712 {
2713         string_append_char(str, "CREATE ");
2714         if (node->sequence->istemp)
2715                 string_append_char(str, "TEMP ");
2716         string_append_char(str, "SEQUENCE ");
2717         _outNode(str, node->sequence);
2718
2719         _outOptSeqList(str, node->options);
2720 }
2721
2722 static void
2723 _outAlterSeqStmt(String *str, AlterSeqStmt *node)
2724 {
2725         string_append_char(str, "ALTER SEQUENCE ");
2726         _outNode(str, node->sequence);
2727         _outOptSeqList(str, node->options);
2728 }
2729
2730 static void
2731 _outCreatePLangStmt(String *str, CreatePLangStmt *node)
2732 {
2733         string_append_char(str, "CREATE ");
2734         if (node->pltrusted == true)
2735                 string_append_char(str, "TRUSTED ");
2736         string_append_char(str, "LANGUAGE \"");
2737         string_append_char(str, node->plname);
2738         string_append_char(str, "\"");
2739
2740         if (node->plhandler != NIL)
2741         {
2742                 ListCell *lc;
2743                 char dot = 0;
2744
2745                 string_append_char(str, " HANDLER ");
2746                 foreach (lc, node->plhandler)
2747                 {
2748                         Value *v = lfirst(lc);
2749                         
2750                         if (dot == 0)
2751                                 dot = 1;
2752                         else
2753                                 string_append_char(str, ".");
2754
2755                         string_append_char(str, "\"");
2756                         string_append_char(str, v->val.str);
2757                         string_append_char(str, "\"");
2758                 }
2759         }
2760
2761         if (node->plvalidator != NIL)
2762         {
2763                 ListCell *lc;
2764                 char dot = 0;
2765
2766                 string_append_char(str, " VALIDATOR ");
2767                 foreach (lc, node->plvalidator)
2768                 {
2769                         Value *v = lfirst(lc);
2770                         
2771                         if (dot == 0)
2772                                 dot = 1;
2773                         else
2774                                 string_append_char(str, ".");
2775
2776                         string_append_char(str, "\"");
2777                         string_append_char(str, v->val.str);
2778                         string_append_char(str, "\"");
2779                 }
2780         }
2781 }
2782
2783 static void
2784 _outDropPLangStmt(String *str, DropPLangStmt *node)
2785 {
2786         string_append_char(str, "DROP LANGUAGE \"");
2787         string_append_char(str, node->plname);
2788         string_append_char(str, "\"");
2789         if (node->behavior == DROP_CASCADE)
2790                 string_append_char(str, " CASCADE");
2791 }
2792
2793 static void
2794 _outCreateTableSpaceStmt(String *str, CreateTableSpaceStmt *node)
2795 {
2796         string_append_char(str, "CREATE TABLESPACE \"");
2797         string_append_char(str, node->tablespacename);
2798         string_append_char(str, "\" ");
2799
2800         if (node->owner)
2801         {
2802                 string_append_char(str, "OWNER \"");
2803                 string_append_char(str, node->owner);
2804                 string_append_char(str, "\" ");
2805         }
2806
2807         string_append_char(str, "LOCATION '");
2808         string_append_char(str, node->location);
2809         string_append_char(str, "'");
2810 }
2811
2812 static void
2813 _outDropTableSpaceStmt(String *str, DropTableSpaceStmt *node)
2814 {
2815         string_append_char(str, "DROP TABLESPACE \"");
2816         string_append_char(str, node->tablespacename);
2817         string_append_char(str, "\"");
2818 }
2819
2820 static void
2821 _outFuncName(String *str, List *func_name)
2822 {
2823         ListCell *lc;
2824         Value *v;
2825         char dot = 0;
2826
2827         if (func_name == NULL)
2828                 return;
2829
2830         foreach (lc, func_name)
2831         {
2832                 v = (Value *) lfirst(lc);
2833
2834                 if (dot == 0)
2835                         dot = 1;
2836                 else
2837                         string_append_char(str, ".");
2838
2839                 if (IsA(v, String))
2840                 {
2841                         string_append_char(str, "\"");
2842                         string_append_char(str, v->val.str);
2843                         string_append_char(str, "\"");
2844                 }
2845                 else
2846                 {
2847                         _outNode(str, v);
2848                 }
2849         }
2850 }
2851
2852 static void
2853 _outCreateTrigStmt(String *str, CreateTrigStmt *node)
2854 {
2855         int i, len;
2856
2857         if (node->isconstraint == TRUE)
2858                 string_append_char(str, "CREATE CONSTRAINT TRIGGER \"");
2859         else
2860                 string_append_char(str, "CREATE TRIGGER \"");
2861         string_append_char(str, node->trigname);
2862         string_append_char(str, "\" ");
2863
2864         if (node->before == TRUE)
2865                 string_append_char(str, "BEFORE ");
2866         else
2867                 string_append_char(str, "AFTER ");
2868
2869         len = strlen(node->actions);
2870         for (i = 0; i < len; i++)
2871         {
2872                 if (i)
2873                         string_append_char(str, "OR ");
2874                 
2875                 if (node->actions[i] == 'i')
2876                         string_append_char(str, "INSERT ");
2877                 else if (node->actions[i] == 'd')
2878                         string_append_char(str, "DELETE ");
2879                 else
2880                         string_append_char(str, "UPDATE ");
2881         }
2882
2883         string_append_char(str, "ON ");
2884         _outNode(str, node->relation);
2885
2886         if (node->constrrel)
2887         {
2888                 string_append_char(str, " FROM ");
2889                 _outNode(str, node->constrrel);
2890         }
2891
2892         if (node->deferrable)
2893                 string_append_char(str, " DEFERRABLE");
2894         if (node->initdeferred)
2895                 string_append_char(str, " INITIALLY DEFERRED");
2896
2897         if (node->row == TRUE)
2898                 string_append_char(str, " FOR EACH ROW ");
2899         else
2900                 string_append_char(str, " FOR EACH STATEMENT ");
2901
2902         string_append_char(str, "EXECUTE PROCEDURE ");
2903
2904         _outFuncName(str, node->funcname);
2905         string_append_char(str, "(");
2906         _outNode(str, node->args);
2907         string_append_char(str, ")");
2908 }
2909
2910 static void
2911 _outDropPropertyStmt(String *str, DropPropertyStmt *node)
2912 {
2913         switch (node->removeType)
2914         {
2915                 case OBJECT_TRIGGER:
2916                         string_append_char(str, "DROP TRIGGER \"");
2917                         string_append_char(str, node->property);
2918                         string_append_char(str, "\" ON ");
2919                         _outNode(str, node->relation);
2920                         if (node->behavior == DROP_CASCADE)
2921                                 string_append_char(str, " CASCADE");
2922                         break;
2923
2924                 case OBJECT_RULE:
2925                         string_append_char(str, "DROP RULE \"");
2926                         string_append_char(str, node->property);
2927                         string_append_char(str, "\" ON ");
2928                         _outNode(str, node->relation);
2929                         if (node->behavior == DROP_CASCADE)
2930                                 string_append_char(str, " CASCADE");
2931                         break;
2932
2933                 default:
2934                         break;
2935         }
2936 }
2937
2938 static void
2939 _outDefinition(String *str, List *definition)
2940 {
2941         ListCell *lc;
2942         char comma = 0;
2943
2944         if (definition == NIL)
2945                 return;
2946         
2947         string_append_char(str, "(");
2948         foreach (lc, definition)
2949         {
2950                 DefElem *e = lfirst(lc);
2951
2952                 if (comma == 0)
2953                         comma = 1;
2954                 else
2955                         string_append_char(str, ", ");
2956
2957                 string_append_char(str, "\"");
2958                 string_append_char(str, e->defname);
2959                 string_append_char(str, "\"");
2960
2961                 if (e->arg)
2962                 {
2963                         string_append_char(str, "=");
2964                         _outNode(str, e->arg);
2965                 }
2966         }
2967         string_append_char(str, ")");
2968 }
2969
2970 static void
2971 _outDefineStmt(String *str, DefineStmt *node)
2972 {
2973         ListCell *lc;
2974         char dot = 0;
2975
2976         switch (node->kind)
2977         {
2978                 case OBJECT_AGGREGATE:
2979                         string_append_char(str, "CREATE AGGREGATE ");
2980                         _outFuncName(str, node->defnames);
2981                         string_append_char(str, " ");
2982                         _outDefinition(str, node->definition);
2983                         break;
2984
2985                 case OBJECT_OPERATOR:
2986                         string_append_char(str, "CREATE OPERATOR ");
2987                         
2988                         foreach (lc, node->defnames)
2989                         {
2990                                 Value *v = lfirst(lc);
2991                                 
2992                                 if (dot == 0)
2993                                         dot = 1;
2994                                 else
2995                                         string_append_char(str, ".");
2996
2997                                 string_append_char(str, v->val.str);
2998                         }
2999                         
3000                         string_append_char(str, " ");
3001                         _outDefinition(str, node->definition);
3002                         break;
3003
3004                 case OBJECT_TYPE:
3005                         string_append_char(str, "CREATE TYPE");
3006                         _outFuncName(str, node->defnames);
3007                         string_append_char(str, " ");
3008                         _outDefinition(str, node->definition);
3009                         break;
3010
3011                 case OBJECT_TSPARSER:
3012                         string_append_char(str, "CREATE TEXT SEARCH PARSER ");
3013                         _outIdList(str, node->defnames);
3014                         _outDefinition(str, node->definition);
3015                         break;
3016
3017                 case OBJECT_TSDICTIONARY:
3018                         string_append_char(str, "CREATE TEXT SEARCH DICTIONARY ");
3019                         _outIdList(str, node->defnames);
3020                         _outDefinition(str, node->definition);
3021                         break;
3022
3023                 case OBJECT_TSTEMPLATE:
3024                         string_append_char(str, "CREATE TEXT SEARCH TEMPLATE ");
3025                         _outIdList(str, node->defnames);
3026                         _outDefinition(str, node->definition);
3027                         break;
3028
3029                 case OBJECT_TSCONFIGURATION:
3030                         string_append_char(str, "CREATE TEXT SEARCH CONFIGURATION ");
3031                         _outIdList(str, node->defnames);
3032                         _outDefinition(str, node->definition);
3033                         break;
3034                         
3035                 default:
3036                         break;
3037         }
3038 }
3039
3040 static void
3041 _outOperatorName(String *str, List *list)
3042 {
3043         char dot = 0;
3044         ListCell *lc;
3045
3046         foreach (lc, list)
3047         {
3048                 Value *v = lfirst(lc);
3049                 
3050                 if (dot == 0)
3051                         dot = 1;
3052                 else
3053                         string_append_char(str, ".");
3054                 
3055                 string_append_char(str, v->val.str);
3056         }
3057 }
3058
3059 static void
3060 _outCreateOpClassItem(String *str, CreateOpClassItem *node)
3061 {
3062         char buf[16];
3063         
3064         switch (node->itemtype)
3065         {
3066                 case OPCLASS_ITEM_OPERATOR:
3067                         string_append_char(str, "OPERATOR ");
3068                         snprintf(buf, 16, "%d", node->number);
3069                         string_append_char(str, buf);
3070                         string_append_char(str, " ");
3071                         _outOperatorName(str, node->name);
3072
3073                         if (node->args != NIL)
3074                         {
3075                                 string_append_char(str, "(");
3076                                 _outNode(str, node->args);
3077                                 string_append_char(str, ")");
3078                         }
3079                         if (node->recheck == TRUE)
3080                                 string_append_char(str, " RECHECK");
3081                         break;
3082
3083                 case OPCLASS_ITEM_FUNCTION:
3084                         string_append_char(str, "FUNCTION ");
3085                         snprintf(buf, 16, "%d", node->number);
3086                         string_append_char(str, buf);
3087                         string_append_char(str, " ");
3088                         _outFuncName(str, node->name);
3089                         string_append_char(str, "(");
3090                         _outNode(str, node->args);
3091                         string_append_char(str, ")");
3092                         break;
3093
3094                 case OPCLASS_ITEM_STORAGETYPE:
3095                         string_append_char(str, "STORAGE ");
3096                         _outNode(str, node->storedtype);
3097                         break;
3098
3099                 default:
3100                         break;
3101         }
3102                         
3103 }
3104
3105 static void
3106 _outCreateOpClassStmt(String *str, CreateOpClassStmt *node)
3107 {
3108         string_append_char(str, "CREATE OPERATOR CLASS ");
3109         _outFuncName(str, node->opclassname);
3110
3111         if (node->isDefault == TRUE)
3112                 string_append_char(str, " DEFAULT");
3113
3114         string_append_char(str, " FOR TYPE ");
3115         _outNode(str, node->datatype);
3116         string_append_char(str, " USING ");
3117         string_append_char(str, node->amname);
3118         string_append_char(str, " AS ");
3119         _outNode(str, node->items);
3120 }
3121
3122 static void
3123 _outRemoveOpClassStmt(String *str, RemoveOpClassStmt *node)
3124 {
3125         string_append_char(str, "DROP OPERATOR CLASS ");
3126         _outFuncName(str, node->opclassname);
3127         string_append_char(str, " USING ");
3128         string_append_char(str, node->amname);
3129         if (node->behavior == DROP_CASCADE)
3130                 string_append_char(str, " CASCADE");
3131 }
3132
3133 static void
3134 _outDropStmt(String *str, DropStmt *node)
3135 {
3136         ListCell *lc;
3137         char comma = 0;
3138         
3139         string_append_char(str, "DROP ");
3140         switch (node->removeType)
3141         {
3142                 case OBJECT_TABLE:
3143                         string_append_char(str, "TABLE ");
3144                         break;
3145
3146                 case OBJECT_SEQUENCE:
3147                         string_append_char(str, "SEQUENCE ");
3148                         break;
3149
3150                 case OBJECT_VIEW:
3151                         string_append_char(str, "VIEW ");
3152                         break;
3153
3154                 case OBJECT_INDEX:
3155                         string_append_char(str, "INDEX ");
3156                         break;
3157
3158                 case OBJECT_TYPE:
3159                         string_append_char(str, "TYPE ");
3160                         break;
3161
3162                 case OBJECT_DOMAIN:
3163                         string_append_char(str, "DOMAIN ");
3164                         break;
3165
3166                 case OBJECT_CONVERSION:
3167                         string_append_char(str, "CONVERSION ");
3168                         break;
3169
3170                 case OBJECT_SCHEMA:
3171                         string_append_char(str, "SCHEMA ");
3172                         break;
3173
3174                 default:
3175                         break;
3176         }
3177
3178         foreach (lc, node->objects)
3179         {
3180                 if (comma == 0)
3181                         comma = 1;
3182                 else
3183                         string_append_char(str, ", ");
3184                 _outFuncName(str, lfirst(lc));
3185         }
3186
3187         if (node->behavior == DROP_CASCADE)
3188                 string_append_char(str, " CASCADE");
3189 }
3190
3191 static void
3192 _outFetchStmt(String *str, FetchStmt *node)
3193 {
3194         char buf[16];
3195
3196         snprintf(buf, 16, "%ld", node->howMany);
3197
3198         if (node->ismove == TRUE)
3199                 string_append_char(str, "MOVE ");
3200         else
3201                 string_append_char(str, "FETCH ");
3202
3203         switch (node->direction)
3204         {
3205                 case FETCH_FORWARD:
3206                         string_append_char(str, "FORWARD ");
3207                         if (node->howMany == FETCH_ALL)
3208                                 string_append_char(str, "ALL ");
3209                         else
3210                         {
3211                                 string_append_char(str, buf);
3212                                 string_append_char(str, " ");
3213                         }
3214                         break;
3215
3216                 case FETCH_BACKWARD:
3217                         string_append_char(str, "BACKWARD ");
3218                         if (node->howMany == FETCH_ALL)
3219                                 string_append_char(str, "ALL ");
3220                         else
3221                         {
3222                                 string_append_char(str, buf);
3223                                 string_append_char(str, " ");
3224                         }
3225                         break;
3226
3227                 case FETCH_ABSOLUTE:
3228                         if (node->howMany == 1)
3229                                 string_append_char(str, "FIRST ");
3230                         else if (node->howMany == -1)
3231                                 string_append_char(str, "LAST ");
3232                         else
3233                         {
3234                                 string_append_char(str, "ABSOLUTE ");
3235                                 string_append_char(str, buf);
3236                                 string_append_char(str, " ");
3237                         }
3238                         break;
3239
3240                 case FETCH_RELATIVE:
3241                         string_append_char(str, "RELATIVE ");
3242                         string_append_char(str, buf);
3243                         string_append_char(str, " ");
3244                         break;
3245         }
3246
3247         string_append_char(str, "IN \"");
3248         string_append_char(str, node->portalname);
3249         string_append_char(str, "\"");
3250 }
3251
3252 static void
3253 _outPrivilegeList(String *str, List *list)
3254 {
3255         ListCell *lc;
3256         char comma = 0;
3257         
3258         if (list == NIL)
3259                 string_append_char(str, "ALL");
3260         else
3261         {
3262                 foreach (lc, list)
3263                 {
3264                         Value *v = lfirst(lc);
3265                         
3266                         if (comma == 0)
3267                                 comma = 1;
3268                         else
3269                                 string_append_char(str, ", ");
3270
3271                         string_append_char(str, v->val.str);
3272                 }
3273         }
3274 }
3275
3276 static void
3277 _outFunctionParameter(String *str, FunctionParameter *node)
3278 {
3279         switch (node->mode)
3280         {
3281                 case FUNC_PARAM_OUT:
3282                         string_append_char(str, "OUT ");
3283                         break;
3284
3285                 case FUNC_PARAM_INOUT:
3286                         string_append_char(str, "INOUT ");
3287                         break;
3288
3289                 default:
3290                         break;
3291         }
3292
3293         /* function name */
3294         if (node->name)
3295         {
3296                 string_append_char(str, "\"");
3297                 string_append_char(str, node->name);
3298                 string_append_char(str, "\" ");
3299         }
3300
3301         _outNode(str, node->argType);
3302 }
3303
3304 static void
3305 _outFuncWithArgs(String *str, FuncWithArgs *node)
3306 {
3307         _outFuncName(str, node->funcname);
3308         string_append_char(str, "(");
3309         _outNode(str, node->funcargs);
3310         string_append_char(str, ")");
3311 }
3312
3313 static void
3314 _outPrivTarget(String *str, PrivTarget *node)
3315 {
3316         switch (node->objtype)
3317         {
3318                 case ACL_OBJECT_RELATION:
3319                         _outNode(str, node->objs);
3320                         break;
3321
3322                 case ACL_OBJECT_SEQUENCE:
3323                         string_append_char(str, "SEQUENCE ");
3324                         _outNode(str, node->objs);
3325                         break;
3326
3327                 case ACL_OBJECT_FUNCTION:
3328                         string_append_char(str, "FUNCTION ");
3329                         _outNode(str, node->objs);
3330                         break;
3331
3332                 case ACL_OBJECT_DATABASE:
3333                         string_append_char(str, "DATABASE ");
3334                         _outIdList(str, node->objs);
3335                         break;
3336
3337                 case ACL_OBJECT_LANGUAGE:
3338                         string_append_char(str, "LANGUAGE ");
3339                         _outIdList(str, node->objs);
3340                         break;
3341
3342                 case ACL_OBJECT_NAMESPACE:
3343                         string_append_char(str, "SCHEMA ");
3344                         _outIdList(str, node->objs);
3345                         break;
3346
3347                 case ACL_OBJECT_TABLESPACE:
3348                         string_append_char(str, "TABLESPACE ");
3349                         _outIdList(str, node->objs);
3350                         break;
3351         }
3352 }
3353
3354 static void
3355 _outPrivGrantee(String *str, PrivGrantee *node)
3356 {
3357         if (node->rolname == NULL)
3358                 string_append_char(str, "PUBLIC");
3359         else
3360         {
3361                 string_append_char(str, "\"");
3362                 string_append_char(str, node->rolname);
3363                 string_append_char(str, "\"");
3364         }
3365 }
3366
3367 static void
3368 _outGrantStmt(String *str, GrantStmt *node)
3369 {
3370         PrivTarget *n;
3371         
3372         if (node->is_grant == true)
3373                 string_append_char(str, "GRANT ");
3374         else
3375         {
3376                 string_append_char(str, "REVOKE ");
3377                 if (node->grant_option == true)
3378                         string_append_char(str, "GRANT OPTION FOR ");
3379         }
3380         
3381         _outPrivilegeList(str, node->privileges);
3382
3383         string_append_char(str, " ON ");
3384
3385         n = makeNode(PrivTarget);
3386         n->objtype = node->objtype;
3387         n->objs = node->objects;
3388         _outNode(str, n);
3389         pfree(n);
3390
3391         if (node->is_grant == true)
3392                 string_append_char(str, " TO ");
3393         else
3394                 string_append_char(str, " FROM ");
3395         _outNode(str, node->grantees);
3396
3397         if (node->is_grant == true && node->grant_option == TRUE)
3398                 string_append_char(str, " WITH GRANT OPTION");
3399
3400         if (node->behavior == DROP_CASCADE)
3401                 string_append_char(str, " CASCADE");
3402 }
3403
3404 static void
3405 _outGrantRoleStmt(String *str, GrantRoleStmt *node)
3406 {
3407         if (node->is_grant == true)
3408                 string_append_char(str, "GRANT ");
3409         else
3410         {
3411                 string_append_char(str, "REVOKE ");
3412                 if (node->admin_opt == true)
3413                         string_append_char(str, "ADMIN OPTION FOR ");
3414         }
3415
3416         _outIdList(str, node->granted_roles);
3417
3418         string_append_char(str, node->is_grant == true ? " TO " : " FROM ");
3419
3420         _outIdList(str, node->grantee_roles);
3421
3422         if (node->admin_opt == true && node->is_grant == true)
3423                 string_append_char(str, "  WITH ADMIN OPTION");
3424
3425         if (node->grantor != NULL)
3426         {
3427                 string_append_char(str, " GRANTED BY \"");
3428                 string_append_char(str, node->grantor);
3429                 string_append_char(str, "\"");
3430         }
3431
3432         if (node->behavior == DROP_CASCADE)
3433                 string_append_char(str, " CASCADE");
3434 }
3435
3436 static void
3437 _outFuncOptList(String *str, List *list)
3438 {
3439         ListCell *lc;
3440
3441         foreach (lc, list)
3442         {
3443                 DefElem *e = lfirst(lc);
3444                 Value *v = (Value *) e->arg;
3445                 
3446                 if (strcmp(e->defname, "strict") == 0)
3447                 {
3448                         if (v->val.ival == TRUE)
3449                                 string_append_char(str, " STRICT");
3450                         else
3451                                 string_append_char(str, " CALLED ON NULL INPUT");
3452                 }
3453                 else if (strcmp(e->defname, "volatility") == 0)
3454                 {
3455                         char *s = v->val.str;
3456                         if (strcmp(s, "immutable") == 0)
3457                                 string_append_char(str, " IMMUTABLE");
3458                         else if (strcmp(s, "stable") == 0)
3459                                 string_append_char(str, " STABLE");
3460                         else if (strcmp(s, "volatile") == 0)
3461                                 string_append_char(str, " VOLATILE");
3462                 }
3463                 else if (strcmp(e->defname, "security") == 0)
3464                 {
3465                         if (v->val.ival == TRUE)
3466                                 string_append_char(str, " SECURITY DEFINER");
3467                         else
3468                                 string_append_char(str, " SECURITY INVOKER");
3469                 }
3470                 else if (strcmp(e->defname, "as") == 0)
3471                 {
3472                         string_append_char(str, " AS ");
3473                         _outNode(str, e->arg);
3474                 }
3475                 else if (strcmp(e->defname, "language") == 0)
3476                 {
3477                         string_append_char(str, " LANGUAGE '");
3478                         string_append_char(str, v->val.str);
3479                         string_append_char(str, "'");
3480                 }
3481         }
3482 }
3483
3484 static void
3485 _outCreateFunctionStmt(String *str, CreateFunctionStmt *node)
3486 {
3487         string_append_char(str, "CREATE ");
3488         if (node->replace == true)
3489                 string_append_char(str, "OR REPLACE ");
3490         string_append_char(str, "FUNCTION ");
3491
3492         _outFuncName(str, node->funcname);
3493
3494         string_append_char(str, " (");
3495         _outNode(str, node->parameters);
3496         string_append_char(str, ")");
3497
3498         if (node->returnType)
3499         {
3500                 string_append_char(str, " RETURNS ");
3501                 _outNode(str, node->returnType);
3502         }
3503
3504         _outFuncOptList(str, node->options);
3505
3506         if (node->withClause)
3507         {
3508                 string_append_char(str, " WITH ");
3509                 _outDefinition(str, node->withClause);
3510         }
3511 }
3512
3513 static void
3514 _outAlterFunctionStmt(String *str, AlterFunctionStmt *node)
3515 {
3516         string_append_char(str, "ALTER FUNCTION ");
3517         _outNode(str, node->func);
3518         _outFuncOptList(str, node->actions);
3519 }
3520
3521 static void
3522 _outRemoveFuncStmt(String *str, RemoveFuncStmt *node)
3523 {
3524         switch (node->kind)
3525         {
3526                 case OBJECT_FUNCTION:
3527                         string_append_char(str, "DROP FUNCTION ");
3528                         break;
3529
3530
3531                 case OBJECT_AGGREGATE:
3532                         string_append_char(str, "DROP AGGREGATE ");
3533                         break;
3534
3535                 case OBJECT_OPERATOR:
3536                         string_append_char(str, "DROP OPERATOR CLASS ");
3537                         break;
3538
3539                 default:
3540                         break;
3541         }
3542
3543         if (node->missing_ok)
3544                 string_append_char(str, "IF EXISTS ");
3545
3546         _outFuncName(str, node->name);
3547
3548         string_append_char(str, " (");
3549         _outNode(str, node->args);
3550         string_append_char(str, ")");
3551
3552         if (node->behavior == DROP_CASCADE)
3553                 string_append_char(str, " CASCADE");
3554 }
3555
3556 static void
3557 _outCreateCastStmt(String *str, CreateCastStmt *node)
3558 {
3559         string_append_char(str, "CREATE CAST (");
3560         _outNode(str, node->sourcetype);
3561         string_append_char(str, " AS ");
3562         _outNode(str, node->targettype);
3563         string_append_char(str, ") WITH FUNCTION ");
3564         _outNode(str, node->func);
3565         
3566         switch (node->context)
3567         {
3568                 case COERCION_IMPLICIT:
3569                         string_append_char(str, " AS IMPLICIT");
3570                         break;
3571
3572                 case COERCION_ASSIGNMENT:
3573                         string_append_char(str, " AS ASSIGNMENT");
3574                         break;
3575
3576                 default:
3577                         break;
3578         }
3579 }
3580
3581 static void
3582 _outDropCastStmt(String *str, DropCastStmt *node)
3583 {
3584         string_append_char(str, "DROP CAST (");
3585         _outNode(str, node->sourcetype);
3586         string_append_char(str, " AS ");
3587         _outNode(str, node->targettype);
3588         string_append_char(str, ")");
3589
3590         if (node->behavior == DROP_CASCADE)
3591                 string_append_char(str, " CASCADE");
3592 }
3593
3594 static void
3595 _outReindexStmt(String *str, ReindexStmt *node)
3596 {
3597         string_append_char(str, "REINDEX ");
3598
3599         switch (node->kind)
3600         {
3601                 case OBJECT_DATABASE:
3602                         if (node->do_system == true && node->do_user == false)
3603                                 string_append_char(str, "SYSTEM ");
3604                         else
3605                                 string_append_char(str, "DATABASE ");
3606                         break;
3607
3608                 case OBJECT_INDEX:
3609                         string_append_char(str, "INDEX ");
3610                         break;
3611
3612                 case OBJECT_TABLE:
3613                         string_append_char(str, "TABLE ");
3614                         break;
3615
3616                 default:
3617                         break;
3618         }
3619
3620         if (node->relation)
3621                 _outNode(str, node->relation);
3622
3623         if (node->name)
3624         {
3625                 string_append_char(str, "\"");
3626                 string_append_char(str, (char *) node->name);
3627                 string_append_char(str, "\"");
3628         }
3629 }
3630
3631 static void
3632 _outAlterObjectSchemaStmt(String *str, AlterObjectSchemaStmt *node)
3633 {
3634         string_append_char(str, "ALTER ");
3635
3636         switch (node->objectType)
3637         {
3638                 case OBJECT_AGGREGATE:
3639                         string_append_char(str, "AGGREGATE ");
3640                         _outFuncName(str, node->object);
3641                         string_append_char(str, "(");
3642                         if (lfirst(list_head(node->objarg)) == NULL)
3643                                 string_append_char(str, "*");
3644                         else
3645                                 _outNode(str, lfirst(list_head(node->objarg)));
3646                         string_append_char(str, ") SET SCHAME \"");
3647                         string_append_char(str, node->newschema);
3648                         string_append_char(str, "\"");
3649                         break;
3650
3651                 case OBJECT_DOMAIN:
3652                         string_append_char(str, "DOMAIN ");
3653                         _outFuncName(str, node->object);
3654                         string_append_char(str, " SET SCHEMA \"");
3655                         string_append_char(str, node->newschema);
3656                         string_append_char(str, "\"");
3657                         break;
3658
3659                 case OBJECT_FUNCTION:
3660                         string_append_char(str, "FUNCTION ");
3661                         _outFuncName(str, node->object);
3662                         string_append_char(str, "(");
3663                         _outNode(str, node->objarg);
3664                         string_append_char(str, ") SET SCHEMA \"");
3665                         string_append_char(str, node->newschema);
3666                         string_append_char(str, "\"");
3667                         break;
3668
3669                 case OBJECT_SEQUENCE:
3670                         string_append_char(str, "SEQUENCE ");
3671                         _outNode(str, node->relation);
3672                         string_append_char(str, " SET SCHEMA \"");
3673                         string_append_char(str, node->newschema);
3674                         string_append_char(str, "\"");
3675                         break;
3676
3677                 case OBJECT_TABLE:
3678                         string_append_char(str, "TABLE ");
3679                         _outNode(str, node->relation);
3680                         string_append_char(str, " SET SCHEMA \"");
3681                         string_append_char(str, node->newschema);
3682                         string_append_char(str, "\"");
3683                         break;
3684
3685                 case OBJECT_TYPE:
3686                         string_append_char(str, "TYPE ");
3687                         _outFuncName(str, node->object);
3688                         string_append_char(str, " SET SCHEMA \"");
3689                         string_append_char(str, node->newschema);
3690                         string_append_char(str, "\"");
3691                         break;
3692
3693                 default:
3694                         break;
3695         }
3696 }
3697
3698 static void
3699 _outAlterOwnerStmt(String *str, AlterOwnerStmt *node)
3700 {
3701         string_append_char(str, "ALTER ");
3702
3703         switch (node->objectType)
3704         {
3705                 case OBJECT_AGGREGATE:
3706                         string_append_char(str, "AGGREGATE ");
3707                         _outFuncName(str, node->object);
3708                         string_append_char(str, "(");
3709                         if (lfirst(list_head(node->objarg)) == NULL)
3710                                 string_append_char(str, "*");
3711                         else
3712                                 _outNode(str, lfirst(list_head(node->objarg)));
3713                         string_append_char(str, ") OWNER TO \"");
3714                         string_append_char(str, node->newowner);
3715                         string_append_char(str, "\"");
3716                         break;
3717
3718                 case OBJECT_CONVERSION:
3719                         string_append_char(str, "CONVERSION ");
3720                         _outFuncName(str, node->object);
3721                         string_append_char(str, " OWNER TO \"");
3722                         string_append_char(str, node->newowner);
3723                         string_append_char(str, "\"");
3724                         break;
3725
3726                 case OBJECT_DATABASE:
3727                         string_append_char(str, "DATABASE \"");
3728                         _outIdList(str, node->object);
3729                         string_append_char(str, "\" OWNER TO \"");
3730                         string_append_char(str, node->newowner);
3731                         string_append_char(str, "\"");
3732                         break;
3733
3734                 case OBJECT_DOMAIN:
3735                         string_append_char(str, "DOMAIN ");
3736                         _outFuncName(str, node->object);
3737                         string_append_char(str, " OWNER TO \"");
3738                         string_append_char(str, node->newowner);
3739                         string_append_char(str, "\"");
3740                         break;
3741
3742                 case OBJECT_FUNCTION:
3743                         string_append_char(str, "FUNCTION ");
3744                         _outFuncName(str, node->object);
3745                         string_append_char(str, "(");
3746                         _outNode(str, node->objarg);
3747                         string_append_char(str, ") OWNER TO \"");
3748                         string_append_char(str, node->newowner);
3749                         string_append_char(str, "\"");
3750                         break;
3751
3752                 case OBJECT_OPERATOR:
3753                         string_append_char(str, "OPERATOR ");
3754                         _outOperatorName(str, node->object);
3755                         string_append_char(str, "(");
3756                         _outOperatorArgTypes(str, node->objarg);
3757                         string_append_char(str, ") OWNER TO \"");
3758                         string_append_char(str, node->newowner);
3759                         string_append_char(str, "\"");                  
3760                         break;
3761
3762                 case OBJECT_OPCLASS:
3763                         string_append_char(str, "OPERATOR CLASS ");
3764                         _outFuncName(str, node->object);
3765                         string_append_char(str, " USING ");
3766                         string_append_char(str, node->addname);
3767                         string_append_char(str, " OWNER TO \"");
3768                         string_append_char(str, node->newowner);
3769                         string_append_char(str, "\"");
3770                         break;
3771
3772                 case OBJECT_SCHEMA:
3773                         string_append_char(str, "SCHEMA \"");
3774                         string_append_char(str, linitial(node->object));
3775                         string_append_char(str, "\" OWNER TO \"");
3776                         string_append_char(str, node->newowner);
3777                         string_append_char(str, "\"");
3778                         break;
3779
3780                 case OBJECT_TYPE:
3781                         string_append_char(str, "TYPE ");
3782                         _outFuncName(str, node->object);
3783                         string_append_char(str, " OWNER TO \"");
3784                         string_append_char(str, node->newowner);
3785                         string_append_char(str, "\"");
3786                         break;
3787
3788                 case OBJECT_TABLESPACE:
3789                         string_append_char(str, "TABLESPACE \"");
3790                         string_append_char(str, linitial(node->object));
3791                         string_append_char(str, "\" OWNER TO \"");
3792                         string_append_char(str, node->newowner);
3793                         string_append_char(str, "\"");
3794                         break;
3795
3796                 default:
3797                         break;
3798         }
3799 }
3800
3801 static void
3802 _outRuleStmt(String *str, RuleStmt *node)
3803 {
3804         string_append_char(str, "CREATE ");
3805         if (node->replace)
3806                 string_append_char(str, "OR REPLACE ");
3807         string_append_char(str, "RULE \"");
3808         string_append_char(str, node->rulename);
3809         string_append_char(str, "\" AS ON ");
3810
3811         switch (node->event)
3812         {
3813                 case CMD_SELECT:
3814                         string_append_char(str, "SELECT");
3815                         break;
3816
3817                 case CMD_UPDATE:
3818                         string_append_char(str, "UPDATE");
3819                         break;
3820
3821                 case CMD_DELETE:
3822                         string_append_char(str, "DELETE");
3823                         break;
3824
3825                 case CMD_INSERT:
3826                         string_append_char(str, "INSERT");
3827                         break;
3828
3829                 default:
3830                         break;
3831         }
3832
3833         string_append_char(str, " TO ");
3834         _outNode(str, node->relation);
3835         
3836         if (node->whereClause)
3837         {
3838                 string_append_char(str, " WHERE ");
3839                 _outNode(str, node->whereClause);
3840         }
3841
3842         string_append_char(str, " DO ");
3843
3844         if (node->instead)
3845                 string_append_char(str, "INSTEAD ");
3846
3847         if (node->actions == NIL)
3848                 string_append_char(str, "NOTHING");
3849         else if (list_length(node->actions) == 1)
3850                 _outNode(str, linitial(node->actions));
3851         else
3852         {
3853                 ListCell *lc;
3854                 char semi = 0;
3855
3856                 string_append_char(str, "(");
3857
3858                 foreach (lc, node->actions)
3859                 {
3860                         if (semi == 0)
3861                                 semi = 1;
3862                         else
3863                                 string_append_char(str, ";");
3864                         
3865                         _outNode(str, lfirst(lc));
3866                 }
3867
3868                 string_append_char(str, ")");
3869         }
3870 }
3871
3872 static void
3873 _outViewStmt(String *str, ViewStmt *node)
3874 {
3875         if (node->replace)
3876                 string_append_char(str, "CREATE OR REPLACE ");
3877         else
3878                 string_append_char(str, "CREATE ");
3879
3880         if (node->view->istemp == TRUE)
3881                 string_append_char(str, "TEMP ");
3882
3883         string_append_char(str, "VIEW ");
3884         _outNode(str, node->view);
3885
3886         if (node->aliases)
3887         {
3888                 string_append_char(str, "(");
3889                 _outIdList(str, node->aliases);
3890                 string_append_char(str, ")");
3891         }
3892
3893         string_append_char(str, " AS");
3894         _outNode(str, node->query);
3895 }
3896
3897 static void
3898 _outCreatedbOptList(String *str, List *options)
3899 {
3900         ListCell *lc;
3901
3902         foreach (lc, options)
3903         {
3904                 DefElem *e = lfirst(lc);
3905                 Value *v = (Value *) e->arg;
3906                 int sconst = false;
3907
3908                 /* keyword */
3909                 if (strcmp(e->defname, "template") == 0)
3910                         string_append_char(str, " TEMPLATE ");
3911                 else if (strcmp(e->defname, "location") == 0)
3912                 {
3913                         string_append_char(str, " LOCATION ");
3914                         sconst = true;
3915                 }
3916                 else if (strcmp(e->defname, "tablespace") == 0)
3917                         string_append_char(str, " TABLESPACE ");
3918                 else if (strcmp(e->defname, "encoding") == 0)
3919                 {
3920                         string_append_char(str, " ENCODING ");
3921                         sconst = true;
3922                 }
3923                 else if (strcmp(e->defname, "owner") == 0)
3924                         string_append_char(str, " OWNER ");
3925                 else if (strcmp(e->defname, "connectionlimit") == 0)
3926                         string_append_char(str, " CONNECTION LIMIT ");
3927
3928                 /* value */
3929                 if (v == NULL)
3930                         string_append_char(str, "DEFAULT");
3931                 else if (IsA((Node *)v, String))
3932                 {
3933                         string_append_char(str, sconst ? "'" : "'");
3934                         string_append_char(str, v->val.str);
3935                         string_append_char(str, sconst ? "'" : "'");
3936                 }
3937                 else
3938                 {
3939                         char buf[16];
3940                         snprintf(buf, 16, "%ld", v->val.ival);
3941                         string_append_char(str, buf);
3942                 }
3943         }
3944 }
3945
3946 static void
3947 _outCreatedbStmt(String *str, CreatedbStmt *node)
3948 {
3949         string_append_char(str, "CREATE DATABASE \"");
3950         string_append_char(str, node->dbname);
3951         string_append_char(str, "\"");
3952
3953         _outCreatedbOptList(str, node->options);
3954 }
3955
3956 static void
3957 _outAlterDatabaseStmt(String *str, AlterDatabaseStmt *node)
3958 {
3959         string_append_char(str, "ALTER DATABASE \"");
3960         string_append_char(str, node->dbname);
3961         string_append_char(str, "\" ");
3962
3963         _outCreatedbOptList(str, node->options);
3964 }
3965
3966 static void
3967 _outAlterDatabaseSetStmt(String *str, AlterDatabaseSetStmt *node)
3968 {
3969         string_append_char(str, "ALTER DATABASE \"");
3970         string_append_char(str, node->dbname);
3971         string_append_char(str, "\" ");
3972
3973         _outNode(str, node->setstmt);
3974 }
3975
3976 static void
3977 _outDropdbStmt(String *str, DropdbStmt *node)
3978 {
3979         string_append_char(str, "DROP DATABASE \"");
3980         string_append_char(str, node->dbname);
3981         string_append_char(str, "\"");
3982 }
3983
3984 static void
3985 _outCreateDomainStmt(String *str, CreateDomainStmt *node)
3986 {
3987         ListCell *lc;
3988
3989         string_append_char(str, "CREATE DOMAIN ");
3990         _outFuncName(str, node->domainname);
3991         string_append_char(str, " ");
3992         _outNode(str, node->typename);
3993
3994
3995         foreach (lc, node->constraints)
3996         {
3997                 string_append_char(str, " ");
3998                 _outNode(str, lfirst(lc));
3999         }
4000 }
4001
4002 static void
4003 _outAlterDomainStmt(String *str, AlterDomainStmt *node)
4004 {
4005         string_append_char(str, "ALTER DOMAIN ");
4006         _outFuncName(str, node->typename);
4007
4008         switch (node->subtype)
4009         {
4010                 case 'T':
4011                         if (node->def)
4012                         {
4013                                 string_append_char(str, " SET DEFAULT ");
4014                                 _outNode(str, node->def);
4015                         }
4016                         else
4017                                 string_append_char(str, " DROP DEFAULT");
4018                         break;
4019
4020                 case 'N':
4021                         string_append_char(str, " DROP NOT NULL");
4022                         break;
4023
4024                 case 'O':
4025                         string_append_char(str, " SET NOT NULL");
4026                         break;
4027
4028                 case 'C':
4029                         string_append_char(str, " ADD ");
4030                         _outNode(str, node->def);
4031                         break;
4032
4033                 case 'X':
4034                         string_append_char(str, " DROP CONSTRAINT \"");
4035                         string_append_char(str, node->name);
4036                         string_append_char(str, "\"");
4037                         if (node->behavior == DROP_CASCADE)
4038                                 string_append_char(str, " CASCADE");
4039                         break;
4040         }
4041 }
4042
4043 static void
4044 _outCreateConversionStmt(String *str, CreateConversionStmt *node)
4045 {
4046         string_append_char(str, "CREATE ");
4047
4048         if (node->def == TRUE)
4049                 string_append_char(str, "DEFAULT ");
4050
4051         string_append_char(str, "CONVERSION ");
4052
4053         _outFuncName(str, node->conversion_name);
4054
4055         string_append_char(str, " FOR '");
4056         string_append_char(str, node->for_encoding_name);
4057         string_append_char(str, "' TO '");
4058         string_append_char(str, node->to_encoding_name);
4059         string_append_char(str, " FROM ");
4060         _outFuncName(str, node->func_name);
4061 }
4062
4063 static void
4064 _outPrepareStmt(String *str, PrepareStmt *node)
4065 {
4066         string_append_char(str, "PREPARE \"");
4067         string_append_char(str, node->name);
4068         string_append_char(str, "\" ");
4069
4070         if (node->argtypes != NIL)
4071         {
4072                 string_append_char(str, "(");
4073                 _outNode(str, node->argtypes);
4074                 string_append_char(str, ") ");
4075         }
4076
4077         string_append_char(str, "AS ");
4078         _outNode(str, node->query);
4079 }
4080
4081 static void
4082 _outExecuteStmt(String *str, ExecuteStmt *node)
4083 {
4084         if (node->into)
4085         {
4086                 IntoClause *into = node->into;
4087                 RangeVar *rel = into->rel;
4088
4089                 string_append_char(str, "CREATE ");
4090                 if (rel->istemp == TRUE)
4091                         string_append_char(str, "TEMP ");
4092                 string_append_char(str, "TABLE ");
4093                 _outNode(str, into->rel);
4094                 string_append_char(str, " AS ");
4095         }
4096
4097         string_append_char(str, "EXECUTE \"");
4098         string_append_char(str, node->name);
4099         string_append_char(str, "\" ");
4100
4101         if (node->params != NIL)
4102         {
4103                 string_append_char(str, "(");
4104                 _outNode(str, node->params);
4105                 string_append_char(str, ")");
4106         }
4107 }
4108
4109 static void
4110 _outLockStmt(String *str, LockStmt *node)
4111 {
4112         string_append_char(str, "LOCK TABLE ");
4113         _outNode(str, node->relations);
4114
4115         string_append_char(str, " IN ");
4116         switch (node->mode)
4117         {
4118                 case AccessShareLock:
4119                         string_append_char(str, "ACCESS SHARE ");
4120                         break;
4121
4122                 case RowShareLock:
4123                         string_append_char(str, "ROW SHARE ");
4124                         break;
4125
4126                 case RowExclusiveLock:
4127                         string_append_char(str, "ROW EXCLUSIVE ");
4128                         break;
4129
4130                 case ShareUpdateExclusiveLock:
4131                         string_append_char(str, "SHARE UPDATE EXCLUSIVE ");
4132                         break;
4133
4134                 case ShareLock:
4135                         string_append_char(str, "SHARE ");
4136                         break;
4137
4138                 case ShareRowExclusiveLock:
4139                         string_append_char(str, "SHARE ROW EXCLUSIVE ");
4140                         break;
4141
4142                 case ExclusiveLock:
4143                         string_append_char(str, "EXCLUSIVE ");
4144                         break;
4145
4146                 case AccessExclusiveLock:
4147                         string_append_char(str, "ACCESS EXCLUSIVE ");
4148                         break;
4149         }
4150         string_append_char(str, "MODE");
4151
4152         if (node->nowait == TRUE)
4153                 string_append_char(str, " NOWAIT");
4154 }
4155
4156 static void
4157 _outOperatorArgTypes(String *str, List *args)
4158 {
4159         TypeName *left, *right;
4160
4161         left = linitial(args);
4162         right = lsecond(args);
4163
4164         if (left)
4165                 _outNode(str, left);
4166         else
4167                 string_append_char(str, "NONE");
4168         string_append_char(str, ", ");
4169         if (right)
4170                 _outNode(str, right);
4171         else
4172                 string_append_char(str, "NONE");
4173 }
4174
4175 static void
4176 _outCommentStmt(String *str, CommentStmt *node)
4177 {
4178         TypeName *t;
4179         Value *v;
4180         char buf[16];
4181
4182         string_append_char(str, "COMMENT ON ");
4183
4184         switch (node->objtype)
4185         {
4186                 case OBJECT_AGGREGATE:
4187                         string_append_char(str, "AGGREGATE ");
4188                         _outFuncName(str, node->objname);
4189                         string_append_char(str, "(");
4190
4191                         t = linitial(node->objargs);
4192                         if (t)
4193                                 _outNode(str, t);
4194                         else
4195                                 string_append_char(str, "*");
4196                         string_append_char(str, ")");
4197                         break;
4198
4199                 case OBJECT_FUNCTION:
4200                         string_append_char(str, "FUNCTION ");
4201                         _outFuncName(str, node->objname);
4202                         string_append_char(str, "(");
4203                         _outNode(str, node->objargs);
4204                         string_append_char(str, ")");
4205                         break;
4206
4207                 case OBJECT_OPERATOR:
4208                         string_append_char(str, "OPERATOR ");
4209                         _outOperatorName(str, node->objname);
4210                         string_append_char(str, "(");
4211                         _outOperatorArgTypes(str, node->objargs);
4212                         string_append_char(str, ")");
4213                         break;
4214
4215                 case OBJECT_CONSTRAINT:
4216                         string_append_char(str, "CONSTRAINT \"");
4217                         v = lsecond(node->objname);
4218                         string_append_char(str, v->val.str);
4219                         string_append_char(str, "\" ON ");
4220                         _outFuncName(str, linitial(node->objargs));
4221                         break;
4222
4223                 case OBJECT_RULE:
4224                         string_append_char(str, "RULE \"");
4225                         v = lsecond(node->objname);
4226                         string_append_char(str, v->val.str);
4227                         string_append_char(str, "\" ON ");
4228                         _outFuncName(str, linitial(node->objargs));
4229                         break;
4230
4231                 case OBJECT_TRIGGER:
4232                         string_append_char(str, "TRIGGER \"");
4233                         v = lsecond(node->objname);
4234                         string_append_char(str, v->val.str);
4235                         string_append_char(str, "\" ON ");
4236                         _outFuncName(str, linitial(node->objargs));
4237                         break;
4238
4239                 case OBJECT_OPCLASS:
4240                         string_append_char(str, "OPERATOR CLASS ");
4241                         _outFuncName(str, node->objname);
4242                         string_append_char(str, " USING ");
4243                         v = linitial(node->objargs);
4244                         string_append_char(str, v->val.str);
4245                         break;
4246
4247                 case OBJECT_LARGEOBJECT:
4248                         string_append_char(str, "LARGE OBJECT ");
4249                         v = linitial(node->objname);
4250                         if (IsA(v, String))
4251                                 string_append_char(str, v->val.str);
4252                         else if (IsA(v, Integer))
4253                         {
4254                                 snprintf(buf, 16, "%ld", v->val.ival);
4255                                 string_append_char(str, buf);
4256                         }
4257
4258                 case OBJECT_CAST:
4259                         string_append_char(str, "CAST (");
4260                         _outNode(str, linitial(node->objname));
4261                         string_append_char(str, " AS ");
4262                         _outNode(str, linitial(node->objargs));
4263                         string_append_char(str, ")");
4264                         break;
4265
4266                 case OBJECT_LANGUAGE:
4267                         string_append_char(str, "LANGUAGE ");
4268                         _outFuncName(str, node->objname);
4269                         break;
4270
4271                 default:
4272                         switch (node->objtype)
4273                         {
4274                                 case OBJECT_COLUMN:
4275                                         string_append_char(str, "COLUMN ");
4276                                         break;
4277                                 case OBJECT_DATABASE:
4278                                         string_append_char(str, "DATABASE ");
4279                                         break;
4280                                 case OBJECT_SCHEMA:
4281                                         string_append_char(str, "SCHEMA ");
4282                                         break;
4283                                 case OBJECT_INDEX:
4284                                         string_append_char(str, "INDEX ");
4285                                         break;
4286                                 case OBJECT_SEQUENCE:
4287                                         string_append_char(str, "SEQUENCE ");
4288                                         break;
4289                                 case OBJECT_TABLE:
4290                                         string_append_char(str, "TABLE ");
4291                                         break;
4292                                 case OBJECT_DOMAIN:
4293                                         string_append_char(str, "DOMAIN ");
4294                                         break;
4295                                 case OBJECT_TYPE:
4296                                         string_append_char(str, "TYPE ");
4297                                         break;
4298                                 case OBJECT_VIEW:
4299                                         string_append_char(str, "VIEW ");
4300                                         break;
4301                                 default:
4302                                         break;
4303                         }
4304                         _outFuncName(str, node->objname);
4305                         break;
4306         }
4307
4308         string_append_char(str, " IS ");
4309         if (node->comment)
4310         {
4311                 string_append_char(str, "'");
4312                 string_append_char(str, node->comment);
4313                 string_append_char(str, "'");
4314         }
4315         else
4316                 string_append_char(str, "NULL");
4317 }
4318
4319 static void
4320 _outRangeSubselect(String *str, RangeSubselect *node)
4321 {
4322         string_append_char(str, "(");
4323         _outNode(str, node->subquery);
4324         string_append_char(str, ")");
4325
4326         _outNode(str, node->alias);
4327 }
4328
4329 static void
4330 _outRangeFunction(String *str, RangeFunction *node)
4331 {
4332         _outNode(str, node->funccallnode);
4333         if (node->alias)
4334         {
4335                 _outNode(str, node->alias);
4336         }               
4337
4338         if (node->coldeflist)
4339         {
4340                 string_append_char(str, " (");
4341                 _outNode(str, node->coldeflist);
4342                 string_append_char(str, ")");
4343         }
4344 }
4345
4346 static void
4347 _outDiscardStmt(String *str, DiscardStmt *node)
4348 {
4349         switch (node->target)
4350         {
4351                 case DISCARD_ALL:
4352                         string_append_char(str, "DISCARD ALL");
4353                         break;
4354
4355                 case DISCARD_TEMP:
4356                         string_append_char(str, "DISCARD TEMP");
4357                         break;
4358
4359                 case DISCARD_PLANS:
4360                         string_append_char(str, "DISCARD PLANS");
4361                         break;
4362
4363                 default:
4364                         break;
4365         }
4366 }
4367
4368 static void
4369 _outCreateOpFamilyStmt(String *str, CreateOpFamilyStmt *node)
4370 {
4371         string_append_char(str, "CREATE OPERATOR FAMILY ");
4372         _outIdList(str, node->opfamilyname);
4373         string_append_char(str, " USING \"");
4374         string_append_char(str, node->amname);
4375         string_append_char(str, "\"");
4376 }
4377
4378 static void
4379 _outAlterOpFamilyStmt(String *str, AlterOpFamilyStmt *node)
4380 {
4381 }
4382
4383 static void
4384 _outRemoveOpFamilyStmt(String *str, RemoveOpFamilyStmt *node)
4385 {
4386         string_append_char(str, "DROP OPERATOR FAMILY ");
4387         if (node->missing_ok)
4388                 string_append_char(str, "IF EXISTS ");
4389         _outIdList(str, node->opfamilyname);
4390         string_append_char(str, " USING \"");
4391         string_append_char(str, node->amname);
4392         string_append_char(str, "\"");
4393 }
4394
4395 static void
4396 _outCreateEnumStmt(String *str, CreateEnumStmt *node)
4397 {
4398         string_append_char(str, "CREATE TYPE ");
4399         _outIdList(str, node->typename);
4400         string_append_char(str, " AS ENUM (");
4401         _outNode(str, node->vals);
4402         string_append_char(str, ")");
4403 }
4404
4405 static void
4406 _outDropOwnedStmt(String *str, DropOwnedStmt *node)
4407 {
4408         string_append_char(str, "DROP OWNED BY ");
4409         _outIdList(str, node->roles);
4410         if (node->behavior == DROP_CASCADE)
4411                 string_append_char(str, " CASCADE");
4412 }
4413
4414 static void
4415 _outReassignOwnedStmt(String *str, ReassignOwnedStmt *node)
4416 {
4417         string_append_char(str, "REASSIGN OWNED BY ");
4418         _outIdList(str, node->roles);
4419         string_append_char(str, " TO \"");
4420         string_append_char(str, node->newrole);
4421         string_append_char(str, "\"");
4422 }
4423
4424 static void
4425 _outAlterTSDictionaryStmt(String *str, AlterTSDictionaryStmt *node)
4426 {
4427         string_append_char(str, "ALTER TEXT SEARCH DICTIONARY ");
4428         _outIdList(str, node->dictname);
4429         string_append_char(str, "(");
4430         _outNode(str, node->options);
4431         string_append_char(str, ")");
4432 }
4433
4434 static void
4435 _outAlterTSConfigurationStmt(String *str, AlterTSConfigurationStmt *node)
4436 {
4437         string_append_char(str, "ALTER TEXT SEARCH CONFIGURATION ");
4438         _outIdList(str, node->cfgname);
4439         if (node->override == false && node->replace == false)
4440         {
4441                 string_append_char(str, "ADD MAPPING FOR ");
4442                 _outIdList(str, node->tokentype);
4443                 string_append_char(str, " WITH ");
4444                 _outIdList(str, node->dicts);
4445         }
4446         else if (node->override == true && node->replace == false)
4447         {
4448                 string_append_char(str, "ALTER MAPPING FOR ");
4449                 _outIdList(str, node->tokentype);
4450                 string_append_char(str, " WITH ");
4451                 _outIdList(str, node->dicts);
4452         }
4453         else if (node->override == false && node->replace == true)
4454         {
4455                 if (node->tokentype == NIL)
4456                         string_append_char(str, "ALTER MAPPING ");
4457                 else
4458                 {
4459                         string_append_char(str, "ALTER MAPPING FOR ");
4460                         _outIdList(str, node->tokentype);
4461                 }
4462                 string_append_char(str, "REPLACE ");
4463                 _outNode(str, linitial(node->dicts));
4464                 string_append_char(str, " WITH ");
4465                 _outNode(str, lsecond(node->dicts));
4466         }
4467         else if (node->missing_ok == false)
4468         {
4469                 string_append_char(str, " DROP MAPPING FOR ");
4470                 _outIdList(str, node->tokentype);
4471         }
4472         else if (node->missing_ok == true)
4473         {
4474                 string_append_char(str, " DROP MAPPING IF EXISTS FOR ");
4475                 _outIdList(str, node->tokentype);
4476         }
4477 }
4478
4479 static void
4480 _outXmlExpr(String *str, XmlExpr *node)
4481 {
4482         A_Const *n;
4483
4484         switch (node->op)
4485         {
4486                 case IS_DOCUMENT:
4487                         _outNode(str, node->args);
4488                         string_append_char(str, " IS DOCUMENT");
4489                         break;
4490
4491                 case IS_XMLCONCAT:
4492                         string_append_char(str, "XMLCONCAT (");
4493                         _outNode(str, node->args);
4494                         string_append_char(str, ")");
4495                         break;
4496
4497                 case IS_XMLELEMENT:
4498                         string_append_char(str, "XMLELEMENT (");
4499                         if (node->name)
4500                         {
4501                                 string_append_char(str, "NAME \"");
4502                                 string_append_char(str, node->name);
4503                                 string_append_char(str, "\"");
4504                                 if (node->named_args != NIL)
4505                                 {
4506                                         string_append_char(str, ",");
4507                                         _outIdList(str, node->named_args);
4508                                 }
4509                         }
4510                         if (node->args != NIL)
4511                         {
4512                                 string_append_char(str, ",");
4513                                 _outNode(str, node->args);
4514                         }
4515                         string_append_char(str, ")");
4516                         break;
4517
4518                 case IS_XMLFOREST:
4519                         string_append_char(str, "XMLFOREST (");
4520                         _outNode(str, node->named_args);
4521                         string_append_char(str, ")");
4522                         break;
4523
4524                 case IS_XMLPARSE:
4525                         string_append_char(str, "XMLPARSE (");
4526                         if (node->xmloption == XMLOPTION_DOCUMENT)
4527                                 string_append_char(str, "DOCUMENT ");
4528                         else
4529                                 string_append_char(str, "CONTENT ");
4530
4531                         _outNode(str, linitial(node->args));
4532                         n = lsecond(node->args);
4533                         if (n->val.val.str[0] == 't')
4534                                 string_append_char(str, " PRESERVE WHITESPACE");
4535
4536                         string_append_char(str, ")");
4537                         break;
4538
4539
4540                 default:
4541                         break;
4542         }
4543 }
4544
4545 static void
4546 _outXmlSerialize(String *str, XmlSerialize *node)
4547 {
4548
4549 }
4550
4551 static void
4552 _outInhRelation(String *str, InhRelation *node)
4553 {
4554         ListCell *lc;
4555
4556         string_append_char(str, "LIKE ");
4557         _outNode(str, node->relation);
4558         foreach (lc, node->options)
4559         {
4560                 CreateStmtLikeOption v;
4561                 v = (CreateStmtLikeOption)lfirst(lc);
4562
4563                 switch (v)
4564                 {
4565                         case CREATE_TABLE_LIKE_INCLUDING_DEFAULTS:
4566                                 string_append_char(str, " INCLUDING DEFAULTS");
4567                                 break;
4568
4569                         case CREATE_TABLE_LIKE_EXCLUDING_DEFAULTS:
4570                                 string_append_char(str, " EXCLUDING DEFAULTS");
4571                                 break;
4572
4573                         case CREATE_TABLE_LIKE_INCLUDING_CONSTRAINTS:
4574                                 string_append_char(str, " INCLUDING CONSTRAINTS");
4575                                 break;
4576
4577                         case CREATE_TABLE_LIKE_EXCLUDING_CONSTRAINTS:
4578                                 string_append_char(str, " EXCLUDING CONSTRAINTS");
4579                                 break;
4580
4581                         case CREATE_TABLE_LIKE_INCLUDING_INDEXES:
4582                                 string_append_char(str, " INCLUDING INDEXES");
4583                                 break;
4584
4585                         case CREATE_TABLE_LIKE_EXCLUDING_INDEXES:
4586                                 string_append_char(str, " EXCLUDING INDEXES");
4587                                 break;
4588
4589                         default:
4590                                 break;
4591                 }
4592         }
4593 }
4594
4595 static void
4596 _outWithDefinition(String *str, List *def_list)
4597 {
4598         int oid = 0;
4599
4600         if (list_length(def_list) == 1)
4601         {
4602                 DefElem *elem;
4603                 Value *v;
4604                 
4605                 elem = linitial(def_list);
4606                 v = (Value *)elem->arg;
4607                 if (strcmp(elem->defname, "oids") == 0)
4608                 {
4609                         Value *v = (Value *)elem->arg;
4610                         if (v->val.ival == 1)
4611                                 string_append_char(str, " WITH OIDS ");
4612                         else
4613                                 string_append_char(str, " WITHOUT OIDS ");
4614                         oid = 1;
4615                 }
4616         }
4617
4618         if (oid == 1)
4619                 return;
4620
4621         string_append_char(str, " WITH ");
4622         _outDefinition(str, def_list);
4623 }
4624
4625 static void
4626 _outCurrentOfExpr(String *str, CurrentOfExpr *node)
4627 {
4628         string_append_char(str, "CURRENT OF ");
4629         if (node->cursor_name == NULL)
4630         {
4631                 char n[10];
4632                 snprintf(n, sizeof(n), "$%d", node->cursor_param);
4633                 string_append_char(str, n);
4634         }
4635         else
4636                 string_append_char(str, node->cursor_name);
4637 }
4638
4639 /*
4640  * _outNode -
4641  *        converts a Node into ascii string and append it to 'str'
4642  */
4643 void
4644 _outNode(String *str, void *obj)
4645 {
4646         if (obj == NULL)
4647                 return;
4648         else if (IsA(obj, List) ||IsA(obj, IntList) || IsA(obj, OidList))
4649                 _outList(str, obj);
4650         else if (IsA(obj, Integer) ||
4651                          IsA(obj, Float) ||
4652                          IsA(obj, String) ||
4653                          IsA(obj, BitString))
4654         {
4655                 /* nodeRead does not want to see { } around these! */
4656                 _outValue(str, obj);
4657         }
4658         else
4659         {
4660                 switch (nodeTag(obj))
4661                 {
4662                         case T_Alias:
4663                                 _outAlias(str, obj);
4664                                 break;
4665                         case T_RangeVar:
4666                                 _outRangeVar(str, obj);
4667                                 break;
4668                         case T_Var:
4669                                 _outVar(str, obj);
4670                                 break;
4671                         case T_Const:
4672                                 _outConst(str, obj);
4673                                 break;
4674                         case T_Param:
4675                                 _outParam(str, obj);
4676                                 break;
4677                         case T_Aggref:
4678                                 _outAggref(str, obj);
4679                                 break;
4680                         case T_ArrayRef:
4681                                 _outArrayRef(str, obj);
4682                                 break;
4683                         case T_FuncExpr:
4684                                 _outFuncExpr(str, obj);
4685                                 break;
4686                         case T_OpExpr:
4687                                 _outOpExpr(str, obj);
4688                                 break;
4689                         case T_DistinctExpr:
4690                                 _outDistinctExpr(str, obj);
4691                                 break;
4692                         case T_ScalarArrayOpExpr:
4693                                 _outScalarArrayOpExpr(str, obj);
4694                                 break;
4695                         case T_BoolExpr:
4696                                 _outBoolExpr(str, obj);
4697                                 break;
4698                         case T_SubLink:
4699                                 _outSubLink(str, obj);
4700                                 break;
4701                         case T_SubPlan:
4702                                 _outSubPlan(str, obj);
4703                                 break;
4704                         case T_FieldSelect:
4705                                 _outFieldSelect(str, obj);
4706                                 break;
4707                         case T_FieldStore:
4708                                 _outFieldStore(str, obj);
4709                                 break;
4710                         case T_RelabelType:
4711                                 _outRelabelType(str, obj);
4712                                 break;
4713                         case T_ConvertRowtypeExpr:
4714                                 _outConvertRowtypeExpr(str, obj);
4715                                 break;
4716                         case T_CaseExpr:
4717                                 _outCaseExpr(str, obj);
4718                                 break;
4719                         case T_CaseWhen:
4720                                 _outCaseWhen(str, obj);
4721                                 break;
4722                         case T_CaseTestExpr:
4723                                 _outCaseTestExpr(str, obj);
4724                                 break;
4725                         case T_ArrayExpr:
4726                                 _outArrayExpr(str, obj);
4727                                 break;
4728                         case T_RowExpr:
4729                                 _outRowExpr(str, obj);
4730                                 break;
4731                         case T_CoalesceExpr:
4732                                 _outCoalesceExpr(str, obj);
4733                                 break;
4734                         case T_MinMaxExpr:
4735                                 _outMinMaxExpr(str, obj);
4736                                 break;
4737                         case T_NullIfExpr:
4738                                 _outNullIfExpr(str, obj);
4739                                 break;
4740                         case T_NullTest:
4741                                 _outNullTest(str, obj);
4742                                 break;
4743                         case T_BooleanTest:
4744                                 _outBooleanTest(str, obj);
4745                                 break;
4746                         case T_CoerceToDomain:
4747                                 _outCoerceToDomain(str, obj);
4748                                 break;
4749                         case T_CoerceToDomainValue:
4750                                 _outCoerceToDomainValue(str, obj);
4751                                 break;
4752                         case T_SetToDefault:
4753                                 _outSetToDefault(str, obj);
4754                                 break;
4755                         case T_TargetEntry:
4756                                 _outTargetEntry(str, obj);
4757                                 break;
4758                         case T_RangeTblRef:
4759                                 _outRangeTblRef(str, obj);
4760                                 break;
4761                         case T_JoinExpr:
4762                                 _outJoinExpr(str, obj);
4763                                 break;
4764                         case T_FromExpr:
4765                                 _outFromExpr(str, obj);
4766                                 break;
4767
4768                         case T_CreateStmt:
4769                                 _outCreateStmt(str, obj);
4770                                 break;
4771                         case T_IndexStmt:
4772                                 _outIndexStmt(str, obj);
4773                                 break;
4774                         case T_NotifyStmt:
4775                                 _outNotifyStmt(str, obj);
4776                                 break;
4777                         case T_DeclareCursorStmt:
4778                                 _outDeclareCursorStmt(str, obj);
4779                                 break;
4780                         case T_SelectStmt:
4781                                 _outSelectStmt(str, obj);
4782                                 break;
4783                         case T_ColumnDef:
4784                                 _outColumnDef(str, obj);
4785                                 break;
4786                         case T_TypeName:
4787                                 _outTypeName(str, obj);
4788                                 break;
4789                         case T_TypeCast:
4790                                 _outTypeCast(str, obj);
4791                                 break;
4792                         case T_IndexElem:
4793                                 _outIndexElem(str, obj);
4794                                 break;
4795                         case T_SortClause:
4796                                 _outSortClause(str, obj);
4797                                 break;
4798                         case T_GroupClause:
4799                                 _outGroupClause(str, obj);
4800                                 break;
4801                         case T_SetOperationStmt:
4802                                 _outSetOperationStmt(str, obj);
4803                                 break;
4804 /*                      case T_RangeTblEntry:
4805                                 _outRangeTblEntry(str, obj);
4806                                 break;*/
4807                         case T_A_Expr:
4808                                 _outAExpr(str, obj);
4809                                 break;
4810                         case T_ColumnRef:
4811                                 _outColumnRef(str, obj);
4812                                 break;
4813                         case T_ParamRef:
4814                                 _outParamRef(str, obj);
4815                                 break;
4816                         case T_A_Const:
4817                                 _outAConst(str, obj);
4818                                 break;
4819                         case T_A_Indices:
4820                                 _outA_Indices(str, obj);
4821                                 break;
4822                         case T_A_Indirection:
4823                                 _outA_Indirection(str, obj);
4824                                 break;
4825                         case T_ResTarget:
4826                                 _outResTarget(str, obj);
4827                                 break;
4828                         case T_Constraint:
4829                                 _outConstraint(str, obj);
4830                                 break;
4831                         case T_FkConstraint:
4832                                 _outFkConstraint(str, obj);
4833                                 break;
4834                         case T_FuncCall:
4835                                 _outFuncCall(str, obj);
4836                                 break;
4837                         case T_DefElem:
4838                                 _outDefElem(str, obj);
4839                                 break;
4840                         case T_LockingClause:
4841                                 _outLockingClause(str, obj);
4842                                 break;
4843
4844                         case T_SortBy:
4845                                 _outSortBy(str, obj);
4846                                 break;
4847
4848                         case T_InsertStmt:
4849                                 _outInsertStmt(str, obj);
4850                                 break;
4851
4852                         case T_UpdateStmt:
4853                                 _outUpdateStmt(str, obj);
4854                                 break;
4855
4856                         case T_DeleteStmt:
4857                                 _outDeleteStmt(str, obj);
4858                                 break;
4859
4860                         case T_TransactionStmt:
4861                                 _outTransactionStmt(str, obj);
4862                                 break;
4863
4864                         case T_TruncateStmt:
4865                                 _outTruncateStmt(str, obj);
4866                                 break;
4867
4868                         case T_VacuumStmt:
4869                                 _outVacuumStmt(str, obj);
4870                                 break;
4871
4872                         case T_ExplainStmt:
4873                                 _outExplainStmt(str, obj);
4874                                 break;
4875
4876                         case T_ClusterStmt:
4877                                 _outClusterStmt(str, obj);
4878                                 break;
4879
4880                         case T_CheckPointStmt:
4881                                 _outCheckPointStmt(str, obj);
4882                                 break;
4883
4884                         case T_ClosePortalStmt:
4885                                 _outClosePortalStmt(str, obj);
4886                                 break;
4887
4888                         case T_ListenStmt:
4889                                 _outListenStmt(str, obj);
4890                                 break;
4891
4892                         case T_UnlistenStmt:
4893                                 _outUnlistenStmt(str, obj);
4894                                 break;
4895
4896                         case T_LoadStmt:
4897                                 _outLoadStmt(str, obj);
4898                                 break;
4899
4900                         case T_CopyStmt:
4901                                 _outCopyStmt(str, obj);
4902                                 break;
4903
4904                         case T_DeallocateStmt:
4905                                 _outDeallocateStmt(str, obj);
4906                                 break;
4907
4908                         case T_RenameStmt:
4909                                 _outRenameStmt(str, obj);
4910                                 break;
4911
4912                         case T_CreateRoleStmt:
4913                                 _outCreateRoleStmt(str, obj);
4914                                 break;
4915
4916                         case T_AlterRoleStmt:
4917                                 _outAlterRoleStmt(str, obj);
4918                                 break;
4919
4920                         case T_AlterRoleSetStmt:
4921                                 _outAlterRoleSetStmt(str, obj);
4922                                 break;
4923
4924                         case T_DropRoleStmt:
4925                                 _outDropRoleStmt(str, obj);
4926                                 break;
4927
4928                         case T_CreateSchemaStmt:
4929                                 _outCreateSchemaStmt(str, obj);
4930                                 break;
4931
4932                         case T_VariableSetStmt:
4933                                 _outVariableSetStmt(str, obj);
4934                                 break;
4935
4936                         case T_VariableShowStmt:
4937                                 _outVariableShowStmt(str, obj);
4938                                 break;
4939
4940                         case T_ConstraintsSetStmt:
4941                                 _outConstraintsSetStmt(str, obj);
4942                                 break;
4943
4944                         case T_AlterTableStmt:
4945                                 _outAlterTableStmt(str, obj);
4946                                 break;
4947
4948                         case T_AlterTableCmd:
4949                                 _outAlterTableCmd(str, obj);
4950                                 break;
4951
4952                         case T_CreateSeqStmt:
4953                                 _outCreateSeqStmt(str, obj);
4954                                 break;
4955
4956                         case T_AlterSeqStmt:
4957                                 _outAlterSeqStmt(str, obj);
4958                                 break;
4959
4960                         case T_CreatePLangStmt:
4961                                 _outCreatePLangStmt(str, obj);
4962                                 break;
4963
4964                         case T_DropPLangStmt:
4965                                 _outDropPLangStmt(str, obj);
4966                                 break;
4967
4968                         case T_CreateTableSpaceStmt:
4969                                 _outCreateTableSpaceStmt(str, obj);
4970                                 break;
4971
4972                         case T_DropTableSpaceStmt:
4973                                 _outDropTableSpaceStmt(str, obj);
4974                                 break;
4975
4976                         case T_CreateTrigStmt:
4977                                 _outCreateTrigStmt(str, obj);
4978                                 break;
4979
4980                         case T_DropPropertyStmt:
4981                                 _outDropPropertyStmt(str, obj);
4982                                 break;
4983
4984                         case T_DefineStmt:
4985                                 _outDefineStmt(str, obj);
4986                                 break;
4987
4988                         case T_CreateOpClassStmt:
4989                                 _outCreateOpClassStmt(str, obj);
4990                                 break;
4991
4992                         case T_CreateOpClassItem:
4993                                 _outCreateOpClassItem(str, obj);
4994                                 break;
4995
4996                         case T_RemoveOpClassStmt:
4997                                 _outRemoveOpClassStmt(str, obj);
4998                                 break;
4999
5000                         case T_DropStmt:
5001                                 _outDropStmt(str, obj);
5002                                 break;
5003
5004                         case T_FetchStmt:
5005                                 _outFetchStmt(str, obj);
5006                                 break;
5007
5008                         case T_GrantStmt:
5009                                 _outGrantStmt(str, obj);
5010                                 break;
5011
5012                         case T_PrivTarget:
5013                                 _outPrivTarget(str, obj);
5014                                 break;
5015
5016                         case T_FuncWithArgs:
5017                                 _outFuncWithArgs(str, obj);
5018                                 break;
5019
5020                         case T_FunctionParameter:
5021                                 _outFunctionParameter(str, obj);
5022                                 break;
5023
5024                         case T_PrivGrantee:
5025                                 _outPrivGrantee(str, obj);
5026                                 break;
5027
5028                         case T_GrantRoleStmt:
5029                                 _outGrantRoleStmt(str, obj);
5030                                 break;
5031
5032                         case T_CreateFunctionStmt:
5033                                 _outCreateFunctionStmt(str, obj);
5034                                 break;
5035
5036                         case T_AlterFunctionStmt:
5037                                 _outAlterFunctionStmt(str, obj);
5038                                 break;
5039
5040                         case T_RemoveFuncStmt:
5041                                 _outRemoveFuncStmt(str, obj);
5042                                 break;
5043
5044                         case T_CreateCastStmt:
5045                                 _outCreateCastStmt(str, obj);
5046                                 break;
5047
5048                         case T_DropCastStmt:
5049                                 _outDropCastStmt(str, obj);
5050                                 break;
5051
5052                         case T_ReindexStmt:
5053                                 _outReindexStmt(str, obj);
5054                                 break;
5055
5056                         case T_AlterObjectSchemaStmt:
5057                                 _outAlterObjectSchemaStmt(str, obj);
5058                                 break;
5059
5060                         case T_AlterOwnerStmt:
5061                                 _outAlterOwnerStmt(str, obj);
5062                                 break;
5063
5064                         case T_RuleStmt:
5065                                 _outRuleStmt(str, obj);
5066                                 break;
5067
5068                         case T_ViewStmt:
5069                                 _outViewStmt(str, obj);
5070                                 break;
5071
5072                         case T_CreatedbStmt:
5073                                 _outCreatedbStmt(str, obj);
5074                                 break;
5075
5076                         case T_AlterDatabaseStmt:
5077                                 _outAlterDatabaseStmt(str, obj);
5078                                 break;
5079
5080
5081                         case T_AlterDatabaseSetStmt:
5082                                 _outAlterDatabaseSetStmt(str, obj);
5083                                 break;
5084
5085                         case T_DropdbStmt:
5086                                 _outDropdbStmt(str, obj);
5087                                 break;
5088
5089                         case T_CreateDomainStmt:
5090                                 _outCreateDomainStmt(str, obj);
5091                                 break;
5092
5093                         case T_AlterDomainStmt:
5094                                 _outAlterDomainStmt(str, obj);
5095                                 break;
5096
5097                         case T_CreateConversionStmt:
5098                                 _outCreateConversionStmt(str, obj);
5099                                 break;
5100
5101                         case T_PrepareStmt:
5102                                 _outPrepareStmt(str, obj);
5103                                 break;
5104
5105                         case T_ExecuteStmt:
5106                                 _outExecuteStmt(str, obj);
5107                                 break;
5108
5109                         case T_LockStmt:
5110                                 _outLockStmt(str, obj);
5111                                 break;
5112
5113                         case T_CommentStmt:
5114                                 _outCommentStmt(str, obj);
5115                                 break;
5116
5117                         case T_RangeSubselect:
5118                                 _outRangeSubselect(str, obj);
5119                                 break;
5120
5121                         case T_RangeFunction:
5122                                 _outRangeFunction(str, obj);
5123                                 break;
5124
5125                         case T_DiscardStmt:
5126                                 _outDiscardStmt(str, obj);
5127                                 break;
5128
5129                         case T_CreateOpFamilyStmt:
5130                                 _outCreateOpFamilyStmt(str, obj);
5131                                 break;
5132
5133                         case T_AlterOpFamilyStmt:
5134                                 _outAlterOpFamilyStmt(str, obj);
5135                                 break;
5136
5137                         case T_RemoveOpFamilyStmt:
5138                                 _outRemoveOpFamilyStmt(str, obj);
5139                                 break;
5140
5141                         case T_CreateEnumStmt:
5142                                 _outCreateEnumStmt(str, obj);
5143                                 break;
5144
5145                         case T_DropOwnedStmt:
5146                                 _outDropOwnedStmt(str, obj);
5147                                 break;
5148
5149                         case T_ReassignOwnedStmt:
5150                                 _outReassignOwnedStmt(str, obj);
5151                                 break;
5152
5153                         case T_AlterTSDictionaryStmt:
5154                                 _outAlterTSDictionaryStmt(str, obj);
5155                                 break;
5156
5157                         case T_AlterTSConfigurationStmt:
5158                                 _outAlterTSConfigurationStmt(str, obj);
5159                                 break;
5160
5161                         case T_XmlExpr:
5162                                 _outXmlExpr(str, obj);
5163                                 break;
5164
5165                         case T_XmlSerialize:
5166                                 _outXmlSerialize(str, obj);
5167                                 break;
5168
5169                         case T_InhRelation:
5170                                 _outInhRelation(str, obj);
5171                                 break;
5172
5173                         case T_CurrentOfExpr:
5174                                 _outCurrentOfExpr(str, obj);
5175
5176                         default:
5177                                 break;
5178                 }
5179         }
5180 }
5181
5182
5183 /*
5184  * nodeToString -
5185  *         returns the ascii representation of the Node as a palloc'd string
5186  */
5187 char *
5188 nodeToString(void *obj)
5189 {
5190         String *str;
5191
5192         str = init_string("");
5193         _outNode(str, obj);
5194         return str->data;
5195 }