outfuncs.c 35.4 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
 *
B
Bruce Momjian 已提交
8
 *	$Id: outfuncs.c,v 1.88 1999/07/16 04:59:05 momjian 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 23 24 25 26
 *
 */
#include <stdio.h>
#include "postgres.h"

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

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

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

/*
 * _outIntList -
48
 *	   converts a List of integers
49
 */
50
static void
51
_outIntList(StringInfo str, List *list)
52
{
B
Bruce Momjian 已提交
53
	List	   *l;
54

55 56
	appendStringInfo(str, "(");
	foreach(l, list)
B
Bruce Momjian 已提交
57
		appendStringInfo(str, " %d ", lfirsti(l));
58
	appendStringInfo(str, ")");
59 60
}

61 62 63
static void
_outCreateStmt(StringInfo str, CreateStmt *node)
{
B
Bruce Momjian 已提交
64 65
	appendStringInfo(str, " CREATE :relname %s ",
					 stringStringInfo(node->relname));
66 67

	appendStringInfo(str, " :istemp %s ",
B
Bruce Momjian 已提交
68
					 node->istemp ? "true" : "false");
69 70

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

73
	appendStringInfo(str, " :inhRelnames ");
74
	_outNode(str, node->inhRelnames);
M
 
Marc G. Fournier 已提交
75

76
	appendStringInfo(str, " :constraints ");
77
	_outNode(str, node->constraints);
78
}
79 80 81 82

static void
_outIndexStmt(StringInfo str, IndexStmt *node)
{
B
Bruce Momjian 已提交
83 84 85 86 87
	appendStringInfo(str,
		 " INDEX :idxname %s :relname %s :accessMethod %s :indexParams ",
					 stringStringInfo(node->idxname),
					 stringStringInfo(node->relname),
					 stringStringInfo(node->accessMethod));
88
	_outNode(str, node->indexParams);
M
 
Marc G. Fournier 已提交
89

90 91
	appendStringInfo(str, " :withClause ");
	_outNode(str, node->withClause);
M
 
Marc G. Fournier 已提交
92

93 94
	appendStringInfo(str, " :whereClause ");
	_outNode(str, node->whereClause);
M
 
Marc G. Fournier 已提交
95

96 97
	appendStringInfo(str, " :rangetable ");
	_outNode(str, node->rangetable);
M
 
Marc G. Fournier 已提交
98 99

	appendStringInfo(str, " :lossy %s :unique %s ",
B
Bruce Momjian 已提交
100 101
					 node->lossy ? "true" : "false",
					 node->unique ? "true" : "false");
102
}
103

104 105 106
static void
_outSelectStmt(StringInfo str, SelectStmt *node)
{
M
 
Marc G. Fournier 已提交
107
	appendStringInfo(str, "SELECT :where ");
108 109 110 111 112 113
	_outNode(str, node->whereClause);
}

static void
_outFuncCall(StringInfo str, FuncCall *node)
{
M
 
Marc G. Fournier 已提交
114
	appendStringInfo(str, "FUNCTION %s :args ", stringStringInfo(node->funcname));
115 116
	_outNode(str, node->args);
}
117

118 119 120
static void
_outColumnDef(StringInfo str, ColumnDef *node)
{
121
	appendStringInfo(str, " COLUMNDEF :colname %s :typename ",
B
Bruce Momjian 已提交
122
					 stringStringInfo(node->colname));
123
	_outNode(str, node->typename);
M
 
Marc G. Fournier 已提交
124 125

	appendStringInfo(str, " :is_not_null %s :defval %s :constraints ",
B
Bruce Momjian 已提交
126 127
					 node->is_not_null ? "true" : "false",
					 stringStringInfo(node->defval));
128
	_outNode(str, node->constraints);
129 130 131 132 133
}

static void
_outTypeName(StringInfo str, TypeName *node)
{
B
Bruce Momjian 已提交
134 135 136 137 138 139
	appendStringInfo(str,
	 " TYPENAME :name %s :timezone %s :setof %s typmod %d :arrayBounds ",
					 stringStringInfo(node->name),
					 node->timezone ? "true" : "false",
					 node->setof ? "true" : "false",
					 node->typmod);
140 141 142 143

	appendStringInfo(str, " :arrayBounds ");
	_outNode(str, node->arrayBounds);
}
144 145 146 147

static void
_outIndexElem(StringInfo str, IndexElem *node)
{
148
	appendStringInfo(str, " INDEXELEM :name %s :args ",
B
Bruce Momjian 已提交
149
					 stringStringInfo(node->name));
150
	_outNode(str, node->args);
M
 
Marc G. Fournier 已提交
151

M
 
Marc G. Fournier 已提交
152
	appendStringInfo(str, " :class %s :typename ", stringStringInfo(node->class));
153
	_outNode(str, node->typename);
154
}
155

156
static void
157
_outQuery(StringInfo str, Query *node)
158
{
159

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

162 163 164 165 166
	if (node->utilityStmt)
	{
		switch (nodeTag(node->utilityStmt))
		{
			case T_CreateStmt:
M
 
Marc G. Fournier 已提交
167
				appendStringInfo(str, " :create %s ",
B
Bruce Momjian 已提交
168
								 stringStringInfo(((CreateStmt *) (node->utilityStmt))->relname));
169 170 171 172
				_outNode(str, node->utilityStmt);
				break;

			case T_IndexStmt:
M
 
Marc G. Fournier 已提交
173
				appendStringInfo(str, " :index %s on %s ",
B
Bruce Momjian 已提交
174 175
								 stringStringInfo(((IndexStmt *) (node->utilityStmt))->idxname),
								 stringStringInfo(((IndexStmt *) (node->utilityStmt))->relname));
176 177 178 179
				_outNode(str, node->utilityStmt);
				break;

			case T_NotifyStmt:
M
 
Marc G. Fournier 已提交
180
				appendStringInfo(str, " :utility %s ",
B
Bruce Momjian 已提交
181
								 stringStringInfo(((NotifyStmt *) (node->utilityStmt))->relname));
182 183 184
				break;

			default:
185
				appendStringInfo(str, " :utility ? ");
186 187
		}
	}
188
	else
189
		appendStringInfo(str, " :utility <>");
190

B
Bruce Momjian 已提交
191 192 193 194 195 196 197 198 199 200 201
	appendStringInfo(str,
					 " :resultRelation %u :into %s :isPortal %s :isBinary %s :isTemp %s :unionall %s ",
					 node->resultRelation,
					 stringStringInfo(node->into),
					 node->isPortal ? "true" : "false",
					 node->isBinary ? "true" : "false",
					 node->isTemp ? "true" : "false",
					 node->unionall ? "true" : "false");

	appendStringInfo(str, " :unique %s :sortClause ",
					 stringStringInfo(node->uniqueFlag));
202
	_outNode(str, node->sortClause);
M
 
Marc G. Fournier 已提交
203

204
	appendStringInfo(str, " :rtable ");
205
	_outNode(str, node->rtable);
M
 
Marc G. Fournier 已提交
206

207
	appendStringInfo(str, " :targetlist ");
208
	_outNode(str, node->targetList);
M
 
Marc G. Fournier 已提交
209

210
	appendStringInfo(str, " :qual ");
211
	_outNode(str, node->qual);
M
 
Marc G. Fournier 已提交
212

213 214
	appendStringInfo(str, " :groupClause ");
	_outNode(str, node->groupClause);
M
 
Marc G. Fournier 已提交
215

216
	appendStringInfo(str, " :havingQual ");
217
	_outNode(str, node->havingQual);
M
 
Marc G. Fournier 已提交
218 219

	appendStringInfo(str, " :hasAggs %s :hasSubLinks %s :unionClause ",
B
Bruce Momjian 已提交
220 221
					 node->hasAggs ? "true" : "false",
					 node->hasSubLinks ? "true" : "false");
222
	_outNode(str, node->unionClause);
M
 
Marc G. Fournier 已提交
223

B
Hi!  
Bruce Momjian 已提交
224 225 226
	appendStringInfo(str, " :intersectClause ");
	_outNode(str, node->intersectClause);

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

B
Bruce Momjian 已提交
230 231
	appendStringInfo(str, " :limitCount ");
	_outNode(str, node->limitCount);
232 233 234 235

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

236 237 238
}

