outfuncs.c 40.6 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.156 2002/04/17 20:57:56 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
	appendStringInfo(str, "FUNCTION ");
163
	_outNode(str, node->funcname);
164
	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 193 194
	appendStringInfo(str, " TYPENAME :names ");
	_outNode(str, node->names);
	appendStringInfo(str, " :typeid %u :timezone %s :setof %s"
					 " :pct_type %s typmod %d :arrayBounds ",
					 node->typeid,
195 196
					 booltostr(node->timezone),
					 booltostr(node->setof),
197
					 booltostr(node->pct_type),
B
Bruce Momjian 已提交
198
					 node->typmod);
199 200
	_outNode(str, node->arrayBounds);
}
201

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

211 212 213
static void
_outIndexElem(StringInfo str, IndexElem *node)
{
214 215
	appendStringInfo(str, " INDEXELEM :name ");
	_outToken(str, node->name);
216 217
	appendStringInfo(str, " :funcname ");
	_outNode(str, node->funcname);
218
	appendStringInfo(str, " :args ");
219
	_outNode(str, node->args);
220 221
	appendStringInfo(str, " :opclass ");
	_outNode(str, node->opclass);
222
}
223

224
static void
225
_outQuery(StringInfo str, Query *node)
226
{
227
	appendStringInfo(str, " QUERY :command %d :utility ", node->commandType);
228

229 230 231 232 233 234 235
	/*
	 * 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.
	 */
236 237 238 239 240 241 242
	if (node->utilityStmt)
	{
		switch (nodeTag(node->utilityStmt))
		{
			case T_CreateStmt:
			case T_IndexStmt:
			case T_NotifyStmt:
243
				_outNode(str, node->utilityStmt);
244 245
				break;
			default:
246 247
				appendStringInfo(str, "?");
				break;
248 249
		}
	}
250
	else
251
		appendStringInfo(str, "<>");
252

253
	appendStringInfo(str, " :resultRelation %d :into ",
254
					 node->resultRelation);
255
	_outNode(str, node->into);
256

257
	appendStringInfo(str, " :isPortal %s :isBinary %s"
258
					 " :hasAggs %s :hasSubLinks %s :rtable ",
259 260 261 262
					 booltostr(node->isPortal),
					 booltostr(node->isBinary),
					 booltostr(node->hasAggs),
					 booltostr(node->hasSubLinks));
263
	_outNode(str, node->rtable);
M
 
Marc G. Fournier 已提交
264

265 266 267
	appendStringInfo(str, " :jointree ");
	_outNode(str, node->jointree);

268 269 270
	appendStringInfo(str, " :rowMarks ");
	_outIntList(str, node->rowMarks);

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

274 275
	appendStringInfo(str, " :groupClause ");
	_outNode(str, node->groupClause);
M
 
Marc G. Fournier 已提交
276

277
	appendStringInfo(str, " :havingQual ");
278
	_outNode(str, node->havingQual);
M
 
Marc G. Fournier 已提交
279

280 281
	appendStringInfo(str, " :distinctClause ");
	_outNode(str, node->distinctClause);
B
Hi!  
Bruce Momjian 已提交
282

283 284
	appendStringInfo(str, " :sortClause ");
	_outNode(str, node->sortClause);
285

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

B
Bruce Momjian 已提交
289 290
	appendStringInfo(str, " :limitCount ");
	_outNode(str, node->limitCount);
291 292 293

	appendStringInfo(str, " :setOperations ");
	_outNode(str, node->setOperations);
294 295 296

	appendStringInfo(str, " :resultRelations ");
	_outIntList(str, node->resultRelations);
297 298 299
}

static void
300
_outSortClause(StringInfo str, SortClause *node)
301
{
302
	appendStringInfo(str, " SORTCLAUSE :tleSortGroupRef %u :sortop %u ",
303
					 node->tleSortGroupRef, node->sortop);
304 305 306 307 308
}

static void
_outGroupClause(StringInfo str, GroupClause *node)
{
309
	appendStringInfo(str, " GROUPCLAUSE :tleSortGroupRef %u :sortop %u ",
310
					 node->tleSortGroupRef, node->sortop);
311 312
}

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

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

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

