outfuncs.c 36.2 KB
Newer Older
M
 
Marc G. Fournier 已提交
1
/*
2
 *
3
 * outfuncs.c
4
 *	  routines to convert a node to ascii representation
5
 *
B
Add:  
Bruce Momjian 已提交
6 7
 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
 * Portions Copyright (c) 1994, Regents of the University of California
8
 *
9
 *	$Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.123 2000/07/17 03:05:01 tgl Exp $
10 11
 *
 * NOTES
12 13 14 15 16
 *	  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
 *	  catalogs (eg. indexes). This is also the plan string sent out in
 *	  Mariposa.
17
 *
18 19 20
 *	  These functions update the in/out argument of type StringInfo
 *	  passed to them. This argument contains the string holding the ASCII
 *	  representation plus some other information (string length, etc.)
21 22
 *
 */
23
#include <ctype.h>
24

25
#include "postgres.h"
26

27 28
#include "access/heapam.h"
#include "access/htup.h"
B
Bruce Momjian 已提交
29
#include "catalog/pg_type.h"
30
#include "fmgr.h"
B
Bruce Momjian 已提交
31
#include "lib/stringinfo.h"
32
#include "nodes/execnodes.h"
B
Bruce Momjian 已提交
33 34
#include "nodes/nodes.h"
#include "nodes/parsenodes.h"
35 36 37 38
#include "nodes/pg_list.h"
#include "nodes/plannodes.h"
#include "nodes/primnodes.h"
#include "nodes/relation.h"
39
#include "parser/parse.h"
B
Bruce Momjian 已提交
40 41 42
#include "utils/datum.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
43

44

45 46
static void _outDatum(StringInfo str, Datum value, Oid type);
static void _outNode(StringInfo str, void *obj);
47

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
/*
 * _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;
	}
63

64 65
	/*
	 * Look for characters or patterns that are treated specially by
66 67
	 * read.c (either in lsptok() or in nodeRead()), and therefore need a
	 * protective backslash.
68 69 70 71 72
	 */
	/* These characters only need to be quoted at the start of the string */
	if (*s == '<' ||
		*s == '\"' ||
		*s == '@' ||
73 74
		isdigit((int) *s) ||
		(*s == '-' && isdigit((int) s[1])))
75 76 77 78 79 80 81 82 83 84 85
		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++);
	}
}
86

87 88
/*
 * _outIntList -
89
 *	   converts a List of integers
90
 */
91
static void
92
_outIntList(StringInfo str, List *list)
93
{
B
Bruce Momjian 已提交
94
	List	   *l;
95

96
	appendStringInfoChar(str, '(');
97
	foreach(l, list)
98 99
		appendStringInfo(str, " %d", lfirsti(l));
	appendStringInfoChar(str, ')');
100 101
}

102 103 104
static void
_outCreateStmt(StringInfo str, CreateStmt *node)
{
105 106
	appendStringInfo(str, " CREATE :relname ");
	_outToken(str, node->relname);
107 108

	appendStringInfo(str, " :istemp %s ",
B
Bruce Momjian 已提交
109
					 node->istemp ? "true" : "false");
110 111

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

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

117
	appendStringInfo(str, " :constraints ");
118
	_outNode(str, node->constraints);
119
}
120 121 122 123

static void
_outIndexStmt(StringInfo str, IndexStmt *node)
{
124 125 126 127 128 129 130
	appendStringInfo(str, " INDEX :idxname ");
	_outToken(str, node->idxname);
	appendStringInfo(str, " :relname ");
	_outToken(str, node->relname);
	appendStringInfo(str, " :accessMethod ");
	_outToken(str, node->accessMethod);
	appendStringInfo(str, " :indexParams ");
131
	_outNode(str, node->indexParams);
M
 
Marc G. Fournier 已提交
132

133 134
	appendStringInfo(str, " :withClause ");
	_outNode(str, node->withClause);
M
 
Marc G. Fournier 已提交
135

136 137
	appendStringInfo(str, " :whereClause ");
	_outNode(str, node->whereClause);
M
 
Marc G. Fournier 已提交
138

139 140
	appendStringInfo(str, " :rangetable ");
	_outNode(str, node->rangetable);
M
 
Marc G. Fournier 已提交
141

142 143 144
	appendStringInfo(str, " :unique %s :primary %s ",
					 node->unique ? "true" : "false",
					 node->primary ? "true" : "false");
145
}
146

147 148 149
static void
_outSelectStmt(StringInfo str, SelectStmt *node)
{
M
 
Marc G. Fournier 已提交
150
	appendStringInfo(str, "SELECT :where ");
151 152 153 154 155 156
	_outNode(str, node->whereClause);
}

static void
_outFuncCall(StringInfo str, FuncCall *node)
{
157 158 159
	appendStringInfo(str, "FUNCTION ");
	_outToken(str, node->funcname);
	appendStringInfo(str, " :args ");
160
	_outNode(str, node->args);
161 162 163
	appendStringInfo(str, " :agg_star %s :agg_distinct %s ",
					 node->agg_star ? "true" : "false",
					 node->agg_distinct ? "true" : "false");
164
}
165

166 167 168
static void
_outColumnDef(StringInfo str, ColumnDef *node)
{
169 170 171
	appendStringInfo(str, " COLUMNDEF :colname ");
	_outToken(str, node->colname);
	appendStringInfo(str, " :typename ");
172
	_outNode(str, node->typename);
173
	appendStringInfo(str, " :is_not_null %s :is_sequence %s :raw_default ",
B
Bruce Momjian 已提交
174
					 node->is_not_null ? "true" : "false",
175 176
					 node->is_sequence ? "true" : "false");
	_outNode(str, node->raw_default);
177 178 179
	appendStringInfo(str, " :cooked_default ");
	_outToken(str, node->cooked_default);
	appendStringInfo(str, " :constraints ");
180
	_outNode(str, node->constraints);
181 182 183 184 185
}

static void
_outTypeName(StringInfo str, TypeName *node)
{
186 187 188
	appendStringInfo(str, " TYPENAME :name ");
	_outToken(str, node->name);
	appendStringInfo(str, " :timezone %s :setof %s typmod %d :arrayBounds ",
B
Bruce Momjian 已提交
189 190 191
					 node->timezone ? "true" : "false",
					 node->setof ? "true" : "false",
					 node->typmod);
192 193
	_outNode(str, node->arrayBounds);
}
194

195 196 197 198 199 200 201 202 203
static void
_outTypeCast(StringInfo str, TypeCast *node)
{
	appendStringInfo(str, " TYPECAST :arg ");
	_outNode(str, node->arg);
	appendStringInfo(str, " :typename ");
	_outNode(str, node->typename);
}

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

