outfuncs.c 36.0 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.108 2000/02/15 20:49:09 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"
B
Bruce Momjian 已提交
39 40 41
#include "utils/datum.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
42

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

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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
/*
 * _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++);
	}
}
85

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

301 302 303
}

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

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

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

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

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

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

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

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

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

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

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

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

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

372 373 374
}

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

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

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

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

394 395 396
}

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

405 406 407
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

}

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

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

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

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

static void
B
Bruce Momjian 已提交
561
_outAgg(StringInfo str, Agg *node)
562
{
563

564
	appendStringInfo(str, " AGG ");
565
	_outPlanInfo(str, (Plan *) node);
566 567 568
}

static void
569
_outGroup(StringInfo str, Group *node)
570
{
571
	appendStringInfo(str, " GRP ");
572 573 574
	_outPlanInfo(str, (Plan *) node);

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

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

589
	appendStringInfo(str, " :nonameid %u :keycount %d :numCols %d ",
B
Bruce Momjian 已提交
590
					 node->nonameid,
591 592
					 node->keycount,
					 node->numCols);
593 594 595 596
}


/*
597
 *	Hash is a subclass of Noname
598 599
 */
static void
600
_outHash(StringInfo str, Hash *node)
601
{
602
	appendStringInfo(str, " HASH ");
603 604
	_outPlanInfo(str, (Plan *) node);

605
	appendStringInfo(str, " :hashkey ");
606
	_outNode(str, node->hashkey);
607 608 609 610
}

/*****************************************************************************
 *
611
 *	Stuff from primnodes.h.
612 613 614 615
 *
 *****************************************************************************/

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

static void
635
_outFjoin(StringInfo str, Fjoin *node)
636
{
637
	int			i;
638

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

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

B
Bruce Momjian 已提交
646 647
	appendStringInfo(str, " :results @ 0x%x :alwaysdone",
					 (int) node->fj_results);
648 649

	for (i = 0; i < node->fj_nNodes; i++)
650
		appendStringInfo(str, (node->fj_alwaysDone[i]) ? "true" : "false");
651 652 653
}

/*
654
 *	Expr is a subclass of Node
655 656
 */
static void
657
_outExpr(StringInfo str, Expr *node)
658
{
659
	char	   *opstr = NULL;
660

M
 
Marc G. Fournier 已提交
661
	appendStringInfo(str, " EXPR :typeOid %u ",
B
Bruce Momjian 已提交
662
					 node->typeOid);
663 664 665

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

690
	appendStringInfo(str, " :args ");
691
	_outNode(str, node->args);
692 693 694
}

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

B
Bruce Momjian 已提交
707 708 709 710
	appendStringInfo(str, " :varlevelsup %u :varnoold %d :varoattno %d",
					 node->varlevelsup,
					 node->varnoold,
					 node->varoattno);
711 712 713
}

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

725
	if (node->constisnull)
B
Bruce Momjian 已提交
726
		appendStringInfo(str, "<>");
727 728
	else
		_outDatum(str, node->constvalue, node->consttype);
M
 
Marc G. Fournier 已提交
729

B
Bruce Momjian 已提交
730 731
	appendStringInfo(str, " :constbyval %s ",
					 node->constbyval ? "true" : "false");
732 733 734
}

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

747 748 749 750 751
	appendStringInfo(str, " :usenulls %s :aggstar %s :aggdistinct %s ",
					 node->usenulls ? "true" : "false",
					 node->aggstar ? "true" : "false",
					 node->aggdistinct ? "true" : "false");
	/* aggno is not dumped */
752 753
}

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

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

