outfuncs.c 35.2 KB
Newer Older
M
 
Marc G. Fournier 已提交
1
/*
2 3
 *
 * outfuncs.c--
4
 *	  routines to convert a node to ascii representation
5 6 7
 *
 * Copyright (c) 1994, Regents of the University of California
 *
8
 *  $Id: outfuncs.c,v 1.57 1998/12/18 14:45:08 wieck 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)
{
72 73
	appendStringInfo(str, " CREATE :relname %s :columns ", 
		stringStringInfo(node->relname));
74 75

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

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

91
	_outNode(str, node->indexParams);
92 93 94 95 96 97
	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 已提交
98 99 100 101

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

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

static void
_outFuncCall(StringInfo str, FuncCall *node)
{
115 116
	appendStringInfo(str, "FUNCTION %s :args ",
			stringStringInfo(node->funcname));
117 118
	_outNode(str, node->args);
}
119

120 121
#endif

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

	appendStringInfo(str, " :is_not_null %s :defval %s :constraints ",
130 131
			node->is_not_null ? "true" : "false", 
			stringStringInfo(node->defval));
132
	_outNode(str, node->constraints);
133 134 135 136 137
}

static void
_outTypeName(StringInfo str, TypeName *node)
{
M
 
Marc G. Fournier 已提交
138 139
	appendStringInfo(str, 
			" TYPENAME :name %s :timezone %s :setof %s typmod %d :arrayBounds ",
140
			stringStringInfo(node->name), 
M
 
Marc G. Fournier 已提交
141
			node->timezone ? "true" : "false",
M
 
Marc G. Fournier 已提交
142
			node->setof ? "true" : "false",
M
 
Marc G. Fournier 已提交
143
			node->typmod);
144 145 146 147

	appendStringInfo(str, " :arrayBounds ");
	_outNode(str, node->arrayBounds);
}
148 149 150 151

static void
_outIndexElem(StringInfo str, IndexElem *node)
{
152 153
	appendStringInfo(str, " INDEXELEM :name %s :args ",
			stringStringInfo(node->name));
154
	_outNode(str, node->args);
M
 
Marc G. Fournier 已提交
155

156 157
	appendStringInfo(str, " :class %s :typename ", 
			stringStringInfo(node->class));
158
	_outNode(str, node->typename);
159
}
160

161
static void
162
_outQuery(StringInfo str, Query *node)
163
{
M
 
Marc G. Fournier 已提交
164
	appendStringInfo(str, " QUERY :command %d ", node->commandType);
165

166 167 168 169 170
	if (node->utilityStmt)
	{
		switch (nodeTag(node->utilityStmt))
		{
			case T_CreateStmt:
M
 
Marc G. Fournier 已提交
171
				appendStringInfo(str, " :create %s ",
172
						stringStringInfo(((CreateStmt *) (node->utilityStmt))->relname));
173 174 175 176
				_outNode(str, node->utilityStmt);
				break;

			case T_IndexStmt:
M
 
Marc G. Fournier 已提交
177
				appendStringInfo(str, " :index %s on %s ",
178 179
					stringStringInfo(((IndexStmt *) (node->utilityStmt))->idxname),
					stringStringInfo(((IndexStmt *) (node->utilityStmt))->relname));
180 181 182 183
				_outNode(str, node->utilityStmt);
				break;

			case T_NotifyStmt:
M
 
Marc G. Fournier 已提交
184
				appendStringInfo(str, " :utility %s ",
185
						stringStringInfo(((NotifyStmt *) (node->utilityStmt))->relname));
186 187 188
				break;

			default:
189
				appendStringInfo(str, " :utility ? ");
190 191
		}
	}
192
	else
193
	{
194
		appendStringInfo(str, " :utility <>");
195
	}
196

M
 
Marc G. Fournier 已提交
197 198 199
	appendStringInfo(str, 
			" :resultRelation %d :into %s :isPortal %s :isBinary %s :unionall %s ",
			node->resultRelation,
200
			stringStringInfo(node->into),
M
 
Marc G. Fournier 已提交
201 202 203 204
			node->isPortal ? "true" : "false",
			node->isBinary ? "true" : "false",
			node->unionall ? "true" : "false");

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

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

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

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

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

221
	appendStringInfo(str, " :havingQual ");
222
	_outNode(str, node->havingQual);
M
 
Marc G. Fournier 已提交
223 224 225 226

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

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

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

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

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

static void
_outGroupClause(StringInfo str, GroupClause *node)
{
M
 
Marc G. Fournier 已提交
248
	appendStringInfo(str, " GROUPCLAUSE :entry ");
249
	_outNode(str, node->entry);
M
 
Marc G. Fournier 已提交
250 251

	appendStringInfo(str, " :grpOpoid %u ", node->grpOpoid);
252 253 254 255 256 257
}

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

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

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

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

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

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

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

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

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

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

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

308 309 310
}

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

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

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

M
 
Marc G. Fournier 已提交
325 326 327
	appendStringInfo(str, 
		" :inheritrelid %d :inheritrtable ", 
		node->inheritrelid);
328
	_outNode(str, node->inheritrtable);
329

330 331 332
}

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

341 342 343
}

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

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

362
	appendStringInfo(str, " :mergeclauses ");
363 364
	_outNode(str, node->mergeclauses);

M
 
Marc G. Fournier 已提交
365 366 367 368 369
	appendStringInfo(str, 
			" :mergejoinop %u :mergerightorder %u :mergeleftorder %u ",
			node->mergejoinop, 
			node->mergerightorder,
			node->mergeleftorder);
370 371 372
}

/*
373
 *	HashJoin is a subclass of Join.
374 375
 */
