outfuncs.c 39.9 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
 *
M
 
Marc G. Fournier 已提交
8
 *  $Id: outfuncs.c,v 1.53 1998/12/15 02:24:15 scrappy 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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
 *
 */
#include <stdio.h>
#include "postgres.h"

#include "access/heapam.h"
#include "access/htup.h"
#include "utils/syscache.h"
#include "utils/lsyscache.h"
#include "fmgr.h"
#include "utils/elog.h"
#include "utils/datum.h"
#include "utils/palloc.h"

#include "nodes/nodes.h"
#include "nodes/execnodes.h"
#include "nodes/pg_list.h"
#include "nodes/plannodes.h"
#include "nodes/parsenodes.h"
#include "nodes/primnodes.h"
#include "nodes/relation.h"

#include "catalog/pg_type.h"
#include "lib/stringinfo.h"

45 46 47 48
#ifdef PARSEDEBUG
#include "../parse.h"
#endif

49 50
static void _outDatum(StringInfo str, Datum value, Oid type);
static void _outNode(StringInfo str, void *obj);
51 52 53

/*
 * _outIntList -
54
 *	   converts a List of integers
55
 */
56
static void
57
_outIntList(StringInfo str, List *list)
58
{
M
 
Marc G. Fournier 已提交
59
	List	*l;
60

61 62 63
	appendStringInfo(str, "(");
	foreach(l, list)
	{
M
 
Marc G. Fournier 已提交
64
		appendStringInfo(str, " %d ", (int) lfirst(l));
65 66
	}
	appendStringInfo(str, ")");
67 68
}

69 70 71
static void
_outCreateStmt(StringInfo str, CreateStmt *node)
{
M
 
Marc G. Fournier 已提交
72
	appendStringInfo(str, " CREATE :relname %s :columns ", node->relname);
73 74

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

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

88
	_outNode(str, node->indexParams);
89 90 91 92 93 94
	appendStringInfo(str, " :withClause ");
	_outNode(str, node->withClause);
	appendStringInfo(str, " :whereClause ");
	_outNode(str, node->whereClause);
	appendStringInfo(str, " :rangetable ");
	_outNode(str, node->rangetable);
M
 
Marc G. Fournier 已提交
95 96 97 98

	appendStringInfo(str, " :lossy %s :unique %s ",
			node->lossy ? "true" : "false",
			node->unique ? "true" : "false");
99
}
100

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

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

116 117
#endif

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

	appendStringInfo(str, " :is_not_null %s :defval %s :constraints ",
			node->is_not_null ? "true" : "false", node->defval);
126
	_outNode(str, node->constraints);
127 128 129 130 131
}

static void
_outTypeName(StringInfo str, TypeName *node)
{
M
 
Marc G. Fournier 已提交
132 133 134 135 136 137
	appendStringInfo(str, 
			" TYPENAME :name %s :timezone %s :setof %s typmod %d :arrayBounds ",
			node->name, 
			node->timezone ? "true" : "false,
			node->setof ? "true" : "false",
			node->typemod);
138 139 140 141

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

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

	appendStringInfo(str, " :class %s :typename ", node->class);
150
	_outNode(str, node->typename);
151
}
152

153
static void
154
_outQuery(StringInfo str, Query *node)
155
{
M
 
Marc G. Fournier 已提交
156
	appendStringInfo(str, " QUERY :command %d ", node->commandType);
157

158 159 160 161 162
	if (node->utilityStmt)
	{
		switch (nodeTag(node->utilityStmt))
		{
			case T_CreateStmt:
M
 
Marc G. Fournier 已提交
163 164
				appendStringInfo(str, " :create %s ",
						((CreateStmt *) (node->utilityStmt))->relname);
165 166 167 168
				_outNode(str, node->utilityStmt);
				break;

			case T_IndexStmt:
M
 
Marc G. Fournier 已提交
169 170 171
				appendStringInfo(str, " :index %s on %s ",
					((IndexStmt *) (node->utilityStmt))->idxname,
					((IndexStmt *) (node->utilityStmt))->relname);
172 173 174 175
				_outNode(str, node->utilityStmt);
				break;

			case T_NotifyStmt:
M
 
Marc G. Fournier 已提交
176 177
				appendStringInfo(str, " :utility %s ",
						((NotifyStmt *) (node->utilityStmt))->relname);
178 179 180
				break;

			default:
181
				appendStringInfo(str, " :utility ? ");
182 183
		}
	}
184
	else
185
	{
M
 
Marc G. Fournier 已提交
186
		appendStringInfo(str, " :utility %s", NULL);
187
	}
188

M
 
Marc G. Fournier 已提交
189 190 191 192 193 194 195 196 197
	appendStringInfo(str, 
			" :resultRelation %d :into %s :isPortal %s :isBinary %s :unionall %s ",
			node->resultRelation,
			node->into,
			node->isPortal ? "true" : "false",
			node->isBinary ? "true" : "false",
			node->unionall ? "true" : "false");

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

200
	appendStringInfo(str, " :rtable ");
201
	_outNode(str, node->rtable);
M
 
Marc G. Fournier 已提交
202

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

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

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

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

	appendStringInfo(str, " :hasAggs %s :hasSubLinks %s :unionClause ",
			node->hasAggs ? "true" : "false",
			node->hasSubLinks ? "true" : "false");
218
	_outNode(str, node->unionClause);
M
 
Marc G. Fournier 已提交
219

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

B
Bruce Momjian 已提交
223 224
	appendStringInfo(str, " :limitCount ");
	_outNode(str, node->limitCount);
225 226 227
}

static void
228
_outSortClause(StringInfo str, SortClause *node)
229
{
M
 
Marc G. Fournier 已提交
230
	appendStringInfo(str, " SORTCLAUSE :resdom ");
231
	_outNode(str, node->resdom);
M
 
Marc G. Fournier 已提交
232 233

	appendStringInfo(str, " :opoid %u ", node->opoid);
234 235 236 237 238
}

static void
_outGroupClause(StringInfo str, GroupClause *node)
{
M
 
Marc G. Fournier 已提交
239
	appendStringInfo(str, " GROUPCLAUSE :entry ");
240
	_outNode(str, node->entry);
M
 
Marc G. Fournier 已提交
241 242

	appendStringInfo(str, " :grpOpoid %u ", node->grpOpoid);
243 244 245 246 247 248
}

/*
 * print the basic stuff of all nodes that inherit from Plan
 */
