outfuncs.c 34.3 KB
Newer Older
M
 
Marc G. Fournier 已提交
1
/*
2 3
 *
 * outfuncs.c--
4
 *	  routines to convert a node to ascii representation
5 6 7
 *
 * Copyright (c) 1994, Regents of the University of California
 *
B
Bruce Momjian 已提交
8
 *  $Id: outfuncs.c,v 1.61 1999/01/24 00:28:20 momjian Exp $
9 10
 *
 * NOTES
11 12 13 14 15
 *	  Every (plan) node in POSTGRES has an associated "out" routine which
 *	  knows how to create its ascii representation. These functions are
 *	  useful for debugging as well as for storing plans in the system
 *	  catalogs (eg. indexes). This is also the plan string sent out in
 *	  Mariposa.
16
 *
17 18 19
 *	  These functions update the in/out argument of type StringInfo
 *	  passed to them. This argument contains the string holding the ASCII
 *	  representation plus some other information (string length, etc.)
20 21 22 23 24 25 26 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
	_outNode(str, node->tableElts);
M
 
Marc G. Fournier 已提交
75

76
	appendStringInfo(str, " :inhRelnames ");
77
	_outNode(str, node->inhRelnames);
M
 
Marc G. Fournier 已提交
78

79
	appendStringInfo(str, " :constraints ");
80
	_outNode(str, node->constraints);
81
}
82 83 84 85

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

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

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

99 100
	appendStringInfo(str, " :rangetable ");
	_outNode(str, node->rangetable);
M
 
Marc G. Fournier 已提交
101 102 103 104

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

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

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

122 123
#endif

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

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

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

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

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

M
 
Marc G. Fournier 已提交
158
	appendStringInfo(str, " :class %s :typename ", stringStringInfo(node->class));
159
	_outNode(str, node->typename);
160
}
161

162
static void
163
_outQuery(StringInfo str, Query *node)
164
{
165

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

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

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

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

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

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

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

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

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

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

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

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

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

B
Hi!  
Bruce Momjian 已提交
231 232 233
	appendStringInfo(str, " :intersectClause ");
	_outNode(str, node->intersectClause);

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

B
Bruce Momjian 已提交
237 238
	appendStringInfo(str, " :limitCount ");
	_outNode(str, node->limitCount);
239 240 241 242

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

243 244 245
}

static void
246
_outSortClause(StringInfo str, SortClause *node)
247
{
M
 
Marc G. Fournier 已提交
248
	appendStringInfo(str, " SORTCLAUSE :resdom ");
249
	_outNode(str, node->resdom);
M
 
Marc G. Fournier 已提交
250 251

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

static void
_outGroupClause(StringInfo str, GroupClause *node)
{
M
 
Marc G. Fournier 已提交
257
	appendStringInfo(str, " GROUPCLAUSE :entry ");
258
	_outNode(str, node->entry);
M
 
Marc G. Fournier 已提交
259 260

	appendStringInfo(str, " :grpOpoid %u ", node->grpOpoid);
261 262 263 264 265 266
}

/*
 * print the basic stuff of all nodes that inherit from Plan
 */
static void
267
_outPlanInfo(StringInfo str, Plan *node)
268
{
M
 
Marc G. Fournier 已提交
269 270 271 272 273 274
  appendStringInfo(str, 
		":cost %g :size %d :width %d :state %s :qptargetlist ",
		node->cost,
		node->plan_size,
		node->plan_width,
		node->state ? "not-NULL" : "<>");
275
	_outNode(str, node->targetlist);
M
 
Marc G. Fournier 已提交
276

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

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

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

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

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

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

M
 
Marc G. Fournier 已提交
295
	appendStringInfo(str, " :nprm %d ", node->nParamExec);
296 297 298
}

/*
299
 *	Stuff from plannodes.h
300 301
 */
static void
302
_outPlan(StringInfo str, Plan *node)
303
{
304
	appendStringInfo(str, " PLAN ");
305
	_outPlanInfo(str, (Plan *) node);
306 307 308
}

static void
309
_outResult(StringInfo str, Result *node)
310
{
311
	appendStringInfo(str, " RESULT ");
312 313
	_outPlanInfo(str, (Plan *) node);

314
	appendStringInfo(str, " :resconstantqual ");
315 316
	_outNode(str, node->resconstantqual);

317 318 319
}

/*
320
 *	Append is a subclass of Plan.
321 322
 */
static void
B
Bruce Momjian 已提交
323
_outAppend(StringInfo str, Append *node)
324
{
325
	appendStringInfo(str, " APPEND ");
326 327
	_outPlanInfo(str, (Plan *) node);

328 329
	appendStringInfo(str, " :appendplans ");
	_outNode(str, node->appendplans);
330

331 332
	appendStringInfo(str, " :unionrtables ");
	_outNode(str, node->unionrtables);
333

M
 
Marc G. Fournier 已提交
334 335 336
	appendStringInfo(str, 
		" :inheritrelid %d :inheritrtable ", 
		node->inheritrelid);
337
	_outNode(str, node->inheritrtable);
338

339 340 341
}

