outfuncs.c 34.5 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.65 1999/02/05 19:59:25 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
	appendStringInfo(str, " CREATE :relname %s ", 
73
		stringStringInfo(node->relname));
74 75 76 77 78

	appendStringInfo(str, " :istemp %s ",
			node->istemp ? "true" : "false");

	appendStringInfo(str, "	:columns ");
79
	_outNode(str, node->tableElts);
M
 
Marc G. Fournier 已提交
80

81
	appendStringInfo(str, " :inhRelnames ");
82
	_outNode(str, node->inhRelnames);
M
 
Marc G. Fournier 已提交
83

84
	appendStringInfo(str, " :constraints ");
85
	_outNode(str, node->constraints);
86
}
87 88 89 90

static void
_outIndexStmt(StringInfo str, IndexStmt *node)
{
M
 
Marc G. Fournier 已提交
91 92
	appendStringInfo(str, 
			" INDEX :idxname %s :relname %s :accessMethod %s :indexParams ",
93 94 95
			stringStringInfo(node->idxname),
			stringStringInfo(node->relname),
			stringStringInfo(node->accessMethod));
96
	_outNode(str, node->indexParams);
M
 
Marc G. Fournier 已提交
97

98 99
	appendStringInfo(str, " :withClause ");
	_outNode(str, node->withClause);
M
 
Marc G. Fournier 已提交
100

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

104 105
	appendStringInfo(str, " :rangetable ");
	_outNode(str, node->rangetable);
M
 
Marc G. Fournier 已提交
106 107 108 109

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

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

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

127 128
#endif

129 130 131
static void
_outColumnDef(StringInfo str, ColumnDef *node)
{
132 133
	appendStringInfo(str, " COLUMNDEF :colname %s :typename ",
			stringStringInfo(node->colname));
134
	_outNode(str, node->typename);
M
 
Marc G. Fournier 已提交
135 136

	appendStringInfo(str, " :is_not_null %s :defval %s :constraints ",
137 138
			node->is_not_null ? "true" : "false", 
			stringStringInfo(node->defval));
139
	_outNode(str, node->constraints);
140 141 142 143 144
}

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

	appendStringInfo(str, " :arrayBounds ");
	_outNode(str, node->arrayBounds);
}
155 156 157 158

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

M
 
Marc G. Fournier 已提交
163
	appendStringInfo(str, " :class %s :typename ", stringStringInfo(node->class));
164
	_outNode(str, node->typename);
165
}
166

167
static void
168
_outQuery(StringInfo str, Query *node)
169
{
170

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

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

			case T_IndexStmt:
M
 
Marc G. Fournier 已提交
184
				appendStringInfo(str, " :index %s on %s ",
185 186
					stringStringInfo(((IndexStmt *) (node->utilityStmt))->idxname),
					stringStringInfo(((IndexStmt *) (node->utilityStmt))->relname));
187 188 189 190
				_outNode(str, node->utilityStmt);
				break;

			case T_NotifyStmt:
M
 
Marc G. Fournier 已提交
191
				appendStringInfo(str, " :utility %s ",
192
						stringStringInfo(((NotifyStmt *) (node->utilityStmt))->relname));
193 194 195
				break;

			default:
196
				appendStringInfo(str, " :utility ? ");
197 198
		}
	}
199
	else
200
	{
201
		appendStringInfo(str, " :utility <>");
202
	}
203

M
 
Marc G. Fournier 已提交
204
	appendStringInfo(str, 
205
	" :resultRelation %d :into %s :isPortal %s :isBinary %s :isTemp %s :unionall %s ",
M
 
Marc G. Fournier 已提交
206
			node->resultRelation,
207
			stringStringInfo(node->into),
M
 
Marc G. Fournier 已提交
208 209
			node->isPortal ? "true" : "false",
			node->isBinary ? "true" : "false",
210
			node->isTemp ? "true" : "false",
M
 
Marc G. Fournier 已提交
211 212
			node->unionall ? "true" : "false");

213 214
	appendStringInfo(str, " :unique %s :sortClause ", 
			stringStringInfo(node->uniqueFlag));
215
	_outNode(str, node->sortClause);
M
 
Marc G. Fournier 已提交
216

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

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

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

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

229
	appendStringInfo(str, " :havingQual ");
230
	_outNode(str, node->havingQual);
M
 
Marc G. Fournier 已提交
231 232 233 234

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

