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
 *
M
 
Marc G. Fournier 已提交
8
 *  $Id: outfuncs.c,v 1.55 1998/12/15 04:00:46 scrappy Exp $
9 10
 *
 * NOTES
11 12 13 14 15
 *	  Every (plan) node in POSTGRES has an associated "out" routine which
 *	  knows how to create its ascii representation. These functions are
 *	  useful for debugging as well as for storing plans in the system
 *	  catalogs (eg. indexes). This is also the plan string sent out in
 *	  Mariposa.
16
 *
17 18 19
 *	  These functions update the in/out argument of type StringInfo
 *	  passed to them. This argument contains the string holding the ASCII
 *	  representation plus some other information (string length, etc.)
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
 *
 */
#include <stdio.h>
#include "postgres.h"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

116 117
#endif

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

M
 
Marc G. Fournier 已提交
277
	appendStringInfo(str, " :nprm %d ", node->nParamExec);
278 279 280
}

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

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

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

299 300 301
}

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

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

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

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

321 322 323
}

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

332 333 334
}

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

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

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

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

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

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

M
 
Marc G. Fournier 已提交
375 376 377 378 379 380 381 382 383 384
	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);
385 386
}

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

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

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

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

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

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

M
 
Marc G. Fournier 已提交
415
	appendStringInfo(str, " :scanrelid %d ", node->scanrelid);
416 417 418
}

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

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

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

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

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

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

448 449 450
}

/*
451
 *	Temp is a subclass of Plan
452 453
 */
static void
454
_outTemp(StringInfo str, Temp *node)
455
{
456
	appendStringInfo(str, " TEMP ");
457 458
	_outPlanInfo(str, (Plan *) node);

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

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

M
 
Marc G. Fournier 已提交
473 474 475
	appendStringInfo(str, " :tempid %u :keycount %d ",
			node->tempid,
			node->keycount);
476 477 478
}

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

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

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

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

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

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

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


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

525
	appendStringInfo(str, " :hashkey ");
526 527
	_outNode(str, node->hashkey);

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

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

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

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

/*****************************************************************************
 *
550
 *	Stuff from primnodes.h.
551 552 553 554
 *
 *****************************************************************************/

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

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

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

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

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

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

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

/*
592
 *	Expr is a subclass of Node
593 594
 */
static void
595
_outExpr(StringInfo str, Expr *node)
596
{
597
	char	   *opstr = NULL;
598

M
 
Marc G. Fournier 已提交
599 600
	appendStringInfo(str, " EXPR :typeOid %u ",
			node->typeOid);
601 602 603

	switch (node->opType)
	{
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
		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 已提交
619 620 621
		case SUBPLAN_EXPR:
			opstr = "subp";
			break;
622
	}
M
 
Marc G. Fournier 已提交
623
	appendStringInfo(str, " :opType %s :oper ", opstr);
624
	_outNode(str, node->oper);
M
 
Marc G. Fournier 已提交
625

626
	appendStringInfo(str, " :args ");
627
	_outNode(str, node->args);
628 629 630
}

/*
631
 *	Var is a subclass of Expr
632 633
 */
static void
634
_outVar(StringInfo str, Var *node)
635
{
M
 
Marc G. Fournier 已提交
636 637 638 639 640 641 642 643 644 645 646
	appendStringInfo(str, 
			" VAR :varno %d :varattno %d :vartype %u %vartypmod %d ",
			node->varno,
			node->varattno,
			node->vartype,
			node->vartypmod);

	appendStringInfo(str, " :varlevelsup %u :varnoold %d :varoattno %d" ,
			node->varlevelsup,
			node->varnoold,
			node->varoattno);
647 648 649
}

/*
650
 *	Const is a subclass of Expr
651 652
 */
