outfuncs.c 35.6 KB
Newer Older
M
 
Marc G. Fournier 已提交
1
/*
2
 *
3
 * outfuncs.c
4
 *	  routines to convert a node to ascii representation
5 6 7
 *
 * Copyright (c) 1994, Regents of the University of California
 *
8
 *	$Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.103 2000/01/17 00:14:47 tgl Exp $
9 10
 *
 * NOTES
11 12 13 14 15
 *	  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.
16
 *
17 18 19
 *	  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.)
20 21
 *
 */
22
#include <ctype.h>
23

24
#include "postgres.h"
25

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

42 43
#include "../parse.h"

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

47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
/*
 * _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;
	}
	/*
	 * Look for characters or patterns that are treated specially by
	 * read.c (either in lsptok() or in nodeRead()), and therefore need
	 * a protective backslash.
	 */
	/* These characters only need to be quoted at the start of the string */
	if (*s == '<' ||
		*s == '\"' ||
		*s == '@' ||
		isdigit(*s) ||
		(*s == '-' && isdigit(s[1])))
		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++);
	}
}
84

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

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

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

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

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

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

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

static void
_outIndexStmt(StringInfo str, IndexStmt *node)
{
122 123 124 125 126 127 128
	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 ");
129
	_outNode(str, node->indexParams);
M
 
Marc G. Fournier 已提交
130

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

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

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

	appendStringInfo(str, " :lossy %s :unique %s ",
B
Bruce Momjian 已提交
141 142
					 node->lossy ? "true" : "false",
					 node->unique ? "true" : "false");
143
}
144

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

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

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

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

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

202 203 204
static void
_outIndexElem(StringInfo str, IndexElem *node)
{
205 206 207
	appendStringInfo(str, " INDEXELEM :name ");
	_outToken(str, node->name);
	appendStringInfo(str, " :args ");
208
	_outNode(str, node->args);
209 210 211
	appendStringInfo(str, " :class ");
	_outToken(str, node->class);
	appendStringInfo(str, " :typename ");
212
	_outNode(str, node->typename);
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 :unique ",
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
	_outToken(str, node->uniqueFlag);
	appendStringInfo(str, " :sortClause ");
265
	_outNode(str, node->sortClause);
M
 
Marc G. Fournier 已提交
266

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

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

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

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

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

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

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

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

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

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

299 300 301
}

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

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

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

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

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

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

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

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

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

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

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

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

366
	appendStringInfo(str, " :resconstantqual ");
367 368
	_outNode(str, node->resconstantqual);

369 370 371
}

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

380 381
	appendStringInfo(str, " :appendplans ");
	_outNode(str, node->appendplans);
382

383 384
	appendStringInfo(str, " :unionrtables ");
	_outNode(str, node->unionrtables);
385

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

391 392 393
}

/*
394
 *	Join is a subclass of Plan
395 396
 */
static void
397
_outJoin(StringInfo str, Join *node)
398
{
399
	appendStringInfo(str, " JOIN ");
400 401
	_outPlanInfo(str, (Plan *) node);

402 403 404
}

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

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

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

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

436
	appendStringInfo(str, " :hashclauses ");
437 438
	_outNode(str, node->hashclauses);

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

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

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

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

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

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

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

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

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

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

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

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

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

503
	appendStringInfo(str, " :indxqual ");
504 505
	_outNode(str, node->indxqual);

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

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

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

}

529
/*
530
 *	Noname is a subclass of Plan
531 532
 */
static void
533
_outNoname(StringInfo str, Noname *node)
534
{
535
	appendStringInfo(str, " NONAME ");
536 537
	_outPlanInfo(str, (Plan *) node);

B
Bruce Momjian 已提交
538 539 540
	appendStringInfo(str, " :nonameid %u :keycount %d ",
					 node->nonameid,
					 node->keycount);
541 542 543
}

/*
544
 *	Sort is a subclass of Noname
545 546
 */