static void
249
_outPlanInfo(StringInfo str, Plan *node)
250
{
M
 
Marc G. Fournier 已提交
251 252 253 254 255 256
  appendStringInfo(str, 
		":cost %g :size %d :width %d :state %s :qptargetlist ",
		node->cost,
		node->plan_size,
		node->plan_width,
		node->state ? "not-NULL" : "<>");
257
	_outNode(str, node->targetlist);
M
 
Marc G. Fournier 已提交
258

259
	appendStringInfo(str, " :qpqual ");
260
	_outNode(str, node->qual);
M
 
Marc G. Fournier 已提交
261

262
	appendStringInfo(str, " :lefttree ");
263
	_outNode(str, node->lefttree);
M
 
Marc G. Fournier 已提交
264

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

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

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

V
Vadim B. Mikheev 已提交
274 275
	appendStringInfo(str, " :initplan ");
	_outNode(str, node->initPlan);
M
 
Marc G. Fournier 已提交
276 277

	appendStringInfo(str, " :nprm %d ", node-nParamExec);
278 279 280
}

/*
281
 *	Stuff from plannodes.h
282 283
 */
static void
284
_outPlan(StringInfo str, Plan *node)
285
{
286
	appendStringInfo(str, " PLAN ");
287
	_outPlanInfo(str, (Plan *) node);
288 289 290
}

static void
291
_outResult(StringInfo str, Result *node)
292
{
293
	appendStringInfo(str, " RESULT ");
294 295
	_outPlanInfo(str, (Plan *) node);

296
	appendStringInfo(str, " :resconstantqual ");
297 298
	_outNode(str, node->resconstantqual);

299 300 301
}

/*
302
 *	Append is a subclass of Plan.
303 304
 */
static void
B
Bruce Momjian 已提交
305
_outAppend(StringInfo str, Append *node)
306
{
307
	appendStringInfo(str, " APPEND ");
308 309
	_outPlanInfo(str, (Plan *) node);

310 311
	appendStringInfo(str, " :appendplans ");
	_outNode(str, node->appendplans);
312

313 314
	appendStringInfo(str, " :unionrtables ");
	_outNode(str, node->unionrtables);
315

M
 
Marc G. Fournier 已提交
316 317 318
	appendStringInfo(str, 
		" :inheritrelid %d :inheritrtable ", 
		node->inheritrelid);
319
	_outNode(str, node->inheritrtable);
320

321 322 323
}

/*
324
 *	Join is a subclass of Plan
325 326
 */
static void
327
_outJoin(StringInfo str, Join *node)
328
{
329
	appendStringInfo(str, " JOIN ");
330 331
	_outPlanInfo(str, (Plan *) node);

332 333 334
}

/*
335
 *	NestLoop is a subclass of Join
336 337
 */
static void
338
_outNestLoop(StringInfo str, NestLoop *node)
339
{
340
	appendStringInfo(str, " NESTLOOP ");
341
	_outPlanInfo(str, (Plan *) node);
342 343 344
}

/*
345
 *	MergeJoin is a subclass of Join
346 347
 */
static void
348
_outMergeJoin(StringInfo str, MergeJoin *node)
349
{
350
	appendStringInfo(str, " MERGEJOIN ");
351 352
	_outPlanInfo(str, (Plan *) node);

353
	appendStringInfo(str, " :mergeclauses ");
354 355
	_outNode(str, node->mergeclauses);

M
 
Marc G. Fournier 已提交
356
	snprintf(buf, 500, " :mergejoinop %u ", node->mergejoinop);
M
 
Marc G. Fournier 已提交
357 358 359 360 361
	appendStringInfo(str, 
			" :mergejoinop %u :mergerightorder %u :mergeleftorder %u ",
			node->mergejoinop, 
			node->mergerightorder,
			node->mergeleftorder);
362 363 364
}

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

373
	appendStringInfo(str, " :hashclauses ");
374 375
	_outNode(str, node->hashclauses);

M
 
Marc G. Fournier 已提交
376 377 378 379 380 381 382 383 384 385
	appendStringInfo(str, 
			" :hashjoinop %u :hashjointable 0x%x :hashjointablekey %d ",
			node->hashjoinop,
			(int) node->hashjointable,
			node->hashjointablekey);

	appendStringInfo(str, 
			" :hashjointablesize %d :hashdone %d ",
			node->hashjointablesize,
			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);

M
 
Marc G. Fournier 已提交
416
	appendStringInfo(str, " :scanrelid %d ", 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);

M
 
Marc G. Fournier 已提交
428
	appendStringInfo(str, " :scanrelid %d ", 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);

M
 
Marc G. Fournier 已提交
440
	appendStringInfo(str, " :scanrelid %d :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
 *	Temp is a subclass of Plan
453 454
 */
static void
455
_outTemp(StringInfo str, Temp *node)
456
{
457
	appendStringInfo(str, " TEMP ");
458 459
	_outPlanInfo(str, (Plan *) node);

M
 
Marc G. Fournier 已提交
460 461 462
	appendStringInfo(str, " :tempid %u :keycount %d ", 
			node->tempid,
			node->keycount);
463 464 465
}

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

M
 
Marc G. Fournier 已提交
474 475 476
	appendStringInfo(str, " :tempid %u :keycount %d ",
			node->tempid,
			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 498 499
	appendStringInfo(str, " :numCols %d :tuplePerGroup %s,
			node->numCols,
			node->tuplePerGroup ? "true" : "false");
500
}
501

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

M
 
Marc G. Fournier 已提交
511 512 513
	appendStringInfo(str, " :tempid %u :keycount %d ",
			node->tempid,
			node->keycount);
514 515 516 517
}


/*
518
 *	Hash is a subclass of Temp
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 528
	_outNode(str, node->hashkey);

B
Bruce Momjian 已提交
529
	sprintf(buf, " :hashtable 0x%x ", (int) (node->hashtable));
M
 
Marc G. Fournier 已提交
530 531 532 533
	appendStringInfo(str, " :hashtable 0x%x :hashtablekey %d :hashtablesize %d ",
			(int) node->hashtable,
			node->hashtablekey,
			node->hashtablesize);
534 535 536
}

static void
537
_outTee(StringInfo str, Tee *node)
538
{
539
	appendStringInfo(str, " TEE ");
540 541
	_outPlanInfo(str, (Plan *) node);

M
 
Marc G. Fournier 已提交
542 543 544
	appendStringInfo(str, " :leftParent %X :rightParent %X ",
		(int) node->leftParent,
		(int) node->rightParent);
545

546
	appendStringInfo(str, " :rtentries ");
547
	_outNode(str, node->rtentries);
548 549 550 551
}

/*****************************************************************************
 *
552
 *	Stuff from primnodes.h.
553 554 555 556
 *
 *****************************************************************************/