215
static void
216
_outQuery(StringInfo str, Query *node)
217
{
218

M
 
Marc G. Fournier 已提交
219
	appendStringInfo(str, " QUERY :command %d ", node->commandType);
220

221 222 223 224 225
	if (node->utilityStmt)
	{
		switch (nodeTag(node->utilityStmt))
		{
			case T_CreateStmt:
226 227 228
				appendStringInfo(str, " :create ");
				_outToken(str, ((CreateStmt *) (node->utilityStmt))->relname);
				appendStringInfo(str, " ");
229 230 231 232
				_outNode(str, node->utilityStmt);
				break;

			case T_IndexStmt:
233 234 235 236 237
				appendStringInfo(str, " :index ");
				_outToken(str, ((IndexStmt *) (node->utilityStmt))->idxname);
				appendStringInfo(str, " on ");
				_outToken(str, ((IndexStmt *) (node->utilityStmt))->relname);
				appendStringInfo(str, " ");
238 239 240 241
				_outNode(str, node->utilityStmt);
				break;

			case T_NotifyStmt:
242 243
				appendStringInfo(str, " :utility ");
				_outToken(str, ((NotifyStmt *) (node->utilityStmt))->relname);
244 245 246
				break;

			default:
247
				appendStringInfo(str, " :utility ? ");
248 249
		}
	}
250
	else
251
		appendStringInfo(str, " :utility <>");
252

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

B
Bruce Momjian 已提交
257
	appendStringInfo(str,
258
	" :isPortal %s :isBinary %s :isTemp %s :unionall %s :distinctClause ",
B
Bruce Momjian 已提交
259 260 261 262
					 node->isPortal ? "true" : "false",
					 node->isBinary ? "true" : "false",
					 node->isTemp ? "true" : "false",
					 node->unionall ? "true" : "false");
263 264
	_outNode(str, node->distinctClause);

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

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

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

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

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

280
	appendStringInfo(str, " :havingQual ");
281
	_outNode(str, node->havingQual);
M
 
Marc G. Fournier 已提交
282 283

	appendStringInfo(str, " :hasAggs %s :hasSubLinks %s :unionClause ",
B
Bruce Momjian 已提交
284 285
					 node->hasAggs ? "true" : "false",
					 node->hasSubLinks ? "true" : "false");
286
	_outNode(str, node->unionClause);
M
 
Marc G. Fournier 已提交
287

B
Hi!  
Bruce Momjian 已提交
288 289 290
	appendStringInfo(str, " :intersectClause ");
	_outNode(str, node->intersectClause);

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

B
Bruce Momjian 已提交
294 295
	appendStringInfo(str, " :limitCount ");
	_outNode(str, node->limitCount);
296 297 298 299

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

300 301 302
}

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

static void
_outGroupClause(StringInfo str, GroupClause *node)
{
312 313
	appendStringInfo(str, " GROUPCLAUSE :tleSortGroupRef %d :sortop %u ",
					 node->tleSortGroupRef, node->sortop);
314 315 316 317 318 319
}

/*
 * print the basic stuff of all nodes that inherit from Plan
 */
static void
320
_outPlanInfo(StringInfo str, Plan *node)
321
{
B
Bruce Momjian 已提交
322
	appendStringInfo(str,
323 324 325
					 ":startup_cost %.2f :total_cost %.2f :rows %.0f :width %d :state %s :qptargetlist ",
					 node->startup_cost,
					 node->total_cost,
326
					 node->plan_rows,
B
Bruce Momjian 已提交
327 328
					 node->plan_width,
					 node->state ? "not-NULL" : "<>");
329
	_outNode(str, node->targetlist);
M
 
Marc G. Fournier 已提交
330

331
	appendStringInfo(str, " :qpqual ");
332
	_outNode(str, node->qual);
M
 
Marc G. Fournier 已提交
333

334
	appendStringInfo(str, " :lefttree ");
335
	_outNode(str, node->lefttree);
M
 
Marc G. Fournier 已提交
336

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

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

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

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

M
 
Marc G. Fournier 已提交
349
	appendStringInfo(str, " :nprm %d ", node->nParamExec);
350 351 352
}

/*
353
 *	Stuff from plannodes.h
354 355
 */
static void
356
_outPlan(StringInfo str, Plan *node)
357
{
358
	appendStringInfo(str, " PLAN ");
359
	_outPlanInfo(str, (Plan *) node);
360 361 362
}

static void
363
_outResult(StringInfo str, Result *node)
364
{
365
	appendStringInfo(str, " RESULT ");
366 367
	_outPlanInfo(str, (Plan *) node);

368
	appendStringInfo(str, " :resconstantqual ");
369 370
	_outNode(str, node->resconstantqual);

371 372 373
}

/*
374
 *	Append is a subclass of Plan.
375 376
 */
static void
B
Bruce Momjian 已提交
377
_outAppend(StringInfo str, Append *node)
378
{
379
	appendStringInfo(str, " APPEND ");
380 381
	_outPlanInfo(str, (Plan *) node);

382 383
	appendStringInfo(str, " :appendplans ");
	_outNode(str, node->appendplans);
384

385 386
	appendStringInfo(str, " :unionrtables ");
	_outNode(str, node->unionrtables);
387

B
Bruce Momjian 已提交
388 389 390
	appendStringInfo(str,
					 " :inheritrelid %u :inheritrtable ",
					 node->inheritrelid);
391
	_outNode(str, node->inheritrtable);
392

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 403
	_outPlanInfo(str, (Plan *) node);

404 405 406
}

/*
407
 *	NestLoop is a subclass of Join
408 409
 */
static void
410
_outNestLoop(StringInfo str, NestLoop *node)
411
{
412
	appendStringInfo(str, " NESTLOOP ");
413
	_outPlanInfo(str, (Plan *) node);
414 415 416
}

/*
417
 *	MergeJoin is a subclass of Join
418 419
 */
static void
420
_outMergeJoin(StringInfo str, MergeJoin *node)
421
{
422
	appendStringInfo(str, " MERGEJOIN ");
423 424
	_outPlanInfo(str, (Plan *) node);

425
	appendStringInfo(str, " :mergeclauses ");
426
	_outNode(str, node->mergeclauses);
427 428 429
}

/*
430
 *	HashJoin is a subclass of Join.
431 432
 */