static void
376
_outHashJoin(StringInfo str, HashJoin *node)
377
{
378
	appendStringInfo(str, " HASHJOIN ");
379 380
	_outPlanInfo(str, (Plan *) node);

381
	appendStringInfo(str, " :hashclauses ");
382 383
	_outNode(str, node->hashclauses);

M
 
Marc G. Fournier 已提交
384 385 386 387 388 389 390 391 392 393
	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);
394 395
}

V
Vadim B. Mikheev 已提交
396 397 398
static void
_outSubPlan(StringInfo str, SubPlan *node)
{
M
 
Marc G. Fournier 已提交
399
	appendStringInfo(str, " SUBPLAN :plan ");
V
Vadim B. Mikheev 已提交
400
	_outNode(str, node->plan);
M
 
Marc G. Fournier 已提交
401 402

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

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

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

V
Vadim B. Mikheev 已提交
411 412 413 414
	appendStringInfo(str, " :slink ");
	_outNode(str, node->sublink);
}

415
/*
416
 *	Scan is a subclass of Node
417 418
 */
static void
419
_outScan(StringInfo str, Scan *node)
420
{
421
	appendStringInfo(str, " SCAN ");
422 423
	_outPlanInfo(str, (Plan *) node);

M
 
Marc G. Fournier 已提交
424
	appendStringInfo(str, " :scanrelid %d ", node->scanrelid);
425 426 427
}

/*
428
 *	SeqScan is a subclass of Scan
429 430
 */
static void
431
_outSeqScan(StringInfo str, SeqScan *node)
432
{
433
	appendStringInfo(str, " SEQSCAN ");
434 435
	_outPlanInfo(str, (Plan *) node);

M
 
Marc G. Fournier 已提交
436
	appendStringInfo(str, " :scanrelid %d ", node->scanrelid);
437 438 439
}

/*
440
 *	IndexScan is a subclass of Scan
441 442
 */
static void
443
_outIndexScan(StringInfo str, IndexScan *node)
444
{
445
	appendStringInfo(str, " INDEXSCAN ");
446 447
	_outPlanInfo(str, (Plan *) node);

M
 
Marc G. Fournier 已提交
448
	appendStringInfo(str, " :scanrelid %d :indxid ", node->scan.scanrelid);
449 450
	_outIntList(str, node->indxid);

451
	appendStringInfo(str, " :indxqual ");
452 453
	_outNode(str, node->indxqual);

V
Vadim B. Mikheev 已提交
454 455 456
	appendStringInfo(str, " :indxqualorig ");
	_outNode(str, node->indxqualorig);

457 458 459
}

/*
460
 *	Temp is a subclass of Plan
461 462
 */
static void
463
_outTemp(StringInfo str, Temp *node)
464
{
465
	appendStringInfo(str, " TEMP ");
466 467
	_outPlanInfo(str, (Plan *) node);

M
 
Marc G. Fournier 已提交
468 469 470
	appendStringInfo(str, " :tempid %u :keycount %d ", 
			node->tempid,
			node->keycount);
471 472 473
}

/*
474
 *	Sort is a subclass of Temp
475 476
 */
static void
477
_outSort(StringInfo str, Sort *node)
478
{
479
	appendStringInfo(str, " SORT ");
480 481
	_outPlanInfo(str, (Plan *) node);

M
 
Marc G. Fournier 已提交
482 483 484
	appendStringInfo(str, " :tempid %u :keycount %d ",
			node->tempid,
			node->keycount);
485 486 487
}

static void
B
Bruce Momjian 已提交
488
_outAgg(StringInfo str, Agg *node)
489
{
490

491
	appendStringInfo(str, " AGG ");
492 493
	_outPlanInfo(str, (Plan *) node);

494 495
	appendStringInfo(str, " :aggs ");
	_outNode(str, node->aggs);
496 497 498
}

static void
499
_outGroup(StringInfo str, Group *node)
500
{
501
	appendStringInfo(str, " GRP ");
502 503 504
	_outPlanInfo(str, (Plan *) node);

	/* the actual Group fields */
M
 
Marc G. Fournier 已提交
505
	appendStringInfo(str, " :numCols %d :tuplePerGroup %s ",
M
 
Marc G. Fournier 已提交
506 507
			node->numCols,
			node->tuplePerGroup ? "true" : "false");
508
}
509

510
/*
511
 *	For some reason, unique is a subclass of Temp.
512 513
 */
static void
514
_outUnique(StringInfo str, Unique *node)
515
{
516
	appendStringInfo(str, " UNIQUE ");
517 518
	_outPlanInfo(str, (Plan *) node);

M
 
Marc G. Fournier 已提交
519 520 521
	appendStringInfo(str, " :tempid %u :keycount %d ",
			node->tempid,
			node->keycount);
522 523 524 525
}


/*
526
 *	Hash is a subclass of Temp
527 528
 */