/*
342
 *	Join is a subclass of Plan
343 344
 */
static void
345
_outJoin(StringInfo str, Join *node)
346
{
347
	appendStringInfo(str, " JOIN ");
348 349
	_outPlanInfo(str, (Plan *) node);

350 351 352
}

/*
353
 *	NestLoop is a subclass of Join
354 355
 */
static void
356
_outNestLoop(StringInfo str, NestLoop *node)
357
{
358
	appendStringInfo(str, " NESTLOOP ");
359
	_outPlanInfo(str, (Plan *) node);
360 361 362
}

/*
363
 *	MergeJoin is a subclass of Join
364 365
 */
static void
366
_outMergeJoin(StringInfo str, MergeJoin *node)
367
{
368
	appendStringInfo(str, " MERGEJOIN ");
369 370
	_outPlanInfo(str, (Plan *) node);

371
	appendStringInfo(str, " :mergeclauses ");
372 373
	_outNode(str, node->mergeclauses);

M
 
Marc G. Fournier 已提交
374 375 376 377 378
	appendStringInfo(str, 
			" :mergejoinop %u :mergerightorder %u :mergeleftorder %u ",
			node->mergejoinop, 
			node->mergerightorder,
			node->mergeleftorder);
379 380 381
}

/*
382
 *	HashJoin is a subclass of Join.
383 384
 */
static void
385
_outHashJoin(StringInfo str, HashJoin *node)
386
{
387
	appendStringInfo(str, " HASHJOIN ");
388 389
	_outPlanInfo(str, (Plan *) node);

390
	appendStringInfo(str, " :hashclauses ");
391 392
	_outNode(str, node->hashclauses);

M
 
Marc G. Fournier 已提交
393 394 395 396 397 398 399 400 401 402
	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);
403 404
}

V
Vadim B. Mikheev 已提交
405 406 407
static void
_outSubPlan(StringInfo str, SubPlan *node)
{
M
 
Marc G. Fournier 已提交
408
	appendStringInfo(str, " SUBPLAN :plan ");
V
Vadim B. Mikheev 已提交
409
	_outNode(str, node->plan);
M
 
Marc G. Fournier 已提交
410 411

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

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

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

V
Vadim B. Mikheev 已提交
420 421 422 423
	appendStringInfo(str, " :slink ");
	_outNode(str, node->sublink);
}

424
/*
425
 *	Scan is a subclass of Node
426 427
 */