/*
557
 *	Resdom is a subclass of Node
558 559
 */
static void
560
_outResdom(StringInfo str, Resdom *node)
561
{
M
 
Marc G. Fournier 已提交
562 563 564 565
	appendStringInfo(str, " RESDOM :resno %d :restype %u :restypmod %d ",
			node->resno,
			node->restype,
			node->restypmod);
566

M
 
Marc G. Fournier 已提交
567 568 569 570 571
	appendStringInfo(str, " :resname \"%s\" :reskey %d :reskeyop %u :resjunk %d",
			node->resname,
			node->reskey,
			node->reskeyop,
			node->resjunk);
572 573 574
}

static void
575
_outFjoin(StringInfo str, Fjoin *node)
576
{
577
	int			i;
578

M
 
Marc G. Fournier 已提交
579 580 581
	appendStringInfo(str, " FJOIN :initialized %s :nNodes %d ",
			node->fj_initialized ? "true" : "false",
			node->fj_nNodes);
582 583 584 585

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

M
 
Marc G. Fournier 已提交
586 587
	appendStringInfo(str, " :results @ 0x%x :alwaysdone", 
			(int) node->fj_results);
588 589

	for (i = 0; i < node->fj_nNodes; i++)
590
		appendStringInfo(str, (node->fj_alwaysDone[i]) ? "true" : "false");
591 592 593
}

/*
594
 *	Expr is a subclass of Node
595 596
 */
static void
597
_outExpr(StringInfo str, Expr *node)
598
{
599 600
	char		buf[500];
	char	   *opstr = NULL;
601

602
	appendStringInfo(str, " EXPR ");
603

B
Bruce Momjian 已提交
604
	sprintf(buf, " :typeOid %u ", node->typeOid);
605 606 607
	appendStringInfo(str, buf);
	switch (node->opType)
	{
608 609 610 611 612 613 614 615 616 617 618 619 620 621 622
		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 已提交
623 624 625
		case SUBPLAN_EXPR:
			opstr = "subp";
			break;
626
	}
627 628 629
	appendStringInfo(str, " :opType ");
	appendStringInfo(str, opstr);
	appendStringInfo(str, " :oper ");
630
	_outNode(str, node->oper);
631
	appendStringInfo(str, " :args ");
632
	_outNode(str, node->args);
633 634 635
}

/*
636
 *	Var is a subclass of Expr
637 638
 */
static void
639
_outVar(StringInfo str, Var *node)
640
{
641
	char		buf[500];
642

643
	appendStringInfo(str, " VAR ");
B
Bruce Momjian 已提交
644
	sprintf(buf, " :varno %d ", node->varno);
645
	appendStringInfo(str, buf);
646
	sprintf(buf, " :varattno %d ", node->varattno);
647
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
648
	sprintf(buf, " :vartype %u ", node->vartype);
649
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
650
	sprintf(buf, " :vartypmod %d ", node->vartypmod);
651
	appendStringInfo(str, buf);
652 653
	sprintf(buf, " :varlevelsup %u ", node->varlevelsup);
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
654
	sprintf(buf, " :varnoold %d ", node->varnoold);
655
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
656
	sprintf(buf, " :varoattno %d ", node->varoattno);
657
	appendStringInfo(str, buf);
658 659 660
}

/*
661
 *	Const is a subclass of Expr
662 663
 */
static void
664
_outConst(StringInfo str, Const *node)
665
{
666
	char		buf[500];
667

668
	appendStringInfo(str, " CONST ");
B
Bruce Momjian 已提交
669
	sprintf(buf, " :consttype %u ", node->consttype);
670
	appendStringInfo(str, buf);
671
	sprintf(buf, " :constlen %d ", node->constlen);
672
	appendStringInfo(str, buf);
673 674 675
	appendStringInfo(str, " :constisnull ");
	appendStringInfo(str, node->constisnull ? "true" : "false");
	appendStringInfo(str, " :constvalue ");
676
	if (node->constisnull)
B
Bruce Momjian 已提交
677
		appendStringInfo(str, "<>");
678 679
	else
		_outDatum(str, node->constvalue, node->consttype);
680 681
	appendStringInfo(str, " :constbyval ");
	appendStringInfo(str, node->constbyval ? "true" : "false");
682 683 684
}

/*
685
 *	Aggreg
686 687
 */
static void
B
Bruce Momjian 已提交
688
_outAggreg(StringInfo str, Aggreg *node)
689
{
690
	char		buf[500];
691

692
	appendStringInfo(str, " AGGREG ");
693 694
	appendStringInfo(str, " :aggname ");
	appendStringInfo(str, (char *) node->aggname);
B
Bruce Momjian 已提交
695
	sprintf(buf, " :basetype %u ", node->basetype);
696
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
697
	sprintf(buf, " :aggtype %u ", node->aggtype);
698
	appendStringInfo(str, buf);
699 700
	appendStringInfo(str, " :target ");
	_outNode(str, node->target);
B
Bruce Momjian 已提交
701
	sprintf(buf, " :aggno %d ", node->aggno);
702
	appendStringInfo(str, buf);
703 704
	appendStringInfo(str, " :usenulls ");
	appendStringInfo(str, node->usenulls ? "true" : "false");
705 706
}

707 708 709 710 711 712 713 714
/*
 *	SubLink
 */
static void
_outSubLink(StringInfo str, SubLink *node)
{
	char		buf[500];

715
	appendStringInfo(str, " SUBLINK ");
716 717 718 719 720 721 722
	sprintf(buf, " :subLinkType %d ", node->subLinkType);
	appendStringInfo(str, buf);
	appendStringInfo(str, " :useor ");
	appendStringInfo(str, node->useor ? "true" : "false");
	appendStringInfo(str, " :lefthand ");
	_outNode(str, node->lefthand);
	appendStringInfo(str, " :oper ");
B
Bruce Momjian 已提交
723
	_outNode(str, node->oper);
724 725 726 727
	appendStringInfo(str, " :subselect ");
	_outNode(str, node->subselect);
}

728
/*
729
 *	Array is a subclass of Expr
730 731
 */
