LCOV - code coverage report
Current view: top level - sql/server - rel_partition.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 84 101 83.2 %
Date: 2021-10-13 02:24:04 Functions: 5 5 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 "sql_query.h"
      11             : #include "rel_partition.h"
      12             : #include "rel_optimizer.h"
      13             : #include "rel_exp.h"
      14             : #include "rel_prop.h"
      15             : #include "rel_dump.h"
      16             : #include "rel_select.h"
      17             : #include "rel_updates.h"
      18             : #include "sql_env.h"
      19             : 
      20             : static lng
      21      224936 : rel_getcount(mvc *sql, sql_rel *rel)
      22             : {
      23      224936 :         if (!sql->session->tr)
      24             :                 return 0;
      25             : 
      26      224936 :         switch(rel->op) {
      27      224936 :         case op_basetable: {
      28      224936 :                 sql_table *t = rel->l;
      29             : 
      30      224936 :                 if (t && isTable(t)) {
      31      224936 :                         sqlstore *store = sql->session->tr->store;
      32      224936 :                         return (lng)store->storage_api.count_col(sql->session->tr, ol_first_node(t->columns)->data, 0);
      33             :                 }
      34             :                 return 0;
      35             :         }
      36             :         default:
      37           0 :                 assert(0);
      38             :                 return 0;
      39             :         }
      40             : }
      41             : 
      42             : static void
      43      230999 : find_basetables(mvc *sql, sql_rel *rel, list *tables )
      44             : {
      45      639657 :         if (THRhighwater()) {
      46           0 :                 (void) sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
      47           0 :                 return;
      48             :         }
      49             : 
      50      639657 :         if (!rel)
      51             :                 return;
      52      639657 :         switch (rel->op) {
      53      224958 :         case op_basetable: {
      54      224958 :                 sql_table *t = rel->l;
      55             : 
      56      224958 :                 if (t && isTable(t))
      57      224936 :                         append(tables, rel);
      58             :                 break;
      59             :         }
      60        4012 :         case op_table:
      61        4012 :                 if (IS_TABLE_PROD_FUNC(rel->flag) || rel->flag == TABLE_FROM_RELATION)
      62        4012 :                         if (rel->l)
      63             :                                 find_basetables(sql, rel->l, tables);
      64             :                 break;
      65      188641 :         case op_join:
      66             :         case op_left:
      67             :         case op_right:
      68             :         case op_full:
      69             :         case op_union:
      70             :         case op_inter:
      71             :         case op_except:
      72             :         case op_insert:
      73             :         case op_update:
      74             :         case op_delete:
      75             :         case op_merge:
      76      188641 :                 if (rel->l)
      77      188640 :                         find_basetables(sql, rel->l, tables);
      78      188641 :                 if (rel->r)
      79             :                         find_basetables(sql, rel->r, tables);
      80             :                 break;
      81      222046 :         case op_semi:
      82             :         case op_anti:
      83             :         case op_groupby:
      84             :         case op_project:
      85             :         case op_select:
      86             :         case op_topn:
      87             :         case op_sample:
      88             :         case op_truncate:
      89      222046 :                 if (rel->l)
      90             :                         find_basetables(sql, rel->l, tables);
      91             :                 break;
      92           0 :         case op_ddl:
      93           0 :                 if (rel->flag == ddl_output || rel->flag == ddl_create_seq || rel->flag == ddl_alter_seq/* || rel->flag == ddl_alter_table || rel->flag == ddl_create_table || rel->flag == ddl_create_view*/) {
      94           0 :                         if (rel->l)
      95             :                                 find_basetables(sql, rel->l, tables);
      96           0 :                 } else if (rel->flag == ddl_list || rel->flag == ddl_exception) {
      97           0 :                         if (rel->l)
      98           0 :                                 find_basetables(sql, rel->l, tables);
      99           0 :                         if (rel->r)
     100             :                                 find_basetables(sql, rel->r, tables);
     101             :                 }
     102             :                 break;
     103             :         }
     104      230999 : }
     105             : 
     106             : static sql_rel *
     107       42359 : _rel_partition(mvc *sql, sql_rel *rel)
     108             : {
     109       42359 :         list *tables = sa_list(sql->sa);
     110             :         /* find basetable relations */
     111             :         /* mark one (largest) with REL_PARTITION */
     112       42359 :         find_basetables(sql, rel, tables);
     113       42359 :         if (list_length(tables)) {
     114             :                 sql_rel *r;
     115             :                 node *n;
     116             :                 int i, mi = 0;
     117       42175 :                 lng *sizes = SA_NEW_ARRAY(sql->sa, lng, list_length(tables)), m = 0;
     118             : 
     119      267111 :                 for(i=0, n = tables->h; n; i++, n = n->next) {
     120      224936 :                         r = n->data;
     121      224936 :                         sizes[i] = rel_getcount(sql, r);
     122      224936 :                         if (sizes[i] > m) {
     123             :                                 m = sizes[i];
     124             :                                 mi = i;
     125             :                         }
     126             :                 }
     127       76963 :                 for(i=0, n = tables->h; i<mi; i++, n = n->next)
     128             :                         ;
     129       42175 :                 r = n->data;
     130             :                 /*  TODO, we now pick first (okay?)! In case of self joins we need to pick the correct table */
     131       42175 :                 r->flag = REL_PARTITION;
     132             :         }
     133       42359 :         return rel;
     134             : }
     135             : 
     136             : static int
     137      464700 : has_groupby(sql_rel *rel)
     138             : {
     139      737004 :         if (!rel)
     140             :                 return 0;
     141      730766 :         if (is_groupby(rel->op))
     142             :                 return 1;
     143      709705 :         if (is_join(rel->op) || is_semi(rel->op) || is_set(rel->op) || is_merge(rel->op))
     144      177421 :                 return has_groupby(rel->l) || has_groupby(rel->r);
     145      532284 :         if (is_simple_project(rel->op) || is_select(rel->op) || is_topn(rel->op) || is_sample(rel->op))
     146      268285 :                 return has_groupby(rel->l);
     147      263999 :         if (is_insert(rel->op) || is_update(rel->op) || is_delete(rel->op) || is_truncate(rel->op))
     148           0 :                 return has_groupby(rel->r);
     149      263999 :         if (is_ddl(rel->op)) {
     150           0 :                 if (rel->flag == ddl_output || rel->flag == ddl_create_seq || rel->flag == ddl_alter_seq || rel->flag == ddl_alter_table || rel->flag == ddl_create_table || rel->flag == ddl_create_view)
     151           0 :                         return has_groupby(rel->l);
     152           0 :                 if (rel->flag == ddl_list || rel->flag == ddl_exception)
     153           0 :                         return has_groupby(rel->l) || has_groupby(rel->r);
     154             :         }
     155      263999 :         if (rel->op == op_table && (IS_TABLE_PROD_FUNC(rel->flag) || rel->flag == TABLE_FROM_RELATION))
     156        4019 :                 return has_groupby(rel->l);
     157             :         return 0;
     158             : }
     159             : 
     160             : sql_rel *
     161      795814 : rel_partition(mvc *sql, sql_rel *rel)
     162             : {
     163      795814 :         if (THRhighwater())
     164           0 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
     165             : 
     166      795814 :         if (is_basetable(rel->op)) {
     167       72010 :                 rel->flag = REL_PARTITION;
     168      723804 :         } else if (is_simple_project(rel->op) || is_select(rel->op) || is_groupby(rel->op) || is_topn(rel->op) || is_sample(rel->op)) {
     169      347276 :                 if (rel->l)
     170      252036 :                         rel_partition(sql, rel->l);
     171      376528 :         } else if (is_semi(rel->op) || is_set(rel->op) || is_merge(rel->op)) {
     172       21064 :                 if (rel->l)
     173       21064 :                         rel_partition(sql, rel->l);
     174       21064 :                 if (rel->r)
     175       21064 :                         rel_partition(sql, rel->r);
     176      355464 :         } else if (is_insert(rel->op) || is_update(rel->op) || is_delete(rel->op) || is_truncate(rel->op)) {
     177       75873 :                 if (rel->r && rel->card <= CARD_AGGR)
     178       70037 :                         rel_partition(sql, rel->r);
     179      279591 :         } else if (is_join(rel->op)) {
     180       63420 :                 if (has_groupby(rel->l) || has_groupby(rel->r)) {
     181       21061 :                         if (rel->l)
     182       21061 :                                 rel_partition(sql, rel->l);
     183       21061 :                         if (rel->r)
     184       21061 :                                 rel_partition(sql, rel->r);
     185             :                 } else
     186       42359 :                         _rel_partition(sql, rel);
     187      216171 :         } else if (is_ddl(rel->op)) {
     188      214883 :                 if (rel->flag == ddl_output || rel->flag == ddl_create_seq || rel->flag == ddl_alter_seq || rel->flag == ddl_alter_table || rel->flag == ddl_create_table || rel->flag == ddl_create_view) {
     189       25252 :                         if (rel->l)
     190       24915 :                                 rel_partition(sql, rel->l);
     191      189631 :                 } else if (rel->flag == ddl_list || rel->flag == ddl_exception) {
     192         754 :                         if (rel->l)
     193         747 :                                 rel_partition(sql, rel->l);
     194         754 :                         if (rel->r)
     195         723 :                                 rel_partition(sql, rel->r);
     196             :                 }
     197        1288 :         } else if (rel->op == op_table) {
     198        1288 :                 if ((IS_TABLE_PROD_FUNC(rel->flag) || rel->flag == TABLE_FROM_RELATION) && rel->l)
     199         406 :                         rel_partition(sql, rel->l);
     200             :         } else {
     201           0 :                 assert(0);
     202             :         }
     203             :         return rel;
     204             : }

Generated by: LCOV version 1.14