outfuncs.c 41.7 KB
Newer Older
1 2 3
/*-------------------------------------------------------------------------
 *
 * outfuncs.c--
4
 *	  routines to convert a node to ascii representation
5 6 7 8 9
 *
 * Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
10
 *	  $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.39 1998/07/14 01:45:24 momjian Exp $
11 12
 *
 * NOTES
13 14 15 16 17
 *	  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.
18
 *
19 20 21
 *	  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.)
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
 *
 *-------------------------------------------------------------------------
 */
#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"

48 49 50 51
#ifdef PARSEDEBUG
#include "../parse.h"
#endif

52 53
static void _outDatum(StringInfo str, Datum value, Oid type);
static void _outNode(StringInfo str, void *obj);
54 55 56

/*
 * _outIntList -
57
 *	   converts a List of integers
58
 */
59
static void
60
_outIntList(StringInfo str, List *list)
61
{
62 63
	List	   *l;
	char		buf[500];
64

65 66 67
	appendStringInfo(str, "(");
	foreach(l, list)
	{
B
Bruce Momjian 已提交
68
		sprintf(buf, " %d ", (int) lfirst(l));
69 70 71
		appendStringInfo(str, buf);
	}
	appendStringInfo(str, ")");
72 73
}

74 75 76
static void
_outCreateStmt(StringInfo str, CreateStmt *node)
{
77
	appendStringInfo(str, " CREATE ");
78

79 80
	appendStringInfo(str, " :relname ");
	appendStringInfo(str, node->relname);
81
	appendStringInfo(str, " :columns ");
82
	_outNode(str, node->tableElts);
83
	appendStringInfo(str, " :inhRelnames ");
84
	_outNode(str, node->inhRelnames);
85
	appendStringInfo(str, " :constraints ");
86
	_outNode(str, node->constraints);
87
}
88 89 90 91

static void
_outIndexStmt(StringInfo str, IndexStmt *node)
{
92
	appendStringInfo(str, " INDEX ");
93 94 95 96 97 98 99 100

	appendStringInfo(str, " :idxname ");
	appendStringInfo(str, node->idxname);
	appendStringInfo(str, " :relname ");
	appendStringInfo(str, node->relname);
	appendStringInfo(str, " :accessMethod ");
	appendStringInfo(str, node->accessMethod);
	appendStringInfo(str, " :indexParams ");
101
	_outNode(str, node->indexParams);
102 103 104 105 106 107 108
	appendStringInfo(str, " :withClause ");
	_outNode(str, node->withClause);
	appendStringInfo(str, " :whereClause ");
	_outNode(str, node->whereClause);
	appendStringInfo(str, " :rangetable ");
	_outNode(str, node->rangetable);
	appendStringInfo(str, " :lossy ");
109
	appendStringInfo(str, (node->lossy ? "true" : "false"));
110
	appendStringInfo(str, " :unique ");
111
	appendStringInfo(str, (node->unique ? "true" : "false"));
112
}
113

114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
#ifdef PARSEDEBUG
static void
_outSelectStmt(StringInfo str, SelectStmt *node)
{
	appendStringInfo(str, "SELECT");

	appendStringInfo(str, " :where ");
	_outNode(str, node->whereClause);
}

static void
_outFuncCall(StringInfo str, FuncCall *node)
{
	appendStringInfo(str, "FUNCTION ");
	appendStringInfo(str, node->funcname);
	appendStringInfo(str, " :args ");
	_outNode(str, node->args);
}
#endif

134 135 136
static void
_outColumnDef(StringInfo str, ColumnDef *node)
{
137
	appendStringInfo(str, " COLUMNDEF ");
138

139 140 141
	appendStringInfo(str, " :colname ");
	appendStringInfo(str, node->colname);
	appendStringInfo(str, " :typename ");
142
	_outNode(str, node->typename);
143
	appendStringInfo(str, " :is_not_null ");
144
	appendStringInfo(str, (node->is_not_null ? "true" : "false"));
145 146
	appendStringInfo(str, " :defval ");
	appendStringInfo(str, node->defval);
147
	appendStringInfo(str, " :constraints ");
148
	_outNode(str, node->constraints);
149 150 151 152 153
}

static void
_outTypeName(StringInfo str, TypeName *node)
{
154 155
	char		buf[500];

156
	appendStringInfo(str, " TYPENAME ");
157 158 159 160 161 162 163

	appendStringInfo(str, " :name ");
	appendStringInfo(str, node->name);
	appendStringInfo(str, " :timezone ");
	appendStringInfo(str, (node->timezone ? "true" : "false"));
	appendStringInfo(str, " :setof ");
	appendStringInfo(str, (node->setof ? "true" : "false"));
164
	appendStringInfo(str, " :typmod ");
165
	sprintf(buf, " %d ", node->typmod);
166
	appendStringInfo(str, buf);
167 168 169
	appendStringInfo(str, " :arrayBounds ");
	_outNode(str, node->arrayBounds);
}
170 171 172 173

static void
_outIndexElem(StringInfo str, IndexElem *node)
{
174
	appendStringInfo(str, " INDEXELEM ");
175

176 177 178 179 180 181
	appendStringInfo(str, " :name ");
	appendStringInfo(str, node->name);
	appendStringInfo(str, " :args ");
	_outNode(str, node->args);
	appendStringInfo(str, " :class ");
	appendStringInfo(str, node->class);
182
	appendStringInfo(str, " :tname ");
183
	_outNode(str, node->tname);
184
}
185