static void
653
_outConst(StringInfo str, Const *node)
654
{
M
 
Marc G. Fournier 已提交
655 656 657 658 659 660
	appendStringInfo(str, 
			" CONST :consttype %u :constlen %d :constisnull %s :constvalue ",
			node->consttype,
			node->constlen,
			node->constisnull ? "true" : "false");

661
	if (node->constisnull)
B
Bruce Momjian 已提交
662
		appendStringInfo(str, "<>");
663 664
	else
		_outDatum(str, node->constvalue, node->consttype);
M
 
Marc G. Fournier 已提交
665 666 667

	appendStringInfo(str, " :constbyval %s ", 
			node->constbyval ? "true" : "false");
668 669 670
}

/*
671
 *	Aggreg
672 673
 */
static void
B
Bruce Momjian 已提交
674
_outAggreg(StringInfo str, Aggreg *node)
675
{
M
 
Marc G. Fournier 已提交
676 677 678 679 680
	appendStringInfo(str, 
			" AGGREG :aggname %s :basetype %u :aggtype %u :target ",
			node->aggname,
			node->basetype,
			node->aggtype);
681
	_outNode(str, node->target);
M
 
Marc G. Fournier 已提交
682 683 684 685

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

688 689 690 691 692 693
/*
 *	SubLink
 */
static void
_outSubLink(StringInfo str, SubLink *node)
{
M
 
Marc G. Fournier 已提交
694 695 696 697
	appendStringInfo(str, 
			" SUBLINK :subLinkType %d :useor %s :lefthand ",
			node->subLinkType,
			node->useor ? "true" : "false");
698
	_outNode(str, node->lefthand);
M
 
Marc G. Fournier 已提交
699

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

703 704 705 706
	appendStringInfo(str, " :subselect ");
	_outNode(str, node->subselect);
}

707
/*
708
 *	Array is a subclass of Expr
709 710
 */
static void
B
Bruce Momjian 已提交
711
_outArray(StringInfo str, Array *node)
712
{
713
	int			i;
714

M
 
Marc G. Fournier 已提交
715 716 717 718 719 720 721
	appendStringInfo(str, 
			" ARRAY :arrayelemtype %u :arrayelemlength %d :arrayelembyval %c ",
			node->arrayelemtype, 
			node->arrayelemlength,
			node->arrayelembyval ? 't' : 'f');

	appendStringInfo(str, " :arrayndim %d ", node->arrayndim);
722
	appendStringInfo(str, " :arraylow ");
723 724
	for (i = 0; i < node->arrayndim; i++)
	{
M
 
Marc G. Fournier 已提交
725
		appendStringInfo(str, " %d ", node->arraylow.indx[i]);
726
	}
727
	appendStringInfo(str, " :arrayhigh ");
728 729
	for (i = 0; i < node->arrayndim; i++)
	{
M
 
Marc G. Fournier 已提交
730
		appendStringInfo(str, " %d ", node->arrayhigh.indx[i]);
731
	}
M
 
Marc G. Fournier 已提交
732
	appendStringInfo(str, " :arraylen %d ", node->arraylen);
733 734 735
}

/*
736
 *	ArrayRef is a subclass of Expr
737 738
 */
static void
B
Bruce Momjian 已提交
739
_outArrayRef(StringInfo str, ArrayRef *node)
740
{
M
 
Marc G. Fournier 已提交
741 742 743 744 745 746 747 748
	appendStringInfo(str, 
			" ARRAYREF :refelemtype %u :refattrlength $d :refelemlength %d ",
			node->refelemtype,
			node->refattrlength,
			node->refelemlength);

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

751
	appendStringInfo(str, " :reflowerindex ");
752 753
	_outNode(str, node->reflowerindexpr);

754
	appendStringInfo(str, " :refexpr ");
755 756
	_outNode(str, node->refexpr);

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

/*
762
 *	Func is a subclass of Expr
763 764
 */
static void
765
_outFunc(StringInfo str, Func *node)
766
{
M
 
Marc G. Fournier 已提交
767 768 769 770 771 772 773 774 775
	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);
776 777 778 779
	_outNode(str, node->func_tlist);

	appendStringInfo(str, " :func_planlist ");
	_outNode(str, node->func_planlist);
780 781 782
}

/*
783
 *	Oper is a subclass of Expr
784 785
 */
static void
786
_outOper(StringInfo str, Oper *node)
787
{
M
 
Marc G. Fournier 已提交
788 789 790 791 792
	appendStringInfo(str, 
			" OPER :opno %u :opid %u :opresulttype %u ",
			node->opno,
			node->opid,
			node->opresulttype);
793 794 795
}

/*
796
 *	Param is a subclass of Expr
797 798
 */
static void
799
_outParam(StringInfo str, Param *node)
800
{
M
 
Marc G. Fournier 已提交
801 802 803 804 805 806
	appendStringInfo(str, 
			" PARAM :paramkind %d :paramid %d :paramname %s :paramtype %u ",
			node->paramkind,
			node->paramid,
			node->paramname,
			node->paramtype);
807 808 809

	appendStringInfo(str, " :param_tlist ");
	_outNode(str, node->param_tlist);
810 811 812
}

/*
813
 *	Stuff from execnodes.h
814 815 816
 */

/*
817
 *	EState is a subclass of Node.
818 819
 */
static void
820
_outEState(StringInfo str, EState *node)
821
{
M
 
Marc G. Fournier 已提交
822 823 824
	appendStringInfo(str, 
			" ESTATE :direction %d :range_table ",
			node->es_direction);
825 826
	_outNode(str, node->es_range_table);

M
 
Marc G. Fournier 已提交
827
	appendStringInfo(str, " :result_relation_info @ 0x%x ",
828
			(int) (node->es_result_relation_info));
829 830 831
}

/*
832
 *	Stuff from relation.h
833 834
 */
static void
835
_outRelOptInfo(StringInfo str, RelOptInfo * node)
836
{
M
 
Marc G. Fournier 已提交
837
	appendStringInfo(str, " RELOPTINFO :relids ");
838 839
	_outIntList(str, node->relids);

M
 
Marc G. Fournier 已提交
840 841 842 843 844 845 846
	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);
847 848
	_outNode(str, node->targetlist);

849
	appendStringInfo(str, " :pathlist ");
850 851 852 853 854 855 856 857
	_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 已提交
858 859 860 861 862
	appendStringInfo(str, 
			" :unorderedpath @ 0x%x :cheapestpath @ 0x%x :pruneable %s :clauseinfo ",
			(int) node->unorderedpath,
			(int) node->cheapestpath,
			node->pruneable ? "true" : "false");
863 864
	_outNode(str, node->clauseinfo);

865
	appendStringInfo(str, " :joininfo ");
866 867
	_outNode(str, node->joininfo);

868
	appendStringInfo(str, " :innerjoin ");
869
	_outNode(str, node->innerjoin);
870 871 872
}

