outfuncs.c 40.2 KB
Newer Older
M
 
Marc G. Fournier 已提交
1
/*
2
 * outfuncs.c
3
 *	  routines to convert a node to ascii representation
4
 *
5
 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
B
Add:  
Bruce Momjian 已提交
6
 * Portions Copyright (c) 1994, Regents of the University of California
7
 *
8
 *	$Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.150 2002/03/21 16:00:40 tgl Exp $
9 10
 *
 * NOTES
11 12 13
 *	  Every (plan) node in POSTGRES has an associated "out" routine which
 *	  knows how to create its ascii representation. These functions are
 *	  useful for debugging as well as for storing plans in the system
14
 *	  catalogs (eg. views).
15
 */
16
#include "postgres.h"
17

18 19
#include <ctype.h>

B
Bruce Momjian 已提交
20 21 22
#include "lib/stringinfo.h"
#include "nodes/nodes.h"
#include "nodes/parsenodes.h"
23 24 25
#include "nodes/plannodes.h"
#include "nodes/primnodes.h"
#include "nodes/relation.h"
26
#include "parser/parse.h"
B
Bruce Momjian 已提交
27
#include "utils/datum.h"
28

29

30 31
#define booltostr(x)  ((x) ? "true" : "false")

32
static void _outDatum(StringInfo str, Datum value, int typlen, bool typbyval);
33
static void _outNode(StringInfo str, void *obj);
34

35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
/*
 * _outToken
 *	  Convert an ordinary string (eg, an identifier) into a form that
 *	  will be decoded back to a plain token by read.c's functions.
 *
 *	  If a null or empty string is given, it is encoded as "<>".
 */
static void
_outToken(StringInfo str, char *s)
{
	if (s == NULL || *s == '\0')
	{
		appendStringInfo(str, "<>");
		return;
	}
50

51 52
	/*
	 * Look for characters or patterns that are treated specially by
53 54
	 * read.c (either in pg_strtok() or in nodeRead()), and therefore need
	 * a protective backslash.
55 56 57 58 59
	 */
	/* These characters only need to be quoted at the start of the string */
	if (*s == '<' ||
		*s == '\"' ||
		*s == '@' ||
60
		isdigit((unsigned char) *s) ||
61 62
		((*s == '+' || *s == '-') &&
		 (isdigit((unsigned char) s[1]) || s[1] == '.')))
63 64 65 66 67 68 69 70 71 72 73
		appendStringInfoChar(str, '\\');
	while (*s)
	{
		/* These chars must be backslashed anywhere in the string */
		if (*s == ' ' || *s == '\n' || *s == '\t' ||
			*s == '(' || *s == ')' || *s == '{' || *s == '}' ||
			*s == '\\')
			appendStringInfoChar(str, '\\');
		appendStringInfoChar(str, *s++);
	}
}
74

75 76
/*
 * _outIntList -
77
 *	   converts a List of integers
78
 */
79
static void
80
_outIntList(StringInfo str, List *list)
81
{
B
Bruce Momjian 已提交
82
	List	   *l;
83

84
	appendStringInfoChar(str, '(');
85
	foreach(l, list)
86 87
		appendStringInfo(str, " %d", lfirsti(l));
	appendStringInfoChar(str, ')');
88 89
}

90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
/*
 * _outOidList -
 *	   converts a List of OIDs
 */
static void
_outOidList(StringInfo str, List *list)
{
	List	   *l;

	appendStringInfoChar(str, '(');
	foreach(l, list)
		appendStringInfo(str, " %u", (Oid) lfirsti(l));
	appendStringInfoChar(str, ')');
}

105 106 107
static void
_outCreateStmt(StringInfo str, CreateStmt *node)
{
108 109
	appendStringInfo(str, " CREATE :relation ");
	_outNode(str, node->relation);
110

111
	appendStringInfo(str, "	:tableElts ");
112
	_outNode(str, node->tableElts);
M
 
Marc G. Fournier 已提交
113

114 115
	appendStringInfo(str, " :inhRelations ");
	_outNode(str, node->inhRelations);
M
 
Marc G. Fournier 已提交
116

117
	appendStringInfo(str, " :constraints ");
118
	_outNode(str, node->constraints);
119

120
	appendStringInfo(str, " :hasoids %s ",
121
					 booltostr(node->hasoids));
122
}
123 124 125 126

static void
_outIndexStmt(StringInfo str, IndexStmt *node)
{
127 128
	appendStringInfo(str, " INDEX :idxname ");
	_outToken(str, node->idxname);
129 130
	appendStringInfo(str, " :relation ");
	_outNode(str, node->relation);
131 132 133
	appendStringInfo(str, " :accessMethod ");
	_outToken(str, node->accessMethod);
	appendStringInfo(str, " :indexParams ");
134
	_outNode(str, node->indexParams);
135 136 137 138
	appendStringInfo(str, " :whereClause ");
	_outNode(str, node->whereClause);
	appendStringInfo(str, " :rangetable ");
	_outNode(str, node->rangetable);
139
	appendStringInfo(str, " :unique %s :primary %s ",
140 141
					 booltostr(node->unique),
					 booltostr(node->primary));
142
}
143

144 145 146 147 148 149 150
static void
_outNotifyStmt(StringInfo str, NotifyStmt *node)
{
	appendStringInfo(str, "NOTIFY :relation ");
	_outNode(str, node->relation);
}

151 152 153
static void
_outSelectStmt(StringInfo str, SelectStmt *node)
{
154
	/* XXX this is pretty durn incomplete */
M
 
Marc G. Fournier 已提交
155
	appendStringInfo(str, "SELECT :where ");
156 157 158 159 160 161
	_outNode(str, node->whereClause);
}

static void
_outFuncCall(StringInfo str, FuncCall *node)
{
162 163 164
	appendStringInfo(str, "FUNCTION ");
	_outToken(str, node->funcname);
	appendStringInfo(str, " :args ");
165
	_outNode(str, node->args);
166
	appendStringInfo(str, " :agg_star %s :agg_distinct %s ",
167 168
					 booltostr(node->agg_star),
					 booltostr(node->agg_distinct));
169
}
170

171 172 173
static void
_outColumnDef(StringInfo str, ColumnDef *node)
{
174 175 176
	appendStringInfo(str, " COLUMNDEF :colname ");
	_outToken(str, node->colname);
	appendStringInfo(str, " :typename ");
177
	_outNode(str, node->typename);
178 179
	appendStringInfo(str, " :is_not_null %s :raw_default ",
					 booltostr(node->is_not_null));
180
	_outNode(str, node->raw_default);
181 182 183
	appendStringInfo(str, " :cooked_default ");
	_outToken(str, node->cooked_default);
	appendStringInfo(str, " :constraints ");
184
	_outNode(str, node->constraints);
185 186 187 188 189
}

static void
_outTypeName(StringInfo str, TypeName *node)
{
190 191 192
	appendStringInfo(str, " TYPENAME :name ");
	_outToken(str, node->name);
	appendStringInfo(str, " :timezone %s :setof %s typmod %d :arrayBounds ",
193 194
					 booltostr(node->timezone),
					 booltostr(node->setof),
B
Bruce Momjian 已提交
195
					 node->typmod);
196 197
	_outNode(str, node->arrayBounds);
}
198

199 200 201 202 203 204 205 206 207
static void
_outTypeCast(StringInfo str, TypeCast *node)
{
	appendStringInfo(str, " TYPECAST :arg ");
	_outNode(str, node->arg);
	appendStringInfo(str, " :typename ");
	_outNode(str, node->typename);
}

208 209 210
static void
_outIndexElem(StringInfo str, IndexElem *node)
{
211 212 213
	appendStringInfo(str, " INDEXELEM :name ");
	_outToken(str, node->name);
	appendStringInfo(str, " :args ");
214
	_outNode(str, node->args);
215 216
	appendStringInfo(str, " :class ");
	_outToken(str, node->class);
217
}
218