B
Hi!  
Bruce Momjian 已提交
237 238 239
	appendStringInfo(str, " :intersectClause ");
	_outNode(str, node->intersectClause);

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

B
Bruce Momjian 已提交
243 244
	appendStringInfo(str, " :limitCount ");
	_outNode(str, node->limitCount);
245 246 247 248

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

249 250 251
}

static void
252
_outSortClause(StringInfo str, SortClause *node)
253
{
M
 
Marc G. Fournier 已提交
254
	appendStringInfo(str, " SORTCLAUSE :resdom ");
255
	_outNode(str, node->resdom);
M
 
Marc G. Fournier 已提交
256 257

	appendStringInfo(str, " :opoid %u ", node->opoid);
258 259 260 261 262
}

static void
_outGroupClause(StringInfo str, GroupClause *node)
{
M
 
Marc G. Fournier 已提交
263
	appendStringInfo(str, " GROUPCLAUSE :entry ");
264
	_outNode(str, node->entry);
M
 
Marc G. Fournier 已提交
265 266

	appendStringInfo(str, " :grpOpoid %u ", node->grpOpoid);
267 268 269 270 271 272
}

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

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

286
	appendStringInfo(str, " :lefttree ");
287
	_outNode(str, node->lefttree);
M
 
Marc G. Fournier 已提交
288

289
	appendStringInfo(str, " :righttree ");
290
	_outNode(str, node->righttree);
M
 
Marc G. Fournier 已提交
291

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

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

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

M
 
Marc G. Fournier 已提交
301
	appendStringInfo(str, " :nprm %d ", node->nParamExec);
302 303 304
}

/*
305
 *	Stuff from plannodes.h
306 307
 */
static void
308
_outPlan(StringInfo str, Plan *node)
309
{
310
	appendStringInfo(str, " PLAN ");
311
	_outPlanInfo(str, (Plan *) node);
312 313 314
}

static void
315
_outResult(StringInfo str, Result *node)
316
{
317
	appendStringInfo(str, " RESULT ");
318 319
	_outPlanInfo(str, (Plan *) node);

320
	appendStringInfo(str, " :resconstantqual ");
321 322
	_outNode(str, node->resconstantqual);

323 324 325
}

/*
326
 *	Append is a subclass of Plan.
327 328
 */
static void
B
Bruce Momjian 已提交
329
_outAppend(StringInfo str, Append *node)
330
{
331
	appendStringInfo(str, " APPEND ");
332 333
	_outPlanInfo(str, (Plan *) node);

334 335
	appendStringInfo(str, " :appendplans ");
	_outNode(str, node->appendplans);
336

337 338
	appendStringInfo(str, " :unionrtables ");
	_outNode(str, node->unionrtables);
339

M
 
Marc G. Fournier 已提交
340 341 342
	appendStringInfo(str, 
		" :inheritrelid %d :inheritrtable ", 
		node->inheritrelid);
343
	_outNode(str, node->inheritrtable);
344

345 346 347
}

/*
348
 *	Join is a subclass of Plan
349 350
 */
static void
351
_outJoin(StringInfo str, Join *node)
352
{
353
	appendStringInfo(str, " JOIN ");
354 355
	_outPlanInfo(str, (Plan *) node);

356 357 358
}

/*
359
 *	NestLoop is a subclass of Join
360 361
 */
static void
362
_outNestLoop(StringInfo str, NestLoop *node)
363
{
364
	appendStringInfo(str, " NESTLOOP ");
365
	_outPlanInfo(str, (Plan *) node);
366 367 368
}

/*
369
 *	MergeJoin is a subclass of Join
370 371
 */
static void
372
_outMergeJoin(StringInfo str, MergeJoin *node)
373
{
374
	appendStringInfo(str, " MERGEJOIN ");
375 376
	_outPlanInfo(str, (Plan *) node);

377
	appendStringInfo(str, " :mergeclauses ");
378 379
	_outNode(str, node->mergeclauses);

M
 
Marc G. Fournier 已提交
380 381 382 383 384
	appendStringInfo(str, 
			" :mergejoinop %u :mergerightorder %u :mergeleftorder %u ",
			node->mergejoinop, 
			node->mergerightorder,
			node->mergeleftorder);
385 386 387
}

/*
388
 *	HashJoin is a subclass of Join.
389 390
 */
static void
391
_outHashJoin(StringInfo str, HashJoin *node)
392
{
393
	appendStringInfo(str, " HASHJOIN ");
394 395
	_outPlanInfo(str, (Plan *) node);

396
	appendStringInfo(str, " :hashclauses ");
397 398
	_outNode(str, node->hashclauses);

M
 
Marc G. Fournier 已提交
399 400 401 402 403 404 405 406 407 408
	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);