186
static void
187
_outQuery(StringInfo str, Query *node)
188
{
189
	char		buf[500];
190

191
	appendStringInfo(str, " QUERY ");
192

193
	appendStringInfo(str, " :command ");
194
	sprintf(buf, " %d ", node->commandType);
195 196
	appendStringInfo(str, buf);

197 198 199 200 201
	if (node->utilityStmt)
	{
		switch (nodeTag(node->utilityStmt))
		{
			case T_CreateStmt:
202 203
				appendStringInfo(str, " :create ");
				appendStringInfo(str, ((CreateStmt *) (node->utilityStmt))->relname);
204 205 206 207
				_outNode(str, node->utilityStmt);
				break;

			case T_IndexStmt:
208 209 210 211
				appendStringInfo(str, " :index ");
				appendStringInfo(str, ((IndexStmt *) (node->utilityStmt))->idxname);
				appendStringInfo(str, " on ");
				appendStringInfo(str, ((IndexStmt *) (node->utilityStmt))->relname);
212 213 214 215
				_outNode(str, node->utilityStmt);
				break;

			case T_NotifyStmt:
216 217
				appendStringInfo(str, " :utility ");
				appendStringInfo(str, ((NotifyStmt *) (node->utilityStmt))->relname);
218 219 220
				break;

			default:
221
				appendStringInfo(str, " :utility ? ");
222 223
		}
	}
224
	else
225
	{
226 227
		appendStringInfo(str, " :utility ");
		appendStringInfo(str, NULL);
228
	}
229

230 231 232 233 234 235
	appendStringInfo(str, " :resultRelation ");
	sprintf(buf, " %d ", node->resultRelation);
	appendStringInfo(str, buf);
	appendStringInfo(str, " :into ");
	appendStringInfo(str, node->into);
	appendStringInfo(str, " :isPortal ");
236
	appendStringInfo(str, (node->isPortal ? "true" : "false"));
237
	appendStringInfo(str, " :isBinary ");
238
	appendStringInfo(str, (node->isBinary ? "true" : "false"));
239
	appendStringInfo(str, " :unionall ");
240
	appendStringInfo(str, (node->unionall ? "true" : "false"));
241 242 243 244 245
	appendStringInfo(str, " :unique ");
	appendStringInfo(str, node->uniqueFlag);
	appendStringInfo(str, " :sortClause ");
	_outNode(str, node->sortClause);
	appendStringInfo(str, " :rtable ");
246
	_outNode(str, node->rtable);
247
	appendStringInfo(str, " :targetlist ");
248
	_outNode(str, node->targetList);
249
	appendStringInfo(str, " :qual ");
250
	_outNode(str, node->qual);
251 252 253
	appendStringInfo(str, " :groupClause ");
	_outNode(str, node->groupClause);
	appendStringInfo(str, " :havingQual ");
254
	_outNode(str, node->havingQual);
255 256
	appendStringInfo(str, " :hasAggs ");
	appendStringInfo(str, (node->hasAggs ? "true" : "false"));
257 258
	appendStringInfo(str, " :hasSubLinks ");
	appendStringInfo(str, (node->hasSubLinks ? "true" : "false"));
259
	appendStringInfo(str, " :unionClause ");
260
	_outNode(str, node->unionClause);
261 262 263
}

static void
264
_outSortClause(StringInfo str, SortClause *node)
265 266
{
	char		buf[500];
267

268
	appendStringInfo(str, " SORTCLAUSE ");
269

270 271 272
	appendStringInfo(str, " :resdom ");
	_outNode(str, node->resdom);
	appendStringInfo(str, " :opoid ");
273
	sprintf(buf, " %u ", node->opoid);
274 275 276 277 278 279 280
	appendStringInfo(str, buf);
}

static void
_outGroupClause(StringInfo str, GroupClause *node)
{
	char		buf[500];
281

282
	appendStringInfo(str, " GROUPCLAUSE ");
283 284 285 286

	appendStringInfo(str, " :entry ");
	_outNode(str, node->entry);
	appendStringInfo(str, " :grpOpoid ");
287
	sprintf(buf, " %u ", node->grpOpoid);
288
	appendStringInfo(str, buf);
289 290 291 292 293 294
}

/*
 * print the basic stuff of all nodes that inherit from Plan
 */
static void
295
_outPlanInfo(StringInfo str, Plan *node)
296
{
297
	char		buf[500];
298

B
Bruce Momjian 已提交
299
	sprintf(buf, " :cost %g ", node->cost);
300
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
301
	sprintf(buf, " :size %d ", node->plan_size);
302
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
303
	sprintf(buf, " :width %d ", node->plan_width);
304
	appendStringInfo(str, buf);
305
	appendStringInfo(str, " :state ");
306
	appendStringInfo(str, node->state ? "not-NULL" : "<>");
307
	appendStringInfo(str, " :qptargetlist ");
308
	_outNode(str, node->targetlist);
309
	appendStringInfo(str, " :qpqual ");
310
	_outNode(str, node->qual);
311
	appendStringInfo(str, " :lefttree ");
312
	_outNode(str, node->lefttree);
313
	appendStringInfo(str, " :righttree ");
314
	_outNode(str, node->righttree);
V
Vadim B. Mikheev 已提交
315 316 317 318 319 320 321 322
	appendStringInfo(str, " :extprm ");
	_outIntList(str, node->extParam);
	appendStringInfo(str, " :locprm ");
	_outIntList(str, node->locParam);
	appendStringInfo(str, " :initplan ");
	_outNode(str, node->initPlan);
	sprintf(buf, " :nprm %d ", node->nParamExec);
	appendStringInfo(str, buf);
323 324 325
}

/*
326
 *	Stuff from plannodes.h
327 328
 */
static void
329
_outPlan(StringInfo str, Plan *node)
330
{
331
	appendStringInfo(str, " PLAN ");
332
	_outPlanInfo(str, (Plan *) node);
333 334 335
}

static void
336
_outResult(StringInfo str, Result *node)
337
{
338
	appendStringInfo(str, " RESULT ");
339 340
	_outPlanInfo(str, (Plan *) node);

341
	appendStringInfo(str, " :resconstantqual ");
342 343
	_outNode(str, node->resconstantqual);

344 345 346
}

/*
347
 *	Append is a subclass of Plan.
348 349
 */
static void
B
Bruce Momjian 已提交
350
_outAppend(StringInfo str, Append *node)
351
{
352
	char		buf[500];
353

354
	appendStringInfo(str, " APPEND ");
355 356
	_outPlanInfo(str, (Plan *) node);

357
	appendStringInfo(str, " :unionplans ");
358 359
	_outNode(str, node->unionplans);

360 361 362
	appendStringInfo(str, " :unionrts ");
	_outNode(str, node->unionrts);

B
Bruce Momjian 已提交
363
	sprintf(buf, " :unionrelid %d ", node->unionrelid);
364 365
	appendStringInfo(str, buf);

366
	appendStringInfo(str, " :unionrtentries ");
367 368
	_outNode(str, node->unionrtentries);

369 370 371
}

/*
372
 *	Join is a subclass of Plan
373 374
 */
static void
375
_outJoin(StringInfo str, Join *node)
376
{
377
	appendStringInfo(str, " JOIN ");
378 379
	_outPlanInfo(str, (Plan *) node);

380 381 382
}

/*
383
 *	NestLoop is a subclass of Join
384 385
 */
static void
386
_outNestLoop(StringInfo str, NestLoop *node)
387
{
388
	appendStringInfo(str, " NESTLOOP ");
389
	_outPlanInfo(str, (Plan *) node);
390 391 392
}

/*
393
 *	MergeJoin is a subclass of Join
394 395
 */
static void
396
_outMergeJoin(StringInfo str, MergeJoin *node)
397
{
398
	char		buf[500];
399

400
	appendStringInfo(str, " MERGEJOIN ");
401 402
	_outPlanInfo(str, (Plan *) node);

403
	appendStringInfo(str, " :mergeclauses ");
404 405
	_outNode(str, node->mergeclauses);

B
Bruce Momjian 已提交
406
	sprintf(buf, " :mergesortop %u ", node->mergesortop);
407 408
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
409
	sprintf(buf, " :mergerightorder %u ", node->mergerightorder[0]);
410 411
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
412
	sprintf(buf, " :mergeleftorder %u ", node->mergeleftorder[0]);
413
	appendStringInfo(str, buf);
414 415 416
}

/*
417
 *	HashJoin is a subclass of Join.
418 419
 */