219
static void
220
_outQuery(StringInfo str, Query *node)
221
{
222
	appendStringInfo(str, " QUERY :command %d :utility ", node->commandType);
223

224 225 226 227 228 229 230
	/*
	 * Hack to work around missing outfuncs routines for a lot of the
	 * utility-statement node types.  (The only one we actually *need*
	 * for rules support is NotifyStmt.)  Someday we ought to support
	 * 'em all, but for the meantime do this to avoid getting lots of
	 * warnings when running with debug_print_parse on.
	 */
231 232 233 234 235 236 237
	if (node->utilityStmt)
	{
		switch (nodeTag(node->utilityStmt))
		{
			case T_CreateStmt:
			case T_IndexStmt:
			case T_NotifyStmt:
238
				_outNode(str, node->utilityStmt);
239 240
				break;
			default:
241 242
				appendStringInfo(str, "?");
				break;
243 244
		}
	}
245
	else
246
		appendStringInfo(str, "<>");
247

248
	appendStringInfo(str, " :resultRelation %d :into ",
249
					 node->resultRelation);
250
	_outNode(str, node->into);
251

252
	appendStringInfo(str, " :isPortal %s :isBinary %s"
253
					 " :hasAggs %s :hasSubLinks %s :rtable ",
254 255 256 257
					 booltostr(node->isPortal),
					 booltostr(node->isBinary),
					 booltostr(node->hasAggs),
					 booltostr(node->hasSubLinks));
258
	_outNode(str, node->rtable);
M
 
Marc G. Fournier 已提交
259

260 261 262
	appendStringInfo(str, " :jointree ");
	_outNode(str, node->jointree);

263 264 265
	appendStringInfo(str, " :rowMarks ");
	_outIntList(str, node->rowMarks);

266 267
	appendStringInfo(str, " :targetList ");
	_outNode(str, node->targetList);
M
 
Marc G. Fournier 已提交
268

269 270
	appendStringInfo(str, " :groupClause ");
	_outNode(str, node->groupClause);
M
 
Marc G. Fournier 已提交
271

272
	appendStringInfo(str, " :havingQual ");
273
	_outNode(str, node->havingQual);
M
 
Marc G. Fournier 已提交
274

275 276
	appendStringInfo(str, " :distinctClause ");
	_outNode(str, node->distinctClause);
B
Hi!  
Bruce Momjian 已提交
277

278 279
	appendStringInfo(str, " :sortClause ");
	_outNode(str, node->sortClause);
280

B
Bruce Momjian 已提交
281 282
	appendStringInfo(str, " :limitOffset ");
	_outNode(str, node->limitOffset);
M
 
Marc G. Fournier 已提交
283

B
Bruce Momjian 已提交
284 285
	appendStringInfo(str, " :limitCount ");
	_outNode(str, node->limitCount);
286 287 288

	appendStringInfo(str, " :setOperations ");
	_outNode(str, node->setOperations);
289 290 291

	appendStringInfo(str, " :resultRelations ");
	_outIntList(str, node->resultRelations);
292 293 294
}

static void
295
_outSortClause(StringInfo str, SortClause *node)
296
{
297
	appendStringInfo(str, " SORTCLAUSE :tleSortGroupRef %u :sortop %u ",
298
					 node->tleSortGroupRef, node->sortop);
299 300 301 302 303
}

static void
_outGroupClause(StringInfo str, GroupClause *node)
{
304
	appendStringInfo(str, " GROUPCLAUSE :tleSortGroupRef %u :sortop %u ",
305
					 node->tleSortGroupRef, node->sortop);
306 307
}

308 309 310 311 312
static void
_outSetOperationStmt(StringInfo str, SetOperationStmt *node)
{
	appendStringInfo(str, " SETOPERATIONSTMT :op %d :all %s :larg ",
					 (int) node->op,
313
					 booltostr(node->all));
314 315 316 317
	_outNode(str, node->larg);
	appendStringInfo(str, " :rarg ");
	_outNode(str, node->rarg);
	appendStringInfo(str, " :colTypes ");
318
	_outOidList(str, node->colTypes);
319 320
}

321 322
/*
 * print the basic stuff of all nodes that inherit from Plan
323 324
 *
 * NOTE: we deliberately omit the execution state (EState)
325 326
 */
static void
327
_outPlanInfo(StringInfo str, Plan *node)
328
{
B
Bruce Momjian 已提交
329
	appendStringInfo(str,
330
					 ":startup_cost %.2f :total_cost %.2f :rows %.0f :width %d :qptargetlist ",
331 332
					 node->startup_cost,
					 node->total_cost,
333
					 node->plan_rows,
334
					 node->plan_width);
335
	_outNode(str, node->targetlist);
M
 
Marc G. Fournier 已提交
336

337
	appendStringInfo(str, " :qpqual ");
338
	_outNode(str, node->qual);
M
 
Marc G. Fournier 已提交
339

340
	appendStringInfo(str, " :lefttree ");
341
	_outNode(str, node->lefttree);
M
 
Marc G. Fournier 已提交
342

343
	appendStringInfo(str, " :righttree ");
344
	_outNode(str, node->righttree);
M
 
Marc G. Fournier 已提交
345

V
Vadim B. Mikheev 已提交
346 347
	appendStringInfo(str, " :extprm ");
	_outIntList(str, node->extParam);
M
 
Marc G. Fournier 已提交
348

V
Vadim B. Mikheev 已提交
349 350
	appendStringInfo(str, " :locprm ");
	_outIntList(str, node->locParam);
M
 
Marc G. Fournier 已提交
351

V
Vadim B. Mikheev 已提交
352 353
	appendStringInfo(str, " :initplan ");
	_outNode(str, node->initPlan);
M
 
Marc G. Fournier 已提交
354

M
 
Marc G. Fournier 已提交
355
	appendStringInfo(str, " :nprm %d ", node->nParamExec);
356 357 358
}

/*
359
 *	Stuff from plannodes.h
360 361
 */
static void
362
_outPlan(StringInfo str, Plan *node)
363
{
364
	appendStringInfo(str, " PLAN ");
365
	_outPlanInfo(str, (Plan *) node);
366 367 368
}

static void
369
_outResult(StringInfo str, Result *node)
370
{
371
	appendStringInfo(str, " RESULT ");
372 373
	_outPlanInfo(str, (Plan *) node);

374
	appendStringInfo(str, " :resconstantqual ");
375 376
	_outNode(str, node->resconstantqual);

377 378 379
}

/*
380
 *	Append is a subclass of Plan.
381 382
 */
static void
B
Bruce Momjian 已提交
383
_outAppend(StringInfo str, Append *node)
384
{
385
	appendStringInfo(str, " APPEND ");
386 387
	_outPlanInfo(str, (Plan *) node);

388 389
	appendStringInfo(str, " :appendplans ");
	_outNode(str, node->appendplans);
390

391
	appendStringInfo(str, " :isTarget %s ",
392
					 booltostr(node->isTarget));
393 394 395
}

/*
396
 *	Join is a subclass of Plan
397 398
 */
static void
399
_outJoin(StringInfo str, Join *node)
400
{
401
	appendStringInfo(str, " JOIN ");
402
	_outPlanInfo(str, (Plan *) node);
403 404 405
	appendStringInfo(str, " :jointype %d :joinqual ",
					 (int) node->jointype);
	_outNode(str, node->joinqual);
406 407
	appendStringInfo(str, " :joinrti %d ",
					 node->joinrti);
408 409 410
}

/*
411
 *	NestLoop is a subclass of Join
412 413
 */
static void
414
_outNestLoop(StringInfo str, NestLoop *node)
415
{
416
	appendStringInfo(str, " NESTLOOP ");
417
	_outPlanInfo(str, (Plan *) node);
418 419 420
	appendStringInfo(str, " :jointype %d :joinqual ",
					 (int) node->join.jointype);
	_outNode(str, node->join.joinqual);
421 422
	appendStringInfo(str, " :joinrti %d ",
					 node->join.joinrti);
423 424 425
}

/*
426
 *	MergeJoin is a subclass of Join
427 428
 */
static void
429
_outMergeJoin(StringInfo str, MergeJoin *node)
430
{
431
	appendStringInfo(str, " MERGEJOIN ");
432
	_outPlanInfo(str, (Plan *) node);
433 434 435
	appendStringInfo(str, " :jointype %d :joinqual ",
					 (int) node->join.jointype);
	_outNode(str, node->join.joinqual);
436 437
	appendStringInfo(str, " :joinrti %d ",
					 node->join.joinrti);
438

439
	appendStringInfo(str, " :mergeclauses ");
440
	_outNode(str, node->mergeclauses);
441 442 443
}