769 770 771 772
	appendStringInfo(str, " :subselect ");
	_outNode(str, node->subselect);
}

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 902 903
	 " :rows %.0f :width %d :indexed %s :pages %ld :tuples %.0f :targetlist ",
					 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 980
	appendStringInfo(str,
					 " 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 1012 1013 1014 1015 1016 1017
/*
 *	TidPath is a subclass of Path.
 */
static void
_outTidPath(StringInfo str, TidPath *node)
{
	appendStringInfo(str,
1018
					 " TIDPATH :pathtype %d :startup_cost %.2f :total_cost %.2f :pathkeys ",
1019
					 node->path.pathtype,
1020 1021
					 node->path.startup_cost,
					 node->path.total_cost);
1022 1023 1024 1025 1026 1027 1028 1029 1030
	_outNode(str, node->path.pathkeys);

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

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

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

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

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

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

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

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

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

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

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

1123
	appendStringInfo(str, " :subclauseindices ");
1124
	_outNode(str, node->subclauseindices);
1125

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

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

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

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

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

1181 1182 1183 1184 1185 1186
			/*
			 * 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 已提交
1187
			appendStringInfo(str, " %d [ ", length);
1188
			for (i = 0; i < length; i++)
1189
				appendStringInfo(str, "%d ", (int) (s[i]));
M
 
Marc G. Fournier 已提交
1190
			appendStringInfo(str, "] ");
1191
		}
1192 1193 1194 1195
	}
}

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

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

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

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

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

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

1280 1281 1282
static void
_outAttr(StringInfo str, Attr *node)
{
1283
	appendStringInfo(str, " ATTR :relname ");
1284
	_outToken(str, node->relname);
1285 1286
	appendStringInfo(str, " :attrs ");
	_outNode(str, node->attrs);
1287 1288
}

1289 1290 1291
static void
_outAConst(StringInfo str, A_Const *node)
{
1292
	appendStringInfo(str, "CONST ");
1293
	_outValue(str, &(node->val));
1294 1295
	appendStringInfo(str, " :typename ");
	_outNode(str, node->typename);
1296 1297
}

T
Thomas G. Lockhart 已提交
1298 1299 1300
static void
_outConstraint(StringInfo str, Constraint *node)
{
1301 1302 1303
	appendStringInfo(str, " ");
	_outToken(str, node->name);
	appendStringInfo(str, " :type ");
T
Thomas G. Lockhart 已提交
1304 1305 1306 1307

	switch (node->contype)
	{
		case CONSTR_PRIMARY:
1308
			appendStringInfo(str, "PRIMARY KEY ");
T
Thomas G. Lockhart 已提交
1309 1310 1311 1312
			_outNode(str, node->keys);
			break;

		case CONSTR_CHECK:
1313
			appendStringInfo(str, "CHECK :raw ");
1314
			_outNode(str, node->raw_expr);
1315 1316
			appendStringInfo(str, " :cooked ");
			_outToken(str, node->cooked_expr);
T
Thomas G. Lockhart 已提交
1317 1318 1319
			break;

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

		case CONSTR_NOTNULL:
1327
			appendStringInfo(str, "NOT NULL");
T
Thomas G. Lockhart 已提交
1328 1329 1330
			break;

		case CONSTR_UNIQUE:
1331
			appendStringInfo(str, "UNIQUE ");
T
Thomas G. Lockhart 已提交
1332 1333 1334 1335
			_outNode(str, node->keys);
			break;

		default:
1336
			appendStringInfo(str, "<unrecognized_constraint>");
T
Thomas G. Lockhart 已提交
1337 1338 1339 1340 1341
			break;
	}
}

static void
1342
_outCaseExpr(StringInfo str, CaseExpr *node)
T
Thomas G. Lockhart 已提交
1343
{
1344
	appendStringInfo(str, "CASE ");
T
Thomas G. Lockhart 已提交
1345
	_outNode(str, node->args);
M
 
Marc G. Fournier 已提交
1346

1347
	appendStringInfo(str, " :default ");
T
Thomas G. Lockhart 已提交
1348 1349 1350 1351
	_outNode(str, node->defresult);
}

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

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

1361 1362
/*
 * _outNode -
1363
 *	  converts a Node into ascii string and append it to 'str'
1364 1365 1366 1367
 */
static void
_outNode(StringInfo str, void *obj)
{
1368 1369
	if (obj == NULL)
	{
B
Bruce Momjian 已提交
1370
		appendStringInfo(str, "<>");
1371 1372
		return;
	}
1373

1374
	if (IsA(obj, List))
1375
	{
1376
		List	   *l;
1377

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

			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;

1596
			default:
B
Bruce Momjian 已提交
1597
				elog(NOTICE, "_outNode: don't know how to print type %d ",
1598 1599
					 nodeTag(obj));
				break;
1600
		}
1601
		appendStringInfoChar(str, '}');
1602 1603 1604 1605 1606
	}
}

/*
 * nodeToString -
1607
 *	   returns the ascii representation of the Node as a palloc'd string
1608
 */
1609
char *
1610 1611
nodeToString(void *obj)
{
B
Bruce Momjian 已提交
1612
	StringInfoData str;
1613

1614 1615 1616 1617
	/* see stringinfo.h for an explanation of this maneuver */
	initStringInfo(&str);
	_outNode(&str, obj);
	return str.data;
1618
}