Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 1 Aug 2005 13:32:01 GMT
From:      Marcos Tischer Vallim <tischer@ig.com.br>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   ports/84430: [New Port] databases/pgcluster74-(server|client) : The multi-master and synchronous replication system for PostgreSQL
Message-ID:  <200508011332.j71DW1iV065323@db01.widesoft.com.br>
Resent-Message-ID: <200508011340.j71DeCGe040547@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         84430
>Category:       ports
>Synopsis:       [New Port] databases/pgcluster74-(server|client) : The multi-master and synchronous replication system for PostgreSQL
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Mon Aug 01 13:40:11 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Marcos Tischer Vallim
>Release:        FreeBSD 5.4-RELEASE-p5 i386
>Organization:
>Environment:
System: FreeBSD db01.widesoft.com.br 5.4-RELEASE-p5 FreeBSD 5.4-RELEASE-p5 #1: Sat Jul 23 20:55:39 UTC 2005 root@db01.wideosft.com.br:/usr/obj/usr/src/sys/db01 i386


	
>Description:
PGCluster is a multi-master and synchronous replication system that
supports load balancing of PostgreSQL.

WWW: http://www.csra.co.jp/~mitani/jpug/pgcluster/
>How-To-Repeat:
	
>Fix:

	

--- pgcluster74.shar begins here ---
# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	pgcluster74-client
#	pgcluster74-client/Makefile
#	pgcluster74-server
#	pgcluster74-server/pkg-descr
#	pgcluster74-server/Makefile
#	pgcluster74-server/distinfo
#	pgcluster74-server/files
#	pgcluster74-server/files/hier-Pg7.4-0.5.3.diff
#	pgcluster74-server/files/dot.profile.in
#	pgcluster74-server/files/dot.cshrc.in
#	pgcluster74-server/files/patch-configure
#	pgcluster74-server/files/patch-plpython-Makefile
#	pgcluster74-server/files/patch-src-interfaces-jdbc-build-xml
#	pgcluster74-server/files/patch-src-interfaces-libpgtcl-Makefile
#	pgcluster74-server/files/patch-src-makefiles-Makefile.freebsd
#	pgcluster74-server/files/patch-src:backend:utils:misc:postgresql.conf.sample
#	pgcluster74-server/files/502.pgsql
#	pgcluster74-server/files/pgcluster.sh.tmpl
#	pgcluster74-server/files/pglb.sh.tmpl
#	pgcluster74-server/files/pgreplicate.sh.tmpl
#	pgcluster74-server/pkg-install
#	pgcluster74-server/pkg-plist-client
#	pgcluster74-server/pkg-plist
#
echo c - pgcluster74-client
mkdir -p pgcluster74-client > /dev/null 2>&1
echo x - pgcluster74-client/Makefile
sed 's/^X//' >pgcluster74-client/Makefile << 'END-of-pgcluster74-client/Makefile'
X# New ports collection makefile for:	PgCluster-client
X# Date created:				Fri Jul 29 16:39:00 UTC 2005
X# Whom:					Marcos Tischer Vallim <tischer@ig.com.br>
X#
X# $FreeBSD$
X#
X
XPORTNAME=	pgcluster
XPKGNAMESUFFIX=	-client
X
XCOMMENT=	The multi-master and synchronous replication system for PostgreSQL(client)
X
XMASTERDIR=	${.CURDIR}/../pgcluster74-server
X
XBUILD_DIRS=	src/bin src/include src/interfaces doc
XCLIENT_ONLY=	yes
XINSTALLS_SHLIB=	yes
X
XPLIST=		${MASTERDIR}/pkg-plist${PKGNAMESUFFIX}
X
X.include "${MASTERDIR}/Makefile"
END-of-pgcluster74-client/Makefile
echo c - pgcluster74-server
mkdir -p pgcluster74-server > /dev/null 2>&1
echo x - pgcluster74-server/pkg-descr
sed 's/^X//' >pgcluster74-server/pkg-descr << 'END-of-pgcluster74-server/pkg-descr'
XPGCluster is a multi-master and synchronous replication system that
Xsupports load balancing of PostgreSQL.
X
XWWW: http://www.csra.co.jp/~mitani/jpug/pgcluster/
END-of-pgcluster74-server/pkg-descr
echo x - pgcluster74-server/Makefile
sed 's/^X//' >pgcluster74-server/Makefile << 'END-of-pgcluster74-server/Makefile'
X# New ports collection makefile for:	pgcluster74
X# Date created:		2005-07-27
X# Whom:			Marcos Tischer Vallim <tischer@ig.com.br>
X#
X# $FreeBSD$
X#
X
XPORTNAME=	pgcluster
XPORTVERSION=	${BASEPGSQL}
XCATEGORIES=	databases
XMASTER_SITES=	${MASTER_SITE_PGSQL}
XMASTER_SITE_SUBDIR=	source/v${BASEPGSQL}
XPKGNAMESUFFIX?=	-server
XDISTFILES?=	postgresql-base-${BASEPGSQL}${EXTRACT_SUFX} \
X		postgresql-opt-${BASEPGSQL}${EXTRACT_SUFX}
X
XPATCH_SITES=	http://pgfoundry.org/frs/download.php/217/:pgcluster111
XPATCHFILES=	pgcluster-1.1.1a-patch.tar.gz:pgcluster111
XPATCH_DIST_STRIP=-p1
X
XMAINTAINER=	tischer@ig.com.br
XCOMMENT=	The multi-master and synchronous replication system for PostgreSQL
X
X.if !defined(CLIENT_ONLY)
XLIB_DEPENDS=	pq.3:${PORTSDIR}/databases/pgcluster74-client
X.endif
X
XRUN_DEPENDS+=	rsync:${PORTSDIR}/net/rsync
X
XCONFLICTS?=	postgresql-server-7.[0-35-9]* \
X		postgresql-server-8.* \
X		postgresql-client-7.[0-35-9]* \
X		postgresql-client-8.*
X
XBASEPGSQL=	7.4.8
X
XRCSCRIPTPGCL=	${PREFIX}/etc/rc.d/pgcluster.sh
XRCSCRIPTPGRP=	${PREFIX}/etc/rc.d/pgreplicate.sh
XRCSCRIPTPGLB=	${PREFIX}/etc/rc.d/pglb.sh
X
XBUILD_DIRS?=	src/backend src/backend/utils/mb/conversion_procs src/pl
XINSTALL_DIRS?=	${BUILD_DIRS}
X
XWRKSRC=		${WRKDIR}/postgresql-${BASEPGSQL}
XDATADIR=	${PREFIX}/share/postgresql
XDIST_SUBDIR=	postgresql
X
XUSE_AUTOCONF_VER=	259
XUSE_RC_SUBR=	yes
XUSE_REINPLACE=	yes
XMAKE_FLAGS=	# empty
XMAKEFILE=	# empty
XUSE_BZIP2=	YES
XUSE_GMAKE=	YES
XGNU_CONFIGURE=	YES
XINSTALLS_SHLIB=	YES
X
XCONFIGURE_ARGS=	--enable-thread-safety \
X		--with-pgcluster \
X		--with-libraries=${LOCALBASE}/lib \
X		--docdir=${DOCSDIR}
XCONFIGURE_ENV+=	LDFLAGS="${LDFLAGS}"
X
X.if !defined(CLIENT_ONLY) && !defined(SLAVE_ONLY)
XSERVER_ONLY=	yes
X.endif
X
X.if !defined(SLAVE_ONLY)
XOPTIONS=	NLS "Use internationalized messages" on \
X		PAM "Build with PAM support" off \
X		MIT_KRB5 "Build with MIT's kerberos support" off \
X		HEIMDAL_KRB5 "Builds with Heimdal kerberos support" off \
X		OPTIMIZED_CFLAGS "Builds with compiler optimizations (-O3)" on \
X		LIBC_R "Link w/ libc_r, used by plpython" off \
X		HIER "Builds with query hierarchy" off \
X		BALANCE "Builds with Load Balance Server" off \
X		REPLICA "Builds with Replication Server" off
X
X.include <bsd.port.pre.mk>
X
X.  if defined(WITH_HIER)
XEXTRA_PATCHES=	${FILESDIR}/hier-Pg7.4-0.5.3.diff
XUSE_BISON=yes
X.  endif
X
X.  if defined(SERVER_ONLY) && defined(WITH_PAM)
XCONFIGURE_ARGS+=--with-pam
X.  endif
X
X.  if !(defined(WITHOUT_NLS) || defined(WITHOUT_GETTEXT))
XCONFIGURE_ARGS+=--enable-nls --with-includes=${LOCALBASE}/include
XPLIST_SUB+=	GETTEXT=""
XUSE_GETTEXT=	YES
X.  else
XCONFIGURE_ARGS+=--disable-nls
XPLIST_SUB+=	GETTEXT="@comment "
X.  endif
X
X.  if defined(WITH_OPTIMIZED_CFLAGS)
XCFLAGS+=	-O3 -funroll-loops
X.  endif
X
X.  if defined(WITH_MIT_KRB5)
XWITH_KRB5=	yes
XKRB5_HOME?=	${LOCALBASE}
XKRB5CONF=	${KRB5_HOME}/bin/krb5-config
XLIB_DEPENDS+=	krb5.3:${PORTSDIR}/security/krb5
X.  endif
X
X.  if defined(WITH_HEIMDAL_KRB5)
XWITH_KRB5=	yes
X.    if defined(HEIMDAL_HOME) && exists(${HEIMDAL_HOME}/lib/libgssapi.a)
XKRB5CONF=	${HEIMDAL_HOME}/bin/krb5-config
X.    elif ( ${OSVERSION} > 500105 ) && exists(${DESTDIR}/usr/lib/libkrb5.a)
XKRB5CONF=	${DESTDIR}/usr/bin/krb5-config
X.    else
XLIB_DEPENDS+=	krb5:${PORTSDIR}/security/heimdal
XKRB5CONF=	${LOCALBASE}/bin/krb5-config
X.    endif
X.  endif
X
X.  if defined(WITH_KRB5)
XCONFIGURE_ARGS+=	--with-krb5="`${KRB5CONF} --prefix krb5`"
XLDFLAGS+=	`${KRB5CONF} --libs krb5`
XCONFIGURE_ENV+=	LDFLAGS="${LDFLAGS}"
X.  endif
X
X.  if defined(SERVER_ONLY) && defined(WITH_LIBC_R)
XCFLAGS+=	${PTHREAD_CFLAGS}
XLDFLAGS+=	${PTHREAD_LIBS}
X.  endif
X
X.  if defined(SERVER_ONLY) && defined(WITH_REPLICA)
XBUILD_DIRS+=	src/pgcluster/pgrp
XPLIST_SUB+=	PGSQLRP=""
X.  else
XPLIST_SUB+=	PGSQLRP="@comment "
X.  endif
X
X.  if defined(SERVER_ONLY) && defined(WITH_BALANCE)
XBUILD_DIRS+=	src/pgcluster/pglb
XPLIST_SUB+=	PGSQLLB=""
X.  else
XPLIST_SUB+=	PGSQLLB="@comment "
X.  endif
X
X.endif
X
X.if defined(CLIENT_ONLY)
XMAN1=	clusterdb.1 createdb.1 createlang.1 createuser.1 dropdb.1 droplang.1 \
X	dropuser.1 ecpg.1 initdb.1 initlocation.1 ipcclean.1 pg_config.1 \
X	pg_controldata.1 pg_ctl.1 pg_dump.1 pg_dumpall.1 pg_resetxlog.1 \
X	pg_restore.1 pgtclsh.1 pgtksh.1 postgres.1 psql.1 postmaster.1 \
X	vacuumdb.1
X
XMAN7=	abort.7 alter_aggregate.7 alter_conversion.7 alter_database.7 \
X	alter_domain.7 alter_function.7 alter_group.7 alter_language.7 \
X	alter_operator_class.7 alter_schema.7 alter_sequence.7 alter_table.7 \
X	alter_trigger.7 alter_user.7 analyze.7 begin.7 checkpoint.7 \
X	close.7 cluster.7 set_transaction.7 comment.7 commit.7 copy.7 \
X	create_aggregate.7 create_cast.7 create_constraint_trigger.7 \
X	create_conversion.7 create_database.7 create_domain.7 create_function.7 \
X	create_group.7 create_index.7 create_language.7 create_operator.7 \
X	create_operator_class.7 create_rule.7 create_schema.7 create_sequence.7 \
X	create_table.7 create_type.7 create_table_as.7 create_trigger.7 \
X	create_user.7 create_view.7 deallocate.7 declare.7 delete.7 \
X	drop_aggregate.7 drop_cast.7 drop_conversion.7 drop_database.7 \
X	drop_domain.7 drop_function.7 drop_group.7 drop_index.7 drop_language.7 \
X	drop_operator.7 drop_operator_class.7 drop_rule.7 drop_schema.7 \
X	drop_sequence.7 drop_table.7 drop_trigger.7 drop_type.7 drop_user.7 \
X	drop_view.7 end.7 execute.7 explain.7 fetch.7 grant.7 insert.7 listen.7 \
X	load.7 lock.7 move.7 notify.7 prepare.7 reindex.7 reset.7 revoke.7 \
X	rollback.7 select.7 select_into.7 set.7 set_constraints.7 \
X	set_session_authorization.7 show.7 start_transaction.7 truncate.7 \
X	unlisten.7 update.7 vacuum.7
X.endif
X
Xpre-everything::
X.if defined(SERVER_ONLY)
X	@${SH} ${PKGINSTALL} ${PORTNAME} BACKUPWARNING
X.endif
X
Xpre-install:
X.if defined(SERVER_ONLY)
X	@${SETENV} PKG_PREFIX=${PREFIX} \
X		${SH} ${PKGINSTALL} ${PORTNAME} PRE-INSTALL
X.endif
X
Xdo-install:
X	@ for dir in ${INSTALL_DIRS}; do \
X		cd ${WRKSRC}/$${dir} && \
X		${SETENV} ${MAKE_ENV} ${GMAKE} install-strip; \
X	done \
X
X.if defined(WITH_REPLICA) && defined(SERVER_ONLY)
X	@ ${SED} -e "s|%%PREFIX%%|${PREFIX}|g; s|%%RC_SUBR%%|${RC_SUBR}|g" \
X		< ${FILESDIR}/pgreplicate.sh.tmpl \
X		> ${RCSCRIPTPGRP} ;\
X	${CHMOD} 554 ${RCSCRIPTPGRP} ;\
X	${CHOWN} root:pgsql ${RCSCRIPTPGRP}
X.endif
X
X.if defined(WITH_BALANCE) && defined(SERVER_ONLY)
X	@${SED} -e "s|%%PREFIX%%|${PREFIX}|g; s|%%RC_SUBR%%|${RC_SUBR}|g" \
X		< ${FILESDIR}/pglb.sh.tmpl \
X		> ${RCSCRIPTPGLB} ; \
X		${CHMOD} 554 ${RCSCRIPTPGLB} ;\
X		${CHOWN} root:pgsql ${RCSCRIPTPGLB}
X.endif
X
X.if defined(CLIENT_ONLY)
X	cd ${WRKSRC} && ${SETENV} ${MAKE_ENV} ${GMAKE} install-all-headers
X.elif defined(SERVER_ONLY)
X	${MKDIR} ${PREFIX}/share/postgresql; \
X
X	for i in profile cshrc; do \
X		${SED} "s|%%PREFIX%%|${PREFIX}|g" \
X			< ${FILESDIR}/dot.$${i}.in \
X			> ${PREFIX}/share/postgresql/dot.$${i}.dist; \
X		${CP} ${PREFIX}/share/postgresql/dot.$${i}.dist ~pgsql/; \
X		if [ ! -f ~pgsql/.$${i} ]; then \
X			${CP} ${PREFIX}/share/postgresql/dot.$${i}.dist ~pgsql/.$${i}; \
X		fi \
X	done \
X
X	${SED} -e "s|%%PREFIX%%|${PREFIX}|g; s|%%RC_SUBR%%|${RC_SUBR}|g" \
X		< ${FILESDIR}/pgcluster.sh.tmpl \
X		> ${RCSCRIPTPGCL} ; \
X	${CHMOD} 554 ${RCSCRIPTPGCL} ;\
X	${CHOWN} root:pgsql ${RCSCRIPTPGCL} ;\
X
X	${CHOWN} -R pgsql:pgsql ~pgsql/. ;\
X	${MKDIR} ${PREFIX}/etc/periodic/daily ;\
X	${INSTALL_SCRIPT} ${FILESDIR}/502.pgsql \
X		${PREFIX}/etc/periodic/daily
X.endif
X
X.include <bsd.port.post.mk>
END-of-pgcluster74-server/Makefile
echo x - pgcluster74-server/distinfo
sed 's/^X//' >pgcluster74-server/distinfo << 'END-of-pgcluster74-server/distinfo'
XMD5 (postgresql/postgresql-base-7.4.8.tar.bz2) = c066dd74a746e15a49e0fded93a45329
XSIZE (postgresql/postgresql-base-7.4.8.tar.bz2) = 6588745
XMD5 (postgresql/postgresql-opt-7.4.8.tar.bz2) = b178144bdb13a2dd8eb0d17a49532296
XSIZE (postgresql/postgresql-opt-7.4.8.tar.bz2) = 332225
XMD5 (postgresql/pgcluster-1.1.1a-patch.tar.gz) = f7667e3cab662ca19b0e3e2d8a2f843c
XSIZE (postgresql/pgcluster-1.1.1a-patch.tar.gz) = 132809
END-of-pgcluster74-server/distinfo
echo c - pgcluster74-server/files
mkdir -p pgcluster74-server/files > /dev/null 2>&1
echo x - pgcluster74-server/files/hier-Pg7.4-0.5.3.diff
sed 's/^X//' >pgcluster74-server/files/hier-Pg7.4-0.5.3.diff << 'END-of-pgcluster74-server/files/hier-Pg7.4-0.5.3.diff'
Xdiff -Prdc --exclude-from=exclude src/backend/commands/explain.c src/backend/commands/explain.c
X*** src/backend/commands/explain.c	Fri Oct 17 01:14:26 2003
X--- src/backend/commands/explain.c	Mon Jul  5 08:19:37 2004
X***************
X*** 474,479 ****
X--- 474,482 ----
X  		case T_Hash:
X  			pname = "Hash";
X  			break;
X+  		case T_Conn:
X+  			pname = "Hier";
X+  			break;
X  		default:
X  			pname = "???";
X  			break;
Xdiff -Prdc --exclude-from=exclude src/backend/executor/Makefile src/backend/executor/Makefile
X*** src/backend/executor/Makefile	Thu Mar 27 16:51:27 2003
X--- src/backend/executor/Makefile	Mon Jul  5 08:19:37 2004
X***************
X*** 18,24 ****
X         nodeHashjoin.o nodeIndexscan.o nodeMaterial.o nodeMergejoin.o \
X         nodeNestloop.o nodeFunctionscan.o nodeResult.o nodeSeqscan.o \
X         nodeSetOp.o nodeSort.o nodeUnique.o nodeLimit.o nodeGroup.o \
X!        nodeSubplan.o nodeSubqueryscan.o nodeTidscan.o tstoreReceiver.o spi.o
X  
X  all: SUBSYS.o
X  
X--- 18,25 ----
X         nodeHashjoin.o nodeIndexscan.o nodeMaterial.o nodeMergejoin.o \
X         nodeNestloop.o nodeFunctionscan.o nodeResult.o nodeSeqscan.o \
X         nodeSetOp.o nodeSort.o nodeUnique.o nodeLimit.o nodeGroup.o \
X!        nodeSubplan.o nodeSubqueryscan.o nodeTidscan.o tstoreReceiver.o spi.o \
X!        nodeConn.o
X  
X  all: SUBSYS.o
X  
Xdiff -Prdc --exclude-from=exclude src/backend/executor/execAmi.c src/backend/executor/execAmi.c
X*** src/backend/executor/execAmi.c	Tue Mar  2 18:56:28 2004
X--- src/backend/executor/execAmi.c	Mon Jul  5 09:21:16 2004
X***************
X*** 37,42 ****
X--- 37,43 ----
X  #include "executor/nodeSubqueryscan.h"
X  #include "executor/nodeTidscan.h"
X  #include "executor/nodeUnique.h"
X+ #include "executor/nodeConn.h"
X  
X  
X  /*
X***************
X*** 171,176 ****
X--- 172,181 ----
X  			ExecReScanLimit((LimitState *) node, exprCtxt);
X  			break;
X  
X+  		case T_ConnectState:
X+  			ExecReScanConn((ConnectState *) node, exprCtxt);
X+  			break;
X+ 
X  		default:
X  			elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
X  			break;
X***************
X*** 217,222 ****
X--- 222,231 ----
X  			ExecSortMarkPos((SortState *) node);
X  			break;
X  
X+  		case T_ConnectState:
X+  			ExecConnMarkPos((ConnectState *) node);
X+  			break;
X+  
X  		default:
X  			/* don't make hard error unless caller asks to restore... */
X  			elog(DEBUG2, "unrecognized node type: %d", (int) nodeTag(node));
X***************
X*** 258,263 ****
X--- 267,276 ----
X  			ExecSortRestrPos((SortState *) node);
X  			break;
X  
X+     case T_ConnectState:
X+       ExecConnRestrPos((ConnectState *) node);
X+       break;
X+                         
X  		default:
X  			elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
X  			break;
Xdiff -Prdc --exclude-from=exclude src/backend/executor/execProcnode.c src/backend/executor/execProcnode.c
X*** src/backend/executor/execProcnode.c	Fri Aug  8 21:41:39 2003
X--- src/backend/executor/execProcnode.c	Mon Jul  5 08:19:37 2004
X***************
X*** 100,105 ****
X--- 100,106 ----
X  #include "executor/nodeUnique.h"
X  #include "miscadmin.h"
X  #include "tcop/tcopprot.h"
X+ #include "executor/nodeConn.h"
X  
X  /* ------------------------------------------------------------------------
X   *		ExecInitNode
X***************
X*** 213,218 ****
X--- 214,223 ----
X  			result = (PlanState *) ExecInitLimit((Limit *) node, estate);
X  			break;
X  
X+  		case T_Conn:
X+  			result = ExecInitConn((Conn *) node, estate);
X+  			break;
X+  
X  		default:
X  			elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
X  			result = NULL;		/* keep compiler quiet */
X***************
X*** 372,377 ****
X--- 377,386 ----
X  			result = ExecLimit((LimitState *) node);
X  			break;
X  
X+  		case T_ConnectState:
X+  			result = ExecConn((ConnectState *) node);
X+  			break;
X+  
X  		default:
X  			elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
X  			result = NULL;
X***************
X*** 464,469 ****
X--- 473,481 ----
X  		case T_Limit:
X  			return ExecCountSlotsLimit((Limit *) node);
X  
X+  		case T_Conn:
X+  			return ExecCountSlotsConn((Conn *) node);
X+  
X  		default:
X  			elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
X  			break;
X***************
X*** 592,597 ****
X--- 604,613 ----
X  			ExecEndLimit((LimitState *) node);
X  			break;
X  
X+  		case T_ConnectState:
X+  			ExecEndConn((ConnectState *) node);
X+  			break;
X+  
X  		default:
X  			elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
X  			break;
Xdiff -Prdc --exclude-from=exclude src/backend/executor/execQual.c src/backend/executor/execQual.c
X*** src/backend/executor/execQual.c	Thu Dec 18 22:23:54 2003
X--- src/backend/executor/execQual.c	Mon Jul  5 08:19:37 2004
X***************
X*** 57,62 ****
X--- 57,63 ----
X  				 ExprContext *econtext,
X  				 bool *isNull, ExprDoneCond *isDone);
X  static Datum ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull);
X+ static Datum ExecEvalFakeVar(FakeVar *variable, ExprContext *econtext, bool *isNull);
X  static Datum ExecEvalParam(Param *expression, ExprContext *econtext,
X  			  bool *isNull);
X  static Datum ExecEvalFunc(FuncExprState *fcache, ExprContext *econtext,
X***************
X*** 403,408 ****
X--- 404,410 ----
X  	 * We assume it's OK to point to the existing tupleDescriptor, rather
X  	 * than copy that too.
X  	 */
X+ 	
X  	if (attnum == InvalidAttrNumber)
X  	{
X  		MemoryContext oldContext;
X***************
X*** 417,422 ****
X--- 419,480 ----
X  		MemoryContextSwitchTo(oldContext);
X  		return PointerGetDatum(tempSlot);
X  	}
X+ 	result = heap_getattr(heapTuple,	/* tuple containing attribute */
X+ 						  attnum,		/* attribute number of desired
X+ 										 * attribute */
X+ 						  tuple_type,	/* tuple descriptor of tuple */
X+ 						  isNull);		/* return: is attribute null? */
X+ 
X+ 	return result;
X+ }
X+ 
X+ /* Same as ExecEvalVar but returns only value from current tuple, or
X+  * (Datum) ) if tuple slot if undefined.
X+  */
X+ static Datum
X+ ExecEvalFakeVar(FakeVar *variable, ExprContext *econtext, bool *isNull)
X+ {
X+ 	Datum		result;
X+ 	TupleTableSlot *slot;
X+ 	AttrNumber	attnum;
X+ 	HeapTuple	heapTuple;
X+ 	TupleDesc	tuple_type;
X+ 	/*
X+ 	 * get the slot we want
X+ 	 */
X+ 	/* FakeVars can't be OUTER or INNER so get the tuple only from 
X+ 	 * the relation being scanned.
X+ 	 */
X+ 	slot = econtext->ecxt_scantuple;
X+ 
X+ 	/* if slot is undefined, then we're on layer under Hier where FakeVar not really exist,
X+ 	 * so show our fake nature, and return 0.
X+ 	 */
X+ 	if(!slot){
X+ 		if(variable->vartype != INT4OID)
X+ 			elog(ERROR,"ExecEvalFakeVar: FakeVars with type other than INT4 is not supported (internal error)");
X+ 		return Int32GetDatum(0);
X+ 	}
X+ 	/*
X+ 	 * extract tuple information from the slot
X+ 	 */
X+ 	heapTuple = slot->val;
X+ 	tuple_type = slot->ttc_tupleDescriptor;
X+ 
X+ 	attnum = variable->varattno;
X+ 
X+ 	/* (See prolog of ExecEvalVar for explanation of this Assert) */
X+ 		
X+ 	if(attnum - 1 >= tuple_type->natts ){
X+ 	  return Int32GetDatum(0);
X+ 	}
X+ 	Assert(attnum <= 0 ||
X+ 		   (attnum - 1 <= tuple_type->natts - 1 &&
X+ 			tuple_type->attrs[attnum - 1] != NULL &&
X+ 		  variable->vartype == tuple_type->attrs[attnum - 1]->atttypid));
X+ 
X+ 	if (attnum == InvalidAttrNumber)
X+ 		elog(ERROR,"ExecEvalFakeVar: invalid attnum %u (internal error)",attnum);
X  
X  	result = heap_getattr(heapTuple,	/* tuple containing attribute */
X  						  attnum,		/* attribute number of desired
X***************
X*** 2221,2232 ****
X--- 2279,2299 ----
X  	 * here we dispatch the work to the appropriate type of function given
X  	 * the type of our expression.
X  	 */
X+   
X  	expr = expression->expr;
X  	switch (nodeTag(expr))
X  	{
X  		case T_Var:
X  			retDatum = ExecEvalVar((Var *) expr, econtext, isNull);
X  			break;
X+ 		case T_FakeVar:
X+ 			retDatum = ExecEvalFakeVar((FakeVar *) expr, econtext, isNull);
X+ 		        break;
X+ 		case T_Prior:
X+  			*isNull = true;
X+  			retDatum = (Datum)0;
X+  			break;
X+ 
X  		case T_Const:
X  			{
X  				Const	   *con = (Const *) expr;
X***************
X*** 2421,2427 ****
X--- 2488,2496 ----
X  	switch (nodeTag(node))
X  	{
X  		case T_Var:
X+     case T_FakeVar:
X  		case T_Const:
X+ 		case T_Prior:
X  		case T_Param:
X  		case T_CoerceToDomainValue:
X  			/* No special setup needed for these node types */
X***************
X*** 3134,3143 ****
X  							  projInfo->pi_tupNulls,
X  							  projInfo->pi_itemIsDone,
X  							  isDone);
X- 
X  	/*
X  	 * store the tuple in the projection slot and return the slot.
X  	 */
X  	return ExecStoreTuple(newTuple,		/* tuple to store */
X  						  slot, /* slot to store in */
X  						  InvalidBuffer,		/* tuple has no buffer */
X--- 3203,3212 ----
X  							  projInfo->pi_tupNulls,
X  							  projInfo->pi_itemIsDone,
X  							  isDone);
X  	/*
X  	 * store the tuple in the projection slot and return the slot.
X  	 */
X+ 
X  	return ExecStoreTuple(newTuple,		/* tuple to store */
X  						  slot, /* slot to store in */
X  						  InvalidBuffer,		/* tuple has no buffer */
Xdiff -Prdc --exclude-from=exclude src/backend/executor/nodeConn.c src/backend/executor/nodeConn.c
X*** src/backend/executor/nodeConn.c	Thu Jan  1 00:00:00 1970
X--- src/backend/executor/nodeConn.c	Mon Jul  5 08:19:37 2004
X***************
X*** 0 ****
X--- 1,323 ----
X+ /*------------------------------------------------------------------------- *
X+  * nodeConn.c
X+  *	  Routines to handle connecting of relations.
X+  *
X+  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
X+  * Portions Copyright (c) 1994, Regents of the University of California
X+  *
X+  * Based on nodeSort.c, by Evgen Potemkin evgent@terminal.ru, 11.2002
X+  *
X+  *-------------------------------------------------------------------------
X+  */
X+ 
X+ #include "postgres.h"
X+ 
X+ #include "executor/execdebug.h"
X+ #include "executor/nodeConn.h"
X+ #include "utils/tupleconn.h"
X+ #include "miscadmin.h"
X+ #include "utils/memutils.h"
X+ 
X+ #include "nodes/print.h"
X+ 
X+ /* ----------------------------------------------------------------
X+  *		ExecConn
X+  *
X+  *		Connects tuples from the outer subtree of the node using tupleconn,
X+  *		which saves the results in a temporary file or memory. After the
X+  *		initial call, returns a tuple from the file with each call.
X+  *
X+  *		Conditions:
X+  *		  -- none.
X+  *
X+  *		Initial States:
X+  *		  -- the outer child is prepared to return the first tuple.
X+  * ----------------------------------------------------------------
X+  */
X+ TupleTableSlot *
X+ ExecConn(ConnectState *node)
X+ {
X+ 	EState	   *estate;
X+ 	TupleTableSlot *slot;
X+ 	HeapTuple	heapTuple;
X+ 	ScanDirection dir;
X+ 	Tupleconnstate *tupleconnstate;
X+ 	bool		should_free;
X+ 	List		*squal;
X+ 	ExprContext *econtext;
X+ 	int			head;
X+ 	bool		ok;
X+   Conn *plan=(Conn *) node->ss.ps.plan;
X+ 	/*
X+ 	 * get state info from node
X+ 	 */
X+ 	estate = node->ss.ps.state;
X+ 	dir = estate->es_direction;
X+ 	tupleconnstate = (Tupleconnstate *) node->tupleconnstate;
X+ 	
X+   econtext = node->ss.ps.ps_ExprContext;
X+ 	if (!node->conn_Done)
X+ 	{
X+ 		TupleDesc	tupDesc;
X+     PlanState *outerNode;
X+     
X+   	SO1_printf("ExecConn: %s\n",
X+ 				   "connecting subplan");
X+ 
X+ 		/*
X+ 		 * Want to scan subplan in the forward direction while creating
X+ 		 * the data for processing.
X+ 		 */
X+ 
X+ 		/*
X+ 		 * Initialize tupleconn module.
X+ 		 */
X+ 		SO1_printf("ExecConn: %s\n",
X+ 				   "calling tupleconn_begin");
X+ 
X+ 		outerNode = outerPlanState((PlanState *) node);
X+ 		tupDesc = ExecGetResultType(outerNode);
X+ 
X+     tupleconnstate = tupleconn_begin_heap(SortMem,tupDesc,plan->connOp,
X+          plan->priorsList,plan->levelColNum,((Plan *)plan)->plan_rows,plan->useHash);
X+ 		node->tupleconnstate = (void *) tupleconnstate;
X+ 
X+ 		/*
X+ 		 * Scan the subplan and feed all the tuples to tupleconn.
X+ 		 */
X+     squal = makeList1(node->startQual);
X+ 
X+ 		ResetExprContext(econtext);
X+ 
X+ 		for (;;)
X+ 		{
X+ 			slot = ExecProcNode(outerNode);
X+ 			if (TupIsNull(slot))
X+ 				break;
X+ 			econtext->ecxt_scantuple = slot;
X+ 			/* check if tuple is a head of tree */
X+ 			head = ExecQual(squal, econtext, false);
X+ 			/* store it */
X+ 			tupleconn_puttuple(tupleconnstate, (void *) slot->val,head);
X+ 		}
X+ 
X+ 		tupleconn_donestoring(tupleconnstate);
X+ 		/* connect them.
X+ 		 * parentExpr, childExpr, econtext is not needed in tupleconn,
X+ 		 * so pass them only for connecting stage.
X+ 		 */
X+ 		tupleconn_performconn(tupleconnstate,plan->parentExpr,plan->childExpr,econtext);
X+ 		/*
X+ 		 * finally set the connected flag to true
X+ 		 */
X+ 		node->conn_Done = true;
X+ 		SO1_printf(stderr, "ExecConn: connecting done.\n");
X+ 	}
X+ 	SO1_printf("ExecConn: %s\n",
X+ 			   "retrieving tuple from tupleconn");
X+ 
X+ 	/*
X+ 	 * Get the first or next tuple from tupleconn. Returns NULL if no more
X+ 	 * tuples.
X+ 	 */
X+   squal = node->ss.ps.qual;
X+ 	ok=0;	
X+ 	/* everywhere here slot is the same pointer, so get it here */
X+ 	slot = node->ss.ps.ps_ResultTupleSlot;
X+ 	/* Apply HAVING clause to post-qual tuples */
X+ 	do{
X+ 		/* if qual present, clear context */
X+ 		if(squal) ResetExprContext(econtext);
X+ 		heapTuple = tupleconn_getheaptuple(tupleconnstate,
X+ 									   &should_free);
X+ 		ExecStoreTuple(heapTuple, slot, InvalidBuffer, should_free);
X+ 		if(!squal) break; /* don't qual */
X+ 		if(!heapTuple) break; /* no more tuples */
X+ 		econtext->ecxt_scantuple = slot;
X+ 		/* if tuple satisfy qual, pass it, else get next */
X+ 		ok=ExecQual(squal, econtext, false);
X+ 	}while(!ok);
X+ 
X+ 	if(squal) ResetExprContext(econtext);
X+ 	return slot;
X+ }
X+ 
X+ /* Everything below is same as nodeSort.c
X+  */
X+ /* ----------------------------------------------------------------
X+  *		ExecInitConn
X+  *
X+  *		Creates the run-time state information for the conn node
X+  *		produced by the planner and initailizes its outer subtree.
X+  * ----------------------------------------------------------------
X+  */
X+ ConnectState *
X+ ExecInitConn(Conn *node, EState *estate)
X+ {
X+ 	ConnectState *connstate;
X+ 	
X+ 	SO1_printf("ExecInitConn: %s\n",
X+ 			   "initializing conn node");
X+ 	/*
X+ 	 * assign the node's execution state
X+ 	 */
X+ 
X+ 	/*
X+ 	 * create state structure
X+ 	 */
X+ 	connstate = makeNode(ConnectState);
X+ 	connstate->ss.ps.plan = (Plan *) node;
X+ 	connstate->ss.ps.qual = ExecInitExpr( (Expr *)((Plan *)node)->qual, (PlanState *)connstate);;
X+ 	connstate->ss.ps.state = estate;
X+ 
X+ 	connstate->startQual = ExecInitExpr( (Expr *)node->startQual, (PlanState *)connstate);
X+ 	connstate->parentExpr = ExecInitExpr((Expr *)node->parentExpr,(PlanState *)connstate);
X+ 	connstate->childExpr = ExecInitExpr( (Expr *)node->childExpr, (PlanState *)connstate);
X+ 
X+   connstate->conn_Done = false;
X+ 	connstate->tupleconnstate = NULL;
X+ 
X+ 	/*
X+ 	 * Miscellaneous initialization
X+ 	 */
X+   ExecAssignExprContext(estate, &connstate->ss.ps); 
X+ #define CONN_NSLOTS 2
X+ 
X+ 	/*
X+ 	 * tuple table initialization
X+ 	 */
X+ 	ExecInitResultTupleSlot(estate, &connstate->ss.ps);
X+ 	ExecInitScanTupleSlot(estate, &connstate->ss);
X+ 	/*
X+ 	 * initializes child nodes
X+ 	 */
X+   outerPlanState(connstate) = ExecInitNode(outerPlan(node), estate);
X+ 	/*
X+ 	 * initialize tuple type.  no need to initialize projection info
X+ 	 * because this node doesn't do projections.
X+ 	 */
X+ 	ExecAssignResultTypeFromOuterPlan(&connstate->ss.ps);
X+ 	ExecAssignScanTypeFromOuterPlan(&connstate->ss);
X+ 	connstate->ss.ps.ps_ProjInfo = NULL;
X+ 
X+ 	SO1_printf("ExecInitConn: %s\n",
X+ 			   "conn node initialized");
X+ 
X+ 	return connstate;
X+ }
X+ 
X+ int
X+ ExecCountSlotsConn(Conn *node)
X+ {
X+ 	return ExecCountSlotsNode(outerPlan((Plan *) node)) +
X+ 		ExecCountSlotsNode(innerPlan((Plan *) node))+CONN_NSLOTS;
X+ }
X+ 
X+ /* ----------------------------------------------------------------
X+  *		ExecEndConn(node)
X+  * ----------------------------------------------------------------
X+  */
X+ void
X+ ExecEndConn(ConnectState *node)
X+ {
X+ 	/*
X+ 	 * get info from the conn state
X+ 	 */
X+ 	SO1_printf("ExecEndConn: %s\n",
X+ 			   "shutting down conn node");
X+ 
X+ 	/*
X+ 	 * shut down the subplan
X+ 	 */
X+ 
X+ 	/*
X+ 	 * clean out the tuple table
X+ 	 */
X+ 	ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
X+ 	ExecClearTuple(node->ss.ss_ScanTupleSlot);
X+ 
X+ 	/*
X+ 	 * Release tupleconn resources
X+ 	 */
X+ 	if (node->tupleconnstate != NULL)
X+ 		tupleconn_end((Tupleconnstate *) node->tupleconnstate);
X+ 	node->tupleconnstate = NULL;
X+ 
X+ 	ExecEndNode(outerPlanState(node));
X+ 
X+ 	SO1_printf("ExecEndConn: %s\n",
X+ 			   "conn node shutdown");
X+ }
X+ 
X+ /* ----------------------------------------------------------------
X+  *		ExecConnMarkPos
X+  *
X+  *		Calls tupleconn to save the current position in the processed file.
X+  * ----------------------------------------------------------------
X+  */
X+ void
X+ ExecConnMarkPos(ConnectState *node)
X+ {
X+ 
X+ 	/*
X+ 	 * if we haven't processed yet, just return
X+ 	 */
X+ 	if (!node->conn_Done)
X+ 		return;
X+ 
X+ 	tupleconn_markpos((Tupleconnstate *) node->tupleconnstate);
X+ }
X+ 
X+ /* ----------------------------------------------------------------
X+  *		ExecConnRestrPos
X+  *
X+  *		Calls tupleconn to restore the last saved processed file position.
X+  * ----------------------------------------------------------------
X+  */
X+ void
X+ ExecConnRestrPos(ConnectState *node)
X+ {
X+ 
X+ 	/*
X+ 	 * if we haven't processed yet, just return.
X+ 	 */
X+ 	if (!node->conn_Done)
X+ 		return;
X+ 
X+ 	/*
X+ 	 * restore the scan to the previously marked position
X+ 	 */
X+ 	tupleconn_restorepos((Tupleconnstate *) node->tupleconnstate);
X+ }
X+ 
X+ void
X+ ExecReScanConn(ConnectState *node, ExprContext *exprCtxt)
X+ {
X+ 
X+ 	/*
X+ 	 * If we haven't processed yet, just return. If outerplan' chgParam is
X+ 	 * not NULL then it will be re-scanned by ExecProcNode, else - no
X+ 	 * reason to re-scan it at all.
X+ 	 */
X+ 	if (!node->conn_Done)
X+ 		return;
X+ 
X+ 	ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
X+ 
X+ 	/*
X+ 	 * If subnode is to be rescanned then we forget previous process results;
X+ 	 * we have to re-read the subplan and re-connect.
X+ 	 *
X+ 	 * Otherwise we can just rewind and rescan the processed output.
X+ 	 */
X+ 
X+ 	if (((PlanState *) node)->lefttree->chgParam != NULL)
X+ 	{
X+ 		node->conn_Done = false;
X+ 		tupleconn_end((Tupleconnstate *) node->tupleconnstate);
X+ 		node->tupleconnstate = NULL;
X+ 	}
X+ 	else
X+ 		tupleconn_rescan((Tupleconnstate *) node->tupleconnstate);
X+ 
X+ }
Xdiff -Prdc --exclude-from=exclude src/backend/nodes/copyfuncs.c src/backend/nodes/copyfuncs.c
X*** src/backend/nodes/copyfuncs.c	Sun Aug 17 23:43:25 2003
X--- src/backend/nodes/copyfuncs.c	Mon Jul  5 08:19:37 2004
X***************
X*** 455,460 ****
X--- 455,494 ----
X  	return newnode;
X  }
X  
X+ /* ----------------
X+  *		_copyConn
X+  * ----------------
X+  */
X+ static Conn *
X+ _copyConn(Conn *from)
X+ {
X+ 	List *tl,*ttl;
X+ 	Conn	   *newnode = makeNode(Conn);
X+ 	
X+ 	/*
X+  	 * copy node superclass fields
X+  	 */
X+  	CopyPlanFields((Plan *) from, (Plan *) newnode);
X+  	
X+  	COPY_NODE_FIELD(startQual);
X+ 
X+ 	COPY_NODE_FIELD(parentExpr);
X+  	COPY_NODE_FIELD(childExpr);
X+  	
X+  	COPY_SCALAR_FIELD(connOp);
X+ 
X+  	COPY_SCALAR_FIELD(levelColNum);
X+  	COPY_SCALAR_FIELD(useHash);
X+ 
X+ 	foreach(tl,from->priorsList){
X+ 	    ttl = lfirst(tl);
X+ 	    newnode->priorsList = lappend(newnode->priorsList,
X+ 		 makeListi2(lfirsti(ttl),lfirsti(lnext(ttl))));
X+ 	}
X+ 	
X+  	return newnode;
X+ }
X+  
X  
X  /*
X   * _copyGroup
X***************
X*** 663,668 ****
X--- 697,727 ----
X  	return newnode;
X  }
X  
X+ static FakeVar *
X+ _copyFakeVar(FakeVar *from)
X+ {
X+   FakeVar            *newnode = makeNode(FakeVar);
X+ 
X+   COPY_SCALAR_FIELD(varattno);
X+   COPY_SCALAR_FIELD(vartype);
X+   COPY_SCALAR_FIELD(vartypmod);
X+ 
X+   return newnode;
X+ }
X+ 
X+ static Prior *
X+ _copyPrior(Prior *from)
X+ {
X+ 	Prior		   *newnode = makeNode(Prior);
X+ 
X+ 	/*
X+ 	 * copy remainder of node
X+ 	 */
X+ 	COPY_SCALAR_FIELD(numcol);
X+ 
X+ 	return newnode;
X+ }
X+ 
X  /*
X   * _copyConst
X   */
X***************
X*** 1249,1254 ****
X--- 1308,1339 ----
X  	return newnode;
X  }
X  
X+ /* see _equalHierClause */
X+ static HierClause *
X+ _copyHierClause(HierClause *from)
X+ {
X+ 	List *tl,*ttl;
X+  	HierClause *newnode = makeNode(HierClause);
X+ 	
X+  	COPY_NODE_FIELD(startQual);
X+  	
X+  	COPY_NODE_FIELD(parentExpr);
X+ 	COPY_NODE_FIELD(childExpr);
X+ 	
X+  	COPY_SCALAR_FIELD(connOp);
X+  
X+  	COPY_SCALAR_FIELD(levelColNum);
X+  	COPY_SCALAR_FIELD(priorsListNItems);
X+  	COPY_SCALAR_FIELD(useHash);
X+ 	foreach(tl,from->priorsList){
X+ 	    ttl = lfirst(tl);
X+ 	    newnode->priorsList = lappend(newnode->priorsList,
X+ 		makeListi2(lfirsti(ttl),lfirsti(lnext(ttl))));
X+ 	}
X+ 
X+  	return newnode;
X+ }
X+  
X  static SortClause *
X  _copySortClause(SortClause *from)
X  {
X***************
X*** 1382,1387 ****
X--- 1467,1473 ----
X  	COPY_STRING_FIELD(name);
X  	COPY_NODE_FIELD(indirection);
X  	COPY_NODE_FIELD(val);
X+ 	COPY_SCALAR_FIELD(prior);
X  
X  	return newnode;
X  }
X***************
X*** 1526,1531 ****
X--- 1612,1620 ----
X  	COPY_NODE_FIELD(sortClause);
X  	COPY_NODE_FIELD(limitOffset);
X  	COPY_NODE_FIELD(limitCount);
X+ 
X+ 	COPY_NODE_FIELD(hierClause);
X+ 
X  	COPY_NODE_FIELD(setOperations);
X  	COPY_INTLIST_FIELD(resultRelations);
X  	COPY_NODE_FIELD(in_info_list);
X***************
X*** 2534,2539 ****
X--- 2623,2634 ----
X  		case T_Limit:
X  			retval = _copyLimit(from);
X  			break;
X+  		case T_Conn:
X+  			retval = _copyConn(from);
X+  			break;
X+  		case T_HierClause:
X+  			retval = _copyHierClause(from);
X+  			break;
X  
X  			/*
X  			 * PRIMITIVE NODES
X***************
X*** 2550,2555 ****
X--- 2645,2656 ----
X  		case T_Var:
X  			retval = _copyVar(from);
X  			break;
X+ 		case T_FakeVar:
X+ 			retval = _copyFakeVar(from);
X+ 			break;
X+ 		case T_Prior:
X+ 			retval = _copyPrior(from);
X+ 			break;
X  		case T_Const:
X  			retval = _copyConst(from);
X  			break;
Xdiff -Prdc --exclude-from=exclude src/backend/nodes/equalfuncs.c src/backend/nodes/equalfuncs.c
X*** src/backend/nodes/equalfuncs.c	Sun Aug 17 23:43:26 2003
X--- src/backend/nodes/equalfuncs.c	Mon Jul  5 08:19:37 2004
X***************
X*** 155,160 ****
X--- 155,178 ----
X  }
X  
X  static bool
X+ _equalFakeVar(FakeVar *a, FakeVar *b)
X+ {
X+   COMPARE_SCALAR_FIELD(varattno);
X+   COMPARE_SCALAR_FIELD(vartype);
X+   COMPARE_SCALAR_FIELD(vartypmod);
X+ 
X+   return true;
X+ }
X+ 
X+ static bool
X+ _equalPrior(Prior *a, Prior *b)
X+ {
X+ 	COMPARE_SCALAR_FIELD(numcol);
X+ 
X+ 	return true;
X+ }
X+   
X+ static bool
X  _equalConst(Const *a, Const *b)
X  {
X  	COMPARE_SCALAR_FIELD(consttype);
X***************
X*** 622,627 ****
X--- 640,648 ----
X  	COMPARE_NODE_FIELD(sortClause);
X  	COMPARE_NODE_FIELD(limitOffset);
X  	COMPARE_NODE_FIELD(limitCount);
X+ 
X+ 	COMPARE_NODE_FIELD(hierClause);
X+ 
X  	COMPARE_NODE_FIELD(setOperations);
X  	COMPARE_INTLIST_FIELD(resultRelations);
X  	COMPARE_NODE_FIELD(in_info_list);
X***************
X*** 637,642 ****
X--- 658,684 ----
X  }
X  
X  static bool
X+ _equalHierClause(HierClause *a, HierClause *b)
X+ {
X+ 	if (!equal(a->startQual, b->startQual))
X+ 		return false;
X+ 	if (!equal(a->parentExpr, b->parentExpr))
X+ 		return false;
X+ 	if (!equal(a->childExpr, b->childExpr))
X+ 		return false;
X+ 	/* we can skip comparing the connOpName because in the DB
X+ 	 * can't exist at the same time several operators with
X+ 	 * same name and parameters, it's checked by PG.
X+ 	 */
X+ 	COMPARE_SCALAR_FIELD(connOp);
X+ 	COMPARE_SCALAR_FIELD(levelColNum);
X+ 	COMPARE_SCALAR_FIELD(priorsListNItems);
X+ 	COMPARE_SCALAR_FIELD(useHash);
X+ 	
X+ 	return true;
X+ }
X+ 
X+ static bool
X  _equalInsertStmt(InsertStmt *a, InsertStmt *b)
X  {
X  	COMPARE_NODE_FIELD(relation);
X***************
X*** 1674,1679 ****
X--- 1716,1727 ----
X  		case T_Var:
X  			retval = _equalVar(a, b);
X  			break;
X+ 		case T_FakeVar:
X+ 			retval = _equalFakeVar(a, b);
X+ 			break;
X+ 		case T_Prior:
X+ 			retval = _equalPrior(a, b);
X+ 			break;
X  		case T_Const:
X  			retval = _equalConst(a, b);
X  			break;
X***************
X*** 2089,2095 ****
X  		case T_FuncWithArgs:
X  			retval = _equalFuncWithArgs(a, b);
X  			break;
X! 
X  		default:
X  			elog(ERROR, "unrecognized node type: %d",
X  				 (int) nodeTag(a));
X--- 2137,2146 ----
X  		case T_FuncWithArgs:
X  			retval = _equalFuncWithArgs(a, b);
X  			break;
X!     case T_HierClause:
X!       retval = _equalHierClause(a, b);
X!       break;
X!                          
X  		default:
X  			elog(ERROR, "unrecognized node type: %d",
X  				 (int) nodeTag(a));
Xdiff -Prdc --exclude-from=exclude src/backend/nodes/outfuncs.c src/backend/nodes/outfuncs.c
X*** src/backend/nodes/outfuncs.c	Sun Aug 17 23:43:26 2003
X--- src/backend/nodes/outfuncs.c	Mon Jul  5 08:19:37 2004
X***************
X*** 575,580 ****
X--- 575,600 ----
X  	WRITE_INT_FIELD(varoattno);
X  }
X  
X+ /*
X+  *    FakeVar is a subclass of Expr
X+  */
X+ static void
X+ _outFakeVar(StringInfo str, FakeVar *node)
X+ {
X+ 	WRITE_NODE_TYPE("FAKEVAR");
X+ 
X+ 	WRITE_INT_FIELD(varattno);
X+ 	WRITE_OID_FIELD(vartype);
X+ 	WRITE_INT_FIELD(vartypmod);
X+ }
X+ static void
X+ _outPrior(StringInfo str, Prior *node)
X+ {
X+ 	appendStringInfo(str,
X+ 				" PRIOR :numcol %d ", node->numcol);
X+ }
X+ 
X+ 
X  static void
X  _outConst(StringInfo str, Const *node)
X  {
X***************
X*** 1256,1261 ****
X--- 1276,1282 ----
X  	WRITE_NODE_FIELD(sortClause);
X  	WRITE_NODE_FIELD(limitOffset);
X  	WRITE_NODE_FIELD(limitCount);
X+ 	WRITE_NODE_FIELD(hierClause);
X  	WRITE_NODE_FIELD(setOperations);
X  	WRITE_INTLIST_FIELD(resultRelations);
X  
X***************
X*** 1263,1268 ****
X--- 1284,1317 ----
X  }
X  
X  static void
X+ _outHierClause(StringInfo str, HierClause *node)
X+ {
X+ 	List *tl;
X+ 	
X+  	appendStringInfo(str, " HIERCLAUSE :startQual ");
X+  	_outNode(str, node->startQual);
X+ 	
X+  	appendStringInfo(str, " :parentExpr ");
X+  	_outNode(str, node->parentExpr);
X+  	
X+  	appendStringInfo(str, " :childExpr ");
X+  	_outNode(str, node->childExpr);
X+  	
X+ 	appendStringInfo(str, " :priorsListNItemsCount %d ",node->priorsListNItems);
X+ 
X+ 	appendStringInfo(str, " :levelColNum %d ",node->levelColNum);
X+ 
X+  	appendStringInfo(str, " :priorsList ");
X+ 	foreach(tl, node->priorsList){
X+ 	    _outIntList(str,lfirst(tl));
X+ 	}  
X+   
X+  	appendStringInfo(str, " :connOp %u ",node->connOp);
X+ 
X+  	appendStringInfo(str, " :useHash %s ",booltostr(node->useHash));
X+ }
X+  
X+ static void
X  _outSortClause(StringInfo str, SortClause *node)
X  {
X  	WRITE_NODE_TYPE("SORTCLAUSE");
X***************
X*** 1625,1630 ****
X--- 1674,1685 ----
X  			case T_Var:
X  				_outVar(str, obj);
X  				break;
X+ 			case T_FakeVar:
X+ 				_outFakeVar(str, obj);
X+ 				break;
X+  			case T_Prior:
X+  				_outPrior(str, obj);
X+  				break;
X  			case T_Const:
X  				_outConst(str, obj);
X  				break;
X***************
X*** 1816,1821 ****
X--- 1871,1879 ----
X  			case T_FuncCall:
X  				_outFuncCall(str, obj);
X  				break;
X+  			case T_HierClause:
X+  				_outHierClause(str, obj);
X+  				break;
X  
X  			default:
X  
Xdiff -Prdc --exclude-from=exclude src/backend/nodes/readfuncs.c src/backend/nodes/readfuncs.c
X*** src/backend/nodes/readfuncs.c	Sun Aug 17 23:43:26 2003
X--- src/backend/nodes/readfuncs.c	Mon Jul  5 08:19:37 2004
X***************
X*** 211,216 ****
X--- 211,217 ----
X  	READ_NODE_FIELD(sortClause);
X  	READ_NODE_FIELD(limitOffset);
X  	READ_NODE_FIELD(limitCount);
X+ 	READ_NODE_FIELD(hierClause);
X  	READ_NODE_FIELD(setOperations);
X  	READ_INTLIST_FIELD(resultRelations);
X  
X***************
X*** 219,224 ****
X--- 220,253 ----
X  	READ_DONE();
X  }
X  
X+ /* ----------------
X+  *		_readHierClause
X+  * ----------------
X+  */
X+ static HierClause *
X+ _readHierClause(void)
X+ {
X+   int i;
X+   READ_LOCALS(HierClause);
X+   
X+   READ_NODE_FIELD(startQual);
X+   READ_NODE_FIELD(parentExpr);
X+   READ_NODE_FIELD(childExpr);
X+   
X+   
X+   READ_UINT_FIELD(priorsListNItems);
X+   READ_UINT_FIELD(levelColNum);
X+   token = pg_strtok(&length); /* skip :priorsList */
X+   for(i=0;i<local_node->priorsListNItems;i++){
X+     local_node->priorsList = lappend(local_node->priorsList,toIntList(nodeRead(true)));
X+   }
X+ 
X+   READ_OID_FIELD(connOp);
X+   READ_BOOL_FIELD(useHash);
X+   
X+   READ_DONE();
X+ }
X+ 
X  /*
X   * _readNotifyStmt
X   */
X***************
X*** 364,369 ****
X--- 393,423 ----
X  	READ_DONE();
X  }
X  
X+ 
X+ /*
X+  *    _readFakeVar
X+  */
X+ static FakeVar *
X+ _readFakeVar(void)
X+ {
X+   READ_LOCALS(FakeVar);
X+ 
X+ 	READ_INT_FIELD(varattno);
X+ 	READ_OID_FIELD(vartype);
X+ 	READ_INT_FIELD(vartypmod);
X+ 
X+   READ_DONE();
X+ }
X+ static Prior *
X+ _readPrior(void)
X+ {
X+     READ_LOCALS(Prior);
X+ 
X+     READ_INT_FIELD(numcol);
X+     READ_DONE();
X+ }
X+ 
X+ 
X  /*
X   * _readConst
X   */
X***************
X*** 983,988 ****
X--- 1037,1044 ----
X  		return_value = _readRangeVar();
X  	else if (MATCH("VAR", 3))
X  		return_value = _readVar();
X+ 	else if (MATCH("FAKEVAR", 7))
X+ 		return_value = _readFakeVar();
X  	else if (MATCH("CONST", 5))
X  		return_value = _readConst();
X  	else if (MATCH("PARAM", 5))
X***************
X*** 1049,1054 ****
X--- 1105,1114 ----
X  		return_value = _readNotifyStmt();
X  	else if (MATCH("DECLARECURSOR", 13))
X  		return_value = _readDeclareCursorStmt();
X+ 	else if (MATCH("HIERCLAUSE", 10))
X+ 		return_value = _readHierClause();
X+  	else if (MATCH("PRIOR", 5))
X+  		return_value = _readPrior();
X  	else
X  	{
X  		elog(ERROR, "badly formatted node string \"%.32s\"...", token);
Xdiff -Prdc --exclude-from=exclude src/backend/optimizer/path/costsize.c src/backend/optimizer/path/costsize.c
X*** src/backend/optimizer/path/costsize.c	Tue Apr  6 18:46:25 2004
X--- src/backend/optimizer/path/costsize.c	Mon Jul  5 08:19:37 2004
X***************
X*** 479,484 ****
X--- 479,549 ----
X  	path->total_cost = startup_cost + run_cost;
X  }
X  
X+ void
X+ cost_conn(Path *path, Query *root,
X+ 		  List *pathkeys, double tuples, int width)
X+ {
X+ 	Cost		startup_cost = 0;
X+ 	Cost		run_cost = 0;	
X+ 	double		nbytes = relation_byte_size(tuples, width);
X+ 	long		sortmembytes = SortMem * 1024L;
X+ 	double	x,cmpamnt,i,j;
X+ 
X+ 	/*
X+ 	 * We want to be sure the cost of a sort is never estimated as zero,
X+  	 * even if passed-in tuple count is zero.  Besides, mustn't do
X+  	 * log(0)...
X+  	 */
X+  	if (tuples < 2.0)
X+  		tuples = 2.0;
X+  
X+  	x = log(tuples)/log(log(tuples));
X+  	x = floor(x); //number of runs, slightly overestimated
X+ 	
X+  	cmpamnt=0.0;
X+  	for(i=1;i<x;i++)
X+  		for(j=0;j<x-i-1;j++)
X+  			cmpamnt+=pow(x,x-j);
X+  	cmpamnt=floor(cmpamnt/2);// rought amount of compares = half of worst case
X+  	if (cmpamnt < 1.0)
X+  		cmpamnt=1.0;
X+  	/*
X+  	 * CPU costs
X+  	 *
X+ 	 * assume: cost of comparation + cost of evaluating parent and child expr ==
X+ 	 *           3 * cost of comparation 
X+ 	 * cost is:	3 * cost of comparation *
X+ 	 *            ( amount of compares + check every tuple for being top node )
X+ 	 * if HAVING clause present then add cost of qualification of every tuple.
X+ 	 * assume we're connected all of input tuples, in real this may be not a true, so
X+ 	 * we're estimating the worst case.
X+  	 */
X+  	startup_cost += 3 * cpu_operator_cost * ( cmpamnt + tuples );
X+  	if(root->havingQual){
X+  		startup_cost += cpu_operator_cost * tuples;
X+  	}
X+  
X+  	/* disk costs */
X+  	if (nbytes > sortmembytes)
X+  	{
X+  		double		npages = ceil(nbytes / BLCKSZ);
X+  		double		npageaccesses;
X+  
X+  		npageaccesses = 2.0 * npages * x;
X+  		/* Assume half are sequential (cost 1), half are not */
X+  		startup_cost += npageaccesses *
X+  			(1.0 + cost_nonsequential_access(npages)) * 0.5;
X+  	}
X+  
X+  	/*
X+  	 * Note: should we bother to assign a nonzero run_cost to reflect the
X+  	 * overhead of extracting tuples from the sort result?	Probably not
X+  	 * worth worrying about.
X+  	 */
X+  	path->startup_cost = startup_cost;
X+  	path->total_cost = startup_cost + run_cost;
X+ }
X+  
X  /*
X   * cost_sort
X   *	  Determines and returns the cost of sorting a relation, including
Xdiff -Prdc --exclude-from=exclude src/backend/optimizer/plan/createplan.c src/backend/optimizer/plan/createplan.c
X*** src/backend/optimizer/plan/createplan.c	Sun Feb 29 17:36:48 2004
X--- src/backend/optimizer/plan/createplan.c	Mon Jul  5 08:19:37 2004
X***************
X*** 1595,1600 ****
X--- 1595,1637 ----
X  	return node;
X  }
X  
X+ /* called in same terms as make_sort.
X+  * copy fileds from HierClause to newly created Conn node,
X+  * and calc costs 
X+  */
X+ Conn *
X+ make_conn(Query *root,
X+ 			 List *tlist,
X+ 			 Plan *lefttree)
X+ {
X+ 	Conn    *node = makeNode(Conn);
X+  	Plan	   *plan = &node->plan;
X+  	HierClause *hier = (HierClause *)root->hierClause;
X+  	Path		conn_path;		/* dummy for result of cost_conn */
X+  
X+   copy_plan_costsize(plan, lefttree); /* only care about copying size */
X+ // 	cost_conn(&conn_path, root, NIL,
X+ // 			  lefttree->plan_rows, lefttree->plan_width);
X+  	plan->startup_cost = conn_path.startup_cost + lefttree->startup_cost;
X+  	plan->total_cost = conn_path.total_cost + lefttree->total_cost;
X+  
X+  	plan->plan_rows = lefttree->plan_rows;
X+  	plan->plan_width = lefttree->plan_width;
X+  	plan->targetlist = tlist;
X+  	plan->qual = (List *)root->havingQual;
X+  	plan->lefttree = lefttree;
X+  	plan->righttree = NULL;
X+  	node->startQual = hier->startQual;
X+ 	node->parentExpr = hier->parentExpr;
X+ 	node->levelColNum = hier->levelColNum;
X+ 		
X+ 	node->childExpr = hier->childExpr;
X+  	node->connOp = hier->connOp;
X+ 	node->priorsList = hier->priorsList;
X+ 	node->useHash = hier->useHash;
X+  	return node;
X+ }
X+ 
X  Append *
X  make_append(List *appendplans, bool isTarget, List *tlist)
X  {
Xdiff -Prdc --exclude-from=exclude src/backend/optimizer/plan/planner.c src/backend/optimizer/plan/planner.c
X*** src/backend/optimizer/plan/planner.c	Tue May 11 02:21:55 2004
X--- src/backend/optimizer/plan/planner.c	Mon Jul  5 08:19:37 2004
X***************
X*** 49,54 ****
X--- 49,55 ----
X  #define EXPRKIND_RTFUNC 2
X  #define EXPRKIND_LIMIT	3
X  #define EXPRKIND_ININFO 4
X+ #define EXPRKIND_STARTWITH 5
X  
X  
X  static Node *preprocess_expression(Query *parse, Node *expr, int kind);
X***************
X*** 131,138 ****
X  	}
X  
X  	/* executor wants to know total number of Params used overall */
X! 	result_plan->nParamExec = length(PlannerParamList);
X! 
X  	/* final cleanup of the plan */
X  	set_plan_references(result_plan, parse->rtable);
X  
X--- 132,138 ----
X  	}
X  
X  	/* executor wants to know total number of Params used overall */
X!  	result_plan->nParamExec = length(PlannerParamList);
X  	/* final cleanup of the plan */
X  	set_plan_references(result_plan, parse->rtable);
X  
X***************
X*** 242,248 ****
X--- 242,256 ----
X  	parse->in_info_list = (List *)
X  		preprocess_expression(parse, (Node *) parse->in_info_list,
X  							  EXPRKIND_ININFO);
X+  	if(parse->hierClause){
X+  		((HierClause *)parse->hierClause)->startQual = preprocess_expression(parse, ((HierClause *)parse->hierClause)->startQual,
X+  											  EXPRKIND_STARTWITH);
X  
X+  		((HierClause *)parse->hierClause)->parentExpr = preprocess_expression(parse, ((HierClause *)parse->hierClause)->parentExpr,
X+  											  EXPRKIND_STARTWITH);
X+  		((HierClause *)parse->hierClause)->childExpr = preprocess_expression(parse, ((HierClause *)parse->hierClause)->childExpr,
X+  											  EXPRKIND_STARTWITH);		
X+  	}
X  	/* Also need to preprocess expressions for function RTEs */
X  	foreach(lst, parse->rtable)
X  	{
X***************
X*** 270,287 ****
X  	 * implicitly-ANDed-list form at this point, even though they are
X  	 * declared as Node *.
X  	 */
X! 	newHaving = NIL;
X! 	foreach(lst, (List *) parse->havingQual)
X! 	{
X! 		Node	   *havingclause = (Node *) lfirst(lst);
X  
X! 		if (contain_agg_clause(havingclause))
X! 			newHaving = lappend(newHaving, havingclause);
X! 		else
X! 			parse->jointree->quals = (Node *)
X! 				lappend((List *) parse->jointree->quals, havingclause);
X! 	}
X! 	parse->havingQual = (Node *) newHaving;
X  
X  	/*
X  	 * If we have any outer joins, try to reduce them to plain inner
X--- 278,297 ----
X  	 * implicitly-ANDed-list form at this point, even though they are
X  	 * declared as Node *.
X  	 */
X! 	if(!parse->hierClause){
X! 		newHaving = NIL;
X! 		foreach(lst, (List *) parse->havingQual)
X! 		{
X! 			Node	   *havingclause = (Node *) lfirst(lst);
X  
X! 			if (contain_agg_clause(havingclause))
X! 				newHaving = lappend(newHaving, havingclause);
X! 			else
X! 				parse->jointree->quals = (Node *)
X! 					lappend((List *) parse->jointree->quals, havingclause);
X! 		}
X! 		parse->havingQual = (Node *) newHaving;
X!  	}
X  
X  	/*
X  	 * If we have any outer joins, try to reduce them to plain inner
X***************
X*** 565,571 ****
X  	List	   *current_pathkeys;
X  	List	   *sort_pathkeys;
X  
X! 	if (parse->setOperations)
X  	{
X  		/*
X  		 * Construct the plan for set operations.  The result will not
X--- 575,581 ----
X  	List	   *current_pathkeys;
X  	List	   *sort_pathkeys;
X  
X!   if (parse->setOperations)
X  	{
X  		/*
X  		 * Construct the plan for set operations.  The result will not
X***************
X*** 1291,1297 ****
X  												 result_plan->plan_rows);
X  		}
X  	}
X! 
X  	/*
X  	 * Finally, if there is a LIMIT/OFFSET clause, add the LIMIT node.
X  	 */
X--- 1301,1313 ----
X  												 result_plan->plan_rows);
X  		}
X  	}
X!  	/*
X!  	 * If there is a CONNECT BY clause, add the CONN node
X!  	 */
X!  	if (parse->hierClause)
X!  	{
X!  		result_plan = (Plan *) make_conn(parse, tlist, result_plan);
X!  	}
X  	/*
X  	 * Finally, if there is a LIMIT/OFFSET clause, add the LIMIT node.
X  	 */
Xdiff -Prdc --exclude-from=exclude src/backend/optimizer/plan/setrefs.c src/backend/optimizer/plan/setrefs.c
X*** src/backend/optimizer/plan/setrefs.c	Tue May 11 13:15:23 2004
X--- src/backend/optimizer/plan/setrefs.c	Mon Jul  5 08:19:37 2004
X***************
X*** 22,27 ****
X--- 22,28 ----
X  #include "optimizer/var.h"
X  #include "parser/parsetree.h"
X  #include "utils/lsyscache.h"
X+ #include "catalog/pg_type.h"
X  
X  
X  typedef struct
X***************
X*** 185,190 ****
X--- 186,201 ----
X  			fix_expr_references(plan,
X  								(Node *) ((Hash *) plan)->hashkeys);
X  			break;
X+  		case T_Conn:
X+  			set_uppernode_references(plan, (Index) 0);			
X+ 
X+  			fix_expr_references(plan, (Node *) plan->targetlist);
X+  			fix_expr_references(plan, (Node *) plan->qual);
X+  			fix_expr_references(plan, (Node *)((Conn *) plan)->startQual);
X+ 
X+  			fix_expr_references(plan, (Node *)((Conn *) plan)->parentExpr);
X+  			fix_expr_references(plan, (Node *)((Conn *) plan)->childExpr);
X+  			break;
X  		case T_Material:
X  		case T_Sort:
X  		case T_Unique:
X***************
X*** 490,495 ****
X--- 501,524 ----
X  									   subvarno,
X  									   subplan_targetlist,
X  									   tlist_has_non_vars);
X+  	if(IsA( plan, Conn)){
X+  		((Conn *)plan)->startQual = 
X+  			replace_vars_with_subplan_refs((Node *) ((Conn *)plan)->startQual,
X+  									   subvarno,
X+  									   subplan_targetlist,
X+  									   tlist_has_non_vars);
X+ 
X+  		((Conn *)plan)->parentExpr =
X+  			replace_vars_with_subplan_refs((Node *) ((Conn *)plan)->parentExpr,
X+  									   subvarno,
X+  									   subplan_targetlist,
X+  									   tlist_has_non_vars);
X+  		((Conn *)plan)->childExpr = 
X+  			replace_vars_with_subplan_refs((Node *) ((Conn *)plan)->childExpr,
X+  									   subvarno,
X+  									   subplan_targetlist,
X+  									   tlist_has_non_vars);
X+  	}
X  }
X  
X  /*
X***************
X*** 564,570 ****
X  {
X  	if (node == NULL)
X  		return NULL;
X! 	if (IsA(node, Var))
X  	{
X  		Var		   *var = (Var *) node;
X  		Resdom	   *resdom;
X--- 593,608 ----
X  {
X  	if (node == NULL)
X  		return NULL;
X! 	if (IsA(node, FakeVar))
X! 	{
X! 		/* FakeVar isn't present on subplan so just copy it*/
X! 		FakeVar		   *var = (FakeVar *) node;
X! 		FakeVar		   *newvar;
X! 
X! 		newvar = (FakeVar *) copyObject((Node *)var);
X! 		return (Node *) newvar;
X! 	}
X! 	else if (IsA(node, Var))
X  	{
X  		Var		   *var = (Var *) node;
X  		Resdom	   *resdom;
X***************
X*** 682,688 ****
X  {
X  	if (node == NULL)
X  		return NULL;
X! 	if (IsA(node, Var))
X  	{
X  		Var		   *var = (Var *) node;
X  		Resdom	   *resdom;
X--- 720,735 ----
X  {
X  	if (node == NULL)
X  		return NULL;
X! 	if (IsA(node, FakeVar))
X! 	{
X! 		/* FakeVar isn't present on subplan so just copy it*/
X! 		FakeVar		   *var = (FakeVar *) node;
X! 		FakeVar		   *newvar;
X! 
X! 		newvar = (FakeVar *) copyObject((Node *)var);
X! 		return (Node *) newvar;
X! 	}
X! 	else if (IsA(node, Var))
X  	{
X  		Var		   *var = (Var *) node;
X  		Resdom	   *resdom;
Xdiff -Prdc --exclude-from=exclude src/backend/optimizer/plan/subselect.c src/backend/optimizer/plan/subselect.c
X*** src/backend/optimizer/plan/subselect.c	Tue May 11 13:15:23 2004
X--- src/backend/optimizer/plan/subselect.c	Mon Jul  5 08:19:37 2004
X***************
X*** 444,449 ****
X--- 444,450 ----
X  				case T_Material:
X  				case T_FunctionScan:
X  				case T_Sort:
X+ 				case T_Conn:
X  
X  					/*
X  					 * Don't add another Material node if there's one
X***************
X*** 1037,1042 ****
X--- 1038,1044 ----
X  		case T_Unique:
X  		case T_SetOp:
X  		case T_Group:
X+ 		case T_Conn:
X  			break;
X  
X  		default:
Xdiff -Prdc --exclude-from=exclude src/backend/optimizer/prep/prepjointree.c src/backend/optimizer/prep/prepjointree.c
X*** src/backend/optimizer/prep/prepjointree.c	Sat Jan 10 00:30:39 2004
X--- src/backend/optimizer/prep/prepjointree.c	Mon Jul  5 08:19:37 2004
X***************
X*** 257,262 ****
X--- 257,275 ----
X  				ResolveNew((Node *) parse->in_info_list,
X  						   varno, 0, subtlist, CMD_SELECT, 0);
X  
X+  			if(parse->hierClause){
X+  				((HierClause *)parse->hierClause)->startQual = 
X+  						ResolveNew(((HierClause *)parse->hierClause)->startQual,
X+  								   varno, 0, subtlist, CMD_SELECT, 0);
X+ 
X+  				((HierClause *)parse->hierClause)->parentExpr = 
X+  						ResolveNew(((HierClause *)parse->hierClause)->parentExpr,
X+  								   varno, 0, subtlist, CMD_SELECT, 0);
X+  				((HierClause *)parse->hierClause)->childExpr = 
X+  						ResolveNew(((HierClause *)parse->hierClause)->childExpr,
X+  								   varno, 0, subtlist, CMD_SELECT, 0);
X+  			}
X+ 
X  			foreach(rt, parse->rtable)
X  			{
X  				RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
X***************
X*** 408,413 ****
X--- 421,427 ----
X  		subquery->groupClause ||
X  		subquery->havingQual ||
X  		subquery->sortClause ||
X+  		subquery->hierClause ||
X  		subquery->distinctClause ||
X  		subquery->limitOffset ||
X  		subquery->limitCount)
Xdiff -Prdc --exclude-from=exclude src/backend/optimizer/util/clauses.c src/backend/optimizer/util/clauses.c
X*** src/backend/optimizer/util/clauses.c	Wed Jan 28 00:05:25 2004
X--- src/backend/optimizer/util/clauses.c	Mon Jul  5 08:19:37 2004
X***************
X*** 2226,2231 ****
X--- 2226,2232 ----
X  	switch (nodeTag(node))
X  	{
X  		case T_Var:
X+ 		case T_FakeVar:
X  		case T_Const:
X  		case T_Param:
X  		case T_CoerceToDomainValue:
X***************
X*** 2233,2238 ****
X--- 2234,2244 ----
X  		case T_RangeTblRef:
X  			/* primitive node types with no subnodes */
X  			break;
X+ 		case T_Prior:
X+ 			{
X+ 				return walker(((Prior *) node)->val, context);
X+ 			}
X+ 			break;
X  		case T_Aggref:
X  			return walker(((Aggref *) node)->target, context);
X  		case T_ArrayRef:
X***************
X*** 2432,2437 ****
X--- 2438,2454 ----
X  					 errmsg("relation reference \"%s\" cannot be used in an expression",
X  							((RangeVar *) node)->relname)));
X  			break;
X+  		case T_HierClause:
X+  			{
X+  				HierClause *hier = (HierClause *)node;
X+  				if (walker(hier->startQual, context))
X+  					return true;
X+  				if (walker(hier->parentExpr, context))
X+  					return true;
X+  				if (walker(hier->childExpr, context))
X+  					return true;
X+  			}
X+  			break;
X  		default:
X  			elog(ERROR, "unrecognized node type: %d",
X  				 (int) nodeTag(node));
X***************
X*** 2479,2484 ****
X--- 2496,2504 ----
X  		return true;
X  	if (walker(query->in_info_list, context))
X  		return true;
X+  	if (walker(query->hierClause, context))
X+  		return true;
X+  	
X  	foreach(rt, query->rtable)
X  	{
X  		RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
X***************
X*** 2599,2604 ****
X--- 2619,2625 ----
X  	switch (nodeTag(node))
X  	{
X  		case T_Var:
X+ 		case T_FakeVar:
X  		case T_Const:
X  		case T_Param:
X  		case T_CoerceToDomainValue:
X***************
X*** 2606,2611 ****
X--- 2627,2642 ----
X  		case T_RangeTblRef:
X  			/* primitive node types with no subnodes */
X  			return (Node *) copyObject(node);
X+ 		case T_Prior:
X+ 			{
X+ 			Prior *expr = (Prior *) node;
X+ 			Prior *newnode;
X+ 
X+ 			FLATCOPY(newnode, expr, Prior);
X+ 			MUTATE(newnode->val, expr->val, Node *);
X+ 			return (Node *) newnode;
X+ 			}
X+ 			break;
X  		case T_Aggref:
X  			{
X  				Aggref	   *aggref = (Aggref *) node;
Xdiff -Prdc --exclude-from=exclude src/backend/optimizer/util/var.c src/backend/optimizer/util/var.c
X*** src/backend/optimizer/util/var.c	Fri Aug  8 21:41:55 2003
X--- src/backend/optimizer/util/var.c	Mon Jul  5 08:19:37 2004
X***************
X*** 225,230 ****
X--- 225,232 ----
X  {
X  	if (node == NULL)
X  		return false;
X+ 	if(IsA(node, FakeVar)) /* fake vars are vars too */
X+ 		return true;
X  	if (IsA(node, Var))
X  	{
X  		if (((Var *) node)->varlevelsup == 0)
Xdiff -Prdc --exclude-from=exclude src/backend/parser/analyze.c src/backend/parser/analyze.c
X*** src/backend/parser/analyze.c	Wed Nov  5 22:00:52 2003
X--- src/backend/parser/analyze.c	Mon Jul  5 08:19:37 2004
X***************
X*** 1957,1963 ****
X--- 1957,1969 ----
X  	transformFromClause(pstate, stmt->fromClause);
X  
X  	/* transform targetlist */
X+ 	/* set flag for '_level_' column can be selected and aliased in target list
X+ 	 * and for PRIOR keyword checks
X+ 	 */
X+ 	if(stmt->hierClause)
X+ 	pstate->p_hierExists = 1; 
X  	qry->targetList = transformTargetList(pstate, stmt->targetList);
X+ 	pstate->p_hierExists = 0;
X  
X  	/* handle any SELECT INTO/CREATE TABLE AS spec */
X  	qry->into = stmt->into;
X***************
X*** 1970,1975 ****
X--- 1976,1984 ----
X  	/* transform WHERE */
X  	qual = transformWhereClause(pstate, stmt->whereClause, "WHERE");
X  
X+ 	/* transform CONNECT BY , START WITH clause */
X+ 	qry->hierClause=transformHierClause(pstate,qry,stmt->hierClause);
X+ 
X  	/*
X  	 * Initial processing of HAVING clause is just like WHERE clause.
X  	 * Additional work will be done in optimizer/plan/planner.c.
Xdiff -Prdc --exclude-from=exclude src/backend/parser/gram.y src/backend/parser/gram.y
X*** src/backend/parser/gram.y	Mon Nov 24 16:54:15 2003
X--- src/backend/parser/gram.y	Mon Jul  5 08:19:37 2004
X***************
X*** 318,323 ****
X--- 318,325 ----
X  %type <list>	constraints_set_list
X  %type <boolean> constraints_set_mode
X  
X+ %type <node>  startwith_clause
X+ %type <list>  connectby_clause hier_clause 
X  
X  /*
X   * If you make any token changes, update the keyword table in
X***************
X*** 336,343 ****
X  	CACHE CALLED CASCADE CASE CAST CHAIN CHAR_P
X  	CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE
X  	CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT
X! 	COMMITTED CONSTRAINT CONSTRAINTS CONVERSION_P CONVERT COPY CREATE CREATEDB
X! 	CREATEUSER CROSS CURRENT_DATE CURRENT_TIME
X  	CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE
X  
X  	DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS
X--- 338,345 ----
X  	CACHE CALLED CASCADE CASE CAST CHAIN CHAR_P
X  	CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE
X  	CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT
X! 	COMMITTED CONNECT CONSTRAINT CONSTRAINTS CONVERSION_P CONVERT 
X! 	COPY CREATE CREATEDB CREATEUSER CROSS CURRENT_DATE CURRENT_TIME
X  	CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE
X  
X  	DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS
X***************
X*** 4455,4461 ****
X  simple_select:
X  			SELECT opt_distinct target_list
X  			into_clause from_clause where_clause
X! 			group_clause having_clause
X  				{
X  					SelectStmt *n = makeNode(SelectStmt);
X  					n->distinctClause = $2;
X--- 4457,4463 ----
X  simple_select:
X  			SELECT opt_distinct target_list
X  			into_clause from_clause where_clause
X! 			group_clause hier_clause having_clause
X  				{
X  					SelectStmt *n = makeNode(SelectStmt);
X  					n->distinctClause = $2;
X***************
X*** 4465,4471 ****
X  					n->fromClause = $5;
X  					n->whereClause = $6;
X  					n->groupClause = $7;
X! 					n->havingClause = $8;
X  					$$ = (Node *)n;
X  				}
X  			| select_clause UNION opt_all select_clause
X--- 4467,4474 ----
X  					n->fromClause = $5;
X  					n->whereClause = $6;
X  					n->groupClause = $7;
X!  					n->havingClause = $9;
X!  					n->hierClause = $8;
X  					$$ = (Node *)n;
X  				}
X  			| select_clause UNION opt_all select_clause
X***************
X*** 4487,4492 ****
X--- 4490,4518 ----
X  			| /*EMPTY*/								{ $$ = NULL; }
X  		;
X  
X+ hier_clause: connectby_clause startwith_clause 
X+  			{ 
X+  				$$ = makeList2($1,$2); 
X+  			}
X+  		| startwith_clause connectby_clause 
X+  			{ 
X+  				$$ = makeList2($2,$1); 
X+  			}
X+  		| /* EMPTY */ { $$ = NULL; }
X+  		;
X+  
X+ connectby_clause: CONNECT BY PRIOR c_expr all_Op c_expr
X+ 			{ 
X+  			  $$ = makeList3($4,makeString($5),$6); 
X+  			}
X+ 		| CONNECT BY a_expr all_Op PRIOR a_expr
X+ 			{ 
X+  			  $$ = makeList3($6,makeString($4),$3); 
X+  			}
X+  		;
X+ startwith_clause: START WITH a_expr { $$ = $3; }
X+  		;
X+  		
X  /*
X   * Redundancy here is needed to avoid shift/reduce conflicts,
X   * since TEMP is not a reserved word.  See also OptTemp.
X***************
X*** 6979,6984 ****
X--- 7005,7026 ----
X  					$$->indirection = NIL;
X  					$$->val = (Node *)$1;
X  				}
X+ 			| PRIOR a_expr AS ColLabel
X+ 				{
X+ 					$$ = makeNode(ResTarget);
X+ 					$$->name = $4;
X+ 					$$->indirection = NIL;
X+ 					$$->val = (Node *)$2;
X+ 					$$->prior = 1;
X+ 				}
X+ 			| PRIOR a_expr
X+ 				{
X+ 					$$ = makeNode(ResTarget);
X+ 					$$->name = NULL;
X+ 					$$->indirection = NIL;
X+ 					$$->val = (Node *)$2;
X+ 					$$->prior = 1;
X+ 				}
X  			| '*'
X  				{
X  					ColumnRef *n = makeNode(ColumnRef);
X***************
X*** 7398,7404 ****
X  			| PRECISION
X  			| PREPARE
X  			| PRESERVE
X- 			| PRIOR
X  			| PRIVILEGES
X  			| PROCEDURAL
X  			| PROCEDURE
X--- 7440,7445 ----
X***************
X*** 7428,7434 ****
X  			| SHOW
X  			| SIMPLE
X  			| STABLE
X- 			| START
X  			| STATEMENT
X  			| STATISTICS
X  			| STDIN
X--- 7469,7474 ----
X***************
X*** 7566,7571 ****
X--- 7606,7612 ----
X  			| CHECK
X  			| COLLATE
X  			| COLUMN
X+ 			| CONNECT
X  			| CONSTRAINT
X  			| CREATE
X  			| CURRENT_DATE
X***************
X*** 7606,7615 ****
X--- 7647,7658 ----
X  			| ORDER
X  			| PLACING
X  			| PRIMARY
X+ 			| PRIOR
X  			| REFERENCES
X  			| SELECT
X  			| SESSION_USER
X  			| SOME
X+ 			| START
X  			| TABLE
X  			| THEN
X  			| TO
Xdiff -Prdc --exclude-from=exclude src/backend/parser/keywords.c src/backend/parser/keywords.c
X*** src/backend/parser/keywords.c	Sat Feb 21 00:35:13 2004
X--- src/backend/parser/keywords.c	Mon Jul  5 08:19:37 2004
X***************
X*** 80,85 ****
X--- 80,86 ----
X  	{"comment", COMMENT},
X  	{"commit", COMMIT},
X  	{"committed", COMMITTED},
X+  	{"connect",CONNECT},
X  	{"constraint", CONSTRAINT},
X  	{"constraints", CONSTRAINTS},
X  	{"conversion", CONVERSION_P},
Xdiff -Prdc --exclude-from=exclude src/backend/parser/parse_clause.c src/backend/parser/parse_clause.c
X*** src/backend/parser/parse_clause.c	Sun Apr 18 18:13:31 2004
X--- src/backend/parser/parse_clause.c	Mon Jul  5 08:19:37 2004
X***************
X*** 38,45 ****
X  #define ORDER_CLAUSE 0
X  #define GROUP_CLAUSE 1
X  #define DISTINCT_ON_CLAUSE 2
X! 
X! static char *clauseText[] = {"ORDER BY", "GROUP BY", "DISTINCT ON"};
X  
X  static void extractRemainingColumns(List *common_colnames,
X  						List *src_colnames, List *src_colvars,
X--- 38,46 ----
X  #define ORDER_CLAUSE 0
X  #define GROUP_CLAUSE 1
X  #define DISTINCT_ON_CLAUSE 2
X! #define CONNECT_CLAUSE 3
X!   
X! static char *clauseText[] = {"ORDER BY", "GROUP BY", "DISTINCT ON","CONNECT BY"};
X  
X  static void extractRemainingColumns(List *common_colnames,
X  						List *src_colnames, List *src_colvars,
X***************
X*** 1285,1290 ****
X--- 1286,1391 ----
X  }
X  
X  /*
X+  * transformConnectClause -
X+  *	  transform a Connect By clause
X+  *
X+  */
X+ Node *
X+ transformHierClause(ParseState *pstate, Query *qry, List *hier)
X+ {
X+ 	List	   *clist = NIL;	
X+ 	TargetEntry *tle;
X+ 	HierClause *node;
X+ 	List *tlist=qry->targetList,*tl;
X+ 	FakeVar *var;
X+  	int i,lev_in_tlist=0;
X+ 	if(!hier) return NULL;
X+  	
X+  	node=makeNode(HierClause);
X+  	
X+  	clist=lfirst(hier);//get conn_list
X+ 	
X+  	/* add a field '_level_', in result there will be deepness of tuple 
X+ 	 * in result tree.
X+ 	 * must be added before tranformation parent/child Expr,
X+ 	 * because in they transformation process may be added some resjunk
X+ 	 * var nodes to tlist, scanRTEForColumn() not supports mix of junk/non-junk
X+ 	 * nodes.
X+  	 */
X+ 	//search for _level_ column in target list, if any use it for 'level' output;
X+ 	i = 1;
X+ 	foreach(tl,tlist){
X+ 	    tle = lfirst(tl);
X+ 	    if(IsA(tle->expr,FakeVar)){
X+ 		lev_in_tlist = i;
X+ 		((FakeVar *)tle->expr)->varattno = i;
X+ 		var = (FakeVar *) tle->expr;
X+ 		break;
X+ 	    }
X+ 	    i++;
X+ 	}
X+ 	if(!lev_in_tlist){
X+ 	    var = makeNode(FakeVar);
X+     	    var->varattno = 0;
X+ 	    var->vartype = INT4OID;
X+ 	    var->vartypmod = -1;	
X+  	
X+  	    tle = transformTargetEntry(pstate, (Node *)var, NULL, "_level_", false);
X+  	    lappend(tlist, tle);
X+ 	}
X+ 	/* transform parent and child expressions */
X+ 	pstate->p_curTlist = tlist; /* also see in parser/parse_node.h */
X+ 	pstate->p_addTle = true;    /* we may add to tagetlist some junk attributes,
X+ 															 * which needed by this expressions but not present in 
X+ 															 * user given targetlist. only vars is added */
X+ 	node->parentExpr = transformExpr(pstate,lfirst(clist));
X+ 	node->childExpr = transformExpr(pstate,lfirst(lnext(lnext(clist))));//lthird
X+ 	pstate->p_addTle = false;
X+ 	
X+ 	/* fetch operatior OID for connecting tuples */
X+  	node->connOp = compatible_oper_opid(makeList1(lsecond(clist)),
X+ 					exprType(node->parentExpr),
X+  					exprType(node->childExpr),
X+ 					true);
X+ 
X+  	if(node->connOp == InvalidOid){
X+  	  elog(ERROR,"CONNECT BY: can't find operator '%s' for connecting on chosen fields",(char *)lsecond(clist));
X+  	}
X+ 	//if connOp eq '==' or '=' assusme it's equality operator and choose to use hash.
X+ 	if(!strcmp("=",((Value *)lsecond(clist))->val.str) || !strcmp("==",((Value *)lsecond(clist))->val.str)){
X+ 	    node->useHash = 1;
X+ 	}	
X+ 	
X+ 	/* transform StartQual, see note above, on parent/child Expr*/
X+ 	pstate->p_addTle = true;
X+ 	node->startQual=transformWhereClause(pstate,lsecond(hier),"CONNECT/BY");
X+ 	pstate->p_addTle = false;
X+ 	pstate->p_curTlist = NULL;// clear
X+  	
X+  	pstate->p_hierLevelColIdx = tle->resdom->resno;
X+ 	
X+ 	/* transformExpr return to us our's pointer, so we can to set
X+ 	 * attno here, for FakeVar attno is the number in targetlist
X+ 	 */
X+ 	var->varattno = tle->resdom->resno;
X+ 	//store it for further processing
X+ 	node->levelColNum = tle->resdom->resno;
X+ 	i=0;
X+ 
X+ 	//process list or prior clauses
X+ 	foreach(tl,tlist){
X+ 	    TargetEntry *te = lfirst(tl);
X+ 	    if(IsA(te->expr,Prior)){
X+         node->priorsList=lappend(node->priorsList,makeListi2(i,((Prior *)te->expr)->numcol));
X+ 	    }
X+ 	    i++;
X+ 	}
X+ 	node->priorsListNItems = length(node->priorsList);
X+  
X+  	return (Node *)node;
X+ }
X+ 
X+ /*
X   * transformSortClause -
X   *	  transform an ORDER BY clause
X   */
Xdiff -Prdc --exclude-from=exclude src/backend/parser/parse_expr.c src/backend/parser/parse_expr.c
X*** src/backend/parser/parse_expr.c	Sun Apr 18 18:13:31 2004
X--- src/backend/parser/parse_expr.c	Mon Jul  5 08:19:37 2004
X***************
X*** 30,35 ****
X--- 30,36 ----
X  #include "parser/parse_oper.h"
X  #include "parser/parse_relation.h"
X  #include "parser/parse_type.h"
X+ #include "parser/parse_target.h"
X  #include "utils/builtins.h"
X  #include "utils/lsyscache.h"
X  #include "utils/syscache.h"
X***************
X*** 903,908 ****
X--- 904,910 ----
X  			 * types that are demonstrably necessary to accept.
X  			 *********************************************/
X  		case T_Var:
X+     case T_FakeVar:
X  		case T_Const:
X  		case T_Param:
X  		case T_Aggref:
X***************
X*** 937,944 ****
X--- 939,972 ----
X  static Node *
X  transformIndirection(ParseState *pstate, Node *basenode, List *indirection)
X  {
X+ 	TargetEntry *tle;
X+ 	List *tl;
X+ 	bool found;
X+ 	
X  	if (indirection == NIL)
X+ 	{
X+ 		/* If node is Var, and tle addition flag is set then we must add var to targetlist
X+ 		 * if it's not presen in tlist
X+ 		 * ( also see parser/parse_node.h, parser/parse_clause.c:transformHierClause())
X+ 		 */
X+ 		if(IsA(basenode, Var) && pstate->p_addTle){
X+ 			found = false;
X+ 			/* search for var */
X+ 			foreach(tl, pstate->p_curTlist){
X+ 				tle = lfirst(tl);
X+ 				if(equal(basenode,tle->expr)){
X+ 					found = true;
X+ 					break;
X+ 				}
X+ 			}
X+ 			/* if not fount, make tle and add to tlist */
X+ 			if(!found){
X+ 				tle = transformTargetEntry(pstate,basenode,basenode,NULL,true);
X+ 				lappend(pstate->p_curTlist,tle);
X+ 			}
X+ 		}
X  		return basenode;
X+ 	}
X  	return (Node *) transformArraySubscripts(pstate,
X  											 basenode,
X  											 exprType(basenode),
X***************
X*** 1028,1033 ****
X--- 1056,1084 ----
X  						rv->inhOpt = INH_DEFAULT;
X  						node = (Node *) rv;
X  					}
X+           else if (pstate->p_hierLevelColIdx!=0 && !strcmp(name,"_level_"))
X+           {
X+                 /* If nothing of above and present hier clause and name is '_level_'
X+                  * then make fake variable
X+                  */
X+                 FakeVar *var = makeNode(FakeVar);
X+ 
X+                 var->varattno = pstate->p_hierLevelColIdx;
X+                 var->vartype = INT4OID;
X+                 var->vartypmod = -1;
X+                 node = (Node *)var;
X+           }else if (pstate->p_hierExists!=0 && !strcmp(name,"_level_"))
X+ 					{
X+ 						/* If nothing of above and present hier clause and name is '_level_'
X+ 						 * then make fake variable 
X+ 						 */
X+ 				 		FakeVar *var = makeNode(FakeVar);
X+  		
X+ 				 		var->varattno = 0;
X+ 				 		var->vartype = INT4OID;
X+ 						var->vartypmod = -1;
X+ 				 		node = (Node *)var;
X+ 				 	}
X  					else
X  						ereport(ERROR,
X  								(errcode(ERRCODE_UNDEFINED_COLUMN),
X***************
X*** 1170,1175 ****
X--- 1221,1229 ----
X  
X  	switch (nodeTag(expr))
X  	{
X+ 		case T_FakeVar:
X+ 			type = ((FakeVar *) expr)->vartype;
X+ 			break;		
X  		case T_Var:
X  			type = ((Var *) expr)->vartype;
X  			break;
Xdiff -Prdc --exclude-from=exclude src/backend/parser/parse_target.c src/backend/parser/parse_target.c
X*** src/backend/parser/parse_target.c	Thu Sep 25 06:58:01 2003
X--- src/backend/parser/parse_target.c	Mon Jul  5 08:19:37 2004
X***************
X*** 102,107 ****
X--- 102,108 ----
X  {
X  	FastList	p_target;
X  	List	   *o_target;
X+  	int prior_count=0;
X  
X  	FastListInit(&p_target);
X  
X***************
X*** 109,114 ****
X--- 110,120 ----
X  	{
X  		ResTarget  *res = (ResTarget *) lfirst(o_target);
X  
X+ 		if(res->prior){
X+       if(!pstate->p_hierExists)
X+         elog(ERROR,"PRIOR keywords can be used only with CONNECT BY clause");
X+ 			prior_count++;
X+ 		}
X  		if (IsA(res->val, ColumnRef))
X  		{
X  			ColumnRef  *cref = (ColumnRef *) res->val;
X***************
X*** 118,123 ****
X--- 124,131 ----
X  			{
X  				int		numnames = length(fields);
X  
X+  				if(res->prior)
X+           elog(ERROR,"Reference with PRIOR keyword to * isn't implemented");
X  				if (numnames == 1)
X  				{
X  					/*
X***************
X*** 187,210 ****
X  			else
X  			{
X  				/* Plain ColumnRef node, treat it as an expression */
X! 				FastAppend(&p_target,
X! 						   transformTargetEntry(pstate,
X  												res->val,
X  												NULL,
X  												res->name,
X! 												false));
X  			}
X  		}
X  		else
X  		{
X  			/* Everything else but ColumnRef */
X! 			FastAppend(&p_target,
X! 					   transformTargetEntry(pstate,
X! 											res->val,
X! 											NULL,
X! 											res->name,
X! 											false));
X  		}
X  	}
X  
X  	return FastListValue(&p_target);
X--- 195,273 ----
X  			else
X  			{
X  				/* Plain ColumnRef node, treat it as an expression */
X! 				TargetEntry *te;
X! 				if(res->prior){
X! 					te = transformTargetEntry(pstate,
X! 														res->val,
X! 														NULL,
X! 														res->name,
X! 														false);
X! 					te->prior=1;
X! 				}else{
X!           te = transformTargetEntry(pstate,
X  												res->val,
X  												NULL,
X  												res->name,
X! 												false);
X!         }
X! 				FastAppend(&p_target,te);
X  			}
X  		}
X  		else
X  		{
X  			/* Everything else but ColumnRef */
X! 			TargetEntry *te;
X! 			if(res->prior){
X! 				te = transformTargetEntry(pstate,
X! 													res->val,
X! 													NULL,
X! 													res->name,
X! 													false);
X! 	  		te->prior=1;
X!   		}else{
X!         te = transformTargetEntry(pstate,
X! 									res->val,
X! 									NULL,
X! 									res->name,
X! 									false);
X!       }
X! 			FastAppend(&p_target,te );
X! 		}
X! 	}
X! 	if(prior_count){
X! 		TargetEntry *te,*te1;
X! 		List *tl,*ttl;
X! 		Prior *pr;
X! 		int i=0,c=0,prior_found=0;
X!     bool found;
X! 		foreach(tl,FastListValue(&p_target)){
X! 			te = lfirst(tl);
X! 			if(te->prior){
X!         found = false;
X! 				pr = makeNode(Prior);
X! 				c = 0;
X! 				foreach(ttl,FastListValue(&p_target)){
X! 					te1 = lfirst(ttl);
X!           //skip PRIOR columns, we can't reference to them
X!           if(te1->prior) continue;
X! 					if(equal(te1->expr,te->expr)){
X! 						pr = makeNode(Prior);
X! 						pr->numcol=c;
X! 						pr->val = te->expr;
X! 						te->expr = (Node *)pr;
X!     				prior_found++;
X! 						break;
X! 					}
X! 					c++;
X! 				}
X! 				if(prior_found==(prior_count))
X! 					break;
X! 			}
X! 			i++;
X  		}
X+     if(prior_found != prior_count){
X+       elog(ERROR,"Expression to which PRIOR references must exist in target list");
X+     }
X  	}
X  
X  	return FastListValue(&p_target);
Xdiff -Prdc --exclude-from=exclude src/backend/utils/adt/ruleutils.c src/backend/utils/adt/ruleutils.c
X*** src/backend/utils/adt/ruleutils.c	Fri May  7 03:20:01 2004
X--- src/backend/utils/adt/ruleutils.c	Mon Jul  5 08:19:37 2004
X***************
X*** 2750,2755 ****
X--- 2750,2758 ----
X  	 */
X  	switch (nodeTag(node))
X  	{
X+     case T_FakeVar:
X+       appendStringInfo(buf, "FakeVar");
X+       break;
X  		case T_Var:
X  			{
X  				Var		   *var = (Var *) node;
Xdiff -Prdc --exclude-from=exclude src/backend/utils/sort/Makefile src/backend/utils/sort/Makefile
X*** src/backend/utils/sort/Makefile	Thu Aug 31 16:10:59 2000
X--- src/backend/utils/sort/Makefile	Mon Jul  5 08:19:37 2004
X***************
X*** 12,18 ****
X  top_builddir = ../../../..
X  include $(top_builddir)/src/Makefile.global
X  
X! OBJS = logtape.o tuplesort.o tuplestore.o
X  
X  all: SUBSYS.o
X  
X--- 12,18 ----
X  top_builddir = ../../../..
X  include $(top_builddir)/src/Makefile.global
X  
X! OBJS = logtape.o tuplesort.o tuplestore.o tupleconn.o
X  
X  all: SUBSYS.o
X  
Xdiff -Prdc --exclude-from=exclude src/backend/utils/sort/tupleconn.c src/backend/utils/sort/tupleconn.c
X*** src/backend/utils/sort/tupleconn.c	Thu Jan  1 00:00:00 1970
X--- src/backend/utils/sort/tupleconn.c	Sun Jul 11 08:07:19 2004
X***************
X*** 0 ****
X--- 1,1455 ----
X+ /*-------------------------------------------------------------------------
X+  *
X+  * tupleconn.c
X+  *	  Routines for tuple connecting.
X+  *
X+  * Based on tuplestore.c, tuplesort.c.
X+  * (c) by Evgen Potemkin evgent@terminal.ru, 11.2002
X+  * 
X+  *-------------------------------------------------------------------------
X+  */
X+ 
X+ #include <stdlib.h>
X+ #include "postgres.h"
X+ 
X+ #include "access/heapam.h"
X+ #include "storage/buffile.h"
X+ #include "utils/tupleconn.h"
X+ #include "utils/tuplesort.h"
X+ 
X+ #include "access/hash.h"
X+ #include "access/nbtree.h"
X+ #include "catalog/catname.h"
X+ #include "catalog/pg_amop.h"
X+ #include "catalog/pg_amproc.h"
X+ #include "catalog/pg_operator.h"
X+ #include "miscadmin.h"
X+ #include "utils/datum.h"
X+ #include "utils/fmgroids.h"
X+ #include "utils/lsyscache.h"
X+ #include "utils/syscache.h"
X+ 
X+ #include "parser/parse_expr.h"
X+ #include "nodes/execnodes.h"
X+ #include "executor/executor.h"
X+ #include "c.h"
X+ /*
X+  * Possible states of a Tupleconn object.	These denote the states that
X+  * persist between calls of Tupleconn routines.
X+  */
X+ typedef enum
X+ {
X+ 	TCS_INITIAL,				/* Loading tuples; still within memory
X+ 								 * limit */
X+ 	TCS_WRITEFILE,				/* Loading tuples; writing to temp file */
X+ 	TCS_READMEM,				/* Reading tuples; entirely in memory */
X+ 	TCS_READFILE				/* Reading tuples from temp file */
X+ } TupConnStatus;
X+ 
X+ 
X+ /* 
X+  * connection tree 
X+  */
X+ typedef struct _ConnectTree ConnectTree;
X+ struct _ConnectTree{
X+   ConnectTree *next; /* next sibling*/
X+   ConnectTree *prev; /* previous sibling */
X+   ConnectTree *sub;  /* child */
X+   ConnectTree *sup;  /* parent */
X+   int  level; /* deep of this node, starts from 1*/
X+   int  tuple; /* index of tuple in memtuples/used/out_store */
X+ };
X+ 
X+ /*
X+  * Information about tuples stored in buffile
X+  */
X+ typedef struct OutStore{
X+ 	int fileno;	/* BufFile fileno */
X+ 	long offs;	/* BufFile offs */
X+ 	int len;		/* tuple length*/
X+ 	HeapTuple tup;	/* in-memory tuple copy, NULL if none */
X+ }OutStore;
X+ 
X+ /*
X+  * Datum cache
X+  */
X+ typedef struct DtCache{
X+ 	Datum pntdt_val;	/* cached pntExpr value of tuple*/
X+ 	Datum chlddt_val;	/* cached chdlExpr value of tuple*/
X+ 	bool pntdt_isnull;	/* cached pntExpr is_null value of tuple*/
X+ 	bool chlddt_isnull;	/* cached chdlExpr is_null value of tuple*/
X+ 	bool pnt_c;	/* parent value is cached flag*/
X+ 	bool chld_c;	/* child value is cached flag*/
X+ } DtCache; 
X+ 
X+ //cached values of 1 tuple 
X+ typedef struct _HashTableListElem HashTableListElem;
X+ struct _HashTableListElem{
X+ 	uint32 pnt_hash;
X+ 	bool pnt_isnull;
X+ 	Datum pnt_val;
X+ 	Datum chld_val;
X+ 	uint tup_idx;
X+ 	HashTableListElem *next;
X+ };
X+ /*
X+  * Private state of a Tupleconn operation.
X+  */
X+ struct Tupleconnstate
X+ {
X+ 	TupConnStatus status;		/* enumerated value as shown above */
X+ 	long		availMem;		/* remaining memory available, in bytes */
X+ 	BufFile    *myfile;			/* underlying file, or NULL if none */
X+ 
X+ 	/*
X+ 	 * Tree and supporting stuff, explanation at _performconn function 
X+ 	 */
X+ 	MemoryContext tree_ctx;	
X+   ConnectTree *head; /* head of the result list */
X+ 	ConnectTree **pnt;  /* parent nodes on curent level*/
X+ 	int pntlast;	/* actual amount of parents on current level */
X+ 	int pntsize;	/* size of pnt array */
X+ 	ConnectTree **chld; /* array of child nodes */
X+ 	int chldlast; /* actual amount of childs on current level */
X+ 	int chldsize;	/* size of chld array */
X+ 	ConnectTree *last; /* last added/fetched node */	
X+   bool skip_node; /* used in gettuple, mean don't fall to ->sub because 
X+ 	                * we're going from that*/
X+ 	char *used;	/* array of flags - was tuple (connected already|is null) or not */
X+   TupleDesc tupDesc;
X+ 	AttrNumber level; /* tuple's '_level_' attribute number */
X+ 	FmgrInfo connFn; /* comparation function */
X+ 	
X+ 	OutStore *out_store; /* array of info about tuples in buffile for faster random access */
X+ 	DtCache *cache; /* cache for datums returned by ExecEvalExpr */
X+ 
X+ 	HashTableListElem *hash_list;
X+ 	HashTableListElem **hash_tbl;
X+ 	int hash_tbl_size;
X+ 	int nbuckets;
X+   bool use_hash;  
X+ 
X+ 	void	   *(*copytup) (Tupleconnstate *state, void *tup);
X+ 	void		(*writetup) (Tupleconnstate *state, void *tup, bool free, int idx);
X+ 	void	   *(*readtup) (Tupleconnstate *state, int idx);
X+ 
X+ 	void	  **memtuples;		/* array of pointers to palloc'd tuples */
X+ 	int			memtupsize;		/* allocated length of memtuples array */
X+ 
X+ 	int			tupcount;	/* number of tuples currently present */
X+ 
X+ 	bool		eof_reached;	/* reached EOF (needed for cursors) */
X+ 
X+ 	/* markpos_xxx holds marked position for mark and restore */
X+ 	bool		markpos_eof;	/* saved "eof_reached" */
X+ 	ConnectTree *markpos_last; /* saved "last" pointer */
X+ 	bool		markpos_skip;	/* saved "skip" flag */
X+   List *priorsList; 
X+   void *prev_tuple;
X+ };
X+ 
X+ 
X+ #define COPYTUP(state,tup)	((*(state)->copytup) (state, tup))
X+ #define WRITETUP(state,tup,free,idx) ((*(state)->writetup) (state, tup, free, idx))
X+ #define READTUP(state,idx)	((*(state)->readtup) (state, idx))
X+ #define LACKMEM(state)		((state)->availMem < 0)
X+ #define USEMEM(state,amt)	((state)->availMem -= (amt))
X+ #define FREEMEM(state,amt)	((state)->availMem += (amt))
X+ #define INIT_GUESS 1024
X+ 
X+ 
X+ static Tupleconnstate *tupleconn_begin_common(int maxKBytes);
X+ static void dumptuples(Tupleconnstate *state);
X+ 
X+ static void *copytup_heap(Tupleconnstate *state, void *tup);
X+ static void writetup_heap(Tupleconnstate *state, void *tup, bool free, int idx);
X+ static void *readtup_heap(Tupleconnstate *state, int idx);
X+ void SelectConnFunction(Oid sortOperator,RegProcedure *sortFunction,
X+ 				   SortFunctionKind *kind);
X+ void *setlevel(Tupleconnstate * state,int level, void *tuple, bool free_it, void *prev_tuple);
X+ 
X+ ConnectTree *add_next(Tupleconnstate * state,ConnectTree *tr,int tup,int level);
X+ ConnectTree *add_sub(Tupleconnstate * state,ConnectTree *tr,int tup,int level);
X+ 
X+ static uint32 hashFunc(Datum key, int typLen, bool byVal);
X+ 
X+ void tupleconn_performconn_hash(Tupleconnstate *state, Node *parentExpr, Node *childExpr, 
X+     ExprContext *econtext);
X+ /*
X+  * Init all
X+  */
X+ static Tupleconnstate *
X+ tupleconn_begin_common(int maxKBytes)
X+ {
X+ 	Tupleconnstate *state;
X+ 	
X+ 	state = (Tupleconnstate *) palloc(sizeof(Tupleconnstate));
X+ 
X+ 	MemSet((char *) state, 0, sizeof(Tupleconnstate));
X+ 
X+ 	state->status = TCS_INITIAL;
X+ 	state->availMem = maxKBytes * 1024L;
X+ 	state->myfile = NULL;
X+ 	state->out_store = NULL;
X+ 	
X+ 	state->tree_ctx = AllocSetContextCreate(CurrentMemoryContext,"Temporary connby storage",8*1024,8*1024,8*1024);
X+ 
X+ 	state->tupcount = 0;
X+ 	if (maxKBytes > 0)
X+ 		state->memtupsize = INIT_GUESS;		/* initial guess */
X+ 	else
X+ 		state->memtupsize = 1;	/* won't really need any space */
X+ 	state->memtuples = (void **) palloc(state->memtupsize * sizeof(void *));
X+ 
X+   state->pntlast=0;
X+   state->chldlast=0;
X+ 	state->pntsize=INIT_GUESS;		/* initial guess */
X+ 	state->chldsize=INIT_GUESS;		/* initial guess */
X+ 	state->pnt=(ConnectTree **)palloc(state->pntsize * sizeof(void *));
X+ 	state->chld=(ConnectTree **)palloc(state->pntsize * sizeof(void *));
X+ 
X+   state->used = (char *) palloc(state->memtupsize * sizeof(char));
X+   state->level=0;
X+ 	return state;
X+ }
X+ 
X+ Tupleconnstate *
X+ tupleconn_begin_heap(int maxKBytes, TupleDesc tupDesc, Oid connOp, List *priorsList, 
X+   int levelColNum, double rows,bool useHash)
X+ {
X+   RegProcedure connFunc;
X+ 	SortFunctionKind connFnKind;
X+ 	double td;
X+   MemoryContext morig;
X+ 	
X+ 	Tupleconnstate *state = tupleconn_begin_common(maxKBytes);
X+ 
X+ 	state->copytup = copytup_heap;
X+ 	state->writetup = writetup_heap;
X+ 	state->readtup = readtup_heap;
X+ 
X+   state->tupDesc=tupDesc;
X+ 	
X+ 	SelectConnFunction(connOp, &connFunc,
X+ 						   &connFnKind);
X+ 	if(connFnKind != SORTFUNC_CMP){
X+ 	  elog(ERROR,"tupleconn: Can't find suitable function for comparison");
X+ 	}
X+ 	fmgr_info(connFunc,&state->connFn);
X+   state->priorsList = priorsList;
X+   state->level = levelColNum - 1;
X+   if(useHash){
X+     state->use_hash = true;
X+   	td = rows/5;
X+   	if(td > INT_MAX)
X+ 	  	td = INT_MAX;
X+   	state->nbuckets = (int)td;//assume there is 8 tuples in bucket
X+ 	  if(state->nbuckets==0)
X+ 		  state->nbuckets=1;
X+     morig = MemoryContextSwitchTo(state->tree_ctx);
X+   	state->hash_list = (HashTableListElem *)palloc(sizeof(HashTableListElem)*INIT_GUESS);	//initial guess
X+ 	  state->hash_tbl = (HashTableListElem **)palloc(sizeof(void *)*state->nbuckets);	//initial guess
X+    	MemoryContextSwitchTo(morig);
X+     MemSet(state->hash_list, 0, sizeof(HashTableListElem)*INIT_GUESS);	//initial guess
X+     MemSet(state->hash_tbl, 0, sizeof(void *)*state->nbuckets);	//initial guess
X+   
X+     state->used = (char *) palloc(state->memtupsize * sizeof(char));
X+     MemSet(state->used, 0, sizeof(char)*state->memtupsize);	//initial guess
X+   }else
X+     state->use_hash = false;
X+ 
X+ 	return state;
X+ }
X+ /*
X+  * tupleconn_end
X+  *
X+  *	Release resources and clean up.
X+  */
X+ void
X+ tupleconn_end(Tupleconnstate *state)
X+ {
X+ 	int	i;
X+ 	/* common frees */
X+ 	pfree(state->pnt);
X+ 	pfree(state->chld);
X+ 	pfree(state->used);
X+ 	/* free tree, if any */
X+ 	state->last = state->head;
X+ 	// release tree and cache
X+ 	MemoryContextDelete(state->tree_ctx);
X+ 	/* free tuples, from out_store or memtuples*/
X+ 	if (state->myfile){
X+ 		BufFileClose(state->myfile);
X+ 		for(i=0;i<state->tupcount;i++){
X+ 			if(state->out_store[i].tup!=NULL){
X+ 				pfree(state->out_store[i].tup);
X+ 				FREEMEM(state,state->out_store[i].len);
X+ 				state->out_store[i].tup=NULL;
X+ 			}
X+ 		}
X+ 	}else{
X+ 		for (i = 0; i < state->tupcount; i++)
X+ 			pfree(state->memtuples[i]);
X+ 		pfree(state->memtuples);
X+ 	}
X+ }
X+ 
X+ /*
X+  * Accept one tuple while collecting input data.
X+  *
X+  * Note that the input tuple is always copied; the caller need not save it.
X+  */
X+ void
X+ tupleconn_puttuple(Tupleconnstate *state, void *tuple,int head)
X+ {
X+ 	/*
X+ 	 * Copy the tuple.	(Must do this even in WRITEFILE case.)
X+ 	 */
X+ 	tuple = COPYTUP(state, tuple);
X+ 
X+ 	/* common thing */
X+   if(head){//it's a head tuple,add it to head list
X+     //add autogrow for pnt
X+ 	  state->last = add_next(state,state->last,state->tupcount,1);
X+     if(!state->head) state->head = state->last;
X+     state->pnt[state->pntlast++] = state->last;
X+ 		state->used[state->tupcount] = 1;
X+   }else{
X+ 	  state->used[state->tupcount] = 0;
X+ 	}
X+ 	
X+ 	switch (state->status)
X+ 	{
X+ 		case TCS_INITIAL:
X+ 
X+ 			/*
X+ 			 * Stash the tuple in the in-memory array.
X+ 			 */
X+ 			if (state->tupcount >= state->memtupsize-1)
X+ 			{
X+ 				/* Grow the arrays as needed. */
X+ 				state->memtupsize *= 2;
X+ 				state->memtuples = (void **)
X+ 					repalloc(state->memtuples,
X+ 							 state->memtupsize * sizeof(void *));
X+ 				state->used = (char *)
X+ 					repalloc(state->used,
X+ 							 state->memtupsize * sizeof(char));
X+ 				MemSet((char *) (state->used+sizeof(char)*(state->memtupsize>>1)), 0, sizeof(char)*(state->memtupsize>>1));
X+ 			}
X+ 			state->memtuples[state->tupcount++] = tuple;
X+ 			/*
X+ 			 * Done if we still fit in available memory.
X+ 			 */
X+ 			if (!LACKMEM(state))
X+ 				break;
X+ 
X+ 			/*
X+ 			 * Nope; time to switch to tape-based operation.
X+ 			 */
X+ 			state->myfile = BufFileCreateTemp(false);			
X+ 			state->status = TCS_WRITEFILE;
X+ 			state->out_store = palloc(state->memtupsize * sizeof(OutStore));
X+ 			dumptuples(state);
X+ 			break;
X+ 		case TCS_WRITEFILE:
X+ 			if (state->tupcount >= state->memtupsize-1)
X+ 			{
X+ 				/* Grow the arrays as needed. */
X+ 				state->memtupsize *= 2;
X+ 				state->out_store = (OutStore *)
X+ 					repalloc(state->out_store,
X+ 							 state->memtupsize * sizeof(OutStore));
X+ 				state->used = (char *)
X+ 					repalloc(state->used,
X+ 							 state->memtupsize * sizeof(char));
X+ 				MemSet((char *) (state->used+sizeof(char)*(state->memtupsize>>1)), 0, sizeof(char)*(state->memtupsize>>1));
X+ 			}
X+ 			WRITETUP(state, tuple,!head,state->tupcount++);
X+ 			break;
X+ 		default:
X+ 			elog(ERROR, "tupleconn_puttuple: invalid state (internal error)");
X+ 			break;
X+ 	}
X+ }
X+ 
X+ /*
X+  * All tuples have been provided; finish writing.
X+  */
X+ void
X+ tupleconn_donestoring(Tupleconnstate *state)
X+ {
X+ 	switch (state->status)
X+ 	{
X+ 		case TCS_INITIAL:
X+ 			/*
X+ 			 * We were able to accumulate all the tuples within the
X+ 			 * allowed amount of memory.  Just set up to connect and scan them.
X+ 			 */
X+ 			state->status = TCS_READMEM;
X+ 			break;
X+ 		case TCS_WRITEFILE:
X+ 			/*
X+ 			 * Set up for connecting/reading from tape.
X+ 			 */
X+ 			state->status = TCS_READFILE;
X+ 			break;
X+ 		default:
X+ 			elog(ERROR, "tupleconn_donestoring: invalid state ");
X+ 			break;
X+ 	}
X+ 	state->eof_reached = false;
X+ 	state->markpos_eof = false;
X+ 	state->last=state->head;
X+ }
X+ 
X+ /*
X+  * tupleconn_performconn: perform connection on tuples
X+  * Algorithm: in puttuple has been made list of top parent nodes,
X+  * in each iteration we try to find all non-connected tuples which
X+  * 'child' attribute is equal to 'parent' attribute in one of parent 
X+  * nodes, if so - tuple becomes a child of corresponding parent node.
X+  * at end of iteration collected childs becomes the parents for next 
X+  * iteration. 
X+  * If no childs were find algorithm stops.
X+  * Scan for childs in one iteration going on full array of stored 
X+  * tuples - this preserves order of tuples from subplan. for example 
X+  * if subplan was alphabetically sorted, childs on one level of each 
X+  * parent will be also alphabetically sorted.
X+  * In case of file storage at end of algorithm all tuples resides only 
X+  * on tape.
X+  * 
X+  * Clause was:
X+  * CONNECT BY PRIOR expr Op expr
X+  * here:
X+  * PRIOR expr is - parentExpr, checked against parent tuple
X+  * Op - is connOp operator, performs comparation
X+  * expr (the rest) - is childExpr, checked against child tuple
X+  */
X+ void
X+ tupleconn_performconn(Tupleconnstate *state, 
X+ 					Node *parentExpr, Node *childExpr, ExprContext *econtext){
X+   int ok=0,i,j,ti,level=1;
X+ 	ConnectTree **t;
X+ 	int32 is_parent;
X+ 	Datum dt1,dt2;
X+ 	bool p_isnull,isnull,conn;
X+ 	HeapTuple pnt,chld;
X+ 	TupleDesc tupDesc;
X+ 	TupleTableSlot *slot;
X+ 	MemoryContext morig;
X+   int16	pnt_typlen;
X+ 	bool	pnt_typbyval;
X+   int16	chld_typlen;
X+ 	bool	chld_typbyval;
X+ 	Size	datalen;
X+ 	char	*newVal;
X+   ExprState *parentExprState,*childExprState;
X+ 
X+ 	if(!state->head) return; /* trivial case, don't connect anything */
X+   if(state->use_hash)
X+     return tupleconn_performconn_hash(state, parentExpr, childExpr, econtext);
X+ 
X+ 	/* check status */
X+ 	switch(state->status){
X+ 		case TCS_READMEM:
X+ 		case TCS_READFILE:
X+ 			break;
X+ 		default:
X+ 			elog(ERROR,"tupleconn: invalid state in performconn (internal error)");
X+ 	}
X+ 
X+   parentExprState=makeNode(ExprState);
X+   parentExprState->expr=(Expr *)parentExpr;
X+   childExprState=makeNode(ExprState);
X+   childExprState->expr=(Expr *)childExpr;
X+ 	tupDesc=state->tupDesc;
X+ 	
X+ 	/* get child and parent exprs typlens for cache */	
X+ 	get_typlenbyval(exprType(parentExpr), &pnt_typlen, &pnt_typbyval);
X+ 	get_typlenbyval(exprType(childExpr), &chld_typlen, &chld_typbyval);
X+ 	
X+ 	/* alloc cache in temp space */
X+ 	morig = MemoryContextSwitchTo(state->tree_ctx);
X+ 	state->cache = (DtCache *)palloc(sizeof(DtCache)*state->tupcount);	
X+ 	MemoryContextSwitchTo(morig);
X+ 	MemSet(state->cache, 0, sizeof(DtCache)*state->tupcount);
X+ 
X+ 	/* make for ExecEvalExpr temporary slot */
X+ 	slot=makeNode(TupleTableSlot);
X+ 	slot->ttc_tupleDescriptor = tupDesc;
X+ 	slot->ttc_buffer = InvalidBuffer;
X+ 	slot->ttc_shouldFreeDesc = false;
X+ 	slot->ttc_shouldFree = true;
X+ 	slot->ttc_descIsNew = false;
X+ 	
X+ 	/* set slot for ExecExvalExpr */
X+ 	econtext->ecxt_scantuple = slot;
X+ 	
X+   while(!ok){
X+ 	  ok=1;
X+  		for(i=0;i<state->tupcount;i++){//scan through array of tuples
X+ 			/* skip already connected and null tuples */
X+ 			CHECK_FOR_INTERRUPTS();
X+      	if(!state->used[i]){
X+ 				ResetExprContext(econtext);
X+ 				/* get tuple for connecting */
X+ 				/* if cached - use cache, in not - retrieve tuple, and build cache */
X+ 				if(state->cache[i].chld_c){
X+ 					dt1 = state->cache[i].chlddt_val;
X+ 					isnull = state->cache[i].chlddt_isnull;
X+ 				}else{
X+ 					if(state->status == TCS_READMEM) {
X+ 						chld=(HeapTuple)state->memtuples[i];
X+ 						slot->val = chld;
X+ 						dt1 = ExecEvalExpr(childExprState,econtext,&isnull,NULL);
X+ 					}	else { //READFILE
X+ 						chld=READTUP(state,i);
X+ 						Assert(chld!=NULL);
X+ 						slot->val = chld;
X+ 						/* get value of child expr,
X+ 						 * in case of variable node is equal to 
X+ 					   * dt1=heap_getattr(chld, attno1, tupDesc, &isnull); 
X+ 						 */
X+ 						dt1 = ExecEvalExpr(childExprState,econtext,&isnull,NULL);						
X+ 					}
X+ 					/* no need in storing isnull, because when we first time 
X+ 					 * evaluating expr and it's null then it marked as used 
X+ 					 * and don't checked anymore, thus cache not involved
X+ 					 */					 
X+ 					state->cache[i].chld_c = true;
X+ 					/* store it if it's not null */
X+ 					if(!isnull){
X+ 						if(chld_typbyval){
X+ 							state->cache[i].chlddt_val = dt1;
X+ 						}else {
X+ 							/* copy datum data to temp space*/
X+ 							datalen = datumGetSize(dt1, false, chld_typlen);
X+ 							morig = MemoryContextSwitchTo(state->tree_ctx);
X+ 							newVal = (char *) palloc(datalen);
X+ 							MemoryContextSwitchTo(morig);
X+ 							memcpy(newVal, DatumGetPointer(dt1), datalen);
X+ 							state->cache[i].chlddt_val = PointerGetDatum(newVal);
X+ 							state->cache[i].chlddt_isnull = false;
X+ 							dt1 = PointerGetDatum(newVal);
X+ 						}
X+ 					}
X+ 					/* free tuple, since we don't need it further, till _gettuple */
X+ 					if(state->status != TCS_READMEM) {
X+ 						pfree(chld);
X+ 						FREEMEM(state,((HeapTuple)chld)->t_len+HEAPTUPLESIZE);
X+ 						state->out_store[i].tup=NULL;						
X+ 					}
X+ 				}
X+ 				conn=false;
X+ 				if(!isnull){
X+ 					/* scan through nodes array of previous level,
X+ 					 * until connect it or array is exhausted
X+ 					 */
X+ 				  for(j=0;j<state->pntlast && !conn;j++){
X+ 						/* get parent tuple */
X+ 						/* if cached - use cache, in not - retrieve tuple, and build cache */
X+ 						if(state->cache[state->pnt[j]->tuple].pnt_c){
X+ 							dt2 = state->cache[state->pnt[j]->tuple].pntdt_val;
X+ 							p_isnull = state->cache[state->pnt[j]->tuple].pntdt_isnull;
X+ 						}else{
X+ 							if(state->status == TCS_READMEM) {
X+ 							  pnt=(HeapTuple)state->memtuples[state->pnt[j]->tuple];
X+ 								slot->val = pnt;
X+ 								dt2 = ExecEvalExpr(parentExprState,econtext,&p_isnull,NULL);
X+ 							} else {
X+ 								// if tuple parent value is not cached and tuple isn't in mem, 
X+ 								// then read it and build cache
X+ 								pnt=state->out_store[state->pnt[j]->tuple].tup;
X+ 						
X+ 								if(pnt==NULL){
X+ 									pnt=READTUP(state,state->pnt[j]->tuple);
X+ 								}
X+ 								Assert(pnt!=NULL); /*elog(ERROR,"tupleconn: parent tuple is null (internal error)");*/
X+ 
X+ 								slot->val = pnt;
X+ 								/* get value of parent expr */
X+ 								dt2 = ExecEvalExpr(parentExprState,econtext,&p_isnull,NULL);
X+ 							}
X+ 							state->cache[state->pnt[j]->tuple].pntdt_isnull = p_isnull;
X+ 							state->cache[state->pnt[j]->tuple].pnt_c = true;
X+ 							/* cache it, if it's not null*/
X+ 							if(!p_isnull){
X+ 								if(pnt_typbyval){
X+ 									state->cache[state->pnt[j]->tuple].pntdt_val = dt2;
X+ 								}else{
X+ 									/* copy datum data to temp space */
X+ 									datalen = datumGetSize(dt2, false, pnt_typlen);
X+ 									morig = MemoryContextSwitchTo(state->tree_ctx);
X+ 									newVal = (char *) palloc(datalen);
X+ 									MemoryContextSwitchTo(morig);
X+ 									memcpy(newVal, DatumGetPointer(dt2), datalen);
X+ 									state->cache[state->pnt[j]->tuple].pntdt_val = PointerGetDatum(newVal);
X+ 									state->cache[state->pnt[j]->tuple].pntdt_isnull = false;
X+ 									dt2 = PointerGetDatum(newVal);
X+ 								}
X+ 							}
X+ 							/* free tuple, same as child */
X+ 							if(state->status != TCS_READMEM) {
X+ 								pfree(pnt);
X+ 								FREEMEM(state,((HeapTuple)pnt)->t_len+HEAPTUPLESIZE);
X+ 								state->out_store[state->pnt[j]->tuple].tup = NULL;
X+ 							}
X+ 						}
X+ 						if(!p_isnull){
X+ 							/* apply connOp operator on parent and child expr results,
X+ 							 * if 0 (in case of CMP means they're equal) connect them
X+ 							 */
X+ 							is_parent=DatumGetInt32(FunctionCall2(&state->connFn,dt1,dt2));
X+ 							if(is_parent==0){
X+ 		        	  ok=0;
X+ 								/* stop scan of parents */
X+ 								conn=true;
X+ 								/* connect tuples (make node of the connect tree)*/
X+  			        	state->chld[state->chldlast++]=add_sub(state,state->pnt[j],i,level+1);
X+ 								state->used[i]=1;
X+ 								if(state->chldlast>=state->chldsize-1){
X+ 									/* grow array of connected tuples as necessary */
X+ 									state->chldsize *= 2;
X+ 									state->chld = (ConnectTree **)
X+ 											repalloc(state->chld,
X+ 									 		state->chldsize * sizeof(void *));
X+ 								}
X+   	       		}
X+ 						}
X+  		    	}
X+ 				}else{
X+ 					/* mark it as used since it has null child value and can't be 
X+ 					 * connected to any node
X+ 					 * may be better to add nullcheck on this field at parse stage to whereClause, 
X+ 					 */
X+ 					state->used[i]=1;
X+ 				}
X+ 			}
X+  	  }
X+ 		/* swap pnt & chld arrays */
X+ 		t=state->pnt;
X+ 		ti=state->pntsize;
X+ 
X+    	state->pnt=state->chld;
X+ 		state->pntsize=state->chldsize;
X+ 		state->pntlast=state->chldlast;
X+ 
X+ 		state->chld=t;
X+ 		state->chldsize=ti;
X+ 		state->chldlast=0;
X+ 
X+  	  level++;
X+  	}
X+ 	/* free anything temporal */
X+ 	ResetExprContext(econtext);
X+ 	pfree(slot);
X+ 	econtext->ecxt_scantuple = NULL;
X+ 	pfree(state->cache);
X+ 	state->cache=NULL;
X+ }
X+ 
X+ void
X+ tupleconn_performconn_hash(Tupleconnstate *state,
X+ 					Node *parentExpr, Node *childExpr, ExprContext *econtext){
X+   int ok=0,i,j,ti,level=1,k;
X+ 	ConnectTree **t;
X+ 	int32 is_parent;
X+ 	Datum dt1,dt2;
X+ 	bool isnull,conn;
X+ 	HeapTuple tuple;
X+ 	TupleDesc tupDesc;
X+ 	TupleTableSlot *slot;
X+ 	MemoryContext morig;
X+   int16	pnt_typlen;
X+ 	bool	pnt_typbyval;
X+   int16	chld_typlen;
X+ 	bool	chld_typbyval;
X+ 	Size	datalen;
X+ 	char	*newVal;
X+ 	uint32 h1,h2;
X+ 	uint bucket;  
X+ 	HashTableListElem *htle;
X+   ExprState *parentExprState,*childExprState;
X+ 
X+ 	if(!state->head) return; /* trivial case, don't connect anything */
X+ 	/* check status */
X+ 	switch(state->status){
X+ 		case TCS_READMEM:
X+ 		case TCS_READFILE:
X+ 			break;
X+ 		default:
X+ 			elog(ERROR,"tupleconn: invalid state in performconn (internal error)");
X+ 	}
X+ 
X+   parentExprState=makeNode(ExprState);
X+   parentExprState->expr=(Expr *)parentExpr;
X+   childExprState=makeNode(ExprState);
X+   childExprState->expr=(Expr *)childExpr;
X+ 	tupDesc=state->tupDesc;
X+ 	/* get child and parent exprs typlens for cache */	
X+ 	get_typlenbyval(exprType(parentExpr), &pnt_typlen, &pnt_typbyval);
X+ 	get_typlenbyval(exprType(childExpr), &chld_typlen, &chld_typbyval);
X+ 	
X+ 	/* alloc cache in temp space */
X+ 	morig = MemoryContextSwitchTo(state->tree_ctx);
X+ 	state->hash_list = (HashTableListElem *)palloc(sizeof(HashTableListElem)*state->tupcount);	
X+ 	MemoryContextSwitchTo(morig);
X+ 	MemSet(state->hash_list, 0, sizeof(HashTableListElem)*state->tupcount);
X+ 
X+ 	/* make for ExecEvalExpr temporary slot */
X+ 	slot=makeNode(TupleTableSlot);
X+ 	slot->ttc_tupleDescriptor = tupDesc;
X+ 	slot->ttc_buffer = InvalidBuffer;
X+ 	slot->ttc_shouldFreeDesc = false;
X+ 	slot->ttc_shouldFree = true;
X+ 	slot->ttc_descIsNew = false;
X+ 	
X+ 	/* set slot for ExecExvalExpr */
X+ 	econtext->ecxt_scantuple = slot;
X+ 
X+   /*
X+    * build hash table
X+    * for all tuples, calculate hash for childExpr. if tuple is head then 
X+    * calc parentExpr hash instead. if either Expr is null, throw tuple out.
X+    */
X+   for(i=0;i<state->tupcount;i++){
X+     //get tuple
X+     if(state->status == TCS_READMEM) {
X+ 			tuple=(HeapTuple)state->memtuples[i];
X+ 		}	else { //READFILE
X+ 			tuple=READTUP(state,i);
X+ 			Assert(tuple!=NULL);
X+   	}
X+     
X+ 		slot->val = tuple;
X+     state->hash_list[i].tup_idx = i;
X+     ResetExprContext(econtext);
X+ 		if(state->used[i]){ //for now it means 'head'
X+   	  dt2 = ExecEvalExpr(parentExprState,econtext,&isnull,NULL);
X+       if(!isnull) {
X+         h2 = hashFunc(dt2, pnt_typlen, pnt_typbyval);
X+   			//fill pnt_hash value for perfconn
X+ 				//no need to add this tuple to hash_table, we never will use it as child tuple
X+ 	      state->hash_list[i].pnt_hash = h2;
X+ 
X+ 				if(pnt_typbyval || state->status == TCS_READMEM){
X+ 					state->hash_list[i].pnt_val = dt2;
X+ 				}else {
X+ 					/* copy datum data to temp space*/
X+ 					datalen = datumGetSize(dt2, false, pnt_typlen);
X+ 					morig = MemoryContextSwitchTo(state->tree_ctx);
X+ 					newVal = (char *) palloc(datalen);
X+ 					MemoryContextSwitchTo(morig);
X+ 					memcpy(newVal, DatumGetPointer(dt2), datalen);
X+ 					state->hash_list[i].pnt_val = PointerGetDatum(newVal);
X+ 					state->hash_list[i].pnt_isnull = false;
X+ 				}
X+ 				/* free tuple, since we don't need it further, till _gettuple */
X+       }else{
X+         state->hash_list[i].pnt_isnull = true;
X+       }
X+ 		}else{
X+ 			uint bucket;
X+ 			HashTableListElem *htle;
X+ 			MemoryContext morig;
X+ 
X+   	  dt1 = ExecEvalExpr(childExprState,econtext,&isnull,NULL);
X+ 			if(!isnull) {// sanity check
X+         
X+         h1 =	hashFunc(dt1, chld_typlen, chld_typbyval);
X+   			bucket = h1 % state->nbuckets;
X+ 
X+ 				if(chld_typbyval || state->status == TCS_READMEM){
X+ 					state->hash_list[i].chld_val = dt1;
X+ 				}else {
X+ 						/* copy datum data to temp space*/
X+ 					datalen = datumGetSize(dt1, false, chld_typlen);
X+ 					morig = MemoryContextSwitchTo(state->tree_ctx);
X+ 					newVal = (char *) palloc(datalen);
X+ 					MemoryContextSwitchTo(morig);
X+ 					memcpy(newVal, DatumGetPointer(dt1), datalen);
X+ 					state->hash_list[i].chld_val = PointerGetDatum(newVal);
X+ 				}
X+         // add tuple to bucket
X+ 				if(state->hash_tbl[bucket]){
X+ 					for(k=0,htle = state->hash_tbl[bucket];htle->next;htle=htle->next);//k++
X+ 					htle->next=&state->hash_list[i];
X+ 				}else{
X+ 					state->hash_tbl[bucket] = &state->hash_list[i];
X+ 				} 
X+       }else{
X+         //it's null, throw it out
X+         state->used[i] = 1;
X+       }
X+ 	
X+   	}
X+ 		/* free tuple, since we don't need it further, till _gettuple */
X+   	if(state->status != TCS_READMEM) {
X+ 			pfree(tuple);
X+ 			FREEMEM(state,((HeapTuple)tuple)->t_len+HEAPTUPLESIZE);
X+ 			state->out_store[i].tup=NULL;						
X+ 		}
X+   }
X+   /*
X+    * perform connection of tuples
X+    * for each head tuple calculate bucket from parent hash, then check connect conditions on 
X+    * every tuple in bucket list, if accepted add to tree.
X+    */
X+   /*
X+    * process list of parents, if no childs are found (ok==1), then tree building is complete.
X+    */
X+   while(!ok){
X+ 	  ok=1;
X+ 		CHECK_FOR_INTERRUPTS();
X+ 		conn=false;
X+           
X+ 		for(j=0;j<state->pntlast;j++){
X+ 			int pnt_tup_idx;
X+ 			/* get parent tuple */
X+ 			/* if cached - use cache, in not - retrieve tuple, and build cache */
X+ 			pnt_tup_idx = state->pnt[j]->tuple;
X+ 			if(state->hash_list[pnt_tup_idx].pnt_isnull) continue;
X+ 			h2 = state->hash_list[pnt_tup_idx].pnt_hash;
X+ 			dt2 = state->hash_list[pnt_tup_idx].pnt_val;
X+ 
X+ 			/* get bucket */
X+ 			bucket = h2 % state->nbuckets;
X+ 
X+       i=0;k=0;
X+       /* search bucket for child tuples */
X+ 			for(htle=state->hash_tbl[bucket];htle;htle = htle->next){
X+ 				if(!htle)
X+ 					break;
X+         //skip it if null or the self
X+ 				if(state->used[htle->tup_idx] || pnt_tup_idx == htle->tup_idx )
X+ 					continue;
X+         //check connect condition
X+ 				is_parent=DatumGetInt32(FunctionCall2(&state->connFn,htle->chld_val,dt2));
X+ 				if(is_parent !=0)//isn't accepted
X+ 					continue;
X+          // found one or more childs
X+ 		    ok=0;
X+         // calc parentExpr hash, it will be used on next round
X+ 				if(!htle->pnt_hash){
X+ 					Datum dt;
X+ 					bool isnull;
X+ 					ResetExprContext(econtext);
X+           
X+           if(state->status == TCS_READMEM) {
X+       			tuple=(HeapTuple)state->memtuples[htle->tup_idx];
X+       		}	else { //READFILE
X+       			tuple=READTUP(state,htle->tup_idx);
X+       			Assert(tuple!=NULL);
X+         	}
X+ 					slot->val = tuple;
X+ 
X+ 				  dt = ExecEvalExpr(parentExprState,econtext,&isnull,NULL);
X+ 			    if(!isnull) {
X+             int tttt;
X+ 						htle->pnt_hash = hashFunc(dt, pnt_typlen, pnt_typbyval);
X+             tttt = htle->pnt_hash % state->nbuckets;
X+       			if(pnt_typbyval){
X+       				htle->pnt_val = dt;
X+       			}else {
X+       				/* copy datum data to temp space*/
X+       				datalen = datumGetSize(dt, false, pnt_typlen);
X+       				morig = MemoryContextSwitchTo(state->tree_ctx);
X+       				newVal = (char *) palloc(datalen);
X+       				MemoryContextSwitchTo(morig);
X+       				memcpy(newVal, DatumGetPointer(dt), datalen);
X+       				htle->pnt_val = PointerGetDatum(newVal);
X+       				htle->pnt_isnull = false;
X+       			}
X+           	if(state->status != TCS_READMEM) {
X+         			pfree(tuple);
X+         			FREEMEM(state,((HeapTuple)tuple)->t_len+HEAPTUPLESIZE);
X+         			state->out_store[i].tup=NULL;						
X+         		}
X+ 					}else
X+ 						htle->pnt_isnull = true;
X+ 				}
X+ 				/* connect tuples (make node of the connect tree)*/
X+  		  	state->chld[state->chldlast++]=add_sub(state,state->pnt[j],htle->tup_idx,level+1);
X+         state->used[htle->tup_idx] = 1;
X+ 				if(state->chldlast>=state->chldsize-1){
X+ 					/* grow array of connected tuples as necessary */
X+ 					state->chldsize *= 2;
X+ 					state->chld = (ConnectTree **)
X+ 							repalloc(state->chld,
X+ 					 		state->chldsize * sizeof(void *));
X+ 				}
X+         i++;
X+   	 	}
X+  		}
X+ 		/* swap pnt & chld arrays */
X+ 		t=state->pnt;
X+ 		ti=state->pntsize;
X+ 
X+    	state->pnt=state->chld;
X+ 		state->pntsize=state->chldsize;
X+ 		state->pntlast=state->chldlast;
X+ 
X+ 		state->chld=t;
X+ 		state->chldsize=ti;
X+ 		state->chldlast=0;
X+  	  level++;
X+  	}
X+ 	/* free anything temporal */
X+ 	ResetExprContext(econtext);
X+ 	pfree(slot);
X+ 	econtext->ecxt_scantuple = NULL;
X+ 	state->cache=NULL;
X+ }
X+ 
X+ 
X+ /* set _level_ column to proper value 
X+  * first decompose tuple. if we're found _level_ column,
X+  * set it to proper value. them form new tuple.
X+  * in tape case free original tuple.
X+  */
X+ void *
X+ setlevel(Tupleconnstate *state,int level, void *tuple,bool free_it, void *prev_tuple){
X+ #define REALLOCATTRS 64
X+ 	Datum valuesArray[REALLOCATTRS];
X+ 	char nullsArray[REALLOCATTRS];
X+ 	Datum pvaluesArray[REALLOCATTRS];
X+ 	char pnullsArray[REALLOCATTRS];
X+ 	Datum *values,*pvalues;
X+ 	char *nulls,*pnulls;
X+ 	HeapTuple newtup,tup = (HeapTuple)tuple,ptup = (HeapTuple)prev_tuple;
X+ 	TupleDesc tdesc = state->tupDesc;
X+ 	int natts,i,c;
X+   List *tl;
X+  	bool		isnull;
X+ 
X+ 	if(!tuple) return NULL;
X+ 	natts = tdesc->natts;
X+ 	/* prepare arrays */
X+ 	if(natts>REALLOCATTRS){
X+ 		values = palloc(natts * sizeof(Datum));
X+ 		nulls = palloc(natts * sizeof(char));
X+     if(prev_tuple){
X+   		pvalues = palloc(natts * sizeof(Datum));
X+ 	  	pnulls = palloc(natts * sizeof(char));
X+     }else{
X+   		pvalues = NULL;
X+ 	  	pnulls = NULL;
X+     }
X+ 	}else{
X+ 		values = valuesArray;
X+ 		nulls = nullsArray;
X+ 		pvalues = pvaluesArray;
X+ 		pnulls = pnullsArray;
X+ 	}
X+ 	/* decompose tuple and substitute attr _level_ with real value */
X+ 	for (i = 0; i < natts; i++){
X+ 		if(i != state->level){
X+ 			values[i] = heap_getattr(tup,
X+ 								 i + 1,
X+ 								 tdesc,
X+ 								 &isnull);
X+ 			if (isnull)
X+ 				nulls[i] = 'n';
X+ 			else
X+ 				nulls[i] = ' ';
X+ 		}else{
X+ 			values[state->level]=Int32GetDatum(level);
X+ 			nulls[i] = ' ';
X+ 		}
X+ 	}
X+   if(state->priorsList){
X+     List *ttl;
X+   
X+     if(prev_tuple)
X+   	for (i = 0; i < natts; i++){
X+ 		  if(i != state->level){
X+ 			  pvalues[i] = heap_getattr(ptup,
X+ 				  			 i + 1,
X+ 								 tdesc,
X+ 								 &isnull);
X+   			if (isnull)
X+ 	  			pnulls[i] = 'n';
X+ 		  	else
X+ 			  	pnulls[i] = ' ';
X+   		}
X+ 	  }
X+ 
X+     foreach(tl,state->priorsList){
X+       ttl=lfirst(tl);
X+       i=lfirsti(ttl);
X+       c=lfirsti(lnext(ttl));
X+       if(prev_tuple){
X+         nulls[i] = pnulls[c];
X+         values[i] = pvalues[c];
X+       }else{
X+         nulls[i] = 'n';
X+       }
X+ 		}
X+   }
X+ 	/* form new */
X+ 	tup = heap_formtuple(state->tupDesc,values,nulls);
X+ 	if(natts>REALLOCATTRS){
X+ 		pfree(values);
X+ 		pfree(nulls);
X+     if(prev_tuple){
X+   		pfree(pvalues);
X+ 	  	pfree(pnulls);
X+     }
X+ 	}
X+ 	if(free_it){
X+ 		/* make full copy of modified tuple and free original */
X+ 		newtup = heap_copytuple(tup);
X+ 		tup = newtup;
X+ 		FREEMEM(state,((HeapTuple)tuple)->t_len+HEAPTUPLESIZE);
X+ 		heap_freetuple(tuple);
X+ 		tup = newtup;
X+     //also free prev_tuple, if any
X+     if(prev_tuple){
X+       FREEMEM(state,((HeapTuple)prev_tuple)->t_len+HEAPTUPLESIZE);
X+       heap_freetuple(prev_tuple);
X+     }
X+ 	}
X+   return tup;
X+ }
X+ /*
X+  * Fetch the next tuple in forward only direction.
X+  * Returns NULL if no more tuples. If should_free is set, the
X+  * caller must pfree the returned tuple when done with it.
X+  */
X+ /* FIXME: add backward direction in future. may be.
X+  */
X+ void *
X+ tupleconn_gettuple(Tupleconnstate *state,
X+ 					bool *should_free)
X+ {
X+ 	void	   *tup=NULL;
X+ 	int 		level=0;
X+   void    *prev_tuple=NULL;
X+ 	  
X+ 	if (state->eof_reached || !state->head) return NULL;
X+ 	/* check status */
X+ 	switch (state->status)
X+ 	{
X+ 		case TCS_READMEM:
X+ 			*should_free = false;
X+ 			break;
X+ 		case TCS_READFILE:
X+ 			*should_free = true;
X+ 			break;
X+ 		default:
X+ 			elog(ERROR, "tupleconn_gettuple: invalid state");
X+ 			return NULL;		/* keep compiler happy */
X+ 	}
X+ 
X+ 	while(!tup) {
X+ 		if(!state->skip_node) {
X+ 			if(state->status == TCS_READMEM){
X+ 				tup=state->memtuples[state->last->tuple];
X+         if(state->last->sup){
X+           prev_tuple = state->memtuples[state->last->sup->tuple];
X+         }else{
X+           prev_tuple = NULL;
X+         }
X+ 			}else{
X+ 				tup=READTUP(state,state->last->tuple);
X+         if(state->priorsList && state->last->sup){
X+           prev_tuple = READTUP(state,state->last->sup->tuple);
X+           // same as a bit below
X+           state->out_store[state->last->sup->tuple].tup=NULL;
X+         }else{
X+           prev_tuple = NULL;
X+         }
X+ 				/* will be freed in setlevel(), but setlevel()
X+ 				 * can't clear tuple's out_store[] cell, so clear it here 
X+ 				 */
X+ 				state->out_store[state->last->tuple].tup=NULL;
X+ 			}
X+ 			level=state->last->level;
X+ 		}
X+ 		if(!state->skip_node && state->last->sub) state->last=state->last->sub;
X+ 		else if(state->last->next){
X+ 			state->last=state->last->next;
X+ 			state->skip_node = false;
X+ 		}	else if(state->last->sup){
X+ 		  state->last=state->last->sup;
X+ 			state->skip_node=true;
X+ 		}	else {
X+ 		  state->eof_reached = true;
X+ 		  break;
X+ 		}
X+ 	}
X+   if(!state->priorsList){
X+     prev_tuple = NULL;
X+   }
X+ 	return setlevel(state,level,tup,*should_free,prev_tuple);
X+ }
X+ 
X+ /*
X+  * dumptuples - remove tuples from memory and write to tape
X+  */
X+ static void
X+ dumptuples(Tupleconnstate *state)
X+ {
X+ 	int			i,j;
X+ 	bool	b;
X+ 	for (i = 0, j = 0; i < state->tupcount; i++){
X+ 		/* don't free pnt list, because we will use it soon, in tupleconn_performconn() */
X+ 		if(j < state->pntlast && i == state->pnt[j]->tuple){
X+ 			b=false;
X+ 			j++;
X+ 		}else b=true;
X+ 		WRITETUP(state, state->memtuples[i],b,i);
X+ 	}
X+ }
X+ 
X+ /*
X+  * tupleconn_rescan		- rewind and replay the scan
X+  */
X+ void
X+ tupleconn_rescan(Tupleconnstate *state)
X+ {
X+ 
X+ 	/* check status */
X+ 	switch (state->status)
X+ 	{
X+ 		case TCS_READMEM:
X+ 		case TCS_READFILE:
X+ 			break;
X+ 		default:
X+ 			elog(ERROR, "tupleconn_rescan: invalid state");
X+ 			break;
X+ 	}
X+ 	state->eof_reached = false;
X+ 	state->markpos_eof = false;
X+ 	
X+ 	state->last = state->head;
X+ }
X+ 
X+ /*
X+  * tupleconn_markpos	- saves current position in the tuple sequence
X+  */
X+ void
X+ tupleconn_markpos(Tupleconnstate *state)
X+ {
X+ 
X+ 	/* check status */
X+ 	switch (state->status)
X+ 	{
X+ 		case TCS_READMEM:
X+ 		case TCS_READFILE:
X+ 			break;
X+ 		default:
X+ 			elog(ERROR, "tupleconn_markpos: invalid state");
X+ 			break;
X+ 	}
X+ 	state->markpos_eof = state->eof_reached;
X+ 
X+ 	/* file/memtuples positions can be retrieved by state->last
X+ 	 * so don't save them
X+ 	 */
X+ 	state->markpos_last = state->last;
X+ 	state->markpos_skip = state->skip_node;
X+ }
X+ 
X+ /*
X+  * tupleconn_restorepos - restores current position in connection tree to
X+  *						  last saved position
X+  */
X+ void
X+ tupleconn_restorepos(Tupleconnstate *state)
X+ {
X+ 
X+ 	/* check status */
X+ 	switch (state->status)
X+ 	{
X+ 		case TCS_READMEM:
X+ 		case TCS_READFILE:
X+ 			break;
X+ 		default:
X+ 			elog(ERROR, "tupleconn_restorepos: invalid state");
X+ 			break;
X+ 	}
X+ 	state->eof_reached = state->markpos_eof;
X+ 
X+ 	state->last = state->markpos_last;
X+ 	state->skip_node = state->markpos_skip;
X+ }
X+ 
X+ /*
X+  * Routines specialized for HeapTuple case
X+  */
X+ 
X+ static void *
X+ copytup_heap(Tupleconnstate *state, void *tup)
X+ {
X+ 	HeapTuple	tuple = (HeapTuple) tup;
X+ 
X+ 	USEMEM(state, HEAPTUPLESIZE + tuple->t_len);
X+ 	return (void *) heap_copytuple(tuple);
X+ }
X+ 
X+ /*
X+  * tree building procedures
X+  */
X+  
X+ /* add new node next to given, set and return it */
X+ ConnectTree *
X+ add_next(Tupleconnstate *state,ConnectTree *tr,int tup,int level){
X+   ConnectTree *t;
X+   MemoryContext morig;
X+   
X+ 	morig=MemoryContextSwitchTo(state->tree_ctx);
X+   t=palloc(sizeof(ConnectTree));
X+ 	MemoryContextSwitchTo(morig);
X+   memset(t,0,sizeof(ConnectTree));
X+   t->tuple=tup;
X+   t->level=level;
X+   if(tr){
X+     tr->next=t;
X+     t->prev=tr;
X+   }
X+   return t;
X+ }
X+ 
X+ /* add new node as child to given, set and return it */
X+ ConnectTree *
X+ add_sub(Tupleconnstate *state,ConnectTree *tr,int tup,int level){
X+   ConnectTree *t,*t1;
X+   MemoryContext morig;
X+   
X+ 	morig=MemoryContextSwitchTo(state->tree_ctx);
X+   t=palloc(sizeof(ConnectTree));
X+ 	MemoryContextSwitchTo(morig);
X+   memset(t,0,sizeof(ConnectTree));
X+   t->tuple=tup;
X+   t->level=level;
X+   if(!tr->sub){
X+     tr->sub=t;  
X+     t->sup=tr;
X+   }else{
X+     for(t1=tr->sub;t1->next;t1=t1->next);
X+     t1->next=t;
X+     t->prev=t1;
X+     t->sup=tr;
X+   }
X+   return t;
X+ }
X+ 
X+ 
X+ /*
X+  * File storage procedures
X+  * this part taken from tuplestore.c, with addition for 
X+  * maintaining out_store[].
X+  * because of all on-tape tuple placement info is stored in 
X+  * out_store[], don't bother to write it on a tape, only
X+  * tuple body is stored.
X+  */
X+  
X+ /*
X+  * We don't bother to write the HeapTupleData part of the tuple.
X+  */
X+ 
X+ static void
X+ writetup_heap(Tupleconnstate *state, void *tup, bool free, int idx)
X+ {
X+ 	HeapTuple	tuple = (HeapTuple) tup;
X+ 
X+ 	/* fill placement info */
X+ 	state->out_store[idx].len = tuple->t_len;
X+ 	BufFileTell(state->myfile,
X+ 				&state->out_store[idx].fileno,
X+ 				&state->out_store[idx].offs);
X+ 	
X+ 	if (BufFileWrite(state->myfile, (void *) tuple->t_data,
X+ 					 tuple->t_len) != (size_t) tuple->t_len)
X+ 		elog(ERROR, "tupleconn: write failed");
X+ 	
X+ 	/* explanation in dumptuples */
X+ 	if(free){
X+ //		FREEMEM(state, HEAPTUPLESIZE + tuple->t_len);
X+ 		heap_freetuple(tuple);
X+ 		state->out_store[idx].tup = NULL;		
X+ 	}else{
X+ 		state->out_store[idx].tup = (HeapTuple)tup;
X+ 	}
X+ }
X+ 
X+ static void *
X+ readtup_heap(Tupleconnstate *state, int idx)
X+ {
X+ 	unsigned int tuplen = state->out_store[idx].len + HEAPTUPLESIZE;
X+ 	/* add block readings */
X+ 	HeapTuple	tuple = (HeapTuple) palloc(tuplen);
X+ 
X+ 	USEMEM(state, tuplen);
X+ 	/* reconstruct the HeapTupleData portion */
X+ 	tuple->t_len = state->out_store[idx].len ;
X+ 	ItemPointerSetInvalid(&(tuple->t_self));
X+ 	tuple->t_datamcxt = CurrentMemoryContext;
X+ 	tuple->t_data = (HeapTupleHeader) (((char *) tuple) + HEAPTUPLESIZE);
X+ 	/* seek to the tuple */
X+ 	if(BufFileSeek(state->myfile,
X+ 			state->out_store[idx].fileno,
X+ 			state->out_store[idx].offs,SEEK_SET)!=0)
X+ 		elog(ERROR,"tupleconn: can't seek in readtup_heap");
X+ 
X+ 	/* read in the tuple proper */
X+ 	if (BufFileRead(state->myfile, (void *) tuple->t_data,
X+ 					tuple->t_len) != (size_t) tuple->t_len)
X+ 		elog(ERROR, "tupleconn: unexpected end of data");
X+ 
X+ 	state->out_store[idx].tup = tuple;
X+ 	return (void *) tuple;
X+ }
X+ 
X+ /*
X+  * Select comparation function
X+  * made from SelectSortFunction() in nodeSort.c.
X+  * differences is the name:) and strategy of operator
X+  * being searched (here is BTEqualStrategyNumber)
X+  */
X+  
X+ void
X+ SelectConnFunction(Oid connOperator,
X+ 				   RegProcedure *connFunction,
X+ 				   SortFunctionKind *kind)
X+ {
X+ 	Relation	relation;
X+ 	HeapScanDesc scan;
X+ 	ScanKeyData skey[1];
X+ 	HeapTuple	tuple;
X+ 	Form_pg_operator optup;
X+ 	Oid			opclass = InvalidOid;
X+ 
X+ 	ScanKeyEntryInitialize(&skey[0], 0x0,
X+ 						   Anum_pg_amop_amopopr,
X+ 						   F_OIDEQ,
X+ 						   ObjectIdGetDatum(connOperator));
X+ 
X+ 	relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock);
X+ 	scan = heap_beginscan(relation, SnapshotNow, 1, skey);
X+ 
X+ 	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
X+ 	{
X+ 		Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
X+ 
X+ 		if (!opclass_is_btree(aform->amopclaid))
X+ 			continue;
X+ 		if (aform->amopstrategy == BTEqualStrategyNumber)
X+ 		{
X+ 			opclass = aform->amopclaid;
X+ 			*kind = SORTFUNC_CMP;
X+ 			break;				/* done looking */
X+ 		}
X+ 	}
X+ 
X+ 	heap_endscan(scan);
X+ 	heap_close(relation, AccessShareLock);
X+ 
X+ 	if (OidIsValid(opclass))
X+ 	{
X+ 		/* Found a suitable opclass, get its comparator support function */
X+ 		tuple = SearchSysCache(AMPROCNUM,
X+ 							   ObjectIdGetDatum(opclass),
X+ 							   Int16GetDatum(BTORDER_PROC),
X+ 							   0, 0);
X+ 		if (HeapTupleIsValid(tuple))
X+ 		{
X+ 			Form_pg_amproc aform = (Form_pg_amproc) GETSTRUCT(tuple);
X+ 
X+ 			*connFunction = aform->amproc;
X+ 			ReleaseSysCache(tuple);
X+ 			Assert(RegProcedureIsValid(*connFunction));
X+ 			return;
X+ 		}
X+ 	}
X+ 
X+ 	/*
X+ 	 * Can't find a comparator, so use the operator as-is.  Decide whether
X+ 	 * it is forward or reverse conn by looking at its name (grotty, but
X+ 	 * this only matters for deciding which end NULLs should get conned
X+ 	 * to).
X+ 	 */
X+ 	tuple = SearchSysCache(OPEROID,
X+ 						   ObjectIdGetDatum(connOperator),
X+ 						   0, 0, 0);
X+ 	if (!HeapTupleIsValid(tuple))
X+ 		elog(ERROR, "SelectConnFunction: cache lookup failed for operator %u",
X+ 			 connOperator);
X+ 	optup = (Form_pg_operator) GETSTRUCT(tuple);
X+ 	if (strcmp(NameStr(optup->oprname), ">") == 0)
X+ 		*kind = SORTFUNC_REVLT;
X+ 	else
X+ 		*kind = SORTFUNC_LT;
X+ 	*connFunction = optup->oprcode;
X+ 	ReleaseSysCache(tuple);
X+ 
X+ 	Assert(RegProcedureIsValid(*connFunction));
X+ }
X+ 
X+ /* ----------------------------------------------------------------
X+  *		hashFunc
X+  *
X+  *  taken from executor/nodeHash.c, it's simplier to copy it here,
X+  *  than link to nodeHash.c
X+  * ----------------------------------------------------------------
X+  */
X+ static uint32
X+ hashFunc(Datum key, int typLen, bool byVal)
X+ {
X+ 	unsigned char *k;
X+ 
X+ 	if (byVal)
X+ 	{
X+ 		/*
X+ 		 * If it's a by-value data type, just hash the whole Datum value.
X+ 		 * This assumes that datatypes narrower than Datum are
X+ 		 * consistently padded (either zero-extended or sign-extended, but
X+ 		 * not random bits) to fill Datum; see the XXXGetDatum macros in
X+ 		 * postgres.h. NOTE: it would not work to do hash_any(&key, len)
X+ 		 * since this would get the wrong bytes on a big-endian machine.
X+ 		 */
X+ 		k = (unsigned char *) &key;
X+ 		typLen = sizeof(Datum);
X+ 	}
X+ 	else
X+ 	{
X+ 		if (typLen > 0)
X+ 		{
X+ 			/* fixed-width pass-by-reference type */
X+ 			k = (unsigned char *) DatumGetPointer(key);
X+ 		}
X+ 		else if (typLen == -1)
X+ 		{
X+ 			/*
X+ 			 * It's a varlena type, so 'key' points to a "struct varlena".
X+ 			 * NOTE: VARSIZE returns the "real" data length plus the
X+ 			 * sizeof the "vl_len" attribute of varlena (the length
X+ 			 * information). 'key' points to the beginning of the varlena
X+ 			 * struct, so we have to use "VARDATA" to find the beginning
X+ 			 * of the "real" data.	Also, we have to be careful to detoast
X+ 			 * the datum if it's toasted.  (We don't worry about freeing
X+ 			 * the detoasted copy; that happens for free when the
X+ 			 * per-tuple memory context is reset in ExecHashGetBucket.)
X+ 			 */
X+ 			struct varlena *vkey = PG_DETOAST_DATUM(key);
X+ 
X+ 			typLen = VARSIZE(vkey) - VARHDRSZ;
X+ 			k = (unsigned char *) VARDATA(vkey);
X+ 		}
X+ 		else if (typLen == -2)
X+ 		{
X+ 			/* It's a null-terminated C string */
X+ 			typLen = strlen(DatumGetCString(key)) + 1;
X+ 			k = (unsigned char *) DatumGetPointer(key);
X+ 		}
X+ 		else
X+ 		{
X+ 			elog(ERROR, "hashFunc: Invalid typLen %d", typLen);
X+ 			k = NULL;			/* keep compiler quiet */
X+ 		}
X+ 	}
X+ 
X+ 	return DatumGetUInt32(hash_any(k, typLen));
X+ }
Xdiff -Prdc --exclude-from=exclude src/include/executor/nodeConn.h src/include/executor/nodeConn.h
X*** src/include/executor/nodeConn.h	Thu Jan  1 00:00:00 1970
X--- src/include/executor/nodeConn.h	Mon Jul  5 08:19:37 2004
X***************
X*** 0 ****
X--- 1,27 ----
X+ /*-------------------------------------------------------------------------
X+  *
X+  * nodeSort.h
X+  *
X+  *
X+  *
X+  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
X+  * Portions Copyright (c) 1994, Regents of the University of California
X+  *
X+  * $Id: nodeSort.h,v 1.14 2001/11/05 17:46:33 momjian Exp $
X+  *
X+  *-------------------------------------------------------------------------
X+  */
X+ #ifndef NODECONN_H
X+ #define NODECONN_H
X+ 
X+ #include "nodes/plannodes.h"
X+ 
X+ extern TupleTableSlot *ExecConn(ConnectState *node);
X+ extern ConnectState * ExecInitConn(Conn *node, EState *estate);
X+ extern int	ExecCountSlotsConn(Conn *node);
X+ extern void ExecEndConn(ConnectState *node);
X+ extern void ExecConnMarkPos(ConnectState *node);
X+ extern void ExecConnRestrPos(ConnectState *node);
X+ extern void ExecReScanConn(ConnectState *node, ExprContext *exprCtxt);
X+ 
X+ #endif   /* NODECONN_H */
Xdiff -Prdc --exclude-from=exclude src/include/nodes/execnodes.h src/include/nodes/execnodes.h
X*** src/include/nodes/execnodes.h	Thu Jan 22 02:23:35 2004
X--- src/include/nodes/execnodes.h	Mon Jul  5 08:19:37 2004
X***************
X*** 1038,1043 ****
X--- 1038,1062 ----
X  } AggState;
X  
X  /* ----------------
X+  *	 ConnectState information
X+  *
X+  *		conn_Done		indicates whether connection has been performed yet
X+  *		tupleconnstate	private state of tuplesort.c
X+  * ----------------
X+  */
X+ typedef struct ConnectState
X+ {
X+  	ScanState ss;	/* its first field is NodeTag */
X+  	bool		conn_Done;
X+   
X+   ExprState 	*startQual;   /* qual conditions for heads */
X+ 	ExprState 	*parentExpr;
X+ 	ExprState 	*childExpr;
X+ 
X+  	void	   *tupleconnstate;
X+ } ConnectState;
X+  
X+ /* ----------------
X   *	 UniqueState information
X   *
X   *		Unique nodes are used "on top of" sort nodes to discard
Xdiff -Prdc --exclude-from=exclude src/include/nodes/nodes.h src/include/nodes/nodes.h
X*** src/include/nodes/nodes.h	Sun Aug 17 19:58:06 2003
X--- src/include/nodes/nodes.h	Mon Jul  5 08:19:37 2004
X***************
X*** 56,61 ****
X--- 56,62 ----
X  	T_HashJoin,
X  	T_Material,
X  	T_Sort,
X+   T_Conn,
X  	T_Group,
X  	T_Agg,
X  	T_Unique,
X***************
X*** 83,88 ****
X--- 84,90 ----
X  	T_HashJoinState,
X  	T_MaterialState,
X  	T_SortState,
X+ 	T_ConnectState,
X  	T_GroupState,
X  	T_AggState,
X  	T_UniqueState,
X***************
X*** 98,103 ****
X--- 100,107 ----
X  	T_RangeVar,
X  	T_Expr,
X  	T_Var,
X+ 	T_FakeVar,
X+ 	T_Prior,
X  	T_Const,
X  	T_Param,
X  	T_Aggref,
X***************
X*** 283,288 ****
X--- 287,293 ----
X  	T_CreateOpClassItem,
X  	T_CompositeTypeStmt,
X  	T_InhRelation,
X+   T_HierClause,
X  
X  	/*
X  	 * TAGS FOR FUNCTION-CALL CONTEXT AND RESULTINFO NODES (see fmgr.h)
Xdiff -Prdc --exclude-from=exclude src/include/nodes/parsenodes.h src/include/nodes/parsenodes.h
X*** src/include/nodes/parsenodes.h	Wed Sep 17 04:25:29 2003
X--- src/include/nodes/parsenodes.h	Mon Jul  5 08:19:37 2004
X***************
X*** 82,87 ****
X--- 82,88 ----
X  	Node	   *setOperations;	/* set-operation tree if this is top level
X  								 * of a UNION/INTERSECT/EXCEPT query */
X  
X+  	Node     *hierClause; /* CONNECT BY/START WITH clause */
X  	/*
X  	 * If the resultRelation turns out to be the parent of an inheritance
X  	 * tree, the planner will add all the child tables to the rtable and
X***************
X*** 274,279 ****
X--- 275,281 ----
X  	char	   *name;			/* column name or NULL */
X  	List	   *indirection;	/* subscripts for destination column, or
X  								 * NIL */
X+ 	int 	prior;
X  	Node	   *val;			/* the value expression to compute or
X  								 * assign */
X  } ResTarget;
X***************
X*** 526,532 ****
X   */
X  typedef SortClause GroupClause;
X  
X! 
X  /*****************************************************************************
X   *		Optimizable Statements
X   *****************************************************************************/
X--- 528,554 ----
X   */
X  typedef SortClause GroupClause;
X  
X! /*
X!  * HierClause -
X!  *	   representation of CONNECT BY/START WITH clauses
X!  * parsed:
X!  * CONNECT BY ( PRIOR expr ) ( op ) ( expr )
X!  * first () is parentExpr
X!  * second () is connOpName
X!  * third () is childExpr
X!  */
X! typedef struct HierClause
X! {
X!  	NodeTag type;
X! 	Node	*parentExpr,*childExpr;
X! 	Node	*connOpName;
X!  	Node	*startQual;		/* Quals for heads */
X!  	Oid	connOp;	/* operator for comparing parent & child exprs*/
X! 	List	*priorsList;
X! 	int	priorsListNItems; 
X! 	int	levelColNum; /* index of _level_ column in target list */
X! 	bool	useHash; /* if true performconn will use hash algorithm */
X! } HierClause;
X  /*****************************************************************************
X   *		Optimizable Statements
X   *****************************************************************************/
X***************
X*** 614,619 ****
X--- 636,642 ----
X  	Node	   *whereClause;	/* WHERE qualification */
X  	List	   *groupClause;	/* GROUP BY clauses */
X  	Node	   *havingClause;	/* HAVING conditional-expression */
X+  	List		 *hierClause;    /* CONNECT BY , START WITH clauses*/
X  
X  	/*
X  	 * These fields are used in both "leaf" SelectStmts and upper-level
Xdiff -Prdc --exclude-from=exclude src/include/nodes/plannodes.h src/include/nodes/plannodes.h
X*** src/include/nodes/plannodes.h	Fri Aug  8 21:42:48 2003
X--- src/include/nodes/plannodes.h	Mon Jul  5 08:19:37 2004
X***************
X*** 283,288 ****
X--- 283,304 ----
X  	Oid		   *sortOperators;	/* OIDs of operators to sort them by */
X  } Sort;
X  
X+ /* ----------------
X+  *		conn node
X+  * ----------------
X+  */
X+ typedef struct Conn
X+ {
X+  	Plan		plan;
X+  	Node	*startQual;   /* qual conditions for heads */
X+ 	Node	*parentExpr;
X+ 	Node	*childExpr;
X+  	Oid	connOp;
X+ 	List	*priorsList;
X+ 	int	levelColNum;
X+ 	bool	useHash;
X+ } Conn;
X+ 
X  /* ---------------
X   *	 group node -
X   *		Used for queries with GROUP BY (but no aggregates) specified.
Xdiff -Prdc --exclude-from=exclude src/include/nodes/primnodes.h src/include/nodes/primnodes.h
X*** src/include/nodes/primnodes.h	Sun Aug 17 23:43:26 2003
X--- src/include/nodes/primnodes.h	Mon Jul  5 08:19:37 2004
X***************
X*** 189,194 ****
X--- 189,226 ----
X  	AttrNumber	varoattno;		/* original value of varattno */
X  } Var;
X  
X+ /* FakeVar is same as Var, with several exeptions:
X+  *
X+  * it's not fetched from the tables.
X+  * it's not passed to scan nodes so them don't see it.
X+  *		 when we comes to moment when we must fetch value from nowhere 
X+  * 		(because of nonexistence of FakeVar as relation attr), we just return
X+  * 		0 as Datum. this made at executor/execQual.c:ExecEvalFakeVar().
X+  * FakeVar exist only for checking attrs in scan tuple with baseing on targetlist,
X+  * 		not in outer or inner relations. so there is no varno.
X+  * it never rewritten because of it's based on targetlist where it's present.
X+  * 		so there is no *old fields.
X+  * now supproted only INT4 type FakeVars (see at executor/execQual.c:ExecEvalFakeVar()).
X+  * 		but may be extended.
X+  */
X+ typedef struct FakeVar
X+ {
X+ 	NodeTag		type;
X+ 	AttrNumber	varattno;		/* attribute number of this var, or zero
X+ 								 * for all */
X+ 	Oid			vartype;		/* pg_type tuple OID for the type of this
X+ 								 * var */
X+ 	int32		vartypmod;		/* pg_attribute typmod value */
X+ 
X+ } FakeVar;
X+ 
X+ typedef struct Prior
X+ {
X+ 	NodeTag type;
X+ 	int numcol;
X+ 	Node *val;
X+ } Prior;
X+ 
X  /*
X   * Const
X   */
X***************
X*** 727,732 ****
X--- 759,765 ----
X  	Expr		xpr;
X  	Resdom	   *resdom;			/* descriptor for targetlist item */
X  	Expr	   *expr;			/* expression to evaluate */
X+ 	int 	prior;
X  } TargetEntry;
X  
X  
Xdiff -Prdc --exclude-from=exclude src/include/optimizer/planmain.h src/include/optimizer/planmain.h
X*** src/include/optimizer/planmain.h	Fri Aug  8 21:42:50 2003
X--- src/include/optimizer/planmain.h	Mon Jul  5 08:19:37 2004
X***************
X*** 51,56 ****
X--- 51,57 ----
X  extern SetOp *make_setop(SetOpCmd cmd, List *tlist, Plan *lefttree,
X  		   List *distinctList, AttrNumber flagColIdx);
X  extern Result *make_result(List *tlist, Node *resconstantqual, Plan *subplan);
X+ extern Conn *make_conn(Query *root, List *tlist, Plan *lefttree);
X  
X  /*
X   * prototypes for plan/initsplan.c
Xdiff -Prdc --exclude-from=exclude src/include/optimizer/planner.h src/include/optimizer/planner.h
X*** src/include/optimizer/planner.h	Mon Aug  4 02:40:14 2003
X--- src/include/optimizer/planner.h	Mon Jul  5 08:19:37 2004
X***************
X*** 21,24 ****
X--- 21,27 ----
X  extern Plan *planner(Query *parse, bool isCursor, int cursorOptions);
X  extern Plan *subquery_planner(Query *parse, double tuple_fraction);
X  
X+ extern Plan *make_connplan(Query *parse, List *tlist,
X+                         Plan *plannode);
X+ 
X  #endif   /* PLANNER_H */
Xdiff -Prdc --exclude-from=exclude src/include/parser/parse_clause.h src/include/parser/parse_clause.h
X*** src/include/parser/parse_clause.h	Sun Aug 17 19:58:06 2003
X--- src/include/parser/parse_clause.h	Mon Jul  5 08:19:37 2004
X***************
X*** 31,36 ****
X--- 31,37 ----
X  					List *targetlist, bool resolveUnknown);
X  extern List *transformDistinctClause(ParseState *pstate, List *distinctlist,
X  						List *targetlist, List **sortClause);
X+ extern Node *transformHierClause(ParseState *pstate, Query *qry, List *hier);
X  
X  extern List *addAllTargetsToSortList(ParseState *pstate,
X  						List *sortlist, List *targetlist,
Xdiff -Prdc --exclude-from=exclude src/include/parser/parse_node.h src/include/parser/parse_node.h
X*** src/include/parser/parse_node.h	Mon Aug  4 02:40:14 2003
X--- src/include/parser/parse_node.h	Mon Jul  5 08:19:37 2004
X***************
X*** 61,66 ****
X--- 61,80 ----
X  	bool		p_hasSubLinks;
X  	bool		p_is_insert;
X  	bool		p_is_update;
X+ 
X+ 	AttrNumber p_hierLevelColIdx; /* _level_ column number for hier clause, if any. 
X+ 										* set in transformHierClause() */
X+ 	bool    p_hierExists;
X+ 	bool		p_addTle; /* flag used in parse_expr.c:transformIndirection().
X+ 										 * if set all vars going thought will be checked against
X+ 										 * current targetlist (field below), and if not present,
X+ 										 * added to it as junk.
X+ 										 * this is needed in HierClause case. in parent/child Expr and startQual
X+ 										 * may be preset attributes which is not in targetlist given by user, so
X+ 										 * at transformation stage we'll add them.
X+ 										 */
X+ 	List		 *p_curTlist; /* current target list (see above)*/
X+ 
X  	Relation	p_target_relation;
X  	RangeTblEntry *p_target_rangetblentry;
X  } ParseState;
Xdiff -Prdc --exclude-from=exclude src/include/stamp-h src/include/stamp-h
X*** src/include/stamp-h	Thu Jan  1 00:00:00 1970
X--- src/include/stamp-h	Thu Jul  8 16:28:04 2004
X***************
X*** 0 ****
X--- 1 ----
X+ 
Xdiff -Prdc --exclude-from=exclude src/include/utils/tupleconn.h src/include/utils/tupleconn.h
X*** src/include/utils/tupleconn.h	Thu Jan  1 00:00:00 1970
X--- src/include/utils/tupleconn.h	Mon Jul  5 08:19:37 2004
X***************
X*** 0 ****
X--- 1,65 ----
X+ /*-------------------------------------------------------------------------
X+  *
X+  * tuplestore.h
X+  *	  Generalized routines for temporary tuple storage.
X+  *
X+  * This module handles temporary storage of tuples for purposes such
X+  * as Materialize nodes, hashjoin batch files, etc.  It is essentially
X+  * a dumbed-down version of tuplesort.c; it does no sorting of tuples
X+  * but can only store a sequence of tuples and regurgitate it later.
X+  * A temporary file is used to handle the data if it exceeds the
X+  * space limit specified by the caller.
X+  *
X+  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
X+  * Portions Copyright (c) 1994, Regents of the University of California
X+  *
X+  * $Id: tuplestore.h,v 1.6 2001/11/05 17:46:36 momjian Exp $
X+  *
X+  *-------------------------------------------------------------------------
X+  */
X+ #ifndef TUPLECONN_H
X+ #define TUPLECONN_H
X+ 
X+ #include "access/htup.h"
X+ #include "nodes/nodes.h"
X+ #include "executor/executor.h"
X+ 
X+ /* Tuplestorestate is an opaque type whose details are not known outside
X+  * tuplestore.c.
X+  */
X+ typedef struct Tupleconnstate Tupleconnstate;
X+ 
X+ /*
X+  * Currently we only need to store HeapTuples, but it would be easy
X+  * to support the same behavior for IndexTuples and/or bare Datums.
X+  */
X+ 
X+ extern Tupleconnstate *tupleconn_begin_heap(
X+ 					  int maxKBytes, TupleDesc tupDesc, Oid connOp, List *priorsList,
X+             int levelColNum,double rows,bool useHash);
X+ 
X+ extern void tupleconn_puttuple(Tupleconnstate *state, void *tuple,int head);
X+ 
X+ extern void tupleconn_donestoring(Tupleconnstate *state);
X+ 
X+ extern void *tupleconn_gettuple(Tupleconnstate *state,
X+ 					bool *should_free);
X+ 
X+ #define tupleconn_getheaptuple(state, should_free) \
X+ 	((HeapTuple) tupleconn_gettuple(state, should_free))
X+ 
X+ extern void tupleconn_end(Tupleconnstate *state);
X+ 
X+ extern void tupleconn_performconn(Tupleconnstate *state, Node *parentExpr, Node *childExpr, ExprContext *econtext);
X+ 
X+ /*
X+  * These routines may only be called if randomAccess was specified 'true'.
X+  * Likewise, backwards scan in gettuple/getdatum is only allowed if
X+  * randomAccess was specified.
X+  */
X+ 
X+ extern void tupleconn_rescan(Tupleconnstate *state);
X+ extern void tupleconn_markpos(Tupleconnstate *state);
X+ extern void tupleconn_restorepos(Tupleconnstate *state);
X+ 
X+ #endif   /* TUPLECONN_H */
END-of-pgcluster74-server/files/hier-Pg7.4-0.5.3.diff
echo x - pgcluster74-server/files/dot.profile.in
sed 's/^X//' >pgcluster74-server/files/dot.profile.in << 'END-of-pgcluster74-server/files/dot.profile.in'
XPGLIB=%%PREFIX%%/lib
X
X# note: PGDATA can be overridden by the -D startup option
XPGDATA=${HOME}/data
X
Xexport PATH PGLIB PGDATA
X
X# if you use the periodic script from share/postgresql/502.pgsql, you
X# can set these
X#PGDUMP_ARGS="-b -F c"
X#PGBACKUPDIR=${HOME}/backups
X#PGBACKUP_SAVE_DAYS=7
X#export PGBACKUPDIR PGDUMP_ARGS PGBACKUP_SAVE_DAYS
X
X#You might want to set some locale stuff here
X#PGDATESTYLE=ISO
X#LC_ALL=sv_SE.ISO_8859-1
X#export PGDATESTYLE LC_ALL
X
X# if you want to make regression tests use this TZ
X#TZ=PST8PDT
X#export TZ
END-of-pgcluster74-server/files/dot.profile.in
echo x - pgcluster74-server/files/dot.cshrc.in
sed 's/^X//' >pgcluster74-server/files/dot.cshrc.in << 'END-of-pgcluster74-server/files/dot.cshrc.in'
Xsetenv PGLIB %%PREFIX%%/lib
X
X# note: PGDATA can be overridden by the -D startup option
Xsetenv PGDATA $HOME/data
X
X#You might want to set some locale stuff here
X#setenv PGDATESTYLE ISO
X#setenv LC_ALL sv_SE.ISO_8859-1
X
X# if you want to make regression tests use this TZ
X#setenv TZ PST8PDT
END-of-pgcluster74-server/files/dot.cshrc.in
echo x - pgcluster74-server/files/patch-configure
sed 's/^X//' >pgcluster74-server/files/patch-configure << 'END-of-pgcluster74-server/files/patch-configure'
X--- configure.orig	Wed Jun 26 21:28:24 2002
X+++ configure	Wed Jun 26 21:35:16 2002
X@@ -2007,11 +2007,13 @@
X EOF
X 
X 
X-  if test -d "$krb4_prefix/include"; then
X-    INCLUDES="$INCLUDES -I$krb4_prefix/include"
X-  fi
X-  if test -d "$krb4_prefix/lib"; then
X-    LIBDIRS="$LIBDIRS -L$krb4_prefix/lib"
X+  if test "$krb4_prefix" != "/usr"; then
X+    if test -d "$krb4_prefix/include"; then
X+      INCLUDES="$INCLUDES -I$krb4_prefix/include"
X+    fi
X+    if test -d "$krb4_prefix/lib"; then
X+      LIBDIRS="$LIBDIRS -L$krb4_prefix/lib"
X+    fi
X   fi
X 
X   krb_srvtab="/etc/srvtab"
X@@ -2052,11 +2054,13 @@
X EOF
X 
X 
X-  if test -d "$krb5_prefix/include"; then
X-    INCLUDES="$INCLUDES -I$krb5_prefix/include"
X-  fi
X-  if test -d "$krb5_prefix/lib"; then
X-    LIBDIRS="$LIBDIRS -L$krb5_prefix/lib"
X+  if test "$krb5_prefix" != "/usr"; then
X+    if test -d "$krb5_prefix/include"; then
X+      INCLUDES="$INCLUDES -I$krb5_prefix/include"
X+    fi
X+    if test -d "$krb5_prefix/lib"; then
X+      LIBDIRS="$LIBDIRS -L$krb5_prefix/lib"
X+    fi
X   fi
X 
X   krb_srvtab="FILE:\$(sysconfdir)/krb5.keytab"
X@@ -2157,11 +2161,13 @@
X EOF
X 
X 
X-  if test -d "${openssl_prefix}/include" ; then
X-    INCLUDES="$INCLUDES -I${openssl_prefix}/include"
X-  fi
X-  if test -d "${openssl_prefix}/lib" ; then
X-    LIBDIRS="$LIBDIRS -L${openssl_prefix}/lib"
X+  if test "${openssl_prefix}" != "/usr"; then
X+    if test -d "${openssl_prefix}/include" ; then
X+      INCLUDES="$INCLUDES -I${openssl_prefix}/include"
X+    fi
X+    if test -d "${openssl_prefix}/lib" ; then
X+      LIBDIRS="$LIBDIRS -L${openssl_prefix}/lib"
X+    fi
X   fi
X 
X fi
END-of-pgcluster74-server/files/patch-configure
echo x - pgcluster74-server/files/patch-plpython-Makefile
sed 's/^X//' >pgcluster74-server/files/patch-plpython-Makefile << 'END-of-pgcluster74-server/files/patch-plpython-Makefile'
X--- src/pl/plpython/Makefile~	Thu Mar  4 08:06:19 2004
X+++ src/pl/plpython/Makefile	Thu Mar  4 08:06:44 2004
X@@ -8,7 +8,7 @@
X # On some platforms we can only build PL/Python if libpython is a
X # shared library.  Since there is no official way to determine this,
X # we see if there is a file that is named like a shared library.
X-ifneq (,$(wildcard $(python_configdir)/libpython*$(DLSUFFIX)*))
X+ifneq (,$(wildcard $(python_configdir)/../../libpython*$(DLSUFFIX)*))
X shared_libpython = yes
X endif
X 
END-of-pgcluster74-server/files/patch-plpython-Makefile
echo x - pgcluster74-server/files/patch-src-interfaces-jdbc-build-xml
sed 's/^X//' >pgcluster74-server/files/patch-src-interfaces-jdbc-build-xml << 'END-of-pgcluster74-server/files/patch-src-interfaces-jdbc-build-xml'
X--- src/interfaces/jdbc/build.xml.orig	Thu Jun 24 11:51:44 2004
X+++ src/interfaces/jdbc/build.xml	Thu Sep  2 01:51:36 2004
X@@ -113,10 +113,7 @@
X 
X   <target name="compile" depends="prepare,check_versions,driver">
X 
X-    <available classname="org.postgresql.Driver" property="old.driver.present" />
X-    <fail message="Old driver was detected on classpath or in jre/lib/ext, please remove and try again." if="old.driver.present" />
X-
X-    <javac classpath="${srcdir}" srcdir="${srcdir}" destdir="${builddir}" debug="${debug}">
X+    <javac includeAntRuntime="no" classpath="${srcdir}" srcdir="${srcdir}" destdir="${builddir}" debug="${debug}">
X       <!-- This is the core of the driver.  It is common for all three versions. -->
X        <include name="${package}/*.java" />
X        <include name="${package}/core/**" />
END-of-pgcluster74-server/files/patch-src-interfaces-jdbc-build-xml
echo x - pgcluster74-server/files/patch-src-interfaces-libpgtcl-Makefile
sed 's/^X//' >pgcluster74-server/files/patch-src-interfaces-libpgtcl-Makefile << 'END-of-pgcluster74-server/files/patch-src-interfaces-libpgtcl-Makefile'
X--- src/interfaces/libpgtcl/Makefile.orig	Tue Feb 10 08:26:48 2004
X+++ src/interfaces/libpgtcl/Makefile	Thu Mar 11 21:12:25 2004
X@@ -21,7 +21,7 @@
X OBJS= pgtcl.o pgtclCmds.o pgtclId.o
X 
X SHLIB_LINK = $(libpq) $(TCL_LIB_SPEC) $(TCL_LIBS) \
X-	$(filter -lintl -lssl -lcrypto -lkrb5 -lcrypt, $(LIBS)) $(THREAD_LIBS)
X+	$(filter -lintl -lssl -lcrypto -lkrb5 -lcrypt -L% -ltcl83 -ltcl84, $(LIBS)) $(THREAD_LIBS)
X 
X all: submake-libpq all-lib
X 
END-of-pgcluster74-server/files/patch-src-interfaces-libpgtcl-Makefile
echo x - pgcluster74-server/files/patch-src-makefiles-Makefile.freebsd
sed 's/^X//' >pgcluster74-server/files/patch-src-makefiles-Makefile.freebsd << 'END-of-pgcluster74-server/files/patch-src-makefiles-Makefile.freebsd'
X--- src/makefiles/Makefile.freebsd.orig	Wed Aug 29 21:14:40 2001
X+++ src/makefiles/Makefile.freebsd	Sat Jan 31 17:51:25 2004
X@@ -7,7 +7,7 @@
X endif
X 
X DLSUFFIX = .so
X-CFLAGS_SL = -fpic -DPIC
X+CFLAGS_SL = -fPIC -DPIC
X 
X %.so: %.o
X ifdef ELF_SYSTEM
X@@ -23,3 +23,5 @@
X endif
X 
X sqlmansect = 7
X+
X+allow_nonpic_in_shlib = yes
END-of-pgcluster74-server/files/patch-src-makefiles-Makefile.freebsd
echo x - pgcluster74-server/files/patch-src:backend:utils:misc:postgresql.conf.sample
sed 's/^X//' >pgcluster74-server/files/patch-src:backend:utils:misc:postgresql.conf.sample << 'END-of-pgcluster74-server/files/patch-src:backend:utils:misc:postgresql.conf.sample'
X--- src/backend/utils/misc/postgresql.conf.sample~	Wed Oct  8 05:49:38 2003
X+++ src/backend/utils/misc/postgresql.conf.sample	Tue Nov 18 05:08:08 2003
X@@ -136,9 +136,9 @@
X 
X # - Syslog -
X 
X-#syslog = 0			# range 0-2; 0=stdout; 1=both; 2=syslog
X-#syslog_facility = 'LOCAL0'
X-#syslog_ident = 'postgres'
X+syslog = 2			# range 0-2; 0=stdout; 1=both; 2=syslog
X+syslog_facility = 'LOCAL0'
X+syslog_ident = 'postgres'
X 
X # - When to Log -
X 
X@@ -162,7 +162,7 @@
X 				 # milliseconds.  Zero prints all queries.
X 				 # Minus-one disables.
X 
X-#silent_mode = false		 # DO NOT USE without Syslog!
X+silent_mode = true		 # DO NOT USE without Syslog!
X 
X # - What to Log -
X 
END-of-pgcluster74-server/files/patch-src:backend:utils:misc:postgresql.conf.sample
echo x - pgcluster74-server/files/502.pgsql
sed 's/^X//' >pgcluster74-server/files/502.pgsql << 'END-of-pgcluster74-server/files/502.pgsql'
X#!/bin/sh
X#
X# $FreeBSD: ports/databases/postgresql74-server/files/502.pgsql,v 1.7 2005/01/31 00:19:47 girgen Exp $
X#
X# Maintenance shell script to vacuum and backup database
X# Put this in /usr/local/etc/periodic/daily, and it will be run 
X# every night
X#
X# Written by Palle Girgensohn <girgen@pingpong.net>
X#
X# In public domain, do what you like with it,
X# and use it at your own risk... :)
X#
X
X# Define these variables in either /etc/periodic.conf or
X# /etc/periodic.conf.local to override the default values.
X#
X# daily_pgsql_backup_enable="YES" # do backup
X# daily_pgsql_vacuum_enable="YES" # do vacuum
X
Xdaily_pgsql_vacuum_enable="YES"
Xdaily_pgsql_backup_enable="NO"
X
Xdaily_pgsql_vacuum_args="-z"
Xdaily_pgsql_pgdump_args="-b -F c"
X# backupdir is relative to ~pgsql home directory unless it begins with a slash:
Xdaily_pgsql_backupdir="~pgsql/backups"
Xdaily_pgsql_savedays="7"
X
X# If there is a global system configuration file, suck it in.
X#
Xif [ -r /etc/defaults/periodic.conf ]
Xthen
X    . /etc/defaults/periodic.conf
X    source_periodic_confs
Xfi
X
X# allow '~´ in dir name
Xeval backupdir=${daily_pgsql_backupdir}
X
Xrc=0
X
Xcase "$daily_pgsql_backup_enable" in
X    [Yy][Ee][Ss])
X
X	# daily_pgsql_backupdir must be writeable by user pgsql
X	# ~pgsql is just that under normal circumstances,
X	# but this might not be where you want the backups...
X	if [ ! -d ${backupdir} ] ; then 
X	    echo Creating ${backupdir}
X	    mkdir ${backupdir}; chmod 700 ${backupdir}; chown pgsql ${backupdir}
X	fi
X
X	echo
X	echo "PostgreSQL maintenance"
X
X	# Protect the data
X	umask 077
X	dbnames=`su -l pgsql -c "psql -q -t -A -d template1 -c SELECT\ datname\ FROM\ pg_database\ WHERE\ datname!=\'template0\'"`
X	rc=$?
X	now=`date "+%Y-%m-%dT%H:%M:%S"`
X	file=${daily_pgsql_backupdir}/pgglobals_${now}
X	su -l pgsql -c "pg_dumpall -g | gzip -9 > ${file}.gz"
X	for db in ${dbnames}; do
X	    echo -n " $db"
X	    file=${backupdir}/pgdump_${db}_${now}
X	    su -l pgsql -c "pg_dump ${daily_pgsql_pgdump_args} -f ${file} ${db}"
X	    [ $? -gt 0 ] && rc=3
X	done
X
X	if [ $rc -gt 0 ]; then
X	    echo
X	    echo "Errors were reported during backup."
X	fi
X
X	# cleaning up old data
X	find ${backupdir} \( -name 'pgdump_*' -o -name 'pgglobals_*' \) \
X	    -a -mtime +${daily_pgsql_savedays} -delete
X	;;
Xesac
X
Xcase "$daily_pgsql_vacuum_enable" in
X    [Yy][Ee][Ss])
X
X	echo
X	echo "vacuuming..."
X	su -l pgsql -c "vacuumdb -a -q ${daily_pgsql_vacuum_args}"
X	if [ $? -gt 0 ]
X	then
X	    echo
X	    echo "Errors were reported during vacuum."
X	    rc=3
X	fi
X	;;
Xesac
X
Xexit $rc
END-of-pgcluster74-server/files/502.pgsql
echo x - pgcluster74-server/files/pgcluster.sh.tmpl
sed 's/^X//' >pgcluster74-server/files/pgcluster.sh.tmpl << 'END-of-pgcluster74-server/files/pgcluster.sh.tmpl'
X#!/bin/sh
X#
X# $FreeBSD: ports/databases/pgcluster/files/pgcluster.sh.tmpl,v 1.3 2004/07/26 23:28:47 kuriyama Exp $
X#
X# PROVIDE: pgcluster
X# REQUIRE: DAEMON
X# BEFORE:  pgreplicate
X# KEYWORD: FreeBSD
X#
X# Add the following line to /etc/rc.conf to enable pgcluster:
X#
X# pgcluster_enable="YES"
X# # optional
X# pgcluster_data="/home/pgsql/data"
X# pgcluster_flags="-w -s"
X#
X
Xpgcluster_enable=${pgcluster_enable-"NO"}
Xpgcluster_data=${pgcluster_data-"%%PREFIX%%/pgsql/data"}
Xpgcluster_flags=${pgcluster_flags-"-w -s"}
X
X. %%RC_SUBR%%
X
Xload_rc_config pgcluster
X
Xname=pgcluster
Xrcvar=`set_rcvar`
Xcommand=%%PREFIX%%/bin/pg_ctl
Xpgcluster_user=pgsql
Xextra_commands="initdb recover"
Xinitdb_cmd="pgcluster_initdb"
Xrecover_cmd="pgcluster_recover"
Xstart_cmd="pgcluster_start"
Xstop_cmd="pgcluster_stop"
X
Xpgcluster_flags="${pgcluster_flags} -D ${pgcluster_data}"
Xpidfile="${pgcluster_data}/postmaster.pid"
X
Xpgcluster_start()
X{
X    su -m ${pgcluster_user} -c "exec ${command} start ${pgcluster_flags} -o '-i'"
X}
Xpgcluster_stop()
X{
X    su -m ${pgcluster_user} -c "exec ${command} stop ${pgcluster_flags} -m i"
X}
Xpgcluster_recover()
X{
X    su -m ${pgcluster_user} -c "exec ${command} start ${pgcluster_flags} -o '-i -R'"
X}
Xpgcluster_initdb()
X{
X    su -m ${pgcluster_user} -c "exec %%PREFIX%%/bin/initdb -D ${pgcluster_data}"
X}
X
Xload_rc_config $name
Xrun_rc_command "$1"
END-of-pgcluster74-server/files/pgcluster.sh.tmpl
echo x - pgcluster74-server/files/pglb.sh.tmpl
sed 's/^X//' >pgcluster74-server/files/pglb.sh.tmpl << 'END-of-pgcluster74-server/files/pglb.sh.tmpl'
X#!/bin/sh
X#
X# $FreeBSD: ports/databases/pgcluster/files/pglb.sh.tmpl,v 1.3 2004/07/26 23:28:47 kuriyama Exp $
X#
X# PROVIDE: pglb
X# REQUIRE: DAEMON
X# KEYWORD: FreeBSD
X#
X# Add the following line to /etc/rc.conf to enable pglb:
X#
X# pglb_enable="YES"
X#
X
Xpglb_enable=${pglb_enable-"NO"}
Xpglb_data=${pglb_data-"%%PREFIX%%/pgsql/data"}
X
X. %%RC_SUBR%%
X
Xload_rc_config pglb
X
Xname=pglb
Xrcvar=`set_rcvar`
Xcommand=%%PREFIX%%/bin/pglb
Xpglb_user=pgsql
Xstop_cmd="pglb_stop"
X
Xpglb_flags="${pglb_flags} -D ${pglb_data}"
X
Xpglb_stop()
X{
X    su -m ${pglb_user} -c "exec ${command} -D ${pglb_data} stop"
X}
X
Xload_rc_config $name
Xrun_rc_command "$1"
END-of-pgcluster74-server/files/pglb.sh.tmpl
echo x - pgcluster74-server/files/pgreplicate.sh.tmpl
sed 's/^X//' >pgcluster74-server/files/pgreplicate.sh.tmpl << 'END-of-pgcluster74-server/files/pgreplicate.sh.tmpl'
X#!/bin/sh
X#
X# $FreeBSD: ports/databases/pgcluster/files/pgreplicate.sh.tmpl,v 1.3 2004/07/26 23:28:47 kuriyama Exp $
X#
X# PROVIDE: pgreplicate
X# REQUIRE: DAEMON
X# BEFORE:  pglb
X# KEYWORD: FreeBSD
X#
X# Add the following line to /etc/rc.conf to enable pgreplicate:
X#
X# pgreplicate_enable="YES"
X#
X
Xpgreplicate_enable=${pgreplicate_enable-"NO"}
Xpgreplicate_data=${pgreplicate_data-"%%PREFIX%%/pgsql/data"}
X
X. %%RC_SUBR%%
X
Xload_rc_config pgreplicate
X
Xname=pgreplicate
Xrcvar=`set_rcvar`
Xcommand=%%PREFIX%%/bin/pgreplicate
Xpgreplicate_user=pgsql
Xstop_cmd="pgreplicate_stop"
X
Xpgreplicate_flags="${pgreplicate_flags} -D ${pgreplicate_data}"
Xpidfile="${pgreplicate_data}/pgreplicate.pid"
X
Xpgreplicate_stop()
X{
X    su -m ${pgreplicate_user} -c "exec ${command} -D ${pgreplicate_data} stop"
X}
X
Xload_rc_config $name
Xrun_rc_command "$1"
END-of-pgcluster74-server/files/pgreplicate.sh.tmpl
echo x - pgcluster74-server/pkg-install
sed 's/^X//' >pgcluster74-server/pkg-install << 'END-of-pgcluster74-server/pkg-install'
X#! /bin/sh
X
XPATH=/bin:/usr/sbin
XPGUSER=pgsql
XDB_DIR=${PKG_PREFIX}/${PGUSER}
X
Xbackupwarning() { echo "
X
X  =========== BACKUP YOUR DATA! =============
X  As always, backup your data before
X  upgrading. If the upgrade leads to a higher
X  minor revision (e.g. 7.3.x -> 7.4), a dump
X  and restore of all databases is
X  required. This is *NOT* done by the port!
X
X  Press ctrl-C *now* if you need to pg_dump.
X  ===========================================
X"
X	sleep 5
X}
X
Xcase $2 in
XPRE-INSTALL)
X	backupwarning
X	USER=${PGUSER}
X	GROUP=${USER}
X	UID=70
X	GID=${UID}
X
X	if pw group show "${GROUP}" 2>/dev/null; then
X		echo "You already have a group \"${GROUP}\", so I will use it."
X	else
X		if pw groupadd ${GROUP} -g ${GID}; then
X			echo "Added group \"${GROUP}\"."
X		else
X			echo "Adding group \"${GROUP}\" failed..."
X			exit 1
X		fi
X	fi
X
X	if pw user show "${USER}" 2>/dev/null; then
X		echo "You already have a user \"${USER}\", so I will use it."
X	else
X		if pw useradd ${USER} -u ${UID} -g ${GROUP} -h - \
X			-d ${DB_DIR} -c "PostgreSQL Daemon"
X		then
X			echo "Added user \"${USER}\"."
X		else
X			echo "Adding user \"${USER}\" failed..."
X			exit 1
X		fi
X	fi
X
X	if ! [ -x ~${PGUSER} ] ; then 
X		mkdir -p ${DB_DIR}
X		chown pgsql:pgsql ${DB_DIR}
X	fi
X	;;
X
XBACKUPWARNING)
X	backupwarning
X	;;
Xesac
END-of-pgcluster74-server/pkg-install
echo x - pgcluster74-server/pkg-plist-client
sed 's/^X//' >pgcluster74-server/pkg-plist-client << 'END-of-pgcluster74-server/pkg-plist-client'
X@comment $FreeBSD$
Xbin/initdb
Xbin/initlocation
Xbin/ipcclean
Xbin/pg_ctl
Xbin/pg_dump
Xbin/pg_restore
Xbin/pg_dumpall
Xbin/pg_id
Xbin/psql
Xbin/createdb
Xbin/dropdb
Xbin/createlang
Xbin/droplang
Xbin/createuser
Xbin/dropuser
Xbin/clusterdb
Xbin/vacuumdb
Xbin/pg_config
Xbin/pg_controldata
Xbin/pg_resetxlog
Xbin/pg_encoding
Xbin/ecpg
Xinclude/libpq/libpq-fs.h
Xinclude/postgresql/internal/libpq/pqcomm.h
Xinclude/postgresql/internal/lib/dllist.h
Xinclude/postgresql/internal/c.h
Xinclude/postgresql/internal/port.h
Xinclude/postgresql/internal/postgres_fe.h
Xinclude/postgresql/internal/libpq-int.h
Xinclude/postgresql/internal/pqexpbuffer.h
Xinclude/postgresql/informix/esql/datetime.h
Xinclude/postgresql/informix/esql/decimal.h
Xinclude/postgresql/informix/esql/sqltypes.h
Xinclude/postgresql/informix/esql/sqlda.h
Xinclude/postgresql/server/access/attnum.h
Xinclude/postgresql/server/access/clog.h
Xinclude/postgresql/server/access/genam.h
Xinclude/postgresql/server/access/gist.h
Xinclude/postgresql/server/access/gistscan.h
Xinclude/postgresql/server/access/hash.h
Xinclude/postgresql/server/access/heapam.h
Xinclude/postgresql/server/access/hio.h
Xinclude/postgresql/server/access/htup.h
Xinclude/postgresql/server/access/ibit.h
Xinclude/postgresql/server/access/iqual.h
Xinclude/postgresql/server/access/istrat.h
Xinclude/postgresql/server/access/itup.h
Xinclude/postgresql/server/access/nbtree.h
Xinclude/postgresql/server/access/printtup.h
Xinclude/postgresql/server/access/relscan.h
Xinclude/postgresql/server/access/rmgr.h
Xinclude/postgresql/server/access/rtree.h
Xinclude/postgresql/server/access/rtscan.h
Xinclude/postgresql/server/access/sdir.h
Xinclude/postgresql/server/access/skey.h
Xinclude/postgresql/server/access/slru.h
Xinclude/postgresql/server/access/strat.h
Xinclude/postgresql/server/access/transam.h
Xinclude/postgresql/server/access/tupdesc.h
Xinclude/postgresql/server/access/tupmacs.h
Xinclude/postgresql/server/access/tuptoaster.h
Xinclude/postgresql/server/access/valid.h
Xinclude/postgresql/server/access/xact.h
Xinclude/postgresql/server/access/xlog.h
Xinclude/postgresql/server/access/xlogdefs.h
Xinclude/postgresql/server/access/xlogutils.h
Xinclude/postgresql/server/bootstrap/bootstrap.h
Xinclude/postgresql/server/catalog/catalog.h
Xinclude/postgresql/server/catalog/catname.h
Xinclude/postgresql/server/catalog/catversion.h
Xinclude/postgresql/server/catalog/dependency.h
Xinclude/postgresql/server/catalog/heap.h
Xinclude/postgresql/server/catalog/index.h
Xinclude/postgresql/server/catalog/indexing.h
Xinclude/postgresql/server/catalog/namespace.h
Xinclude/postgresql/server/catalog/pg_aggregate.h
Xinclude/postgresql/server/catalog/pg_am.h
Xinclude/postgresql/server/catalog/pg_amop.h
Xinclude/postgresql/server/catalog/pg_amproc.h
Xinclude/postgresql/server/catalog/pg_attrdef.h
Xinclude/postgresql/server/catalog/pg_attribute.h
Xinclude/postgresql/server/catalog/pg_cast.h
Xinclude/postgresql/server/catalog/pg_class.h
Xinclude/postgresql/server/catalog/pg_constraint.h
Xinclude/postgresql/server/catalog/pg_control.h
Xinclude/postgresql/server/catalog/pg_conversion.h
Xinclude/postgresql/server/catalog/pg_database.h
Xinclude/postgresql/server/catalog/pg_depend.h
Xinclude/postgresql/server/catalog/pg_group.h
Xinclude/postgresql/server/catalog/pg_description.h
Xinclude/postgresql/server/catalog/pg_index.h
Xinclude/postgresql/server/catalog/pg_inherits.h
Xinclude/postgresql/server/catalog/pg_language.h
Xinclude/postgresql/server/catalog/pg_largeobject.h
Xinclude/postgresql/server/catalog/pg_listener.h
Xinclude/postgresql/server/catalog/pg_namespace.h
Xinclude/postgresql/server/catalog/pg_opclass.h
Xinclude/postgresql/server/catalog/pg_operator.h
Xinclude/postgresql/server/catalog/pg_proc.h
Xinclude/postgresql/server/catalog/pg_rewrite.h
Xinclude/postgresql/server/catalog/pg_shadow.h
Xinclude/postgresql/server/catalog/pg_statistic.h
Xinclude/postgresql/server/catalog/pg_trigger.h
Xinclude/postgresql/server/catalog/pg_type.h
Xinclude/postgresql/server/catalog/pg_version.h
Xinclude/postgresql/server/commands/alter.h
Xinclude/postgresql/server/commands/async.h
Xinclude/postgresql/server/commands/cluster.h
Xinclude/postgresql/server/commands/comment.h
Xinclude/postgresql/server/commands/conversioncmds.h
Xinclude/postgresql/server/commands/copy.h
Xinclude/postgresql/server/commands/dbcommands.h
Xinclude/postgresql/server/commands/defrem.h
Xinclude/postgresql/server/commands/explain.h
Xinclude/postgresql/server/commands/lockcmds.h
Xinclude/postgresql/server/commands/portalcmds.h
Xinclude/postgresql/server/commands/prepare.h
Xinclude/postgresql/server/commands/proclang.h
Xinclude/postgresql/server/commands/schemacmds.h
Xinclude/postgresql/server/commands/sequence.h
Xinclude/postgresql/server/commands/tablecmds.h
Xinclude/postgresql/server/commands/trigger.h
Xinclude/postgresql/server/commands/typecmds.h
Xinclude/postgresql/server/commands/user.h
Xinclude/postgresql/server/commands/vacuum.h
Xinclude/postgresql/server/commands/variable.h
Xinclude/postgresql/server/commands/version.h
Xinclude/postgresql/server/commands/view.h
Xinclude/postgresql/server/executor/execdebug.h
Xinclude/postgresql/server/executor/execdefs.h
Xinclude/postgresql/server/executor/execdesc.h
Xinclude/postgresql/server/executor/executor.h
Xinclude/postgresql/server/executor/functions.h
Xinclude/postgresql/server/executor/hashjoin.h
Xinclude/postgresql/server/executor/instrument.h
Xinclude/postgresql/server/executor/nodeAgg.h
Xinclude/postgresql/server/executor/nodeAppend.h
Xinclude/postgresql/server/executor/nodeFunctionscan.h
Xinclude/postgresql/server/executor/nodeGroup.h
Xinclude/postgresql/server/executor/nodeHash.h
Xinclude/postgresql/server/executor/nodeHashjoin.h
Xinclude/postgresql/server/executor/nodeIndexscan.h
Xinclude/postgresql/server/executor/nodeLimit.h
Xinclude/postgresql/server/executor/nodeMaterial.h
Xinclude/postgresql/server/executor/nodeMergejoin.h
Xinclude/postgresql/server/executor/nodeNestloop.h
Xinclude/postgresql/server/executor/nodeResult.h
Xinclude/postgresql/server/executor/nodeSeqscan.h
Xinclude/postgresql/server/executor/nodeSetOp.h
Xinclude/postgresql/server/executor/nodeSort.h
Xinclude/postgresql/server/executor/nodeSubplan.h
Xinclude/postgresql/server/executor/nodeSubqueryscan.h
Xinclude/postgresql/server/executor/nodeTidscan.h
Xinclude/postgresql/server/executor/nodeUnique.h
Xinclude/postgresql/server/executor/spi.h
Xinclude/postgresql/server/executor/spi_priv.h
Xinclude/postgresql/server/executor/tstoreReceiver.h
Xinclude/postgresql/server/executor/tuptable.h
Xinclude/postgresql/server/lib/dllist.h
Xinclude/postgresql/server/lib/lispsort.h
Xinclude/postgresql/server/lib/stringinfo.h
Xinclude/postgresql/server/libpq/auth.h
Xinclude/postgresql/server/libpq/be-fsstubs.h
Xinclude/postgresql/server/libpq/crypt.h
Xinclude/postgresql/server/libpq/hba.h
Xinclude/postgresql/server/libpq/ip.h
Xinclude/postgresql/server/libpq/libpq-be.h
Xinclude/postgresql/server/libpq/libpq-fs.h
Xinclude/postgresql/server/libpq/libpq.h
Xinclude/postgresql/server/libpq/pqcomm.h
Xinclude/postgresql/server/libpq/pqformat.h
Xinclude/postgresql/server/libpq/pqsignal.h
Xinclude/postgresql/server/mb/pg_wchar.h
Xinclude/postgresql/server/nodes/bitmapset.h
Xinclude/postgresql/server/nodes/execnodes.h
Xinclude/postgresql/server/nodes/makefuncs.h
Xinclude/postgresql/server/nodes/memnodes.h
Xinclude/postgresql/server/nodes/nodeFuncs.h
Xinclude/postgresql/server/nodes/nodes.h
Xinclude/postgresql/server/nodes/params.h
Xinclude/postgresql/server/nodes/parsenodes.h
Xinclude/postgresql/server/nodes/pg_list.h
Xinclude/postgresql/server/nodes/plannodes.h
Xinclude/postgresql/server/nodes/primnodes.h
Xinclude/postgresql/server/nodes/print.h
Xinclude/postgresql/server/nodes/readfuncs.h
Xinclude/postgresql/server/nodes/relation.h
Xinclude/postgresql/server/optimizer/clauses.h
Xinclude/postgresql/server/optimizer/cost.h
Xinclude/postgresql/server/optimizer/geqo.h
Xinclude/postgresql/server/optimizer/geqo_copy.h
Xinclude/postgresql/server/optimizer/geqo_gene.h
Xinclude/postgresql/server/optimizer/geqo_misc.h
Xinclude/postgresql/server/optimizer/geqo_mutation.h
Xinclude/postgresql/server/optimizer/geqo_pool.h
Xinclude/postgresql/server/optimizer/geqo_random.h
Xinclude/postgresql/server/optimizer/geqo_recombination.h
Xinclude/postgresql/server/optimizer/geqo_selection.h
Xinclude/postgresql/server/optimizer/joininfo.h
Xinclude/postgresql/server/optimizer/pathnode.h
Xinclude/postgresql/server/optimizer/paths.h
Xinclude/postgresql/server/optimizer/plancat.h
Xinclude/postgresql/server/optimizer/planmain.h
Xinclude/postgresql/server/optimizer/planner.h
Xinclude/postgresql/server/optimizer/prep.h
Xinclude/postgresql/server/optimizer/restrictinfo.h
Xinclude/postgresql/server/optimizer/subselect.h
Xinclude/postgresql/server/optimizer/tlist.h
Xinclude/postgresql/server/optimizer/var.h
Xinclude/postgresql/server/parser/analyze.h
Xinclude/postgresql/server/parser/gramparse.h
Xinclude/postgresql/server/parser/keywords.h
Xinclude/postgresql/server/parser/parse.h
Xinclude/postgresql/server/parser/parse_agg.h
Xinclude/postgresql/server/parser/parse_clause.h
Xinclude/postgresql/server/parser/parse_coerce.h
Xinclude/postgresql/server/parser/parse_expr.h
Xinclude/postgresql/server/parser/parse_func.h
Xinclude/postgresql/server/parser/parse_node.h
Xinclude/postgresql/server/parser/parse_oper.h
Xinclude/postgresql/server/parser/parse_relation.h
Xinclude/postgresql/server/parser/parse_target.h
Xinclude/postgresql/server/parser/parse_type.h
Xinclude/postgresql/server/parser/parser.h
Xinclude/postgresql/server/parser/parsetree.h
Xinclude/postgresql/server/parser/scansup.h
Xinclude/postgresql/server/port/aix.h
Xinclude/postgresql/server/port/beos.h
Xinclude/postgresql/server/port/bsdi.h
Xinclude/postgresql/server/port/cygwin.h
Xinclude/postgresql/server/port/darwin.h
Xinclude/postgresql/server/port/dgux.h
Xinclude/postgresql/server/port/freebsd.h
Xinclude/postgresql/server/port/hpux.h
Xinclude/postgresql/server/port/irix5.h
Xinclude/postgresql/server/port/linux.h
Xinclude/postgresql/server/port/netbsd.h
Xinclude/postgresql/server/port/nextstep.h
Xinclude/postgresql/server/port/openbsd.h
Xinclude/postgresql/server/port/osf.h
Xinclude/postgresql/server/port/qnx4.h
Xinclude/postgresql/server/port/sco.h
Xinclude/postgresql/server/port/solaris.h
Xinclude/postgresql/server/port/sunos4.h
Xinclude/postgresql/server/port/svr4.h
Xinclude/postgresql/server/port/ultrix4.h
Xinclude/postgresql/server/port/univel.h
Xinclude/postgresql/server/port/unixware.h
Xinclude/postgresql/server/port/win32.h
Xinclude/postgresql/server/regex/regcustom.h
Xinclude/postgresql/server/regex/regerrs.h
Xinclude/postgresql/server/regex/regex.h
Xinclude/postgresql/server/regex/regguts.h
Xinclude/postgresql/server/rewrite/prs2lock.h
Xinclude/postgresql/server/rewrite/rewriteDefine.h
Xinclude/postgresql/server/rewrite/rewriteHandler.h
Xinclude/postgresql/server/rewrite/rewriteManip.h
Xinclude/postgresql/server/rewrite/rewriteRemove.h
Xinclude/postgresql/server/rewrite/rewriteSupport.h
Xinclude/postgresql/server/storage/backendid.h
Xinclude/postgresql/server/storage/block.h
Xinclude/postgresql/server/storage/buf.h
Xinclude/postgresql/server/storage/buf_internals.h
Xinclude/postgresql/server/storage/buffile.h
Xinclude/postgresql/server/storage/bufmgr.h
Xinclude/postgresql/server/storage/bufpage.h
Xinclude/postgresql/server/storage/fd.h
Xinclude/postgresql/server/storage/freespace.h
Xinclude/postgresql/server/storage/ipc.h
Xinclude/postgresql/server/storage/item.h
Xinclude/postgresql/server/storage/itemid.h
Xinclude/postgresql/server/storage/itempos.h
Xinclude/postgresql/server/storage/itemptr.h
Xinclude/postgresql/server/storage/large_object.h
Xinclude/postgresql/server/storage/lmgr.h
Xinclude/postgresql/server/storage/lock.h
Xinclude/postgresql/server/storage/lwlock.h
Xinclude/postgresql/server/storage/off.h
Xinclude/postgresql/server/storage/pg_sema.h
Xinclude/postgresql/server/storage/pg_shmem.h
Xinclude/postgresql/server/storage/pmsignal.h
Xinclude/postgresql/server/storage/pos.h
Xinclude/postgresql/server/storage/proc.h
Xinclude/postgresql/server/storage/shmem.h
Xinclude/postgresql/server/storage/relfilenode.h
Xinclude/postgresql/server/storage/s_lock.h
Xinclude/postgresql/server/storage/sinval.h
Xinclude/postgresql/server/storage/sinvaladt.h
Xinclude/postgresql/server/storage/smgr.h
Xinclude/postgresql/server/storage/spin.h
Xinclude/postgresql/server/tcop/dest.h
Xinclude/postgresql/server/tcop/fastpath.h
Xinclude/postgresql/server/tcop/pquery.h
Xinclude/postgresql/server/tcop/tcopdebug.h
Xinclude/postgresql/server/tcop/tcopprot.h
Xinclude/postgresql/server/tcop/utility.h
Xinclude/postgresql/server/utils/acl.h
Xinclude/postgresql/server/utils/array.h
Xinclude/postgresql/server/utils/ascii.h
Xinclude/postgresql/server/utils/builtins.h
Xinclude/postgresql/server/utils/cash.h
Xinclude/postgresql/server/utils/catcache.h
Xinclude/postgresql/server/utils/date.h
Xinclude/postgresql/server/utils/datetime.h
Xinclude/postgresql/server/utils/datum.h
Xinclude/postgresql/server/utils/dynahash.h
Xinclude/postgresql/server/utils/dynamic_loader.h
Xinclude/postgresql/server/utils/elog.h
Xinclude/postgresql/server/utils/errcodes.h
Xinclude/postgresql/server/utils/fmgroids.h
Xinclude/postgresql/server/utils/fmgrtab.h
Xinclude/postgresql/server/utils/formatting.h
Xinclude/postgresql/server/utils/geo_decls.h
Xinclude/postgresql/server/utils/guc.h
Xinclude/postgresql/server/utils/guc_tables.h
Xinclude/postgresql/server/utils/help_config.h
Xinclude/postgresql/server/utils/hsearch.h
Xinclude/postgresql/server/utils/inet.h
Xinclude/postgresql/server/utils/int8.h
Xinclude/postgresql/server/utils/inval.h
Xinclude/postgresql/server/utils/logtape.h
Xinclude/postgresql/server/utils/lsyscache.h
Xinclude/postgresql/server/utils/memutils.h
Xinclude/postgresql/server/utils/nabstime.h
Xinclude/postgresql/server/utils/numeric.h
Xinclude/postgresql/server/utils/palloc.h
Xinclude/postgresql/server/utils/pg_crc.h
Xinclude/postgresql/server/utils/pg_locale.h
Xinclude/postgresql/server/utils/pg_lzcompress.h
Xinclude/postgresql/server/utils/portal.h
Xinclude/postgresql/server/utils/ps_status.h
Xinclude/postgresql/server/utils/rel.h
Xinclude/postgresql/server/utils/relcache.h
Xinclude/postgresql/server/utils/selfuncs.h
Xinclude/postgresql/server/utils/sets.h
Xinclude/postgresql/server/utils/syscache.h
Xinclude/postgresql/server/utils/timestamp.h
Xinclude/postgresql/server/utils/tqual.h
Xinclude/postgresql/server/utils/tuplesort.h
Xinclude/postgresql/server/utils/tuplestore.h
Xinclude/postgresql/server/utils/typcache.h
Xinclude/postgresql/server/utils/varbit.h
Xinclude/postgresql/server/pg_config.h
Xinclude/postgresql/server/pg_config_os.h
Xinclude/postgresql/server/c.h
Xinclude/postgresql/server/dynloader.h
Xinclude/postgresql/server/fmgr.h
Xinclude/postgresql/server/funcapi.h
Xinclude/postgresql/server/getaddrinfo.h
Xinclude/postgresql/server/getopt_long.h
Xinclude/postgresql/server/miscadmin.h
Xinclude/postgresql/server/pg_config_manual.h
Xinclude/postgresql/server/pgstat.h
Xinclude/postgresql/server/port.h
Xinclude/postgresql/server/postgres.h
Xinclude/postgresql/server/postgres_ext.h
Xinclude/postgresql/server/postgres_fe.h
Xinclude/postgresql/server/replicate.h
Xinclude/postgresql/server/replicate_com.h
Xinclude/postgresql/server/rusagestub.h
Xinclude/postgresql/server/strdup.h
Xinclude/postgres_ext.h
Xinclude/pg_config.h
Xinclude/pg_config_os.h
Xinclude/pg_config_manual.h
Xinclude/libpq-fe.h
Xinclude/ecpgerrno.h
Xinclude/ecpglib.h
Xinclude/ecpgtype.h
Xinclude/sqlca.h
Xinclude/sql3types.h
Xinclude/ecpg_informix.h
Xinclude/pgtypes_error.h
Xinclude/pgtypes_numeric.h
Xinclude/pgtypes_timestamp.h
Xinclude/pgtypes_date.h
Xinclude/pgtypes_interval.h
Xlib/libpq.so
Xlib/libpq.a
Xlib/libpq.so.3
Xlib/libpgtypes.so
Xlib/libpgtypes.a
Xlib/libpgtypes.so.1
Xlib/libecpg.so
Xlib/libecpg.a
Xlib/libecpg.so.4
Xlib/libecpg_compat.a
Xlib/libecpg_compat.so.1
Xlib/libecpg_compat.so
X%%DATADIR%%/pg_service.conf.sample
X%%GETTEXT%%share/locale/de/LC_MESSAGES/pg_dump.mo
X%%GETTEXT%%share/locale/de/LC_MESSAGES/psql.mo
X%%GETTEXT%%share/locale/de/LC_MESSAGES/pgscripts.mo
X%%GETTEXT%%share/locale/de/LC_MESSAGES/pg_controldata.mo
X%%GETTEXT%%share/locale/de/LC_MESSAGES/pg_resetxlog.mo
X%%GETTEXT%%share/locale/de/LC_MESSAGES/libpq.mo
X%%GETTEXT%%share/locale/es/LC_MESSAGES/pg_dump.mo
X%%GETTEXT%%share/locale/es/LC_MESSAGES/psql.mo
X%%GETTEXT%%share/locale/es/LC_MESSAGES/pgscripts.mo
X%%GETTEXT%%share/locale/es/LC_MESSAGES/pg_controldata.mo
X%%GETTEXT%%share/locale/es/LC_MESSAGES/pg_resetxlog.mo
X%%GETTEXT%%share/locale/es/LC_MESSAGES/libpq.mo
X%%GETTEXT%%share/locale/fr/LC_MESSAGES/pg_dump.mo
X%%GETTEXT%%share/locale/fr/LC_MESSAGES/psql.mo
X%%GETTEXT%%share/locale/fr/LC_MESSAGES/pgscripts.mo
X%%GETTEXT%%share/locale/fr/LC_MESSAGES/pg_controldata.mo
X%%GETTEXT%%share/locale/fr/LC_MESSAGES/pg_resetxlog.mo
X%%GETTEXT%%share/locale/fr/LC_MESSAGES/libpq.mo
X%%GETTEXT%%share/locale/hr/LC_MESSAGES/libpq.mo
X%%GETTEXT%%share/locale/hu/LC_MESSAGES/psql.mo
X%%GETTEXT%%share/locale/hu/LC_MESSAGES/pg_controldata.mo
X%%GETTEXT%%share/locale/hu/LC_MESSAGES/pg_resetxlog.mo
X%%GETTEXT%%share/locale/it/LC_MESSAGES/pg_dump.mo
X%%GETTEXT%%share/locale/it/LC_MESSAGES/psql.mo
X%%GETTEXT%%share/locale/it/LC_MESSAGES/pgscripts.mo
X%%GETTEXT%%share/locale/it/LC_MESSAGES/pg_controldata.mo
X%%GETTEXT%%share/locale/it/LC_MESSAGES/pg_resetxlog.mo
X%%GETTEXT%%share/locale/it/LC_MESSAGES/libpq.mo
X%%GETTEXT%%share/locale/nb/LC_MESSAGES/pg_dump.mo
X%%GETTEXT%%share/locale/nb/LC_MESSAGES/psql.mo
X%%GETTEXT%%share/locale/nb/LC_MESSAGES/pg_controldata.mo
X%%GETTEXT%%share/locale/nb/LC_MESSAGES/pg_resetxlog.mo
X%%GETTEXT%%share/locale/nb/LC_MESSAGES/libpq.mo
X%%GETTEXT%%share/locale/pt_BR/LC_MESSAGES/pg_dump.mo
X%%GETTEXT%%share/locale/pt_BR/LC_MESSAGES/psql.mo
X%%GETTEXT%%share/locale/pt_BR/LC_MESSAGES/pgscripts.mo
X%%GETTEXT%%share/locale/pt_BR/LC_MESSAGES/pg_controldata.mo
X%%GETTEXT%%share/locale/pt_BR/LC_MESSAGES/pg_resetxlog.mo
X%%GETTEXT%%share/locale/pt_BR/LC_MESSAGES/libpq.mo
X%%GETTEXT%%share/locale/ru/LC_MESSAGES/pg_dump.mo
X%%GETTEXT%%share/locale/ru/LC_MESSAGES/psql.mo
X%%GETTEXT%%share/locale/ru/LC_MESSAGES/pgscripts.mo
X%%GETTEXT%%share/locale/ru/LC_MESSAGES/pg_controldata.mo
X%%GETTEXT%%share/locale/ru/LC_MESSAGES/pg_resetxlog.mo
X%%GETTEXT%%share/locale/ru/LC_MESSAGES/libpq.mo
X%%GETTEXT%%share/locale/sv/LC_MESSAGES/pg_dump.mo
X%%GETTEXT%%share/locale/sv/LC_MESSAGES/psql.mo
X%%GETTEXT%%share/locale/sv/LC_MESSAGES/pgscripts.mo
X%%GETTEXT%%share/locale/sv/LC_MESSAGES/pg_controldata.mo
X%%GETTEXT%%share/locale/sv/LC_MESSAGES/pg_resetxlog.mo
X%%GETTEXT%%share/locale/sv/LC_MESSAGES/libpq.mo
X%%GETTEXT%%share/locale/tr/LC_MESSAGES/psql.mo
X%%GETTEXT%%share/locale/tr/LC_MESSAGES/pgscripts.mo
X%%GETTEXT%%share/locale/tr/LC_MESSAGES/pg_controldata.mo
X%%GETTEXT%%share/locale/tr/LC_MESSAGES/pg_resetxlog.mo
X%%GETTEXT%%share/locale/tr/LC_MESSAGES/libpq.mo
X%%GETTEXT%%share/locale/cs/LC_MESSAGES/pg_dump.mo
X%%GETTEXT%%share/locale/cs/LC_MESSAGES/psql.mo
X%%GETTEXT%%share/locale/cs/LC_MESSAGES/pgscripts.mo
X%%GETTEXT%%share/locale/cs/LC_MESSAGES/pg_controldata.mo
X%%GETTEXT%%share/locale/cs/LC_MESSAGES/pg_resetxlog.mo
X%%GETTEXT%%share/locale/cs/LC_MESSAGES/libpq.mo
X%%GETTEXT%%share/locale/zh_CN/LC_MESSAGES/pg_dump.mo
X%%GETTEXT%%share/locale/zh_CN/LC_MESSAGES/psql.mo
X%%GETTEXT%%share/locale/zh_CN/LC_MESSAGES/pgscripts.mo
X%%GETTEXT%%share/locale/zh_CN/LC_MESSAGES/pg_controldata.mo
X%%GETTEXT%%share/locale/zh_CN/LC_MESSAGES/pg_resetxlog.mo
X%%GETTEXT%%share/locale/zh_CN/LC_MESSAGES/libpq.mo
X%%GETTEXT%%share/locale/zh_TW/LC_MESSAGES/pg_dump.mo
X%%GETTEXT%%share/locale/zh_TW/LC_MESSAGES/psql.mo
X%%GETTEXT%%share/locale/zh_TW/LC_MESSAGES/pg_controldata.mo
X%%GETTEXT%%share/locale/zh_TW/LC_MESSAGES/libpq.mo
X%%GETTEXT%%share/locale/sl/LC_MESSAGES/psql.mo
X%%GETTEXT%%share/locale/sl/LC_MESSAGES/pgscripts.mo
X%%GETTEXT%%share/locale/sl/LC_MESSAGES/pg_controldata.mo
X%%GETTEXT%%share/locale/sl/LC_MESSAGES/pg_resetxlog.mo
X%%GETTEXT%%share/locale/sl/LC_MESSAGES/libpq.mo
X@dirrm %%DATADIR%%
X@unexec rmdir %D/include/postgresql/server/utils 2>/dev/null || true
X@unexec rmdir %D/include/postgresql/server/tcop 2>/dev/null || true
X@unexec rmdir %D/include/postgresql/server/storage 2>/dev/null || true
X@unexec rmdir %D/include/postgresql/server/rewrite 2>/dev/null || true
X@unexec rmdir %D/include/postgresql/server/regex 2>/dev/null || true
X@unexec rmdir %D/include/postgresql/server/port 2>/dev/null || true
X@unexec rmdir %D/include/postgresql/server/parser 2>/dev/null || true
X@unexec rmdir %D/include/postgresql/server/optimizer 2>/dev/null || true
X@unexec rmdir %D/include/postgresql/server/nodes 2>/dev/null || true
X@unexec rmdir %D/include/postgresql/server/mb 2>/dev/null || true
X@unexec rmdir %D/include/postgresql/server/libpq 2>/dev/null || true
X@unexec rmdir %D/include/postgresql/server/lib 2>/dev/null || true
X@unexec rmdir %D/include/postgresql/server/executor 2>/dev/null || true
X@unexec rmdir %D/include/postgresql/server/commands 2>/dev/null || true
X@unexec rmdir %D/include/postgresql/server/catalog 2>/dev/null || true
X@unexec rmdir %D/include/postgresql/server/bootstrap 2>/dev/null || true
X@unexec rmdir %D/include/postgresql/server/access 2>/dev/null || true
X@unexec rmdir %D/include/postgresql/server 2>/dev/null || true
X@unexec rmdir %D/include/postgresql/internal/libpq 2>/dev/null || true
X@unexec rmdir %D/include/postgresql/internal/lib 2>/dev/null || true
X@unexec rmdir %D/include/postgresql/internal 2>/dev/null || true
X@unexec rmdir %D/include/postgresql/informix/esql 2>/dev/null || true
X@unexec rmdir %D/include/postgresql/informix 2>/dev/null || true
X@unexec rmdir %D/include/postgresql 2>/dev/null || true
X@unexec rmdir %D/include/libpq 2>/dev/null || true
END-of-pgcluster74-server/pkg-plist-client
echo x - pgcluster74-server/pkg-plist
sed 's/^X//' >pgcluster74-server/pkg-plist << 'END-of-pgcluster74-server/pkg-plist'
X@comment $FreeBSD$
Xetc/rc.d/pgcluster.sh
Xetc/periodic/daily/502.pgsql
Xbin/postmaster
Xbin/postgres
Xlib/postgresql/ascii_and_mic.so
Xlib/postgresql/cyrillic_and_mic.so
Xlib/postgresql/euc_cn_and_mic.so
Xlib/postgresql/euc_jp_and_sjis.so
Xlib/postgresql/euc_kr_and_mic.so
Xlib/postgresql/euc_tw_and_big5.so
Xlib/postgresql/latin2_and_win1250.so
Xlib/postgresql/latin_and_mic.so
Xlib/postgresql/utf8_and_ascii.so
Xlib/postgresql/utf8_and_big5.so
Xlib/postgresql/utf8_and_cyrillic.so
Xlib/postgresql/utf8_and_euc_cn.so
Xlib/postgresql/utf8_and_euc_jp.so
Xlib/postgresql/utf8_and_euc_kr.so
Xlib/postgresql/utf8_and_euc_tw.so
Xlib/postgresql/utf8_and_gb18030.so
Xlib/postgresql/utf8_and_gbk.so
Xlib/postgresql/utf8_and_iso8859.so
Xlib/postgresql/utf8_and_iso8859_1.so
Xlib/postgresql/utf8_and_johab.so
Xlib/postgresql/utf8_and_sjis.so
Xlib/postgresql/utf8_and_tcvn.so
Xlib/postgresql/utf8_and_uhc.so
Xlib/postgresql/utf8_and_win1250.so
Xlib/postgresql/utf8_and_win1256.so
Xlib/postgresql/utf8_and_win874.so
Xlib/postgresql/plpgsql.so
Xshare/postgresql/postgres.bki
Xshare/postgresql/postgres.description
Xshare/postgresql/information_schema.sql
Xshare/postgresql/sql_features.txt
Xshare/postgresql/pg_hba.conf.sample
Xshare/postgresql/pg_ident.conf.sample
Xshare/postgresql/postgresql.conf.sample
Xshare/postgresql/cluster.conf.sample
Xshare/postgresql/conversion_create.sql
Xshare/postgresql/dot.cshrc.dist
Xshare/postgresql/dot.profile.dist
X%%GETTEXT%%share/locale/de/LC_MESSAGES/postgres.mo
X%%GETTEXT%%share/locale/es/LC_MESSAGES/postgres.mo
X%%GETTEXT%%share/locale/fr/LC_MESSAGES/postgres.mo
X%%GETTEXT%%share/locale/hr/LC_MESSAGES/postgres.mo
X%%GETTEXT%%share/locale/hu/LC_MESSAGES/postgres.mo
X%%GETTEXT%%share/locale/it/LC_MESSAGES/postgres.mo
X%%GETTEXT%%share/locale/nb/LC_MESSAGES/postgres.mo
X%%GETTEXT%%share/locale/pt_BR/LC_MESSAGES/postgres.mo
X%%GETTEXT%%share/locale/ru/LC_MESSAGES/postgres.mo
X%%GETTEXT%%share/locale/sv/LC_MESSAGES/postgres.mo
X%%GETTEXT%%share/locale/tr/LC_MESSAGES/postgres.mo
X%%GETTEXT%%share/locale/cs/LC_MESSAGES/postgres.mo
X%%GETTEXT%%share/locale/zh_CN/LC_MESSAGES/postgres.mo
X%%GETTEXT%%share/locale/zh_TW/LC_MESSAGES/postgres.mo
X%%PGSQLLB%%bin/pglb
X%%PGSQLLB%%etc/pglb.conf.sample
X%%PGSQLLB%%etc/rc.d/pglb.sh
X%%PGSQLRP%%bin/pgreplicate
X%%PGSQLRP%%etc/pgreplicate.conf.sample
X%%PGSQLRP%%etc/rc.d/pgreplicate.sh
END-of-pgcluster74-server/pkg-plist
exit
--- pgcluster74.shar ends here ---


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200508011332.j71DW1iV065323>