/*
444
 *	HashJoin is a subclass of Join.
445 446
 */
static void
447
_outHashJoin(StringInfo str, HashJoin *node)
448
{
449
	appendStringInfo(str, " HASHJOIN ");
450
	_outPlanInfo(str, (Plan *) node);
451 452 453
	appendStringInfo(str, " :jointype %d :joinqual ",
					 (int) node->join.jointype);
	_outNode(str, node->join.joinqual);
454 455
	appendStringInfo(str, " :joinrti %d ",
					 node->join.joinrti);
456

457
	appendStringInfo(str, " :hashclauses ");
458
	_outNode(str, node->hashclauses);
459
	appendStringInfo(str, " :hashjoinop %u ",
B
Bruce Momjian 已提交
460
					 node->hashjoinop);
461 462
}

V
Vadim B. Mikheev 已提交
463 464 465
static void
_outSubPlan(StringInfo str, SubPlan *node)
{
M
 
Marc G. Fournier 已提交
466
	appendStringInfo(str, " SUBPLAN :plan ");
V
Vadim B. Mikheev 已提交
467
	_outNode(str, node->plan);
M
 
Marc G. Fournier 已提交
468

469
	appendStringInfo(str, " :planid %d :rtable ", node->plan_id);
V
Vadim B. Mikheev 已提交
470
	_outNode(str, node->rtable);
M
 
Marc G. Fournier 已提交
471

V
Vadim B. Mikheev 已提交
472
	appendStringInfo(str, " :setprm ");
473
	_outIntList(str, node->setParam);
M
 
Marc G. Fournier 已提交
474

V
Vadim B. Mikheev 已提交
475
	appendStringInfo(str, " :parprm ");
476
	_outIntList(str, node->parParam);
M
 
Marc G. Fournier 已提交
477

V
Vadim B. Mikheev 已提交
478 479 480 481
	appendStringInfo(str, " :slink ");
	_outNode(str, node->sublink);
}

482
/*
483
 *	Scan is a subclass of Node
484 485
 */
static void
486
_outScan(StringInfo str, Scan *node)
487
{
488
	appendStringInfo(str, " SCAN ");
489 490
	_outPlanInfo(str, (Plan *) node);

491
	appendStringInfo(str, " :scanrelid %u ", node->scanrelid);
492 493 494
}

/*
495
 *	SeqScan is a subclass of Scan
496 497
 */
static void
498
_outSeqScan(StringInfo str, SeqScan *node)
499
{
500
	appendStringInfo(str, " SEQSCAN ");
501 502
	_outPlanInfo(str, (Plan *) node);

503
	appendStringInfo(str, " :scanrelid %u ", node->scanrelid);
504 505 506
}

/*
507
 *	IndexScan is a subclass of Scan
508 509
 */
static void
510
_outIndexScan(StringInfo str, IndexScan *node)
511
{
512
	appendStringInfo(str, " INDEXSCAN ");
513 514
	_outPlanInfo(str, (Plan *) node);

515
	appendStringInfo(str, " :scanrelid %u :indxid ", node->scan.scanrelid);
516
	_outOidList(str, node->indxid);
517

518
	appendStringInfo(str, " :indxqual ");
519 520
	_outNode(str, node->indxqual);

V
Vadim B. Mikheev 已提交
521 522 523
	appendStringInfo(str, " :indxqualorig ");
	_outNode(str, node->indxqualorig);

524
	appendStringInfo(str, " :indxorderdir %d ", node->indxorderdir);
525 526
}

527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543
/*
 *	TidScan is a subclass of Scan
 */
static void
_outTidScan(StringInfo str, TidScan *node)
{
	appendStringInfo(str, " TIDSCAN ");
	_outPlanInfo(str, (Plan *) node);

	appendStringInfo(str, " :scanrelid %u ", node->scan.scanrelid);
	appendStringInfo(str, " :needrescan %d ", node->needRescan);

	appendStringInfo(str, " :tideval ");
	_outNode(str, node->tideval);

}

544 545 546 547 548 549 550 551 552 553 554 555 556
/*
 *	SubqueryScan is a subclass of Scan
 */
static void
_outSubqueryScan(StringInfo str, SubqueryScan *node)
{
	appendStringInfo(str, " SUBQUERYSCAN ");
	_outPlanInfo(str, (Plan *) node);

	appendStringInfo(str, " :scanrelid %u :subplan ", node->scan.scanrelid);
	_outNode(str, node->subplan);
}

557
/*
558
 *	Material is a subclass of Plan
559 560 561 562 563 564 565 566
 */
static void
_outMaterial(StringInfo str, Material *node)
{
	appendStringInfo(str, " MATERIAL ");
	_outPlanInfo(str, (Plan *) node);
}

567
/*
568
 *	Sort is a subclass of Plan
569 570
 */
static void
571
_outSort(StringInfo str, Sort *node)
572
{
573
	appendStringInfo(str, " SORT ");
574
	_outPlanInfo(str, (Plan *) node);
575
	appendStringInfo(str, " :keycount %d ", node->keycount);
576 577 578
}

static void
B
Bruce Momjian 已提交
579
_outAgg(StringInfo str, Agg *node)
580
{
581
	appendStringInfo(str, " AGG ");
582
	_outPlanInfo(str, (Plan *) node);
583 584 585
}

static void
586
_outGroup(StringInfo str, Group *node)
587
{
588
	appendStringInfo(str, " GRP ");
589 590 591
	_outPlanInfo(str, (Plan *) node);

	/* the actual Group fields */
M
 
Marc G. Fournier 已提交
592
	appendStringInfo(str, " :numCols %d :tuplePerGroup %s ",
B
Bruce Momjian 已提交
593
					 node->numCols,
594
					 booltostr(node->tuplePerGroup));
595
}
596

597
static void
598
_outUnique(StringInfo str, Unique *node)
599
{
B
Bruce Momjian 已提交
600
	int			i;
601

602
	appendStringInfo(str, " UNIQUE ");
603 604
	_outPlanInfo(str, (Plan *) node);

605
	appendStringInfo(str, " :numCols %d :uniqColIdx ",
606
					 node->numCols);
607 608 609
	for (i = 0; i < node->numCols; i++)
		appendStringInfo(str, "%d ", (int) node->uniqColIdx[i]);
}
610

611 612 613
static void
_outSetOp(StringInfo str, SetOp *node)
{
B
Bruce Momjian 已提交
614
	int			i;
615 616 617 618 619 620 621 622 623 624 625 626

	appendStringInfo(str, " SETOP ");
	_outPlanInfo(str, (Plan *) node);

	appendStringInfo(str, " :cmd %d :numCols %d :dupColIdx ",
					 (int) node->cmd, node->numCols);
	for (i = 0; i < node->numCols; i++)
		appendStringInfo(str, "%d ", (int) node->dupColIdx[i]);
	appendStringInfo(str, " :flagColIdx %d ",
					 (int) node->flagColIdx);
}

627 628 629 630 631 632 633 634 635 636 637 638
static void
_outLimit(StringInfo str, Limit *node)
{
	appendStringInfo(str, " LIMIT ");
	_outPlanInfo(str, (Plan *) node);

	appendStringInfo(str, " :limitOffset ");
	_outNode(str, node->limitOffset);
	appendStringInfo(str, " :limitCount ");
	_outNode(str, node->limitCount);
}

639
/*
640
 *	Hash is a subclass of Plan
641 642
 */
static void
643
_outHash(StringInfo str, Hash *node)
644
{
645
	appendStringInfo(str, " HASH ");
646 647
	_outPlanInfo(str, (Plan *) node);

648
	appendStringInfo(str, " :hashkey ");
649
	_outNode(str, node->hashkey);
650 651 652 653
}

/*****************************************************************************
 *
654
 *	Stuff from primnodes.h.
655 656 657 658
 *
 *****************************************************************************/