static void
420
_outHashJoin(StringInfo str, HashJoin *node)
421
{
422
	char		buf[500];
423

424
	appendStringInfo(str, " HASHJOIN ");
425 426
	_outPlanInfo(str, (Plan *) node);

427
	appendStringInfo(str, " :hashclauses ");
428 429
	_outNode(str, node->hashclauses);

B
Bruce Momjian 已提交
430
	sprintf(buf, " :hashjoinop %u ", node->hashjoinop);
431
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
432
	sprintf(buf, " :hashjointable 0x%x ", (int) node->hashjointable);
433
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
434
	sprintf(buf, " :hashjointablekey %d ", node->hashjointablekey);
435
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
436
	sprintf(buf, " :hashjointablesize %d ", node->hashjointablesize);
437
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
438
	sprintf(buf, " :hashdone %d ", node->hashdone);
439
	appendStringInfo(str, buf);
440 441
}

V
Vadim B. Mikheev 已提交
442 443 444 445 446
static void
_outSubPlan(StringInfo str, SubPlan *node)
{
	char		buf[500];

447
	appendStringInfo(str, " SUBPLAN ");
V
Vadim B. Mikheev 已提交
448 449 450 451 452 453 454
	appendStringInfo(str, " :plan ");
	_outNode(str, node->plan);
	sprintf(buf, " :planid %u ", node->plan_id);
	appendStringInfo(str, buf);
	appendStringInfo(str, " :rtable ");
	_outNode(str, node->rtable);
	appendStringInfo(str, " :setprm ");
455
	_outIntList(str, node->setParam);
V
Vadim B. Mikheev 已提交
456
	appendStringInfo(str, " :parprm ");
457
	_outIntList(str, node->parParam);
V
Vadim B. Mikheev 已提交
458 459 460 461
	appendStringInfo(str, " :slink ");
	_outNode(str, node->sublink);
}

462
/*
463
 *	Scan is a subclass of Node
464 465
 */
static void
466
_outScan(StringInfo str, Scan *node)
467
{
468
	char		buf[500];
469

470
	appendStringInfo(str, " SCAN ");
471 472
	_outPlanInfo(str, (Plan *) node);

B
Bruce Momjian 已提交
473
	sprintf(buf, " :scanrelid %d ", node->scanrelid);
474 475
	appendStringInfo(str, buf);

476 477 478
}

/*
479
 *	SeqScan is a subclass of Scan
480 481
 */
static void
482
_outSeqScan(StringInfo str, SeqScan *node)
483
{
484
	char		buf[500];
485

486
	appendStringInfo(str, " SEQSCAN ");
487 488
	_outPlanInfo(str, (Plan *) node);

B
Bruce Momjian 已提交
489
	sprintf(buf, " :scanrelid %d ", node->scanrelid);
490 491 492
	appendStringInfo(str, buf);


493 494 495
}

/*
496
 *	IndexScan is a subclass of Scan
497 498
 */
static void
499
_outIndexScan(StringInfo str, IndexScan *node)
500
{
501
	char		buf[500];
502

503
	appendStringInfo(str, " INDEXSCAN ");
504 505
	_outPlanInfo(str, (Plan *) node);

B
Bruce Momjian 已提交
506
	sprintf(buf, " :scanrelid %d ", node->scan.scanrelid);
507 508
	appendStringInfo(str, buf);

509
	appendStringInfo(str, " :indxid ");
510 511
	_outIntList(str, node->indxid);

512
	appendStringInfo(str, " :indxqual ");
513 514
	_outNode(str, node->indxqual);

515 516 517
}

/*
518
 *	Temp is a subclass of Plan
519 520
 */
static void
521
_outTemp(StringInfo str, Temp *node)
522
{
523
	char		buf[500];
524

525
	appendStringInfo(str, " TEMP ");
526 527
	_outPlanInfo(str, (Plan *) node);

B
Bruce Momjian 已提交
528
	sprintf(buf, " :tempid %u ", node->tempid);
529
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
530
	sprintf(buf, " :keycount %d ", node->keycount);
531 532
	appendStringInfo(str, buf);

533 534 535
}

/*
536
 *	Sort is a subclass of Temp
537 538
 */
static void
539
_outSort(StringInfo str, Sort *node)
540
{
541
	char		buf[500];
542

543
	appendStringInfo(str, " SORT ");
544 545
	_outPlanInfo(str, (Plan *) node);

B
Bruce Momjian 已提交
546
	sprintf(buf, " :tempid %u ", node->tempid);
547
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
548
	sprintf(buf, " :keycount %d ", node->keycount);
549 550
	appendStringInfo(str, buf);

551 552 553
}

static void
B
Bruce Momjian 已提交
554
_outAgg(StringInfo str, Agg *node)
555
{
556

557
	appendStringInfo(str, " AGG ");
558 559
	_outPlanInfo(str, (Plan *) node);

560 561
	appendStringInfo(str, " :aggs ");
	_outNode(str, node->aggs);
562 563 564
}

static void
565
_outGroup(StringInfo str, Group *node)
566
{
567
	char		buf[500];
568

569
	appendStringInfo(str, " GRP ");
570 571 572 573 574
	_outPlanInfo(str, (Plan *) node);

	/* the actual Group fields */
	sprintf(buf, " :numCols %d ", node->numCols);
	appendStringInfo(str, buf);
575 576
	appendStringInfo(str, " :tuplePerGroup ");
	appendStringInfo(str, node->tuplePerGroup ? "true" : "false");
577
}
578 579


580
/*
581
 *	For some reason, unique is a subclass of Temp.
582 583
 */
static void
584
_outUnique(StringInfo str, Unique *node)
585
{
586
	char		buf[500];
587

588
	appendStringInfo(str, " UNIQUE ");
589 590
	_outPlanInfo(str, (Plan *) node);

B
Bruce Momjian 已提交
591
	sprintf(buf, " :tempid %u ", node->tempid);
592
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
593
	sprintf(buf, " :keycount %d ", node->keycount);
594 595
	appendStringInfo(str, buf);

596 597 598 599
}


/*
600
 *	Hash is a subclass of Temp
601 602
 */
static void
603
_outHash(StringInfo str, Hash *node)
604
{
605
	char		buf[500];
606

607
	appendStringInfo(str, " HASH ");
608 609
	_outPlanInfo(str, (Plan *) node);

610
	appendStringInfo(str, " :hashkey ");
611 612
	_outNode(str, node->hashkey);

B
Bruce Momjian 已提交
613
	sprintf(buf, " :hashtable 0x%x ", (int) (node->hashtable));
614
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
615
	sprintf(buf, " :hashtablekey %d ", node->hashtablekey);
616
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
617
	sprintf(buf, " :hashtablesize %d ", node->hashtablesize);
618
	appendStringInfo(str, buf);
619 620 621
}

static void
622
_outTee(StringInfo str, Tee *node)
623
{
624
	char		buf[500];
625

626
	appendStringInfo(str, " TEE ");
627 628
	_outPlanInfo(str, (Plan *) node);

B
Bruce Momjian 已提交
629
	sprintf(buf, " :leftParent %X ", (int) (node->leftParent));
630
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
631
	sprintf(buf, " :rightParent %X ", (int) (node->rightParent));
632 633
	appendStringInfo(str, buf);

634
	appendStringInfo(str, " :rtentries ");
635
	_outNode(str, node->rtentries);
636 637 638 639 640 641
}