409 410
}

V
Vadim B. Mikheev 已提交
411 412 413
static void
_outSubPlan(StringInfo str, SubPlan *node)
{
M
 
Marc G. Fournier 已提交
414
	appendStringInfo(str, " SUBPLAN :plan ");
V
Vadim B. Mikheev 已提交
415
	_outNode(str, node->plan);
M
 
Marc G. Fournier 已提交
416 417

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

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

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

V
Vadim B. Mikheev 已提交
426 427 428 429
	appendStringInfo(str, " :slink ");
	_outNode(str, node->sublink);
}

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

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

/*
443
 *	SeqScan is a subclass of Scan
444 445
 */
static void
446
_outSeqScan(StringInfo str, SeqScan *node)
447
{
448
	appendStringInfo(str, " SEQSCAN ");
449 450
	_outPlanInfo(str, (Plan *) node);

M
 
Marc G. Fournier 已提交
451
	appendStringInfo(str, " :scanrelid %d ", node->scanrelid);
452 453 454
}

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

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

466
	appendStringInfo(str, " :indxqual ");
467 468
	_outNode(str, node->indxqual);

V
Vadim B. Mikheev 已提交
469 470 471
	appendStringInfo(str, " :indxqualorig ");
	_outNode(str, node->indxqualorig);

472 473 474
}

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

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

/*
489
 *	Sort is a subclass of Temp
490 491
 */
static void
492
_outSort(StringInfo str, Sort *node)
493
{
494
	appendStringInfo(str, " SORT ");
495 496
	_outPlanInfo(str, (Plan *) node);

M
 
Marc G. Fournier 已提交
497 498 499
	appendStringInfo(str, " :tempid %u :keycount %d ",
			node->tempid,
			node->keycount);
500 501 502
}

static void
B
Bruce Momjian 已提交
503
_outAgg(StringInfo str, Agg *node)
504
{
505

506
	appendStringInfo(str, " AGG ");
507 508
	_outPlanInfo(str, (Plan *) node);

509 510
	appendStringInfo(str, " :aggs ");
	_outNode(str, node->aggs);
511 512 513
}

static void
514
_outGroup(StringInfo str, Group *node)
515
{
516
	appendStringInfo(str, " GRP ");
517 518 519
	_outPlanInfo(str, (Plan *) node);

	/* the actual Group fields */
M
 
Marc G. Fournier 已提交
520
	appendStringInfo(str, " :numCols %d :tuplePerGroup %s ",
M
 
Marc G. Fournier 已提交
521 522
			node->numCols,
			node->tuplePerGroup ? "true" : "false");
523
}
524

525
/*
526
 *	For some reason, unique is a subclass of Temp.
527 528
 */
static void
529
_outUnique(StringInfo str, Unique *node)
530
{
531
	appendStringInfo(str, " UNIQUE ");
532 533
	_outPlanInfo(str, (Plan *) node);

M
 
Marc G. Fournier 已提交
534 535 536
	appendStringInfo(str, " :tempid %u :keycount %d ",
			node->tempid,
			node->keycount);
537 538 539 540
}


/*
541
 *	Hash is a subclass of Temp
542 543
 */
static void
544
_outHash(StringInfo str, Hash *node)
545
{
546
	appendStringInfo(str, " HASH ");
547 548
	_outPlanInfo(str, (Plan *) node);

549
	appendStringInfo(str, " :hashkey ");
550 551
	_outNode(str, node->hashkey);

M
 
Marc G. Fournier 已提交
552 553 554 555
	appendStringInfo(str, " :hashtable 0x%x :hashtablekey %d :hashtablesize %d ",
			(int) node->hashtable,
			node->hashtablekey,
			node->hashtablesize);
556 557 558
}

static void
559
_outTee(StringInfo str, Tee *node)
560
{
561
	appendStringInfo(str, " TEE ");
562 563
	_outPlanInfo(str, (Plan *) node);

M
 
Marc G. Fournier 已提交
564 565 566
	appendStringInfo(str, " :leftParent %X :rightParent %X ",
		(int) node->leftParent,
		(int) node->rightParent);
567

568
	appendStringInfo(str, " :rtentries ");
569
	_outNode(str, node->rtentries);
570 571 572 573
}