static void
239
_outSortClause(StringInfo str, SortClause *node)
240
{
M
 
Marc G. Fournier 已提交
241
	appendStringInfo(str, " SORTCLAUSE :resdom ");
242
	_outNode(str, node->resdom);
M
 
Marc G. Fournier 已提交
243 244

	appendStringInfo(str, " :opoid %u ", node->opoid);
245 246 247 248 249
}

static void
_outGroupClause(StringInfo str, GroupClause *node)
{
B
Bruce Momjian 已提交
250 251 252
	appendStringInfo(str, " GROUPCLAUSE :grpOpoid %u :tleGroupref %d",
					 node->grpOpoid,
					 node->tleGroupref);
253 254 255 256 257 258
}

/*
 * print the basic stuff of all nodes that inherit from Plan
 */
static void
259
_outPlanInfo(StringInfo str, Plan *node)
260
{
B
Bruce Momjian 已提交
261 262 263 264 265 266
	appendStringInfo(str,
				  ":cost %g :size %d :width %d :state %s :qptargetlist ",
					 node->cost,
					 node->plan_size,
					 node->plan_width,
					 node->state ? "not-NULL" : "<>");
267
	_outNode(str, node->targetlist);
M
 
Marc G. Fournier 已提交
268

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

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

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

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

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

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

M
 
Marc G. Fournier 已提交
287
	appendStringInfo(str, " :nprm %d ", node->nParamExec);
288 289 290
}

/*
291
 *	Stuff from plannodes.h
292 293
 */
static void
294
_outPlan(StringInfo str, Plan *node)
295
{
296
	appendStringInfo(str, " PLAN ");
297
	_outPlanInfo(str, (Plan *) node);
298 299 300
}

static void
301
_outResult(StringInfo str, Result *node)
302
{
303
	appendStringInfo(str, " RESULT ");
304 305
	_outPlanInfo(str, (Plan *) node);

306
	appendStringInfo(str, " :resconstantqual ");
307 308
	_outNode(str, node->resconstantqual);

309 310 311
}

/*
312
 *	Append is a subclass of Plan.
313 314
 */
static void
B
Bruce Momjian 已提交
315
_outAppend(StringInfo str, Append *node)
316
{
317
	appendStringInfo(str, " APPEND ");
318 319
	_outPlanInfo(str, (Plan *) node);

320 321
	appendStringInfo(str, " :appendplans ");
	_outNode(str, node->appendplans);
322

323 324
	appendStringInfo(str, " :unionrtables ");
	_outNode(str, node->unionrtables);
325

B
Bruce Momjian 已提交
326 327 328
	appendStringInfo(str,
					 " :inheritrelid %u :inheritrtable ",
					 node->inheritrelid);
329
	_outNode(str, node->inheritrtable);
330

331 332 333
}

/*
334
 *	Join is a subclass of Plan
335 336
 */
static void
337
_outJoin(StringInfo str, Join *node)
338
{
339
	appendStringInfo(str, " JOIN ");
340 341
	_outPlanInfo(str, (Plan *) node);

342 343 344
}

/*
345
 *	NestLoop is a subclass of Join
346 347
 */
static void
348
_outNestLoop(StringInfo str, NestLoop *node)
349
{
350
	appendStringInfo(str, " NESTLOOP ");
351
	_outPlanInfo(str, (Plan *) node);
352 353 354
}

/*
355
 *	MergeJoin is a subclass of Join
356 357
 */
static void
358
_outMergeJoin(StringInfo str, MergeJoin *node)
359
{
360
	appendStringInfo(str, " MERGEJOIN ");
361 362
	_outPlanInfo(str, (Plan *) node);

363
	appendStringInfo(str, " :mergeclauses ");
364
	_outNode(str, node->mergeclauses);
365 366 367
}

/*
368
 *	HashJoin is a subclass of Join.
369 370
 */
static void
371
_outHashJoin(StringInfo str, HashJoin *node)
372
{
373
	appendStringInfo(str, " HASHJOIN ");
374 375
	_outPlanInfo(str, (Plan *) node);

376
	appendStringInfo(str, " :hashclauses ");
377 378
	_outNode(str, node->hashclauses);

B
Bruce Momjian 已提交
379 380 381
	appendStringInfo(str,
					 " :hashjoinop %u ",
					 node->hashjoinop);
M
 
Marc G. Fournier 已提交
382

B
Bruce Momjian 已提交
383 384 385
	appendStringInfo(str,
					 " :hashdone %d ",
					 node->hashdone);
386 387
}

V
Vadim B. Mikheev 已提交
388 389 390
static void
_outSubPlan(StringInfo str, SubPlan *node)
{
M
 
Marc G. Fournier 已提交
391
	appendStringInfo(str, " SUBPLAN :plan ");
V
Vadim B. Mikheev 已提交
392
	_outNode(str, node->plan);
M
 
Marc G. Fournier 已提交
393 394

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

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

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

V
Vadim B. Mikheev 已提交
403 404 405 406
	appendStringInfo(str, " :slink ");
	_outNode(str, node->sublink);
}