static void
428
_outScan(StringInfo str, Scan *node)
429
{
430
	appendStringInfo(str, " SCAN ");
431 432
	_outPlanInfo(str, (Plan *) node);

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

/*
437
 *	SeqScan is a subclass of Scan
438 439
 */
static void
440
_outSeqScan(StringInfo str, SeqScan *node)
441
{
442
	appendStringInfo(str, " SEQSCAN ");
443 444
	_outPlanInfo(str, (Plan *) node);

M
 
Marc G. Fournier 已提交
445
	appendStringInfo(str, " :scanrelid %d ", node->scanrelid);
446 447 448
}

/*
449
 *	IndexScan is a subclass of Scan
450 451
 */
static void
452
_outIndexScan(StringInfo str, IndexScan *node)
453
{
454
	appendStringInfo(str, " INDEXSCAN ");
455 456
	_outPlanInfo(str, (Plan *) node);

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

460
	appendStringInfo(str, " :indxqual ");
461 462
	_outNode(str, node->indxqual);

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

466 467 468
}

/*
469
 *	Temp is a subclass of Plan
470 471
 */
static void
472
_outTemp(StringInfo str, Temp *node)
473
{
474
	appendStringInfo(str, " TEMP ");
475 476
	_outPlanInfo(str, (Plan *) node);

M
 
Marc G. Fournier 已提交
477 478 479
	appendStringInfo(str, " :tempid %u :keycount %d ", 
			node->tempid,
			node->keycount);
480 481 482
}

/*
483
 *	Sort is a subclass of Temp
484 485
 */
static void
486
_outSort(StringInfo str, Sort *node)
487
{
488
	appendStringInfo(str, " SORT ");
489 490
	_outPlanInfo(str, (Plan *) node);

M
 
Marc G. Fournier 已提交
491 492 493
	appendStringInfo(str, " :tempid %u :keycount %d ",
			node->tempid,
			node->keycount);
494 495 496
}

static void
B
Bruce Momjian 已提交
497
_outAgg(StringInfo str, Agg *node)
498
{
499

500
	appendStringInfo(str, " AGG ");
501 502
	_outPlanInfo(str, (Plan *) node);

503 504
	appendStringInfo(str, " :aggs ");
	_outNode(str, node->aggs);
505 506 507
}

static void
508
_outGroup(StringInfo str, Group *node)
509
{
510
	appendStringInfo(str, " GRP ");
511 512 513
	_outPlanInfo(str, (Plan *) node);

	/* the actual Group fields */
M
 
Marc G. Fournier 已提交
514
	appendStringInfo(str, " :numCols %d :tuplePerGroup %s ",
M
 
Marc G. Fournier 已提交
515 516
			node->numCols,
			node->tuplePerGroup ? "true" : "false");
517
}
518

519
/*
520
 *	For some reason, unique is a subclass of Temp.
521 522
 */
static void
523
_outUnique(StringInfo str, Unique *node)
524
{
525
	appendStringInfo(str, " UNIQUE ");
526 527
	_outPlanInfo(str, (Plan *) node);

M
 
Marc G. Fournier 已提交
528 529 530
	appendStringInfo(str, " :tempid %u :keycount %d ",
			node->tempid,
			node->keycount);
531 532 533 534
}


/*
535
 *	Hash is a subclass of Temp
536 537
 */
static void
538
_outHash(StringInfo str, Hash *node)
539
{
540
	appendStringInfo(str, " HASH ");
541 542
	_outPlanInfo(str, (Plan *) node);

543
	appendStringInfo(str, " :hashkey ");
544 545
	_outNode(str, node->hashkey);

M
 
Marc G. Fournier 已提交
546 547 548 549
	appendStringInfo(str, " :hashtable 0x%x :hashtablekey %d :hashtablesize %d ",
			(int) node->hashtable,
			node->hashtablekey,
			node->hashtablesize);
550 551 552
}

static void
553
_outTee(StringInfo str, Tee *node)
554
{
555
	appendStringInfo(str, " TEE ");
556 557
	_outPlanInfo(str, (Plan *) node);

M
 
Marc G. Fournier 已提交
558 559 560
	appendStringInfo(str, " :leftParent %X :rightParent %X ",
		(int) node->leftParent,
		(int) node->rightParent);
561

562
	appendStringInfo(str, " :rtentries ");
563
	_outNode(str, node->rtentries);
564 565 566 567
}

/*****************************************************************************
 *
568
 *	Stuff from primnodes.h.
569 570 571 572
 *
 *****************************************************************************/

/*
573
 *	Resdom is a subclass of Node
574 575
 */
static void
576
_outResdom(StringInfo str, Resdom *node)
577
{
M
 
Marc G. Fournier 已提交
578 579 580 581
	appendStringInfo(str, " RESDOM :resno %d :restype %u :restypmod %d ",
			node->resno,
			node->restype,
			node->restypmod);
582

M
 
Marc G. Fournier 已提交
583
	appendStringInfo(str, " :resname \"%s\" :reskey %d :reskeyop %u :resjunk %d",
584
			stringStringInfo(node->resname),
M
 
Marc G. Fournier 已提交
585 586 587
			node->reskey,
			node->reskeyop,
			node->resjunk);
588 589 590
}

static void
591
_outFjoin(StringInfo str, Fjoin *node)
592
{
593
	int			i;
594

M
 
Marc G. Fournier 已提交
595 596 597
	appendStringInfo(str, " FJOIN :initialized %s :nNodes %d ",
			node->fj_initialized ? "true" : "false",
			node->fj_nNodes);
598 599 600 601

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

M
 
Marc G. Fournier 已提交
602 603
	appendStringInfo(str, " :results @ 0x%x :alwaysdone", 
			(int) node->fj_results);
604 605

	for (i = 0; i < node->fj_nNodes; i++)
606
		appendStringInfo(str, (node->fj_alwaysDone[i]) ? "true" : "false");
607 608 609
}

/*
610
 *	Expr is a subclass of Node
611 612
 */
static void
613
_outExpr(StringInfo str, Expr *node)
614
{
615
	char	   *opstr = NULL;
616

M
 
Marc G. Fournier 已提交
617 618
	appendStringInfo(str, " EXPR :typeOid %u ",
			node->typeOid);
619 620 621

	switch (node->opType)
	{
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
		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 已提交
637 638 639
		case SUBPLAN_EXPR:
			opstr = "subp";
			break;
640
	}
641
	appendStringInfo(str, " :opType %s :oper ", stringStringInfo(opstr));
642
	_outNode(str, node->oper);
M
 
Marc G. Fournier 已提交
643

644
	appendStringInfo(str, " :args ");
645
	_outNode(str, node->args);
646 647 648
}

/*
649
 *	Var is a subclass of Expr
650 651
 */
static void
652
_outVar(StringInfo str, Var *node)
653
{
M
 
Marc G. Fournier 已提交
654
	appendStringInfo(str, 
M
 
Marc G. Fournier 已提交
655
			" VAR :varno %d :varattno %d :vartype %u :vartypmod %d ",
M
 
Marc G. Fournier 已提交
656 657 658 659 660 661 662 663 664
			node->varno,
			node->varattno,
			node->vartype,
			node->vartypmod);

	appendStringInfo(str, " :varlevelsup %u :varnoold %d :varoattno %d" ,
			node->varlevelsup,
			node->varnoold,
			node->varoattno);
665 666 667
}

/*
668
 *	Const is a subclass of Expr
669 670
 */
static void
671
_outConst(StringInfo str, Const *node)
672
{
M
 
Marc G. Fournier 已提交
673 674 675 676 677 678
	appendStringInfo(str, 
			" CONST :consttype %u :constlen %d :constisnull %s :constvalue ",
			node->consttype,
			node->constlen,
			node->constisnull ? "true" : "false");

679
	if (node->constisnull)
B
Bruce Momjian 已提交
680
		appendStringInfo(str, "<>");
681 682
	else
		_outDatum(str, node->constvalue, node->consttype);
M
 
Marc G. Fournier 已提交
683 684 685

	appendStringInfo(str, " :constbyval %s ", 
			node->constbyval ? "true" : "false");
686 687 688
}

/*
B
Bruce Momjian 已提交
689
 *	Aggref
690 691
 */
static void
B
Bruce Momjian 已提交
692
_outAggref(StringInfo str, Aggref *node)
693
{
M
 
Marc G. Fournier 已提交
694 695
	appendStringInfo(str, 
			" AGGREG :aggname %s :basetype %u :aggtype %u :target ",
696
			stringStringInfo(node->aggname),
M
 
Marc G. Fournier 已提交
697 698
			node->basetype,
			node->aggtype);
699
	_outNode(str, node->target);
M
 
Marc G. Fournier 已提交
700 701 702 703

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

706 707 708 709 710 711
/*
 *	SubLink
 */
static void
_outSubLink(StringInfo str, SubLink *node)
{
M
 
Marc G. Fournier 已提交
712 713 714 715
	appendStringInfo(str, 
			" SUBLINK :subLinkType %d :useor %s :lefthand ",
			node->subLinkType,
			node->useor ? "true" : "false");
716
	_outNode(str, node->lefthand);
M
 
Marc G. Fournier 已提交
717

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

721 722 723 724
	appendStringInfo(str, " :subselect ");
	_outNode(str, node->subselect);
}

725
/*
726
 *	Array is a subclass of Expr
727 728
 */
static void
B
Bruce Momjian 已提交
729
_outArray(StringInfo str, Array *node)
730
{
731
	int			i;
732

M
 
Marc G. Fournier 已提交
733 734 735 736 737 738
	appendStringInfo(str, 
			" ARRAY :arrayelemtype %u :arrayelemlength %d :arrayelembyval %c ",
			node->arrayelemtype, 
			node->arrayelemlength,
			node->arrayelembyval ? 't' : 'f');

M
 
Marc G. Fournier 已提交
739
	appendStringInfo(str, " :arrayndim %d :arraylow ", node->arrayndim);
740 741
	for (i = 0; i < node->arrayndim; i++)
	{
M
 
Marc G. Fournier 已提交
742
		appendStringInfo(str, " %d ", node->arraylow.indx[i]);
743
	}
744
	appendStringInfo(str, " :arrayhigh ");
745 746
	for (i = 0; i < node->arrayndim; i++)
	{
M
 
Marc G. Fournier 已提交
747
		appendStringInfo(str, " %d ", node->arrayhigh.indx[i]);
748
	}
M
 
Marc G. Fournier 已提交
749
	appendStringInfo(str, " :arraylen %d ", node->arraylen);
750 751 752
}

/*
753
 *	ArrayRef is a subclass of Expr
754 755
 */
static void
B
Bruce Momjian 已提交
756
_outArrayRef(StringInfo str, ArrayRef *node)
757
{
M
 
Marc G. Fournier 已提交
758 759 760 761 762 763 764 765
	appendStringInfo(str, 
			" ARRAYREF :refelemtype %u :refattrlength $d :refelemlength %d ",
			node->refelemtype,
			node->refattrlength,
			node->refelemlength);

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

768
	appendStringInfo(str, " :reflowerindex ");
769 770
	_outNode(str, node->reflowerindexpr);

771
	appendStringInfo(str, " :refexpr ");
772 773
	_outNode(str, node->refexpr);

774
	appendStringInfo(str, " :refassgnexpr ");
775
	_outNode(str, node->refassgnexpr);
776 777 778
}

/*
779
 *	Func is a subclass of Expr
780 781
 */
static void
782
_outFunc(StringInfo str, Func *node)
783
{
M
 
Marc G. Fournier 已提交
784 785 786 787 788 789 790 791 792
	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);
793 794 795 796
	_outNode(str, node->func_tlist);

	appendStringInfo(str, " :func_planlist ");
	_outNode(str, node->func_planlist);
797 798 799
}

/*
800
 *	Oper is a subclass of Expr
801 802
 */
static void
803
_outOper(StringInfo str, Oper *node)
804
{
M
 
Marc G. Fournier 已提交
805 806 807 808 809
	appendStringInfo(str, 
			" OPER :opno %u :opid %u :opresulttype %u ",
			node->opno,
			node->opid,
			node->opresulttype);
810 811 812
}

/*
813
 *	Param is a subclass of Expr
814 815
 */
static void
816
_outParam(StringInfo str, Param *node)
817
{
M
 
Marc G. Fournier 已提交
818 819 820 821
	appendStringInfo(str, 
			" PARAM :paramkind %d :paramid %d :paramname %s :paramtype %u ",
			node->paramkind,
			node->paramid,
822
			stringStringInfo(node->paramname),
M
 
Marc G. Fournier 已提交
823
			node->paramtype);
824 825 826

	appendStringInfo(str, " :param_tlist ");
	_outNode(str, node->param_tlist);
827 828 829
}

/*
830
 *	Stuff from execnodes.h
831 832 833
 */

/*
834
 *	EState is a subclass of Node.
835 836
 */
static void
837
_outEState(StringInfo str, EState *node)
838
{
M
 
Marc G. Fournier 已提交
839 840 841
	appendStringInfo(str, 
			" ESTATE :direction %d :range_table ",
			node->es_direction);
842 843
	_outNode(str, node->es_range_table);

M
 
Marc G. Fournier 已提交
844
	appendStringInfo(str, " :result_relation_info @ 0x%x ",
845
			(int) (node->es_result_relation_info));
846 847 848
}

/*
849
 *	Stuff from relation.h
850 851
 */
static void
852
_outRelOptInfo(StringInfo str, RelOptInfo * node)
853
{
M
 
Marc G. Fournier 已提交
854
	appendStringInfo(str, " RELOPTINFO :relids ");
855 856
	_outIntList(str, node->relids);

M
 
Marc G. Fournier 已提交
857 858 859 860 861 862 863
	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);
864 865
	_outNode(str, node->targetlist);

866
	appendStringInfo(str, " :pathlist ");
867 868 869 870 871 872 873 874
	_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 已提交
875 876 877 878 879
	appendStringInfo(str, 
			" :unorderedpath @ 0x%x :cheapestpath @ 0x%x :pruneable %s :clauseinfo ",
			(int) node->unorderedpath,
			(int) node->cheapestpath,
			node->pruneable ? "true" : "false");
880 881
	_outNode(str, node->clauseinfo);

882
	appendStringInfo(str, " :joininfo ");
883 884
	_outNode(str, node->joininfo);

885
	appendStringInfo(str, " :innerjoin ");
886
	_outNode(str, node->innerjoin);
887 888 889
}

