outfuncs.c 32.8 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.96 1999/10/03 23:55:29 tgl 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
#include "postgres.h"
24 25
#include "access/heapam.h"
#include "access/htup.h"
B
Bruce Momjian 已提交
26
#include "catalog/pg_type.h"
27
#include "fmgr.h"
B
Bruce Momjian 已提交
28
#include "lib/stringinfo.h"
29
#include "nodes/execnodes.h"
B
Bruce Momjian 已提交
30 31
#include "nodes/nodes.h"
#include "nodes/parsenodes.h"
32 33 34 35
#include "nodes/pg_list.h"
#include "nodes/plannodes.h"
#include "nodes/primnodes.h"
#include "nodes/relation.h"
B
Bruce Momjian 已提交
36 37 38
#include "utils/datum.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
39

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

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

45 46 47 48
/* Convert a null string pointer into "<>" */
#define stringStringInfo(s) (((s) == NULL) ? "<>" : (s))


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

58 59
	appendStringInfo(str, "(");
	foreach(l, list)
B
Bruce Momjian 已提交
60
		appendStringInfo(str, " %d ", lfirsti(l));
61
	appendStringInfo(str, ")");
62 63
}

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

	appendStringInfo(str, " :istemp %s ",
B
Bruce Momjian 已提交
71
					 node->istemp ? "true" : "false");
72 73

	appendStringInfo(str, "	:columns ");
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)
{
B
Bruce Momjian 已提交
86 87 88 89 90
	appendStringInfo(str,
		 " INDEX :idxname %s :relname %s :accessMethod %s :indexParams ",
					 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

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

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

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

121 122 123
static void
_outColumnDef(StringInfo str, ColumnDef *node)
{
124
	appendStringInfo(str, " COLUMNDEF :colname %s :typename ",
B
Bruce Momjian 已提交
125
					 stringStringInfo(node->colname));
126
	_outNode(str, node->typename);
127
	appendStringInfo(str, " :is_not_null %s :is_sequence %s :raw_default ",
B
Bruce Momjian 已提交
128
					 node->is_not_null ? "true" : "false",
129 130 131 132
					 node->is_sequence ? "true" : "false");
	_outNode(str, node->raw_default);
	appendStringInfo(str, " :cooked_default %s :constraints ",
					 stringStringInfo(node->cooked_default));
133
	_outNode(str, node->constraints);
134 135 136 137 138
}

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

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

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

M
 
Marc G. Fournier 已提交
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
{
164

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

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

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

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

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

B
Bruce Momjian 已提交
196 197 198 199 200 201 202 203 204 205 206
	appendStringInfo(str,
					 " :resultRelation %u :into %s :isPortal %s :isBinary %s :isTemp %s :unionall %s ",
					 node->resultRelation,
					 stringStringInfo(node->into),
					 node->isPortal ? "true" : "false",
					 node->isBinary ? "true" : "false",
					 node->isTemp ? "true" : "false",
					 node->unionall ? "true" : "false");

	appendStringInfo(str, " :unique %s :sortClause ",
					 stringStringInfo(node->uniqueFlag));
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

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

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

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

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

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

241 242 243
}

static void
244
_outSortClause(StringInfo str, SortClause *node)
245
{
246 247
	appendStringInfo(str, " SORTCLAUSE :tleSortGroupRef %d :sortop %u ",
					 node->tleSortGroupRef, node->sortop);
248 249 250 251 252
}

static void
_outGroupClause(StringInfo str, GroupClause *node)
{
253 254
	appendStringInfo(str, " GROUPCLAUSE :tleSortGroupRef %d :sortop %u ",
					 node->tleSortGroupRef, node->sortop);
255 256 257 258 259 260
}

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

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

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

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

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

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

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

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

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

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

308
	appendStringInfo(str, " :resconstantqual ");
309 310
	_outNode(str, node->resconstantqual);

311 312 313
}

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

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

325 326
	appendStringInfo(str, " :unionrtables ");
	_outNode(str, node->unionrtables);
327

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

333 334 335
}

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

344 345 346
}

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

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

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

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