static void
433
_outHashJoin(StringInfo str, HashJoin *node)
434
{
435
	appendStringInfo(str, " HASHJOIN ");
436 437
	_outPlanInfo(str, (Plan *) node);

438
	appendStringInfo(str, " :hashclauses ");
439 440
	_outNode(str, node->hashclauses);

B
Bruce Momjian 已提交
441 442 443
	appendStringInfo(str,
					 " :hashjoinop %u ",
					 node->hashjoinop);
M
 
Marc G. Fournier 已提交
444

B
Bruce Momjian 已提交
445 446 447
	appendStringInfo(str,
					 " :hashdone %d ",
					 node->hashdone);
448 449
}

V
Vadim B. Mikheev 已提交
450 451 452
static void
_outSubPlan(StringInfo str, SubPlan *node)
{
M
 
Marc G. Fournier 已提交
453
	appendStringInfo(str, " SUBPLAN :plan ");
V
Vadim B. Mikheev 已提交
454
	_outNode(str, node->plan);
M
 
Marc G. Fournier 已提交
455 456

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

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

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

V
Vadim B. Mikheev 已提交
465 466 467 468
	appendStringInfo(str, " :slink ");
	_outNode(str, node->sublink);
}

469
/*
470
 *	Scan is a subclass of Node
471 472
 */
static void
473
_outScan(StringInfo str, Scan *node)
474
{
475
	appendStringInfo(str, " SCAN ");
476 477
	_outPlanInfo(str, (Plan *) node);

478
	appendStringInfo(str, " :scanrelid %u ", node->scanrelid);
479 480 481
}

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

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

/*
494
 *	IndexScan is a subclass of Scan
495 496
 */
static void
497
_outIndexScan(StringInfo str, IndexScan *node)
498
{
499
	appendStringInfo(str, " INDEXSCAN ");
500 501
	_outPlanInfo(str, (Plan *) node);

502
	appendStringInfo(str, " :scanrelid %u :indxid ", node->scan.scanrelid);
503 504
	_outIntList(str, node->indxid);

505
	appendStringInfo(str, " :indxqual ");
506 507
	_outNode(str, node->indxqual);

V
Vadim B. Mikheev 已提交
508 509 510
	appendStringInfo(str, " :indxqualorig ");
	_outNode(str, node->indxqualorig);

511
	appendStringInfo(str, " :indxorderdir %d ", node->indxorderdir);
512 513
}

514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
/*
 *	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);

}

531
/*
532
 *	Material is a subclass of Plan
533 534 535 536 537 538 539 540
 */
static void
_outMaterial(StringInfo str, Material *node)
{
	appendStringInfo(str, " MATERIAL ");
	_outPlanInfo(str, (Plan *) node);
}

541
/*
542
 *	Sort is a subclass of Plan
543 544
 */
static void
545
_outSort(StringInfo str, Sort *node)
546
{
547
	appendStringInfo(str, " SORT ");
548
	_outPlanInfo(str, (Plan *) node);
549
	appendStringInfo(str, " :keycount %d ", node->keycount);
550 551 552
}

static void
B
Bruce Momjian 已提交
553
_outAgg(StringInfo str, Agg *node)
554
{
555
	appendStringInfo(str, " AGG ");
556
	_outPlanInfo(str, (Plan *) node);
557 558 559
}

static void
560
_outGroup(StringInfo str, Group *node)
561
{
562
	appendStringInfo(str, " GRP ");
563 564 565
	_outPlanInfo(str, (Plan *) node);

	/* the actual Group fields */
M
 
Marc G. Fournier 已提交
566
	appendStringInfo(str, " :numCols %d :tuplePerGroup %s ",
B
Bruce Momjian 已提交
567 568
					 node->numCols,
					 node->tuplePerGroup ? "true" : "false");
569
}
570

571
static void
572
_outUnique(StringInfo str, Unique *node)
573
{
574 575
	int		i;

576
	appendStringInfo(str, " UNIQUE ");
577 578
	_outPlanInfo(str, (Plan *) node);

579
	appendStringInfo(str, " :numCols %d :uniqColIdx ",
580
					 node->numCols);
581 582 583
	for (i = 0; i < node->numCols; i++)
		appendStringInfo(str, "%d ", (int) node->uniqColIdx[i]);
}
584 585

/*
586
 *	Hash is a subclass of Plan
587 588
 */
static void
589
_outHash(StringInfo str, Hash *node)
590
{
591
	appendStringInfo(str, " HASH ");
592 593
	_outPlanInfo(str, (Plan *) node);

594
	appendStringInfo(str, " :hashkey ");
595
	_outNode(str, node->hashkey);
596 597 598 599
}

/*****************************************************************************
 *
600
 *	Stuff from primnodes.h.
601 602 603 604
 *
 *****************************************************************************/

/*
605
 *	Resdom is a subclass of Node
606 607
 */
static void
608
_outResdom(StringInfo str, Resdom *node)
609
{
610
	appendStringInfo(str,
611
				 " RESDOM :resno %d :restype %u :restypmod %d :resname ",
B
Bruce Momjian 已提交
612 613 614
					 node->resno,
					 node->restype,
					 node->restypmod);
615 616
	_outToken(str, node->resname);
	appendStringInfo(str, " :reskey %d :reskeyop %u :ressortgroupref %d :resjunk %s ",
B
Bruce Momjian 已提交
617
					 node->reskey,
618
					 node->reskeyop,
619
					 node->ressortgroupref,
B
Bruce Momjian 已提交
620
					 node->resjunk ? "true" : "false");
621 622 623
}

static void
624
_outFjoin(StringInfo str, Fjoin *node)
625
{
626
	int			i;
627

M
 
Marc G. Fournier 已提交
628
	appendStringInfo(str, " FJOIN :initialized %s :nNodes %d ",
B
Bruce Momjian 已提交
629 630
					 node->fj_initialized ? "true" : "false",
					 node->fj_nNodes);
631 632 633 634

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

B
Bruce Momjian 已提交
635 636
	appendStringInfo(str, " :results @ 0x%x :alwaysdone",
					 (int) node->fj_results);
637 638

	for (i = 0; i < node->fj_nNodes; i++)
639
		appendStringInfo(str, (node->fj_alwaysDone[i]) ? "true" : "false");
640 641 642
}

/*
643
 *	Expr is a subclass of Node
644 645
 */
static void
646
_outExpr(StringInfo str, Expr *node)
647
{
648
	char	   *opstr = NULL;
649

M
 
Marc G. Fournier 已提交
650
	appendStringInfo(str, " EXPR :typeOid %u ",
B
Bruce Momjian 已提交
651
					 node->typeOid);
652 653 654

	switch (node->opType)
	{
655 656 657 658 659 660 661 662 663 664 665 666 667 668 669
		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 已提交
670 671 672
		case SUBPLAN_EXPR:
			opstr = "subp";
			break;
673
	}
674 675 676
	appendStringInfo(str, " :opType ");
	_outToken(str, opstr);
	appendStringInfo(str, " :oper ");
677
	_outNode(str, node->oper);
M
 
Marc G. Fournier 已提交
678

679
	appendStringInfo(str, " :args ");
680
	_outNode(str, node->args);
681 682 683
}

