Update of /cvsroot/monetdb/pathfinder/runtime
In directory sc8-pr-cvs16:/tmp/cvs-serv17931/runtime
Modified Files:
Makefile.ag pf_support.mx
Added Files:
ll_prec_foll.mx
Log Message:
added loop-lifted implementation of following step
(not activated, yet; activation will follow in extra checkin)
(preceding step will follow later)
No extensive performance testing done, yet
(of all standard benchmarks, only one query of XPathMark uses the following
step).
However, the query reported by JanR in bug report #1654317
"XQ: following step kills Mserver (after 2h)"
(http://sourceforge.net/tracker/index.php?func=detail&aid=1654317&group_id=56967&atid=482468)
now runs in ~45 secs instead of ~30 min with the ALG backend
(on a 2 GHz Opteron with 8 GB RAM; Mserver grows to 4/8 GB res/virt);
Unfortunately, the MPS version now grows to 14 GB and does not finish
within 3 h (used to take 2 h requiring "just" 8 GB).
Declaration/disclaimer:
-----------------------
On my FC6 desktop (64-bit, 64-bit OIDs, configured with --enable-optimize,
compiled with gcc 4.1.1), this check-in does not make any pathfinder test
fail that did not also fail with the most recent code base in CVS prior to
this check-in.
I did not check in detail, though, whether all previously failing tests
still fail the same way after this check-in as they did before this
check-in.
Index: Makefile.ag
===================================================================
RCS file: /cvsroot/monetdb/pathfinder/runtime/Makefile.ag,v
retrieving revision 1.74
retrieving revision 1.75
diff -u -d -r1.74 -r1.75
--- Makefile.ag 2 Mar 2007 12:35:42 -0000 1.74
+++ Makefile.ag 14 May 2007 09:55:29 -0000 1.75
@@ -46,7 +46,8 @@
SOURCES = \
levelsteps.mx \
ll_staircasejoin.mx \
- ll_upwards.mx
+ ll_upwards.mx \
+ ll_prec_foll.mx
}
lib__pf_support = {
--- NEW FILE: ll_prec_foll.mx ---
kf@' Copyright Notice:
@' -----------------
@'
@' The contents of this file are subject to the Pathfinder Public License
@' Version 1.1 (the "License"); you may not use this file except in
@' compliance with the License. You may obtain a copy of the License at
@' http://monetdb.cwi.nl/Legal/PathfinderLicense-1.1.html
@'
@' Software distributed under the License is distributed on an "AS IS"
@' basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
@' the License for the specific language governing rights and limitations
@' under the License.
@'
@' The Original Code is the Pathfinder system.
@'
@' The Original Code has initially been developed by the Database &
@' Information Systems Group at the University of Konstanz, Germany and
@' is now maintained by the Database Systems Group at the Technische
@' Universitaet Muenchen, Germany. Portions created by the University of
@' Konstanz and the Technische Universitaet Muenchen are Copyright (C)
@' 2000-2005 University of Konstanz and (C) 2005-2007 Technische
@' Universitaet Muenchen, respectively. All Rights Reserved.
@'
@' $Id: ll_prec_foll.mx,v 1.1 2007/05/14 09:55:29 stmane Exp $
@f ll_prec_foll
@a Stefan Manegold, Peter Boncz, Jenni Zhang
@t ll_prec_foll
@c
/*******************************************
* ll_prec_foll.c : axis step operators for loop-lifted preceding and following
axis
*
*/
#include "pf_config.h"
#include <gdk.h>
/**
* This file contains the axis step algoritms for following and
* preceding axis.
*
* Both algorithms work similiar to the staircase-join approach:
*
* - evaluation is done during a single sequential scan of the
* size table and the context set
* (we now use size rather than level to enable skipping)
* - context set pruning is performed on-the-fly
*
* Unlike the staircasejoins for ancestor and desecendant steps
* we have to take care about the limitations of document fragments.
* Nodes on the following axis of x, are all nodes with
* pre(v) > pre(x) + size(x),
* but only that nodes qualify, that belong to the same document fragment
* as x itself.
*/
#define PFll_check_BAT_capacity(b,grow) \
{\
size_t _oldcap = BATbuncount(b);\
size_t _reqcap = BATcount(b) + grow;\
size_t _bunsize = BUNsize(b);\
if (_oldcap < _reqcap) {\
size_t _newcap = MAX(_reqcap, BATgrows(b));\
if (BATextend((b), _newcap) == NULL) {\
GDKerror("%s: BATextend of BAT '%s' (#%d) failed "\
"for " SZFMT " buns (" SZFMT " bytes).\n",\
__func__, BATgetId(b), (b)->batCacheid,\
_newcap, _newcap * _bunsize);\
BBPreclaim(b);\
return GDK_FAIL;\
}\
_newcap = BATbuncount(b);\
if (_newcap < _reqcap) {\
GDKerror("%s: BATextend of BAT '%s' (#%d) failed: "\
"required " SZFMT " buns (" SZFMT " bytes), "\
"got only " SZFMT " buns (" SZFMT " bytes).\n",\
__func__, BATgetId(b), (b)->batCacheid,\
_reqcap, _reqcap * _bunsize,\
_newcap, _newcap * _bunsize);\
BBPreclaim(b);\
return GDK_FAIL;\
}\
}\
}
/* FOLLOWING STEP */
int
PFll_following(BAT **result, BAT *iter_bat, BAT *ctx_bat, BAT *pre_size, BAT
*doc_pre/*, int *upperbound*/)
{
@= init
char *name = "[EMAIL PROTECTED]";
BUN p = 0, q = 0;
int xx = 0, *size = 0;
size_t res_size = 0, grow = 0;
BAT *res = 0;
oid *iter_cur = 0, *iter_end = 0, *ctx_cur = 0, *ctx_end = 0, *res_cur = 0;
int iter_nxt = 0, ctx_nxt = 0;
bit one_ctx = 0;
oid min_iter = 0, max_iter = 0, num_iter = 0;
/* --------------------------- checks ---------------------------------- */
BATcheck(iter_bat, name);
BATcheck(ctx_bat, name);
BATcheck(pre_size, name);
BATcheck(doc_pre, name);
iter_cur = (oid*) BUNtail(iter_bat, BUNfirst(iter_bat));
iter_end = (oid*) BUNtail(iter_bat, BUNlast(iter_bat));
iter_nxt = BUNsize(iter_bat)/sizeof(oid);
ctx_cur = (oid*) BUNtail(ctx_bat, BUNfirst(ctx_bat));
ctx_end = (oid*) BUNtail(ctx_bat, BUNlast(ctx_bat));
ctx_nxt = BUNsize(ctx_bat)/sizeof(oid);
one_ctx = *ctx_cur == *(ctx_end - ctx_nxt);
ALGODEBUG
THRprintf(GDKout, "%s: |iter_bat|="SZFMT", |ctx_bat|="SZFMT",
|pre_size|="SZFMT", |doc_pre|="SZFMT", one_ctx=%d\n",
name, BATcount(iter_bat), BATcount(ctx_bat),
BATcount(pre_size), BATcount(doc_pre), (int)one_ctx);
if (!(BAThdense(iter_bat) && BAThdense(ctx_bat)))
{
GDKerror("%s: both iter_bat and ctx_bat must have a dense head.\n",
name);
return GDK_FAIL;
}
if ((iter_bat->hseqbase != ctx_bat->hseqbase) || (BATcount(iter_bat) !=
BATcount(ctx_bat)))
{
GDKerror("%s: iter_bat and ctx_bat must be head-aligned, i.e., have
equal head seqbases and length.\n", name);
return GDK_FAIL;
}
if (!(BATtordered(ctx_bat) & 1))
{
GDKerror("%s: ctx_bat must be ordered on tail.\n", name);
return GDK_FAIL;
}
if (one_ctx && !(BATtordered(iter_bat) & 1))
{
GDKerror("%s: iter_bat must be ordered on tail.\n", name);
return GDK_FAIL;
}
if (!BAThdense(pre_size))
{
GDKerror("%s: head of pre_size must be dense.\n", name);
return GDK_FAIL;
}
if (pre_size->ttype != TYPE_int)
{
GDKerror("%s: tail of pre_size must be type INT.\n", name);
return GDK_FAIL;
}
if (BUNsize(pre_size) != sizeof(int))
{
GDKerror("%s: head (oid) of pre_size must NOT be materialized.\n",
name);
return GDK_FAIL;
}
if (!(BATtordered(doc_pre) & 1))
{
GDKerror("%s: doc_pre must be ordered on tail.\n", name);
return GDK_FAIL;
}
/* --------------------------- empty result ---------------------------- */
if (BATcount(ctx_bat) == 0 || BATcount(pre_size) == 0 || BATcount(doc_pre)
== 0)
{
res = BATnew(TYPE_oid, TYPE_void, 0);
BATkey (res, TRUE);
res->hsorted = GDK_SORTED;
res->hdense = TRUE;
BATseqbase (res, (oid)0); /* does not really matter */
BATkey (BATmirror(res), TRUE);
res->tsorted = TRUE;
res->tdense = TRUE;
BATseqbase (BATmirror(res), (oid)0); /* does not really matter */
BATset(res, TRUE);
*result = res;
return GDK_SUCCEED;
}
/* --------------------------- special cases --------------------------- */
size = ((int*) BUNtloc(pre_size, BUNfirst(pre_size))) -
(int)pre_size->hseqbase;
if (BATtordered(iter_bat) & 1)
{
min_iter = *iter_cur;
max_iter = *(iter_end - iter_nxt);
} else {
oid *cur_iter = iter_cur;
min_iter = GDK_oid_max;
max_iter = GDK_oid_min;
for (; cur_iter < iter_end; cur_iter += iter_nxt) {
oid iter = *cur_iter;
if (iter < min_iter) min_iter = iter;
if (iter > max_iter) max_iter = iter;
}
}
assert(min_iter <= max_iter);
num_iter = (max_iter - min_iter) + 1;
ALGODEBUG
THRprintf(GDKout, "%s: min_iter="OIDFMT", max_iter="OIDFMT",
num_iter="OIDFMT"\n",
name, min_iter, max_iter, num_iter);
/* --- result bat allocation. for result size use res_size parameter --- */
res_size = num_iter * ((BATcount(pre_size) / 2) / BATcount(doc_pre));
res = BATnew(TYPE_oid, TYPE_oid, res_size);
if (res == NULL)
{
GDKerror("%s: could not allocate a result BAT of size "SZFMT".\n",
name, res_size);
return GDK_FAIL;
}
assert(BUNsize(res) == 2 * sizeof(oid));
assert((res->hloc == 0) && (res->tloc == sizeof(oid)));
res_cur = (oid*) BUNhead(res, BUNfirst(res));
@c
@:init(following)@
if (one_ctx) {
/* 1 ctx, 1/n iter */
p = SORTfndlast(doc_pre, ctx_cur);
if (p > BUNfirst(doc_pre)) {
oid boundary = *(oid*) BUNtail(doc_pre, p - BUNsize(doc_pre));
oid cur_following = *ctx_cur + size[*ctx_cur] + 1;
/* now, everything until the end of the fragment is a following
node */
boundary += size[boundary] + 1;
if (cur_following < boundary) {
/* check, if result buffer is big enough; otherwise extend it */
grow = num_iter * (boundary - cur_following);
PFll_check_BAT_capacity(res, grow);
if (num_iter == 1) {
ALGODEBUG THRprintf(GDKout, "%s: 1 ctx, 1 iter\n", name);
while(cur_following < boundary) {
int sz = size[cur_following];
if (sz >= 0) {
*res_cur++ = min_iter;
*res_cur++ = cur_following++;
} else {
/* this node has been deleted! skip the hole */
cur_following += 1 + (sz & ~(1<<31));
}
}
} else {
/* num_iter > 1 */
if (iter_bat->tkey) {
ALGODEBUG THRprintf(GDKout, "%s: 1 ctx, n iter
(key)\n", name);
while(cur_following < boundary) {
int sz = size[cur_following];
if (sz >= 0) {
oid *cur_iter = iter_cur;
for (; cur_iter < iter_end; cur_iter +=
iter_nxt) {
*res_cur++ = *cur_iter;
*res_cur++ = cur_following;
}
cur_following++;
} else {
/* this node has been deleted! skip the hole */
cur_following += 1 + (sz & ~(1<<31));
}
}
} else {
/* !iter_bat->tkey */
ALGODEBUG THRprintf(GDKout, "%s: 1 ctx, n iter\n",
name);
while(cur_following < boundary) {
int sz = size[cur_following];
if (sz >= 0) {
oid *cur_iter = iter_cur;
oid prev_iter = oid_nil;
for (; cur_iter < iter_end; cur_iter +=
iter_nxt) {
if (*cur_iter != prev_iter) {
*res_cur++ = *cur_iter;
*res_cur++ = cur_following;
prev_iter = *cur_iter;
}
}
cur_following++;
} else {
/* this node has been deleted! skip the hole */
cur_following += 1 + (sz & ~(1<<31));
}
}
}
}
/* mark the end point of the BUNs section in the BUNheap */
res->batBuns->free = ((BUN)res_cur) - res->batBuns->base;
BATsetcount(res,
(res->batBuns->free+Bunbase(res)-BUNfirst(res))/BUNsize(res));
}
}
} else
if (num_iter == 1) {
/* n ctx, 1 iter */
ALGODEBUG THRprintf(GDKout, "%s: n ctx, 1 iter\n", name);
BATloopFast(doc_pre, p, q, xx) {
oid boundary = *(oid*) BUNtail(doc_pre,p);
oid cur_following = boundary += size[boundary] + 1;
/* within the fragment (boundary), go over all context nodes */
while(ctx_cur < ctx_end && *ctx_cur < cur_following /*<=
boundary*/) {
/* new following is the first following node of the current
context node */
oid new_following = *ctx_cur + size[*ctx_cur] + 1;
if (new_following < cur_following) {
cur_following = new_following; /* keep setting
cur_following back */
}
ctx_cur += ctx_nxt;
}
while(ctx_cur < ctx_end && *ctx_cur < boundary) {
ctx_cur += ctx_nxt; /* advance ctx pointer after breaking out
early */
}
if (cur_following < boundary) {
/* now, everything until the end of the fragment is a following
node */
/* check, if result buffer is big enough; otherwise extend it */
grow = boundary - cur_following;
PFll_check_BAT_capacity(res, grow);
while(cur_following < boundary) {
int sz = size[cur_following];
if (sz >= 0) {
*res_cur++ = min_iter;
*res_cur++ = cur_following++;
} else {
/* this node has been deleted! skip the hole */
cur_following += 1 + (sz & ~(1<<31));
}
}
/* mark the end point of the BUNs section in the BUNheap */
res->batBuns->free = ((BUN)res_cur) - res->batBuns->base;
BATsetcount(res,
(res->batBuns->free+Bunbase(res)-BUNfirst(res))/BUNsize(res));
}
}
} else
{
/* n ctx, n iter */
ALGODEBUG THRprintf(GDKout, "%s: n ctx, n iter\n", name);
oid *min_following = GDKmalloc(num_iter * sizeof(oid));
if (min_following == NULL)
{
GDKerror("%s: could not allocate a stack of size "SZFMT".\n", name,
(size_t)num_iter * sizeof(oid));
BBPreclaim(res);
return GDK_FAIL;
}
BATloopFast(doc_pre, p, q, xx) {
oid iter = 0, fst_iter = num_iter, lst_iter = 0;
oid boundary = *(oid*) BUNtail(doc_pre,p);
oid cur_following = boundary += size[boundary] + 1;
for (; iter < num_iter; iter++) {
min_following[iter] = cur_following;
}
/* within the fragment (boundary), go over all context nodes */
while(ctx_cur < ctx_end && *ctx_cur < /*cur_following <=*/
boundary) {
/* new following is the first following node of the current
context node */
oid new_following = *ctx_cur + size[*ctx_cur] + 1;
oid prev_ctx = *ctx_cur;
if (new_following < cur_following) {
cur_following = new_following; /* keep setting
cur_following back */
}
while(ctx_cur < ctx_end && *ctx_cur == prev_ctx) {
iter = *iter_cur - min_iter;
if (new_following < min_following[iter]) {
min_following[iter] = new_following;
if (iter < fst_iter) fst_iter = iter;
if (iter > lst_iter) lst_iter = iter;
}
ctx_cur += ctx_nxt;
iter_cur += iter_nxt;
}
}
@(
while(ctx_cur < ctx_end && *ctx_cur < boundary) {
ctx_cur += ctx_nxt; /* advance ctx pointer after breaking out
early */
iter_cur += iter_nxt;
}
@)
if (cur_following < boundary && fst_iter <= lst_iter) {
/* now, everything until the end of the fragment is a following
node */
/* check, if result buffer is big enough; otherwise extend it */
grow = ((lst_iter - fst_iter) + 1) * (boundary - cur_following);
PFll_check_BAT_capacity(res, grow);
while(cur_following < boundary) {
int sz = size[cur_following];
if (sz >= 0) {
for (iter = fst_iter; iter <= lst_iter; iter++) {
if (min_following[iter] <= cur_following) {
*res_cur++ = iter + min_iter;
*res_cur++ = cur_following;
}
}
cur_following++;
} else {
/* this node has been deleted! skip the hole */
cur_following += 1 + (sz & ~(1<<31));
}
}
/* mark the end point of the BUNs section in the BUNheap */
res->batBuns->free = ((BUN)res_cur) - res->batBuns->base;
BATsetcount(res,
(res->batBuns->free+Bunbase(res)-BUNfirst(res))/BUNsize(res));
}
}
GDKfree(min_following);
}
@= end
/* -------------------- set result properties ---------------------- */
{
bit trivial = (BATcount(res) < 2);
oid fst_item = *(oid*)BUNtail(res, BUNfirst(res));
oid lst_item = *(oid*)BUNtail(res, BUNlast(res) - BUNsize(res));
bit one_item = (fst_item == lst_item);
bit one_iter = (num_iter == 1);
res->batDirty = TRUE;
res->hdense = (trivial||(res->htype==TYPE_void)); /* might be TRUE in some
more cases... */
if (res->hdense) {
if (BATcount(res) == 0) {
BATseqbase (res, (oid)0); /* does not really matter */
} else {
BATseqbase (res, *(oid*)BUNhead(res, BUNfirst(res)));
}
}
res->hsorted = ((one_iter||one_item) ? GDK_SORTED : 0); /* might be TRUE in
some more cases... */
BATkey(res,(res->hdense||one_item)); /* might be TRUE in some more cases...
*/
res->tdense = (trivial||(res->ttype==TYPE_void)); /* might be TRUE in some
more cases... */
if (res->tdense) {
if (BATcount(res) == 0) {
BATseqbase (BATmirror(res), (oid)0); /* does not really matter */
} else {
BATseqbase (BATmirror(res), *(oid*)BUNtail(res, BUNfirst(res)));
}
}
res->tsorted = GDK_SORTED;
BATkey(BATmirror(res),(res->tdense||one_iter)); /* might be TRUE in some
more cases... */
BATset(res, TRUE);
}
*result = res;
return GDK_SUCCEED;
@c
@:end@
}
@(
/* PRECEDING STEP */
int
PFpreceding_void(BAT **result, BAT *pre_size, BAT *ctx, BAT *doc_pre, int
*upperbound)
{
@:init(preceding)@
BATloopFast(doc_pre, p, q, xx) {
oid cur_preceding = *(oid*) BUNtail(doc_pre,p); /* first node of the
fragment */
oid boundary = cur_preceding + size[cur_preceding] + 1; /* first of
next fragment */
oid *ctx_start = ctx_cur;
/* within the fragment (boundary), go over all context nodes; and
remember the last one */
while(ctx_cur < ctx_end && *ctx_cur < boundary) {
ctx_cur += ctx_nxt;
}
if (ctx_start < ctx_cur) {
oid ctx_last = ctx_cur[-ctx_nxt]; /* the last context node in this
fragment */
/* cur_preceding is before ctx_last, so it contains its preceding
*and* ancestor nodes */
while(cur_preceding < ctx_last) {
oid new_preceding = cur_preceding + 1 + size[cur_preceding];
if (new_preceding > ctx_last) {
cur_preceding++; /* skip ancestor */
} else {
/* cur_preceding and its descendants are not ancestors, so
they must be preceding
* but: beware of holes!
*/
while(cur_preceding < new_preceding) {
while(cur_preceding < new_preceding &&
size[cur_preceding] >= 0) {
*res_cur++ = cur_preceding++;
}
if (cur_preceding < new_preceding) {
/* we hit a deleted node: skip hole */
cur_preceding = 1 + (size[cur_preceding] &
~(1<<31));
}
}
}
}
}
}
@:end@
}
@)
@c
/* vim:set shiftwidth=4 expandtab: */
Index: pf_support.mx
===================================================================
RCS file: /cvsroot/monetdb/pathfinder/runtime/pf_support.mx,v
retrieving revision 1.226
retrieving revision 1.227
diff -u -d -r1.226 -r1.227
--- pf_support.mx 13 May 2007 11:40:15 -0000 1.226
+++ pf_support.mx 14 May 2007 09:55:29 -0000 1.227
@@ -269,6 +269,24 @@
DESCRIPTION
axis step evaluation on the @1 axis from the given context."
@m
+@(
+@:ll_prec_foll_decl(following)@
+@:ll_prec_foll_decl(preceding)@
+@)
+
[EMAIL PROTECTED] ll_prec_foll_decl
+.COMMAND [EMAIL PROTECTED](BAT[oid,oid] iter,
+ BAT[oid,oid] ctx,
+ BAT[oid,int] pre_size,
+ BAT[oid,oid] doc_pre): BAT[oid,oid] = [EMAIL PROTECTED];
+"PARAMETERS:
+BAT[void,oid] iter (grouping relation; sorted on tail within each ctx group)
+BAT[void,oid] ctx (context set; sorted on tail)
+BAT[void,int] pre_size (from the working set)
+BAT[void,oid] table of document containers (doc id, preorder start value)
+DESCRIPTION:
+returns all nodes on the @2 axis of the ctx-nodes duplicate free for each
group."
[EMAIL PROTECTED]
@:scj_cmd(descorself,descendant-or-self)@
@:scj_cmd(desc,descendant)@
@:scj_cmd(ancorself,ancestor-or-self)@
@@ -1416,6 +1434,11 @@
@:step(following,following,following_void,,@:sizes_code@,
@:foll_prec_code@,@:doc_pre@)@
@:step(preceding,preceding,preceding_void,,@:sizes_code@,
@:foll_prec_code@,@:doc_pre@)@
+@(
+@:ll_prec_foll_impl(following)@
+@:ll_prec_foll_impl(preceding)@
+@)
+
@= chk_order
if ( and(order,1) = @2 ) {
@3 := @3.chk_order(); # just in case...
@@ -1553,6 +1576,25 @@
.access(BAT_READ);
}
+ @:post_sort_output@
+
+ return result;
+}
+ADDHELP("@1", "tsheyar", "Sep 2004",
+"PARAMETERS:\n\
+BAT[void,oid] iter (grouping relation)\n\
+BAT[void,oid] item (context set)\n\
+oid cont (the current container of the ws)\n\
+BAT[void,bat] ws (working set)\n\
+int order (input & output order properties:\n\
+ bit 0: input is sorted on iter(0) or item(1)\n\
+ bit 1: output must be sorted on iter(0) or item(1))\n\
+BAT[oid,oid] cands (sorted list of result candidate OIDs in the tail)\n\
+DESCRIPTION:\n\
+returns all nodes on the @1 axis of the ctx-nodes duplicate free for each
group.",
+"pf_support");
+@
[EMAIL PROTECTED] post_sort_output
# post-sort output
if ( (and(order,2) = 2) and not(ordered(reverse(result.fetch(1)))) ) {
iter := result.fetch(0);
@@ -1576,22 +1618,6 @@
.append(ord.leftfetchjoin(item).chk_order())
.access(BAT_READ);
}
-
- return result;
-}
-ADDHELP("@1", "tsheyar", "Sep 2004",
-"PARAMETERS:\n\
-BAT[void,oid] iter (grouping relation)\n\
-BAT[void,oid] item (context set)\n\
-oid cont (the current container of the ws)\n\
-BAT[void,bat] ws (working set)\n\
-int order (input & output order properties:\n\
- bit 0: input is sorted on iter(0) or item(1)\n\
- bit 1: output must be sorted on iter(0) or item(1))\n\
-BAT[oid,oid] cands (sorted list of result candidate OIDs in the tail)\n\
-DESCRIPTION:\n\
-returns all nodes on the @1 axis of the ctx-nodes duplicate free for each
group.",
-"pf_support");
@
# use size concept
@= sizes_code
@@ -1609,7 +1635,7 @@
# find the document root-pre's for prec_foll
var nid_rid := ws.fetch(NID_RID).fetch(cont);
var map_pid := ws.fetch(MAP_PID).fetch(cont);
- var doc_pre := ws.fetch(FRAG_ROOT).fetch(cont).tmark([EMAIL
PROTECTED]).leftfetchjoin(nid_rid).[swizzle](map_pid);
+ var doc_pre := ws.fetch(FRAG_ROOT).fetch(cont).tmark([EMAIL
PROTECTED]).leftfetchjoin(nid_rid).[swizzle](map_pid).chk_order();
@
@= doc_pre
doc_pre,
@@ -1683,6 +1709,21 @@
}
@
[EMAIL PROTECTED] ll_prec_foll_impl
+PROC @1(BAT[void,oid] iter, BAT[void,oid] item, oid cont, BAT[void,bat] ws,
int order) : BAT[void,bat]
+{
+ # "order" is not (yet?) used, here.
+ var pre_sizes := ws.fetch(PRE_SIZE).fetch(cont);
+ @:foll_prec_code@
+ var res := [EMAIL PROTECTED](iter.chk_order(), item.chk_order(),
pre_sizes, doc_pre);
+ var result := new(void,bat,2).seqbase([EMAIL
PROTECTED]).append(hmark(res,[EMAIL PROTECTED])).append(tmark(res,[EMAIL
PROTECTED])).access(BAT_READ);
+
+ @:post_sort_output@
+
+ return result;
+}
+@
+
@mil
@:loop_lifted_scj_step1(ancestor)@
@:loop_lifted_scj_step1(ancestor_or_self)@
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Monetdb-pf-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/monetdb-pf-checkins