378
	appendStringInfo(str, " :hashclauses ");
379 380
	_outNode(str, node->hashclauses);

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

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

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

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

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

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

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

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

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

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

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

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

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

445
	appendStringInfo(str, " :indxqual ");
446 447
	_outNode(str, node->indxqual);

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

451
	appendStringInfo(str, " :indxorderdir %d ", node->indxorderdir);
452 453 454
}

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

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

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

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

static void
B
Bruce Momjian 已提交
483
_outAgg(StringInfo str, Agg *node)
484
{
485

486
	appendStringInfo(str, " AGG ");
487
	_outPlanInfo(str, (Plan *) node);
488 489 490
}

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

	switch (node->opType)
	{
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603
		case OP_EXPR:
			opstr = "op";
			break;
		case FUNC_EXPR:
			opstr = "func";
			break;
		case OR_EXPR:
			opstr = "or";
			break;
		case AND_EXPR:
			opstr = "and";
			break;
		case NOT_EXPR:
			opstr = "not";
			break;
V
Vadim B. Mikheev 已提交
604 605 606
		case SUBPLAN_EXPR:
			opstr = "subp";
			break;
607
	}
608
	appendStringInfo(str, " :opType %s :oper ", stringStringInfo(opstr));
609
	_outNode(str, node->oper);
M
 
Marc G. Fournier 已提交
610

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

/*
741
 *	Func is a subclass of Expr
742 743
 */
static void
744
_outFunc(StringInfo str, Func *node)
745
{
B
Bruce Momjian 已提交
746 747 748 749 750 751
	appendStringInfo(str,
		   " FUNC :funcid %u :functype %u :funcisindex %s :funcsize %d ",
					 node->funcid,
					 node->functype,
					 node->funcisindex ? "true" : "false",
					 node->funcsize);
M
 
Marc G. Fournier 已提交
752 753

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

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

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

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

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

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

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

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

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

B
Bruce Momjian 已提交
819 820 821 822 823 824 825
	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);
826 827
	_outNode(str, node->targetlist);

828
	appendStringInfo(str, " :pathlist ");
829 830 831 832 833 834 835 836
	_outNode(str, node->pathlist);

	/*
	 * Not sure if these are nodes or not.	They're declared as struct
	 * Path *.	Since i don't know, i'll just print the addresses for now.
	 * This can be changed later, if necessary.
	 */

B
Bruce Momjian 已提交
837 838 839 840
	appendStringInfo(str,
					 " :cheapestpath @ 0x%x :pruneable %s :restrictinfo ",
					 (int) node->cheapestpath,
					 node->pruneable ? "true" : "false");
841
	_outNode(str, node->restrictinfo);
842

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

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

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

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

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

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

882
/*
883
 *	Path is a subclass of Node.
884 885
 */
static void
886
_outPath(StringInfo str, Path *node)
887
{
888
	appendStringInfo(str, " PATH :pathtype %d :cost %f :pathkeys ",
B
Bruce Momjian 已提交
889 890
					 node->pathtype,
					 node->path_cost);
891
	_outNode(str, node->pathkeys);
892 893 894
}

/*
895
 *	IndexPath is a subclass of Path.
896 897
 */
static void
898
_outIndexPath(StringInfo str, IndexPath *node)
899
{
B
Bruce Momjian 已提交
900 901 902 903
	appendStringInfo(str,
					 " INDEXPATH :pathtype %d :cost %f :pathkeys ",
					 node->path.pathtype,
					 node->path.path_cost);
904
	_outNode(str, node->path.pathkeys);
905

906
	appendStringInfo(str, " :indexid ");
907 908
	_outIntList(str, node->indexid);

909
	appendStringInfo(str, " :indexqual ");
910
	_outNode(str, node->indexqual);
911 912 913

	appendStringInfo(str, " :joinrelids ");
	_outIntList(str, node->joinrelids);
914 915 916
}

/*
917
 *	NestPath is a subclass of Path
918 919
 */