/*****************************************************************************
 *
574
 *	Stuff from primnodes.h.
575 576 577 578
 *
 *****************************************************************************/

/*
579
 *	Resdom is a subclass of Node
580 581
 */
static void
582
_outResdom(StringInfo str, Resdom *node)
583
{
M
 
Marc G. Fournier 已提交
584 585 586 587
	appendStringInfo(str, " RESDOM :resno %d :restype %u :restypmod %d ",
			node->resno,
			node->restype,
			node->restypmod);
588

M
 
Marc G. Fournier 已提交
589
	appendStringInfo(str, " :resname \"%s\" :reskey %d :reskeyop %u :resjunk %d",
590
			stringStringInfo(node->resname),
M
 
Marc G. Fournier 已提交
591 592 593
			node->reskey,
			node->reskeyop,
			node->resjunk);
594 595 596
}

static void
597
_outFjoin(StringInfo str, Fjoin *node)
598
{
599
	int			i;
600

M
 
Marc G. Fournier 已提交
601 602 603
	appendStringInfo(str, " FJOIN :initialized %s :nNodes %d ",
			node->fj_initialized ? "true" : "false",
			node->fj_nNodes);
604 605 606 607

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

M
 
Marc G. Fournier 已提交
608 609
	appendStringInfo(str, " :results @ 0x%x :alwaysdone", 
			(int) node->fj_results);
610 611

	for (i = 0; i < node->fj_nNodes; i++)
612
		appendStringInfo(str, (node->fj_alwaysDone[i]) ? "true" : "false");
613 614 615
}

/*
616
 *	Expr is a subclass of Node
617 618
 */
static void
619
_outExpr(StringInfo str, Expr *node)
620
{
621
	char	   *opstr = NULL;
622

M
 
Marc G. Fournier 已提交
623 624
	appendStringInfo(str, " EXPR :typeOid %u ",
			node->typeOid);
625 626 627

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

650
	appendStringInfo(str, " :args ");
651
	_outNode(str, node->args);
652 653 654
}

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

	appendStringInfo(str, " :varlevelsup %u :varnoold %d :varoattno %d" ,
			node->varlevelsup,
			node->varnoold,
			node->varoattno);
671 672 673
}

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

685
	if (node->constisnull)
B
Bruce Momjian 已提交
686
		appendStringInfo(str, "<>");
687 688
	else
		_outDatum(str, node->constvalue, node->consttype);
M
 
Marc G. Fournier 已提交
689 690 691

	appendStringInfo(str, " :constbyval %s ", 
			node->constbyval ? "true" : "false");
692 693 694
}

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

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

712 713 714 715 716 717
/*
 *	SubLink
 */
static void
_outSubLink(StringInfo str, SubLink *node)
{
M
 
Marc G. Fournier 已提交
718 719 720 721
	appendStringInfo(str, 
			" SUBLINK :subLinkType %d :useor %s :lefthand ",
			node->subLinkType,
			node->useor ? "true" : "false");
722
	_outNode(str, node->lefthand);
M
 
Marc G. Fournier 已提交
723

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

727 728 729 730
	appendStringInfo(str, " :subselect ");
	_outNode(str, node->subselect);
}

731
/*
732
 *	Array is a subclass of Expr
733 734
 */
static void
B
Bruce Momjian 已提交
735
_outArray(StringInfo str, Array *node)
736
{
737
	int			i;
738

M
 
Marc G. Fournier 已提交
739 740 741 742 743 744
	appendStringInfo(str, 
			" ARRAY :arrayelemtype %u :arrayelemlength %d :arrayelembyval %c ",
			node->arrayelemtype, 
			node->arrayelemlength,
			node->arrayelembyval ? 't' : 'f');

M
 
Marc G. Fournier 已提交
745
	appendStringInfo(str, " :arrayndim %d :arraylow ", node->arrayndim);
746 747
	for (i = 0; i < node->arrayndim; i++)
	{
M
 
Marc G. Fournier 已提交
748
		appendStringInfo(str, " %d ", node->arraylow.indx[i]);
749
	}
750
	appendStringInfo(str, " :arrayhigh ");
751 752
	for (i = 0; i < node->arrayndim; i++)
	{
M
 
Marc G. Fournier 已提交
753
		appendStringInfo(str, " %d ", node->arrayhigh.indx[i]);
754
	}
M
 
Marc G. Fournier 已提交
755
	appendStringInfo(str, " :arraylen %d ", node->arraylen);
756 757 758
}

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

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