/*
684
 *	Var is a subclass of Expr
685 686
 */
static void
687
_outVar(StringInfo str, Var *node)
688
{
B
Bruce Momjian 已提交
689 690 691 692 693 694
	appendStringInfo(str,
				" VAR :varno %d :varattno %d :vartype %u :vartypmod %d ",
					 node->varno,
					 node->varattno,
					 node->vartype,
					 node->vartypmod);
M
 
Marc G. Fournier 已提交
695

B
Bruce Momjian 已提交
696 697 698 699
	appendStringInfo(str, " :varlevelsup %u :varnoold %d :varoattno %d",
					 node->varlevelsup,
					 node->varnoold,
					 node->varoattno);
700 701 702
}

/*
703
 *	Const is a subclass of Expr
704 705
 */
static void
706
_outConst(StringInfo str, Const *node)
707
{
B
Bruce Momjian 已提交
708 709 710 711 712
	appendStringInfo(str,
		" CONST :consttype %u :constlen %d :constisnull %s :constvalue ",
					 node->consttype,
					 node->constlen,
					 node->constisnull ? "true" : "false");
M
 
Marc G. Fournier 已提交
713

714
	if (node->constisnull)
B
Bruce Momjian 已提交
715
		appendStringInfo(str, "<>");
716 717
	else
		_outDatum(str, node->constvalue, node->consttype);
M
 
Marc G. Fournier 已提交
718

B
Bruce Momjian 已提交
719 720
	appendStringInfo(str, " :constbyval %s ",
					 node->constbyval ? "true" : "false");
721 722 723
}

/*
B
Bruce Momjian 已提交
724
 *	Aggref
725 726
 */
static void
727
_outAggref(StringInfo str, Aggref *node)
728
{
729 730 731
	appendStringInfo(str, " AGGREG :aggname ");
	_outToken(str, node->aggname);
	appendStringInfo(str, " :basetype %u :aggtype %u :target ",
732
					 node->basetype, node->aggtype);
733
	_outNode(str, node->target);
M
 
Marc G. Fournier 已提交
734

735
	appendStringInfo(str, " :aggstar %s :aggdistinct %s ",
736 737 738
					 node->aggstar ? "true" : "false",
					 node->aggdistinct ? "true" : "false");
	/* aggno is not dumped */
739 740
}

741 742 743 744 745 746
/*
 *	SubLink
 */
static void
_outSubLink(StringInfo str, SubLink *node)
{
B
Bruce Momjian 已提交
747 748 749 750
	appendStringInfo(str,
					 " SUBLINK :subLinkType %d :useor %s :lefthand ",
					 node->subLinkType,
					 node->useor ? "true" : "false");
751
	_outNode(str, node->lefthand);
M
 
Marc G. Fournier 已提交
752

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

756 757 758 759
	appendStringInfo(str, " :subselect ");
	_outNode(str, node->subselect);
}

760 761 762 763 764 765 766 767 768 769 770 771 772
/*
 *	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);
}

773
/*
774
 *	Array is a subclass of Expr
775 776
 */
static void
B
Bruce Momjian 已提交
777
_outArray(StringInfo str, Array *node)
778
{
779
	int			i;
780

B
Bruce Momjian 已提交
781 782 783 784 785
	appendStringInfo(str,
	  " ARRAY :arrayelemtype %u :arrayelemlength %d :arrayelembyval %c ",
					 node->arrayelemtype,
					 node->arrayelemlength,
					 node->arrayelembyval ? 't' : 'f');
M
 
Marc G. Fournier 已提交
786

M
 
Marc G. Fournier 已提交
787
	appendStringInfo(str, " :arrayndim %d :arraylow ", node->arrayndim);
788
	for (i = 0; i < node->arrayndim; i++)
M
 
Marc G. Fournier 已提交
789
		appendStringInfo(str, " %d ", node->arraylow.indx[i]);
790
	appendStringInfo(str, " :arrayhigh ");
791
	for (i = 0; i < node->arrayndim; i++)
M
 
Marc G. Fournier 已提交
792 793
		appendStringInfo(str, " %d ", node->arrayhigh.indx[i]);
	appendStringInfo(str, " :arraylen %d ", node->arraylen);
794 795 796
}

/*
797
 *	ArrayRef is a subclass of Expr
798 799
 */
static void
B
Bruce Momjian 已提交
800
_outArrayRef(StringInfo str, ArrayRef *node)
801
{
B
Bruce Momjian 已提交
802
	appendStringInfo(str,
T
Tom Lane 已提交
803
		" ARRAYREF :refelemtype %u :refattrlength %d :refelemlength %d ",
B
Bruce Momjian 已提交
804 805 806
					 node->refelemtype,
					 node->refattrlength,
					 node->refelemlength);
M
 
Marc G. Fournier 已提交
807

B
Bruce Momjian 已提交
808 809
	appendStringInfo(str, " :refelembyval %c :refupperindex ",
					 node->refelembyval ? 't' : 'f');
810 811
	_outNode(str, node->refupperindexpr);

812
	appendStringInfo(str, " :reflowerindex ");
813 814
	_outNode(str, node->reflowerindexpr);

815
	appendStringInfo(str, " :refexpr ");
816 817
	_outNode(str, node->refexpr);

818
	appendStringInfo(str, " :refassgnexpr ");
819
	_outNode(str, node->refassgnexpr);
820 821 822
}

/*
823
 *	Func is a subclass of Expr
824 825
 */