static void
547
_outSort(StringInfo str, Sort *node)
548
{
549
	appendStringInfo(str, " SORT ");
550 551
	_outPlanInfo(str, (Plan *) node);

552
	appendStringInfo(str, " :nonameid %u :keycount %d ",
B
Bruce Momjian 已提交
553 554
					 node->nonameid,
					 node->keycount);
555 556 557
}

static void
B
Bruce Momjian 已提交
558
_outAgg(StringInfo str, Agg *node)
559
{
560

561
	appendStringInfo(str, " AGG ");
562
	_outPlanInfo(str, (Plan *) node);
563 564 565
}

static void
566
_outGroup(StringInfo str, Group *node)
567
{
568
	appendStringInfo(str, " GRP ");
569 570 571
	_outPlanInfo(str, (Plan *) node);

	/* the actual Group fields */
M
 
Marc G. Fournier 已提交
572
	appendStringInfo(str, " :numCols %d :tuplePerGroup %s ",
B
Bruce Momjian 已提交
573 574
					 node->numCols,
					 node->tuplePerGroup ? "true" : "false");
575
}
576

577
/*
578
 *	For some reason, unique is a subclass of Noname.
579 580
 */
static void
581
_outUnique(StringInfo str, Unique *node)
582
{
583
	appendStringInfo(str, " UNIQUE ");
584 585
	_outPlanInfo(str, (Plan *) node);

586
	appendStringInfo(str, " :nonameid %u :keycount %d ",
B
Bruce Momjian 已提交
587 588
					 node->nonameid,
					 node->keycount);
589 590 591 592
}


/*
593
 *	Hash is a subclass of Noname
594 595
 */
static void
596
_outHash(StringInfo str, Hash *node)
597
{
598
	appendStringInfo(str, " HASH ");
599 600
	_outPlanInfo(str, (Plan *) node);

601
	appendStringInfo(str, " :hashkey ");
602
	_outNode(str, node->hashkey);
603 604 605 606
}

/*****************************************************************************
 *
607
 *	Stuff from primnodes.h.
608 609 610 611
 *
 *****************************************************************************/

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

static void
631
_outFjoin(StringInfo str, Fjoin *node)
632
{
633
	int			i;
634

M
 
Marc G. Fournier 已提交
635
	appendStringInfo(str, " FJOIN :initialized %s :nNodes %d ",
B
Bruce Momjian 已提交
636 637
					 node->fj_initialized ? "true" : "false",
					 node->fj_nNodes);
638 639 640 641

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

B
Bruce Momjian 已提交
642 643
	appendStringInfo(str, " :results @ 0x%x :alwaysdone",
					 (int) node->fj_results);
644 645

	for (i = 0; i < node->fj_nNodes; i++)
646
		appendStringInfo(str, (node->fj_alwaysDone[i]) ? "true" : "false");
647 648 649
}

/*
650
 *	Expr is a subclass of Node
651 652
 */
static void
653
_outExpr(StringInfo str, Expr *node)
654
{
655
	char	   *opstr = NULL;
656

M
 
Marc G. Fournier 已提交
657
	appendStringInfo(str, " EXPR :typeOid %u ",
B
Bruce Momjian 已提交
658
					 node->typeOid);
659 660 661

	switch (node->opType)
	{
662 663 664 665 666 667 668 669 670 671 672 673 674 675 676
		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 已提交
677 678 679
		case SUBPLAN_EXPR:
			opstr = "subp";
			break;
680
	}
681 682 683
	appendStringInfo(str, " :opType ");
	_outToken(str, opstr);
	appendStringInfo(str, " :oper ");
684
	_outNode(str, node->oper);
M
 
Marc G. Fournier 已提交
685

686
	appendStringInfo(str, " :args ");
687
	_outNode(str, node->args);
688 689 690
}

/*
691
 *	Var is a subclass of Expr
692 693
 */