static void
920
_outNestPath(StringInfo str, NestPath *node)
921
{
B
Bruce Momjian 已提交
922 923 924 925
	appendStringInfo(str,
					 " NESTPATH :pathtype %d :cost %f :pathkeys ",
					 node->path.pathtype,
					 node->path.path_cost);
926
	_outNode(str, node->path.pathkeys);
927

928 929
	appendStringInfo(str, " :pathinfo ");
	_outNode(str, node->pathinfo);
930 931 932 933 934 935

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

B
Bruce Momjian 已提交
936
	appendStringInfo(str,
937
					 " :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x ",
B
Bruce Momjian 已提交
938
					 (int) node->outerjoinpath,
939
					 (int) node->innerjoinpath);
940 941 942
}

/*
943
 *	MergePath is a subclass of NestPath.
944 945
 */
static void
946
_outMergePath(StringInfo str, MergePath *node)
947
{
B
Bruce Momjian 已提交
948 949 950 951
	appendStringInfo(str,
					 " MERGEPATH :pathtype %d :cost %f :pathkeys ",
					 node->jpath.path.pathtype,
					 node->jpath.path.path_cost);
952
	_outNode(str, node->jpath.path.pathkeys);
953

954 955
	appendStringInfo(str, " :pathinfo ");
	_outNode(str, node->jpath.pathinfo);
956 957 958 959 960 961

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

B
Bruce Momjian 已提交
962
	appendStringInfo(str,
963
					 " :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x ",
B
Bruce Momjian 已提交
964
					 (int) node->jpath.outerjoinpath,
965
					 (int) node->jpath.innerjoinpath);
966

967
	appendStringInfo(str, " :path_mergeclauses ");
968 969
	_outNode(str, node->path_mergeclauses);

970
	appendStringInfo(str, " :outersortkeys ");
971 972
	_outNode(str, node->outersortkeys);

973
	appendStringInfo(str, " :innersortkeys ");
974
	_outNode(str, node->innersortkeys);
975 976 977
}

/*
978
 *	HashPath is a subclass of NestPath.
979 980
 */
static void
981
_outHashPath(StringInfo str, HashPath *node)
982
{
B
Bruce Momjian 已提交
983 984 985 986
	appendStringInfo(str,
					 " HASHPATH :pathtype %d :cost %f :pathkeys ",
					 node->jpath.path.pathtype,
					 node->jpath.path.path_cost);
987
	_outNode(str, node->jpath.path.pathkeys);
988

989 990
	appendStringInfo(str, " :pathinfo ");
	_outNode(str, node->jpath.pathinfo);
991 992 993 994 995 996

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

B
Bruce Momjian 已提交
997
	appendStringInfo(str,
998
					 " :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x ",
B
Bruce Momjian 已提交
999
					 (int) node->jpath.outerjoinpath,
1000
					 (int) node->jpath.innerjoinpath);
1001

1002
	appendStringInfo(str, " :path_hashclauses ");
1003
	_outNode(str, node->path_hashclauses);
1004 1005 1006
}

/*
1007
 *	PathKeyItem is a subclass of Node.
1008 1009
 */
static void
1010
_outPathKeyItem(StringInfo str, PathKeyItem *node)
1011
{
1012 1013 1014
	appendStringInfo(str, " PATHKEYITEM :sortop %u :key ",
					 node->sortop);
	_outNode(str, node->key);
1015 1016 1017
}

/*
1018
 *	RestrictInfo is a subclass of Node.
1019 1020
 */
static void
1021
_outRestrictInfo(StringInfo str, RestrictInfo *node)
1022
{
B
Bruce Momjian 已提交
1023
	appendStringInfo(str, " RESTRICTINFO :clause ");
1024 1025
	_outNode(str, node->clause);

B
Bruce Momjian 已提交
1026
	appendStringInfo(str,
1027
					 " :selectivity %f :subclauseindices ",
1028
					 node->selectivity);
1029
	_outNode(str, node->subclauseindices);
1030

1031 1032 1033
	appendStringInfo(str, " :mergejoinoperator %u ", node->mergejoinoperator);
	appendStringInfo(str, " :left_sortop %u ", node->left_sortop);
	appendStringInfo(str, " :right_sortop %u ", node->right_sortop);
M
 
Marc G. Fournier 已提交
1034
	appendStringInfo(str, " :hashjoinoperator %u ", node->hashjoinoperator);
1035 1036 1037
}