/*
873
 *	TargetEntry is a subclass of Node.
874 875
 */
static void
876
_outTargetEntry(StringInfo str, TargetEntry *node)
877
{
M
 
Marc G. Fournier 已提交
878
	appendStringInfo(str, " TARGETENTRY :resdom ");
879 880
	_outNode(str, node->resdom);

881 882
	appendStringInfo(str, " :expr ");
	_outNode(str, node->expr);
883
}
884 885

static void
886
_outRangeTblEntry(StringInfo str, RangeTblEntry *node)
887
{
M
 
Marc G. Fournier 已提交
888 889 890 891 892 893 894 895
	appendStringInfo(str, 
			" RTE :relname %s :refname %s :relid %u :inh %s :inFromCl %s :skipAcl %s",
			node->relname,
			node->refname,
			node->relid,
			node->inh ? "true" : "false",
			node->inFromCl ? "true" : "false",
			node->skipAcl ? "true" : "false");
896
}
897 898

/*
899
 *	Path is a subclass of Node.
900 901
 */
static void
902
_outPath(StringInfo str, Path *node)
903
{
M
 
Marc G. Fournier 已提交
904 905 906
	appendStringInfo(str, " PATH :pathtype %d :cost %f :keys ",
			node->pathtype,
			node->path_cost);
907
	_outNode(str, node->keys);
908 909 910
}

/*
911
 *	IndexPath is a subclass of Path.
912 913
 */