static void
B
Bruce Momjian 已提交
732
_outArray(StringInfo str, Array *node)
733
{
734 735
	char		buf[500];
	int			i;
736

737
	appendStringInfo(str, " ARRAY ");
B
Bruce Momjian 已提交
738
	sprintf(buf, " :arrayelemtype %u ", node->arrayelemtype);
739
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
740
	sprintf(buf, " :arrayelemlength %d ", node->arrayelemlength);
741
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
742
	sprintf(buf, " :arrayelembyval %c ", (node->arrayelembyval) ? 't' : 'f');
743
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
744
	sprintf(buf, " :arrayndim %d ", node->arrayndim);
745
	appendStringInfo(str, buf);
746
	appendStringInfo(str, " :arraylow ");
747 748
	for (i = 0; i < node->arrayndim; i++)
	{
749
		sprintf(buf, " %d ", node->arraylow.indx[i]);
750 751
		appendStringInfo(str, buf);
	}
752
	appendStringInfo(str, " :arrayhigh ");
753 754
	for (i = 0; i < node->arrayndim; i++)
	{
B
Bruce Momjian 已提交
755
		sprintf(buf, " %d ", node->arrayhigh.indx[i]);
756 757
		appendStringInfo(str, buf);
	}
B
Bruce Momjian 已提交
758
	sprintf(buf, " :arraylen %d ", node->arraylen);
759
	appendStringInfo(str, buf);
760 761 762
}

/*
763
 *	ArrayRef is a subclass of Expr
764 765
 */