345
	appendStringInfo(str, " :lefttree ");
346
	_outNode(str, node->lefttree);
M
 
Marc G. Fournier 已提交
347

348
	appendStringInfo(str, " :righttree ");
349
	_outNode(str, node->righttree);
M
 
Marc G. Fournier 已提交
350

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

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

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

M
 
Marc G. Fournier 已提交
360
	appendStringInfo(str, " :nprm %d ", node->nParamExec);
361 362 363
}

/*
364
 *	Stuff from plannodes.h
365 366
 */
static void
367
_outPlan(StringInfo str, Plan *node)
368
{
369
	appendStringInfo(str, " PLAN ");
370
	_outPlanInfo(str, (Plan *) node);
371 372 373
}

static void
374
_outResult(StringInfo str, Result *node)
375
{
376
	appendStringInfo(str, " RESULT ");
377 378
	_outPlanInfo(str, (Plan *) node);

379
	appendStringInfo(str, " :resconstantqual ");
380 381
	_outNode(str, node->resconstantqual);

382 383 384
}

/*
385
 *	Append is a subclass of Plan.
386 387
 */
static void
B
Bruce Momjian 已提交
388
_outAppend(StringInfo str, Append *node)
389
{
390
	appendStringInfo(str, " APPEND ");
391 392
	_outPlanInfo(str, (Plan *) node);

393 394
	appendStringInfo(str, " :appendplans ");
	_outNode(str, node->appendplans);
395

396
	appendStringInfo(str, " :isTarget %s ",
397
					 booltostr(node->isTarget));
398 399 400
}

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

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

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

444
	appendStringInfo(str, " :mergeclauses ");
445
	_outNode(str, node->mergeclauses);
446 447 448
}

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

462
	appendStringInfo(str, " :hashclauses ");
463
	_outNode(str, node->hashclauses);
464
	appendStringInfo(str, " :hashjoinop %u ",
B
Bruce Momjian 已提交
465
					 node->hashjoinop);
466 467
}

V
Vadim B. Mikheev 已提交
468 469 470
static void
_outSubPlan(StringInfo str, SubPlan *node)
{
M
 
Marc G. Fournier 已提交
471
	appendStringInfo(str, " SUBPLAN :plan ");
V
Vadim B. Mikheev 已提交
472
	_outNode(str, node->plan);
M
 
Marc G. Fournier 已提交
473

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

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

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

V
Vadim B. Mikheev 已提交
483 484 485 486
	appendStringInfo(str, " :slink ");
	_outNode(str, node->sublink);
}

487
/*
488
 *	Scan is a subclass of Node
489 490
 */
static void
491
_outScan(StringInfo str, Scan *node)
492
{
493
	appendStringInfo(str, " SCAN ");
494 495
	_outPlanInfo(str, (Plan *) node);

496
	appendStringInfo(str, " :scanrelid %u ", node->scanrelid);
497 498 499
}

/*
500
 *	SeqScan is a subclass of Scan
501 502
 */
static void
503
_outSeqScan(StringInfo str, SeqScan *node)
504
{
505
	appendStringInfo(str, " SEQSCAN ");
506 507
	_outPlanInfo(str, (Plan *) node);

508
	appendStringInfo(str, " :scanrelid %u ", node->scanrelid);
509 510 511
}

/*
512
 *	IndexScan is a subclass of Scan
513 514
 */
static void
515
_outIndexScan(StringInfo str, IndexScan *node)
516
{
517
	appendStringInfo(str, " INDEXSCAN ");
518 519
	_outPlanInfo(str, (Plan *) node);

520
	appendStringInfo(str, " :scanrelid %u :indxid ", node->scan.scanrelid);
521
	_outOidList(str, node->indxid);
522

523
	appendStringInfo(str, " :indxqual ");
524 525
	_outNode(str, node->indxqual);

V
Vadim B. Mikheev 已提交
526 527 528
	appendStringInfo(str, " :indxqualorig ");
	_outNode(str, node->indxqualorig);

529
	appendStringInfo(str, " :indxorderdir %d ", node->indxorderdir);
530 531
}