static void
914
_outIndexPath(StringInfo str, IndexPath *node)
915
{
M
 
Marc G. Fournier 已提交
916 917 918 919
	appendStringInfo(str, 
			" INDEXPATH :pathtype %d :cost %f :keys ",
			node->path.pathtype,
			node->path.path_cost);
920 921
	_outNode(str, node->path.keys);

922
	appendStringInfo(str, " :indexid ");
923 924
	_outIntList(str, node->indexid);

925
	appendStringInfo(str, " :indexqual ");
926
	_outNode(str, node->indexqual);
927 928 929
}

/*
930
 *	JoinPath is a subclass of Path
931 932
 */
static void
933
_outJoinPath(StringInfo str, JoinPath *node)
934
{
M
 
Marc G. Fournier 已提交
935 936 937 938
	appendStringInfo(str, 
			" JOINPATH :pathtype %d :cost %f :keys ",
			node->path.pathtype,
			node->path.path_cost);
939 940
	_outNode(str, node->path.keys);

941
	appendStringInfo(str, " :pathclauseinfo ");
942 943 944 945 946 947 948
	_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 已提交
949 950 951 952 953
	appendStringInfo(str, 
			" :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x :outjoincost %f :joinid ",
			(int) node->outerjoinpath,
			(int) node->innerjoinpath,
			node->path.outerjoincost);
954
	_outIntList(str, node->path.joinid);
955 956 957
}

/*
958
 *	MergePath is a subclass of JoinPath.
959 960
 */
static void
961
_outMergePath(StringInfo str, MergePath *node)
962
{
M
 
Marc G. Fournier 已提交
963 964 965 966
	appendStringInfo(str, 
			" MERGEPATH :pathtype %d :cost %f :keys ",
			node->jpath.path.pathtype,
			node->jpath.path.path_cost);
967 968
	_outNode(str, node->jpath.path.keys);

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

984
	appendStringInfo(str, " :path_mergeclauses ");
985 986
	_outNode(str, node->path_mergeclauses);

987
	appendStringInfo(str, " :outersortkeys ");
988 989
	_outNode(str, node->outersortkeys);

990
	appendStringInfo(str, " :innersortkeys ");
991
	_outNode(str, node->innersortkeys);
992 993 994
}

/*
995
 *	HashPath is a subclass of JoinPath.
996 997
 */
static void
998
_outHashPath(StringInfo str, HashPath *node)
999
{
M
 
Marc G. Fournier 已提交
1000 1001 1002 1003
	appendStringInfo(str, 
			" HASHPATH :pathtype %d :cost %f :keys ",
			node->jpath.path.pathtype,
			node->jpath.path.path_cost);
1004 1005
	_outNode(str, node->jpath.path.keys);

1006
	appendStringInfo(str, " :pathclauseinfo ");
1007 1008 1009 1010 1011 1012 1013
	_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 已提交
1014 1015 1016 1017 1018
	appendStringInfo(str, 
			" :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x :outerjoincost %f :joinid ",
			(int) node->jpath.outerjoinpath,
			(int) node->jpath.innerjoinpath,
			node->jpath.path.outerjoincost);
1019 1020
	_outIntList(str, node->jpath.path.joinid);

1021
	appendStringInfo(str, " :path_hashclauses ");
1022 1023
	_outNode(str, node->path_hashclauses);

1024
	appendStringInfo(str, " :outerhashkeys ");
1025 1026
	_outNode(str, node->outerhashkeys);

1027
	appendStringInfo(str, " :innerhashkeys ");
1028
	_outNode(str, node->innerhashkeys);
1029 1030 1031
}

/*
1032
 *	OrderKey is a subclass of Node.
1033 1034
 */
static void
1035
_outOrderKey(StringInfo str, OrderKey *node)
1036
{
M
 
Marc G. Fournier 已提交
1037 1038 1039 1040
	appendStringInfo(str, 
			" ORDERKEY :attribute_number %d :array_index %d ",
			node->attribute_number,
			node->array_index);
1041 1042 1043
}

/*
1044
 *	JoinKey is a subclass of Node.
1045 1046
 */