/*****************************************************************************
 *
642
 *	Stuff from primnodes.h.
643 644 645 646 647
 *
 *****************************************************************************/


/*
648
 *	Resdom is a subclass of Node
649 650
 */
static void
651
_outResdom(StringInfo str, Resdom *node)
652
{
653
	char		buf[500];
654

655
	appendStringInfo(str, " RESDOM ");
656
	sprintf(buf, " :resno %d ", node->resno);
657
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
658
	sprintf(buf, " :restype %u ", node->restype);
659
	appendStringInfo(str, buf);
660
	sprintf(buf, " :restypmod %d ", node->restypmod);
661
	appendStringInfo(str, buf);
662
	appendStringInfo(str, " :resname ");
663
	sprintf(buf,"\"%s\"", node->resname); /* fix for SELECT col AS "my name" */
664
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
665
	sprintf(buf, " :reskey %d ", node->reskey);
666
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
667
	sprintf(buf, " :reskeyop %u ", node->reskeyop);
668
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
669
	sprintf(buf, " :resjunk %d ", node->resjunk);
670 671
	appendStringInfo(str, buf);

672 673 674
}

static void
675
_outFjoin(StringInfo str, Fjoin *node)
676
{
677 678
	char		buf[500];
	int			i;
679

680
	appendStringInfo(str, " FJOIN ");
681 682
	appendStringInfo(str, " :initialized ");
	appendStringInfo(str, node->fj_initialized ? "true" : "false");
B
Bruce Momjian 已提交
683
	sprintf(buf, " :nNodes %d ", node->fj_nNodes);
684 685 686 687 688 689 690 691 692 693
	appendStringInfo(str, buf);

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

	sprintf(buf, " :results @  0x%x ", (int) (node->fj_results));
	appendStringInfo(str, buf);

	appendStringInfo(str, " :alwaysdone ");
	for (i = 0; i < node->fj_nNodes; i++)
694
		appendStringInfo(str, (node->fj_alwaysDone[i]) ? "true" : "false");
695 696 697
}

/*
698
 *	Expr is a subclass of Node
699 700
 */
static void
701
_outExpr(StringInfo str, Expr *node)
702
{
703 704
	char		buf[500];
	char	   *opstr = NULL;
705

706
	appendStringInfo(str, " EXPR ");
707

B
Bruce Momjian 已提交
708
	sprintf(buf, " :typeOid %u ", node->typeOid);
709 710 711
	appendStringInfo(str, buf);
	switch (node->opType)
	{
712 713 714 715 716 717 718 719 720 721 722 723 724 725 726
		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 已提交
727 728 729
		case SUBPLAN_EXPR:
			opstr = "subp";
			break;
730
	}
731 732 733
	appendStringInfo(str, " :opType ");
	appendStringInfo(str, opstr);
	appendStringInfo(str, " :oper ");
734
	_outNode(str, node->oper);
735
	appendStringInfo(str, " :args ");
736
	_outNode(str, node->args);
737 738 739
}

/*
740
 *	Var is a subclass of Expr
741 742
 */
static void
743
_outVar(StringInfo str, Var *node)
744
{
745
	char		buf[500];
746

747
	appendStringInfo(str, " VAR ");
B
Bruce Momjian 已提交
748
	sprintf(buf, " :varno %d ", node->varno);
749
	appendStringInfo(str, buf);
750
	sprintf(buf, " :varattno %d ", node->varattno);
751
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
752
	sprintf(buf, " :vartype %u ", node->vartype);
753
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
754
	sprintf(buf, " :vartypmod %d ", node->vartypmod);
755
	appendStringInfo(str, buf);
756 757
	sprintf(buf, " :varlevelsup %u ", node->varlevelsup);
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
758
	sprintf(buf, " :varnoold %d ", node->varnoold);
759
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
760
	sprintf(buf, " :varoattno %d ", node->varoattno);
761
	appendStringInfo(str, buf);
762 763 764
}

/*
765
 *	Const is a subclass of Expr
766 767
 */
static void
768
_outConst(StringInfo str, Const *node)
769
{
770
	char		buf[500];
771

772
	appendStringInfo(str, " CONST ");
B
Bruce Momjian 已提交
773
	sprintf(buf, " :consttype %u ", node->consttype);
774
	appendStringInfo(str, buf);
775
	sprintf(buf, " :constlen %d ", node->constlen);
776
	appendStringInfo(str, buf);
777 778 779
	appendStringInfo(str, " :constisnull ");
	appendStringInfo(str, node->constisnull ? "true" : "false");
	appendStringInfo(str, " :constvalue ");
780
	if (node->constisnull)
B
Bruce Momjian 已提交
781
		appendStringInfo(str, "<>");
782 783
	else
		_outDatum(str, node->constvalue, node->consttype);
784 785
	appendStringInfo(str, " :constbyval ");
	appendStringInfo(str, node->constbyval ? "true" : "false");
786 787 788
}

/*
789
 *	Aggreg
790 791
 */
static void
B
Bruce Momjian 已提交
792
_outAggreg(StringInfo str, Aggreg *node)
793
{
794
	char		buf[500];
795

796
	appendStringInfo(str, " AGGREG ");
797 798
	appendStringInfo(str, " :aggname ");
	appendStringInfo(str, (char *) node->aggname);
B
Bruce Momjian 已提交
799
	sprintf(buf, " :basetype %u ", node->basetype);
800
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
801
	sprintf(buf, " :aggtype %u ", node->aggtype);
802
	appendStringInfo(str, buf);
803 804
	appendStringInfo(str, " :target ");
	_outNode(str, node->target);
B
Bruce Momjian 已提交
805
	sprintf(buf, " :aggno %d ", node->aggno);
806
	appendStringInfo(str, buf);
807 808
	appendStringInfo(str, " :usenulls ");
	appendStringInfo(str, node->usenulls ? "true" : "false");
809 810
}

811 812 813 814 815 816 817 818
/*
 *	SubLink
 */
static void
_outSubLink(StringInfo str, SubLink *node)
{
	char		buf[500];

819
	appendStringInfo(str, " SUBLINK ");
820 821 822 823 824 825 826
	sprintf(buf, " :subLinkType %d ", node->subLinkType);
	appendStringInfo(str, buf);
	appendStringInfo(str, " :useor ");
	appendStringInfo(str, node->useor ? "true" : "false");
	appendStringInfo(str, " :lefthand ");
	_outNode(str, node->lefthand);
	appendStringInfo(str, " :oper ");
B
Bruce Momjian 已提交
827
	_outNode(str, node->oper);
828 829 830 831
	appendStringInfo(str, " :subselect ");
	_outNode(str, node->subselect);
}

832
/*
833
 *	Array is a subclass of Expr
834 835
 */