/*
890
 *	TargetEntry is a subclass of Node.
891 892
 */
static void
893
_outTargetEntry(StringInfo str, TargetEntry *node)
894
{
M
 
Marc G. Fournier 已提交
895
	appendStringInfo(str, " TARGETENTRY :resdom ");
896 897
	_outNode(str, node->resdom);

898 899
	appendStringInfo(str, " :expr ");
	_outNode(str, node->expr);
900
}
901 902

static void
903
_outRangeTblEntry(StringInfo str, RangeTblEntry *node)
904
{
M
 
Marc G. Fournier 已提交
905 906
	appendStringInfo(str, 
			" RTE :relname %s :refname %s :relid %u :inh %s :inFromCl %s :skipAcl %s",
907 908
			stringStringInfo(node->relname),
			stringStringInfo(node->refname),
M
 
Marc G. Fournier 已提交
909 910 911 912
			node->relid,
			node->inh ? "true" : "false",
			node->inFromCl ? "true" : "false",
			node->skipAcl ? "true" : "false");
913
}
914

915 916 917 918 919 920
static void
_outRowMark(StringInfo str, RowMark *node)
{
	appendStringInfo(str, " ROWMARK :rti %u :info %u", node->rti, node->info);
}

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

/*
934
 *	IndexPath is a subclass of Path.
935 936
 */