407
/*
408
 *	Scan is a subclass of Node
409 410
 */
static void
411
_outScan(StringInfo str, Scan *node)
412
{
413
	appendStringInfo(str, " SCAN ");
414 415
	_outPlanInfo(str, (Plan *) node);

416
	appendStringInfo(str, " :scanrelid %u ", node->scanrelid);
417 418 419
}

/*
420
 *	SeqScan is a subclass of Scan
421 422
 */
static void
423
_outSeqScan(StringInfo str, SeqScan *node)
424
{
425
	appendStringInfo(str, " SEQSCAN ");
426 427
	_outPlanInfo(str, (Plan *) node);

428
	appendStringInfo(str, " :scanrelid %u ", node->scanrelid);
429 430 431
}

/*
432
 *	IndexScan is a subclass of Scan
433 434
 */
static void
435
_outIndexScan(StringInfo str, IndexScan *node)
436
{
437
	appendStringInfo(str, " INDEXSCAN ");
438 439
	_outPlanInfo(str, (Plan *) node);

440
	appendStringInfo(str, " :scanrelid %u :indxid ", node->scan.scanrelid);
441 442
	_outIntList(str, node->indxid);

443
	appendStringInfo(str, " :indxqual ");
444 445
	_outNode(str, node->indxqual);

V
Vadim B. Mikheev 已提交
446 447 448
	appendStringInfo(str, " :indxqualorig ");
	_outNode(str, node->indxqualorig);

449 450 451
}

/*
452
 *	Noname is a subclass of Plan
453 454
 */
static void
455
_outNoname(StringInfo str, Noname *node)
456
{
457
	appendStringInfo(str, " NONAME ");
458 459
	_outPlanInfo(str, (Plan *) node);

B
Bruce Momjian 已提交
460 461 462
	appendStringInfo(str, " :nonameid %u :keycount %d ",
					 node->nonameid,
					 node->keycount);
463 464 465
}

/*
466
 *	Sort is a subclass of Noname
467 468
 */
static void
469
_outSort(StringInfo str, Sort *node)
470
{
471
	appendStringInfo(str, " SORT ");
472 473
	_outPlanInfo(str, (Plan *) node);

474
	appendStringInfo(str, " :nonameid %u :keycount %d ",
B
Bruce Momjian 已提交
475 476
					 node->nonameid,
					 node->keycount);
477 478 479
}

static void
B
Bruce Momjian 已提交
480
_outAgg(StringInfo str, Agg *node)
481
{
482

483
	appendStringInfo(str, " AGG ");
484 485
	_outPlanInfo(str, (Plan *) node);

486 487
	appendStringInfo(str, " :aggs ");
	_outNode(str, node->aggs);
488 489 490
}

static void
491
_outGroup(StringInfo str, Group *node)
492
{
493
	appendStringInfo(str, " GRP ");
494 495 496
	_outPlanInfo(str, (Plan *) node);

	/* the actual Group fields */
M
 
Marc G. Fournier 已提交
497
	appendStringInfo(str, " :numCols %d :tuplePerGroup %s ",
B
Bruce Momjian 已提交
498 499
					 node->numCols,
					 node->tuplePerGroup ? "true" : "false");
500
}
501

502
/*
503
 *	For some reason, unique is a subclass of Noname.
504 505
 */
static void
506
_outUnique(StringInfo str, Unique *node)
507
{
508
	appendStringInfo(str, " UNIQUE ");
509 510
	_outPlanInfo(str, (Plan *) node);

511
	appendStringInfo(str, " :nonameid %u :keycount %d ",
B
Bruce Momjian 已提交
512 513
					 node->nonameid,
					 node->keycount);
514 515 516 517
}


/*
518
 *	Hash is a subclass of Noname
519 520
 */
static void
521
_outHash(StringInfo str, Hash *node)
522
{
523
	appendStringInfo(str, " HASH ");
524 525
	_outPlanInfo(str, (Plan *) node);

526
	appendStringInfo(str, " :hashkey ");
527
	_outNode(str, node->hashkey);
528 529 530 531
}

/*****************************************************************************
 *
532
 *	Stuff from primnodes.h.
533 534 535 536
 *
 *****************************************************************************/

/*
537
 *	Resdom is a subclass of Node
538 539
 */
static void
540
_outResdom(StringInfo str, Resdom *node)
541
{
542
	appendStringInfo(str, " RESDOM :resno %d :restype %u :restypmod %d",
B
Bruce Momjian 已提交
543 544 545
					 node->resno,
					 node->restype,
					 node->restypmod);
546

547
	appendStringInfo(str, " :resname \"%s\" :reskey %d :reskeyop %u",
B
Bruce Momjian 已提交
548 549 550
					 stringStringInfo(node->resname),
					 node->reskey,
					 node->reskeyop);
551

B
Bruce Momjian 已提交
552
	appendStringInfo(str, " :resgroupref %d :resjunk %s ",
B
Bruce Momjian 已提交
553 554
					 node->resgroupref,
					 node->resjunk ? "true" : "false");
555 556 557
}

static void
558
_outFjoin(StringInfo str, Fjoin *node)
559
{
560
	int			i;
561

M
 
Marc G. Fournier 已提交
562
	appendStringInfo(str, " FJOIN :initialized %s :nNodes %d ",
B
Bruce Momjian 已提交
563 564
					 node->fj_initialized ? "true" : "false",
					 node->fj_nNodes);
565 566 567 568

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

B
Bruce Momjian 已提交
569 570
	appendStringInfo(str, " :results @ 0x%x :alwaysdone",
					 (int) node->fj_results);
571 572

	for (i = 0; i < node->fj_nNodes; i++)
573
		appendStringInfo(str, (node->fj_alwaysDone[i]) ? "true" : "false");
574 575 576
}

/*
577
 *	Expr is a subclass of Node
578 579
 */
static void
580
_outExpr(StringInfo str, Expr *node)
581
{
582
	char	   *opstr = NULL;
583

M
 
Marc G. Fournier 已提交
584
	appendStringInfo(str, " EXPR :typeOid %u ",
B
Bruce Momjian 已提交
585
					 node->typeOid);
586 587 588

	switch (node->opType)
	{
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603
		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 已提交
604 605 606
		case SUBPLAN_EXPR:
			opstr = "subp";
			break;
607
	}
608
	appendStringInfo(str, " :opType %s :oper ", stringStringInfo(opstr));
609
	_outNode(str, node->oper);
M
 
Marc G. Fournier 已提交
610

611
	appendStringInfo(str, " :args ");
612
	_outNode(str, node->args);
613 614 615
}