static void
B
Bruce Momjian 已提交
836
_outArray(StringInfo str, Array *node)
837
{
838 839
	char		buf[500];
	int			i;
840

841
	appendStringInfo(str, " ARRAY ");
B
Bruce Momjian 已提交
842
	sprintf(buf, " :arrayelemtype %u ", node->arrayelemtype);
843
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
844
	sprintf(buf, " :arrayelemlength %d ", node->arrayelemlength);
845
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
846
	sprintf(buf, " :arrayelembyval %c ", (node->arrayelembyval) ? 't' : 'f');
847
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
848
	sprintf(buf, " :arrayndim %d ", node->arrayndim);
849
	appendStringInfo(str, buf);
850
	appendStringInfo(str, " :arraylow ");
851 852
	for (i = 0; i < node->arrayndim; i++)
	{
853
		sprintf(buf, " %d ", node->arraylow.indx[i]);
854 855
		appendStringInfo(str, buf);
	}
856
	appendStringInfo(str, " :arrayhigh ");
857 858
	for (i = 0; i < node->arrayndim; i++)
	{
B
Bruce Momjian 已提交
859
		sprintf(buf, " %d ", node->arrayhigh.indx[i]);
860 861
		appendStringInfo(str, buf);
	}
B
Bruce Momjian 已提交
862
	sprintf(buf, " :arraylen %d ", node->arraylen);
863
	appendStringInfo(str, buf);
864 865 866
}

/*
867
 *	ArrayRef is a subclass of Expr
868 869
 */
static void
B
Bruce Momjian 已提交
870
_outArrayRef(StringInfo str, ArrayRef *node)
871
{
872
	char		buf[500];
873

874
	appendStringInfo(str, " ARRAYREF ");
B
Bruce Momjian 已提交
875
	sprintf(buf, " :refelemtype %u ", node->refelemtype);
876
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
877
	sprintf(buf, " :refattrlength %d ", node->refattrlength);
878
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
879
	sprintf(buf, " :refelemlength %d ", node->refelemlength);
880
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
881
	sprintf(buf, " :refelembyval %c ", (node->refelembyval) ? 't' : 'f');
882 883
	appendStringInfo(str, buf);

884
	appendStringInfo(str, " :refupperindex ");
885 886
	_outNode(str, node->refupperindexpr);

887
	appendStringInfo(str, " :reflowerindex ");
888 889
	_outNode(str, node->reflowerindexpr);

890
	appendStringInfo(str, " :refexpr ");
891 892
	_outNode(str, node->refexpr);

893
	appendStringInfo(str, " :refassgnexpr ");
894
	_outNode(str, node->refassgnexpr);
895 896 897
}

/*
898
 *	Func is a subclass of Expr
899 900
 */
static void
901
_outFunc(StringInfo str, Func *node)
902
{
903
	char		buf[500];
904

905
	appendStringInfo(str, " FUNC ");
B
Bruce Momjian 已提交
906
	sprintf(buf, " :funcid %u ", node->funcid);
907
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
908
	sprintf(buf, " :functype %u ", node->functype);
909
	appendStringInfo(str, buf);
910 911
	appendStringInfo(str, " :funcisindex ");
	appendStringInfo(str, (node->funcisindex ? "true" : "false"));
B
Bruce Momjian 已提交
912
	sprintf(buf, " :funcsize %d ", node->funcsize);
913
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
914
	sprintf(buf, " :func_fcache @ 0x%x ", (int) (node->func_fcache));
915 916 917 918 919 920 921
	appendStringInfo(str, buf);

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

	appendStringInfo(str, " :func_planlist ");
	_outNode(str, node->func_planlist);
922 923 924
}

/*
925
 *	Oper is a subclass of Expr
926 927
 */
static void
928
_outOper(StringInfo str, Oper *node)
929
{
930
	char		buf[500];
931

932
	appendStringInfo(str, " OPER ");
B
Bruce Momjian 已提交
933
	sprintf(buf, " :opno %u ", node->opno);
934
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
935
	sprintf(buf, " :opid %u ", node->opid);
936
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
937
	sprintf(buf, " :opresulttype %u ", node->opresulttype);
938 939
	appendStringInfo(str, buf);

940 941 942
}

/*
943
 *	Param is a subclass of Expr
944 945
 */
static void
946
_outParam(StringInfo str, Param *node)
947
{
948
	char		buf[500];
949

950
	appendStringInfo(str, " PARAM ");
B
Bruce Momjian 已提交
951
	sprintf(buf, " :paramkind %d ", node->paramkind);
952
	appendStringInfo(str, buf);
953
	sprintf(buf, " :paramid %d ", node->paramid);
954
	appendStringInfo(str, buf);
955 956
	appendStringInfo(str, " :paramname ");
	appendStringInfo(str, node->paramname);
B
Bruce Momjian 已提交
957
	sprintf(buf, " :paramtype %u ", node->paramtype);
958 959 960 961
	appendStringInfo(str, buf);

	appendStringInfo(str, " :param_tlist ");
	_outNode(str, node->param_tlist);
962 963 964
}

/*
965
 *	Stuff from execnodes.h
966 967 968
 */

/*
969
 *	EState is a subclass of Node.
970 971
 */
static void
972
_outEState(StringInfo str, EState *node)
973
{
974
	char		buf[500];
975

976
	appendStringInfo(str, " ESTATE ");
B
Bruce Momjian 已提交
977
	sprintf(buf, " :direction %d ", node->es_direction);
978 979
	appendStringInfo(str, buf);

980
	appendStringInfo(str, " :range_table ");
981 982
	_outNode(str, node->es_range_table);

B
Bruce Momjian 已提交
983
	sprintf(buf, " :result_relation_info @ 0x%x ",
984 985 986
			(int) (node->es_result_relation_info));
	appendStringInfo(str, buf);

987 988 989
}

/*
990
 *	Stuff from relation.h
991 992
 */
static void
993
_outRel(StringInfo str, Rel *node)
994
{
995
	char		buf[500];
996

997
	appendStringInfo(str, " REL ");
998

999
	appendStringInfo(str, " :relids ");
1000 1001
	_outIntList(str, node->relids);

1002 1003
	appendStringInfo(str, " :indexed ");
	appendStringInfo(str, node->indexed ? "true" : "false");
B
Bruce Momjian 已提交
1004
	sprintf(buf, " :pages %u ", node->pages);
1005
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1006
	sprintf(buf, " :tuples %u ", node->tuples);
1007
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1008
	sprintf(buf, " :size %u ", node->size);
1009
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1010
	sprintf(buf, " :width %u ", node->width);
1011 1012
	appendStringInfo(str, buf);

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

1016
	appendStringInfo(str, " :pathlist ");
1017 1018 1019 1020 1021 1022 1023 1024
	_outNode(str, node->pathlist);

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

B
Bruce Momjian 已提交
1025
	sprintf(buf, " :unorderedpath @ 0x%x ", (int) (node->unorderedpath));
1026
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1027
	sprintf(buf, " :cheapestpath @ 0x%x ", (int) (node->cheapestpath));
1028 1029
	appendStringInfo(str, buf);

1030 1031
	appendStringInfo(str, " :pruneable ");
	appendStringInfo(str, node->pruneable ? "true" : "false");
1032

1033
#if 0
1034
	appendStringInfo(str, " :classlist ");
1035 1036
	_outNode(str, node->classlist);

1037
	appendStringInfo(str, " :indexkeys ");
1038 1039
	_outNode(str, node->indexkeys);

1040
	appendStringInfo(str, " :ordering ");
1041 1042 1043
	_outNode(str, node->ordering);
#endif

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

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

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

1053 1054 1055
}

