/*-------------------------------------------------------------------------
 *
 * print.c--
 *    various print routines (used mostly for debugging)
 *
 * Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *    $Header: /usr/local/devel/pglite/cvs/src/backend/nodes/print.c,v 1.7 1995/03/17 20:26:00 andrew Exp $
 *
 * HISTORY
 *    AUTHOR		DATE		MAJOR EVENT
 *    Andrew Yu		Oct 26, 1994	file creation
 *
 *-------------------------------------------------------------------------
 */
#include <stdio.h>
#include "postgres.h"
#include "access/printtup.h"
#include "nodes/pg_list.h"
#include "nodes/execnodes.h"
#include "nodes/parsenodes.h"

#include "parser/parsetree.h"
#include "parser/catalog_utils.h"
#include "access/heapam.h"
#include "utils/lsyscache.h"

/*
 * print--
 *    print contents of Node to stdout
 */
void
print(void *obj)
{
    char *s;

    s = nodeToString(obj);
    printf("%s\n", s);
    fflush(stdout);
    return;
}

/*
 * pretty print hack extraordinaire.  -ay 10/94
 */
void
pprint(void *obj)
{
    char *s;
    int i;
    char line[80];
    int indentLev;
    int j;

    s = nodeToString(obj);

    indentLev = 0;
    i = 0;
    for(;;) {
	for(j=0; j<indentLev*3; j++) {
	    line[j] = ' ';
	}
	for( ; j<75 && s[i]!='\0'; i++, j++) {
	    line[j] = s[i];
	    switch (line[j]) {
	    case '}':
		if (j != indentLev*3) {
		    line[j] = '\0';
		    printf("%s\n",line);
		    line[indentLev*3] = '\0';
		    printf("%s}\n",line);
		}else {
		    line[j] = '\0';
		    printf("%s}\n",line);
		}
		indentLev--;
		j = indentLev*3-1; /* print the line before : and resets */
		break;
	    case ')':
		line[j+1] = '\0';
		printf("%s\n", line);
		j = indentLev*3-1;
		break;
	    case '{':
		indentLev++;
		/* !!! FALLS THROUGH */
	    case ':':
		if (j != 0) {
		    line[j] = '\0';
		    printf("%s\n",line);
		    /* print the line before : and resets */
		    for(j=0; j<indentLev*3; j++) {
			line[j] = ' ';
		    }
		}
		line[j] = s[i];
		break;
	    }
	}
	line[j] = '\0';
	if (s[i]=='\0')
	    break;
	printf("%s\n", line);
    }
    if (j!=0) {
	printf("%s\n", line);
    }
    fflush(stdout);
    return;
}

/*
 * print_rt--
 *    print contents of range table
 */
void
print_rt(List *rtable)
{
    List *l;
    int i=1;

    printf("resno\trelname(refname)\trelid\tinFromCl\n");
    printf("-----\t----------------\t-----\t--------\n");
    foreach(l, rtable) {
	RangeTblEntry *rte = lfirst(l);
	printf("%d\t%.*s(%-16s)\t%d\t%d\t%s\n",
	       i,NAMEDATALEN,rte->relname,rte->refname,rte->relid,
	       rte->inFromCl,
	       (rte->inh?"inh":""));
	i++;
    }
}


/*
 * print_expr--
 *    print an expression
 */
void
print_expr(Node *expr, List *rtable)
{
    if (expr==NULL) {
	printf("nil");
	return;
    }
    
    if (IsA(expr,Var)) {
	Var *var = (Var*)expr;
	RangeTblEntry *rt;
	Name relname, attname;
	
	switch (var->varno) {
	case INNER:
	    relname = (Name)"INNER";
	    attname = (Name)"?";
	    break;
	case OUTER:
	    relname = (Name)"OUTER";
	    attname = (Name)"?";
	    break;
	default:
	    {
		Relation r;
		rt = rt_fetch(var->varno, rtable);
		relname = rt->relname;
		r = heap_openr(relname);
		if (rt->refname)
		    relname = (Name)rt->refname; /* table renamed */
		attname = getAttrName(r, var->varattno);
		heap_close(r);
	    }
	    break;
	}
	printf("%.*s.%.*s",NAMEDATALEN,relname, NAMEDATALEN, attname);
    } else if (IsA(expr,Expr)) {
	Expr *e = (Expr*)expr;
	if (is_opclause(expr)) {
	    NameData opname;

	    print_expr((Node*)get_leftop(e), rtable);
	    opname = get_opname(((Oper*)e->oper)->opno);
	    printf(" %.*s ", NAMEDATALEN, (char*)opname.data);
	    print_expr((Node*)get_rightop(e), rtable);
	} else {
	    printf("an expr");
	}
    } else {
	printf("not an expr");
    }
}

/*
 * print_keys -
 *    temporary here. where is keys list of list??
 */
void
print_keys(List *keys, List *rtable)
{
    List *k;

    printf("(");
    foreach(k, keys) {
	Node *var = lfirst((List*)lfirst(k));
	print_expr(var, rtable);
	if (lnext(k)) printf(", ");
    }
    printf(")\n");
}

/*
 * print_tl --
 *    print targetlist in a more legible way.
 */
void   
print_tl(List *tlist, List *rtable)
{
    List *tl;

    printf("(\n");
    foreach(tl, tlist) {
	TargetEntry *tle = lfirst(tl);

	printf("\t%d %s\t", tle->resdom->resno, tle->resdom->resname);
	if (tle->resdom->reskey!=0) {
	    printf("(%d):\t", tle->resdom->reskey);
	} else {
	    printf("    :\t", tle->resdom->reskey);
	}
	print_expr(tle->expr, rtable);
	printf("\n");
    }
    printf(")\n");
}

/*
 * print_slot--
 *    print out the tuple with the given TupleTableSlot
 */
void
print_slot(TupleTableSlot *slot)
{
    if (!slot->val) {
	printf("tuple is null.\n");
	return;
    }
    if (!slot->ttc_tupleDescriptor) {
	printf("no tuple descriptor.\n");
	return;
    }
    
    debugtup(slot->val, slot->ttc_tupleDescriptor);
}

