Changeset: 2b0a6451e0d6 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=2b0a6451e0d6
Modified Files:
sql/common/sql_hash.c
sql/include/sql_hash.h
sql/server/rel_exp.c
sql/server/rel_graph.c
sql/server/rel_graph.h
sql/server/rel_optimizer.c
sql/server/rel_rel.c
sql/server/rel_rel.h
Branch: graph0
Log Message:
QRW: join reordering (WIP)
Still need to ensure that join predicates are not moved upward
when they depend on a graph operator
diffs (truncated from 507 to 300 lines):
diff --git a/sql/common/sql_hash.c b/sql/common/sql_hash.c
--- a/sql/common/sql_hash.c
+++ b/sql/common/sql_hash.c
@@ -5,6 +5,8 @@
*
* Copyright 1997 - July 2008 CWI, August 2008 - 2017 MonetDB B.V.
*/
+#include <inttypes.h> // uint64_t
+#include <stdlib.h> // rand
#include "monetdb_config.h"
#include "sql_mem.h"
@@ -81,3 +83,18 @@ hash_key(const char *k)
h += (h << 15);
return h;
}
+
+//unsigned int
+//hash_key_ptr(void* ptr)
+//{
+// static uint64_t a = 0;
+// static uint64_t b = 0;
+// const uint64_t p = 2386660291; // prime number
+// if(a == 0 && b == 0){
+// srand(time(NULL));
+// a = rand() +1;
+// b = rand() +1;
+// }
+//
+// return (unsigned int) (( a * ((uint64_t) ptr) + b ) % p);
+//}
diff --git a/sql/include/sql_hash.h b/sql/include/sql_hash.h
--- a/sql/include/sql_hash.h
+++ b/sql/include/sql_hash.h
@@ -37,5 +37,6 @@ extern sql_hash_e *hash_add(sql_hash *ht
extern void hash_del(sql_hash *ht, int key, void *value);
extern unsigned int hash_key(const char *n);
+//extern unsigned int hash_key_ptr(void* pointer);
#endif /* SQL_STACK_H */
diff --git a/sql/server/rel_exp.c b/sql/server/rel_exp.c
--- a/sql/server/rel_exp.c
+++ b/sql/server/rel_exp.c
@@ -1262,7 +1262,6 @@ rel_find_exp( sql_rel *rel, sql_exp *e)
case op_full:
case op_join:
case op_apply:
- case op_graph_join:
ne = rel_find_exp(rel->l, e);
if (!ne)
ne = rel_find_exp(rel->r, e);
@@ -1287,6 +1286,20 @@ rel_find_exp( sql_rel *rel, sql_exp *e)
if (rel->exps && e->type == e_column && e->l)
ne = exps_bind_column2(rel->exps, e->l, e->r);
break;
+ case op_graph_join:
+ case op_graph_select: {
+ assert(ne == NULL && "Expression already assigned?");
+ // check whether this is some kind of shortest path
+ if(e->type == e_column){
+ sql_graph* graph_ptr = (sql_graph*) rel;
+ ne = exps_bind_column2(graph_ptr->spfw, e->l,
e->r);
+ }
+
+ // try with the lhs
+ if(!ne) { ne = rel_find_exp(rel->l, e); }
+ // and then with the rhs (ok for selects as well)
+ if(!ne) { ne = rel_find_exp(rel->r, e); }
+ } break;
default:
if (!is_project(rel->op) && rel->l)
ne = rel_find_exp(rel->l, e);
diff --git a/sql/server/rel_graph.c b/sql/server/rel_graph.c
--- a/sql/server/rel_graph.c
+++ b/sql/server/rel_graph.c
@@ -15,8 +15,51 @@
#include "rel_exp.h"
#include "rel_rel.h"
#include "rel_select.h"
+#include "sql_mem.h" // sql_ref_init
#include "sql_relation.h" // rel_graph
+/*****************************************************************************
+ * *
+ * Create the graph operator *
+ * *
+ *****************************************************************************/
+
+sql_graph* rel_graph_create(sql_allocator *sa) {
+ sql_graph *r = SA_NEW(sa, sql_graph);
+ if(!r) return NULL;
+ memset(r, 0, sizeof(sql_graph));
+ sql_ref_init(&(r->relation.ref));
+ return r;
+}
+
+sql_graph* rel_graph_move(mvc* sql, sql_rel* rel, sql_rel* l, sql_rel* r,
sql_exp* e){
+ sql_graph* graph_old = NULL;
+ sql_graph* graph_new = NULL;
+ sql_rel* graph_rel = NULL;
+
+ assert(rel && is_graph(rel->op));
+ graph_old = (sql_graph*) rel;
+ graph_new = rel_graph_create(sql->sa);
+ if(!graph_new) return NULL;
+ memcpy(graph_new + sizeof(sql_ref), graph_old + sizeof(sql_ref),
sizeof(sql_graph) - sizeof(sql_ref));
+ graph_rel = &(graph_new->relation);
+ graph_rel->l = l;
+ graph_rel->r = r;
+ graph_rel->exps = new_exp_list(sql->sa);
+ list_append(graph_rel->exps, e);
+
+ return graph_new;
+}
+
+sql_rel* rel_graph_move2rel(mvc* sql, sql_rel* rel, sql_rel* l, sql_rel* r,
sql_exp* e){
+ return (sql_rel*) rel_graph_move(sql, rel, l, r, e);
+}
+
+/*****************************************************************************
+ * *
+ * Parse the REACHES clause *
+ * *
+ *****************************************************************************/
sql_rel* rel_graph_reaches(mvc *sql, sql_rel *rel, symbol *sq, int context){
// TODO handle edge components defined with multiple attributes
// this needs changes in the parser to accept list of columns & scalars
diff --git a/sql/server/rel_graph.h b/sql/server/rel_graph.h
--- a/sql/server/rel_graph.h
+++ b/sql/server/rel_graph.h
@@ -15,4 +15,8 @@
sql_rel* rel_graph_reaches(mvc *sql, sql_rel *rel, symbol *sq, int context);
sql_exp* rel_graph_cheapest_sum(mvc *sql, sql_rel **rel, symbol *sq, int
context);
+sql_graph* rel_graph_create(sql_allocator *sa);
+sql_graph* rel_graph_move(mvc* sql, sql_rel* graph_old, sql_rel* l, sql_rel*
r, sql_exp* e);
+sql_rel* rel_graph_move2rel(mvc* sql, sql_rel* graph_old, sql_rel* l, sql_rel*
r, sql_exp* e);
+
#endif /* _REL_GRAPH_H_ */
diff --git a/sql/server/rel_optimizer.c b/sql/server/rel_optimizer.c
--- a/sql/server/rel_optimizer.c
+++ b/sql/server/rel_optimizer.c
@@ -319,10 +319,21 @@ rel_properties(mvc *sql, global_props *g
static sql_rel * rel_join_order(mvc *sql, sql_rel *rel) ;
+// graph related stuff
+typedef struct {
+ sql_exp* join;
+ sql_rel* graph;
+} graph_association;
+
+static int
+graph_association_cmp(graph_association* a, sql_exp* e){
+ return (e == a->join) ? 0 : -1;
+}
+
static void
get_relations(mvc *sql, sql_rel *rel, list *rels)
{
- if (!rel_is_ref(rel) && rel->op == op_join && rel->exps == NULL) {
+ if (!rel_is_ref(rel) && (rel->op == op_join || rel->op ==
op_graph_join) && rel->exps == NULL) {
sql_rel *l = rel->l;
sql_rel *r = rel->r;
@@ -484,29 +495,54 @@ exp_joins_rels(sql_exp *e, list *rels)
{
sql_rel *l = NULL, *r = NULL;
- assert (e->type == e_cmp);
-
- if (e->flag == cmp_or) {
- l = NULL;
- } else if (get_cmp(e) == cmp_filter) {
+ switch(e->type){
+ case e_cmp:
+ if (e->flag == cmp_or) {
+ l = NULL;
+ } else if (get_cmp(e) == cmp_filter) {
+ list *ll = e->l;
+ list *lr = e->r;
+
+ l = find_rel(rels, ll->h->data);
+ r = find_rel(rels, lr->h->data);
+ } else if (e->flag == cmp_in || e->flag == cmp_notin) {
+ list *lr = e->r;
+
+ l = find_rel(rels, e->l);
+ if (lr && lr->h)
+ r = find_rel(rels, lr->h->data);
+ } else {
+ l = find_rel(rels, e->l);
+ r = find_rel(rels, e->r);
+ }
+
+ if (l && r)
+ return 0;
+ break;
+ case e_graph: {
+ // same as cmp_filter
list *ll = e->l;
list *lr = e->r;
-
- l = find_rel(rels, ll->h->data);
- r = find_rel(rels, lr->h->data);
- } else if (e->flag == cmp_in || e->flag == cmp_notin) {
- list *lr = e->r;
-
- l = find_rel(rels, e->l);
- if (lr && lr->h)
- r = find_rel(rels, lr->h->data);
- } else {
- l = find_rel(rels, e->l);
- r = find_rel(rels, e->r);
- }
-
- if (l && r)
+ assert(list_length(ll) >= 1 && list_length(lr) >= 1);
+
+ for(node *n = ll->h; n; n = n->next){
+ sql_rel* tmp = find_rel(rels, n->data);
+ if(tmp == NULL || (l != NULL && l != tmp)) return -1;
+ l = tmp;
+ }
+ for(node *n = lr->h; n; n = n->next){
+ sql_rel* tmp = find_rel(rels, n->data);
+ if(tmp == NULL || (r != NULL && r != tmp)) return -1;
+ r = tmp;
+ }
+
return 0;
+ } break;
+ default:
+ assert (0 && "Invalid expression type");
+ }
+
+
return -1;
}
@@ -794,8 +830,22 @@ find_fk( mvc *sql, list *rels, list *exp
return sdje;
}
+
static sql_rel *
-order_joins(mvc *sql, list *rels, list *exps)
+reset_graph_join(mvc *sql, list* graphs, sql_rel *l, sql_rel *r, sql_exp *e){
+ node* n = NULL;
+ sql_rel* graph = NULL;
+
+ n = list_find(graphs, e, (fcmp) graph_association_cmp);
+ assert(n != NULL);
+ graph = rel_graph_move2rel(sql, ((graph_association*) n->data)->graph,
l, r, e);
+ list_remove_node(graphs, n);
+
+ return graph;
+}
+
+static sql_rel *
+order_joins(mvc *sql, list *rels, list *exps, list *graphs)
{
sql_rel *top = NULL, *l = NULL, *r = NULL;
sql_exp *cje;
@@ -828,51 +878,74 @@ order_joins(mvc *sql, list *rels, list *
* */
if (cje->type != e_cmp || !is_complex_exp(cje->flag) ||
!find_prop(cje->p, PROP_HASHCOL) /*||
(cje->type == e_cmp && cje->f == NULL)*/) {
- l = find_one_rel(rels, cje->l);
- r = find_one_rel(rels, cje->r);
+ sql_exp *le, *re;
+ if(cje->type == e_graph){
+ assert(list_length(cje->l) == 1 &&
list_length(cje->r) == 1);
+ le = ((list*) cje->l)->h->data;
+ re = ((list*) cje->r)->h->data;
+ } else {
+ le = cje->l;
+ re = cje->r;
+ }
+
+ l = find_one_rel(rels, le);
+ r = find_one_rel(rels, re);
}
if (l && r && l != r) {
list_remove_data(sdje, cje);
list_remove_data(exps, cje);
- }
- }
- if (l && r && l != r) {
- list_remove_data(rels, l);
- list_remove_data(rels, r);
- list_append(n_rels, l);
- list_append(n_rels, r);
-
- /* Create a relation between l and r. Since the calling
- functions rewrote the join tree, into a list of expressions
- and a list of (simple) relations, there are no outer joins
- involved, we can simply do a crossproduct here.
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list