static void
826
_outFunc(StringInfo str, Func *node)
827
{
B
Bruce Momjian 已提交
828 829 830 831 832 833
	appendStringInfo(str,
		   " FUNC :funcid %u :functype %u :funcisindex %s :funcsize %d ",
					 node->funcid,
					 node->functype,
					 node->funcisindex ? "true" : "false",
					 node->funcsize);
M
 
Marc G. Fournier 已提交
834 835

	appendStringInfo(str, " :func_fcache @ 0x%x :func_tlist ",
B
Bruce Momjian 已提交
836
					 (int) node->func_fcache);
837 838 839 840
	_outNode(str, node->func_tlist);

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

/*
844
 *	Oper is a subclass of Expr
845 846
 */
static void
847
_outOper(StringInfo str, Oper *node)
848
{
B
Bruce Momjian 已提交
849 850 851 852 853
	appendStringInfo(str,
					 " OPER :opno %u :opid %u :opresulttype %u ",
					 node->opno,
					 node->opid,
					 node->opresulttype);
854 855 856
}

/*
857
 *	Param is a subclass of Expr
858 859
 */
static void
860
_outParam(StringInfo str, Param *node)
861
{
862
	appendStringInfo(str, " PARAM :paramkind %d :paramid %d :paramname ",
B
Bruce Momjian 已提交
863
					 node->paramkind,
864 865 866
					 node->paramid);
	_outToken(str, node->paramname);
	appendStringInfo(str, " :paramtype %u :param_tlist ",
B
Bruce Momjian 已提交
867
					 node->paramtype);
868
	_outNode(str, node->param_tlist);
869 870 871
}

/*
872
 *	Stuff from execnodes.h
873 874 875
 */

/*
876
 *	EState is a subclass of Node.
877 878
 */
static void
879
_outEState(StringInfo str, EState *node)
880
{
B
Bruce Momjian 已提交
881 882 883
	appendStringInfo(str,
					 " ESTATE :direction %d :range_table ",
					 node->es_direction);
884 885
	_outNode(str, node->es_range_table);

M
 
Marc G. Fournier 已提交
886
	appendStringInfo(str, " :result_relation_info @ 0x%x ",
B
Bruce Momjian 已提交
887
					 (int) (node->es_result_relation_info));
888 889 890
}

/*
891
 *	Stuff from relation.h
892
 */
893

894
static void
895
_outRelOptInfo(StringInfo str, RelOptInfo *node)
896
{
M
 
Marc G. Fournier 已提交
897
	appendStringInfo(str, " RELOPTINFO :relids ");
898 899
	_outIntList(str, node->relids);

B
Bruce Momjian 已提交
900
	appendStringInfo(str,
901
					 " :rows %.0f :width %d :indexed %s :pages %ld :tuples %.0f :targetlist ",
902 903
					 node->rows,
					 node->width,
B
Bruce Momjian 已提交
904 905
					 node->indexed ? "true" : "false",
					 node->pages,
906
					 node->tuples);
907 908
	_outNode(str, node->targetlist);

909
	appendStringInfo(str, " :pathlist ");
910 911
	_outNode(str, node->pathlist);

912 913 914 915
	appendStringInfo(str, " :cheapest_startup_path ");
	_outNode(str, node->cheapest_startup_path);
	appendStringInfo(str, " :cheapest_total_path ");
	_outNode(str, node->cheapest_total_path);
916

B
Bruce Momjian 已提交
917
	appendStringInfo(str,
918
					 " :pruneable %s :baserestrictinfo ",
B
Bruce Momjian 已提交
919
					 node->pruneable ? "true" : "false");
920
	_outNode(str, node->baserestrictinfo);
921

922
	appendStringInfo(str, " :joininfo ");
923 924
	_outNode(str, node->joininfo);

925
	appendStringInfo(str, " :innerjoin ");
926
	_outNode(str, node->innerjoin);
927 928
}

929 930 931 932 933 934 935 936 937
static void
_outIndexOptInfo(StringInfo str, IndexOptInfo *node)
{
	appendStringInfo(str, " INDEXOPTINFO :indexoid %u :pages %ld :tuples %g ",
					 node->indexoid,
					 node->pages,
					 node->tuples);
}

938
/*
939
 *	TargetEntry is a subclass of Node.
940 941
 */
static void
942
_outTargetEntry(StringInfo str, TargetEntry *node)
943
{
M
 
Marc G. Fournier 已提交
944
	appendStringInfo(str, " TARGETENTRY :resdom ");
945 946
	_outNode(str, node->resdom);

947 948
	appendStringInfo(str, " :expr ");
	_outNode(str, node->expr);
949
}
950 951

static void
952
_outRangeTblEntry(StringInfo str, RangeTblEntry *node)
953
{
954 955
	appendStringInfo(str, " RTE :relname ");
	_outToken(str, node->relname);
956 957
	appendStringInfo(str, " :ref ");
	_outNode(str, node->ref);
B
Bruce Momjian 已提交
958
	appendStringInfo(str,
959
			 " :relid %u :inh %s :inFromCl %s :inJoinSet %s :skipAcl %s",
B
Bruce Momjian 已提交
960 961 962
					 node->relid,
					 node->inh ? "true" : "false",
					 node->inFromCl ? "true" : "false",
963
					 node->inJoinSet ? "true" : "false",
B
Bruce Momjian 已提交
964
					 node->skipAcl ? "true" : "false");
965
}
966

967
static void
968
_outRowMark(StringInfo str, RowMark *node)
969 970 971 972
{
	appendStringInfo(str, " ROWMARK :rti %u :info %u", node->rti, node->info);
}

973
/*
974
 *	Path is a subclass of Node.
975 976
 */
static void
977
_outPath(StringInfo str, Path *node)
978
{
979
	appendStringInfo(str,
980
	 " PATH :pathtype %d :startup_cost %.2f :total_cost %.2f :pathkeys ",
B
Bruce Momjian 已提交
981
					 node->pathtype,
982 983
					 node->startup_cost,
					 node->total_cost);
984
	_outNode(str, node->pathkeys);
985 986 987
}

/*
988
 *	IndexPath is a subclass of Path.
989 990
 */
static void
991
_outIndexPath(StringInfo str, IndexPath *node)
992
{
B
Bruce Momjian 已提交
993
	appendStringInfo(str,
994
					 " INDEXPATH :pathtype %d :startup_cost %.2f :total_cost %.2f :pathkeys ",
B
Bruce Momjian 已提交
995
					 node->path.pathtype,
996 997
					 node->path.startup_cost,
					 node->path.total_cost);
998
	_outNode(str, node->path.pathkeys);
999

1000
	appendStringInfo(str, " :indexid ");
1001 1002
	_outIntList(str, node->indexid);

1003
	appendStringInfo(str, " :indexqual ");
1004
	_outNode(str, node->indexqual);
1005

1006 1007
	appendStringInfo(str, " :indexscandir %d :joinrelids ",
					 (int) node->indexscandir);
1008
	_outIntList(str, node->joinrelids);
1009 1010 1011

	appendStringInfo(str, " :rows %.2f ",
					 node->rows);
1012 1013
}

1014 1015 1016 1017 1018 1019 1020
/*
 *	TidPath is a subclass of Path.
 */
static void
_outTidPath(StringInfo str, TidPath *node)
{
	appendStringInfo(str,
1021
					 " TIDPATH :pathtype %d :startup_cost %.2f :total_cost %.2f :pathkeys ",
1022
					 node->path.pathtype,
1023 1024
					 node->path.startup_cost,
					 node->path.total_cost);
1025 1026 1027 1028 1029 1030 1031 1032 1033
	_outNode(str, node->path.pathkeys);

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

	appendStringInfo(str, " :un joined_relids ");
	_outIntList(str, node->unjoined_relids);
}

1034
/*
1035
 *	NestPath is a subclass of Path
1036 1037
 */
static void
1038
_outNestPath(StringInfo str, NestPath *node)
1039
{
B
Bruce Momjian 已提交
1040
	appendStringInfo(str,
1041
					 " NESTPATH :pathtype %d :startup_cost %.2f :total_cost %.2f :pathkeys ",
B
Bruce Momjian 已提交
1042
					 node->path.pathtype,
1043 1044
					 node->path.startup_cost,
					 node->path.total_cost);
1045
	_outNode(str, node->path.pathkeys);
1046 1047 1048 1049 1050 1051
	appendStringInfo(str, " :outerjoinpath ");
	_outNode(str, node->outerjoinpath);
	appendStringInfo(str, " :innerjoinpath ");
	_outNode(str, node->innerjoinpath);
	appendStringInfo(str, " :joinrestrictinfo ");
	_outNode(str, node->joinrestrictinfo);
1052 1053 1054
}

/*
1055
 *	MergePath is a subclass of NestPath.
1056 1057
 */
static void
1058
_outMergePath(StringInfo str, MergePath *node)
1059
{
B
Bruce Momjian 已提交
1060
	appendStringInfo(str,
1061
					 " MERGEPATH :pathtype %d :startup_cost %.2f :total_cost %.2f :pathkeys ",
B
Bruce Momjian 已提交
1062
					 node->jpath.path.pathtype,
1063 1064
					 node->jpath.path.startup_cost,
					 node->jpath.path.total_cost);
1065
	_outNode(str, node->jpath.path.pathkeys);
1066 1067 1068 1069 1070 1071
	appendStringInfo(str, " :outerjoinpath ");
	_outNode(str, node->jpath.outerjoinpath);
	appendStringInfo(str, " :innerjoinpath ");
	_outNode(str, node->jpath.innerjoinpath);
	appendStringInfo(str, " :joinrestrictinfo ");
	_outNode(str, node->jpath.joinrestrictinfo);
1072

1073
	appendStringInfo(str, " :path_mergeclauses ");
1074 1075
	_outNode(str, node->path_mergeclauses);

1076
	appendStringInfo(str, " :outersortkeys ");
1077 1078
	_outNode(str, node->outersortkeys);

1079
	appendStringInfo(str, " :innersortkeys ");
1080
	_outNode(str, node->innersortkeys);
1081 1082 1083
}

/*
1084
 *	HashPath is a subclass of NestPath.
1085 1086
 */
static void
1087
_outHashPath(StringInfo str, HashPath *node)
1088
{
B
Bruce Momjian 已提交
1089
	appendStringInfo(str,
1090
					 " HASHPATH :pathtype %d :startup_cost %.2f :total_cost %.2f :pathkeys ",
B
Bruce Momjian 已提交
1091
					 node->jpath.path.pathtype,
1092 1093
					 node->jpath.path.startup_cost,
					 node->jpath.path.total_cost);
1094
	_outNode(str, node->jpath.path.pathkeys);
1095 1096 1097 1098 1099 1100
	appendStringInfo(str, " :outerjoinpath ");
	_outNode(str, node->jpath.outerjoinpath);
	appendStringInfo(str, " :innerjoinpath ");
	_outNode(str, node->jpath.innerjoinpath);
	appendStringInfo(str, " :joinrestrictinfo ");
	_outNode(str, node->jpath.joinrestrictinfo);
1101

1102
	appendStringInfo(str, " :path_hashclauses ");
1103
	_outNode(str, node->path_hashclauses);
1104 1105 1106
}

/*
1107
 *	PathKeyItem is a subclass of Node.
1108 1109
 */
static void
1110
_outPathKeyItem(StringInfo str, PathKeyItem *node)
1111
{
1112 1113 1114
	appendStringInfo(str, " PATHKEYITEM :sortop %u :key ",
					 node->sortop);
	_outNode(str, node->key);
1115 1116 1117
}

/*
1118
 *	RestrictInfo is a subclass of Node.
1119 1120
 */
static void
1121
_outRestrictInfo(StringInfo str, RestrictInfo *node)
1122
{
B
Bruce Momjian 已提交
1123
	appendStringInfo(str, " RESTRICTINFO :clause ");
1124 1125
	_outNode(str, node->clause);

1126
	appendStringInfo(str, " :subclauseindices ");
1127
	_outNode(str, node->subclauseindices);
1128

1129 1130 1131
	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 已提交
1132
	appendStringInfo(str, " :hashjoinoperator %u ", node->hashjoinoperator);
1133 1134 1135
}

/*
1136
 *	JoinInfo is a subclass of Node.
1137 1138
 */
static void
1139
_outJoinInfo(StringInfo str, JoinInfo *node)
1140
{
B
Bruce Momjian 已提交
1141 1142
	appendStringInfo(str, " JINFO :unjoined_relids ");
	_outIntList(str, node->unjoined_relids);
1143

1144 1145
	appendStringInfo(str, " :jinfo_restrictinfo ");
	_outNode(str, node->jinfo_restrictinfo);
1146 1147 1148 1149 1150 1151 1152 1153
}

/*
 * Print the value of a Datum given its type.
 */
static void
_outDatum(StringInfo str, Datum value, Oid type)
{
1154
	bool		byValue;
1155 1156 1157
	int			typeLength;
	Size		length;
	char	   *s;
1158
	int			i;
1159 1160 1161 1162 1163 1164 1165

	/*
	 * find some information about the type and the "real" length of the
	 * datum.
	 */
	byValue = get_typbyval(type);
	typeLength = get_typlen(type);
1166
	length = datumGetSize(value, byValue, typeLength);
1167 1168 1169 1170

	if (byValue)
	{
		s = (char *) (&value);
1171
		appendStringInfo(str, " %u [ ", (unsigned int) length);
1172
		for (i = 0; i < (int) sizeof(Datum); i++)
1173
			appendStringInfo(str, "%d ", (int) (s[i]));
M
 
Marc G. Fournier 已提交
1174
		appendStringInfo(str, "] ");
1175
	}
1176 1177 1178 1179
	else
	{							/* !byValue */
		s = (char *) DatumGetPointer(value);
		if (!PointerIsValid(s))
M
 
Marc G. Fournier 已提交
1180
			appendStringInfo(str, " 0 [ ] ");
1181 1182
		else
		{
1183
			appendStringInfo(str, " %u [ ", (unsigned int) length);
1184
			for (i = 0; i < (int) length; i++)
1185
				appendStringInfo(str, "%d ", (int) (s[i]));
M
 
Marc G. Fournier 已提交
1186
			appendStringInfo(str, "] ");
1187
		}
1188 1189 1190 1191
	}
}

static void
1192
_outIter(StringInfo str, Iter *node)
1193
{
M
 
Marc G. Fournier 已提交
1194
	appendStringInfo(str, " ITER :iterexpr ");
1195
	_outNode(str, node->iterexpr);
1196 1197 1198
}

static void
1199
_outStream(StringInfo str, Stream *node)
1200
{
B
Bruce Momjian 已提交
1201 1202 1203 1204 1205 1206
	appendStringInfo(str,
					 " STREAM :pathptr @ 0x%x :cinfo @ 0x%x :clausetype %d :upstream @ 0x%x ",
					 (int) node->pathptr,
					 (int) node->cinfo,
					 (int) node->clausetype,
					 (int) node->upstream);
1207

B
Bruce Momjian 已提交
1208 1209 1210 1211 1212 1213
	appendStringInfo(str,
		   " :downstream @ 0x%x :groupup %d :groupcost %f :groupsel %f ",
					 (int) node->downstream,
					 node->groupup,
					 node->groupcost,
					 node->groupsel);
1214
}
1215

1216 1217 1218
static void
_outAExpr(StringInfo str, A_Expr *node)
{
1219
	appendStringInfo(str, " AEXPR ");
1220 1221 1222
	switch (node->oper)
	{
		case AND:
1223
			appendStringInfo(str, "AND ");
1224 1225
			break;
		case OR:
1226
			appendStringInfo(str, "OR ");
1227 1228
			break;
		case NOT:
1229
			appendStringInfo(str, "NOT ");
1230 1231
			break;
		case ISNULL:
1232
			appendStringInfo(str, "ISNULL ");
1233 1234
			break;
		case NOTNULL:
1235
			appendStringInfo(str, "NOTNULL ");
1236
			break;
1237
		case OP:
1238 1239
			_outToken(str, node->opname);
			appendStringInfo(str, " ");
1240
			break;
1241 1242 1243
		default:
			appendStringInfo(str, "?? ");
			break;
1244
	}
1245
	_outNode(str, node->lexpr);
1246
	appendStringInfo(str, " ");
1247 1248 1249
	_outNode(str, node->rexpr);
}

1250
static void
1251
_outValue(StringInfo str, Value *value)
1252
{
1253 1254
	switch (value->type)
	{
1255
			case T_Integer:
1256
			appendStringInfo(str, " %ld ", value->val.ival);
1257 1258
			break;
		case T_Float:
1259 1260 1261 1262

			/*
			 * We assume the value is a valid numeric literal and so does
			 * not need quoting.
1263 1264 1265 1266 1267 1268 1269
			 */
			appendStringInfo(str, " %s ", value->val.str);
			break;
		case T_String:
			appendStringInfo(str, " \"");
			_outToken(str, value->val.str);
			appendStringInfo(str, "\" ");
1270 1271
			break;
		default:
1272 1273
			elog(NOTICE, "_outValue: don't know how to print type %d ",
				 value->type);
1274
			break;
1275
	}
1276 1277
}

1278 1279 1280
static void
_outIdent(StringInfo str, Ident *node)
{
1281 1282
	appendStringInfo(str, " IDENT ");
	_outToken(str, node->name);
1283 1284
}

1285 1286 1287
static void
_outAttr(StringInfo str, Attr *node)
{
1288
	appendStringInfo(str, " ATTR :relname ");
1289
	_outToken(str, node->relname);
1290 1291
	appendStringInfo(str, " :attrs ");
	_outNode(str, node->attrs);
1292 1293
}

1294 1295 1296
static void
_outAConst(StringInfo str, A_Const *node)
{
1297
	appendStringInfo(str, "CONST ");
1298
	_outValue(str, &(node->val));
1299 1300
	appendStringInfo(str, " :typename ");
	_outNode(str, node->typename);
1301 1302
}

T
Thomas G. Lockhart 已提交
1303 1304 1305
static void
_outConstraint(StringInfo str, Constraint *node)
{
1306 1307 1308
	appendStringInfo(str, " ");
	_outToken(str, node->name);
	appendStringInfo(str, " :type ");
T
Thomas G. Lockhart 已提交
1309 1310 1311 1312

	switch (node->contype)
	{
		case CONSTR_PRIMARY:
1313
			appendStringInfo(str, "PRIMARY KEY ");
T
Thomas G. Lockhart 已提交
1314 1315 1316 1317
			_outNode(str, node->keys);
			break;

		case CONSTR_CHECK:
1318
			appendStringInfo(str, "CHECK :raw ");
1319
			_outNode(str, node->raw_expr);
1320 1321
			appendStringInfo(str, " :cooked ");
			_outToken(str, node->cooked_expr);
T
Thomas G. Lockhart 已提交
1322 1323 1324
			break;

		case CONSTR_DEFAULT:
1325
			appendStringInfo(str, "DEFAULT :raw ");
1326
			_outNode(str, node->raw_expr);
1327 1328
			appendStringInfo(str, " :cooked ");
			_outToken(str, node->cooked_expr);
T
Thomas G. Lockhart 已提交
1329 1330 1331
			break;

		case CONSTR_NOTNULL:
1332
			appendStringInfo(str, "NOT NULL");
T
Thomas G. Lockhart 已提交
1333 1334 1335
			break;

		case CONSTR_UNIQUE:
1336
			appendStringInfo(str, "UNIQUE ");
T
Thomas G. Lockhart 已提交
1337 1338 1339 1340
			_outNode(str, node->keys);
			break;

		default:
1341
			appendStringInfo(str, "<unrecognized_constraint>");
T
Thomas G. Lockhart 已提交
1342 1343 1344 1345 1346
			break;
	}
}

static void
1347
_outCaseExpr(StringInfo str, CaseExpr *node)
T
Thomas G. Lockhart 已提交
1348
{
1349 1350 1351 1352 1353
	appendStringInfo(str, " CASE :casetype %u :arg ",
					 node->casetype);
	_outNode(str, node->arg);

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

1356
	appendStringInfo(str, " :defresult ");
T
Thomas G. Lockhart 已提交
1357 1358 1359 1360
	_outNode(str, node->defresult);
}

static void
1361
_outCaseWhen(StringInfo str, CaseWhen *node)
T
Thomas G. Lockhart 已提交
1362
{
1363
	appendStringInfo(str, " WHEN ");
T
Thomas G. Lockhart 已提交
1364
	_outNode(str, node->expr);
M
 
Marc G. Fournier 已提交
1365

1366
	appendStringInfo(str, " :then ");
T
Thomas G. Lockhart 已提交
1367 1368 1369
	_outNode(str, node->result);
}

1370 1371
/*
 * _outNode -
1372
 *	  converts a Node into ascii string and append it to 'str'
1373 1374 1375 1376
 */
static void
_outNode(StringInfo str, void *obj)
{
1377 1378
	if (obj == NULL)
	{
B
Bruce Momjian 已提交
1379
		appendStringInfo(str, "<>");
1380 1381
		return;
	}
1382

1383
	if (IsA(obj, List))
1384
	{
1385
		List	   *l;
1386

1387
		appendStringInfoChar(str, '(');
1388 1389 1390 1391
		foreach(l, (List *) obj)
		{
			_outNode(str, lfirst(l));
			if (lnext(l))
1392
				appendStringInfoChar(str, ' ');
1393
		}
1394
		appendStringInfoChar(str, ')');
1395
	}
1396 1397 1398 1399 1400
	else if (IsA_Value(obj))
	{
		/* nodeRead does not want to see { } around these! */
		_outValue(str, obj);
	}
1401 1402
	else
	{
1403
		appendStringInfoChar(str, '{');
1404 1405
		switch (nodeTag(obj))
		{
1406 1407 1408 1409 1410 1411 1412 1413 1414
			case T_CreateStmt:
				_outCreateStmt(str, obj);
				break;
			case T_IndexStmt:
				_outIndexStmt(str, obj);
				break;
			case T_ColumnDef:
				_outColumnDef(str, obj);
				break;
1415 1416 1417
			case T_TypeName:
				_outTypeName(str, obj);
				break;
1418 1419 1420
			case T_TypeCast:
				_outTypeCast(str, obj);
				break;
1421 1422 1423
			case T_IndexElem:
				_outIndexElem(str, obj);
				break;
1424 1425 1426
			case T_Query:
				_outQuery(str, obj);
				break;
1427 1428 1429 1430 1431
			case T_SortClause:
				_outSortClause(str, obj);
				break;
			case T_GroupClause:
				_outGroupClause(str, obj);
1432
				break;
1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462
			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;
1463 1464 1465
			case T_TidScan:
				_outTidScan(str, obj);
				break;
1466 1467 1468
			case T_Material:
				_outMaterial(str, obj);
				break;
1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483
			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;
			case T_Hash:
				_outHash(str, obj);
				break;
V
Vadim B. Mikheev 已提交
1484 1485 1486
			case T_SubPlan:
				_outSubPlan(str, obj);
				break;
1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501
			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 已提交
1502 1503
			case T_Aggref:
				_outAggref(str, obj);
1504
				break;
1505 1506 1507
			case T_SubLink:
				_outSubLink(str, obj);
				break;
1508 1509 1510
			case T_RelabelType:
				_outRelabelType(str, obj);
				break;
1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528
			case T_Array:
				_outArray(str, obj);
				break;
			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;
			case T_EState:
				_outEState(str, obj);
				break;
B
Bruce Momjian 已提交
1529
			case T_RelOptInfo:
B
Bruce Momjian 已提交
1530
				_outRelOptInfo(str, obj);
1531
				break;
1532 1533 1534
			case T_IndexOptInfo:
				_outIndexOptInfo(str, obj);
				break;
1535 1536 1537 1538 1539 1540
			case T_TargetEntry:
				_outTargetEntry(str, obj);
				break;
			case T_RangeTblEntry:
				_outRangeTblEntry(str, obj);
				break;
1541 1542 1543
			case T_RowMark:
				_outRowMark(str, obj);
				break;
1544 1545 1546 1547 1548 1549
			case T_Path:
				_outPath(str, obj);
				break;
			case T_IndexPath:
				_outIndexPath(str, obj);
				break;
1550 1551 1552
			case T_TidPath:
				_outTidPath(str, obj);
				break;
1553 1554
			case T_NestPath:
				_outNestPath(str, obj);
1555 1556 1557 1558 1559 1560 1561
				break;
			case T_MergePath:
				_outMergePath(str, obj);
				break;
			case T_HashPath:
				_outHashPath(str, obj);
				break;
1562 1563
			case T_PathKeyItem:
				_outPathKeyItem(str, obj);
1564
				break;
1565 1566
			case T_RestrictInfo:
				_outRestrictInfo(str, obj);
1567
				break;
1568 1569
			case T_JoinInfo:
				_outJoinInfo(str, obj);
1570 1571 1572 1573 1574 1575 1576
				break;
			case T_Iter:
				_outIter(str, obj);
				break;
			case T_Stream:
				_outStream(str, obj);
				break;
1577 1578 1579 1580 1581 1582 1583 1584 1585
			case T_A_Expr:
				_outAExpr(str, obj);
				break;
			case T_Ident:
				_outIdent(str, obj);
				break;
			case T_A_Const:
				_outAConst(str, obj);
				break;
T
Thomas G. Lockhart 已提交
1586 1587 1588 1589 1590 1591 1592 1593 1594
			case T_Constraint:
				_outConstraint(str, obj);
				break;
			case T_CaseExpr:
				_outCaseExpr(str, obj);
				break;
			case T_CaseWhen:
				_outCaseWhen(str, obj);
				break;
1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607

			case T_VariableSetStmt:
				break;
			case T_SelectStmt:
				_outSelectStmt(str, obj);
				break;
			case T_FuncCall:
				_outFuncCall(str, obj);
				break;
			case T_Attr:
				_outAttr(str, obj);
				break;

1608
			default:
B
Bruce Momjian 已提交
1609
				elog(NOTICE, "_outNode: don't know how to print type %d ",
1610 1611
					 nodeTag(obj));
				break;
1612
		}
1613
		appendStringInfoChar(str, '}');
1614 1615 1616 1617 1618
	}
}

/*
 * nodeToString -
1619
 *	   returns the ascii representation of the Node as a palloc'd string
1620
 */
1621
char *
1622 1623
nodeToString(void *obj)
{
B
Bruce Momjian 已提交
1624
	StringInfoData str;
1625

1626 1627 1628 1629
	/* see stringinfo.h for an explanation of this maneuver */
	initStringInfo(&str);
	_outNode(&str, obj);
	return str.data;
1630
}