/*
616
 *	Var is a subclass of Expr
617 618
 */
static void
619
_outVar(StringInfo str, Var *node)
620
{
B
Bruce Momjian 已提交
621 622 623 624 625 626
	appendStringInfo(str,
				" VAR :varno %d :varattno %d :vartype %u :vartypmod %d ",
					 node->varno,
					 node->varattno,
					 node->vartype,
					 node->vartypmod);
M
 
Marc G. Fournier 已提交
627

B
Bruce Momjian 已提交
628 629 630 631
	appendStringInfo(str, " :varlevelsup %u :varnoold %d :varoattno %d",
					 node->varlevelsup,
					 node->varnoold,
					 node->varoattno);
632 633 634
}

/*
635
 *	Const is a subclass of Expr
636 637
 */
static void
638
_outConst(StringInfo str, Const *node)
639
{
B
Bruce Momjian 已提交
640 641 642 643 644
	appendStringInfo(str,
		" CONST :consttype %u :constlen %d :constisnull %s :constvalue ",
					 node->consttype,
					 node->constlen,
					 node->constisnull ? "true" : "false");
M
 
Marc G. Fournier 已提交
645

646
	if (node->constisnull)
B
Bruce Momjian 已提交
647
		appendStringInfo(str, "<>");
648 649
	else
		_outDatum(str, node->constvalue, node->consttype);
M
 
Marc G. Fournier 已提交
650

B
Bruce Momjian 已提交
651 652
	appendStringInfo(str, " :constbyval %s ",
					 node->constbyval ? "true" : "false");
653 654 655
}

/*
B
Bruce Momjian 已提交
656
 *	Aggref
657 658
 */
static void
659
_outAggref(StringInfo str, Aggref *node)
660
{
B
Bruce Momjian 已提交
661 662 663 664 665
	appendStringInfo(str,
				 " AGGREG :aggname %s :basetype %u :aggtype %u :target ",
					 stringStringInfo(node->aggname),
					 node->basetype,
					 node->aggtype);
666
	_outNode(str, node->target);
M
 
Marc G. Fournier 已提交
667 668

	appendStringInfo(str, ":aggno %d :usenulls %s",
B
Bruce Momjian 已提交
669 670
					 node->aggno,
					 node->usenulls ? "true" : "false");
671 672
}

673 674 675 676 677 678
/*
 *	SubLink
 */
static void
_outSubLink(StringInfo str, SubLink *node)
{
B
Bruce Momjian 已提交
679 680 681 682
	appendStringInfo(str,
					 " SUBLINK :subLinkType %d :useor %s :lefthand ",
					 node->subLinkType,
					 node->useor ? "true" : "false");
683
	_outNode(str, node->lefthand);
M
 
Marc G. Fournier 已提交
684

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

688 689 690 691
	appendStringInfo(str, " :subselect ");
	_outNode(str, node->subselect);
}

692
/*
693
 *	Array is a subclass of Expr
694 695
 */
static void
B
Bruce Momjian 已提交
696
_outArray(StringInfo str, Array *node)
697
{
698
	int			i;
699

B
Bruce Momjian 已提交
700 701 702 703 704
	appendStringInfo(str,
	  " ARRAY :arrayelemtype %u :arrayelemlength %d :arrayelembyval %c ",
					 node->arrayelemtype,
					 node->arrayelemlength,
					 node->arrayelembyval ? 't' : 'f');
M
 
Marc G. Fournier 已提交
705

M
 
Marc G. Fournier 已提交
706
	appendStringInfo(str, " :arrayndim %d :arraylow ", node->arrayndim);
707
	for (i = 0; i < node->arrayndim; i++)
M
 
Marc G. Fournier 已提交
708
		appendStringInfo(str, " %d ", node->arraylow.indx[i]);
709
	appendStringInfo(str, " :arrayhigh ");
710
	for (i = 0; i < node->arrayndim; i++)
M
 
Marc G. Fournier 已提交
711 712
		appendStringInfo(str, " %d ", node->arrayhigh.indx[i]);
	appendStringInfo(str, " :arraylen %d ", node->arraylen);
713 714 715
}

/*
716
 *	ArrayRef is a subclass of Expr
717 718
 */
static void
B
Bruce Momjian 已提交
719
_outArrayRef(StringInfo str, ArrayRef *node)
720
{
B
Bruce Momjian 已提交
721 722 723 724 725
	appendStringInfo(str,
		" ARRAYREF :refelemtype %u :refattrlength $d :refelemlength %d ",
					 node->refelemtype,
					 node->refattrlength,
					 node->refelemlength);
M
 
Marc G. Fournier 已提交
726

B
Bruce Momjian 已提交
727 728
	appendStringInfo(str, " :refelembyval %c :refupperindex ",
					 node->refelembyval ? 't' : 'f');
729 730
	_outNode(str, node->refupperindexpr);

731
	appendStringInfo(str, " :reflowerindex ");
732 733
	_outNode(str, node->reflowerindexpr);

734
	appendStringInfo(str, " :refexpr ");
735 736
	_outNode(str, node->refexpr);

737
	appendStringInfo(str, " :refassgnexpr ");
738
	_outNode(str, node->refassgnexpr);
739 740 741
}

/*
742
 *	Func is a subclass of Expr
743 744
 */
static void
745
_outFunc(StringInfo str, Func *node)
746
{
B
Bruce Momjian 已提交
747 748 749 750 751 752
	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 已提交
753 754

	appendStringInfo(str, " :func_fcache @ 0x%x :func_tlist ",
B
Bruce Momjian 已提交
755
					 (int) node->func_fcache);
756 757 758 759
	_outNode(str, node->func_tlist);

	appendStringInfo(str, " :func_planlist ");
	_outNode(str, node->func_planlist);
760 761 762
}

/*
763
 *	Oper is a subclass of Expr
764 765
 */
static void
766
_outOper(StringInfo str, Oper *node)
767
{
B
Bruce Momjian 已提交
768 769 770 771 772
	appendStringInfo(str,
					 " OPER :opno %u :opid %u :opresulttype %u ",
					 node->opno,
					 node->opid,
					 node->opresulttype);
773 774 775
}

/*
776
 *	Param is a subclass of Expr
777 778
 */
static void
779
_outParam(StringInfo str, Param *node)
780
{
B
Bruce Momjian 已提交
781 782 783 784 785 786
	appendStringInfo(str,
		 " PARAM :paramkind %d :paramid %d :paramname %s :paramtype %u ",
					 node->paramkind,
					 node->paramid,
					 stringStringInfo(node->paramname),
					 node->paramtype);
787 788 789

	appendStringInfo(str, " :param_tlist ");
	_outNode(str, node->param_tlist);
790 791 792
}

