ports/84430: [New Port] databases/pgcluster74-(server|client) : The multi-master and synchronous replication system for PostgreSQL
Marcos Tischer Vallim
tischer at ig.com.br
Mon Aug 1 13:40:21 UTC 2005
>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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at dirrm %%DATADIR%%
X at unexec rmdir %D/include/postgresql/server/utils 2>/dev/null || true
X at unexec rmdir %D/include/postgresql/server/tcop 2>/dev/null || true
X at unexec rmdir %D/include/postgresql/server/storage 2>/dev/null || true
X at unexec rmdir %D/include/postgresql/server/rewrite 2>/dev/null || true
X at unexec rmdir %D/include/postgresql/server/regex 2>/dev/null || true
X at unexec rmdir %D/include/postgresql/server/port 2>/dev/null || true
X at unexec rmdir %D/include/postgresql/server/parser 2>/dev/null || true
X at unexec rmdir %D/include/postgresql/server/optimizer 2>/dev/null || true
X at unexec rmdir %D/include/postgresql/server/nodes 2>/dev/null || true
X at unexec rmdir %D/include/postgresql/server/mb 2>/dev/null || true
X at unexec rmdir %D/include/postgresql/server/libpq 2>/dev/null || true
X at unexec rmdir %D/include/postgresql/server/lib 2>/dev/null || true
X at unexec rmdir %D/include/postgresql/server/executor 2>/dev/null || true
X at unexec rmdir %D/include/postgresql/server/commands 2>/dev/null || true
X at unexec rmdir %D/include/postgresql/server/catalog 2>/dev/null || true
X at unexec rmdir %D/include/postgresql/server/bootstrap 2>/dev/null || true
X at unexec rmdir %D/include/postgresql/server/access 2>/dev/null || true
X at unexec rmdir %D/include/postgresql/server 2>/dev/null || true
X at unexec rmdir %D/include/postgresql/internal/libpq 2>/dev/null || true
X at unexec rmdir %D/include/postgresql/internal/lib 2>/dev/null || true
X at unexec rmdir %D/include/postgresql/internal 2>/dev/null || true
X at unexec rmdir %D/include/postgresql/informix/esql 2>/dev/null || true
X at unexec rmdir %D/include/postgresql/informix 2>/dev/null || true
X at unexec rmdir %D/include/postgresql 2>/dev/null || true
X at 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 at 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:
More information about the freebsd-ports-bugs
mailing list