774
	appendStringInfo(str, " :reflowerindex ");
775 776
	_outNode(str, node->reflowerindexpr);

777
	appendStringInfo(str, " :refexpr ");
778 779
	_outNode(str, node->refexpr);

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

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

	appendStringInfo(str, " :func_planlist ");
	_outNode(str, node->func_planlist);
803 804 805
}

/*
806
 *	Oper is a subclass of Expr
807 808
 */
static void
809
_outOper(StringInfo str, Oper *node)
810
{
M
 
Marc G. Fournier 已提交
811 812 813 814 815
	appendStringInfo(str, 
			" OPER :opno %u :opid %u :opresulttype %u ",
			node->opno,
			node->opid,
			node->opresulttype);
816 817 818
}

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

	appendStringInfo(str, " :param_tlist ");
	_outNode(str, node->param_tlist);
833 834 835
}

/*
836
 *	Stuff from execnodes.h
837 838 839
 */

/*
840
 *	EState is a subclass of Node.
841 842
 */
static void
843
_outEState(StringInfo str, EState *node)
844
{
M
 
Marc G. Fournier 已提交
845 846 847
	appendStringInfo(str, 
			" ESTATE :direction %d :range_table ",
			node->es_direction);
848 849
	_outNode(str, node->es_range_table);

M
 
Marc G. Fournier 已提交
850
	appendStringInfo(str, " :result_relation_info @ 0x%x ",
851
			(int) (node->es_result_relation_info));
852 853 854
}

/*
855
 *	Stuff from relation.h
856 857
 */
static void
858
_outRelOptInfo(StringInfo str, RelOptInfo * node)
859
{
M
 
Marc G. Fournier 已提交
860
	appendStringInfo(str, " RELOPTINFO :relids ");
861 862
	_outIntList(str, node->relids);

M
 
Marc G. Fournier 已提交
863 864 865 866 867 868 869
	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);
870 871
	_outNode(str, node->targetlist);

872
	appendStringInfo(str, " :pathlist ");
873 874 875 876 877 878 879 880
	_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 已提交
881
	appendStringInfo(str, 
882
			" :unorderedpath @ 0x%x :cheapestpath @ 0x%x :pruneable %s :restrictinfo ",
M
 
Marc G. Fournier 已提交
883 884 885
			(int) node->unorderedpath,
			(int) node->cheapestpath,
			node->pruneable ? "true" : "false");
886
	_outNode(str, node->restrictinfo);
887

888
	appendStringInfo(str, " :joininfo ");
889 890
	_outNode(str, node->joininfo);

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

/*
896
 *	TargetEntry is a subclass of Node.
897 898
 */
static void
899
_outTargetEntry(StringInfo str, TargetEntry *node)
900
{
M
 
Marc G. Fournier 已提交
901
	appendStringInfo(str, " TARGETENTRY :resdom ");
902 903
	_outNode(str, node->resdom);

904 905
	appendStringInfo(str, " :expr ");
	_outNode(str, node->expr);
906
}
907 908

static void
909
_outRangeTblEntry(StringInfo str, RangeTblEntry *node)
910
{
M
 
Marc G. Fournier 已提交
911 912
	appendStringInfo(str, 
			" RTE :relname %s :refname %s :relid %u :inh %s :inFromCl %s :skipAcl %s",
913 914
			stringStringInfo(node->relname),
			stringStringInfo(node->refname),
M
 
Marc G. Fournier 已提交
915 916 917 918
			node->relid,
			node->inh ? "true" : "false",
			node->inFromCl ? "true" : "false",
			node->skipAcl ? "true" : "false");
919
}
920

921 922 923 924 925 926
static void
_outRowMark(StringInfo str, RowMark *node)
{
	appendStringInfo(str, " ROWMARK :rti %u :info %u", node->rti, node->info);
}

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

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

951
	appendStringInfo(str, " :indexid ");
952 953
	_outIntList(str, node->indexid);

954
	appendStringInfo(str, " :indexqual ");
955
	_outNode(str, node->indexqual);
956 957 958
}

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

970 971
	appendStringInfo(str, " :pathinfo ");
	_outNode(str, node->pathinfo);
972 973 974 975 976 977

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

M
 
Marc G. Fournier 已提交
978 979 980 981 982
	appendStringInfo(str, 
			" :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x :outjoincost %f :joinid ",
			(int) node->outerjoinpath,
			(int) node->innerjoinpath,
			node->path.outerjoincost);