/*
1056
 *	TargetEntry is a subclass of Node.
1057 1058
 */
static void
1059
_outTargetEntry(StringInfo str, TargetEntry *node)
1060
{
1061
	appendStringInfo(str, " TLE ");
1062
	appendStringInfo(str, " :resdom ");
1063 1064
	_outNode(str, node->resdom);

1065 1066
	appendStringInfo(str, " :expr ");
	_outNode(str, node->expr);
1067
}
1068 1069

static void
1070
_outRangeTblEntry(StringInfo str, RangeTblEntry *node)
1071
{
1072
	char		buf[500];
1073

1074
	appendStringInfo(str, " RTE ");
1075

1076 1077
	appendStringInfo(str, " :relname ");
	appendStringInfo(str, node->relname);
1078

1079 1080
	appendStringInfo(str, " :refname ");
	appendStringInfo(str, node->refname);
1081 1082 1083

	sprintf(buf, " :relid %u ", node->relid);
	appendStringInfo(str, buf);
1084 1085 1086 1087 1088 1089 1090 1091 1092 1093

	appendStringInfo(str, " :inh ");
	appendStringInfo(str, node->inh ? "true" : "false");

	appendStringInfo(str, " :inFromCl ");
	appendStringInfo(str, node->inFromCl ? "true" : "false");

	appendStringInfo(str, " :skipAcl ");
	appendStringInfo(str, node->skipAcl ? "true" : "false");

1094
}
1095 1096

/*
1097
 *	Path is a subclass of Node.
1098 1099
 */
static void
1100
_outPath(StringInfo str, Path *node)
1101
{
1102
	char		buf[500];
1103

1104
	appendStringInfo(str, " PATH ");
1105

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

B
Bruce Momjian 已提交
1109
	sprintf(buf, " :cost %f ", node->path_cost);
1110 1111
	appendStringInfo(str, buf);

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

1115 1116 1117
}

/*
1118
 *	IndexPath is a subclass of Path.
1119 1120
 */
static void
1121
_outIndexPath(StringInfo str, IndexPath *node)
1122
{
1123
	char		buf[500];
1124

1125
	appendStringInfo(str, " INDEXPATH ");
1126

B
Bruce Momjian 已提交
1127
	sprintf(buf, " :pathtype %d ", node->path.pathtype);
1128 1129 1130 1131 1132 1133 1134
	appendStringInfo(str, buf);

	/*
	 * sprintf(buf, " :parent "); appendStringInfo(str,buf); _outNode(str,
	 * node->parent);
	 */

B
Bruce Momjian 已提交
1135
	sprintf(buf, " :cost %f ", node->path.path_cost);
1136 1137
	appendStringInfo(str, buf);

1138
#if 0
1139
	appendStringInfo(str, " :p_ordering ");
1140 1141
	_outNode(str, node->path.p_ordering);
#endif
1142
	appendStringInfo(str, " :keys ");
1143 1144
	_outNode(str, node->path.keys);

1145
	appendStringInfo(str, " :indexid ");
1146 1147
	_outIntList(str, node->indexid);

1148
	appendStringInfo(str, " :indexqual ");
1149 1150
	_outNode(str, node->indexqual);

1151 1152 1153
}

/*
1154
 *	JoinPath is a subclass of Path
1155 1156
 */
static void
1157
_outJoinPath(StringInfo str, JoinPath *node)
1158
{
1159
	char		buf[500];
1160

1161
	appendStringInfo(str, " JOINPATH ");
1162

B
Bruce Momjian 已提交
1163
	sprintf(buf, " :pathtype %d ", node->path.pathtype);
1164 1165 1166 1167 1168 1169 1170
	appendStringInfo(str, buf);

	/*
	 * sprintf(buf, " :parent "); appendStringInfo(str,buf); _outNode(str,
	 * node->parent);
	 */

B
Bruce Momjian 已提交
1171
	sprintf(buf, " :cost %f ", node->path.path_cost);
1172 1173
	appendStringInfo(str, buf);

1174
#if 0
1175
	appendStringInfo(str, " :p_ordering ");
1176 1177
	_outNode(str, node->path.p_ordering);
#endif
1178
	appendStringInfo(str, " :keys ");
1179 1180
	_outNode(str, node->path.keys);

1181
	appendStringInfo(str, " :pathclauseinfo ");
1182 1183 1184 1185 1186 1187 1188
	_outNode(str, node->pathclauseinfo);

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

B
Bruce Momjian 已提交
1189
	sprintf(buf, " :outerjoinpath @ 0x%x ", (int) (node->outerjoinpath));
1190
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1191
	sprintf(buf, " :innerjoinpath @ 0x%x ", (int) (node->innerjoinpath));
1192 1193
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
1194
	sprintf(buf, " :outerjoincost %f ", node->path.outerjoincost);
1195 1196
	appendStringInfo(str, buf);

1197
	appendStringInfo(str, " :joinid ");
1198 1199
	_outIntList(str, node->path.joinid);

1200 1201 1202
}

/*
1203
 *	MergePath is a subclass of JoinPath.
1204 1205
 */
static void
1206
_outMergePath(StringInfo str, MergePath *node)
1207
{
1208
	char		buf[500];
1209

1210
	appendStringInfo(str, " MERGEPATH ");
1211

B
Bruce Momjian 已提交
1212
	sprintf(buf, " :pathtype %d ", node->jpath.path.pathtype);
1213 1214
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
1215
	sprintf(buf, " :cost %f ", node->jpath.path.path_cost);
1216 1217
	appendStringInfo(str, buf);

1218
	appendStringInfo(str, " :keys ");
1219 1220
	_outNode(str, node->jpath.path.keys);

1221
	appendStringInfo(str, " :pathclauseinfo ");
1222 1223 1224 1225 1226 1227 1228
	_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.
	 */

B
Bruce Momjian 已提交
1229
	sprintf(buf, " :outerjoinpath @ 0x%x ", (int) (node->jpath.outerjoinpath));
1230
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1231
	sprintf(buf, " :innerjoinpath @ 0x%x ", (int) (node->jpath.innerjoinpath));
1232 1233
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
1234
	sprintf(buf, " :outerjoincost %f ", node->jpath.path.outerjoincost);
1235 1236
	appendStringInfo(str, buf);

1237
	appendStringInfo(str, " :joinid ");
1238 1239
	_outIntList(str, node->jpath.path.joinid);

1240
	appendStringInfo(str, " :path_mergeclauses ");
1241 1242
	_outNode(str, node->path_mergeclauses);

1243
	appendStringInfo(str, " :outersortkeys ");
1244 1245
	_outNode(str, node->outersortkeys);

1246
	appendStringInfo(str, " :innersortkeys ");
1247 1248
	_outNode(str, node->innersortkeys);

1249 1250 1251
}