/*
659
 *	Resdom is a subclass of Node
660 661
 */
static void
662
_outResdom(StringInfo str, Resdom *node)
663
{
664
	appendStringInfo(str,
665
				 " RESDOM :resno %d :restype %u :restypmod %d :resname ",
B
Bruce Momjian 已提交
666 667 668
					 node->resno,
					 node->restype,
					 node->restypmod);
669
	_outToken(str, node->resname);
670
	appendStringInfo(str, " :reskey %u :reskeyop %u :ressortgroupref %u :resjunk %s ",
B
Bruce Momjian 已提交
671
					 node->reskey,
672
					 node->reskeyop,
673
					 node->ressortgroupref,
674
					 booltostr(node->resjunk));
675 676 677
}

static void
678
_outFjoin(StringInfo str, Fjoin *node)
679
{
680
	int			i;
681

M
 
Marc G. Fournier 已提交
682
	appendStringInfo(str, " FJOIN :initialized %s :nNodes %d ",
683
					 booltostr(node->fj_initialized),
B
Bruce Momjian 已提交
684
					 node->fj_nNodes);
685 686 687 688

	appendStringInfo(str, " :innerNode ");
	_outNode(str, node->fj_innerNode);

689 690
	appendStringInfo(str, " :results @ 0x%p :alwaysdone",
					 node->fj_results);
691 692

	for (i = 0; i < node->fj_nNodes; i++)
693 694
		appendStringInfo(str,
						 booltostr(node->fj_alwaysDone[i]));
695 696 697
}

/*
698
 *	Expr is a subclass of Node
699 700
 */
static void
701
_outExpr(StringInfo str, Expr *node)
702
{
703
	char	   *opstr = NULL;
704

M
 
Marc G. Fournier 已提交
705
	appendStringInfo(str, " EXPR :typeOid %u ",
B
Bruce Momjian 已提交
706
					 node->typeOid);
707 708 709

	switch (node->opType)
	{
710 711 712 713 714 715 716 717 718 719 720 721 722 723 724
		case OP_EXPR:
			opstr = "op";
			break;
		case FUNC_EXPR:
			opstr = "func";
			break;
		case OR_EXPR:
			opstr = "or";
			break;
		case AND_EXPR:
			opstr = "and";
			break;
		case NOT_EXPR:
			opstr = "not";
			break;
V
Vadim B. Mikheev 已提交
725 726 727
		case SUBPLAN_EXPR:
			opstr = "subp";
			break;
728
	}
729 730 731
	appendStringInfo(str, " :opType ");
	_outToken(str, opstr);
	appendStringInfo(str, " :oper ");
732
	_outNode(str, node->oper);
M
 
Marc G. Fournier 已提交
733

734
	appendStringInfo(str, " :args ");
735
	_outNode(str, node->args);
736 737 738
}

/*
739
 *	Var is a subclass of Expr
740 741
 */
static void
742
_outVar(StringInfo str, Var *node)
743
{
B
Bruce Momjian 已提交
744
	appendStringInfo(str,
745
				" VAR :varno %u :varattno %d :vartype %u :vartypmod %d ",
B
Bruce Momjian 已提交
746 747 748 749
					 node->varno,
					 node->varattno,
					 node->vartype,
					 node->vartypmod);
M
 
Marc G. Fournier 已提交
750

751
	appendStringInfo(str, " :varlevelsup %u :varnoold %u :varoattno %d",
B
Bruce Momjian 已提交
752 753 754
					 node->varlevelsup,
					 node->varnoold,
					 node->varoattno);
755 756 757
}

/*
758
 *	Const is a subclass of Expr
759 760
 */
static void
761
_outConst(StringInfo str, Const *node)
762
{
B
Bruce Momjian 已提交
763
	appendStringInfo(str,
764 765
					 " CONST :consttype %u :constlen %d :constbyval %s"
					 " :constisnull %s :constvalue ",
B
Bruce Momjian 已提交
766 767
					 node->consttype,
					 node->constlen,
768 769
					 booltostr(node->constbyval),
					 booltostr(node->constisnull));
M
 
Marc G. Fournier 已提交
770

771
	if (node->constisnull)
B
Bruce Momjian 已提交
772
		appendStringInfo(str, "<>");
773
	else
774
		_outDatum(str, node->constvalue, node->constlen, node->constbyval);
775 776 777
}

/*
B
Bruce Momjian 已提交
778
 *	Aggref
779 780
 */
static void
781
_outAggref(StringInfo str, Aggref *node)
782
{
783 784 785
	appendStringInfo(str, " AGGREG :aggname ");
	_outToken(str, node->aggname);
	appendStringInfo(str, " :basetype %u :aggtype %u :target ",
786
					 node->basetype, node->aggtype);
787
	_outNode(str, node->target);
M
 
Marc G. Fournier 已提交
788

789
	appendStringInfo(str, " :aggstar %s :aggdistinct %s ",
790 791
					 booltostr(node->aggstar),
					 booltostr(node->aggdistinct));
792
	/* aggno is not dumped */
793 794
}

795 796 797 798 799 800
/*
 *	SubLink
 */
static void
_outSubLink(StringInfo str, SubLink *node)
{
B
Bruce Momjian 已提交
801 802 803
	appendStringInfo(str,
					 " SUBLINK :subLinkType %d :useor %s :lefthand ",
					 node->subLinkType,
804
					 booltostr(node->useor));
805
	_outNode(str, node->lefthand);
M
 
Marc G. Fournier 已提交
806

807
	appendStringInfo(str, " :oper ");
B
Bruce Momjian 已提交
808
	_outNode(str, node->oper);
M
 
Marc G. Fournier 已提交
809

810 811 812 813
	appendStringInfo(str, " :subselect ");
	_outNode(str, node->subselect);
}

814
/*
815
 *	ArrayRef is a subclass of Expr
816 817
 */
static void
B
Bruce Momjian 已提交
818
_outArrayRef(StringInfo str, ArrayRef *node)
819
{
B
Bruce Momjian 已提交
820
	appendStringInfo(str,
T
Tom Lane 已提交
821
		" ARRAYREF :refelemtype %u :refattrlength %d :refelemlength %d ",
B
Bruce Momjian 已提交
822 823 824
					 node->refelemtype,
					 node->refattrlength,
					 node->refelemlength);
M
 
Marc G. Fournier 已提交
825

B
Bruce Momjian 已提交
826 827
	appendStringInfo(str, " :refelembyval %c :refupperindex ",
					 node->refelembyval ? 't' : 'f');
828 829
	_outNode(str, node->refupperindexpr);

830
	appendStringInfo(str, " :reflowerindex ");
831 832
	_outNode(str, node->reflowerindexpr);

833
	appendStringInfo(str, " :refexpr ");
834 835
	_outNode(str, node->refexpr);

836
	appendStringInfo(str, " :refassgnexpr ");
837
	_outNode(str, node->refassgnexpr);
838 839 840
}

/*
841
 *	Func is a subclass of Expr
842 843
 */
static void
844
_outFunc(StringInfo str, Func *node)
845
{
846
	appendStringInfo(str, " FUNC :funcid %u :functype %u ",
B
Bruce Momjian 已提交
847
					 node->funcid,
848
					 node->functype);
849 850 851
}

/*
852
 *	Oper is a subclass of Expr
853 854
 */
static void
855
_outOper(StringInfo str, Oper *node)
856
{
B
Bruce Momjian 已提交
857 858 859 860 861
	appendStringInfo(str,
					 " OPER :opno %u :opid %u :opresulttype %u ",
					 node->opno,
					 node->opid,
					 node->opresulttype);
862 863 864
}

/*
865
 *	Param is a subclass of Expr
866 867
 */
static void
868
_outParam(StringInfo str, Param *node)
869
{
870
	appendStringInfo(str, " PARAM :paramkind %d :paramid %d :paramname ",
B
Bruce Momjian 已提交
871
					 node->paramkind,
872 873
					 node->paramid);
	_outToken(str, node->paramname);
874
	appendStringInfo(str, " :paramtype %u ", node->paramtype);
875 876
}

877 878 879 880 881 882 883 884 885 886
/*
 *	FieldSelect
 */