/*
793
 *	Stuff from execnodes.h
794 795 796
 */

/*
797
 *	EState is a subclass of Node.
798 799
 */
static void
800
_outEState(StringInfo str, EState *node)
801
{
B
Bruce Momjian 已提交
802 803 804
	appendStringInfo(str,
					 " ESTATE :direction %d :range_table ",
					 node->es_direction);
805 806
	_outNode(str, node->es_range_table);

M
 
Marc G. Fournier 已提交
807
	appendStringInfo(str, " :result_relation_info @ 0x%x ",
B
Bruce Momjian 已提交
808
					 (int) (node->es_result_relation_info));
809 810 811
}

/*
812
 *	Stuff from relation.h
813 814
 */
static void
815
_outRelOptInfo(StringInfo str, RelOptInfo *node)
816
{
M
 
Marc G. Fournier 已提交
817
	appendStringInfo(str, " RELOPTINFO :relids ");
818 819
	_outIntList(str, node->relids);

B
Bruce Momjian 已提交
820 821 822 823 824 825 826
	appendStringInfo(str,
	 " :indexed %s :pages %u :tuples %u :size %u :width %u :targetlist ",
					 node->indexed ? "true" : "false",
					 node->pages,
					 node->tuples,
					 node->size,
					 node->width);
827 828
	_outNode(str, node->targetlist);

829
	appendStringInfo(str, " :pathlist ");
830 831 832 833 834 835 836 837
	_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 已提交
838 839 840 841
	appendStringInfo(str,
					 " :cheapestpath @ 0x%x :pruneable %s :restrictinfo ",
					 (int) node->cheapestpath,
					 node->pruneable ? "true" : "false");
842
	_outNode(str, node->restrictinfo);
843

844
	appendStringInfo(str, " :joininfo ");
845 846
	_outNode(str, node->joininfo);

847
	appendStringInfo(str, " :innerjoin ");
848
	_outNode(str, node->innerjoin);
849 850 851
}

/*
852
 *	TargetEntry is a subclass of Node.
853 854
 */
static void
855
_outTargetEntry(StringInfo str, TargetEntry *node)
856
{
M
 
Marc G. Fournier 已提交
857
	appendStringInfo(str, " TARGETENTRY :resdom ");
858 859
	_outNode(str, node->resdom);

860 861
	appendStringInfo(str, " :expr ");
	_outNode(str, node->expr);
862
}
863 864

static void
865
_outRangeTblEntry(StringInfo str, RangeTblEntry *node)
866
{
B
Bruce Momjian 已提交
867 868 869 870 871 872 873 874
	appendStringInfo(str,
					 " RTE :relname %s :refname %s :relid %u :inh %s :inFromCl %s :skipAcl %s",
					 stringStringInfo(node->relname),
					 stringStringInfo(node->refname),
					 node->relid,
					 node->inh ? "true" : "false",
					 node->inFromCl ? "true" : "false",
					 node->skipAcl ? "true" : "false");
875
}
876

877
static void
878
_outRowMark(StringInfo str, RowMark *node)
879 880 881 882
{
	appendStringInfo(str, " ROWMARK :rti %u :info %u", node->rti, node->info);
}

883 884 885 886 887 888 889
/*
 *	Path is a subclass of Node.
 */
static void
_outPathOrder(StringInfo str, PathOrder *node)
{
	appendStringInfo(str, " PATHORDER :ordtype %d ",
B
Bruce Momjian 已提交
890
					 node->ordtype);
891 892
	if (node->ordtype == SORTOP_ORDER)
	{
B
Bruce Momjian 已提交
893 894
		int			i;

895 896 897 898 899
		appendStringInfo(str, " :sortop ");
		if (node->ord.sortop == NULL)
			appendStringInfo(str, "<>");
		else
		{
B
Bruce Momjian 已提交
900
			for (i = 0; node->ord.sortop[i] != 0; i++)
901 902 903 904 905 906 907
				appendStringInfo(str, " %d ", node->ord.sortop[i]);
			appendStringInfo(str, " %d ", 0);
		}
	}
	else
	{
		appendStringInfo(str, " :merge ");
B
Bruce Momjian 已提交
908
		_outNode(str, node->ord.merge);
909 910 911
	}
}

912
/*
913
 *	Path is a subclass of Node.
914 915
 */
static void
916
_outPath(StringInfo str, Path *node)
917
{
918
	appendStringInfo(str, " PATH :pathtype %d :cost %f :pathkeys ",
B
Bruce Momjian 已提交
919 920
					 node->pathtype,
					 node->path_cost);
921
	_outNode(str, node->pathkeys);
922

B
Bruce Momjian 已提交
923 924
	appendStringInfo(str, " :pathorder ");
	_outNode(str, node->pathorder);
925 926 927
}

/*
928
 *	IndexPath is a subclass of Path.
929 930
 */