static void
694
_outVar(StringInfo str, Var *node)
695
{
B
Bruce Momjian 已提交
696 697 698 699 700 701
	appendStringInfo(str,
				" VAR :varno %d :varattno %d :vartype %u :vartypmod %d ",
					 node->varno,
					 node->varattno,
					 node->vartype,
					 node->vartypmod);
M
 
Marc G. Fournier 已提交
702

B
Bruce Momjian 已提交
703 704 705 706
	appendStringInfo(str, " :varlevelsup %u :varnoold %d :varoattno %d",
					 node->varlevelsup,
					 node->varnoold,
					 node->varoattno);
707 708 709
}

/*
710
 *	Const is a subclass of Expr
711 712
 */
static void
713
_outConst(StringInfo str, Const *node)
714
{
B
Bruce Momjian 已提交
715 716 717 718 719
	appendStringInfo(str,
		" CONST :consttype %u :constlen %d :constisnull %s :constvalue ",
					 node->consttype,
					 node->constlen,
					 node->constisnull ? "true" : "false");
M
 
Marc G. Fournier 已提交
720

721
	if (node->constisnull)
B
Bruce Momjian 已提交
722
		appendStringInfo(str, "<>");
723 724
	else
		_outDatum(str, node->constvalue, node->consttype);
M
 
Marc G. Fournier 已提交
725

B
Bruce Momjian 已提交
726 727
	appendStringInfo(str, " :constbyval %s ",
					 node->constbyval ? "true" : "false");
728 729 730
}

/*
B
Bruce Momjian 已提交
731
 *	Aggref
732 733
 */
static void
734
_outAggref(StringInfo str, Aggref *node)
735
{
736 737 738
	appendStringInfo(str, " AGGREG :aggname ");
	_outToken(str, node->aggname);
	appendStringInfo(str, " :basetype %u :aggtype %u :target ",
B
Bruce Momjian 已提交
739 740
					 node->basetype,
					 node->aggtype);
741
	_outNode(str, node->target);
M
 
Marc G. Fournier 已提交
742

743 744 745 746 747
	appendStringInfo(str, " :usenulls %s :aggstar %s :aggdistinct %s ",
					 node->usenulls ? "true" : "false",
					 node->aggstar ? "true" : "false",
					 node->aggdistinct ? "true" : "false");
	/* aggno is not dumped */
748 749
}

750 751 752 753 754 755
/*
 *	SubLink
 */
static void
_outSubLink(StringInfo str, SubLink *node)
{
B
Bruce Momjian 已提交
756 757 758 759
	appendStringInfo(str,
					 " SUBLINK :subLinkType %d :useor %s :lefthand ",
					 node->subLinkType,
					 node->useor ? "true" : "false");
760
	_outNode(str, node->lefthand);
M
 
Marc G. Fournier 已提交
761

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

765 766 767 768
	appendStringInfo(str, " :subselect ");
	_outNode(str, node->subselect);
}

769
/*
770
 *	Array is a subclass of Expr
771 772
 */
static void
B
Bruce Momjian 已提交
773
_outArray(StringInfo str, Array *node)
774
{
775
	int			i;
776

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

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

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

B
Bruce Momjian 已提交
804 805
	appendStringInfo(str, " :refelembyval %c :refupperindex ",
					 node->refelembyval ? 't' : 'f');
806 807
	_outNode(str, node->refupperindexpr);

808
	appendStringInfo(str, " :reflowerindex ");
809 810
	_outNode(str, node->reflowerindexpr);

811
	appendStringInfo(str, " :refexpr ");
812 813
	_outNode(str, node->refexpr);

814
	appendStringInfo(str, " :refassgnexpr ");
815
	_outNode(str, node->refassgnexpr);
816 817 818
}

/*
819
 *	Func is a subclass of Expr
820 821
 */