/*
1038
 *	JoinInfo is a subclass of Node.
1039 1040
 */
static void
1041
_outJoinInfo(StringInfo str, JoinInfo *node)
1042
{
B
Bruce Momjian 已提交
1043 1044
	appendStringInfo(str, " JINFO :unjoined_relids ");
	_outIntList(str, node->unjoined_relids);
1045

1046 1047
	appendStringInfo(str, " :jinfo_restrictinfo ");
	_outNode(str, node->jinfo_restrictinfo);
1048 1049 1050 1051 1052 1053 1054 1055
}

/*
 * Print the value of a Datum given its type.
 */
static void
_outDatum(StringInfo str, Datum value, Oid type)
{
B
Bruce Momjian 已提交
1056
	char	   *s;
1057
	Size		length,
B
Bruce Momjian 已提交
1058
				typeLength;
1059 1060
	bool		byValue;
	int			i;
1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072

	/*
	 * 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 已提交
1073
		appendStringInfo(str, " %d [ ", length);
1074
		for (i = 0; i < sizeof(Datum); i++)
M
 
Marc G. Fournier 已提交
1075 1076
			appendStringInfo(str, " %d ", (int) (s[i]));
		appendStringInfo(str, "] ");
1077
	}
1078 1079 1080 1081
	else
	{							/* !byValue */
		s = (char *) DatumGetPointer(value);
		if (!PointerIsValid(s))
M
 
Marc G. Fournier 已提交
1082
			appendStringInfo(str, " 0 [ ] ");
1083 1084
		else
		{
B
Bruce Momjian 已提交
1085

1086 1087 1088 1089 1090 1091
			/*
			 * 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 已提交
1092
			appendStringInfo(str, " %d [ ", length);
1093
			for (i = 0; i < length; i++)
M
 
Marc G. Fournier 已提交
1094 1095
				appendStringInfo(str, " %d ", (int) (s[i]));
			appendStringInfo(str, "] ");
1096
		}
1097 1098 1099 1100
	}
}

static void
1101
_outIter(StringInfo str, Iter *node)
1102
{
M
 
Marc G. Fournier 已提交
1103
	appendStringInfo(str, " ITER :iterexpr ");
1104
	_outNode(str, node->iterexpr);
1105 1106 1107
}

static void
1108
_outStream(StringInfo str, Stream *node)
1109
{
B
Bruce Momjian 已提交
1110 1111 1112 1113 1114 1115
	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);
1116

B
Bruce Momjian 已提交
1117 1118 1119 1120 1121 1122
	appendStringInfo(str,
		   " :downstream @ 0x%x :groupup %d :groupcost %f :groupsel %f ",
					 (int) node->downstream,
					 node->groupup,
					 node->groupcost,
					 node->groupsel);
1123
}
1124

1125 1126 1127
static void
_outAExpr(StringInfo str, A_Expr *node)
{
1128
	appendStringInfo(str, "EXPR ");
1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146
	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:
1147
			appendStringInfo(str, stringStringInfo(node->opname));
1148 1149
			break;
	}
1150 1151 1152 1153 1154
	_outNode(str, node->lexpr);
	_outNode(str, node->rexpr);
	return;
}

1155
static void
1156
_outValue(StringInfo str, Value *value)
1157
{
1158 1159
	switch (value->type)
	{
B
Bruce Momjian 已提交
1160
			case T_String:
M
 
Marc G. Fournier 已提交
1161
			appendStringInfo(str, " \"%s\" ", stringStringInfo(value->val.str));
1162 1163
			break;
		case T_Integer:
1164
			appendStringInfo(str, " %ld ", value->val.ival);
1165 1166
			break;
		case T_Float:
1167
			appendStringInfo(str, " %f ", value->val.dval);
1168 1169 1170
			break;
		default:
			break;
1171 1172
	}
	return;
1173 1174
}

1175 1176 1177
static void
_outIdent(StringInfo str, Ident *node)
{
1178
	appendStringInfo(str, " IDENT \"%s\" ", stringStringInfo(node->name));
1179 1180 1181
	return;
}

1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199
static void
_outAttr(StringInfo str, Attr *node)
{
	List	   *l;

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

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

1200 1201 1202
static void
_outAConst(StringInfo str, A_Const *node)
{
1203
	appendStringInfo(str, "CONST ");
1204 1205 1206 1207
	_outValue(str, &(node->val));
	return;
}

T
Thomas G. Lockhart 已提交
1208 1209 1210
static void
_outConstraint(StringInfo str, Constraint *node)
{
B
Bruce Momjian 已提交
1211
	appendStringInfo(str, " %s :type", stringStringInfo(node->name));
T
Thomas G. Lockhart 已提交
1212 1213 1214 1215

	switch (node->contype)
	{
		case CONSTR_PRIMARY:
1216
			appendStringInfo(str, " PRIMARY KEY ");
T
Thomas G. Lockhart 已提交
1217 1218 1219 1220
			_outNode(str, node->keys);
			break;

		case CONSTR_CHECK:
1221 1222 1223 1224
			appendStringInfo(str, " CHECK :raw ");
			_outNode(str, node->raw_expr);
			appendStringInfo(str, " :cooked %s ",
							 stringStringInfo(node->cooked_expr));
T
Thomas G. Lockhart 已提交
1225 1226 1227
			break;

		case CONSTR_DEFAULT:
1228 1229 1230 1231
			appendStringInfo(str, " DEFAULT :raw ");
			_outNode(str, node->raw_expr);
			appendStringInfo(str, " :cooked %s ",
							 stringStringInfo(node->cooked_expr));
T
Thomas G. Lockhart 已提交
1232 1233 1234
			break;

		case CONSTR_NOTNULL:
1235
			appendStringInfo(str, " NOT NULL ");
T
Thomas G. Lockhart 已提交
1236 1237 1238
			break;

		case CONSTR_UNIQUE:
1239
			appendStringInfo(str, " UNIQUE ");
T
Thomas G. Lockhart 已提交
1240 1241 1242 1243
			_outNode(str, node->keys);
			break;

		default:
1244
			appendStringInfo(str, "<unrecognized constraint>");
T
Thomas G. Lockhart 已提交
1245 1246 1247 1248 1249
			break;
	}
}

static void
1250
_outCaseExpr(StringInfo str, CaseExpr *node)
T
Thomas G. Lockhart 已提交
1251
{
1252
	appendStringInfo(str, "CASE ");
T
Thomas G. Lockhart 已提交
1253
	_outNode(str, node->args);
M
 
Marc G. Fournier 已提交
1254

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

T
Thomas G. Lockhart 已提交
1258 1259 1260 1261
	return;
}

static void
1262
_outCaseWhen(StringInfo str, CaseWhen *node)
T
Thomas G. Lockhart 已提交
1263
{
1264
	appendStringInfo(str, " WHEN ");
T
Thomas G. Lockhart 已提交
1265
	_outNode(str, node->expr);
M
 
Marc G. Fournier 已提交
1266

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

T
Thomas G. Lockhart 已提交
1270 1271 1272
	return;
}

1273 1274
/*
 * _outNode -
1275
 *	  converts a Node into ascii string and append it to 'str'
1276 1277 1278 1279
 */
static void
_outNode(StringInfo str, void *obj)
{
1280 1281
	if (obj == NULL)
	{
B
Bruce Momjian 已提交
1282
		appendStringInfo(str, "<>");
1283 1284
		return;
	}
1285

1286 1287
	if (nodeTag(obj) == T_List)
	{
1288
		List	   *l;
1289 1290 1291 1292 1293 1294 1295 1296 1297

		appendStringInfo(str, "(");
		foreach(l, (List *) obj)
		{
			_outNode(str, lfirst(l));
			if (lnext(l))
				appendStringInfo(str, " ");
		}
		appendStringInfo(str, ")");
1298
	}
1299 1300 1301 1302 1303
	else
	{
		appendStringInfo(str, "{");
		switch (nodeTag(obj))
		{
1304 1305 1306 1307 1308 1309 1310 1311 1312 1313
			case T_CreateStmt:
				_outCreateStmt(str, obj);
				break;
			case T_IndexStmt:
				_outIndexStmt(str, obj);
				break;

			case T_ColumnDef:
				_outColumnDef(str, obj);
				break;
1314 1315 1316
			case T_TypeName:
				_outTypeName(str, obj);
				break;
1317 1318 1319
			case T_IndexElem:
				_outIndexElem(str, obj);
				break;
1320 1321 1322
			case T_Query:
				_outQuery(str, obj);
				break;
1323 1324 1325 1326 1327
			case T_SortClause:
				_outSortClause(str, obj);
				break;
			case T_GroupClause:
				_outGroupClause(str, obj);
1328
				break;
1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358
			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;
1359 1360
			case T_Noname:
				_outNoname(str, obj);
1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376
				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 已提交
1377 1378 1379
			case T_SubPlan:
				_outSubPlan(str, obj);
				break;
1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394
			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 已提交
1395 1396
			case T_Aggref:
				_outAggref(str, obj);
1397
				break;
1398 1399 1400
			case T_SubLink:
				_outSubLink(str, obj);
				break;
1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418
			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 已提交
1419
			case T_RelOptInfo:
B
Bruce Momjian 已提交
1420
				_outRelOptInfo(str, obj);
1421 1422 1423 1424 1425 1426 1427
				break;
			case T_TargetEntry:
				_outTargetEntry(str, obj);
				break;
			case T_RangeTblEntry:
				_outRangeTblEntry(str, obj);
				break;
1428 1429 1430
			case T_RowMark:
				_outRowMark(str, obj);
				break;
1431 1432 1433 1434 1435 1436
			case T_Path:
				_outPath(str, obj);
				break;
			case T_IndexPath:
				_outIndexPath(str, obj);
				break;
1437 1438
			case T_NestPath:
				_outNestPath(str, obj);
1439 1440 1441 1442 1443 1444 1445
				break;
			case T_MergePath:
				_outMergePath(str, obj);
				break;
			case T_HashPath:
				_outHashPath(str, obj);
				break;
1446 1447
			case T_PathKeyItem:
				_outPathKeyItem(str, obj);
1448
				break;
1449 1450
			case T_RestrictInfo:
				_outRestrictInfo(str, obj);
1451
				break;
1452 1453
			case T_JoinInfo:
				_outJoinInfo(str, obj);
1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465
				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;
1466 1467 1468 1469 1470 1471 1472 1473 1474
			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 已提交
1475 1476 1477 1478 1479 1480 1481 1482 1483
			case T_Constraint:
				_outConstraint(str, obj);
				break;
			case T_CaseExpr:
				_outCaseExpr(str, obj);
				break;
			case T_CaseWhen:
				_outCaseWhen(str, obj);
				break;
1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496

			case T_VariableSetStmt:
				break;
			case T_SelectStmt:
				_outSelectStmt(str, obj);
				break;
			case T_FuncCall:
				_outFuncCall(str, obj);
				break;
			case T_Attr:
				_outAttr(str, obj);
				break;

1497
			default:
B
Bruce Momjian 已提交
1498
				elog(NOTICE, "_outNode: don't know how to print type %d ",
1499 1500
					 nodeTag(obj));
				break;
1501 1502
		}
		appendStringInfo(str, "}");
1503
	}
1504
	return;
1505 1506 1507 1508
}

/*
 * nodeToString -
1509
 *	   returns the ascii representation of the Node as a palloc'd string
1510
 */
1511
char *
1512 1513
nodeToString(void *obj)
{
B
Bruce Momjian 已提交
1514
	StringInfoData str;
1515

1516 1517 1518 1519
	/* see stringinfo.h for an explanation of this maneuver */
	initStringInfo(&str);
	_outNode(&str, obj);
	return str.data;
1520
}