static void
937
_outIndexPath(StringInfo str, IndexPath *node)
938
{
M
 
Marc G. Fournier 已提交
939 940 941 942
	appendStringInfo(str, 
			" INDEXPATH :pathtype %d :cost %f :keys ",
			node->path.pathtype,
			node->path.path_cost);
943 944
	_outNode(str, node->path.keys);

945
	appendStringInfo(str, " :indexid ");
946 947
	_outIntList(str, node->indexid);

948
	appendStringInfo(str, " :indexqual ");
949
	_outNode(str, node->indexqual);
950 951 952
}

/*
953
 *	JoinPath is a subclass of Path
954 955
 */
static void
956
_outJoinPath(StringInfo str, JoinPath *node)
957
{
M
 
Marc G. Fournier 已提交
958 959 960 961
	appendStringInfo(str, 
			" JOINPATH :pathtype %d :cost %f :keys ",
			node->path.pathtype,
			node->path.path_cost);
962 963
	_outNode(str, node->path.keys);

964
	appendStringInfo(str, " :pathclauseinfo ");
965 966 967 968 969 970 971
	_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 已提交
972 973 974 975 976
	appendStringInfo(str, 
			" :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x :outjoincost %f :joinid ",
			(int) node->outerjoinpath,
			(int) node->innerjoinpath,
			node->path.outerjoincost);
977
	_outIntList(str, node->path.joinid);
978 979 980
}

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

992
	appendStringInfo(str, " :pathclauseinfo ");
993 994 995 996 997 998 999
	_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 已提交