532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548
/*
 *	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);

}

549 550 551 552 553 554 555 556 557 558 559 560 561
/*
 *	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);
}

562
/*
563
 *	Material is a subclass of Plan
564 565 566 567 568 569 570 571
 */
static void
_outMaterial(StringInfo str, Material *node)
{
	appendStringInfo(str, " MATERIAL ");
	_outPlanInfo(str, (Plan *) node);
}

572
/*
573
 *	Sort is a subclass of Plan
574 575
 */
static void
576
_outSort(StringInfo str, Sort *node)
577
{
578
	appendStringInfo(str, " SORT ");
579
	_outPlanInfo(str, (Plan *) node);
580
	appendStringInfo(str, " :keycount %d ", node->keycount);
581 582 583
}

static void
B
Bruce Momjian 已提交
584
_outAgg(StringInfo str, Agg *node)
585
{
586
	appendStringInfo(str, " AGG ");
587
	_outPlanInfo(str, (Plan *) node);
588 589 590
}

static void
591
_outGroup(StringInfo str, Group *node)
592
{
593
	appendStringInfo(str, " GRP ");
594 595 596
	_outPlanInfo(str, (Plan *) node);

	/* the actual Group fields */
M
 
Marc G. Fournier 已提交
597
	appendStringInfo(str, " :numCols %d :tuplePerGroup %s ",
B
Bruce Momjian 已提交
598
					 node->numCols,
599
					 booltostr(node->tuplePerGroup));
600
}
601

602
static void
603
_outUnique(StringInfo str, Unique *node)
604
{
B
Bruce Momjian 已提交
605
	int			i;
606

607
	appendStringInfo(str, " UNIQUE ");
608 609
	_outPlanInfo(str, (Plan *) node);

610
	appendStringInfo(str, " :numCols %d :uniqColIdx ",
611
					 node->numCols);
612 613 614
	for (i = 0; i < node->numCols; i++)
		appendStringInfo(str, "%d ", (int) node->uniqColIdx[i]);
}
615

616 617 618
static void
_outSetOp(StringInfo str, SetOp *node)
{
B
Bruce Momjian 已提交
619
	int			i;
620 621 622 623 624 625 626 627 628 629 630 631

	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);
}

632 633 634 635 636 637 638 639 640 641 642 643
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);
}

644
/*
645
 *	Hash is a subclass of Plan
646 647
 */
static void
648
_outHash(StringInfo str, Hash *node)
649
{
650
	appendStringInfo(str, " HASH ");
651 652
	_outPlanInfo(str, (Plan *) node);

653
	appendStringInfo(str, " :hashkey ");
654
	_outNode(str, node->hashkey);
655 656 657 658
}

/*****************************************************************************
 *
659
 *	Stuff from primnodes.h.
660 661 662 663
 *
 *****************************************************************************/

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

static void
683
_outFjoin(StringInfo str, Fjoin *node)
684
{
685
	int			i;
686

M
 
Marc G. Fournier 已提交
687
	appendStringInfo(str, " FJOIN :initialized %s :nNodes %d ",
688
					 booltostr(node->fj_initialized),
B
Bruce Momjian 已提交
689
					 node->fj_nNodes);
690 691 692 693

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

694 695
	appendStringInfo(str, " :results @ 0x%p :alwaysdone",
					 node->fj_results);
696 697

	for (i = 0; i < node->fj_nNodes; i++)
698 699
		appendStringInfo(str,
						 booltostr(node->fj_alwaysDone[i]));
700 701 702
}

/*
703
 *	Expr is a subclass of Node
704 705
 */
static void
706
_outExpr(StringInfo str, Expr *node)
707
{
708
	char	   *opstr = NULL;
709

M
 
Marc G. Fournier 已提交
710
	appendStringInfo(str, " EXPR :typeOid %u ",
B
Bruce Momjian 已提交
711
					 node->typeOid);
712 713 714

	switch (node->opType)
	{
715 716 717 718 719 720 721 722 723 724 725 726 727 728 729
		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 已提交
730 731 732
		case SUBPLAN_EXPR:
			opstr = "subp";
			break;
733
	}
734 735 736
	appendStringInfo(str, " :opType ");
	_outToken(str, opstr);
	appendStringInfo(str, " :oper ");
737
	_outNode(str, node->oper);
M
 
Marc G. Fournier 已提交
738

739
	appendStringInfo(str, " :args ");
740
	_outNode(str, node->args);
741 742 743
}

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

