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