static void
529
_outHash(StringInfo str, Hash *node)
530
{
531
	appendStringInfo(str, " HASH ");
532 533
	_outPlanInfo(str, (Plan *) node);

534
	appendStringInfo(str, " :hashkey ");
535 536
	_outNode(str, node->hashkey);

M
 
Marc G. Fournier 已提交
537 538 539 540
	appendStringInfo(str, " :hashtable 0x%x :hashtablekey %d :hashtablesize %d ",
			(int) node->hashtable,
			node->hashtablekey,
			node->hashtablesize);
541 542 543
}

static void
544
_outTee(StringInfo str, Tee *node)
545
{
546
	appendStringInfo(str, " TEE ");
547 548
	_outPlanInfo(str, (Plan *) node);

M
 
Marc G. Fournier 已提交
549 550 551
	appendStringInfo(str, " :leftParent %X :rightParent %X ",
		(int) node->leftParent,
		(int) node->rightParent);
552

553
	appendStringInfo(str, " :rtentries ");
554
	_outNode(str, node->rtentries);
555 556 557 558
}

/*****************************************************************************
 *
559
 *	Stuff from primnodes.h.
560 561 562 563
 *
 *****************************************************************************/

/*
564
 *	Resdom is a subclass of Node
565 566
 */
static void
567
_outResdom(StringInfo str, Resdom *node)
568
{
M
 
Marc G. Fournier 已提交
569 570 571 572
	appendStringInfo(str, " RESDOM :resno %d :restype %u :restypmod %d ",
			node->resno,
			node->restype,
			node->restypmod);
573

M
 
Marc G. Fournier 已提交
574
	appendStringInfo(str, " :resname \"%s\" :reskey %d :reskeyop %u :resjunk %d",
575
			stringStringInfo(node->resname),
M
 
Marc G. Fournier 已提交
576 577 578
			node->reskey,
			node->reskeyop,
			node->resjunk);
579 580 581
}

static void
582
_outFjoin(StringInfo str, Fjoin *node)
583
{
584
	int			i;
585

M
 
Marc G. Fournier 已提交
586 587 588
	appendStringInfo(str, " FJOIN :initialized %s :nNodes %d ",
			node->fj_initialized ? "true" : "false",
			node->fj_nNodes);
589 590 591 592

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

M
 
Marc G. Fournier 已提交
593 594
	appendStringInfo(str, " :results @ 0x%x :alwaysdone", 
			(int) node->fj_results);
595 596

	for (i = 0; i < node->fj_nNodes; i++)
597
		appendStringInfo(str, (node->fj_alwaysDone[i]) ? "true" : "false");
598 599 600
}

/*
601
 *	Expr is a subclass of Node
602 603
 */
static void
604
_outExpr(StringInfo str, Expr *node)
605
{
606
	char	   *opstr = NULL;
607

M
 
Marc G. Fournier 已提交
608 609
	appendStringInfo(str, " EXPR :typeOid %u ",
			node->typeOid);
610 611 612

	switch (node->opType)
	{
613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
		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 已提交
628 629 630
		case SUBPLAN_EXPR:
			opstr = "subp";
			break;
631
	}
632
	appendStringInfo(str, " :opType %s :oper ", stringStringInfo(opstr));
633
	_outNode(str, node->oper);
M
 
Marc G. Fournier 已提交
634

635
	appendStringInfo(str, " :args ");
636
	_outNode(str, node->args);
637 638 639
}

/*
640
 *	Var is a subclass of Expr
641 642
 */
static void
643
_outVar(StringInfo str, Var *node)
644
{
M
 
Marc G. Fournier 已提交
645
	appendStringInfo(str, 
M
 
Marc G. Fournier 已提交
646
			" VAR :varno %d :varattno %d :vartype %u :vartypmod %d ",
M
 
Marc G. Fournier 已提交
647 648 649 650 651 652 653 654 655
			node->varno,
			node->varattno,
			node->vartype,
			node->vartypmod);

	appendStringInfo(str, " :varlevelsup %u :varnoold %d :varoattno %d" ,
			node->varlevelsup,
			node->varnoold,
			node->varoattno);
656 657 658
}

/*
659
 *	Const is a subclass of Expr
660 661
 */
static void
662
_outConst(StringInfo str, Const *node)
663
{
M
 
Marc G. Fournier 已提交
664 665 666 667 668 669
	appendStringInfo(str, 
			" CONST :consttype %u :constlen %d :constisnull %s :constvalue ",
			node->consttype,
			node->constlen,
			node->constisnull ? "true" : "false");

670
	if (node->constisnull)
B
Bruce Momjian 已提交
671
		appendStringInfo(str, "<>");
672 673
	else
		_outDatum(str, node->constvalue, node->consttype);
M
 
Marc G. Fournier 已提交
674 675 676

	appendStringInfo(str, " :constbyval %s ", 
			node->constbyval ? "true" : "false");
677 678 679
}

/*
680
 *	Aggreg
681 682
 */
static void
B
Bruce Momjian 已提交
683
_outAggreg(StringInfo str, Aggreg *node)
684
{
M
 
Marc G. Fournier 已提交
685 686
	appendStringInfo(str, 
			" AGGREG :aggname %s :basetype %u :aggtype %u :target ",
687
			stringStringInfo(node->aggname),
M
 
Marc G. Fournier 已提交
688 689
			node->basetype,
			node->aggtype);
690
	_outNode(str, node->target);
M
 
Marc G. Fournier 已提交
691 692 693 694

	appendStringInfo(str, ":aggno %d :usenulls %s",
			node->aggno,
			node->usenulls ? "true" : "false");
695 696
}