1000 1001 1002 1003 1004
	appendStringInfo(str, 
			" :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x :outerjoincost %f :joinid ",
			(int) node->jpath.outerjoinpath,
			(int) node->jpath.innerjoinpath,
			(int) node->jpath.path.outerjoincost);
1005 1006
	_outIntList(str, node->jpath.path.joinid);

1007
	appendStringInfo(str, " :path_mergeclauses ");
1008 1009
	_outNode(str, node->path_mergeclauses);

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

1013
	appendStringInfo(str, " :innersortkeys ");
1014
	_outNode(str, node->innersortkeys);
1015 1016 1017
}

/*
1018
 *	HashPath is a subclass of JoinPath.
1019 1020
 */
static void
1021
_outHashPath(StringInfo str, HashPath *node)
1022
{
M
 
Marc G. Fournier 已提交
1023 1024 1025 1026
	appendStringInfo(str, 
			" HASHPATH :pathtype %d :cost %f :keys ",
			node->jpath.path.pathtype,
			node->jpath.path.path_cost);
1027 1028
	_outNode(str, node->jpath.path.keys);

1029
	appendStringInfo(str, " :pathclauseinfo ");
1030 1031 1032 1033 1034 1035 1036
	_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 已提交
1037 1038 1039 1040 1041
	appendStringInfo(str, 
			" :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x :outerjoincost %f :joinid ",
			(int) node->jpath.outerjoinpath,
			(int) node->jpath.innerjoinpath,
			node->jpath.path.outerjoincost);
1042 1043
	_outIntList(str, node->jpath.path.joinid);

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

1047
	appendStringInfo(str, " :outerhashkeys ");
1048 1049
	_outNode(str, node->outerhashkeys);

1050
	appendStringInfo(str, " :innerhashkeys ");
1051
	_outNode(str, node->innerhashkeys);
1052 1053 1054
}

/*
1055
 *	OrderKey is a subclass of Node.
1056 1057
 */
static void
1058
_outOrderKey(StringInfo str, OrderKey *node)
1059
{
M
 
Marc G. Fournier 已提交
1060 1061 1062 1063
	appendStringInfo(str, 
			" ORDERKEY :attribute_number %d :array_index %d ",
			node->attribute_number,
			node->array_index);
1064 1065 1066
}

/*
1067
 *	JoinKey is a subclass of Node.
1068 1069
 */
static void
1070
_outJoinKey(StringInfo str, JoinKey *node)
1071
{
M
 
Marc G. Fournier 已提交
1072
	appendStringInfo(str, " JOINKEY :outer ");
1073 1074
	_outNode(str, node->outer);

1075
	appendStringInfo(str, " :inner ");
1076 1077
	_outNode(str, node->inner);

1078 1079 1080
}

/*
1081
 *	MergeOrder is a subclass of Node.
1082 1083
 */
static void
1084
_outMergeOrder(StringInfo str, MergeOrder *node)
1085
{
M
 
Marc G. Fournier 已提交
1086 1087 1088 1089 1090
	appendStringInfo(str, 
			" MERGEORDER :join_operator %d :left_operator %d :right_operator %d ",
			node->join_operator,
			node->left_operator,
			node->right_operator);
1091

M
 
Marc G. Fournier 已提交
1092 1093 1094 1095
	appendStringInfo(str, 
			" :left_type %d :right_type %d ",
			node->left_type, 
			node->right_type);
1096 1097 1098
}

/*
1099
 *	ClauseInfo is a subclass of Node.
1100 1101
 */
static void
1102
_outClauseInfo(StringInfo str, ClauseInfo * node)
1103
{
M
 
Marc G. Fournier 已提交
1104
	appendStringInfo(str, " CINFO :clause ");
1105 1106
	_outNode(str, node->clause);

M
 
Marc G. Fournier 已提交
1107 1108 1109 1110
	appendStringInfo(str, 
			" :selectivity %f :notclause %s :indexids ",
			node->selectivity,
			node->notclause ? "true" : "false");
1111 1112
	_outNode(str, node->indexids);

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

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

1118 1119 1120
}

/*
1121
 *	JoinMethod is a subclass of Node.
1122 1123
 */
static void
1124
_outJoinMethod(StringInfo str, JoinMethod *node)
1125
{
M
 
Marc G. Fournier 已提交
1126
	appendStringInfo(str, " JOINMETHOD :jmkeys ");
1127 1128
	_outNode(str, node->jmkeys);

1129
	appendStringInfo(str, " :clauses ");
1130
	_outNode(str, node->clauses);
1131 1132 1133 1134 1135 1136
}

/*
 * HInfo is a subclass of JoinMethod.
 */
static void
1137
_outHInfo(StringInfo str, HInfo *node)
1138
{
M
 
Marc G. Fournier 已提交
1139
	appendStringInfo(str, " HASHINFO :hashop %u :jmkeys ", node->hashop);
1140 1141
	_outNode(str, node->jmethod.jmkeys);

1142
	appendStringInfo(str, " :clauses ");
1143
	_outNode(str, node->jmethod.clauses);
1144 1145 1146
}

/*
1147
 *	JoinInfo is a subclass of Node.
1148 1149
 */