static void
1047
_outJoinKey(StringInfo str, JoinKey *node)
1048
{
1049
	appendStringInfo(str, " JOINKEY ");
1050

1051
	appendStringInfo(str, " :outer ");
1052 1053
	_outNode(str, node->outer);

1054
	appendStringInfo(str, " :inner ");
1055 1056
	_outNode(str, node->inner);

1057 1058 1059
}

/*
1060
 *	MergeOrder is a subclass of Node.
1061 1062
 */
static void
1063
_outMergeOrder(StringInfo str, MergeOrder *node)
1064
{
1065
	char		buf[500];
1066

1067
	appendStringInfo(str, " MERGEORDER ");
1068

B
Bruce Momjian 已提交
1069
	sprintf(buf, " :join_operator %d ", node->join_operator);
1070
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1071
	sprintf(buf, " :left_operator %d ", node->left_operator);
1072
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1073
	sprintf(buf, " :right_operator %d ", node->right_operator);
1074
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1075
	sprintf(buf, " :left_type %d ", node->left_type);
1076
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1077
	sprintf(buf, " :right_type %d ", node->right_type);
1078 1079
	appendStringInfo(str, buf);

1080 1081 1082
}

/*
1083
 *	ClauseInfo is a subclass of Node.
1084 1085
 */
static void
1086
_outClauseInfo(StringInfo str, ClauseInfo * node)
1087
{
1088
	char		buf[500];
1089

1090
	appendStringInfo(str, " CINFO ");
1091

1092
	appendStringInfo(str, " :clause ");
1093 1094
	_outNode(str, node->clause);

B
Bruce Momjian 已提交
1095
	sprintf(buf, " :selectivity %f ", node->selectivity);
1096
	appendStringInfo(str, buf);
1097 1098
	appendStringInfo(str, " :notclause ");
	appendStringInfo(str, node->notclause ? "true" : "false");
1099

1100
	appendStringInfo(str, " :indexids ");
1101 1102
	_outNode(str, node->indexids);

1103 1104
	appendStringInfo(str, " :mergejoinorder ");
	_outNode(str, node->mergejoinorder);
1105

B
Bruce Momjian 已提交
1106
	sprintf(buf, " :hashjoinoperator %u ", node->hashjoinoperator);
1107 1108
	appendStringInfo(str, buf);

1109 1110 1111
}

/*
1112
 *	JoinMethod is a subclass of Node.
1113 1114
 */
static void
1115
_outJoinMethod(StringInfo str, JoinMethod *node)
1116
{
1117
	appendStringInfo(str, " JOINMETHOD ");
1118

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

1122
	appendStringInfo(str, " :clauses ");
1123 1124 1125
	_outNode(str, node->clauses);


1126 1127 1128 1129 1130 1131
}

/*
 * HInfo is a subclass of JoinMethod.
 */
static void
1132
_outHInfo(StringInfo str, HInfo *node)
1133
{
1134
	char		buf[500];
1135

1136
	appendStringInfo(str, " HASHINFO ");
1137

1138
	appendStringInfo(str, " :hashop ");
B
Bruce Momjian 已提交
1139
	sprintf(buf, " %u ", node->hashop);
1140 1141
	appendStringInfo(str, buf);

1142
	appendStringInfo(str, " :jmkeys ");
1143 1144
	_outNode(str, node->jmethod.jmkeys);

1145
	appendStringInfo(str, " :clauses ");
1146 1147
	_outNode(str, node->jmethod.clauses);

1148 1149 1150
}

/*
1151
 *	JoinInfo is a subclass of Node.
1152 1153
 */
static void
1154
_outJoinInfo(StringInfo str, JoinInfo * node)
1155
{
1156
	appendStringInfo(str, " JINFO ");
1157

1158
	appendStringInfo(str, " :otherrels ");
1159 1160
	_outIntList(str, node->otherrels);

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

1164 1165
	appendStringInfo(str, " :mergejoinable ");
	appendStringInfo(str, node->mergejoinable ? "true" : "false");
1166 1167
	appendStringInfo(str, " :hashjoinable ");
	appendStringInfo(str, node->hashjoinable ? "true" : "false");
1168

1169 1170 1171 1172 1173 1174 1175 1176
}