756
	appendStringInfo(str, " :varlevelsup %u :varnoold %u :varoattno %d",
B
Bruce Momjian 已提交
757 758 759
					 node->varlevelsup,
					 node->varnoold,
					 node->varoattno);
760 761 762
}

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

776
	if (node->constisnull)
B
Bruce Momjian 已提交
777
		appendStringInfo(str, "<>");
778
	else
779
		_outDatum(str, node->constvalue, node->constlen, node->constbyval);
780 781 782
}

/*
B
Bruce Momjian 已提交
783
 *	Aggref
784 785
 */
static void
786
_outAggref(StringInfo str, Aggref *node)
787
{
788 789
	appendStringInfo(str, " AGGREG :aggfnoid %u :aggtype %u :target ",
					 node->aggfnoid, node->aggtype);
790
	_outNode(str, node->target);
M
 
Marc G. Fournier 已提交
791

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

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

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

813 814 815 816
	appendStringInfo(str, " :subselect ");
	_outNode(str, node->subselect);
}

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

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

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

836
	appendStringInfo(str, " :refexpr ");
837 838
	_outNode(str, node->refexpr);

839
	appendStringInfo(str, " :refassgnexpr ");
840
	_outNode(str, node->refassgnexpr);
841 842 843
}

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

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

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

880 881 882 883 884 885 886 887 888 889
/*
 *	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 已提交
890
				   node->fieldnum, node->resulttype, node->resulttypmod);
891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915
}

/*
 *	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);
}

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

928 929 930 931 932 933 934 935
/*
 *	JoinExpr
 */
static void
_outJoinExpr(StringInfo str, JoinExpr *node)
{
	appendStringInfo(str, " JOINEXPR :jointype %d :isNatural %s :larg ",
					 (int) node->jointype,
936
					 booltostr(node->isNatural));
937 938 939 940 941 942 943 944 945
	_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);
946
	appendStringInfo(str, " :rtindex %d ", node->rtindex);
947 948
}

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

958 959
	appendStringInfo(str, " :expr ");
	_outNode(str, node->expr);
960
}
961

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

971
static void
972
_outRangeTblEntry(StringInfo str, RangeTblEntry *node)
973
{
974 975
	/* put alias + eref first to make dump more legible */
	appendStringInfo(str, " RTE :alias ");
976 977 978
	_outNode(str, node->alias);
	appendStringInfo(str, " :eref ");
	_outNode(str, node->eref);
979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005
	appendStringInfo(str, " :rtekind %d ",
					 (int) node->rtekind);
	switch (node->rtekind)
	{
		case RTE_RELATION:
		case RTE_SPECIAL:
			appendStringInfo(str, ":relid %u ", node->relid);
			break;
		case RTE_SUBQUERY:
			appendStringInfo(str, ":subquery ");
			_outNode(str, node->subquery);
			break;
		case RTE_JOIN:
			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);
			break;
		default:
			elog(ERROR, "bogus rte kind %d", (int) node->rtekind);
			break;
	}
1006 1007
	appendStringInfo(str, " :inh %s :inFromCl %s :checkForRead %s"
					 " :checkForWrite %s :checkAsUser %u",
1008 1009 1010 1011
					 booltostr(node->inh),
					 booltostr(node->inFromCl),
					 booltostr(node->checkForRead),
					 booltostr(node->checkForWrite),
1012
					 node->checkAsUser);
1013 1014
}

1015
/*
1016
 *	Path is a subclass of Node.
1017 1018
 */
static void
1019
_outPath(StringInfo str, Path *node)
1020
{
1021
	appendStringInfo(str,
1022
	 " PATH :pathtype %d :startup_cost %.2f :total_cost %.2f :pathkeys ",
B
Bruce Momjian 已提交
1023
					 node->pathtype,
1024 1025
					 node->startup_cost,
					 node->total_cost);
1026
	_outNode(str, node->pathkeys);
1027 1028 1029
}