static void
_outFieldSelect(StringInfo str, FieldSelect *node)
{
	appendStringInfo(str, " FIELDSELECT :arg ");
	_outNode(str, node->arg);

	appendStringInfo(str, " :fieldnum %d :resulttype %u :resulttypmod %d ",
B
Bruce Momjian 已提交
887
				   node->fieldnum, node->resulttype, node->resulttypmod);
888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912
}

/*
 *	RelabelType
 */
static void
_outRelabelType(StringInfo str, RelabelType *node)
{
	appendStringInfo(str, " RELABELTYPE :arg ");
	_outNode(str, node->arg);

	appendStringInfo(str, " :resulttype %u :resulttypmod %d ",
					 node->resulttype, node->resulttypmod);
}

/*
 *	RangeTblRef
 */
static void
_outRangeTblRef(StringInfo str, RangeTblRef *node)
{
	appendStringInfo(str, " RANGETBLREF %d ",
					 node->rtindex);
}

913 914 915 916 917 918 919 920 921 922 923 924
/*
 *	FromExpr
 */
static void
_outFromExpr(StringInfo str, FromExpr *node)
{
	appendStringInfo(str, " FROMEXPR :fromlist ");
	_outNode(str, node->fromlist);
	appendStringInfo(str, " :quals ");
	_outNode(str, node->quals);
}

925 926 927 928 929 930 931 932
/*
 *	JoinExpr
 */
static void
_outJoinExpr(StringInfo str, JoinExpr *node)
{
	appendStringInfo(str, " JOINEXPR :jointype %d :isNatural %s :larg ",
					 (int) node->jointype,
933
					 booltostr(node->isNatural));
934 935 936 937 938 939 940 941 942
	_outNode(str, node->larg);
	appendStringInfo(str, " :rarg ");
	_outNode(str, node->rarg);
	appendStringInfo(str, " :using ");
	_outNode(str, node->using);
	appendStringInfo(str, " :quals ");
	_outNode(str, node->quals);
	appendStringInfo(str, " :alias ");
	_outNode(str, node->alias);
943
	appendStringInfo(str, " :rtindex %d ", node->rtindex);
944 945
}

946
/*
947
 *	TargetEntry is a subclass of Node.
948 949
 */
static void
950
_outTargetEntry(StringInfo str, TargetEntry *node)
951
{
M
 
Marc G. Fournier 已提交
952
	appendStringInfo(str, " TARGETENTRY :resdom ");
953 954
	_outNode(str, node->resdom);

955 956
	appendStringInfo(str, " :expr ");
	_outNode(str, node->expr);
957
}
958

959 960 961 962 963 964 965 966 967
static void
_outAlias(StringInfo str, Alias *node)
{
	appendStringInfo(str, " ALIAS :aliasname ");
	_outToken(str, node->aliasname);
	appendStringInfo(str, " :colnames ");
	_outNode(str, node->colnames);
}

968
static void
969
_outRangeTblEntry(StringInfo str, RangeTblEntry *node)
970
{
971 972
	appendStringInfo(str, " RTE :rtekind %d :relname ",
					 (int) node->rtekind);
973
	_outToken(str, node->relname);
974
	appendStringInfo(str, " :relid %u :subquery ",
975
					 node->relid);
976
	_outNode(str, node->subquery);
977 978 979 980 981 982 983 984 985
	appendStringInfo(str, " :jointype %d :joincoltypes ",
					 (int) node->jointype);
	_outOidList(str, node->joincoltypes);
	appendStringInfo(str, " :joincoltypmods ");
	_outIntList(str, node->joincoltypmods);
	appendStringInfo(str, " :joinleftcols ");
	_outIntList(str, node->joinleftcols);
	appendStringInfo(str, " :joinrightcols ");
	_outIntList(str, node->joinrightcols);
986
	appendStringInfo(str, " :alias ");
987 988 989
	_outNode(str, node->alias);
	appendStringInfo(str, " :eref ");
	_outNode(str, node->eref);
990 991
	appendStringInfo(str, " :inh %s :inFromCl %s :checkForRead %s"
					 " :checkForWrite %s :checkAsUser %u",
992 993 994 995
					 booltostr(node->inh),
					 booltostr(node->inFromCl),
					 booltostr(node->checkForRead),
					 booltostr(node->checkForWrite),
996
					 node->checkAsUser);
997 998
}

999
/*
1000
 *	Path is a subclass of Node.
1001 1002
 */
static void
1003
_outPath(StringInfo str, Path *node)
1004
{
1005
	appendStringInfo(str,
1006
	 " PATH :pathtype %d :startup_cost %.2f :total_cost %.2f :pathkeys ",
B
Bruce Momjian 已提交
1007
					 node->pathtype,
1008 1009
					 node->startup_cost,
					 node->total_cost);
1010
	_outNode(str, node->pathkeys);
1011 1012 1013
}

/*
1014
 *	IndexPath is a subclass of Path.
1015 1016
 */
static void
1017
_outIndexPath(StringInfo str, IndexPath *node)
1018
{
B
Bruce Momjian 已提交
1019
	appendStringInfo(str,
1020
					 " INDEXPATH :pathtype %d :startup_cost %.2f :total_cost %.2f :pathkeys ",
B
Bruce Momjian 已提交
1021
					 node->path.pathtype,
1022 1023
					 node->path.startup_cost,
					 node->path.total_cost);
1024
	_outNode(str, node->path.pathkeys);
1025

1026 1027
	appendStringInfo(str, " :indexinfo ");
	_outNode(str, node->indexinfo);
1028

1029
	appendStringInfo(str, " :indexqual ");
1030
	_outNode(str, node->indexqual);
1031

1032 1033
	appendStringInfo(str, " :indexscandir %d :joinrelids ",
					 (int) node->indexscandir);
1034
	_outIntList(str, node->joinrelids);
1035

1036
	appendStringInfo(str, " :alljoinquals %s :rows %.2f ",
1037
					 booltostr(node->alljoinquals),
1038
					 node->rows);
1039 1040
}

1041 1042 1043 1044 1045 1046 1047
/*
 *	TidPath is a subclass of Path.
 */
static void
_outTidPath(StringInfo str, TidPath *node)
{
	appendStringInfo(str,
1048
					 " TIDPATH :pathtype %d :startup_cost %.2f :total_cost %.2f :pathkeys ",
1049
					 node->path.pathtype,
1050 1051
					 node->path.startup_cost,
					 node->path.total_cost);
1052 1053 1054 1055 1056
	_outNode(str, node->path.pathkeys);

	appendStringInfo(str, " :tideval ");
	_outNode(str, node->tideval);

1057
	appendStringInfo(str, " :unjoined_relids ");
1058 1059 1060
	_outIntList(str, node->unjoined_relids);
}

1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077
/*
 *	AppendPath is a subclass of Path.
 */
static void
_outAppendPath(StringInfo str, AppendPath *node)
{
	appendStringInfo(str,
					 " APPENDPATH :pathtype %d :startup_cost %.2f :total_cost %.2f :pathkeys ",
					 node->path.pathtype,
					 node->path.startup_cost,
					 node->path.total_cost);
	_outNode(str, node->path.pathkeys);

	appendStringInfo(str, " :subpaths ");
	_outNode(str, node->subpaths);
}

1078
/*
1079
 *	NestPath is a subclass of Path
1080 1081
 */
static void
1082
_outNestPath(StringInfo str, NestPath *node)
1083
{
B
Bruce Momjian 已提交
1084
	appendStringInfo(str,
1085
					 " NESTPATH :pathtype %d :startup_cost %.2f :total_cost %.2f :pathkeys ",
B
Bruce Momjian 已提交
1086
					 node->path.pathtype,
1087 1088
					 node->path.startup_cost,
					 node->path.total_cost);
1089
	_outNode(str, node->path.pathkeys);
1090 1091
	appendStringInfo(str, " :jointype %d :outerjoinpath ",
					 (int) node->jointype);
1092 1093 1094 1095 1096
	_outNode(str, node->outerjoinpath);
	appendStringInfo(str, " :innerjoinpath ");
	_outNode(str, node->innerjoinpath);
	appendStringInfo(str, " :joinrestrictinfo ");
	_outNode(str, node->joinrestrictinfo);
1097 1098 1099
}