/*
1252
 *	HashPath is a subclass of JoinPath.
1253 1254
 */
static void
1255
_outHashPath(StringInfo str, HashPath *node)
1256
{
1257
	char		buf[500];
1258

1259
	appendStringInfo(str, " HASHPATH ");
1260

B
Bruce Momjian 已提交
1261
	sprintf(buf, " :pathtype %d ", node->jpath.path.pathtype);
1262 1263
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
1264
	sprintf(buf, " :cost %f ", node->jpath.path.path_cost);
1265 1266
	appendStringInfo(str, buf);

1267
	appendStringInfo(str, " :keys ");
1268 1269
	_outNode(str, node->jpath.path.keys);

1270
	appendStringInfo(str, " :pathclauseinfo ");
1271 1272 1273 1274 1275 1276 1277
	_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.
	 */

B
Bruce Momjian 已提交
1278
	sprintf(buf, " :outerjoinpath @ 0x%x ", (int) (node->jpath.outerjoinpath));
1279
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1280
	sprintf(buf, " :innerjoinpath @ 0x%x ", (int) (node->jpath.innerjoinpath));
1281 1282
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
1283
	sprintf(buf, " :outerjoincost %f ", node->jpath.path.outerjoincost);
1284 1285
	appendStringInfo(str, buf);

1286
	appendStringInfo(str, " :joinid ");
1287 1288
	_outIntList(str, node->jpath.path.joinid);

1289
	appendStringInfo(str, " :path_hashclauses ");
1290 1291
	_outNode(str, node->path_hashclauses);

1292
	appendStringInfo(str, " :outerhashkeys ");
1293 1294
	_outNode(str, node->outerhashkeys);

1295
	appendStringInfo(str, " :innerhashkeys ");
1296 1297
	_outNode(str, node->innerhashkeys);

1298 1299 1300
}

/*
1301
 *	OrderKey is a subclass of Node.
1302 1303
 */
static void
1304
_outOrderKey(StringInfo str, OrderKey *node)
1305
{
1306
	char		buf[500];
1307

1308
	appendStringInfo(str, " ORDERKEY ");
B
Bruce Momjian 已提交
1309
	sprintf(buf, " :attribute_number %d ", node->attribute_number);
1310
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1311
	sprintf(buf, " :array_index %d ", node->array_index);
1312 1313
	appendStringInfo(str, buf);

1314 1315 1316
}

/*
1317
 *	JoinKey is a subclass of Node.
1318 1319
 */
static void
1320
_outJoinKey(StringInfo str, JoinKey *node)
1321
{
1322
	appendStringInfo(str, " JOINKEY ");
1323

1324
	appendStringInfo(str, " :outer ");
1325 1326
	_outNode(str, node->outer);

1327
	appendStringInfo(str, " :inner ");
1328 1329
	_outNode(str, node->inner);

1330 1331 1332
}

/*
1333
 *	MergeOrder is a subclass of Node.
1334 1335
 */
static void
1336
_outMergeOrder(StringInfo str, MergeOrder *node)
1337
{
1338
	char		buf[500];
1339

1340
	appendStringInfo(str, " MERGEORDER ");
1341

B
Bruce Momjian 已提交
1342
	sprintf(buf, " :join_operator %d ", node->join_operator);
1343
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1344
	sprintf(buf, " :left_operator %d ", node->left_operator);
1345
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1346
	sprintf(buf, " :right_operator %d ", node->right_operator);
1347
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1348
	sprintf(buf, " :left_type %d ", node->left_type);
1349
	appendStringInfo(str, buf);
B
Bruce Momjian 已提交
1350
	sprintf(buf, " :right_type %d ", node->right_type);
1351 1352
	appendStringInfo(str, buf);

1353 1354 1355
}

/*
1356
 *	CInfo is a subclass of Node.
1357 1358
 */
static void
1359
_outCInfo(StringInfo str, CInfo *node)
1360
{
1361
	char		buf[500];
1362

1363
	appendStringInfo(str, " CINFO ");
1364

1365
	appendStringInfo(str, " :clause ");
1366 1367
	_outNode(str, node->clause);

B
Bruce Momjian 已提交
1368
	sprintf(buf, " :selectivity %f ", node->selectivity);
1369
	appendStringInfo(str, buf);
1370 1371
	appendStringInfo(str, " :notclause ");
	appendStringInfo(str, node->notclause ? "true" : "false");
1372

1373
	appendStringInfo(str, " :indexids ");
1374 1375
	_outNode(str, node->indexids);

1376
	appendStringInfo(str, " :mergesortorder ");
1377 1378
	_outNode(str, node->mergesortorder);

B
Bruce Momjian 已提交
1379
	sprintf(buf, " :hashjoinoperator %u ", node->hashjoinoperator);
1380 1381
	appendStringInfo(str, buf);

1382 1383 1384
}

/*
1385
 *	JoinMethod is a subclass of Node.
1386 1387
 */
static void
1388
_outJoinMethod(StringInfo str, JoinMethod *node)
1389
{
1390
	appendStringInfo(str, " JOINMETHOD ");
1391

1392
	appendStringInfo(str, " :jmkeys ");
1393 1394
	_outNode(str, node->jmkeys);

1395
	appendStringInfo(str, " :clauses ");
1396 1397 1398
	_outNode(str, node->clauses);


1399 1400 1401 1402 1403 1404
}

/*
 * HInfo is a subclass of JoinMethod.
 */
static void
1405
_outHInfo(StringInfo str, HInfo *node)
1406
{
1407
	char		buf[500];
1408

1409
	appendStringInfo(str, " HASHINFO ");
1410

1411
	appendStringInfo(str, " :hashop ");
B
Bruce Momjian 已提交
1412
	sprintf(buf, " %u ", node->hashop);
1413 1414
	appendStringInfo(str, buf);

1415
	appendStringInfo(str, " :jmkeys ");
1416 1417
	_outNode(str, node->jmethod.jmkeys);

1418
	appendStringInfo(str, " :clauses ");
1419 1420
	_outNode(str, node->jmethod.clauses);

1421 1422 1423
}

/*
1424
 *	JInfo is a subclass of Node.
1425 1426
 */
static void
1427
_outJInfo(StringInfo str, JInfo *node)
1428
{
1429
	appendStringInfo(str, " JINFO ");
1430

1431
	appendStringInfo(str, " :otherrels ");
1432 1433
	_outIntList(str, node->otherrels);

1434
	appendStringInfo(str, " :jinfoclauseinfo ");
1435 1436
	_outNode(str, node->jinfoclauseinfo);

1437 1438 1439 1440
	appendStringInfo(str, " :mergesortable ");
	appendStringInfo(str, node->mergesortable ? "true" : "false");
	appendStringInfo(str, " :hashjoinable ");
	appendStringInfo(str, node->hashjoinable ? "true" : "false");
1441

1442 1443 1444 1445 1446 1447 1448 1449
}

