LCOV - code coverage report
Current view: top level - sql/server - rel_multiset.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 50 50 100.0 %
Date: 2025-03-25 21:27:32 Functions: 5 5 100.0 %

          Line data    Source code
       1             : 
       2             : #include "monetdb_config.h"
       3             : #include "rel_multiset.h"
       4             : #include "rel_exp.h"
       5             : #include "rel_rel.h"
       6             : #include "rel_basetable.h"
       7             : #include "rel_updates.h"
       8             : #include "rel_rewriter.h"
       9             : 
      10             : /* TODO move into unnest code */
      11             : static bool
      12         183 : has_multiset(list *exps)
      13             : {
      14         183 :         bool needed = false;
      15         183 :         if (list_empty(exps))
      16             :                 return needed;
      17         731 :         for(node *n = exps->h; n && !needed; n = n->next) {
      18         548 :                 sql_exp *e = n->data;
      19         548 :                 sql_subtype *t = exp_subtype(e);
      20             : 
      21         548 :                 needed = (t && t->multiset);
      22         548 :                 if (!needed && t && t->type->composite && is_nested(e))
      23          23 :                         needed = has_multiset(e->f);
      24             :         }
      25             :         return needed;
      26             : }
      27             : 
      28             : static sql_rel *
      29         156 : ms_add_join_exps(visitor *v, sql_rel *rel, list *exps)
      30             : {
      31         156 :         if (list_empty(exps))
      32             :                 return rel;
      33         156 :         sql_rel *r = rel->r;
      34         156 :         prop *p = r->p;
      35         156 :         if (!p || p->kind != PROP_UNNEST)
      36             :                 return NULL;
      37         156 :         sql_exp *re = p->value.pval;
      38             : 
      39         496 :         for(node *n = exps->h; n; n = n->next) {
      40         407 :                 sql_exp *e = n->data;
      41         407 :                 sql_subtype *t = exp_subtype(e);
      42         407 :                 if (exp_match(e, re) && t->multiset) {
      43          38 :                         v->changes++;
      44          38 :                         sql_exp *le = exp_ref(v->sql, e);
      45          38 :                         list *rexps = rel_projections(v->sql, rel->r, NULL, 0, 1);
      46          38 :                         sql_exp *re = exps_bind_column(rexps, MSID_NAME, NULL, NULL, 0);
      47          38 :                         if (le && re) {
      48          38 :                                 re = exp_ref(v->sql, re);
      49          38 :                                 e = exp_compare(v->sql->sa, le, re, cmp_equal);
      50          38 :                                 rel->exps = sa_list_append(v->sql->sa, rel->exps, e);
      51             :                         }
      52          38 :                         return rel;
      53         369 :                 } else if (t->type->composite) {
      54             :                         /* sofar only handles one level */
      55         118 :                         sql_rel *res = ms_add_join_exps(v, rel, e->f);
      56         118 :                         if (res)
      57          29 :                                 return res;
      58             :                 }
      59             :         }
      60             :         return NULL;
      61             : }
      62             : 
      63             : /* TODO handle composite/multset (ie deep nested cases) too */
      64             : static sql_rel *
      65      122207 : fm_join(visitor *v, sql_rel *rel)
      66             : {
      67      122207 :         if (is_dependent(rel) && list_length(rel->exps) <= 1) {
      68        2954 :                 if (list_length(rel->exps) == 1) {
      69        2802 :                         sql_exp *e = rel->exps->h->data;
      70        2802 :                         if (!exp_is_true(e))
      71             :                                 return rel;
      72             :                 }
      73         160 :                 list *exps = rel_projections(v->sql, rel->l, NULL, 0, 1);
      74         160 :                 bool needed = has_multiset(exps);
      75             : 
      76         160 :                 if (needed)
      77          38 :                         return ms_add_join_exps(v, rel, exps);
      78             :         }
      79             :         return rel;
      80             : }
      81             : 
      82             : static sql_rel *
      83     2059424 : flatten_multiset(visitor *v, sql_rel *rel)
      84             : {
      85     2059424 :         (void)v;
      86     2059424 :         switch(rel->op) {
      87      122207 :         case op_join:
      88             :         case op_left:
      89      122207 :                 return fm_join(v, rel);
      90             :         default:
      91             :                 return rel;
      92             :         }
      93             :         return rel;
      94             : }
      95             : 
      96             : sql_rel *
      97      770673 : rel_multiset(mvc *sql, sql_rel *rel)
      98             : {
      99      770673 :         visitor v = { .sql = sql };
     100             : 
     101      770673 :         rel = rel_visitor_bottomup(&v, rel, &flatten_multiset);
     102      771548 :         return rel;
     103             : }

Generated by: LCOV version 1.14