/*
1030
 *	IndexPath is a subclass of Path.
1031 1032
 */
static void
1033
_outIndexPath(StringInfo str, IndexPath *node)
1034
{
B
Bruce Momjian 已提交
1035
	appendStringInfo(str,
1036
					 " INDEXPATH :pathtype %d :startup_cost %.2f :total_cost %.2f :pathkeys ",
B
Bruce Momjian 已提交
1037
					 node->path.pathtype,
1038 1039
					 node->path.startup_cost,
					 node->path.total_cost);
1040
	_outNode(str, node->path.pathkeys);
1041

1042 1043
	appendStringInfo(str, " :indexinfo ");
	_outNode(str, node->indexinfo);
1044

1045
	appendStringInfo(str, " :indexqual ");
1046
	_outNode(str, node->indexqual);
1047

1048 1049
	appendStringInfo(str, " :indexscandir %d :joinrelids ",
					 (int) node->indexscandir);
1050
	_outIntList(str, node->joinrelids);
1051

1052
	appendStringInfo(str, " :alljoinquals %s :rows %.2f ",
1053
					 booltostr(node->alljoinquals),
1054
					 node->rows);
1055 1056
}

1057 1058 1059 1060 1061 1062 1063
/*
 *	TidPath is a subclass of Path.
 */
static void
_outTidPath(StringInfo str, TidPath *node)
{
	appendStringInfo(str,
1064
					 " TIDPATH :pathtype %d :startup_cost %.2f :total_cost %.2f :pathkeys ",
1065
					 node->path.pathtype,
1066 1067
					 node->path.startup_cost,
					 node->path.total_cost);
1068 1069 1070 1071 1072
	_outNode(str, node->path.pathkeys);

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

1073
	appendStringInfo(str, " :unjoined_relids ");
1074 1075 1076
	_outIntList(str, node->unjoined_relids);
}

1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093
/*
 *	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);
}

1094
/*
1095
 *	NestPath is a subclass of Path
1096 1097
 */
static void
1098
_outNestPath(StringInfo str, NestPath *node)
1099
{
B
Bruce Momjian 已提交
1100
	appendStringInfo(str,
1101
					 " NESTPATH :pathtype %d :startup_cost %.2f :total_cost %.2f :pathkeys ",
B
Bruce Momjian 已提交
1102
					 node->path.pathtype,
1103 1104
					 node->path.startup_cost,
					 node->path.total_cost);
1105
	_outNode(str, node->path.pathkeys);
1106 1107
	appendStringInfo(str, " :jointype %d :outerjoinpath ",
					 (int) node->jointype);
1108 1109 1110 1111 1112
	_outNode(str, node->outerjoinpath);
	appendStringInfo(str, " :innerjoinpath ");
	_outNode(str, node->innerjoinpath);
	appendStringInfo(str, " :joinrestrictinfo ");
	_outNode(str, node->joinrestrictinfo);
1113 1114 1115
}

/*
1116
 *	MergePath is a subclass of NestPath.
1117 1118
 */
static void
1119
_outMergePath(StringInfo str, MergePath *node)
1120
{
B
Bruce Momjian 已提交
1121
	appendStringInfo(str,
1122
					 " MERGEPATH :pathtype %d :startup_cost %.2f :total_cost %.2f :pathkeys ",
B
Bruce Momjian 已提交
1123
					 node->jpath.path.pathtype,
1124 1125
					 node->jpath.path.startup_cost,
					 node->jpath.path.total_cost);
1126
	_outNode(str, node->jpath.path.pathkeys);
1127 1128
	appendStringInfo(str, " :jointype %d :outerjoinpath ",
					 (int) node->jpath.jointype);
1129 1130 1131 1132 1133
	_outNode(str, node->jpath.outerjoinpath);
	appendStringInfo(str, " :innerjoinpath ");
	_outNode(str, node->jpath.innerjoinpath);
	appendStringInfo(str, " :joinrestrictinfo ");
	_outNode(str, node->jpath.joinrestrictinfo);
1134

1135
	appendStringInfo(str, " :path_mergeclauses ");
1136 1137
	_outNode(str, node->path_mergeclauses);

1138
	appendStringInfo(str, " :outersortkeys ");
1139 1140
	_outNode(str, node->outersortkeys);

1141
	appendStringInfo(str, " :innersortkeys ");
1142
	_outNode(str, node->innersortkeys);
1143 1144 1145
}