static void
931
_outIndexPath(StringInfo str, IndexPath *node)
932
{
B
Bruce Momjian 已提交
933 934 935 936
	appendStringInfo(str,
					 " INDEXPATH :pathtype %d :cost %f :pathkeys ",
					 node->path.pathtype,
					 node->path.path_cost);
937
	_outNode(str, node->path.pathkeys);
938

B
Bruce Momjian 已提交
939 940
	appendStringInfo(str, " :pathorder ");
	_outNode(str, node->path.pathorder);
941

942
	appendStringInfo(str, " :indexid ");
943 944
	_outIntList(str, node->indexid);

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

/*
950
 *	NestPath is a subclass of Path
951 952
 */
static void
953
_outNestPath(StringInfo str, NestPath *node)
954
{
B
Bruce Momjian 已提交
955 956 957 958
	appendStringInfo(str,
					 " NESTPATH :pathtype %d :cost %f :pathkeys ",
					 node->path.pathtype,
					 node->path.path_cost);
959
	_outNode(str, node->path.pathkeys);
960

B
Bruce Momjian 已提交
961 962
	appendStringInfo(str, " :pathorder ");
	_outNode(str, node->path.pathorder);
B
Bruce Momjian 已提交
963

964 965
	appendStringInfo(str, " :pathinfo ");
	_outNode(str, node->pathinfo);
966 967 968 969 970 971

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

B
Bruce Momjian 已提交
972 973 974 975 976
	appendStringInfo(str,
					 " :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x :outjoincost %f :joinid ",
					 (int) node->outerjoinpath,
					 (int) node->innerjoinpath,
					 node->path.outerjoincost);
977
	_outIntList(str, node->path.joinid);
978 979 980
}

/*
981
 *	MergePath is a subclass of NestPath.
982 983
 */
static void
984
_outMergePath(StringInfo str, MergePath *node)
985
{
B
Bruce Momjian 已提交
986 987 988 989
	appendStringInfo(str,
					 " MERGEPATH :pathtype %d :cost %f :pathkeys ",
					 node->jpath.path.pathtype,
					 node->jpath.path.path_cost);
990
	_outNode(str, node->jpath.path.pathkeys);
991

B
Bruce Momjian 已提交
992 993
	appendStringInfo(str, " :pathorder ");
	_outNode(str, node->jpath.path.pathorder);
B
Bruce Momjian 已提交
994

995 996
	appendStringInfo(str, " :pathinfo ");
	_outNode(str, node->jpath.pathinfo);
997 998 999 1000 1001 1002

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

B
Bruce Momjian 已提交
1003 1004 1005 1006 1007
	appendStringInfo(str,
					 " :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x :outerjoincost %f :joinid ",
					 (int) node->jpath.outerjoinpath,
					 (int) node->jpath.innerjoinpath,
					 (int) node->jpath.path.outerjoincost);
1008 1009
	_outIntList(str, node->jpath.path.joinid);

1010
	appendStringInfo(str, " :path_mergeclauses ");
1011 1012
	_outNode(str, node->path_mergeclauses);

1013
	appendStringInfo(str, " :outersortkeys ");
1014 1015
	_outNode(str, node->outersortkeys);

1016
	appendStringInfo(str, " :innersortkeys ");
1017
	_outNode(str, node->innersortkeys);
1018 1019 1020
}

/*
1021
 *	HashPath is a subclass of NestPath.
1022 1023
 */
static void
1024
_outHashPath(StringInfo str, HashPath *node)
1025
{
B
Bruce Momjian 已提交
1026 1027 1028 1029
	appendStringInfo(str,
					 " HASHPATH :pathtype %d :cost %f :pathkeys ",
					 node->jpath.path.pathtype,
					 node->jpath.path.path_cost);
1030
	_outNode(str, node->jpath.path.pathkeys);
1031

B
Bruce Momjian 已提交
1032 1033
	appendStringInfo(str, " :pathorder ");
	_outNode(str, node->jpath.path.pathorder);
1034

1035 1036
	appendStringInfo(str, " :pathinfo ");
	_outNode(str, node->jpath.pathinfo);
1037 1038 1039 1040 1041 1042

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

B
Bruce Momjian 已提交
1043 1044 1045 1046 1047
	appendStringInfo(str,
					 " :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x :outerjoincost %f :joinid ",
					 (int) node->jpath.outerjoinpath,
					 (int) node->jpath.innerjoinpath,
					 node->jpath.path.outerjoincost);
1048 1049
	_outIntList(str, node->jpath.path.joinid);

1050
	appendStringInfo(str, " :path_hashclauses ");
1051 1052
	_outNode(str, node->path_hashclauses);

1053
	appendStringInfo(str, " :outerhashkeys ");
1054 1055
	_outNode(str, node->outerhashkeys);

1056
	appendStringInfo(str, " :innerhashkeys ");
1057
	_outNode(str, node->innerhashkeys);
1058 1059 1060
}

/*
1061
 *	OrderKey is a subclass of Node.
1062 1063
 */
static void
1064
_outOrderKey(StringInfo str, OrderKey *node)
1065
{
B
Bruce Momjian 已提交
1066 1067 1068 1069
	appendStringInfo(str,
					 " ORDERKEY :attribute_number %d :array_index %d ",
					 node->attribute_number,
					 node->array_index);
1070 1071 1072
}

/*
1073
 *	JoinKey is a subclass of Node.
1074 1075
 */
static void
1076
_outJoinKey(StringInfo str, JoinKey *node)
1077
{
M
 
Marc G. Fournier 已提交
1078
	appendStringInfo(str, " JOINKEY :outer ");
1079 1080
	_outNode(str, node->outer);

1081
	appendStringInfo(str, " :inner ");
1082 1083
	_outNode(str, node->inner);

1084 1085 1086
}

/*
1087
 *	MergeOrder is a subclass of Node.
1088 1089
 */
static void
1090
_outMergeOrder(StringInfo str, MergeOrder *node)
1091
{
B
Bruce Momjian 已提交
1092 1093 1094 1095 1096
	appendStringInfo(str,
	" MERGEORDER :join_operator %u :left_operator %u :right_operator %u ",
					 node->join_operator,
					 node->left_operator,
					 node->right_operator);
1097

B
Bruce Momjian 已提交
1098 1099 1100 1101
	appendStringInfo(str,
					 " :left_type %u :right_type %u ",
					 node->left_type,
					 node->right_type);
1102 1103 1104
}

/*
1105
 *	RestrictInfo is a subclass of Node.
1106 1107
 */
static void
1108
_outRestrictInfo(StringInfo str, RestrictInfo *node)
1109
{
B
Bruce Momjian 已提交
1110
	appendStringInfo(str, " RESTRICTINFO :clause ");
1111 1112
	_outNode(str, node->clause);

B
Bruce Momjian 已提交
1113 1114 1115 1116
	appendStringInfo(str,
					 " :selectivity %f :notclause %s :indexids ",
					 node->selectivity,
					 node->notclause ? "true" : "false");
1117 1118
	_outNode(str, node->indexids);

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

M
 
Marc G. Fournier 已提交
1122
	appendStringInfo(str, " :hashjoinoperator %u ", node->hashjoinoperator);
1123

1124 1125 1126
}

/*
1127
 *	JoinMethod is a subclass of Node.
1128 1129
 */
static void
1130
_outJoinMethod(StringInfo str, JoinMethod *node)
1131
{
M
 
Marc G. Fournier 已提交
1132
	appendStringInfo(str, " JOINMETHOD :jmkeys ");
1133 1134
	_outNode(str, node->jmkeys);

1135
	appendStringInfo(str, " :clauses ");
1136
	_outNode(str, node->clauses);
1137 1138 1139
}

/*
1140
 * HashInfo is a subclass of JoinMethod.
1141 1142
 */
static void
1143
_outHashInfo(StringInfo str, HashInfo *node)
1144
{
M
 
Marc G. Fournier 已提交
1145
	appendStringInfo(str, " HASHINFO :hashop %u :jmkeys ", node->hashop);
1146 1147
	_outNode(str, node->jmethod.jmkeys);

1148
	appendStringInfo(str, " :clauses ");
1149
	_outNode(str, node->jmethod.clauses);
1150 1151 1152
}

/*
1153
 *	JoinInfo is a subclass of Node.
1154 1155
 */
static void
1156
_outJoinInfo(StringInfo str, JoinInfo *node)
1157
{
B
Bruce Momjian 已提交
1158 1159
	appendStringInfo(str, " JINFO :unjoined_relids ");
	_outIntList(str, node->unjoined_relids);
1160

1161 1162
	appendStringInfo(str, " :jinfo_restrictinfo ");
	_outNode(str, node->jinfo_restrictinfo);
1163

M
 
Marc G. Fournier 已提交
1164
	appendStringInfo(str, " :mergejoinable %s :hashjoinable %s ",
B
Bruce Momjian 已提交
1165 1166
					 node->mergejoinable ? "true" : "false",
					 node->hashjoinable ? "true" : "false");
1167 1168 1169 1170 1171 1172 1173 1174
}

/*
 * Print the value of a Datum given its type.
 */
static void
_outDatum(StringInfo str, Datum value, Oid type)
{
B
Bruce Momjian 已提交
1175
	char	   *s;
1176
	Size		length,
B
Bruce Momjian 已提交
1177
				typeLength;
1178 1179
	bool		byValue;
	int			i;
1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191

	/*
	 * 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 已提交
1192
		appendStringInfo(str, " %d [ ", length);
1193
		for (i = 0; i < sizeof(Datum); i++)
M
 
Marc G. Fournier 已提交
1194 1195
			appendStringInfo(str, " %d ", (int) (s[i]));
		appendStringInfo(str, "] ");
1196
	}
1197 1198 1199 1200
	else
	{							/* !byValue */
		s = (char *) DatumGetPointer(value);
		if (!PointerIsValid(s))
M
 
Marc G. Fournier 已提交
1201
			appendStringInfo(str, " 0 [ ] ");
1202 1203
		else
		{
B
Bruce Momjian 已提交
1204

1205 1206 1207 1208 1209 1210
			/*
			 * 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 已提交
1211
			appendStringInfo(str, " %d [ ", length);
1212
			for (i = 0; i < length; i++)
M
 
Marc G. Fournier 已提交
1213 1214
				appendStringInfo(str, " %d ", (int) (s[i]));
			appendStringInfo(str, "] ");
1215
		}
1216 1217 1218 1219
	}
}

static void
1220
_outIter(StringInfo str, Iter *node)
1221
{
M
 
Marc G. Fournier 已提交
1222
	appendStringInfo(str, " ITER :iterexpr ");
1223
	_outNode(str, node->iterexpr);
1224 1225 1226
}

static void
1227
_outStream(StringInfo str, Stream *node)
1228
{
B
Bruce Momjian 已提交
1229 1230 1231 1232 1233 1234
	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);
1235

B
Bruce Momjian 已提交
1236 1237 1238 1239 1240 1241
	appendStringInfo(str,
		   " :downstream @ 0x%x :groupup %d :groupcost %f :groupsel %f ",
					 (int) node->downstream,
					 node->groupup,
					 node->groupcost,
					 node->groupsel);
1242
}
1243

1244 1245 1246
static void
_outAExpr(StringInfo str, A_Expr *node)
{
1247
	appendStringInfo(str, "EXPR ");
1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265
	switch (node->oper)
	{
		case AND:
			appendStringInfo(str, "AND");
			break;
		case OR:
			appendStringInfo(str, "OR");
			break;
		case NOT:
			appendStringInfo(str, "NOT");
			break;
		case ISNULL:
			appendStringInfo(str, "ISNULL");
			break;
		case NOTNULL:
			appendStringInfo(str, "NOTNULL");
			break;
		default:
1266
			appendStringInfo(str, stringStringInfo(node->opname));
1267 1268
			break;
	}
1269 1270 1271 1272 1273
	_outNode(str, node->lexpr);
	_outNode(str, node->rexpr);
	return;
}

1274
static void
1275
_outValue(StringInfo str, Value *value)
1276
{
1277 1278
	switch (value->type)
	{
B
Bruce Momjian 已提交
1279
			case T_String:
M
 
Marc G. Fournier 已提交
1280
			appendStringInfo(str, " \"%s\" ", stringStringInfo(value->val.str));
1281 1282
			break;
		case T_Integer:
1283
			appendStringInfo(str, " %ld ", value->val.ival);
1284 1285
			break;
		case T_Float:
1286
			appendStringInfo(str, " %f ", value->val.dval);
1287 1288 1289
			break;
		default:
			break;
1290 1291
	}
	return;
1292 1293
}

1294 1295 1296
static void
_outIdent(StringInfo str, Ident *node)
{
1297
	appendStringInfo(str, " IDENT \"%s\" ", stringStringInfo(node->name));
1298 1299 1300
	return;
}

1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318
static void
_outAttr(StringInfo str, Attr *node)
{
	List	   *l;

	appendStringInfo(str, " ATTR \"%s\" ", stringStringInfo(node->relname));

	appendStringInfo(str, "(");
	foreach(l, node->attrs)
	{
		_outNode(str, lfirst(l));
		if (lnext(l))
			appendStringInfo(str, ",");
	}
	appendStringInfo(str, ")");
	return;
}

1319 1320 1321
static void
_outAConst(StringInfo str, A_Const *node)
{
1322
	appendStringInfo(str, "CONST ");
1323 1324 1325 1326
	_outValue(str, &(node->val));
	return;
}

T
Thomas G. Lockhart 已提交
1327 1328 1329
static void
_outConstraint(StringInfo str, Constraint *node)
{
B
Bruce Momjian 已提交
1330
	appendStringInfo(str, " %s :type", stringStringInfo(node->name));
T
Thomas G. Lockhart 已提交
1331 1332 1333 1334

	switch (node->contype)
	{
		case CONSTR_PRIMARY:
1335
			appendStringInfo(str, " PRIMARY KEY ");
T
Thomas G. Lockhart 已提交
1336 1337 1338 1339
			_outNode(str, node->keys);
			break;

		case CONSTR_CHECK:
M
 
Marc G. Fournier 已提交
1340
			appendStringInfo(str, " CHECK %s", stringStringInfo(node->def));
T
Thomas G. Lockhart 已提交
1341 1342 1343
			break;

		case CONSTR_DEFAULT:
M
 
Marc G. Fournier 已提交
1344
			appendStringInfo(str, " DEFAULT %s", stringStringInfo(node->def));
T
Thomas G. Lockhart 已提交
1345 1346 1347
			break;

		case CONSTR_NOTNULL:
1348
			appendStringInfo(str, " NOT NULL ");
T
Thomas G. Lockhart 已提交
1349 1350 1351
			break;

		case CONSTR_UNIQUE:
1352
			appendStringInfo(str, " UNIQUE ");
T
Thomas G. Lockhart 已提交
1353 1354 1355 1356
			_outNode(str, node->keys);
			break;

		default:
1357
			appendStringInfo(str, "<unrecognized constraint>");
T
Thomas G. Lockhart 已提交
1358 1359 1360 1361 1362 1363
			break;
	}
	return;
}

static void
1364
_outCaseExpr(StringInfo str, CaseExpr *node)
T
Thomas G. Lockhart 已提交
1365
{
1366
	appendStringInfo(str, "CASE ");
T
Thomas G. Lockhart 已提交
1367
	_outNode(str, node->args);
M
 
Marc G. Fournier 已提交
1368

1369
	appendStringInfo(str, " :default ");
T
Thomas G. Lockhart 已提交
1370
	_outNode(str, node->defresult);
M
 
Marc G. Fournier 已提交
1371

T
Thomas G. Lockhart 已提交
1372 1373 1374 1375
	return;
}

static void
1376
_outCaseWhen(StringInfo str, CaseWhen *node)
T
Thomas G. Lockhart 已提交
1377
{
1378
	appendStringInfo(str, " WHEN ");
T
Thomas G. Lockhart 已提交
1379
	_outNode(str, node->expr);
M
 
Marc G. Fournier 已提交
1380

1381
	appendStringInfo(str, " :then ");
T
Thomas G. Lockhart 已提交
1382
	_outNode(str, node->result);
M
 
Marc G. Fournier 已提交
1383

T
Thomas G. Lockhart 已提交
1384 1385 1386
	return;
}

1387 1388
/*
 * _outNode -
1389
 *	  converts a Node into ascii string and append it to 'str'
1390 1391 1392 1393
 */
static void
_outNode(StringInfo str, void *obj)
{
1394 1395
	if (obj == NULL)
	{
B
Bruce Momjian 已提交
1396
		appendStringInfo(str, "<>");
1397 1398
		return;
	}
1399

1400 1401
	if (nodeTag(obj) == T_List)
	{
1402
		List	   *l;
1403 1404 1405 1406 1407 1408 1409 1410 1411

		appendStringInfo(str, "(");
		foreach(l, (List *) obj)
		{
			_outNode(str, lfirst(l));
			if (lnext(l))
				appendStringInfo(str, " ");
		}
		appendStringInfo(str, ")");
1412
	}
1413 1414 1415 1416 1417
	else
	{
		appendStringInfo(str, "{");
		switch (nodeTag(obj))
		{
1418 1419 1420 1421 1422 1423 1424 1425 1426 1427
			case T_CreateStmt:
				_outCreateStmt(str, obj);
				break;
			case T_IndexStmt:
				_outIndexStmt(str, obj);
				break;

			case T_ColumnDef:
				_outColumnDef(str, obj);
				break;
1428 1429 1430
			case T_TypeName:
				_outTypeName(str, obj);
				break;
1431 1432 1433
			case T_IndexElem:
				_outIndexElem(str, obj);
				break;
1434 1435 1436
			case T_Query:
				_outQuery(str, obj);
				break;
1437 1438 1439 1440 1441
			case T_SortClause:
				_outSortClause(str, obj);
				break;
			case T_GroupClause:
				_outGroupClause(str, obj);
1442
				break;
1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472
			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;
1473 1474
			case T_Noname:
				_outNoname(str, obj);
1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490
				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 已提交
1491 1492 1493
			case T_SubPlan:
				_outSubPlan(str, obj);
				break;
1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508
			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 已提交
1509 1510
			case T_Aggref:
				_outAggref(str, obj);
1511
				break;
1512 1513 1514
			case T_SubLink:
				_outSubLink(str, obj);
				break;
1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532
			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 已提交
1533
			case T_RelOptInfo:
B
Bruce Momjian 已提交
1534
				_outRelOptInfo(str, obj);
1535 1536 1537 1538 1539 1540 1541
				break;
			case T_TargetEntry:
				_outTargetEntry(str, obj);
				break;
			case T_RangeTblEntry:
				_outRangeTblEntry(str, obj);
				break;
1542 1543 1544
			case T_RowMark:
				_outRowMark(str, obj);
				break;
1545 1546 1547
			case T_PathOrder:
				_outPathOrder(str, obj);
				break;
1548 1549 1550 1551 1552 1553
			case T_Path:
				_outPath(str, obj);
				break;
			case T_IndexPath:
				_outIndexPath(str, obj);
				break;
1554 1555
			case T_NestPath:
				_outNestPath(str, obj);
1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571
				break;
			case T_MergePath:
				_outMergePath(str, obj);
				break;
			case T_HashPath:
				_outHashPath(str, obj);
				break;
			case T_OrderKey:
				_outOrderKey(str, obj);
				break;
			case T_JoinKey:
				_outJoinKey(str, obj);
				break;
			case T_MergeOrder:
				_outMergeOrder(str, obj);
				break;
1572 1573
			case T_RestrictInfo:
				_outRestrictInfo(str, obj);
1574 1575 1576 1577
				break;
			case T_JoinMethod:
				_outJoinMethod(str, obj);
				break;
1578 1579
			case T_HashInfo:
				_outHashInfo(str, obj);
1580
				break;
1581 1582
			case T_JoinInfo:
				_outJoinInfo(str, obj);
1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594
				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;
1595 1596 1597 1598 1599 1600 1601 1602 1603
			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 已提交
1604 1605 1606 1607 1608 1609 1610 1611 1612
			case T_Constraint:
				_outConstraint(str, obj);
				break;
			case T_CaseExpr:
				_outCaseExpr(str, obj);
				break;
			case T_CaseWhen:
				_outCaseWhen(str, obj);
				break;
1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625

			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;

1626
			default:
B
Bruce Momjian 已提交
1627
				elog(NOTICE, "_outNode: don't know how to print type %d ",
1628 1629
					 nodeTag(obj));
				break;
1630 1631
		}
		appendStringInfo(str, "}");
1632
	}
1633
	return;
1634 1635 1636 1637
}

/*
 * nodeToString -
1638
 *	   returns the ascii representation of the Node as a palloc'd string
1639
 */
1640
char *
1641 1642
nodeToString(void *obj)
{
B
Bruce Momjian 已提交
1643
	StringInfoData str;
1644

1645 1646 1647 1648
	/* see stringinfo.h for an explanation of this maneuver */
	initStringInfo(&str);
	_outNode(&str, obj);
	return str.data;
1649
}