983
	_outIntList(str, node->path.joinid);
984 985 986
}

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

998 999
	appendStringInfo(str, " :pathinfo ");
	_outNode(str, node->jpath.pathinfo);
1000 1001 1002 1003 1004 1005

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

M
 
Marc G. Fournier 已提交
1006 1007 1008 1009 1010
	appendStringInfo(str, 
			" :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x :outerjoincost %f :joinid ",
			(int) node->jpath.outerjoinpath,
			(int) node->jpath.innerjoinpath,
			(int) node->jpath.path.outerjoincost);
1011 1012
	_outIntList(str, node->jpath.path.joinid);

1013
	appendStringInfo(str, " :path_mergeclauses ");
1014 1015
	_outNode(str, node->path_mergeclauses);

1016
	appendStringInfo(str, " :outersortkeys ");
1017 1018
	_outNode(str, node->outersortkeys);

1019
	appendStringInfo(str, " :innersortkeys ");
1020
	_outNode(str, node->innersortkeys);
1021 1022 1023
}

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

1035 1036
	appendStringInfo(str, " :pathinfo ");
	_outNode(str, node->jpath.pathinfo);
1037 1038 1039 1040 1041 1042

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

M
 
Marc G. Fournier 已提交
1043 1044 1045 1046 1047
	appendStringInfo(str, 
			" :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x :outerjoincost %f :joinid ",
			(int) node->jpath.outerjoinpath,
			(int) node->jpath.innerjoinpath,
			node->jpath.path.outerjoincost);
1048 1049
	_outIntList(str, node->jpath.path.joinid);

1050
	appendStringInfo(str, " :path_hashclauses ");
1051 1052
	_outNode(str, node->path_hashclauses);

1053
	appendStringInfo(str, " :outerhashkeys ");
1054 1055
	_outNode(str, node->outerhashkeys);

1056
	appendStringInfo(str, " :innerhashkeys ");
1057
	_outNode(str, node->innerhashkeys);
1058 1059 1060
}

/*
1061
 *	OrderKey is a subclass of Node.
1062 1063
 */
static void
1064
_outOrderKey(StringInfo str, OrderKey *node)
1065
{
M
 
Marc G. Fournier 已提交
1066 1067 1068 1069
	appendStringInfo(str, 
			" ORDERKEY :attribute_number %d :array_index %d ",
			node->attribute_number,
			node->array_index);
1070 1071 1072
}

/*
1073
 *	JoinKey is a subclass of Node.
1074 1075
 */
static void
1076
_outJoinKey(StringInfo str, JoinKey *node)
1077
{
M
 
Marc G. Fournier 已提交
1078
	appendStringInfo(str, " JOINKEY :outer ");
1079 1080
	_outNode(str, node->outer);

1081
	appendStringInfo(str, " :inner ");
1082 1083
	_outNode(str, node->inner);

1084 1085 1086
}

/*
1087
 *	MergeOrder is a subclass of Node.
1088 1089
 */
static void
1090
_outMergeOrder(StringInfo str, MergeOrder *node)
1091
{
M
 
Marc G. Fournier 已提交
1092 1093 1094 1095 1096
	appendStringInfo(str, 
			" MERGEORDER :join_operator %d :left_operator %d :right_operator %d ",
			node->join_operator,
			node->left_operator,
			node->right_operator);
1097

M
 
Marc G. Fournier 已提交
1098 1099 1100 1101
	appendStringInfo(str, 
			" :left_type %d :right_type %d ",
			node->left_type, 
			node->right_type);
1102 1103 1104
}

/*
1105
 *	RestrictInfo is a subclass of Node.
1106 1107
 */
static void
1108
_outRestrictInfo(StringInfo str, RestrictInfo * node)
1109
{
B
Bruce Momjian 已提交
1110
	appendStringInfo(str, " RESTRICTINFO :clause ");
1111 1112
	_outNode(str, node->clause);

M
 
Marc G. Fournier 已提交
1113 1114 1115 1116
	appendStringInfo(str, 
			" :selectivity %f :notclause %s :indexids ",
			node->selectivity,
			node->notclause ? "true" : "false");
1117 1118
	_outNode(str, node->indexids);

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

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

1124 1125 1126
}

/*
1127
 *	JoinMethod is a subclass of Node.
1128 1129
 */