/*
1100
 *	MergePath is a subclass of NestPath.
1101 1102
 */
static void
1103
_outMergePath(StringInfo str, MergePath *node)
1104
{
B
Bruce Momjian 已提交
1105
	appendStringInfo(str,
1106
					 " MERGEPATH :pathtype %d :startup_cost %.2f :total_cost %.2f :pathkeys ",
B
Bruce Momjian 已提交
1107
					 node->jpath.path.pathtype,
1108 1109
					 node->jpath.path.startup_cost,
					 node->jpath.path.total_cost);
1110
	_outNode(str, node->jpath.path.pathkeys);
1111 1112
	appendStringInfo(str, " :jointype %d :outerjoinpath ",
					 (int) node->jpath.jointype);
1113 1114 1115 1116 1117
	_outNode(str, node->jpath.outerjoinpath);
	appendStringInfo(str, " :innerjoinpath ");
	_outNode(str, node->jpath.innerjoinpath);
	appendStringInfo(str, " :joinrestrictinfo ");
	_outNode(str, node->jpath.joinrestrictinfo);
1118

1119
	appendStringInfo(str, " :path_mergeclauses ");
1120 1121
	_outNode(str, node->path_mergeclauses);

1122
	appendStringInfo(str, " :outersortkeys ");
1123 1124
	_outNode(str, node->outersortkeys);

1125
	appendStringInfo(str, " :innersortkeys ");
1126
	_outNode(str, node->innersortkeys);
1127 1128 1129
}

/*
1130
 *	HashPath is a subclass of NestPath.
1131 1132
 */
static void
1133
_outHashPath(StringInfo str, HashPath *node)
1134
{
B
Bruce Momjian 已提交
1135
	appendStringInfo(str,
1136
					 " HASHPATH :pathtype %d :startup_cost %.2f :total_cost %.2f :pathkeys ",
B
Bruce Momjian 已提交
1137
					 node->jpath.path.pathtype,
1138 1139
					 node->jpath.path.startup_cost,
					 node->jpath.path.total_cost);
1140
	_outNode(str, node->jpath.path.pathkeys);
1141 1142
	appendStringInfo(str, " :jointype %d :outerjoinpath ",
					 (int) node->jpath.jointype);
1143 1144 1145 1146 1147
	_outNode(str, node->jpath.outerjoinpath);
	appendStringInfo(str, " :innerjoinpath ");
	_outNode(str, node->jpath.innerjoinpath);
	appendStringInfo(str, " :joinrestrictinfo ");
	_outNode(str, node->jpath.joinrestrictinfo);
1148

1149
	appendStringInfo(str, " :path_hashclauses ");
1150
	_outNode(str, node->path_hashclauses);
1151 1152 1153
}

/*
1154
 *	PathKeyItem is a subclass of Node.
1155 1156
 */
static void
1157
_outPathKeyItem(StringInfo str, PathKeyItem *node)
1158
{
1159 1160 1161
	appendStringInfo(str, " PATHKEYITEM :sortop %u :key ",
					 node->sortop);
	_outNode(str, node->key);
1162 1163 1164
}

/*
1165
 *	RestrictInfo is a subclass of Node.
1166 1167
 */
static void
1168
_outRestrictInfo(StringInfo str, RestrictInfo *node)
1169
{
B
Bruce Momjian 已提交
1170
	appendStringInfo(str, " RESTRICTINFO :clause ");
1171 1172
	_outNode(str, node->clause);

1173
	appendStringInfo(str, " :ispusheddown %s :subclauseindices ",
1174
					 booltostr(node->ispusheddown));
1175
	_outNode(str, node->subclauseindices);
1176

1177 1178 1179
	appendStringInfo(str, " :mergejoinoperator %u ", node->mergejoinoperator);
	appendStringInfo(str, " :left_sortop %u ", node->left_sortop);
	appendStringInfo(str, " :right_sortop %u ", node->right_sortop);
M
 
Marc G. Fournier 已提交
1180
	appendStringInfo(str, " :hashjoinoperator %u ", node->hashjoinoperator);
1181 1182 1183
}

/*
1184
 *	JoinInfo is a subclass of Node.
1185 1186
 */
static void
1187
_outJoinInfo(StringInfo str, JoinInfo *node)
1188
{
B
Bruce Momjian 已提交
1189 1190
	appendStringInfo(str, " JINFO :unjoined_relids ");
	_outIntList(str, node->unjoined_relids);
1191

1192 1193
	appendStringInfo(str, " :jinfo_restrictinfo ");
	_outNode(str, node->jinfo_restrictinfo);
1194 1195 1196 1197 1198 1199
}

/*
 * Print the value of a Datum given its type.
 */
static void
1200
_outDatum(StringInfo str, Datum value, int typlen, bool typbyval)
1201
{
1202 1203
	Size		length,
				i;
1204
	char	   *s;
1205

1206
	length = datumGetSize(value, typbyval, typlen);
1207

1208
	if (typbyval)
1209 1210
	{
		s = (char *) (&value);
1211
		appendStringInfo(str, " %u [ ", (unsigned int) length);
1212
		for (i = 0; i < (Size) sizeof(Datum); i++)
1213
			appendStringInfo(str, "%d ", (int) (s[i]));
M
 
Marc G. Fournier 已提交
1214
		appendStringInfo(str, "] ");
1215
	}
1216
	else
1217
	{
1218 1219
		s = (char *) DatumGetPointer(value);
		if (!PointerIsValid(s))
M
 
Marc G. Fournier 已提交
1220
			appendStringInfo(str, " 0 [ ] ");
1221 1222
		else
		{
1223
			appendStringInfo(str, " %u [ ", (unsigned int) length);
1224
			for (i = 0; i < length; i++)
1225
				appendStringInfo(str, "%d ", (int) (s[i]));
M
 
Marc G. Fournier 已提交
1226
			appendStringInfo(str, "] ");
1227
		}
1228 1229 1230 1231
	}
}

static void
1232
_outIter(StringInfo str, Iter *node)
1233
{
M
 
Marc G. Fournier 已提交
1234
	appendStringInfo(str, " ITER :iterexpr ");
1235
	_outNode(str, node->iterexpr);
1236 1237 1238
}

static void
1239
_outStream(StringInfo str, Stream *node)
1240
{
B
Bruce Momjian 已提交
1241
	appendStringInfo(str,
B
Bruce Momjian 已提交
1242
	  " STREAM :pathptr @ %p :cinfo @ %p :clausetype %p :upstream @ %p ",
1243 1244 1245 1246
					 node->pathptr,
					 node->cinfo,
					 node->clausetype,
					 node->upstream);
1247

B
Bruce Momjian 已提交
1248
	appendStringInfo(str,
B
Bruce Momjian 已提交
1249
			 " :downstream @ %p :groupup %d :groupcost %f :groupsel %f ",
1250
					 node->downstream,
B
Bruce Momjian 已提交
1251 1252 1253
					 node->groupup,
					 node->groupcost,
					 node->groupsel);
1254
}
1255

1256 1257 1258
static void
_outAExpr(StringInfo str, A_Expr *node)
{
1259
	appendStringInfo(str, " AEXPR ");
1260 1261 1262
	switch (node->oper)
	{
		case AND:
1263
			appendStringInfo(str, "AND ");
1264 1265
			break;
		case OR:
1266
			appendStringInfo(str, "OR ");
1267 1268
			break;
		case NOT:
1269
			appendStringInfo(str, "NOT ");
1270
			break;
1271
		case OP:
1272 1273
			_outToken(str, node->opname);
			appendStringInfo(str, " ");
1274
			break;
1275 1276 1277
		default:
			appendStringInfo(str, "?? ");
			break;
1278
	}
1279
	_outNode(str, node->lexpr);
1280
	appendStringInfo(str, " ");
1281 1282 1283
	_outNode(str, node->rexpr);
}