static void
B
Bruce Momjian 已提交
766
_outArrayRef(StringInfo str, ArrayRef *node)
767
{
768
	char		buf[500];
769

770
	appendStringInfo(str, " ARRAYREF ");
B
Bruce Momjian 已提交
771
	sprintf(buf, " :refelemtype %u ", node->refelemtype);
772
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
773
	sprintf(buf, " :refattrlength %d ", node->refattrlength);
774
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
775
	sprintf(buf, " :refelemlength %d ", node->refelemlength);
776
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
777
	sprintf(buf, " :refelembyval %c ", (node->refelembyval) ? 't' : 'f');
778 779
	appendStringInfo(str, buf);

780
	appendStringInfo(str, " :refupperindex ");
781 782
	_outNode(str, node->refupperindexpr);

783
	appendStringInfo(str, " :reflowerindex ");
784 785
	_outNode(str, node->reflowerindexpr);

786
	appendStringInfo(str, " :refexpr ");
787 788
	_outNode(str, node->refexpr);

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

/*
794
 *	Func is a subclass of Expr
795 796
 */
static void
797
_outFunc(StringInfo str, Func *node)
798
{
799
	char		buf[500];
800

801
	appendStringInfo(str, " FUNC ");
B
Bruce Momjian 已提交
802
	sprintf(buf, " :funcid %u ", node->funcid);
803
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
804
	sprintf(buf, " :functype %u ", node->functype);
805
	appendStringInfo(str, buf);
806 807
	appendStringInfo(str, " :funcisindex ");
	appendStringInfo(str, (node->funcisindex ? "true" : "false"));
B
Bruce Momjian 已提交
808
	sprintf(buf, " :funcsize %d ", node->funcsize);
809
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
810
	sprintf(buf, " :func_fcache @ 0x%x ", (int) (node->func_fcache));
811 812 813 814 815 816 817
	appendStringInfo(str, buf);

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

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

/*
821
 *	Oper is a subclass of Expr
822 823
 */
static void
824
_outOper(StringInfo str, Oper *node)
825
{
826
	char		buf[500];
827

828
	appendStringInfo(str, " OPER ");
B
Bruce Momjian 已提交
829
	sprintf(buf, " :opno %u ", node->opno);
830
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
831
	sprintf(buf, " :opid %u ", node->opid);
832
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
833
	sprintf(buf, " :opresulttype %u ", node->opresulttype);
834 835
	appendStringInfo(str, buf);

836 837 838
}

/*
839
 *	Param is a subclass of Expr
840 841
 */
static void
842
_outParam(StringInfo str, Param *node)
843
{
844
	char		buf[500];
845

846
	appendStringInfo(str, " PARAM ");
B
Bruce Momjian 已提交
847
	sprintf(buf, " :paramkind %d ", node->paramkind);
848
	appendStringInfo(str, buf);
849
	sprintf(buf, " :paramid %d ", node->paramid);
850
	appendStringInfo(str, buf);
851 852
	appendStringInfo(str, " :paramname ");
	appendStringInfo(str, node->paramname);
B
Bruce Momjian 已提交
853
	sprintf(buf, " :paramtype %u ", node->paramtype);
854 855 856 857
	appendStringInfo(str, buf);

	appendStringInfo(str, " :param_tlist ");
	_outNode(str, node->param_tlist);
858 859 860
}

/*
861
 *	Stuff from execnodes.h
862 863 864
 */

/*
865
 *	EState is a subclass of Node.
866 867
 */
static void
868
_outEState(StringInfo str, EState *node)
869
{
870
	char		buf[500];
871

872
	appendStringInfo(str, " ESTATE ");
B
Bruce Momjian 已提交
873
	sprintf(buf, " :direction %d ", node->es_direction);
874 875
	appendStringInfo(str, buf);

876
	appendStringInfo(str, " :range_table ");
877 878
	_outNode(str, node->es_range_table);

B
Bruce Momjian 已提交
879
	sprintf(buf, " :result_relation_info @ 0x%x ",
880 881 882
			(int) (node->es_result_relation_info));
	appendStringInfo(str, buf);

883 884 885
}

/*
886
 *	Stuff from relation.h
887 888
 */
static void
889
_outRelOptInfo(StringInfo str, RelOptInfo * node)
890
{
891
	char		buf[500];
892

B
Bruce Momjian 已提交
893
	appendStringInfo(str, " RELOPTINFO ");
894

895
	appendStringInfo(str, " :relids ");
896 897
	_outIntList(str, node->relids);

898 899
	appendStringInfo(str, " :indexed ");
	appendStringInfo(str, node->indexed ? "true" : "false");
B
Bruce Momjian 已提交
900
	sprintf(buf, " :pages %u ", node->pages);
901
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
902
	sprintf(buf, " :tuples %u ", node->tuples);
903
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
904
	sprintf(buf, " :size %u ", node->size);
905
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
906
	sprintf(buf, " :width %u ", node->width);
907 908
	appendStringInfo(str, buf);

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

912
	appendStringInfo(str, " :pathlist ");
913 914 915 916 917 918 919 920
	_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 已提交
921
	sprintf(buf, " :unorderedpath @ 0x%x ", (int) (node->unorderedpath));
922
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
923
	sprintf(buf, " :cheapestpath @ 0x%x ", (int) (node->cheapestpath));
924 925
	appendStringInfo(str, buf);

926 927
	appendStringInfo(str, " :pruneable ");
	appendStringInfo(str, node->pruneable ? "true" : "false");
928

929
#if 0
930
	appendStringInfo(str, " :classlist ");
931 932
	_outNode(str, node->classlist);

933
	appendStringInfo(str, " :indexkeys ");
934 935
	_outNode(str, node->indexkeys);

936
	appendStringInfo(str, " :ordering ");
937 938 939
	_outNode(str, node->ordering);
#endif

940
	appendStringInfo(str, " :clauseinfo ");
941 942
	_outNode(str, node->clauseinfo);

943
	appendStringInfo(str, " :joininfo ");
944 945
	_outNode(str, node->joininfo);

946
	appendStringInfo(str, " :innerjoin ");
947 948
	_outNode(str, node->innerjoin);

949 950 951
}

/*
952
 *	TargetEntry is a subclass of Node.
953 954
 */
static void
955
_outTargetEntry(StringInfo str, TargetEntry *node)
956
{
B
Bruce Momjian 已提交
957
	appendStringInfo(str, " TARGETENTRY ");
958
	appendStringInfo(str, " :resdom ");
959 960
	_outNode(str, node->resdom);

961 962
	appendStringInfo(str, " :expr ");
	_outNode(str, node->expr);
963
}
964 965

static void
966
_outRangeTblEntry(StringInfo str, RangeTblEntry *node)
967
{
968
	char		buf[500];
969

970
	appendStringInfo(str, " RTE ");
971

972 973
	appendStringInfo(str, " :relname ");
	appendStringInfo(str, node->relname);
974

975 976
	appendStringInfo(str, " :refname ");
	appendStringInfo(str, node->refname);
977 978 979

	sprintf(buf, " :relid %u ", node->relid);
	appendStringInfo(str, buf);
980 981 982 983 984 985 986 987 988 989

	appendStringInfo(str, " :inh ");
	appendStringInfo(str, node->inh ? "true" : "false");

	appendStringInfo(str, " :inFromCl ");
	appendStringInfo(str, node->inFromCl ? "true" : "false");

	appendStringInfo(str, " :skipAcl ");
	appendStringInfo(str, node->skipAcl ? "true" : "false");

990
}
991 992

/*
993
 *	Path is a subclass of Node.
994 995
 */
static void
996
_outPath(StringInfo str, Path *node)
997
{
998
	char		buf[500];
999

1000
	appendStringInfo(str, " PATH ");
1001

B
Bruce Momjian 已提交
1002
	sprintf(buf, " :pathtype %d ", node->pathtype);
1003 1004
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
1005
	sprintf(buf, " :cost %f ", node->path_cost);
1006 1007
	appendStringInfo(str, buf);

1008
	appendStringInfo(str, " :keys ");
1009 1010
	_outNode(str, node->keys);

1011 1012 1013
}

/*
1014
 *	IndexPath is a subclass of Path.
1015 1016
 */
static void
1017
_outIndexPath(StringInfo str, IndexPath *node)
1018
{
1019
	char		buf[500];
1020

1021
	appendStringInfo(str, " INDEXPATH ");
1022

B
Bruce Momjian 已提交
1023
	sprintf(buf, " :pathtype %d ", node->path.pathtype);
1024 1025 1026 1027 1028 1029 1030
	appendStringInfo(str, buf);

	/*
	 * sprintf(buf, " :parent "); appendStringInfo(str,buf); _outNode(str,
	 * node->parent);
	 */

B
Bruce Momjian 已提交
1031
	sprintf(buf, " :cost %f ", node->path.path_cost);
1032 1033
	appendStringInfo(str, buf);

1034
#if 0
1035
	appendStringInfo(str, " :p_ordering ");
1036 1037
	_outNode(str, node->path.p_ordering);
#endif
1038
	appendStringInfo(str, " :keys ");
1039 1040
	_outNode(str, node->path.keys);

1041
	appendStringInfo(str, " :indexid ");
1042 1043
	_outIntList(str, node->indexid);

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

1047 1048 1049
}

/*
1050
 *	JoinPath is a subclass of Path
1051 1052
 */
static void
1053
_outJoinPath(StringInfo str, JoinPath *node)
1054
{
1055
	char		buf[500];
1056

1057
	appendStringInfo(str, " JOINPATH ");
1058

B
Bruce Momjian 已提交
1059
	sprintf(buf, " :pathtype %d ", node->path.pathtype);
1060 1061 1062 1063 1064 1065 1066
	appendStringInfo(str, buf);

	/*
	 * sprintf(buf, " :parent "); appendStringInfo(str,buf); _outNode(str,
	 * node->parent);
	 */

B
Bruce Momjian 已提交
1067
	sprintf(buf, " :cost %f ", node->path.path_cost);
1068 1069
	appendStringInfo(str, buf);

1070
#if 0
1071
	appendStringInfo(str, " :p_ordering ");
1072 1073
	_outNode(str, node->path.p_ordering);
#endif
1074
	appendStringInfo(str, " :keys ");
1075 1076
	_outNode(str, node->path.keys);

1077
	appendStringInfo(str, " :pathclauseinfo ");
1078 1079 1080 1081 1082 1083 1084
	_outNode(str, node->pathclauseinfo);

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

B
Bruce Momjian 已提交
1085
	sprintf(buf, " :outerjoinpath @ 0x%x ", (int) (node->outerjoinpath));
1086
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1087
	sprintf(buf, " :innerjoinpath @ 0x%x ", (int) (node->innerjoinpath));
1088 1089
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
1090
	sprintf(buf, " :outerjoincost %f ", node->path.outerjoincost);
1091 1092
	appendStringInfo(str, buf);

1093
	appendStringInfo(str, " :joinid ");
1094 1095
	_outIntList(str, node->path.joinid);

1096 1097 1098
}

/*
1099
 *	MergePath is a subclass of JoinPath.
1100 1101
 */
static void
1102
_outMergePath(StringInfo str, MergePath *node)
1103
{
1104
	char		buf[500];
1105

1106
	appendStringInfo(str, " MERGEPATH ");
1107

B
Bruce Momjian 已提交
1108
	sprintf(buf, " :pathtype %d ", node->jpath.path.pathtype);
1109 1110
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
1111
	sprintf(buf, " :cost %f ", node->jpath.path.path_cost);
1112 1113
	appendStringInfo(str, buf);

1114
	appendStringInfo(str, " :keys ");
1115 1116
	_outNode(str, node->jpath.path.keys);

1117
	appendStringInfo(str, " :pathclauseinfo ");
1118 1119 1120 1121 1122 1123 1124
	_outNode(str, node->jpath.pathclauseinfo);

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

B
Bruce Momjian 已提交
1125
	sprintf(buf, " :outerjoinpath @ 0x%x ", (int) (node->jpath.outerjoinpath));
1126
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1127
	sprintf(buf, " :innerjoinpath @ 0x%x ", (int) (node->jpath.innerjoinpath));
1128 1129
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
1130
	sprintf(buf, " :outerjoincost %f ", node->jpath.path.outerjoincost);
1131 1132
	appendStringInfo(str, buf);

1133
	appendStringInfo(str, " :joinid ");
1134 1135
	_outIntList(str, node->jpath.path.joinid);

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

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

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

1145 1146 1147
}

/*
1148
 *	HashPath is a subclass of JoinPath.
1149 1150
 */
static void
1151
_outHashPath(StringInfo str, HashPath *node)
1152
{
1153
	char		buf[500];
1154

1155
	appendStringInfo(str, " HASHPATH ");
1156

B
Bruce Momjian 已提交
1157
	sprintf(buf, " :pathtype %d ", node->jpath.path.pathtype);
1158 1159
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
1160
	sprintf(buf, " :cost %f ", node->jpath.path.path_cost);
1161 1162
	appendStringInfo(str, buf);

1163
	appendStringInfo(str, " :keys ");
1164 1165
	_outNode(str, node->jpath.path.keys);

1166
	appendStringInfo(str, " :pathclauseinfo ");
1167 1168 1169 1170 1171 1172 1173
	_outNode(str, node->jpath.pathclauseinfo);

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

B
Bruce Momjian 已提交
1174
	sprintf(buf, " :outerjoinpath @ 0x%x ", (int) (node->jpath.outerjoinpath));
1175
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1176
	sprintf(buf, " :innerjoinpath @ 0x%x ", (int) (node->jpath.innerjoinpath));
1177 1178
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
1179
	sprintf(buf, " :outerjoincost %f ", node->jpath.path.outerjoincost);
1180 1181
	appendStringInfo(str, buf);

1182
	appendStringInfo(str, " :joinid ");
1183 1184
	_outIntList(str, node->jpath.path.joinid);

1185
	appendStringInfo(str, " :path_hashclauses ");
1186 1187
	_outNode(str, node->path_hashclauses);

1188
	appendStringInfo(str, " :outerhashkeys ");
1189 1190
	_outNode(str, node->outerhashkeys);

1191
	appendStringInfo(str, " :innerhashkeys ");
1192 1193
	_outNode(str, node->innerhashkeys);

1194 1195 1196
}

/*
1197
 *	OrderKey is a subclass of Node.
1198 1199
 */
static void
1200
_outOrderKey(StringInfo str, OrderKey *node)
1201
{
1202
	char		buf[500];
1203

1204
	appendStringInfo(str, " ORDERKEY ");
B
Bruce Momjian 已提交
1205
	sprintf(buf, " :attribute_number %d ", node->attribute_number);
1206
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1207
	sprintf(buf, " :array_index %d ", node->array_index);
1208 1209
	appendStringInfo(str, buf);

1210 1211 1212
}

/*
1213
 *	JoinKey is a subclass of Node.
1214 1215
 */
static void
1216
_outJoinKey(StringInfo str, JoinKey *node)
1217
{
1218
	appendStringInfo(str, " JOINKEY ");
1219

1220
	appendStringInfo(str, " :outer ");
1221 1222
	_outNode(str, node->outer);

1223
	appendStringInfo(str, " :inner ");
1224 1225
	_outNode(str, node->inner);

1226 1227 1228
}

/*
1229
 *	MergeOrder is a subclass of Node.
1230 1231
 */
static void
1232
_outMergeOrder(StringInfo str, MergeOrder *node)
1233
{
1234
	char		buf[500];
1235

1236
	appendStringInfo(str, " MERGEORDER ");
1237

B
Bruce Momjian 已提交
1238
	sprintf(buf, " :join_operator %d ", node->join_operator);
1239
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1240
	sprintf(buf, " :left_operator %d ", node->left_operator);
1241
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1242
	sprintf(buf, " :right_operator %d ", node->right_operator);
1243
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1244
	sprintf(buf, " :left_type %d ", node->left_type);
1245
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1246
	sprintf(buf, " :right_type %d ", node->right_type);
1247 1248
	appendStringInfo(str, buf);

1249 1250 1251
}

/*
1252
 *	ClauseInfo is a subclass of Node.
1253 1254
 */
static void
1255
_outClauseInfo(StringInfo str, ClauseInfo * node)
1256
{
1257
	char		buf[500];
1258

1259
	appendStringInfo(str, " CINFO ");
1260

1261
	appendStringInfo(str, " :clause ");
1262 1263
	_outNode(str, node->clause);

B
Bruce Momjian 已提交
1264
	sprintf(buf, " :selectivity %f ", node->selectivity);
1265
	appendStringInfo(str, buf);
1266 1267
	appendStringInfo(str, " :notclause ");
	appendStringInfo(str, node->notclause ? "true" : "false");
1268

1269
	appendStringInfo(str, " :indexids ");
1270 1271
	_outNode(str, node->indexids);

1272 1273
	appendStringInfo(str, " :mergejoinorder ");
	_outNode(str, node->mergejoinorder);
1274

B
Bruce Momjian 已提交
1275
	sprintf(buf, " :hashjoinoperator %u ", node->hashjoinoperator);
1276 1277
	appendStringInfo(str, buf);

1278 1279 1280
}

/*
1281
 *	JoinMethod is a subclass of Node.
1282 1283
 */
static void
1284
_outJoinMethod(StringInfo str, JoinMethod *node)
1285
{
1286
	appendStringInfo(str, " JOINMETHOD ");
1287

1288
	appendStringInfo(str, " :jmkeys ");
1289 1290
	_outNode(str, node->jmkeys);

1291
	appendStringInfo(str, " :clauses ");
1292 1293 1294
	_outNode(str, node->clauses);


1295 1296 1297 1298 1299 1300
}

/*
 * HInfo is a subclass of JoinMethod.
 */
static void
1301
_outHInfo(StringInfo str, HInfo *node)
1302
{
1303
	char		buf[500];
1304

1305
	appendStringInfo(str, " HASHINFO ");
1306

1307
	appendStringInfo(str, " :hashop ");
B
Bruce Momjian 已提交
1308
	sprintf(buf, " %u ", node->hashop);
1309 1310
	appendStringInfo(str, buf);

1311
	appendStringInfo(str, " :jmkeys ");
1312 1313
	_outNode(str, node->jmethod.jmkeys);

1314
	appendStringInfo(str, " :clauses ");
1315 1316
	_outNode(str, node->jmethod.clauses);

1317 1318 1319
}

/*
1320
 *	JoinInfo is a subclass of Node.
1321 1322
 */
static void
1323
_outJoinInfo(StringInfo str, JoinInfo * node)
1324
{
1325
	appendStringInfo(str, " JINFO ");
1326

1327
	appendStringInfo(str, " :otherrels ");
1328 1329
	_outIntList(str, node->otherrels);

1330
	appendStringInfo(str, " :jinfoclauseinfo ");
1331 1332
	_outNode(str, node->jinfoclauseinfo);

1333 1334
	appendStringInfo(str, " :mergejoinable ");
	appendStringInfo(str, node->mergejoinable ? "true" : "false");
1335 1336
	appendStringInfo(str, " :hashjoinable ");
	appendStringInfo(str, node->hashjoinable ? "true" : "false");
1337

1338 1339 1340 1341 1342 1343 1344 1345
}

/*
 * Print the value of a Datum given its type.
 */
static void
_outDatum(StringInfo str, Datum value, Oid type)
{
1346 1347 1348 1349 1350 1351
	char		buf[500];
	Size		length,
				typeLength;
	bool		byValue;
	int			i;
	char	   *s;
1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367

	/*
	 * 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);
		sprintf(buf, " %d [ ", length);
		appendStringInfo(str, buf);
		for (i = 0; i < sizeof(Datum); i++)
		{
B
Bruce Momjian 已提交
1368
			sprintf(buf, " %d ", (int) (s[i]));
1369 1370 1371 1372
			appendStringInfo(str, buf);
		}
		sprintf(buf, "] ");
		appendStringInfo(str, buf);
1373
	}
1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394
	else
	{							/* !byValue */
		s = (char *) DatumGetPointer(value);
		if (!PointerIsValid(s))
		{
			sprintf(buf, " 0 [ ] ");
			appendStringInfo(str, buf);
		}
		else
		{

			/*
			 * 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);
			sprintf(buf, " %d [ ", length);
			appendStringInfo(str, buf);
			for (i = 0; i < length; i++)
			{
B
Bruce Momjian 已提交
1395
				sprintf(buf, " %d ", (int) (s[i]));
1396 1397 1398 1399 1400
				appendStringInfo(str, buf);
			}
			sprintf(buf, "] ");
			appendStringInfo(str, buf);
		}
1401 1402 1403 1404
	}
}

static void
1405
_outIter(StringInfo str, Iter *node)
1406
{
1407
	appendStringInfo(str, " ITER ");
1408 1409 1410

	appendStringInfo(str, " :iterexpr ");
	_outNode(str, node->iterexpr);
1411 1412 1413
}

static void
1414
_outStream(StringInfo str, Stream *node)
1415
{
1416
	char		buf[500];
1417

1418
	appendStringInfo(str, " STREAM ");
1419

B
Bruce Momjian 已提交
1420
	sprintf(buf, " :pathptr @ 0x%x ", (int) (node->pathptr));
1421 1422
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
1423
	sprintf(buf, " :cinfo @ 0x%x ", (int) (node->cinfo));
1424 1425
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
1426
	sprintf(buf, " :clausetype %d ", (int) (node->clausetype));
1427 1428
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
1429
	sprintf(buf, " :upstream @ 0x%x ", (int) (node->upstream));
1430 1431
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
1432
	sprintf(buf, " :downstream @ 0x%x ", (int) (node->downstream));
1433 1434
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
1435
	sprintf(buf, " :groupup %d ", node->groupup);
1436 1437
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
1438
	sprintf(buf, " :groupcost %f ", node->groupcost);
1439 1440
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
1441
	sprintf(buf, " :groupsel %f ", node->groupsel);
1442 1443
	appendStringInfo(str, buf);
}
1444

1445 1446 1447
static void
_outAExpr(StringInfo str, A_Expr *node)
{
1448
	appendStringInfo(str, "EXPR ");
1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473
#ifdef PARSEDEBUG
	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:
#endif
			appendStringInfo(str, node->opname);
#ifdef PARSEDEBUG
			break;
	}
#endif
1474 1475 1476 1477 1478
	_outNode(str, node->lexpr);
	_outNode(str, node->rexpr);
	return;
}

1479
static void
1480
_outValue(StringInfo str, Value *value)
1481
{
1482
	char		buf[500];
1483 1484 1485

	switch (value->type)
	{
1486
		case T_String:
B
Bruce Momjian 已提交
1487
			sprintf(buf, " \"%s\" ", value->val.str);
1488 1489 1490
			appendStringInfo(str, buf);
			break;
		case T_Integer:
B
Bruce Momjian 已提交
1491
			sprintf(buf, " %ld ", value->val.ival);
1492 1493 1494
			appendStringInfo(str, buf);
			break;
		case T_Float:
B
Bruce Momjian 已提交
1495
			sprintf(buf, " %f ", value->val.dval);
1496 1497 1498 1499
			appendStringInfo(str, buf);
			break;
		default:
			break;
1500 1501
	}
	return;
1502 1503
}

1504 1505 1506 1507 1508
static void
_outIdent(StringInfo str, Ident *node)
{
	char		buf[500];

B
Bruce Momjian 已提交
1509
	sprintf(buf, " IDENT \"%s\" ", node->name);
1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524
	appendStringInfo(str, buf);
	return;
}

static void
_outAConst(StringInfo str, A_Const *node)
{
	char		buf[500];

	sprintf(buf, "CONST ");
	appendStringInfo(str, buf);
	_outValue(str, &(node->val));
	return;
}

T
Thomas G. Lockhart 已提交
1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591
static void
_outConstraint(StringInfo str, Constraint *node)
{
	char		buf[500];

	sprintf(buf," %s :type",
		((node->name != NULL)? node->name: "<>"));
	appendStringInfo(str, buf);

	switch (node->contype)
	{
		case CONSTR_PRIMARY:
			sprintf(buf," PRIMARY KEY ");
			appendStringInfo(str, buf);
			_outNode(str, node->keys);
			break;

		case CONSTR_CHECK:
			sprintf(buf," CHECK ");
			appendStringInfo(str, buf);
			appendStringInfo(str, node->def);
			break;

		case CONSTR_DEFAULT:
			sprintf(buf," DEFAULT ");
			appendStringInfo(str, buf);
			appendStringInfo(str, node->def);
			break;

		case CONSTR_NOTNULL:
			sprintf(buf," NOT NULL ");
			appendStringInfo(str, buf);
			break;

		case CONSTR_UNIQUE:
			sprintf(buf," UNIQUE ");
			appendStringInfo(str, buf);
			_outNode(str, node->keys);
			break;

		default:
			sprintf(buf,"<unrecognized constraint>");
			appendStringInfo(str, buf);
			break;
	}
	return;
}

static void
_outCaseExpr(StringInfo str, CaseExpr *node)
{
	char		buf[500];

	sprintf(buf, "CASE ");
	appendStringInfo(str, buf);
	_outNode(str, node->args);
	sprintf(buf, " :default ");
	appendStringInfo(str, buf);
	_outNode(str, node->defresult);
	return;
}

static void
_outCaseWhen(StringInfo str, CaseWhen *node)
{
	char		buf[500];

1592
	sprintf(buf, " WHEN ");
T
Thomas G. Lockhart 已提交
1593 1594 1595 1596 1597 1598 1599 1600
	appendStringInfo(str, buf);
	_outNode(str, node->expr);
	sprintf(buf, " :then ");
	appendStringInfo(str, buf);
	_outNode(str, node->result);
	return;
}

1601 1602
/*
 * _outNode -
1603
 *	  converts a Node into ascii string and append it to 'str'
1604 1605 1606 1607
 */
static void
_outNode(StringInfo str, void *obj)
{
1608 1609
	if (obj == NULL)
	{
B
Bruce Momjian 已提交
1610
		appendStringInfo(str, "<>");
1611 1612
		return;
	}
1613

1614 1615
	if (nodeTag(obj) == T_List)
	{
1616
		List	   *l;
1617 1618 1619 1620 1621 1622 1623 1624 1625

		appendStringInfo(str, "(");
		foreach(l, (List *) obj)
		{
			_outNode(str, lfirst(l));
			if (lnext(l))
				appendStringInfo(str, " ");
		}
		appendStringInfo(str, ")");
1626
	}
1627 1628 1629 1630 1631
	else
	{
		appendStringInfo(str, "{");
		switch (nodeTag(obj))
		{
1632 1633 1634 1635 1636 1637 1638 1639 1640 1641
			case T_CreateStmt:
				_outCreateStmt(str, obj);
				break;
			case T_IndexStmt:
				_outIndexStmt(str, obj);
				break;

			case T_ColumnDef:
				_outColumnDef(str, obj);
				break;
1642 1643 1644
			case T_TypeName:
				_outTypeName(str, obj);
				break;
1645 1646 1647 1648
			case T_IndexElem:
				_outIndexElem(str, obj);
				break;

1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659
#ifdef PARSEDEBUG
			case T_VariableSetStmt:
				break;
			case T_SelectStmt:
				_outSelectStmt(str, obj);
				break;
			case T_FuncCall:
				_outFuncCall(str, obj);
				break;
#endif

1660 1661 1662
			case T_Query:
				_outQuery(str, obj);
				break;
1663 1664 1665 1666 1667
			case T_SortClause:
				_outSortClause(str, obj);
				break;
			case T_GroupClause:
				_outGroupClause(str, obj);
1668
				break;
1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716
			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;
			case T_Temp:
				_outTemp(str, obj);
				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 已提交
1717 1718 1719
			case T_SubPlan:
				_outSubPlan(str, obj);
				break;
1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740
			case T_Tee:
				_outTee(str, obj);
				break;
			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;
			case T_Aggreg:
				_outAggreg(str, obj);
				break;
1741 1742 1743
			case T_SubLink:
				_outSubLink(str, obj);
				break;
1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761
			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 已提交
1762
			case T_RelOptInfo:
B
Bruce Momjian 已提交
1763
				_outRelOptInfo(str, obj);
1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794
				break;
			case T_TargetEntry:
				_outTargetEntry(str, obj);
				break;
			case T_RangeTblEntry:
				_outRangeTblEntry(str, obj);
				break;
			case T_Path:
				_outPath(str, obj);
				break;
			case T_IndexPath:
				_outIndexPath(str, obj);
				break;
			case T_JoinPath:
				_outJoinPath(str, obj);
				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;
1795 1796
			case T_ClauseInfo:
				_outClauseInfo(str, obj);
1797 1798 1799 1800 1801 1802 1803
				break;
			case T_JoinMethod:
				_outJoinMethod(str, obj);
				break;
			case T_HInfo:
				_outHInfo(str, obj);
				break;
1804 1805
			case T_JoinInfo:
				_outJoinInfo(str, obj);
1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817
				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;
1818 1819 1820 1821 1822 1823 1824 1825 1826
			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 已提交
1827 1828 1829 1830 1831 1832 1833 1834 1835
			case T_Constraint:
				_outConstraint(str, obj);
				break;
			case T_CaseExpr:
				_outCaseExpr(str, obj);
				break;
			case T_CaseWhen:
				_outCaseWhen(str, obj);
				break;
1836
			default:
B
Bruce Momjian 已提交
1837
				elog(NOTICE, "_outNode: don't know how to print type %d ",
1838 1839
					 nodeTag(obj));
				break;
1840 1841
		}
		appendStringInfo(str, "}");
1842
	}
1843
	return;
1844 1845 1846 1847
}

/*
 * nodeToString -
1848
 *	   returns the ascii representation of the Node
1849
 */
1850
char *
1851 1852
nodeToString(void *obj)
{
1853 1854
	StringInfo	str;
	char	   *s;
1855 1856 1857 1858 1859 1860 1861 1862 1863 1864

	if (obj == NULL)
		return "";
	Assert(obj != NULL);
	str = makeStringInfo();
	_outNode(str, obj);
	s = str->data;
	pfree(str);

	return s;
1865
}