static void
1150
_outJoinInfo(StringInfo str, JoinInfo * node)
1151
{
M
 
Marc G. Fournier 已提交
1152
	appendStringInfo(str, " JINFO :otherrels ");
1153 1154
	_outIntList(str, node->otherrels);

1155
	appendStringInfo(str, " :jinfoclauseinfo ");
1156 1157
	_outNode(str, node->jinfoclauseinfo);

M
 
Marc G. Fournier 已提交
1158 1159 1160
	appendStringInfo(str, " :mergejoinable %s :hashjoinable %s ",
			node->mergejoinable ? "true" : "false",
			node->hashjoinable ? "true" : "false");
1161 1162 1163 1164 1165 1166 1167 1168
}

/*
 * Print the value of a Datum given its type.
 */
static void
_outDatum(StringInfo str, Datum value, Oid type)
{
M
 
Marc G. Fournier 已提交
1169
	char		*s;
1170
	Size		length,
M
 
Marc G. Fournier 已提交
1171
					typeLength;
1172 1173
	bool		byValue;
	int			i;
1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185

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

	if (byValue)
	{
		s = (char *) (&value);
M
 
Marc G. Fournier 已提交
1186
		appendStringInfo(str, " %d [ ", length);
1187 1188
		for (i = 0; i < sizeof(Datum); i++)
		{
M
 
Marc G. Fournier 已提交
1189
			appendStringInfo(str, " %d ", (int) (s[i]));
1190
		}
M
 
Marc G. Fournier 已提交
1191
		appendStringInfo(str, "] ");
1192
	}
1193 1194 1195 1196 1197
	else
	{							/* !byValue */
		s = (char *) DatumGetPointer(value);
		if (!PointerIsValid(s))
		{
M
 
Marc G. Fournier 已提交
1198
			appendStringInfo(str, " 0 [ ] ");
1199 1200 1201 1202 1203 1204 1205 1206 1207
		}
		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);
M
 
Marc G. Fournier 已提交
1208
			appendStringInfo(str, " %d [ ", length);
1209 1210
			for (i = 0; i < length; i++)
			{
M
 
Marc G. Fournier 已提交
1211
				appendStringInfo(str, " %d ", (int) (s[i]));
1212
			}
M
 
Marc G. Fournier 已提交
1213
			appendStringInfo(str, "] ");
1214
		}
1215 1216 1217 1218
	}
}

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

static void
1226
_outStream(StringInfo str, Stream *node)
1227
{
M
 
Marc G. Fournier 已提交
1228 1229 1230 1231 1232 1233
	appendStringInfo(str, 
			" STREAM :pathptr @ 0x%x :cinfo @ 0x%x :clausetype %d :upstream @ 0x%x ",
			(int) node->pathptr,
			(int) node->cinfo,
			(int) node->clausetype,
			(int) node->upstream);
1234

M
 
Marc G. Fournier 已提交
1235 1236 1237 1238 1239 1240
	appendStringInfo(str, 
			" :downstream @ 0x%x :groupup %d :groupcost %f :groupsel %f ",
			(int) node->downstream,
			node->groupup,
			node->groupcost,
			node->groupsel);
1241
}
1242

1243 1244 1245
static void
_outAExpr(StringInfo str, A_Expr *node)
{
1246
	appendStringInfo(str, "EXPR ");
1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266
#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
1267
			appendStringInfo(str, stringStringInfo(node->opname));
1268 1269 1270 1271
#ifdef PARSEDEBUG
			break;
	}
#endif
1272 1273 1274 1275 1276
	_outNode(str, node->lexpr);
	_outNode(str, node->rexpr);
	return;
}

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

1297 1298 1299
static void
_outIdent(StringInfo str, Ident *node)
{
1300
	appendStringInfo(str, " IDENT \"%s\" ", stringStringInfo(node->name));
1301 1302 1303 1304 1305 1306
	return;
}

static void
_outAConst(StringInfo str, A_Const *node)
{
1307
	appendStringInfo(str, "CONST ");
1308 1309 1310 1311
	_outValue(str, &(node->val));
	return;
}

T
Thomas G. Lockhart 已提交
1312 1313 1314
static void
_outConstraint(StringInfo str, Constraint *node)
{
M
 
Marc G. Fournier 已提交
1315
	appendStringInfo(str," %s :type", stringStringInfo(node->name));
T
Thomas G. Lockhart 已提交
1316 1317 1318 1319

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

		case CONSTR_CHECK:
M
 
Marc G. Fournier 已提交
1325
			appendStringInfo(str, " CHECK %s", stringStringInfo(node->def));
T
Thomas G. Lockhart 已提交
1326 1327 1328
			break;

		case CONSTR_DEFAULT:
M
 
Marc G. Fournier 已提交
1329
			appendStringInfo(str, " DEFAULT %s", stringStringInfo(node->def));
T
Thomas G. Lockhart 已提交
1330 1331 1332
			break;

		case CONSTR_NOTNULL:
1333
			appendStringInfo(str, " NOT NULL ");
T
Thomas G. Lockhart 已提交
1334 1335 1336
			break;

		case CONSTR_UNIQUE:
1337
			appendStringInfo(str, " UNIQUE ");
T
Thomas G. Lockhart 已提交
1338 1339 1340 1341
			_outNode(str, node->keys);
			break;

		default:
1342
			appendStringInfo(str, "<unrecognized constraint>");
T
Thomas G. Lockhart 已提交
1343 1344 1345 1346 1347 1348 1349 1350
			break;
	}
	return;
}

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

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