/*
 * Print the value of a Datum given its type.
 */
static void
_outDatum(StringInfo str, Datum value, Oid type)
{
1177 1178 1179 1180 1181 1182
	char		buf[500];
	Size		length,
				typeLength;
	bool		byValue;
	int			i;
	char	   *s;
1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198

	/*
	 * 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 已提交
1199
			sprintf(buf, " %d ", (int) (s[i]));
1200 1201 1202 1203
			appendStringInfo(str, buf);
		}
		sprintf(buf, "] ");
		appendStringInfo(str, buf);
1204
	}
1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225
	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 已提交
1226
				sprintf(buf, " %d ", (int) (s[i]));
1227 1228 1229 1230 1231
				appendStringInfo(str, buf);
			}
			sprintf(buf, "] ");
			appendStringInfo(str, buf);
		}
1232 1233 1234 1235
	}
}

static void
1236
_outIter(StringInfo str, Iter *node)
1237
{
1238
	appendStringInfo(str, " ITER ");
1239 1240 1241

	appendStringInfo(str, " :iterexpr ");
	_outNode(str, node->iterexpr);
1242 1243 1244
}

static void
1245
_outStream(StringInfo str, Stream *node)
1246
{
1247
	char		buf[500];
1248

1249
	appendStringInfo(str, " STREAM ");
1250

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

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

B
Bruce Momjian 已提交
1257
	sprintf(buf, " :clausetype %d ", (int) (node->clausetype));
1258 1259
	appendStringInfo(str, buf);

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

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

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

B
Bruce Momjian 已提交
1269
	sprintf(buf, " :groupcost %f ", node->groupcost);
1270 1271
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
1272
	sprintf(buf, " :groupsel %f ", node->groupsel);
1273 1274
	appendStringInfo(str, buf);
}
1275

1276 1277 1278
static void
_outAExpr(StringInfo str, A_Expr *node)
{
1279
	appendStringInfo(str, "EXPR ");
1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304
#ifdef PARSEDEBUG
	switch (node->oper)
	{
		case AND:
			appendStringInfo(str, "AND");
			break;
		case OR:
			appendStringInfo(str, "OR");
			break;
		case NOT:
			appendStringInfo(str, "NOT");
			break;
		case ISNULL:
			appendStringInfo(str, "ISNULL");
			break;
		case NOTNULL:
			appendStringInfo(str, "NOTNULL");
			break;
		default:
#endif
			appendStringInfo(str, node->opname);
#ifdef PARSEDEBUG
			break;
	}
#endif
1305 1306 1307 1308 1309
	_outNode(str, node->lexpr);
	_outNode(str, node->rexpr);
	return;
}

1310
static void
1311
_outValue(StringInfo str, Value *value)
1312
{
1313
	char		buf[500];
1314 1315 1316

	switch (value->type)
	{
1317
		case T_String:
B
Bruce Momjian 已提交
1318
			sprintf(buf, " \"%s\" ", value->val.str);
1319 1320 1321
			appendStringInfo(str, buf);
			break;
		case T_Integer:
B
Bruce Momjian 已提交
1322
			sprintf(buf, " %ld ", value->val.ival);
1323 1324 1325
			appendStringInfo(str, buf);
			break;
		case T_Float:
B
Bruce Momjian 已提交
1326
			sprintf(buf, " %f ", value->val.dval);
1327 1328 1329 1330
			appendStringInfo(str, buf);
			break;
		default:
			break;
1331 1332
	}
	return;
1333 1334
}

1335 1336 1337 1338 1339
static void
_outIdent(StringInfo str, Ident *node)
{
	char		buf[500];

B
Bruce Momjian 已提交
1340
	sprintf(buf, " IDENT \"%s\" ", node->name);
1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355
	appendStringInfo(str, buf);
	return;
}

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

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

T
Thomas G. Lockhart 已提交
1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422
static void
_outConstraint(StringInfo str, Constraint *node)
{
	char		buf[500];

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

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

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

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

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

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

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

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

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

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

1423
	sprintf(buf, " WHEN ");
T
Thomas G. Lockhart 已提交
1424 1425 1426 1427 1428 1429 1430 1431
	appendStringInfo(str, buf);
	_outNode(str, node->expr);
	sprintf(buf, " :then ");
	appendStringInfo(str, buf);
	_outNode(str, node->result);
	return;
}

1432 1433
/*
 * _outNode -
1434
 *	  converts a Node into ascii string and append it to 'str'
1435 1436 1437 1438
 */
static void
_outNode(StringInfo str, void *obj)
{
1439 1440
	if (obj == NULL)
	{
B
Bruce Momjian 已提交
1441
		appendStringInfo(str, "<>");
1442 1443
		return;
	}
1444

1445 1446
	if (nodeTag(obj) == T_List)
	{
1447
		List	   *l;
1448 1449 1450 1451 1452 1453 1454 1455 1456

		appendStringInfo(str, "(");
		foreach(l, (List *) obj)
		{
			_outNode(str, lfirst(l));
			if (lnext(l))
				appendStringInfo(str, " ");
		}
		appendStringInfo(str, ")");
1457
	}
1458 1459 1460 1461 1462
	else
	{
		appendStringInfo(str, "{");
		switch (nodeTag(obj))
		{
1463 1464 1465 1466 1467 1468 1469 1470 1471 1472
			case T_CreateStmt:
				_outCreateStmt(str, obj);
				break;
			case T_IndexStmt:
				_outIndexStmt(str, obj);
				break;

			case T_ColumnDef:
				_outColumnDef(str, obj);
				break;
1473 1474 1475
			case T_TypeName:
				_outTypeName(str, obj);
				break;
1476 1477 1478 1479
			case T_IndexElem:
				_outIndexElem(str, obj);
				break;

1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490
#ifdef PARSEDEBUG
			case T_VariableSetStmt:
				break;
			case T_SelectStmt:
				_outSelectStmt(str, obj);
				break;
			case T_FuncCall:
				_outFuncCall(str, obj);
				break;
#endif

1491 1492 1493
			case T_Query:
				_outQuery(str, obj);
				break;
1494 1495 1496 1497 1498
			case T_SortClause:
				_outSortClause(str, obj);
				break;
			case T_GroupClause:
				_outGroupClause(str, obj);
1499
				break;
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 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547
			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 已提交
1548 1549 1550
			case T_SubPlan:
				_outSubPlan(str, obj);
				break;
1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571
			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;
1572 1573 1574
			case T_SubLink:
				_outSubLink(str, obj);
				break;
1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592
			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 已提交
1593
			case T_RelOptInfo:
B
Bruce Momjian 已提交
1594
				_outRelOptInfo(str, obj);
1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625
				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;
1626 1627
			case T_ClauseInfo:
				_outClauseInfo(str, obj);
1628 1629 1630 1631 1632 1633 1634
				break;
			case T_JoinMethod:
				_outJoinMethod(str, obj);
				break;
			case T_HInfo:
				_outHInfo(str, obj);
				break;
1635 1636
			case T_JoinInfo:
				_outJoinInfo(str, obj);
1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648
				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;
1649 1650 1651 1652 1653 1654 1655 1656 1657
			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 已提交
1658 1659 1660 1661 1662 1663 1664 1665 1666
			case T_Constraint:
				_outConstraint(str, obj);
				break;
			case T_CaseExpr:
				_outCaseExpr(str, obj);
				break;
			case T_CaseWhen:
				_outCaseWhen(str, obj);
				break;
1667
			default:
B
Bruce Momjian 已提交
1668
				elog(NOTICE, "_outNode: don't know how to print type %d ",
1669 1670
					 nodeTag(obj));
				break;
1671 1672
		}
		appendStringInfo(str, "}");
1673
	}
1674
	return;
1675 1676 1677 1678
}

/*
 * nodeToString -
1679
 *	   returns the ascii representation of the Node
1680
 */
1681
char *
1682 1683
nodeToString(void *obj)
{
1684 1685
	StringInfo	str;
	char	   *s;
1686 1687 1688 1689 1690 1691 1692 1693 1694 1695

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

	return s;
1696
}