/*
1146
 *	HashPath is a subclass of NestPath.
1147 1148
 */
static void
1149
_outHashPath(StringInfo str, HashPath *node)
1150
{
B
Bruce Momjian 已提交
1151
	appendStringInfo(str,
1152
					 " HASHPATH :pathtype %d :startup_cost %.2f :total_cost %.2f :pathkeys ",
B
Bruce Momjian 已提交
1153
					 node->jpath.path.pathtype,
1154 1155
					 node->jpath.path.startup_cost,
					 node->jpath.path.total_cost);
1156
	_outNode(str, node->jpath.path.pathkeys);
1157 1158
	appendStringInfo(str, " :jointype %d :outerjoinpath ",
					 (int) node->jpath.jointype);
1159 1160 1161 1162 1163
	_outNode(str, node->jpath.outerjoinpath);
	appendStringInfo(str, " :innerjoinpath ");
	_outNode(str, node->jpath.innerjoinpath);
	appendStringInfo(str, " :joinrestrictinfo ");
	_outNode(str, node->jpath.joinrestrictinfo);
1164

1165
	appendStringInfo(str, " :path_hashclauses ");
1166
	_outNode(str, node->path_hashclauses);
1167 1168 1169
}

/*
1170
 *	PathKeyItem is a subclass of Node.
1171 1172
 */
static void
1173
_outPathKeyItem(StringInfo str, PathKeyItem *node)
1174
{
1175 1176 1177
	appendStringInfo(str, " PATHKEYITEM :sortop %u :key ",
					 node->sortop);
	_outNode(str, node->key);
1178 1179 1180
}

/*
1181
 *	RestrictInfo is a subclass of Node.
1182 1183
 */
static void
1184
_outRestrictInfo(StringInfo str, RestrictInfo *node)
1185
{
B
Bruce Momjian 已提交
1186
	appendStringInfo(str, " RESTRICTINFO :clause ");
1187 1188
	_outNode(str, node->clause);

1189
	appendStringInfo(str, " :ispusheddown %s :subclauseindices ",
1190
					 booltostr(node->ispusheddown));
1191
	_outNode(str, node->subclauseindices);
1192

1193 1194 1195
	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 已提交
1196
	appendStringInfo(str, " :hashjoinoperator %u ", node->hashjoinoperator);
1197 1198 1199
}

/*
1200
 *	JoinInfo is a subclass of Node.
1201 1202
 */
static void
1203
_outJoinInfo(StringInfo str, JoinInfo *node)
1204
{
B
Bruce Momjian 已提交
1205 1206
	appendStringInfo(str, " JINFO :unjoined_relids ");
	_outIntList(str, node->unjoined_relids);
1207

1208 1209
	appendStringInfo(str, " :jinfo_restrictinfo ");
	_outNode(str, node->jinfo_restrictinfo);
1210 1211 1212 1213 1214 1215
}

/*
 * Print the value of a Datum given its type.
 */
static void
1216
_outDatum(StringInfo str, Datum value, int typlen, bool typbyval)
1217
{
1218 1219
	Size		length,
				i;
1220
	char	   *s;
1221

1222
	length = datumGetSize(value, typbyval, typlen);
1223

1224
	if (typbyval)
1225 1226
	{
		s = (char *) (&value);
1227
		appendStringInfo(str, " %u [ ", (unsigned int) length);
1228
		for (i = 0; i < (Size) sizeof(Datum); i++)
1229
			appendStringInfo(str, "%d ", (int) (s[i]));
M
 
Marc G. Fournier 已提交
1230
		appendStringInfo(str, "] ");
1231
	}
1232
	else
1233
	{
1234 1235
		s = (char *) DatumGetPointer(value);
		if (!PointerIsValid(s))
M
 
Marc G. Fournier 已提交
1236
			appendStringInfo(str, " 0 [ ] ");
1237 1238
		else
		{
1239
			appendStringInfo(str, " %u [ ", (unsigned int) length);
1240
			for (i = 0; i < length; i++)
1241
				appendStringInfo(str, "%d ", (int) (s[i]));
M
 
Marc G. Fournier 已提交
1242
			appendStringInfo(str, "] ");
1243
		}
1244 1245 1246 1247
	}
}