static void
822
_outFunc(StringInfo str, Func *node)
823
{
B
Bruce Momjian 已提交
824 825 826 827 828 829
	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 已提交
830 831

	appendStringInfo(str, " :func_fcache @ 0x%x :func_tlist ",
B
Bruce Momjian 已提交
832
					 (int) node->func_fcache);
833 834 835 836
	_outNode(str, node->func_tlist);

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

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

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

/*
868
 *	Stuff from execnodes.h
869 870 871
 */

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

M
 
Marc G. Fournier 已提交
882
	appendStringInfo(str, " :result_relation_info @ 0x%x ",
B
Bruce Momjian 已提交
883
					 (int) (node->es_result_relation_info));
884 885 886
}

/*
887
 *	Stuff from relation.h
888
 */
889

890
static void
891
_outRelOptInfo(StringInfo str, RelOptInfo *node)
892
{
M
 
Marc G. Fournier 已提交
893
	appendStringInfo(str, " RELOPTINFO :relids ");
894 895
	_outIntList(str, node->relids);

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

905
	appendStringInfo(str, " :pathlist ");
906 907 908 909 910 911 912 913
	_outNode(str, node->pathlist);

	/*
	 * Not sure if these are nodes or not.	They're declared as struct
	 * Path *.	Since i don't know, i'll just print the addresses for now.
	 * This can be changed later, if necessary.
	 */

B
Bruce Momjian 已提交
914 915 916 917
	appendStringInfo(str,
					 " :cheapestpath @ 0x%x :pruneable %s :restrictinfo ",
					 (int) node->cheapestpath,
					 node->pruneable ? "true" : "false");
918
	_outNode(str, node->restrictinfo);
919

920
	appendStringInfo(str, " :joininfo ");
921 922
	_outNode(str, node->joininfo);

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

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

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

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

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

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

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

/*
984
 *	IndexPath is a subclass of Path.
985 986
 */
static void
987
_outIndexPath(StringInfo str, IndexPath *node)
988
{
B
Bruce Momjian 已提交
989
	appendStringInfo(str,
990
					 " INDEXPATH :pathtype %d :cost %.2f :pathkeys ",
B
Bruce Momjian 已提交
991 992
					 node->path.pathtype,
					 node->path.path_cost);
993
	_outNode(str, node->path.pathkeys);
994

995
	appendStringInfo(str, " :indexid ");
996 997
	_outIntList(str, node->indexid);

998
	appendStringInfo(str, " :indexqual ");
999
	_outNode(str, node->indexqual);
1000 1001 1002

	appendStringInfo(str, " :joinrelids ");
	_outIntList(str, node->joinrelids);
1003 1004
}

1005 1006 1007 1008 1009 1010 1011
/*
 *	TidPath is a subclass of Path.
 */
static void
_outTidPath(StringInfo str, TidPath *node)
{
	appendStringInfo(str,
1012
					 " TIDPATH :pathtype %d :cost %.2f :pathkeys ",
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
					 node->path.pathtype,
					 node->path.path_cost);
	_outNode(str, node->path.pathkeys);

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

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

1024
/*
1025
 *	NestPath is a subclass of Path
1026 1027
 */
static void
1028
_outNestPath(StringInfo str, NestPath *node)
1029
{
B
Bruce Momjian 已提交
1030
	appendStringInfo(str,
1031
					 " NESTPATH :pathtype %d :cost %.2f :pathkeys ",
B
Bruce Momjian 已提交
1032 1033
					 node->path.pathtype,
					 node->path.path_cost);
1034
	_outNode(str, node->path.pathkeys);
1035 1036 1037 1038 1039 1040

	/*
	 * Not sure if these are nodes; they're declared as "struct path *".
	 * For now, i'll just print the addresses.
	 */

B
Bruce Momjian 已提交
1041
	appendStringInfo(str,
1042
					 " :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x ",
B
Bruce Momjian 已提交
1043
					 (int) node->outerjoinpath,
1044
					 (int) node->innerjoinpath);
1045 1046 1047
}

/*
1048
 *	MergePath is a subclass of NestPath.
1049 1050
 */
static void
1051
_outMergePath(StringInfo str, MergePath *node)
1052
{
B
Bruce Momjian 已提交
1053
	appendStringInfo(str,
1054
					 " MERGEPATH :pathtype %d :cost %.2f :pathkeys ",
B
Bruce Momjian 已提交
1055 1056
					 node->jpath.path.pathtype,
					 node->jpath.path.path_cost);
1057
	_outNode(str, node->jpath.path.pathkeys);
1058 1059 1060 1061 1062 1063

	/*
	 * Not sure if these are nodes; they're declared as "struct path *".
	 * For now, i'll just print the addresses.
	 */

B
Bruce Momjian 已提交
1064
	appendStringInfo(str,
1065
					 " :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x ",
B
Bruce Momjian 已提交
1066
					 (int) node->jpath.outerjoinpath,
1067
					 (int) node->jpath.innerjoinpath);
1068

1069
	appendStringInfo(str, " :path_mergeclauses ");
1070 1071
	_outNode(str, node->path_mergeclauses);

1072
	appendStringInfo(str, " :outersortkeys ");
1073 1074
	_outNode(str, node->outersortkeys);

1075
	appendStringInfo(str, " :innersortkeys ");
1076
	_outNode(str, node->innersortkeys);
1077 1078 1079
}

/*
1080
 *	HashPath is a subclass of NestPath.
1081 1082
 */
static void
1083
_outHashPath(StringInfo str, HashPath *node)
1084
{
B
Bruce Momjian 已提交
1085
	appendStringInfo(str,
1086
					 " HASHPATH :pathtype %d :cost %.2f :pathkeys ",
B
Bruce Momjian 已提交
1087 1088
					 node->jpath.path.pathtype,
					 node->jpath.path.path_cost);
1089
	_outNode(str, node->jpath.path.pathkeys);
1090 1091 1092 1093 1094 1095

	/*
	 * Not sure if these are nodes; they're declared as "struct path *".
	 * For now, i'll just print the addresses.
	 */

B
Bruce Momjian 已提交
1096
	appendStringInfo(str,
1097
					 " :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x ",
B
Bruce Momjian 已提交
1098
					 (int) node->jpath.outerjoinpath,
1099
					 (int) node->jpath.innerjoinpath);
1100

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

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

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

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

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

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

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

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

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

	if (byValue)
	{
		s = (char *) (&value);
M
 
Marc G. Fournier 已提交
1170
		appendStringInfo(str, " %d [ ", length);
1171
		for (i = 0; i < sizeof(Datum); i++)
1172
			appendStringInfo(str, "%d ", (int) (s[i]));
M
 
Marc G. Fournier 已提交
1173
		appendStringInfo(str, "] ");
1174
	}
1175 1176 1177 1178
	else
	{							/* !byValue */
		s = (char *) DatumGetPointer(value);
		if (!PointerIsValid(s))
M
 
Marc G. Fournier 已提交
1179
			appendStringInfo(str, " 0 [ ] ");
1180 1181
		else
		{
B
Bruce Momjian 已提交
1182

1183 1184 1185 1186 1187 1188
			/*
			 * length is unsigned - very bad to do < comparison to -1
			 * without casting it to int first!! -mer 8 Jan 1991
			 */
			if (((int) length) <= -1)
				length = VARSIZE(s);
M
 
Marc G. Fournier 已提交
1189
			appendStringInfo(str, " %d [ ", length);
1190
			for (i = 0; i < length; i++)
1191
				appendStringInfo(str, "%d ", (int) (s[i]));
M
 
Marc G. Fournier 已提交
1192
			appendStringInfo(str, "] ");
1193
		}
1194 1195 1196 1197
	}
}

static void
1198
_outIter(StringInfo str, Iter *node)
1199
{
M
 
Marc G. Fournier 已提交
1200
	appendStringInfo(str, " ITER :iterexpr ");
1201
	_outNode(str, node->iterexpr);
1202 1203 1204
}

static void
1205
_outStream(StringInfo str, Stream *node)
1206
{
B
Bruce Momjian 已提交
1207 1208 1209 1210 1211 1212
	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);
1213

B
Bruce Momjian 已提交
1214 1215 1216 1217 1218 1219
	appendStringInfo(str,
		   " :downstream @ 0x%x :groupup %d :groupcost %f :groupsel %f ",
					 (int) node->downstream,
					 node->groupup,
					 node->groupcost,
					 node->groupsel);
1220
}
1221

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

1252
static void
1253
_outValue(StringInfo str, Value *value)
1254
{
1255 1256
	switch (value->type)
	{
1257 1258 1259 1260
		case T_String:
			appendStringInfo(str, " \"");
			_outToken(str, value->val.str);
			appendStringInfo(str, "\" ");
1261 1262
			break;
		case T_Integer:
1263
			appendStringInfo(str, " %ld ", value->val.ival);
1264 1265
			break;
		case T_Float:
1266
			appendStringInfo(str, " %.17g ", value->val.dval);
1267 1268
			break;
		default:
1269 1270
			elog(NOTICE, "_outValue: don't know how to print type %d ",
				 value->type);
1271
			break;
1272
	}
1273 1274
}

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

1282 1283 1284 1285 1286
static void
_outAttr(StringInfo str, Attr *node)
{
	List	   *l;

1287 1288 1289
	appendStringInfo(str, " ATTR ");
	_outToken(str, node->relname);
	appendStringInfo(str, " (");
1290 1291 1292 1293
	foreach(l, node->attrs)
	{
		_outNode(str, lfirst(l));
		if (lnext(l))
1294
			appendStringInfo(str, " ");
1295 1296 1297 1298
	}
	appendStringInfo(str, ")");
}

1299 1300 1301
static void
_outAConst(StringInfo str, A_Const *node)
{
1302
	appendStringInfo(str, "CONST ");
1303
	_outValue(str, &(node->val));
1304 1305
	appendStringInfo(str, " :typename ");
	_outNode(str, node->typename);
1306 1307
}

T
Thomas G. Lockhart 已提交
1308 1309 1310
static void
_outConstraint(StringInfo str, Constraint *node)
{
1311 1312 1313
	appendStringInfo(str, " ");
	_outToken(str, node->name);
	appendStringInfo(str, " :type ");
T
Thomas G. Lockhart 已提交
1314 1315 1316 1317

	switch (node->contype)
	{
		case CONSTR_PRIMARY:
1318
			appendStringInfo(str, "PRIMARY KEY ");
T
Thomas G. Lockhart 已提交
1319 1320 1321 1322
			_outNode(str, node->keys);
			break;

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

		case CONSTR_DEFAULT:
1330
			appendStringInfo(str, "DEFAULT :raw ");
1331
			_outNode(str, node->raw_expr);
1332 1333
			appendStringInfo(str, " :cooked ");
			_outToken(str, node->cooked_expr);
T
Thomas G. Lockhart 已提交
1334 1335 1336
			break;

		case CONSTR_NOTNULL:
1337
			appendStringInfo(str, "NOT NULL");
T
Thomas G. Lockhart 已提交
1338 1339 1340
			break;

		case CONSTR_UNIQUE:
1341
			appendStringInfo(str, "UNIQUE ");
T
Thomas G. Lockhart 已提交
1342 1343 1344 1345
			_outNode(str, node->keys);
			break;

		default:
1346
			appendStringInfo(str, "<unrecognized_constraint>");
T
Thomas G. Lockhart 已提交
1347 1348 1349 1350 1351
			break;
	}
}

static void
1352
_outCaseExpr(StringInfo str, CaseExpr *node)
T
Thomas G. Lockhart 已提交
1353
{
1354
	appendStringInfo(str, "CASE ");
T
Thomas G. Lockhart 已提交
1355
	_outNode(str, node->args);
M
 
Marc G. Fournier 已提交
1356

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

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

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

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

1384 1385
	if (nodeTag(obj) == T_List)
	{
1386
		List	   *l;
1387

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

			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;

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

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

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