Update of /cvsroot/monetdb/pathfinder/compiler/algebra
In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv11729
Modified Files:
builtins.c core2alg.brg logical.c
Log Message:
undo XQuery Fulltext checkin in HEAD. Updates are now in XQFT branch
Index: core2alg.brg
===================================================================
RCS file: /cvsroot/monetdb/pathfinder/compiler/algebra/core2alg.brg,v
retrieving revision 1.92
retrieving revision 1.93
diff -u -d -r1.92 -r1.93
--- core2alg.brg 5 Nov 2009 16:23:57 -0000 1.92
+++ core2alg.brg 10 Nov 2009 09:45:09 -0000 1.93
@@ -172,9 +172,6 @@
/* Pathfinder extension: XRPC */
%term xrpc = 76 /**< XRPC calls: "execute at" */
- /* Associated For variable holders */
-%term vars = 77 /**< variable pair (position. var + score. var)
of a for */
-
%%
Query: main (FunctionDecls, CoreExpr) = 1 (10);
@@ -200,14 +197,6 @@
CoreExpr),
OptBindExpr) = 6 (10);
-/* Pathfinder full-text score var */
-OptBindExpr: for_ (forbind (forvars (var,
- vars (OptVar,
- OptVar)
- ),
- CoreExpr),
- OptBindExpr) = 109 (10);
-
OptVar: var = 200 (10);
OptVar: nil = 201 (10);
@@ -523,12 +512,6 @@
CoreExpr),
CoreExpr) */
case 6:
-
- /* OptBindExpr: for_ (forbind (forvars (var,
- vars (OptVar, OptVar)),
- CoreExpr),
- OptBindExpr) */
- case 109:
/* OptBindExpr: let (letbind (var, CoreExpr), CoreExpr) */
case 7:
@@ -960,8 +943,7 @@
}
A(p) = (struct PFla_pair_t) {
- .rel = project (rank (eqjoin (attach_score(
-
A(R(p)).rel),
+ .rel = project (rank (eqjoin (A(R(p)).rel,
MAP,
col_iter,
col_inner),
@@ -969,8 +951,7 @@
sortby),
proj (col_iter, col_outer),
proj (col_pos, col_pos1),
- proj (col_item, col_item),
- proj (col_score1, col_score1)),
+ proj (col_item, col_item)),
.frag = A(R(p)).frag };
}
} else
@@ -984,7 +965,7 @@
ENV = old_env;
} break;
-
+
/* OptBindExpr: for_ (forbind (forvars (var, OptVar),
CoreExpr),
OptBindExpr) */
@@ -1174,236 +1155,6 @@
/* compute result using old env and old loop. */
/* backmapping is now done in flwr
A(p) = (struct PFla_pair_t) {
- .rel = project (rownum (eqjoin(attach_score(
-
A(R(p)).rel),
- var_map,
- col_iter,
- col_inner),
- col_pos1,
- sortby (col_sort, col_pos),
- col_outer),
- proj (col_iter, col_outer),
- proj (col_pos, col_pos1),
- proj (col_item, col_item),
- proj (col_score1, col_score1)),
- .frag = A(R(p)).frag };
- */
- } break;
-
- /* OptBindExpr: for_ (forbind (forvars (var, vars (OptVar,
- OptVar)),
- CoreExpr),
- OptBindExpr) */
- case 109:
- { /* TOPDOWN */
-
- /*
- * for $v in e1 return e2 OR
- * for $v at $p in e1 return e2
- *
- * Given the current environment (which may or may not contain
- * bindings), the current loop relation and delta with e1
- * already compiled:
- * - declare variable $v by loop lifting the result of q1,
- *(- declare variable $p if present)
- * - create a new loop relation and
- * - a new var_map relation,
- * - as the for expression opens up a scope, update all existing
- * bindings to the new scope and add the binding of $v
- * Given the updated environment and the new loop relation
- * compile e2. Return the (possibly intermediate) result.
- *
- * env,loop: e1 => q1,delta1
- *
- * pos
- * q(v) = --- X proj_iter:inner,item(row_inner:<iter,pos> q1)
- * 1
- *
- * loop(v) = proj_iter(q(v))
- *
- * var_map = proj_outer:iter,inner(row_inner:<iter,pos> q1)
- *
- * updated_env,(v->q(v)) e updated_env,loop(v): e2 => (q2,delta2)
- *
-----------------------------------------------------------------
- * env,loop: for &v in e1 return e2 =>
- * (proj_iter:outer, pos:pos1,item
- * (row_pos1:<iter,pos>/outer (q2 |X| (iter = inner) var_map)),
- * delta2)
- */
- PFla_op_t *var;
- PFla_op_t *opt_var;
- PFla_op_t *opt_var1;
- PFla_op_t *var_map;
- PFla_op_t *rowid;
- unsigned int i;
- PFla_env_t e;
- PFla_op_t *new_map;
- /* save old environment */
- PFarray_t *old_env = ENV;
-
- /* initiate translation of e1 */
- reduce (ctx, kids[2], nts[2]);
-
- /*
- * Add 'real' positions and the new iter values.
- * (Note: We add the positions outside as some proxy rewrites
- * expect that no rownum can escape its 'scope'. The
- * result of the rownum operator is discarded in the
- * first icols optimization if no positional variable
- * exists.)
- */
- rowid = rowid (rownum (A(LR(p)).rel,
- col_pos1,
- sortby (col_pos),
- col_iter),
- col_inner);
-
- /* translate $v */
- var = attach (project (rowid,
- proj (col_iter, col_inner),
- proj (col_item, col_item)),
- col_pos, lit_nat (1));
-
- /* create new environment */
- ENV = PFarray (sizeof (PFla_env_t), 50);
-
- /* insert $v and "its document" into NEW environment */
- *((PFla_env_t *) PFarray_add (ENV))
- = enventry (LLL(p)->sem.var, var, NULL, A(LR(p)).frag);
-
- /* create new loop operator */
- LOOP = project (var, proj (col_iter, col_iter));
-
- /* create var_map relation. */
- var_map = project (rowid,
- proj (col_outer, col_iter),
- proj (col_sort, col_pos),
- proj (col_inner, col_inner));
-
- /*
- * Handle optional variable ($p).
- * (Note: The rownum () routine was used to create
- * the 'item' column of $p's operator. Since this
- * column must be of type integer instead of nat, we
- * cast it accordingly.)
- */
- if (LLRL(p)->kind == c_var) {
- assert (LLRL(p)->sem.var);
- opt_var = attach (project (cast (rowid,
- col_cast,
- col_pos1,
- aat_int),
- proj (col_iter, col_inner),
- proj (col_item, col_cast)),
- col_pos, lit_nat (1));
-
- /* insert $p into NEW environment */
- *((PFla_env_t *) PFarray_add (ENV)) =
- enventry (LLRL(p)->sem.var,
- opt_var,
- NULL,
- PFla_empty_set ());
- }
-
- /*
- * Handle optional variable ($s).
- * (Note: The rownum () routine was used to create
- * the 'item' column of $p's operator. Since this
- * column must be of type integer instead of nat, we
- * cast it accordingly.)
- */
- if (LLRR(p)->kind == c_var) {
- assert (LLRR(p)->sem.var);
- opt_var1 = project (A(LR(p)).rel,
- proj (col_pos, col_pos),
- proj (col_iter, col_iter),
- proj (col_item, col_score1),
- proj (col_score1, col_score1));
-
- /* insert $p into NEW environment */
- *((PFla_env_t *) PFarray_add (ENV)) =
- enventry (LLRR(p)->sem.var,
- opt_var1,
- NULL,
- PFla_empty_set ());
- }
-
- /* update all variable bindings in old environment and put
- * them into new environment */
- for (i = 0; i < PFarray_last (old_env); i++) {
- e = *((PFla_env_t *) PFarray_at (old_env, i));
-
- if (!e.map)
- new_map = project (var_map,
- proj (col_outer, col_outer),
- proj (col_inner, col_inner));
- else
- new_map = project (
- eqjoin (
- project (
- e.map,
- proj (col_iter, col_inner),
- proj (col_outer, col_outer)),
- project (
- var_map,
- proj (col_iter2, col_outer),
- proj (col_inner, col_inner)),
- col_iter,
- col_iter2),
- proj (col_outer, col_outer),
- proj (col_inner, col_inner));
-
- *((PFla_env_t *) PFarray_add (ENV)) =
- enventry (e.var, e.rel, new_map, e.frag);
- }
-
- if (!MAP) {
- /* create a first backmapping relation */
- MAP = var_map;
- MAP_COUNT = 3;
- } else {
- /* extend the backmapping relation map with
- * (a) position information of the for-loop input sequence and
- * (b) the current iteration values */
-
- MAP_COUNT++;
- PFalg_proj_t *cols = PFmalloc (MAP_COUNT *
- sizeof (PFalg_proj_t));
- /* column outer remains the same */
- cols[0].new = col_outer;
- cols[0].old = col_outer;
- /* column iter1 becomes the new inner column */
- cols[1].new = col_inner;
- cols[1].old = col_iter1;
- /* copy all old sort columns */
- for (unsigned i = 2; i < MAP_COUNT - 1; i++)
- cols[i].new =
- cols[i].old = col_sort << (i - 2);
- /* we now have on additional sort column generated
- from column pos */
- /* the first sort criterion is column sort itself */
- cols[MAP_COUNT -1].new = col_sort << (MAP_COUNT - 3);
- cols[MAP_COUNT -1].old = col_pos;
-
- MAP = PFla_project_ (
- eqjoin (MAP,
- project (rowid,
- proj (col_iter1, col_inner),
- proj (col_iter, col_iter),
- proj (col_pos, col_pos)),
- col_inner,
- col_iter),
- MAP_COUNT, cols);
- }
-
- /* translate e2 under the specified conditions (updated
- * environment, loop(v))
- */
- reduce (ctx, kids[3], nts[3]);
-
- /* compute result using old env and old loop. */
- /* backmapping is now done in flwr
- A(p) = (struct PFla_pair_t) {
.rel = project (rownum (eqjoin(A(R(p)).rel,
var_map,
col_iter,
@@ -1912,7 +1663,7 @@
*else_res;
/* initiate translation of e1 */
- reduce (ctx, kids[0], nts[0]);
+ reduce (ctx, kids[0], nts[0]);
/* save old loop operator */
old_loop = LOOP;
@@ -1923,10 +1674,9 @@
/* create new loop operator */
LOOP = project (rowid, proj (col_iter, col_inner));
/* create var_map relation. */
- var_map = project (attach_score(rowid),
+ var_map = project (rowid,
proj (col_outer, col_iter),
- proj (col_inner, col_inner),
- proj (col_score1, col_score1));
+ proj (col_inner, col_inner));
/* store the variable map to retrieve the old iter values */
then_map = var_map;
@@ -1975,10 +1725,9 @@
/* create new loop operator */
LOOP = project (rowid, proj (col_iter, col_inner));
/* create var_map relation. */
- var_map = project (attach_score(rowid),
+ var_map = project (rowid,
proj (col_outer, col_iter),
- proj (col_inner, col_inner),
- proj (col_score1, col_score1));
+ proj (col_inner, col_inner));
/* store the variable map to retrieve the old iter values */
else_map = var_map;
@@ -2023,29 +1772,17 @@
/* merge back the old iter values */
then_res = project (
- eqjoin (
- project (A(RL(p)).rel,
- proj (col_iter, col_iter),
- proj (col_pos, col_pos),
- proj (col_item, col_item)),
- then_map, col_iter, col_inner),
+ eqjoin (A(RL(p)).rel, then_map, col_iter,
col_inner),
proj (col_iter, col_outer),
proj (col_pos, col_pos),
- proj (col_item, col_item),
- proj (col_score1, col_score1));
+ proj (col_item, col_item));
/* merge back the old iter values */
else_res = project (
- eqjoin (
- project (A(RR(p)).rel,
- proj (col_iter, col_iter),
- proj (col_pos, col_pos),
- proj (col_item, col_item)),
- else_map, col_iter, col_inner),
+ eqjoin (A(RR(p)).rel, else_map, col_iter,
col_inner),
proj (col_iter, col_outer),
proj (col_pos, col_pos),
- proj (col_item, col_item),
- proj (col_score1, col_score1));
+ proj (col_item, col_item));
A(p) = (struct PFla_pair_t) {
.rel = disjunion (then_res, else_res),
@@ -2800,10 +2537,6 @@
/**
* Translation of fn:trace ()
*/
- /* if (! PFqname_eq (p->sem.fun->qname,
- PFqname (PFns_fn, "boolean")))
- PFoops (OOPS_FATAL,
- "Function Name: %s", PFqname_str (p->sem.fun->qname));*/
if (! PFqname_eq (p->sem.fun->qname,
PFqname (PFns_fn, "trace"))) {
/* For fn:trace we need to introduce for each map relation
@@ -3386,11 +3119,6 @@
/* OptBindExpr: for_ (forbind (forvars (var, nil),
CoreExpr), CoreExpr) */
case 6:
- /* OptBindExpr: for_ (forbind (forvars (var,
- vars (OptVar, OptVar)),
- CoreExpr),
- OptBindExpr) */
- case 109:
/* OptBindExpr: let (letbind (var, CoreExpr), CoreExpr) */
case 7:
/* OptBindExpr: nil */
Index: logical.c
===================================================================
RCS file: /cvsroot/monetdb/pathfinder/compiler/algebra/logical.c,v
retrieving revision 1.129
retrieving revision 1.130
diff -u -d -r1.129 -r1.130
--- logical.c 5 Nov 2009 16:23:58 -0000 1.129
+++ logical.c 10 Nov 2009 09:45:09 -0000 1.130
@@ -605,7 +605,7 @@
/* indicate what kind of internal operator we are working on */
ret->sem.eqjoin_opt.kind = la_cross;
-
+
/* copy schema from argument 2, check for duplicate column names
and discard if present */
for (j = 0; j < n2->schema.count; j++) {
@@ -800,7 +800,7 @@
i--;
}
}
-
+
/* copy schema from projection list 'rproj' */
/* discard join columns - they are already added */
for (i = 1; i < PFarray_last (rproj); i++) {
@@ -1241,34 +1241,17 @@
kind == la_difference);
/* see if both operands have same number of columns */
- if (n1->schema.count != n2->schema.count){
- if(n1->schema.count > n2->schema.count)
- for(i=0; i< n1->schema.count; i++){
- if(n1->schema.items[i].name == col_score1){
- return set_operator (kind, n1, attach(n2, col_score1,
lit_dbl(1)));
- }
- } else
- for(i=0; i< n2->schema.count; i++){
- if(n2->schema.items[i].name == col_score1){
- return set_operator (kind, attach(n1, col_score1,
lit_dbl(1)), n2);
- }
- }
-
- if (n1->schema.count != n2->schema.count)
- PFoops (OOPS_FATAL,
- "Schema of two arguments of set operation (%s) "
- "do not match. (%i #cols != %i #cols)",
- kind == la_disjunion
- ? "union"
- : kind == la_intersect
- ? "intersect"
- : "difference",
- n1->schema.count,
- n2->schema.count);
-
- }
-
-
+ if (n1->schema.count != n2->schema.count)
+ PFoops (OOPS_FATAL,
+ "Schema of two arguments of set operation (%s) "
+ "do not match. (%i #cols != %i #cols)",
+ kind == la_disjunion
+ ? "union"
+ : kind == la_intersect
+ ? "intersect"
+ : "difference",
+ n1->schema.count,
+ n2->schema.count);
/* allocate memory for the result schema */
ret->schema.count = n1->schema.count;
@@ -4589,27 +4572,4 @@
return n; /* satisfy picky compilers */
}
-/** Check if score colomn exists if not then
- * add score coloumn
- */
-PFla_op_t *
-attach_score (PFla_op_t *n){
-
-
- unsigned int i;
-
- for (i = 0; i < n->schema.count; i++) {
- /* check if there's a coloumn named col_score1 */
- if (n->schema.items[i].name == col_score1)
- break;
- }
-
- if(i >= n->schema.count){
- return attach(n, col_score1, lit_dbl(1));
- } else {
- return n;
- }
-
-}
-
/* vim:set shiftwidth=4 expandtab: */
Index: builtins.c
===================================================================
RCS file: /cvsroot/monetdb/pathfinder/compiler/algebra/builtins.c,v
retrieving revision 1.131
retrieving revision 1.132
diff -u -d -r1.131 -r1.132
--- builtins.c 5 Nov 2009 16:23:57 -0000 1.131
+++ builtins.c 10 Nov 2009 09:45:09 -0000 1.132
@@ -370,9 +370,9 @@
/* 2.1. fn:node-name */
/* ----------------- */
-/* The fn:node-name function returns an expanded for
+/* The fn:node-name function returns an expanded for
* node kinds that can have names.
- * Among them obviously elements and attributes.
+ * Among them obviously elements and attributes.
*/
static struct PFla_pair_t
@@ -430,15 +430,15 @@
struct PFla_pair_t *args)
{
(void) loop; (void) ordering; (void) side_effects;
-
+
PFla_op_t *attributes = NULL;
PFalg_step_spec_t self_attr_spec;
self_attr_spec.axis = alg_self;
self_attr_spec.kind = node_kind_attr;
-
+
/* just find every attribute */
- self_attr_spec.qname = PFqname (PFns_wild, NULL);
-
+ self_attr_spec.qname = PFqname (PFns_wild, NULL);
+
attributes = attach (
project (
PFla_step_join_simple (
@@ -466,27 +466,28 @@
struct PFla_pair_t *args)
{
(void) loop; (void) ordering; (void) side_effects;
-
+
PFla_op_t *elements = NULL;
PFalg_step_spec_t self_elem_spec;
self_elem_spec.axis = alg_self;
- self_elem_spec.kind = node_kind_elem;
-
+ self_elem_spec.kind = node_kind_elem;
+
/* just find every element */
self_elem_spec.qname = PFqname (PFns_wild, NULL);
-
+
elements = attach (
-
- PFla_step_simple (
- PFla_set_to_la (args[0].frag),
- project (args[0].rel,
- proj (col_iter, col_iter),
- proj (col_item, col_item)),
- self_elem_spec,
- col_iter, col_item, col_item),
- col_pos, lit_int(1));
-
-
+ project (
+ PFla_step_join_simple (
+ PFla_set_to_la (args[0].frag),
+ project (args[0].rel,
+ proj (col_iter, col_iter),
+ proj (col_item, col_item)),
+ self_elem_spec,
+ col_item, col_res),
+ proj (col_iter, col_iter),
+ proj (col_item, col_res)),
+ col_pos, lit_int(1));
+
return (struct PFla_pair_t) {
.rel = elements,
.frag = args[0].frag
@@ -508,7 +509,7 @@
ordering,
side_effects,
args).rel);
-
+
return (struct PFla_pair_t) {
.rel = union_,
.frag = args[0].frag
@@ -527,7 +528,7 @@
}
/* node-name for elements */
-struct PFla_pair_t
+struct PFla_pair_t
PFfn_bui_node_name_elem (const PFla_op_t *loop,
bool ordering,
PFla_op_t **side_effects,
@@ -2386,7 +2387,7 @@
/**
* Algebra implementation for
* geoxml:intersection(xs:string, xs:string) : xs:string </code>
- * stolen from fn:concat
+ * stolen from fn:concat
*/
struct PFla_pair_t
PFbui_geoxml_intersection (const PFla_op_t *loop,
@@ -4255,12 +4256,12 @@
PFla_op_t *node_scj,
*sel;
PFalg_step_spec_t anc_node_spec;
-
+
anc_node_spec.axis = alg_anc_s;
anc_node_spec.kind = node_kind_node;
/* missing QName */
anc_node_spec.qname = PFqname (PFns_wild, NULL);
-
+
/* do an ancestor-or-self::node() step
with exact position values */
node_scj = rownum (
@@ -4276,7 +4277,7 @@
proj (col_iter, col_iter),
proj (col_item, col_res))),
col_pos, sortby (col_item), col_iter);
-
+
/* select the first ancestor */
sel = project (
select_ (
@@ -4289,7 +4290,7 @@
col_res),
proj (col_iter, col_iter),
proj (col_item, col_item));
-
+
/* add the position values */
return (struct PFla_pair_t) {
.rel = attach (sel, col_pos, lit_nat (1)),
@@ -4348,19 +4349,9 @@
{
if (PFprop_type_of (args[0].rel, col_item) != aat_bln)
return PFbui_fn_boolean_item (loop, ordering, side_effects, args);
- else{
-
- unsigned int i = 0;
- int scoreFlag = 0;
- for(i=0; i< args[0].rel->schema.count; i++)
- if(args[0].rel->schema.items[i].name == col_score1 ||
- args[0].rel->schema.items[i].name ==
col_score2){
- scoreFlag = 1;
- break;
- }
- if(scoreFlag == 0)
- return (struct PFla_pair_t) {
- .rel = disjunion (
+ else
+ return (struct PFla_pair_t) {
+ .rel = disjunion (
args[0].rel,
attach (
attach (
@@ -4371,24 +4362,7 @@
proj (col_iter, col_iter))),
col_pos, lit_nat (1)),
col_item, lit_bln (false))),
- .frag = PFla_empty_set () };
- else
- return (struct PFla_pair_t) {
- .rel = disjunion (
- args[0].rel,
- attach(
- attach (
- attach (
- difference (
- loop,
- project (
- args[0].rel,
- proj (col_iter,
col_iter))),
- col_pos, lit_nat
(1)),
- col_item, lit_bln (false)),
- args[0].rel->schema.items[i].name,
lit_nat(0))),
- .frag = PFla_empty_set () };
- }
+ .frag = PFla_empty_set () };
}
/**
@@ -5912,11 +5886,9 @@
struct PFla_pair_t *args)
{
PFla_op_t *distinct = distinct (
- project ( attach_score(
-
args[0].rel),
+ project (args[0].rel,
proj (col_iter, col_iter),
- proj (col_item, col_item),
- proj (col_score1, col_score1)));
+ proj (col_item, col_item)));
(void) loop; (void) side_effects;
@@ -6533,7 +6505,7 @@
/**
* Build in function fn:put(node, xs:string) as empty-sequence()
*/
-struct PFla_pair_t
+struct PFla_pair_t
PFbui_fn_put (const PFla_op_t *loop,
bool ordering,
PFla_op_t **side_effects,
@@ -6549,7 +6521,7 @@
/**
* Build in function pf:documents() as element()*
*/
-struct PFla_pair_t
+struct PFla_pair_t
PFbui_pf_documents (const PFla_op_t *loop,
bool ordering,
PFla_op_t **side_effects,
@@ -6895,7 +6867,7 @@
.rel = fun_param(
p1->rel,
nil(),
- ipi_schema(itemType)),
+ ipi_schema(itemType)),
.frag = PFla_empty_set () };
}
@@ -6909,8 +6881,8 @@
fun_param(
p2->rel,
nil(),
- ipi_schema(itemType2)),
- ipi_schema(itemType1)),
+ ipi_schema(itemType2)),
+ ipi_schema(itemType1)),
.frag = PFla_empty_set () };
}
@@ -6927,9 +6899,9 @@
fun_param(
p3->rel,
nil(),
- ipi_schema(itemType3)),
- ipi_schema(itemType2)),
- ipi_schema(itemType1)),
+ ipi_schema(itemType3)),
+ ipi_schema(itemType2)),
+ ipi_schema(itemType1)),
.frag = PFla_empty_set () };
}
@@ -6951,7 +6923,7 @@
.rel = fun_call(
loop,
p_fun_param.rel,
- ((PFT_FUN_FTFUN(query_name)) ?
+ ((PFT_FUN_FTFUN(query_name)) ?
ipis_schema(funcall_t) : ipi_schema(funcall_t) ),
alg_fun_call_tijah,
PFqname (PFns_wild, query_name),
@@ -7956,34 +7928,4 @@
.frag = args[0].frag };
}
-
-#ifdef HAVE_PFTIJAH
-
-struct PFla_pair_t PFbui_op_fts_str (const PFla_op_t *loop,
- bool ordering,
- PFla_op_t **side_effects,
- struct PFla_pair_t *args)
-{
- return bin_comp (aat_str, PFla_eq, loop, ordering, side_effects, args);
-}
-
-struct PFla_pair_t PFbui_tijah_ftfun_score(const PFla_op_t *loop,
- bool ordering,
- PFla_op_t **side_effects,
- struct PFla_pair_t *args){
-
- (void) loop; (void) ordering; (void) side_effects;
-
- return (struct PFla_pair_t) {
- .rel = project (attach_score(args[0].rel),
- proj (col_pos, col_pos),
- proj (col_iter, col_iter),
- proj (col_item, col_score1),
- proj (col_score1, col_score1)),
- .frag = PFla_empty_set () };
-
-}
-
-#endif
-
/* vim:set shiftwidth=4 expandtab: */
------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now. http://p.sf.net/sfu/bobj-july
_______________________________________________
Monetdb-pf-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/monetdb-pf-checkins