697 698 699 700 701 702
/*
 *	SubLink
 */
static void
_outSubLink(StringInfo str, SubLink *node)
{
M
 
Marc G. Fournier 已提交
703 704 705 706
	appendStringInfo(str, 
			" SUBLINK :subLinkType %d :useor %s :lefthand ",
			node->subLinkType,
			node->useor ? "true" : "false");
707
	_outNode(str, node->lefthand);
M
 
Marc G. Fournier 已提交
708

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

712 713 714 715
	appendStringInfo(str, " :subselect ");
	_outNode(str, node->subselect);
}

716
/*
717
 *	Array is a subclass of Expr
718 719
 */
static void
B
Bruce Momjian 已提交
720
_outArray(StringInfo str, Array *node)
721
{
722
	int			i;
723

M
 
Marc G. Fournier 已提交
724 725 726 727 728 729 730
	appendStringInfo(str, 
			" ARRAY :arrayelemtype %u :arrayelemlength %d :arrayelembyval %c ",
			node->arrayelemtype, 
			node->arrayelemlength,
			node->arrayelembyval ? 't' : 'f');

	appendStringInfo(str, " :arrayndim %d ", node->arrayndim);
731
	appendStringInfo(str, " :arraylow ");
732 733
	for (i = 0; i < node->arrayndim; i++)
	{
M
 
Marc G. Fournier 已提交
734
		appendStringInfo(str, " %d ", node->arraylow.indx[i]);
735
	}
736
	appendStringInfo(str, " :arrayhigh ");
737 738
	for (i = 0; i < node->arrayndim; i++)
	{
M
 
Marc G. Fournier 已提交
739
		appendStringInfo(str, " %d ", node->arrayhigh.indx[i]);
740
	}
M
 
Marc G. Fournier 已提交
741
	appendStringInfo(str, " :arraylen %d ", node->arraylen);
742 743 744
}

/*
745
 *	ArrayRef is a subclass of Expr
746 747
 */
static void
B
Bruce Momjian 已提交
748
_outArrayRef(StringInfo str, ArrayRef *node)
749
{
M
 
Marc G. Fournier 已提交
750 751 752 753 754 755 756 757
	appendStringInfo(str, 
			" ARRAYREF :refelemtype %u :refattrlength $d :refelemlength %d ",
			node->refelemtype,
			node->refattrlength,
			node->refelemlength);

	appendStringInfo(str, " :refelembyval %c :refupperindex ", 
			node->refelembyval ? 't' : 'f');
758 759
	_outNode(str, node->refupperindexpr);

760
	appendStringInfo(str, " :reflowerindex ");
761 762
	_outNode(str, node->reflowerindexpr);

763
	appendStringInfo(str, " :refexpr ");
764 765
	_outNode(str, node->refexpr);

766
	appendStringInfo(str, " :refassgnexpr ");
767
	_outNode(str, node->refassgnexpr);
768 769 770
}

/*
771
 *	Func is a subclass of Expr
772 773
 */