static void
1130
_outJoinMethod(StringInfo str, JoinMethod *node)
1131
{
M
 
Marc G. Fournier 已提交
1132
	appendStringInfo(str, " JOINMETHOD :jmkeys ");
1133 1134
	_outNode(str, node->jmkeys);

1135
	appendStringInfo(str, " :clauses ");
1136
	_outNode(str, node->clauses);
1137 1138 1139
}

/*
1140
 * HashInfo is a subclass of JoinMethod.
1141 1142
 */
static void
1143
_outHashInfo(StringInfo str, HashInfo *node)
1144
{
M
 
Marc G. Fournier 已提交
1145
	appendStringInfo(str, " HASHINFO :hashop %u :jmkeys ", node->hashop);
1146 1147
	_outNode(str, node->jmethod.jmkeys);

1148
	appendStringInfo(str, " :clauses ");
1149
	_outNode(str, node->jmethod.clauses);
1150 1151 1152
}

/*
1153
 *	JoinInfo is a subclass of Node.
1154 1155
 */
static void
1156
_outJoinInfo(StringInfo str, JoinInfo * node)
1157
{
M
 
Marc G. Fournier 已提交
1158
	appendStringInfo(str, " JINFO :otherrels ");
1159 1160
	_outIntList(str, node->otherrels);

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

M
 
Marc G. Fournier 已提交
1164 1165 1166
	appendStringInfo(str, " :mergejoinable %s :hashjoinable %s ",
			node->mergejoinable ? "true" : "false",
			node->hashjoinable ? "true" : "false");
1167 1168 1169 1170 1171 1172 1173 1174
}

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

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

static void
1225
_outIter(StringInfo str, Iter *node)
1226
{
M
 
Marc G. Fournier 已提交
1227
	appendStringInfo(str, " ITER :iterexpr ");
1228
	_outNode(str, node->iterexpr);
1229 1230 1231
}

static void
1232
_outStream(StringInfo str, Stream *node)
1233
{
M
 
Marc G. Fournier 已提交
1234 1235 1236 1237 1238 1239
	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);
1240

M
 
Marc G. Fournier 已提交
1241 1242 1243 1244 1245 1246
	appendStringInfo(str, 
			" :downstream @ 0x%x :groupup %d :groupcost %f :groupsel %f ",
			(int) node->downstream,
			node->groupup,
			node->groupcost,
			node->groupsel);
1247
}
1248

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

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

1303 1304 1305
static void
_outIdent(StringInfo str, Ident *node)
{
1306
	appendStringInfo(str, " IDENT \"%s\" ", stringStringInfo(node->name));
1307 1308 1309 1310 1311 1312
	return;
}

static void
_outAConst(StringInfo str, A_Const *node)
{
1313
	appendStringInfo(str, "CONST ");
1314 1315 1316 1317
	_outValue(str, &(node->val));
	return;
}

T
Thomas G. Lockhart 已提交
1318 1319 1320
static void
_outConstraint(StringInfo str, Constraint *node)
{
M
 
Marc G. Fournier 已提交
1321
	appendStringInfo(str," %s :type", stringStringInfo(node->name));
T
Thomas G. Lockhart 已提交
1322 1323 1324 1325

	switch (node->contype)
	{
		case CONSTR_PRIMARY:
1326
			appendStringInfo(str, " PRIMARY KEY ");
T
Thomas G. Lockhart 已提交
1327 1328 1329 1330
			_outNode(str, node->keys);
			break;

		case CONSTR_CHECK:
M
 
Marc G. Fournier 已提交
1331
			appendStringInfo(str, " CHECK %s", stringStringInfo(node->def));
T
Thomas G. Lockhart 已提交
1332 1333 1334
			break;

		case CONSTR_DEFAULT:
M
 
Marc G. Fournier 已提交
1335
			appendStringInfo(str, " DEFAULT %s", stringStringInfo(node->def));
T
Thomas G. Lockhart 已提交
1336 1337 1338
			break;

		case CONSTR_NOTNULL:
1339
			appendStringInfo(str, " NOT NULL ");
T
Thomas G. Lockhart 已提交
1340 1341 1342
			break;

		case CONSTR_UNIQUE:
1343
			appendStringInfo(str, " UNIQUE ");
T
Thomas G. Lockhart 已提交
1344 1345 1346 1347
			_outNode(str, node->keys);
			break;

		default:
1348
			appendStringInfo(str, "<unrecognized constraint>");
T
Thomas G. Lockhart 已提交
1349 1350 1351 1352 1353 1354 1355 1356
			break;
	}
	return;
}

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

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