1284
static void
1285
_outValue(StringInfo str, Value *value)
1286
{
1287 1288
	switch (value->type)
	{
1289
		case T_Integer:
1290
			appendStringInfo(str, " %ld ", value->val.ival);
1291 1292
			break;
		case T_Float:
1293 1294 1295 1296

			/*
			 * We assume the value is a valid numeric literal and so does
			 * not need quoting.
1297 1298 1299 1300 1301 1302 1303
			 */
			appendStringInfo(str, " %s ", value->val.str);
			break;
		case T_String:
			appendStringInfo(str, " \"");
			_outToken(str, value->val.str);
			appendStringInfo(str, "\" ");
1304
			break;
1305
		case T_BitString:
1306 1307
			/* internal representation already has leading 'b' */
			appendStringInfo(str, " %s ", value->val.str);
1308
			break;
1309
		default:
B
Bruce Momjian 已提交
1310
			elog(WARNING, "_outValue: don't know how to print type %d ",
1311
				 value->type);
1312
			break;
1313
	}
1314 1315
}

1316
static void
1317
_outRangeVar(StringInfo str, RangeVar *node)
1318
{
1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331
	appendStringInfo(str, " RANGEVAR :relation ");
	/*
	 * we deliberately ignore catalogname here, since it is presently not
	 * semantically meaningful
	 */
	_outToken(str, node->schemaname);
	appendStringInfo(str, " . ");
	_outToken(str, node->relname);
	appendStringInfo(str, " :inhopt %d :istemp %s",
					(int) node->inhOpt,
					booltostr(node->istemp));
	appendStringInfo(str, " :alias ");
	_outNode(str, node->alias);
1332 1333
}

1334
static void
1335
_outColumnRef(StringInfo str, ColumnRef *node)
1336
{
1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356
	appendStringInfo(str, " COLUMNREF :fields ");
	_outNode(str, node->fields);
	appendStringInfo(str, " :indirection ");
	_outNode(str, node->indirection);
}

static void
_outParamRef(StringInfo str, ParamRef *node)
{
	appendStringInfo(str, " PARAMREF :number %d :fields ", node->number);
	_outNode(str, node->fields);
	appendStringInfo(str, " :indirection ");
	_outNode(str, node->indirection);
}

static void
_outIdent(StringInfo str, Ident *node)
{
	appendStringInfo(str, " IDENT ");
	_outToken(str, node->name);
1357 1358
}

1359 1360 1361
static void
_outAConst(StringInfo str, A_Const *node)
{
1362
	appendStringInfo(str, "CONST ");
1363
	_outValue(str, &(node->val));
1364 1365
	appendStringInfo(str, " :typename ");
	_outNode(str, node->typename);
1366 1367
}

1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378
static void
_outExprFieldSelect(StringInfo str, ExprFieldSelect *node)
{
	appendStringInfo(str, " EXPRFIELDSELECT :arg ");
	_outNode(str, node->arg);
	appendStringInfo(str, " :fields ");
	_outNode(str, node->fields);
	appendStringInfo(str, " :indirection ");
	_outNode(str, node->indirection);
}

T
Thomas G. Lockhart 已提交
1379 1380 1381
static void
_outConstraint(StringInfo str, Constraint *node)
{
1382
	appendStringInfo(str, " CONSTRAINT :name ");
1383 1384
	_outToken(str, node->name);
	appendStringInfo(str, " :type ");
T
Thomas G. Lockhart 已提交
1385 1386 1387 1388

	switch (node->contype)
	{
		case CONSTR_PRIMARY:
1389
			appendStringInfo(str, "PRIMARY_KEY :keys ");
T
Thomas G. Lockhart 已提交
1390 1391 1392 1393
			_outNode(str, node->keys);
			break;

		case CONSTR_CHECK:
1394
			appendStringInfo(str, "CHECK :raw ");
1395
			_outNode(str, node->raw_expr);
1396 1397
			appendStringInfo(str, " :cooked ");
			_outToken(str, node->cooked_expr);
T
Thomas G. Lockhart 已提交
1398 1399 1400
			break;

		case CONSTR_DEFAULT:
1401
			appendStringInfo(str, "DEFAULT :raw ");
1402
			_outNode(str, node->raw_expr);
1403 1404
			appendStringInfo(str, " :cooked ");
			_outToken(str, node->cooked_expr);
T
Thomas G. Lockhart 已提交
1405 1406 1407
			break;

		case CONSTR_NOTNULL:
1408
			appendStringInfo(str, "NOT_NULL");
T
Thomas G. Lockhart 已提交
1409 1410 1411
			break;

		case CONSTR_UNIQUE:
1412
			appendStringInfo(str, "UNIQUE :keys ");
T
Thomas G. Lockhart 已提交
1413 1414 1415 1416
			_outNode(str, node->keys);
			break;

		default:
1417
			appendStringInfo(str, "<unrecognized_constraint>");
T
Thomas G. Lockhart 已提交
1418 1419 1420 1421
			break;
	}
}

1422 1423 1424 1425 1426
static void
_outFkConstraint(StringInfo str, FkConstraint *node)
{
	appendStringInfo(str, " FKCONSTRAINT :constr_name ");
	_outToken(str, node->constr_name);
1427 1428
	appendStringInfo(str, " :pktable ");
	_outNode(str, node->pktable);
1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440
	appendStringInfo(str, " :fk_attrs ");
	_outNode(str, node->fk_attrs);
	appendStringInfo(str, " :pk_attrs ");
	_outNode(str, node->pk_attrs);
	appendStringInfo(str, " :match_type ");
	_outToken(str, node->match_type);
	appendStringInfo(str, " :actions %d :deferrable %s :initdeferred %s",
					 node->actions,
					 booltostr(node->deferrable),
					 booltostr(node->initdeferred));
}

T
Thomas G. Lockhart 已提交
1441
static void
1442
_outCaseExpr(StringInfo str, CaseExpr *node)
T
Thomas G. Lockhart 已提交
1443
{
1444 1445 1446 1447 1448
	appendStringInfo(str, " CASE :casetype %u :arg ",
					 node->casetype);
	_outNode(str, node->arg);

	appendStringInfo(str, " :args ");
T
Thomas G. Lockhart 已提交
1449
	_outNode(str, node->args);
M
 
Marc G. Fournier 已提交
1450

1451
	appendStringInfo(str, " :defresult ");
T
Thomas G. Lockhart 已提交
1452 1453 1454 1455
	_outNode(str, node->defresult);
}

static void
1456
_outCaseWhen(StringInfo str, CaseWhen *node)
T
Thomas G. Lockhart 已提交
1457
{
1458
	appendStringInfo(str, " WHEN ");
T
Thomas G. Lockhart 已提交
1459
	_outNode(str, node->expr);
M
 
Marc G. Fournier 已提交
1460

1461
	appendStringInfo(str, " :then ");
T
Thomas G. Lockhart 已提交
1462 1463 1464
	_outNode(str, node->result);
}

1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490
/*
 *	NullTest
 */
static void
_outNullTest(StringInfo str, NullTest *node)
{
	appendStringInfo(str, " NULLTEST :arg ");
	_outNode(str, node->arg);

	appendStringInfo(str, " :nulltesttype %d ",
					 (int) node->nulltesttype);
}

/*
 *	BooleanTest
 */
static void
_outBooleanTest(StringInfo str, BooleanTest *node)
{
	appendStringInfo(str, " BOOLEANTEST :arg ");
	_outNode(str, node->arg);

	appendStringInfo(str, " :booltesttype %d ",
					 (int) node->booltesttype);
}

1491 1492
/*
 * _outNode -
1493
 *	  converts a Node into ascii string and append it to 'str'
1494 1495 1496 1497
 */