static void
1248
_outIter(StringInfo str, Iter *node)
1249
{
M
 
Marc G. Fournier 已提交
1250
	appendStringInfo(str, " ITER :iterexpr ");
1251
	_outNode(str, node->iterexpr);
1252 1253 1254
}

static void
1255
_outStream(StringInfo str, Stream *node)
1256
{
B
Bruce Momjian 已提交
1257
	appendStringInfo(str,
B
Bruce Momjian 已提交
1258
	  " STREAM :pathptr @ %p :cinfo @ %p :clausetype %p :upstream @ %p ",
1259 1260 1261 1262
					 node->pathptr,
					 node->cinfo,
					 node->clausetype,
					 node->upstream);
1263

B
Bruce Momjian 已提交
1264
	appendStringInfo(str,
B
Bruce Momjian 已提交
1265
			 " :downstream @ %p :groupup %d :groupcost %f :groupsel %f ",
1266
					 node->downstream,
B
Bruce Momjian 已提交
1267 1268 1269
					 node->groupup,
					 node->groupcost,
					 node->groupsel);
1270
}
1271

1272 1273 1274
static void
_outAExpr(StringInfo str, A_Expr *node)
{
1275
	appendStringInfo(str, " AEXPR ");
1276 1277 1278
	switch (node->oper)
	{
		case AND:
1279
			appendStringInfo(str, "AND ");
1280 1281
			break;
		case OR:
1282
			appendStringInfo(str, "OR ");
1283 1284
			break;
		case NOT:
1285
			appendStringInfo(str, "NOT ");
1286
			break;
1287
		case OP:
1288
			_outNode(str, node->name);
1289
			appendStringInfo(str, " ");
1290
			break;
1291 1292 1293
		default:
			appendStringInfo(str, "?? ");
			break;
1294
	}
1295
	_outNode(str, node->lexpr);
1296
	appendStringInfo(str, " ");
1297 1298 1299
	_outNode(str, node->rexpr);
}

1300
static void
1301
_outValue(StringInfo str, Value *value)
1302
{
1303 1304
	switch (value->type)
	{
1305
		case T_Integer:
1306
			appendStringInfo(str, " %ld ", value->val.ival);
1307 1308
			break;
		case T_Float:
1309 1310 1311 1312

			/*
			 * We assume the value is a valid numeric literal and so does
			 * not need quoting.
1313 1314 1315 1316 1317 1318 1319
			 */
			appendStringInfo(str, " %s ", value->val.str);
			break;
		case T_String:
			appendStringInfo(str, " \"");
			_outToken(str, value->val.str);
			appendStringInfo(str, "\" ");
1320
			break;
1321
		case T_BitString:
1322 1323
			/* internal representation already has leading 'b' */
			appendStringInfo(str, " %s ", value->val.str);
1324
			break;
1325
		default:
B
Bruce Momjian 已提交
1326
			elog(WARNING, "_outValue: don't know how to print type %d ",
1327
				 value->type);
1328
			break;
1329
	}
1330 1331
}

1332
static void
1333
_outRangeVar(StringInfo str, RangeVar *node)
1334
{
1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347
	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);
1348 1349
}

1350
static void
1351
_outColumnRef(StringInfo str, ColumnRef *node)
1352
{
1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372
	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);
1373 1374
}

1375 1376 1377
static void
_outAConst(StringInfo str, A_Const *node)
{
1378
	appendStringInfo(str, "CONST ");
1379
	_outValue(str, &(node->val));
1380 1381
	appendStringInfo(str, " :typename ");
	_outNode(str, node->typename);
1382 1383
}