T
Thomas G. Lockhart 已提交
1363 1364 1365 1366 1367 1368
	return;
}

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

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

T
Thomas G. Lockhart 已提交
1375 1376 1377
	return;
}

1378 1379
/*
 * _outNode -
1380
 *	  converts a Node into ascii string and append it to 'str'
1381 1382 1383 1384
 */
static void
_outNode(StringInfo str, void *obj)
{
1385 1386
	if (obj == NULL)
	{
B
Bruce Momjian 已提交
1387
		appendStringInfo(str, "<>");
1388 1389
		return;
	}
1390

1391 1392
	if (nodeTag(obj) == T_List)
	{
1393
		List	   *l;
1394 1395 1396 1397 1398 1399 1400 1401 1402

		appendStringInfo(str, "(");
		foreach(l, (List *) obj)
		{
			_outNode(str, lfirst(l));
			if (lnext(l))
				appendStringInfo(str, " ");
		}
		appendStringInfo(str, ")");
1403
	}
1404 1405 1406 1407 1408
	else
	{
		appendStringInfo(str, "{");
		switch (nodeTag(obj))
		{
1409 1410 1411 1412 1413 1414 1415 1416 1417 1418
			case T_CreateStmt:
				_outCreateStmt(str, obj);
				break;
			case T_IndexStmt:
				_outIndexStmt(str, obj);
				break;

			case T_ColumnDef:
				_outColumnDef(str, obj);
				break;
1419 1420 1421
			case T_TypeName:
				_outTypeName(str, obj);
				break;
1422 1423 1424 1425
			case T_IndexElem:
				_outIndexElem(str, obj);
				break;

1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436
#ifdef PARSEDEBUG
			case T_VariableSetStmt:
				break;
			case T_SelectStmt:
				_outSelectStmt(str, obj);
				break;
			case T_FuncCall:
				_outFuncCall(str, obj);
				break;
#endif

1437 1438 1439
			case T_Query:
				_outQuery(str, obj);
				break;
1440 1441 1442 1443 1444
			case T_SortClause:
				_outSortClause(str, obj);
				break;
			case T_GroupClause:
				_outGroupClause(str, obj);
1445
				break;
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 1488 1489 1490 1491 1492 1493
			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 已提交
1494 1495 1496
			case T_SubPlan:
				_outSubPlan(str, obj);
				break;
1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514
			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 已提交
1515 1516
			case T_Aggref:
				_outAggref(str, obj);
1517
				break;
1518 1519 1520
			case T_SubLink:
				_outSubLink(str, obj);
				break;
1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538
			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 已提交
1539
			case T_RelOptInfo:
B
Bruce Momjian 已提交
1540
				_outRelOptInfo(str, obj);
1541 1542 1543 1544 1545 1546 1547
				break;
			case T_TargetEntry:
				_outTargetEntry(str, obj);
				break;
			case T_RangeTblEntry:
				_outRangeTblEntry(str, obj);
				break;
1548 1549 1550
			case T_RowMark:
				_outRowMark(str, obj);
				break;
1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574
			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;
1575 1576
			case T_RestrictInfo:
				_outRestrictInfo(str, obj);
1577 1578 1579 1580
				break;
			case T_JoinMethod:
				_outJoinMethod(str, obj);
				break;
1581 1582
			case T_HashInfo:
				_outHashInfo(str, obj);
1583
				break;
1584 1585
			case T_JoinInfo:
				_outJoinInfo(str, obj);
1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597
				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;
1598 1599 1600 1601 1602 1603 1604 1605 1606
			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 已提交
1607 1608 1609 1610 1611 1612 1613 1614 1615
			case T_Constraint:
				_outConstraint(str, obj);
				break;
			case T_CaseExpr:
				_outCaseExpr(str, obj);
				break;
			case T_CaseWhen:
				_outCaseWhen(str, obj);
				break;
1616
			default:
B
Bruce Momjian 已提交
1617
				elog(NOTICE, "_outNode: don't know how to print type %d ",
1618 1619
					 nodeTag(obj));
				break;
1620 1621
		}
		appendStringInfo(str, "}");
1622
	}
1623
	return;
1624 1625 1626 1627
}

/*
 * nodeToString -
1628
 *	   returns the ascii representation of the Node
1629
 */
1630
char *
1631 1632
nodeToString(void *obj)
{
1633 1634
	StringInfo	str;
	char	   *s;
1635 1636 1637 1638 1639 1640 1641 1642 1643 1644

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

	return s;
1645
}