static void
774
_outFunc(StringInfo str, Func *node)
775
{
M
 
Marc G. Fournier 已提交
776 777 778 779 780 781 782 783 784
	appendStringInfo(str, 
			" FUNC :funcid %u :functype %u :funcisindex %s :funcsize %d ",
			node->funcid,
			node->functype,
			node->funcisindex ? "true" : "false",
			node->funcsize);

	appendStringInfo(str, " :func_fcache @ 0x%x :func_tlist ",
			(int) node->func_fcache);
785 786 787 788
	_outNode(str, node->func_tlist);

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

/*
792
 *	Oper is a subclass of Expr
793 794
 */
static void
795
_outOper(StringInfo str, Oper *node)
796
{
M
 
Marc G. Fournier 已提交
797 798 799 800 801
	appendStringInfo(str, 
			" OPER :opno %u :opid %u :opresulttype %u ",
			node->opno,
			node->opid,
			node->opresulttype);
802 803 804
}

/*
805
 *	Param is a subclass of Expr
806 807
 */
static void
808
_outParam(StringInfo str, Param *node)
809
{
M
 
Marc G. Fournier 已提交
810 811 812 813
	appendStringInfo(str, 
			" PARAM :paramkind %d :paramid %d :paramname %s :paramtype %u ",
			node->paramkind,
			node->paramid,
814
			stringStringInfo(node->paramname),
M
 
Marc G. Fournier 已提交
815
			node->paramtype);
816 817 818

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

/*
822
 *	Stuff from execnodes.h
823 824 825
 */

/*
826
 *	EState is a subclass of Node.
827 828
 */
static void
829
_outEState(StringInfo str, EState *node)
830
{
M
 
Marc G. Fournier 已提交
831 832 833
	appendStringInfo(str, 
			" ESTATE :direction %d :range_table ",
			node->es_direction);
834 835
	_outNode(str, node->es_range_table);

M
 
Marc G. Fournier 已提交
836
	appendStringInfo(str, " :result_relation_info @ 0x%x ",
837
			(int) (node->es_result_relation_info));
838 839 840
}

/*
841
 *	Stuff from relation.h
842 843
 */
static void
844
_outRelOptInfo(StringInfo str, RelOptInfo * node)
845
{
M
 
Marc G. Fournier 已提交
846
	appendStringInfo(str, " RELOPTINFO :relids ");
847 848
	_outIntList(str, node->relids);

M
 
Marc G. Fournier 已提交
849 850 851 852 853 854 855
	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);
856 857
	_outNode(str, node->targetlist);

858
	appendStringInfo(str, " :pathlist ");
859 860 861 862 863 864 865 866
	_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.
	 */

M
 
Marc G. Fournier 已提交
867 868 869 870 871
	appendStringInfo(str, 
			" :unorderedpath @ 0x%x :cheapestpath @ 0x%x :pruneable %s :clauseinfo ",
			(int) node->unorderedpath,
			(int) node->cheapestpath,
			node->pruneable ? "true" : "false");
872 873
	_outNode(str, node->clauseinfo);

874
	appendStringInfo(str, " :joininfo ");
875 876
	_outNode(str, node->joininfo);

877
	appendStringInfo(str, " :innerjoin ");
878
	_outNode(str, node->innerjoin);
879 880 881
}

/*
882
 *	TargetEntry is a subclass of Node.
883 884
 */
static void
885
_outTargetEntry(StringInfo str, TargetEntry *node)
886
{
M
 
Marc G. Fournier 已提交
887
	appendStringInfo(str, " TARGETENTRY :resdom ");
888 889
	_outNode(str, node->resdom);

890 891
	appendStringInfo(str, " :expr ");
	_outNode(str, node->expr);
892
}
893 894

static void
895
_outRangeTblEntry(StringInfo str, RangeTblEntry *node)
896
{
M
 
Marc G. Fournier 已提交
897 898
	appendStringInfo(str, 
			" RTE :relname %s :refname %s :relid %u :inh %s :inFromCl %s :skipAcl %s",
899 900
			stringStringInfo(node->relname),
			stringStringInfo(node->refname),
M
 
Marc G. Fournier 已提交
901 902 903 904
			node->relid,
			node->inh ? "true" : "false",
			node->inFromCl ? "true" : "false",
			node->skipAcl ? "true" : "false");
905
}
906 907

/*
908
 *	Path is a subclass of Node.
909 910
 */
static void
911
_outPath(StringInfo str, Path *node)
912
{
M
 
Marc G. Fournier 已提交
913 914 915
	appendStringInfo(str, " PATH :pathtype %d :cost %f :keys ",
			node->pathtype,
			node->path_cost);
916
	_outNode(str, node->keys);
917 918 919
}

/*
920
 *	IndexPath is a subclass of Path.
921 922
 */
static void
923
_outIndexPath(StringInfo str, IndexPath *node)
924
{
M
 
Marc G. Fournier 已提交
925 926 927 928
	appendStringInfo(str, 
			" INDEXPATH :pathtype %d :cost %f :keys ",
			node->path.pathtype,
			node->path.path_cost);
929 930
	_outNode(str, node->path.keys);

931
	appendStringInfo(str, " :indexid ");
932 933
	_outIntList(str, node->indexid);

934
	appendStringInfo(str, " :indexqual ");
935
	_outNode(str, node->indexqual);
936 937 938
}

/*
939
 *	JoinPath is a subclass of Path
940 941
 */
static void
942
_outJoinPath(StringInfo str, JoinPath *node)
943
{
M
 
Marc G. Fournier 已提交
944 945 946 947
	appendStringInfo(str, 
			" JOINPATH :pathtype %d :cost %f :keys ",
			node->path.pathtype,
			node->path.path_cost);
948 949
	_outNode(str, node->path.keys);

950
	appendStringInfo(str, " :pathclauseinfo ");
951 952 953 954 955 956 957
	_outNode(str, node->pathclauseinfo);

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

M
 
Marc G. Fournier 已提交
958 959 960 961 962
	appendStringInfo(str, 
			" :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x :outjoincost %f :joinid ",
			(int) node->outerjoinpath,
			(int) node->innerjoinpath,
			node->path.outerjoincost);
963
	_outIntList(str, node->path.joinid);
964 965 966
}

/*
967
 *	MergePath is a subclass of JoinPath.
968 969
 */
static void
970
_outMergePath(StringInfo str, MergePath *node)
971
{
M
 
Marc G. Fournier 已提交
972 973 974 975
	appendStringInfo(str, 
			" MERGEPATH :pathtype %d :cost %f :keys ",
			node->jpath.path.pathtype,
			node->jpath.path.path_cost);
976 977
	_outNode(str, node->jpath.path.keys);

978
	appendStringInfo(str, " :pathclauseinfo ");
979 980 981 982 983 984 985
	_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.
	 */

M
 
Marc G. Fournier 已提交
986 987 988 989 990
	appendStringInfo(str, 
			" :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x :outerjoincost %f :joinid ",
			(int) node->jpath.outerjoinpath,
			(int) node->jpath.innerjoinpath,
			(int) node->jpath.path.outerjoincost);
991 992
	_outIntList(str, node->jpath.path.joinid);

993
	appendStringInfo(str, " :path_mergeclauses ");
994 995
	_outNode(str, node->path_mergeclauses);

996
	appendStringInfo(str, " :outersortkeys ");
997 998
	_outNode(str, node->outersortkeys);

999
	appendStringInfo(str, " :innersortkeys ");
1000
	_outNode(str, node->innersortkeys);
1001 1002 1003
}

/*
1004
 *	HashPath is a subclass of JoinPath.
1005 1006
 */
static void
1007
_outHashPath(StringInfo str, HashPath *node)
1008
{
M
 
Marc G. Fournier 已提交
1009 1010 1011 1012
	appendStringInfo(str, 
			" HASHPATH :pathtype %d :cost %f :keys ",
			node->jpath.path.pathtype,
			node->jpath.path.path_cost);
1013 1014
	_outNode(str, node->jpath.path.keys);

1015
	appendStringInfo(str, " :pathclauseinfo ");
1016 1017 1018 1019 1020 1021 1022
	_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.
	 */

M
 
Marc G. Fournier 已提交
1023 1024 1025 1026 1027
	appendStringInfo(str, 
			" :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x :outerjoincost %f :joinid ",
			(int) node->jpath.outerjoinpath,
			(int) node->jpath.innerjoinpath,
			node->jpath.path.outerjoincost);
1028 1029
	_outIntList(str, node->jpath.path.joinid);

1030
	appendStringInfo(str, " :path_hashclauses ");
1031 1032
	_outNode(str, node->path_hashclauses);

1033
	appendStringInfo(str, " :outerhashkeys ");
1034 1035
	_outNode(str, node->outerhashkeys);

1036
	appendStringInfo(str, " :innerhashkeys ");
1037
	_outNode(str, node->innerhashkeys);
1038 1039 1040
}

/*
1041
 *	OrderKey is a subclass of Node.
1042 1043
 */
static void
1044
_outOrderKey(StringInfo str, OrderKey *node)
1045
{
M
 
Marc G. Fournier 已提交
1046 1047 1048 1049
	appendStringInfo(str, 
			" ORDERKEY :attribute_number %d :array_index %d ",
			node->attribute_number,
			node->array_index);
1050 1051 1052
}

/*
1053
 *	JoinKey is a subclass of Node.
1054 1055
 */
static void
1056
_outJoinKey(StringInfo str, JoinKey *node)
1057
{
1058
	appendStringInfo(str, " JOINKEY ");
1059

1060
	appendStringInfo(str, " :outer ");
1061 1062
	_outNode(str, node->outer);

1063
	appendStringInfo(str, " :inner ");
1064 1065
	_outNode(str, node->inner);

1066 1067 1068
}

/*
1069
 *	MergeOrder is a subclass of Node.
1070 1071
 */
static void
1072
_outMergeOrder(StringInfo str, MergeOrder *node)
1073
{
1074
	char		buf[500];
1075

1076
	appendStringInfo(str, " MERGEORDER ");
1077

B
Bruce Momjian 已提交
1078
	sprintf(buf, " :join_operator %d ", node->join_operator);
1079
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1080
	sprintf(buf, " :left_operator %d ", node->left_operator);
1081
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1082
	sprintf(buf, " :right_operator %d ", node->right_operator);
1083
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1084
	sprintf(buf, " :left_type %d ", node->left_type);
1085
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1086
	sprintf(buf, " :right_type %d ", node->right_type);
1087 1088
	appendStringInfo(str, buf);

1089 1090 1091
}

/*
1092
 *	ClauseInfo is a subclass of Node.
1093 1094
 */
static void
1095
_outClauseInfo(StringInfo str, ClauseInfo * node)
1096
{
1097
	char		buf[500];
1098

1099
	appendStringInfo(str, " CINFO ");
1100

1101
	appendStringInfo(str, " :clause ");
1102 1103
	_outNode(str, node->clause);

B
Bruce Momjian 已提交
1104
	sprintf(buf, " :selectivity %f ", node->selectivity);
1105
	appendStringInfo(str, buf);
1106 1107
	appendStringInfo(str, " :notclause ");
	appendStringInfo(str, node->notclause ? "true" : "false");
1108

1109
	appendStringInfo(str, " :indexids ");
1110 1111
	_outNode(str, node->indexids);

1112 1113
	appendStringInfo(str, " :mergejoinorder ");
	_outNode(str, node->mergejoinorder);
1114

B
Bruce Momjian 已提交
1115
	sprintf(buf, " :hashjoinoperator %u ", node->hashjoinoperator);
1116 1117
	appendStringInfo(str, buf);

1118 1119 1120
}

/*
1121
 *	JoinMethod is a subclass of Node.
1122 1123
 */
static void
1124
_outJoinMethod(StringInfo str, JoinMethod *node)
1125
{
1126
	appendStringInfo(str, " JOINMETHOD ");
1127

1128
	appendStringInfo(str, " :jmkeys ");
1129 1130
	_outNode(str, node->jmkeys);

1131
	appendStringInfo(str, " :clauses ");
1132 1133 1134
	_outNode(str, node->clauses);


1135 1136 1137 1138 1139 1140
}

/*
 * HInfo is a subclass of JoinMethod.
 */
static void
1141
_outHInfo(StringInfo str, HInfo *node)
1142
{
1143
	char		buf[500];
1144

1145
	appendStringInfo(str, " HASHINFO ");
1146

1147
	appendStringInfo(str, " :hashop ");
B
Bruce Momjian 已提交
1148
	sprintf(buf, " %u ", node->hashop);
1149 1150
	appendStringInfo(str, buf);

1151
	appendStringInfo(str, " :jmkeys ");
1152 1153
	_outNode(str, node->jmethod.jmkeys);

1154
	appendStringInfo(str, " :clauses ");
1155 1156
	_outNode(str, node->jmethod.clauses);

1157 1158 1159
}

/*
1160
 *	JoinInfo is a subclass of Node.
1161 1162
 */
static void
1163
_outJoinInfo(StringInfo str, JoinInfo * node)
1164
{
1165
	appendStringInfo(str, " JINFO ");
1166

1167
	appendStringInfo(str, " :otherrels ");
1168 1169
	_outIntList(str, node->otherrels);

1170
	appendStringInfo(str, " :jinfoclauseinfo ");
1171 1172
	_outNode(str, node->jinfoclauseinfo);

1173 1174
	appendStringInfo(str, " :mergejoinable ");
	appendStringInfo(str, node->mergejoinable ? "true" : "false");
1175 1176
	appendStringInfo(str, " :hashjoinable ");
	appendStringInfo(str, node->hashjoinable ? "true" : "false");
1177

1178 1179 1180 1181 1182 1183 1184 1185
}

/*
 * Print the value of a Datum given its type.
 */
static void
_outDatum(StringInfo str, Datum value, Oid type)
{
1186 1187 1188 1189 1190 1191
	char		buf[500];
	Size		length,
				typeLength;
	bool		byValue;
	int			i;
	char	   *s;
1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207

	/*
	 * 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 已提交
1208
			sprintf(buf, " %d ", (int) (s[i]));
1209 1210 1211 1212
			appendStringInfo(str, buf);
		}
		sprintf(buf, "] ");
		appendStringInfo(str, buf);
1213
	}
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234
	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 已提交
1235
				sprintf(buf, " %d ", (int) (s[i]));
1236 1237 1238 1239 1240
				appendStringInfo(str, buf);
			}
			sprintf(buf, "] ");
			appendStringInfo(str, buf);
		}
1241 1242 1243 1244
	}
}

static void
1245
_outIter(StringInfo str, Iter *node)
1246
{
1247
	appendStringInfo(str, " ITER ");
1248 1249 1250

	appendStringInfo(str, " :iterexpr ");
	_outNode(str, node->iterexpr);
1251 1252 1253
}

static void
1254
_outStream(StringInfo str, Stream *node)
1255
{
1256
	char		buf[500];
1257

1258
	appendStringInfo(str, " STREAM ");
1259

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

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

B
Bruce Momjian 已提交
1266
	sprintf(buf, " :clausetype %d ", (int) (node->clausetype));
1267 1268
	appendStringInfo(str, buf);

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

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

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

B
Bruce Momjian 已提交
1278
	sprintf(buf, " :groupcost %f ", node->groupcost);
1279 1280
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
1281
	sprintf(buf, " :groupsel %f ", node->groupsel);
1282 1283
	appendStringInfo(str, buf);
}
1284

1285 1286 1287
static void
_outAExpr(StringInfo str, A_Expr *node)
{
1288
	appendStringInfo(str, "EXPR ");
1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308
#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
1309
			appendStringInfo(str, stringStringInfo(node->opname));
1310 1311 1312 1313
#ifdef PARSEDEBUG
			break;
	}
#endif
1314 1315 1316 1317 1318
	_outNode(str, node->lexpr);
	_outNode(str, node->rexpr);
	return;
}

1319
static void
1320
_outValue(StringInfo str, Value *value)
1321
{
1322 1323
	switch (value->type)
	{
1324
		case T_String:
1325 1326
			appendStringInfo(str, " \"%s\" ", 
					stringStringInfo(value->val.str));
1327 1328
			break;
		case T_Integer:
1329
			appendStringInfo(str, " %ld ", value->val.ival);
1330 1331
			break;
		case T_Float:
1332
			appendStringInfo(str, " %f ", value->val.dval);
1333 1334 1335
			break;
		default:
			break;
1336 1337
	}
	return;
1338 1339
}

1340 1341 1342
static void
_outIdent(StringInfo str, Ident *node)
{
1343
	appendStringInfo(str, " IDENT \"%s\" ", stringStringInfo(node->name));
1344 1345 1346 1347 1348 1349
	return;
}

static void
_outAConst(StringInfo str, A_Const *node)
{
1350
	appendStringInfo(str, "CONST ");
1351 1352 1353 1354
	_outValue(str, &(node->val));
	return;
}

T
Thomas G. Lockhart 已提交
1355 1356 1357
static void
_outConstraint(StringInfo str, Constraint *node)
{
1358 1359
	appendStringInfo(str," %s :type",
		stringStringInfo(node->name));
T
Thomas G. Lockhart 已提交
1360 1361 1362 1363

	switch (node->contype)
	{
		case CONSTR_PRIMARY:
1364
			appendStringInfo(str, " PRIMARY KEY ");
T
Thomas G. Lockhart 已提交
1365 1366 1367 1368
			_outNode(str, node->keys);
			break;

		case CONSTR_CHECK:
1369 1370
			appendStringInfo(str, " CHECK %s",
					stringStringInfo(node->def));
T
Thomas G. Lockhart 已提交
1371 1372 1373
			break;

		case CONSTR_DEFAULT:
1374 1375
			appendStringInfo(str, " DEFAULT %s",
					stringStringInfo(node->def));
T
Thomas G. Lockhart 已提交
1376 1377 1378
			break;

		case CONSTR_NOTNULL:
1379
			appendStringInfo(str, " NOT NULL ");
T
Thomas G. Lockhart 已提交
1380 1381 1382
			break;

		case CONSTR_UNIQUE:
1383
			appendStringInfo(str, " UNIQUE ");
T
Thomas G. Lockhart 已提交
1384 1385 1386 1387
			_outNode(str, node->keys);
			break;

		default:
1388
			appendStringInfo(str, "<unrecognized constraint>");
T
Thomas G. Lockhart 已提交
1389 1390 1391 1392 1393 1394 1395 1396
			break;
	}
	return;
}

static void
_outCaseExpr(StringInfo str, CaseExpr *node)
{
1397
	appendStringInfo(str, "CASE ");
T
Thomas G. Lockhart 已提交
1398
	_outNode(str, node->args);
1399
	appendStringInfo(str, " :default ");
T
Thomas G. Lockhart 已提交
1400 1401 1402 1403 1404 1405 1406
	_outNode(str, node->defresult);
	return;
}

static void
_outCaseWhen(StringInfo str, CaseWhen *node)
{
1407
	appendStringInfo(str, " WHEN ");
T
Thomas G. Lockhart 已提交
1408
	_outNode(str, node->expr);
1409
	appendStringInfo(str, " :then ");
T
Thomas G. Lockhart 已提交
1410 1411 1412 1413
	_outNode(str, node->result);
	return;
}

1414 1415
/*
 * _outNode -
1416
 *	  converts a Node into ascii string and append it to 'str'
1417 1418 1419 1420
 */
static void
_outNode(StringInfo str, void *obj)
{
1421 1422
	if (obj == NULL)
	{
B
Bruce Momjian 已提交
1423
		appendStringInfo(str, "<>");
1424 1425
		return;
	}
1426

1427 1428
	if (nodeTag(obj) == T_List)
	{
1429
		List	   *l;
1430 1431 1432 1433 1434 1435 1436 1437 1438

		appendStringInfo(str, "(");
		foreach(l, (List *) obj)
		{
			_outNode(str, lfirst(l));
			if (lnext(l))
				appendStringInfo(str, " ");
		}
		appendStringInfo(str, ")");
1439
	}
1440 1441 1442 1443 1444
	else
	{
		appendStringInfo(str, "{");
		switch (nodeTag(obj))
		{
1445 1446 1447 1448 1449 1450 1451 1452 1453 1454
			case T_CreateStmt:
				_outCreateStmt(str, obj);
				break;
			case T_IndexStmt:
				_outIndexStmt(str, obj);
				break;

			case T_ColumnDef:
				_outColumnDef(str, obj);
				break;
1455 1456 1457
			case T_TypeName:
				_outTypeName(str, obj);
				break;
1458 1459 1460 1461
			case T_IndexElem:
				_outIndexElem(str, obj);
				break;

1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472
#ifdef PARSEDEBUG
			case T_VariableSetStmt:
				break;
			case T_SelectStmt:
				_outSelectStmt(str, obj);
				break;
			case T_FuncCall:
				_outFuncCall(str, obj);
				break;
#endif

1473 1474 1475
			case T_Query:
				_outQuery(str, obj);
				break;
1476 1477 1478 1479 1480
			case T_SortClause:
				_outSortClause(str, obj);
				break;
			case T_GroupClause:
				_outGroupClause(str, obj);
1481
				break;
1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529
			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 已提交
1530 1531 1532
			case T_SubPlan:
				_outSubPlan(str, obj);
				break;
1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553
			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;
1554 1555 1556
			case T_SubLink:
				_outSubLink(str, obj);
				break;
1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574
			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 已提交
1575
			case T_RelOptInfo:
B
Bruce Momjian 已提交
1576
				_outRelOptInfo(str, obj);
1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607
				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;
1608 1609
			case T_ClauseInfo:
				_outClauseInfo(str, obj);
1610 1611 1612 1613 1614 1615 1616
				break;
			case T_JoinMethod:
				_outJoinMethod(str, obj);
				break;
			case T_HInfo:
				_outHInfo(str, obj);
				break;
1617 1618
			case T_JoinInfo:
				_outJoinInfo(str, obj);
1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630
				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;
1631 1632 1633 1634 1635 1636 1637 1638 1639
			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 已提交
1640 1641 1642 1643 1644 1645 1646 1647 1648
			case T_Constraint:
				_outConstraint(str, obj);
				break;
			case T_CaseExpr:
				_outCaseExpr(str, obj);
				break;
			case T_CaseWhen:
				_outCaseWhen(str, obj);
				break;
1649
			default:
B
Bruce Momjian 已提交
1650
				elog(NOTICE, "_outNode: don't know how to print type %d ",
1651 1652
					 nodeTag(obj));
				break;
1653 1654
		}
		appendStringInfo(str, "}");
1655
	}
1656
	return;
1657 1658 1659 1660
}

/*
 * nodeToString -
1661
 *	   returns the ascii representation of the Node
1662
 */
1663
char *
1664 1665
nodeToString(void *obj)
{
1666 1667
	StringInfo	str;
	char	   *s;
1668 1669 1670 1671 1672 1673 1674 1675 1676 1677

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

	return s;
1678
}