1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394
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 已提交
1395 1396 1397
static void
_outConstraint(StringInfo str, Constraint *node)
{
1398
	appendStringInfo(str, " CONSTRAINT :name ");
1399 1400
	_outToken(str, node->name);
	appendStringInfo(str, " :type ");
T
Thomas G. Lockhart 已提交
1401 1402 1403 1404

	switch (node->contype)
	{
		case CONSTR_PRIMARY:
1405
			appendStringInfo(str, "PRIMARY_KEY :keys ");
T
Thomas G. Lockhart 已提交
1406 1407 1408 1409
			_outNode(str, node->keys);
			break;

		case CONSTR_CHECK:
1410
			appendStringInfo(str, "CHECK :raw ");
1411
			_outNode(str, node->raw_expr);
1412 1413
			appendStringInfo(str, " :cooked ");
			_outToken(str, node->cooked_expr);
T
Thomas G. Lockhart 已提交
1414 1415 1416
			break;

		case CONSTR_DEFAULT:
1417
			appendStringInfo(str, "DEFAULT :raw ");
1418
			_outNode(str, node->raw_expr);
1419 1420
			appendStringInfo(str, " :cooked ");
			_outToken(str, node->cooked_expr);
T
Thomas G. Lockhart 已提交
1421 1422 1423
			break;

		case CONSTR_NOTNULL:
1424
			appendStringInfo(str, "NOT_NULL");
T
Thomas G. Lockhart 已提交
1425 1426 1427
			break;

		case CONSTR_UNIQUE:
1428
			appendStringInfo(str, "UNIQUE :keys ");
T
Thomas G. Lockhart 已提交
1429 1430 1431 1432
			_outNode(str, node->keys);
			break;

		default:
1433
			appendStringInfo(str, "<unrecognized_constraint>");
T
Thomas G. Lockhart 已提交
1434 1435 1436 1437
			break;
	}
}

1438 1439 1440 1441 1442
static void
_outFkConstraint(StringInfo str, FkConstraint *node)
{
	appendStringInfo(str, " FKCONSTRAINT :constr_name ");
	_outToken(str, node->constr_name);
1443 1444
	appendStringInfo(str, " :pktable ");
	_outNode(str, node->pktable);
1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456
	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 已提交
1457
static void
1458
_outCaseExpr(StringInfo str, CaseExpr *node)
T
Thomas G. Lockhart 已提交
1459
{
1460 1461 1462 1463 1464
	appendStringInfo(str, " CASE :casetype %u :arg ",
					 node->casetype);
	_outNode(str, node->arg);

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

1467
	appendStringInfo(str, " :defresult ");
T
Thomas G. Lockhart 已提交
1468 1469 1470 1471
	_outNode(str, node->defresult);
}

static void
1472
_outCaseWhen(StringInfo str, CaseWhen *node)
T
Thomas G. Lockhart 已提交
1473
{
1474
	appendStringInfo(str, " WHEN ");
T
Thomas G. Lockhart 已提交
1475
	_outNode(str, node->expr);
M
 
Marc G. Fournier 已提交
1476

1477
	appendStringInfo(str, " :then ");
T
Thomas G. Lockhart 已提交
1478 1479 1480
	_outNode(str, node->result);
}

1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506
/*
 *	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);
}

1507 1508
/*
 * _outNode -
1509
 *	  converts a Node into ascii string and append it to 'str'
1510 1511 1512 1513
 */
static void
_outNode(StringInfo str, void *obj)
{
1514 1515
	if (obj == NULL)
	{
B
Bruce Momjian 已提交
1516
		appendStringInfo(str, "<>");
1517 1518
		return;
	}
1519

1520
	if (IsA(obj, List))
1521
	{
1522
		List	   *l;
1523

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

1778
			default:
B
Bruce Momjian 已提交
1779
				elog(WARNING, "_outNode: don't know how to print type %d ",
1780 1781
					 nodeTag(obj));
				break;
1782
		}
1783
		appendStringInfoChar(str, '}');
1784 1785 1786 1787 1788
	}
}

/*
 * nodeToString -
1789
 *	   returns the ascii representation of the Node as a palloc'd string
1790
 */
1791
char *
1792 1793
nodeToString(void *obj)
{
B
Bruce Momjian 已提交
1794
	StringInfoData str;
1795

1796 1797 1798 1799
	/* see stringinfo.h for an explanation of this maneuver */
	initStringInfo(&str);
	_outNode(&str, obj);
	return str.data;
1800
}