static void
_outNode(StringInfo str, void *obj)
{
1498 1499
	if (obj == NULL)
	{
B
Bruce Momjian 已提交
1500
		appendStringInfo(str, "<>");
1501 1502
		return;
	}
1503

1504
	if (IsA(obj, List))
1505
	{
1506
		List	   *l;
1507

1508
		appendStringInfoChar(str, '(');
1509 1510 1511 1512
		foreach(l, (List *) obj)
		{
			_outNode(str, lfirst(l));
			if (lnext(l))
1513
				appendStringInfoChar(str, ' ');
1514
		}
1515
		appendStringInfoChar(str, ')');
1516
	}
1517
	else if (IsA(obj, Integer) || IsA(obj, Float) || IsA(obj, String) || IsA(obj, BitString))
1518 1519 1520 1521
	{
		/* nodeRead does not want to see { } around these! */
		_outValue(str, obj);
	}
1522 1523
	else
	{
1524
		appendStringInfoChar(str, '{');
1525 1526
		switch (nodeTag(obj))
		{
1527 1528 1529 1530 1531 1532
			case T_CreateStmt:
				_outCreateStmt(str, obj);
				break;
			case T_IndexStmt:
				_outIndexStmt(str, obj);
				break;
1533 1534 1535 1536 1537 1538
			case T_NotifyStmt:
				_outNotifyStmt(str, obj);
				break;
			case T_SelectStmt:
				_outSelectStmt(str, obj);
				break;
1539 1540 1541
			case T_ColumnDef:
				_outColumnDef(str, obj);
				break;
1542 1543 1544
			case T_TypeName:
				_outTypeName(str, obj);
				break;
1545 1546 1547
			case T_TypeCast:
				_outTypeCast(str, obj);
				break;
1548 1549 1550
			case T_IndexElem:
				_outIndexElem(str, obj);
				break;
1551 1552 1553
			case T_Query:
				_outQuery(str, obj);
				break;
1554 1555 1556 1557 1558
			case T_SortClause:
				_outSortClause(str, obj);
				break;
			case T_GroupClause:
				_outGroupClause(str, obj);
1559
				break;
1560 1561 1562
			case T_SetOperationStmt:
				_outSetOperationStmt(str, obj);
				break;
1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592
			case T_Plan:
				_outPlan(str, obj);
				break;
			case T_Result:
				_outResult(str, obj);
				break;
			case T_Append:
				_outAppend(str, obj);
				break;
			case T_Join:
				_outJoin(str, obj);
				break;
			case T_NestLoop:
				_outNestLoop(str, obj);
				break;
			case T_MergeJoin:
				_outMergeJoin(str, obj);
				break;
			case T_HashJoin:
				_outHashJoin(str, obj);
				break;
			case T_Scan:
				_outScan(str, obj);
				break;
			case T_SeqScan:
				_outSeqScan(str, obj);
				break;
			case T_IndexScan:
				_outIndexScan(str, obj);
				break;
1593 1594 1595
			case T_TidScan:
				_outTidScan(str, obj);
				break;
1596 1597 1598
			case T_SubqueryScan:
				_outSubqueryScan(str, obj);
				break;
1599 1600 1601
			case T_Material:
				_outMaterial(str, obj);
				break;
1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613
			case T_Sort:
				_outSort(str, obj);
				break;
			case T_Agg:
				_outAgg(str, obj);
				break;
			case T_Group:
				_outGroup(str, obj);
				break;
			case T_Unique:
				_outUnique(str, obj);
				break;
1614 1615 1616
			case T_SetOp:
				_outSetOp(str, obj);
				break;
1617 1618 1619
			case T_Limit:
				_outLimit(str, obj);
				break;
1620 1621 1622
			case T_Hash:
				_outHash(str, obj);
				break;
V
Vadim B. Mikheev 已提交
1623 1624 1625
			case T_SubPlan:
				_outSubPlan(str, obj);
				break;
1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640
			case T_Resdom:
				_outResdom(str, obj);
				break;
			case T_Fjoin:
				_outFjoin(str, obj);
				break;
			case T_Expr:
				_outExpr(str, obj);
				break;
			case T_Var:
				_outVar(str, obj);
				break;
			case T_Const:
				_outConst(str, obj);
				break;
B
Bruce Momjian 已提交
1641 1642
			case T_Aggref:
				_outAggref(str, obj);
1643
				break;
1644 1645 1646
			case T_SubLink:
				_outSubLink(str, obj);
				break;
1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658
			case T_ArrayRef:
				_outArrayRef(str, obj);
				break;
			case T_Func:
				_outFunc(str, obj);
				break;
			case T_Oper:
				_outOper(str, obj);
				break;
			case T_Param:
				_outParam(str, obj);
				break;
1659 1660 1661 1662 1663 1664 1665 1666 1667
			case T_FieldSelect:
				_outFieldSelect(str, obj);
				break;
			case T_RelabelType:
				_outRelabelType(str, obj);
				break;
			case T_RangeTblRef:
				_outRangeTblRef(str, obj);
				break;
1668 1669 1670
			case T_FromExpr:
				_outFromExpr(str, obj);
				break;
1671 1672 1673
			case T_JoinExpr:
				_outJoinExpr(str, obj);
				break;
1674 1675 1676
			case T_TargetEntry:
				_outTargetEntry(str, obj);
				break;
1677 1678 1679
			case T_Alias:
				_outAlias(str, obj);
				break;
1680 1681 1682 1683 1684 1685 1686 1687 1688
			case T_RangeTblEntry:
				_outRangeTblEntry(str, obj);
				break;
			case T_Path:
				_outPath(str, obj);
				break;
			case T_IndexPath:
				_outIndexPath(str, obj);
				break;
1689 1690 1691
			case T_TidPath:
				_outTidPath(str, obj);
				break;
1692 1693 1694
			case T_AppendPath:
				_outAppendPath(str, obj);
				break;
1695 1696
			case T_NestPath:
				_outNestPath(str, obj);
1697 1698 1699 1700 1701 1702 1703
				break;
			case T_MergePath:
				_outMergePath(str, obj);
				break;
			case T_HashPath:
				_outHashPath(str, obj);
				break;
1704 1705
			case T_PathKeyItem:
				_outPathKeyItem(str, obj);
1706
				break;
1707 1708
			case T_RestrictInfo:
				_outRestrictInfo(str, obj);
1709
				break;
1710 1711
			case T_JoinInfo:
				_outJoinInfo(str, obj);
1712 1713 1714 1715 1716 1717 1718
				break;
			case T_Iter:
				_outIter(str, obj);
				break;
			case T_Stream:
				_outStream(str, obj);
				break;
1719 1720 1721
			case T_A_Expr:
				_outAExpr(str, obj);
				break;
1722 1723 1724 1725 1726 1727 1728 1729 1730
			case T_RangeVar:
				_outRangeVar(str, obj);
				break;
			case T_ColumnRef:
				_outColumnRef(str, obj);
				break;
			case T_ParamRef:
				_outParamRef(str, obj);
				break;
1731 1732 1733 1734 1735 1736
			case T_Ident:
				_outIdent(str, obj);
				break;
			case T_A_Const:
				_outAConst(str, obj);
				break;
1737 1738 1739
			case T_ExprFieldSelect:
				_outExprFieldSelect(str, obj);
				break;
T
Thomas G. Lockhart 已提交
1740 1741 1742
			case T_Constraint:
				_outConstraint(str, obj);
				break;
1743 1744 1745
			case T_FkConstraint:
				_outFkConstraint(str, obj);
				break;
T
Thomas G. Lockhart 已提交
1746 1747 1748 1749 1750 1751
			case T_CaseExpr:
				_outCaseExpr(str, obj);
				break;
			case T_CaseWhen:
				_outCaseWhen(str, obj);
				break;
1752 1753 1754 1755 1756 1757
			case T_NullTest:
				_outNullTest(str, obj);
				break;
			case T_BooleanTest:
				_outBooleanTest(str, obj);
				break;
1758 1759 1760 1761
			case T_FuncCall:
				_outFuncCall(str, obj);
				break;

1762
			default:
B
Bruce Momjian 已提交
1763
				elog(WARNING, "_outNode: don't know how to print type %d ",
1764 1765
					 nodeTag(obj));
				break;
1766
		}
1767
		appendStringInfoChar(str, '}');
1768 1769 1770 1771 1772
	}
}

/*
 * nodeToString -
1773
 *	   returns the ascii representation of the Node as a palloc'd string
1774
 */
1775
char *
1776 1777
nodeToString(void *obj)
{
B
Bruce Momjian 已提交
1778
	StringInfoData str;
1779

1780 1781 1782 1783
	/* see stringinfo.h for an explanation of this maneuver */
	initStringInfo(&str);
	_outNode(&str, obj);
	return str.data;
1784
}