T
Thomas G. Lockhart 已提交
1357 1358 1359 1360 1361 1362
	return;
}

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

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

T
Thomas G. Lockhart 已提交
1369 1370 1371
	return;
}

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

1385 1386
	if (nodeTag(obj) == T_List)
	{
1387
		List	   *l;
1388 1389 1390 1391 1392 1393 1394 1395 1396

		appendStringInfo(str, "(");
		foreach(l, (List *) obj)
		{
			_outNode(str, lfirst(l));
			if (lnext(l))
				appendStringInfo(str, " ");
		}
		appendStringInfo(str, ")");
1397
	}
1398 1399 1400 1401 1402
	else
	{
		appendStringInfo(str, "{");
		switch (nodeTag(obj))
		{
1403 1404 1405 1406 1407 1408 1409 1410 1411 1412
			case T_CreateStmt:
				_outCreateStmt(str, obj);
				break;
			case T_IndexStmt:
				_outIndexStmt(str, obj);
				break;

			case T_ColumnDef:
				_outColumnDef(str, obj);
				break;
1413 1414 1415
			case T_TypeName:
				_outTypeName(str, obj);
				break;
1416 1417 1418 1419
			case T_IndexElem:
				_outIndexElem(str, obj);
				break;

1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430
#ifdef PARSEDEBUG
			case T_VariableSetStmt:
				break;
			case T_SelectStmt:
				_outSelectStmt(str, obj);
				break;
			case T_FuncCall:
				_outFuncCall(str, obj);
				break;
#endif

1431 1432 1433
			case T_Query:
				_outQuery(str, obj);
				break;
1434 1435 1436 1437 1438
			case T_SortClause:
				_outSortClause(str, obj);
				break;
			case T_GroupClause:
				_outGroupClause(str, obj);
1439
				break;
1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487
			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 已提交
1488 1489 1490
			case T_SubPlan:
				_outSubPlan(str, obj);
				break;
1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508
			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;
B
Bruce Momjian 已提交
1509 1510
			case T_Aggref:
				_outAggref(str, obj);
1511
				break;
1512 1513 1514
			case T_SubLink:
				_outSubLink(str, obj);
				break;
1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532
			case T_Array:
				_outArray(str, obj);
				break;
			case T_ArrayRef:
				_outArrayRef(str, obj);
				break;
			case T_Func:
				_outFunc(str, obj);
				break;
			case T_Oper:
				_outOper(str, obj);
				break;
			case T_Param:
				_outParam(str, obj);
				break;
			case T_EState:
				_outEState(str, obj);
				break;
B
Bruce Momjian 已提交
1533
			case T_RelOptInfo:
B
Bruce Momjian 已提交
1534
				_outRelOptInfo(str, obj);
1535 1536 1537 1538 1539 1540 1541
				break;
			case T_TargetEntry:
				_outTargetEntry(str, obj);
				break;
			case T_RangeTblEntry:
				_outRangeTblEntry(str, obj);
				break;
1542 1543 1544
			case T_RowMark:
				_outRowMark(str, obj);
				break;
1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568
			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;
1569 1570
			case T_ClauseInfo:
				_outClauseInfo(str, obj);
1571 1572 1573 1574 1575 1576 1577
				break;
			case T_JoinMethod:
				_outJoinMethod(str, obj);
				break;
			case T_HInfo:
				_outHInfo(str, obj);
				break;
1578 1579
			case T_JoinInfo:
				_outJoinInfo(str, obj);
1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591
				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;
1592 1593 1594 1595 1596 1597 1598 1599 1600
			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 已提交
1601 1602 1603 1604 1605 1606 1607 1608 1609
			case T_Constraint:
				_outConstraint(str, obj);
				break;
			case T_CaseExpr:
				_outCaseExpr(str, obj);
				break;
			case T_CaseWhen:
				_outCaseWhen(str, obj);
				break;
1610
			default:
B
Bruce Momjian 已提交
1611
				elog(NOTICE, "_outNode: don't know how to print type %d ",
1612 1613
					 nodeTag(obj));
				break;
1614 1615
		}
		appendStringInfo(str, "}");
1616
	}
1617
	return;
1618 1619 1620 1621
}

/*
 * nodeToString -
1622
 *	   returns the ascii representation of the Node
1623
 */
1624
char *
1625 1626
nodeToString(void *obj)
{
1627 1628
	StringInfo	str;
	char	   *s;
1629 1630 1631 1632 1633 1634 1635 1636 1637 1638

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

	return s;
1639
}