LCOV - code coverage report
Current view: top level - sql/server - rel_rewriter.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 81 123 65.9 %
Date: 2021-10-13 02:24:04 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : #include "monetdb_config.h"
      10             : #include "rel_rewriter.h"
      11             : #include "rel_prop.h"
      12             : #include "rel_rel.h"
      13             : #include "rel_exp.h"
      14             : #include "mal_errors.h" /* for SQLSTATE() */
      15             : 
      16             : /* simplify expressions, such as not(not(x)) */
      17             : /* exp visitor */
      18             : 
      19             : #define is_not_anyequal(sf) (strcmp((sf)->func->base.name, "sql_not_anyequal") == 0)
      20             : 
      21             : static list *
      22     3115535 : exps_simplify_exp(visitor *v, list *exps)
      23             : {
      24     3115535 :         if (list_empty(exps))
      25             :                 return exps;
      26             : 
      27             :         int needed = 0;
      28     6822400 :         for (node *n=exps->h; n && !needed; n = n->next) {
      29     3706865 :                 sql_exp *e = n->data;
      30             : 
      31     3706865 :                 needed = (exp_is_true(e) || exp_is_false(e) || (is_compare(e->type) && e->flag == cmp_or));
      32             :         }
      33             :         /* if there's only one expression and it is false, we have to keep it */
      34     3115535 :         if (list_length(exps) == 1 && exp_is_false(exps->h->data))
      35             :                 return exps;
      36     3111353 :         if (needed) {
      37      120832 :                 list *nexps = sa_list(v->sql->sa);
      38      259690 :                 for (node *n=exps->h; n; n = n->next) {
      39      138921 :                         sql_exp *e = n->data;
      40             : 
      41             :                         /* TRUE or X -> TRUE
      42             :                         * FALSE or X -> X */
      43      138921 :                         if (is_compare(e->type) && e->flag == cmp_or) {
      44      120969 :                                 list *l = e->l = exps_simplify_exp(v, e->l);
      45      120969 :                                 list *r = e->r = exps_simplify_exp(v, e->r);
      46             : 
      47      120969 :                                 if (list_length(l) == 1) {
      48      115058 :                                         sql_exp *ie = l->h->data;
      49             : 
      50      115058 :                                         if (exp_is_true(ie)) {
      51           0 :                                                 v->changes++;
      52           0 :                                                 continue;
      53      115058 :                                         } else if (exp_is_false(ie)) {
      54          49 :                                                 v->changes++;
      55          49 :                                                 nexps = list_merge(nexps, r, (fdup)NULL);
      56          49 :                                                 continue;
      57             :                                         }
      58        5911 :                                 } else if (list_length(l) == 0) { /* left is true */
      59          34 :                                         v->changes++;
      60          34 :                                         continue;
      61             :                                 }
      62      120886 :                                 if (list_length(r) == 1) {
      63      114186 :                                         sql_exp *ie = r->h->data;
      64             : 
      65      114186 :                                         if (exp_is_true(ie)) {
      66           0 :                                                 v->changes++;
      67           0 :                                                 continue;
      68      114186 :                                         } else if (exp_is_false(ie)) {
      69         254 :                                                 nexps = list_merge(nexps, l, (fdup)NULL);
      70         254 :                                                 v->changes++;
      71         254 :                                                 continue;
      72             :                                         }
      73        6700 :                                 } else if (list_length(r) == 0) { /* right is true */
      74          30 :                                         v->changes++;
      75          30 :                                         continue;
      76             :                                 }
      77             :                         }
      78             :                         /* TRUE and X -> X */
      79      138554 :                         if (exp_is_true(e)) {
      80        1832 :                                 v->changes++;
      81        1832 :                                 continue;
      82             :                         /* FALSE and X -> FALSE */
      83      136722 :                         } else if (exp_is_false(e)) {
      84          63 :                                 v->changes++;
      85          63 :                                 return append(sa_list(v->sql->sa), e);
      86             :                         } else {
      87      136659 :                                 append(nexps, e);
      88             :                         }
      89             :                 }
      90      120769 :                 return nexps;
      91             :         }
      92             :         return exps;
      93             : }
      94             : 
      95             : sql_exp *
      96    16792264 : rewrite_simplify_exp(visitor *v, sql_rel *rel, sql_exp *e, int depth)
      97             : {
      98    16792264 :         if (!e)
      99             :                 return e;
     100             : 
     101    16792264 :         v->changes = 0;
     102             :         (void)rel; (void)depth;
     103             : 
     104    16792264 :         sql_subfunc *sf = e->f;
     105    16792264 :         if (is_func(e->type) && list_length(e->l) == 1 && is_not_func(sf)) {
     106       25775 :                 list *args = e->l;
     107       25775 :                 sql_exp *ie = args->h->data;
     108             : 
     109       25775 :                 if (!ie)
     110             :                         return e;
     111             : 
     112       25775 :                 sql_subfunc *sf = ie->f;
     113       25775 :                 if (is_func(ie->type) && list_length(ie->l) == 1 && is_not_func(sf)) {
     114           0 :                         args = ie->l;
     115             : 
     116           0 :                         ie = args->h->data;
     117           0 :                         if (exp_name(e))
     118           0 :                                 exp_prop_alias(v->sql->sa, ie, e);
     119           0 :                         v->changes++;
     120           0 :                         return ie;
     121             :                 }
     122       25775 :                 if (is_func(ie->type) && list_length(ie->l) == 2 && is_not_anyequal(sf)) {
     123           0 :                         args = ie->l;
     124             : 
     125           0 :                         sql_exp *l = args->h->data;
     126           0 :                         sql_exp *vals = args->h->next->data;
     127             : 
     128           0 :                         if (!(ie = exp_in_func(v->sql, l, vals, 1, 0)))
     129             :                                 return NULL;
     130           0 :                         if (exp_name(e))
     131           0 :                                 exp_prop_alias(v->sql->sa, ie, e);
     132           0 :                         v->changes++;
     133           0 :                         return ie;
     134             :                 }
     135             :                 /* TRUE or X -> TRUE
     136             :                  * FALSE or X -> X */
     137       25775 :                 if (is_compare(e->type) && e->flag == cmp_or) {
     138           0 :                         list *l = e->l = exps_simplify_exp(v, e->l);
     139           0 :                         list *r = e->r = exps_simplify_exp(v, e->r);
     140             : 
     141           0 :                         if (list_length(l) == 1) {
     142           0 :                                 sql_exp *ie = l->h->data;
     143             : 
     144           0 :                                 if (exp_is_true(ie)) {
     145           0 :                                         v->changes++;
     146           0 :                                         return ie;
     147           0 :                                 } else if (exp_is_false(ie) && list_length(r) == 1) {
     148           0 :                                         v->changes++;
     149           0 :                                         return r->h->data;
     150             :                                 }
     151           0 :                         } else if (list_length(l) == 0) { /* left is true */
     152           0 :                                 v->changes++;
     153           0 :                                 return exp_atom_bool(v->sql->sa, 1);
     154             :                         }
     155           0 :                         if (list_length(r) == 1) {
     156           0 :                                 sql_exp *ie = r->h->data;
     157             : 
     158           0 :                                 if (exp_is_true(ie)) {
     159           0 :                                         v->changes++;
     160           0 :                                         return ie;
     161           0 :                                 } else if (exp_is_false(ie) && list_length(l) == 1) {
     162           0 :                                         v->changes++;
     163           0 :                                         return l->h->data;
     164             :                                 }
     165           0 :                         } else if (list_length(r) == 0) { /* right is true */
     166           0 :                                 v->changes++;
     167           0 :                                 return exp_atom_bool(v->sql->sa, 1);
     168             :                         }
     169             :                 }
     170             :         }
     171             :         return e;
     172             : }
     173             : 
     174             : sql_rel *
     175     8567899 : rewrite_simplify(visitor *v, sql_rel *rel)
     176             : {
     177     8567899 :         if (!rel)
     178             :                 return rel;
     179             : 
     180     8567899 :         if ((is_select(rel->op) || is_join(rel->op) || is_semi(rel->op)) && !list_empty(rel->exps)) {
     181     2873597 :                 int changes = v->changes, level = *(int*)v->data;
     182     2873597 :                 rel->exps = exps_simplify_exp(v, rel->exps);
     183             :                 /* At a select or inner join relation if the single expression is false, eliminate the inner relations with a dummy projection */
     184     2873597 :                 if (v->value_based_opt && (v->changes > changes || level == 0) && (is_select(rel->op) || is_innerjoin(rel->op)) &&
     185      237783 :                         !is_single(rel) && list_length(rel->exps) == 1 && (exp_is_false(rel->exps->h->data) || exp_is_null(rel->exps->h->data))) {
     186        1328 :                         list *nexps = sa_list(v->sql->sa), *toconvert = rel_projections(v->sql, rel->l, NULL, 1, 1);
     187        1328 :                         if (is_innerjoin(rel->op))
     188           6 :                                 toconvert = list_merge(toconvert, rel_projections(v->sql, rel->r, NULL, 1, 1), NULL);
     189             : 
     190        8488 :                         for (node *n = toconvert->h ; n ; n = n->next) {
     191        7160 :                                 sql_exp *e = n->data, *a = exp_atom(v->sql->sa, atom_general(v->sql->sa, exp_subtype(e), NULL));
     192        7160 :                                 exp_prop_alias(v->sql->sa, a, e);
     193        7160 :                                 list_append(nexps, a);
     194             :                         }
     195        1328 :                         rel_destroy(rel->l);
     196        1328 :                         if (is_innerjoin(rel->op)) {
     197           6 :                                 rel_destroy(rel->r);
     198           6 :                                 rel->r = NULL;
     199           6 :                                 rel->op = op_select;
     200             :                         }
     201        1328 :                         rel->l = rel_project(v->sql->sa, NULL, nexps);
     202        1328 :                         rel->card = CARD_ATOM;
     203        1328 :                         v->changes++;
     204             :                 }
     205             :         }
     206     8567899 :         if (is_join(rel->op) && list_empty(rel->exps))
     207      174250 :                 rel->exps = NULL; /* crossproduct */
     208     8567899 :         return try_remove_empty_select(v, rel);
     209             : }
     210             : 
     211             : sql_rel *
     212     8271901 : rewrite_reset_used(visitor *v, sql_rel *rel)
     213             : {
     214             :         (void) v;
     215     8271901 :         rel->used = 0;
     216     8271901 :         return rel;
     217             : }

Generated by: LCOV version 1.14