/*
 * Print the value of a Datum given its type.
 */
static void
_outDatum(StringInfo str, Datum value, Oid type)
{
1450 1451 1452 1453 1454 1455
	char		buf[500];
	Size		length,
				typeLength;
	bool		byValue;
	int			i;
	char	   *s;
1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471

	/*
	 * 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 已提交
1472
			sprintf(buf, " %d ", (int) (s[i]));
1473 1474 1475 1476
			appendStringInfo(str, buf);
		}
		sprintf(buf, "] ");
		appendStringInfo(str, buf);
1477
	}
1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498
	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 已提交
1499
				sprintf(buf, " %d ", (int) (s[i]));
1500 1501 1502 1503 1504
				appendStringInfo(str, buf);
			}
			sprintf(buf, "] ");
			appendStringInfo(str, buf);
		}
1505 1506 1507 1508
	}
}

static void
1509
_outIter(StringInfo str, Iter *node)
1510
{
1511
	appendStringInfo(str, " ITER ");
1512 1513 1514

	appendStringInfo(str, " :iterexpr ");
	_outNode(str, node->iterexpr);
1515 1516 1517
}

static void
1518
_outStream(StringInfo str, Stream *node)
1519
{
1520
	char		buf[500];
1521

1522
	appendStringInfo(str, " STREAM ");
1523

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

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

B
Bruce Momjian 已提交
1530
	sprintf(buf, " :clausetype %d ", (int) (node->clausetype));
1531 1532
	appendStringInfo(str, buf);

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

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

B
Bruce Momjian 已提交
1539
	sprintf(buf, " :groupup %d ", node->groupup);
1540 1541
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
1542
	sprintf(buf, " :groupcost %f ", node->groupcost);
1543 1544
	appendStringInfo(str, buf);

B
Bruce Momjian 已提交
1545
	sprintf(buf, " :groupsel %f ", node->groupsel);
1546 1547
	appendStringInfo(str, buf);
}
1548

1549 1550 1551
static void
_outAExpr(StringInfo str, A_Expr *node)
{
1552
	appendStringInfo(str, "EXPR ");
1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577
#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
1578 1579 1580 1581 1582
	_outNode(str, node->lexpr);
	_outNode(str, node->rexpr);
	return;
}

1583
static void
1584
_outValue(StringInfo str, Value *value)
1585
{
1586
	char		buf[500];
1587 1588 1589

	switch (value->type)
	{
1590
		case T_String:
B
Bruce Momjian 已提交
1591
			sprintf(buf, " \"%s\" ", value->val.str);
1592 1593 1594
			appendStringInfo(str, buf);
			break;
		case T_Integer:
B
Bruce Momjian 已提交
1595
			sprintf(buf, " %ld ", value->val.ival);
1596 1597 1598
			appendStringInfo(str, buf);
			break;
		case T_Float:
B
Bruce Momjian 已提交
1599
			sprintf(buf, " %f ", value->val.dval);
1600 1601 1602 1603
			appendStringInfo(str, buf);
			break;
		default:
			break;
1604 1605
	}
	return;
1606 1607
}

1608 1609 1610 1611 1612
static void
_outIdent(StringInfo str, Ident *node)
{
	char		buf[500];

B
Bruce Momjian 已提交
1613
	sprintf(buf, " IDENT \"%s\" ", node->name);
1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628
	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;
}

1629 1630
/*
 * _outNode -
1631
 *	  converts a Node into ascii string and append it to 'str'
1632 1633 1634 1635
 */
static void
_outNode(StringInfo str, void *obj)
{
1636 1637
	if (obj == NULL)
	{
B
Bruce Momjian 已提交
1638
		appendStringInfo(str, "<>");
1639 1640
		return;
	}
1641

1642 1643
	if (nodeTag(obj) == T_List)
	{
1644
		List	   *l;
1645 1646 1647 1648 1649 1650 1651 1652 1653

		appendStringInfo(str, "(");
		foreach(l, (List *) obj)
		{
			_outNode(str, lfirst(l));
			if (lnext(l))
				appendStringInfo(str, " ");
		}
		appendStringInfo(str, ")");
1654
	}
1655 1656 1657 1658 1659
	else
	{
		appendStringInfo(str, "{");
		switch (nodeTag(obj))
		{
1660 1661 1662 1663 1664 1665 1666 1667 1668 1669
			case T_CreateStmt:
				_outCreateStmt(str, obj);
				break;
			case T_IndexStmt:
				_outIndexStmt(str, obj);
				break;

			case T_ColumnDef:
				_outColumnDef(str, obj);
				break;
1670 1671 1672
			case T_TypeName:
				_outTypeName(str, obj);
				break;
1673 1674 1675 1676
			case T_IndexElem:
				_outIndexElem(str, obj);
				break;

1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687
#ifdef PARSEDEBUG
			case T_VariableSetStmt:
				break;
			case T_SelectStmt:
				_outSelectStmt(str, obj);
				break;
			case T_FuncCall:
				_outFuncCall(str, obj);
				break;
#endif

1688 1689 1690
			case T_Query:
				_outQuery(str, obj);
				break;
1691 1692 1693 1694 1695
			case T_SortClause:
				_outSortClause(str, obj);
				break;
			case T_GroupClause:
				_outGroupClause(str, obj);
1696
				break;
1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744
			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 已提交
1745 1746 1747
			case T_SubPlan:
				_outSubPlan(str, obj);
				break;
1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768
			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;
1769 1770 1771
			case T_SubLink:
				_outSubLink(str, obj);
				break;
1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845
			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;
			case T_Rel:
				_outRel(str, obj);
				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;
			case T_CInfo:
				_outCInfo(str, obj);
				break;
			case T_JoinMethod:
				_outJoinMethod(str, obj);
				break;
			case T_HInfo:
				_outHInfo(str, obj);
				break;
			case T_JInfo:
				_outJInfo(str, obj);
				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;
1846 1847 1848 1849 1850 1851 1852 1853 1854
			case T_A_Expr:
				_outAExpr(str, obj);
				break;
			case T_Ident:
				_outIdent(str, obj);
				break;
			case T_A_Const:
				_outAConst(str, obj);
				break;
1855
			default:
B
Bruce Momjian 已提交
1856
				elog(NOTICE, "_outNode: don't know how to print type %d ",
1857 1858
					 nodeTag(obj));
				break;
1859 1860
		}
		appendStringInfo(str, "}");
1861
	}
1862
	return;
1863 1864 1865 1866
}

/*
 * nodeToString -
1867
 *	   returns the ascii representation of the Node
1868
 */
1869
char *
1870 1871
nodeToString(void *obj)
{
1872 1873
	StringInfo	str;
	char	   *s;
1874 1875 1876 1877 1878 1879 1880 1881 1882 1883

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

	return s;
1884
}