LCOV - code coverage report
Current view: top level - monetdb5/optimizer - opt_costModel.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 62 62 100.0 %
Date: 2024-04-25 20:03:45 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : #include "monetdb_config.h"
      14             : #include "opt_costModel.h"
      15             : 
      16             : /*
      17             :  * The cost formula are repetitive
      18             :  */
      19             : #define newRows(W,X,Y,Z)                                                                                \
      20             :         do {                                                                                                            \
      21             :                 c1 = getRowCnt(mb, getArg(p,W));                                                \
      22             :                 c2 = getRowCnt(mb, getArg(p,X));                                                \
      23             :                 /* just to ensure that rowcnt was/is never set to -1 */ \
      24             :                 if (c1 == (BUN) -1 || c2 == (BUN) -1                                    \
      25             :                         || c1 == BUN_NONE || c2 == BUN_NONE)                            \
      26             :                         continue;                                                                                       \
      27             :                 setRowCnt(mb, getArg(p,Z), (Y));                                                \
      28             :         } while (0)
      29             : 
      30             : /*
      31             :  * The cost will be used in many places to make decisions.
      32             :  * Access should be fast.
      33             :  * The SQL front-end also makes the BAT index available as the
      34             :  * property bid. This can be used to access the BAT and involve
      35             :  * more properties into the decision procedure.
      36             :  * [to be done]
      37             :  * Also make sure you don't re-use variables, because then the
      38             :  * row count becomes non-deterministic.
      39             :  */
      40             : str
      41      467671 : OPTcostModelImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
      42             :                                                    InstrPtr pci)
      43             : {
      44      467671 :         int i;
      45      467671 :         BUN c1, c2;
      46      467671 :         InstrPtr p;
      47      467671 :         str msg = MAL_SUCCEED;
      48             : 
      49      467671 :         (void) cntxt;
      50      467671 :         (void) stk;
      51             : 
      52      467671 :         if (mb->inlineProp)
      53             :                 return MAL_SUCCEED;
      54             : 
      55    25251511 :         for (i = 0; i < mb->stop; i++) {
      56    24783840 :                 p = getInstrPtr(mb, i);
      57    24783840 :                 if (getModuleId(p) == algebraRef) {
      58     3403039 :                         if (getFunctionId(p) == selectRef
      59     3362380 :                                 || getFunctionId(p) == thetaselectRef) {
      60      208785 :                                 newRows(1, 2, (c1 > 2 ? c2 / 2 + 1 : c1 / 2 + 1), 0);
      61     3194254 :                         } else if (getFunctionId(p) == selectNotNilRef
      62     3194254 :                                            || getFunctionId(p) == sortRef
      63     3172034 :                                            || getFunctionId(p) == projectRef) {
      64      126777 :                                 newRows(1, 1, c1, 0);
      65     3067477 :                         } else if (getFunctionId(p) == joinRef
      66     2997061 :                                            || getFunctionId(p) == projectionRef
      67       87485 :                                            || getFunctionId(p) == bandjoinRef
      68       87485 :                                            || getFunctionId(p) == projectionpathRef) {
      69             :                                 /* assume 1-1 joins */
      70     2979992 :                                 newRows(1, 2, (c1 < c2 ? c1 : c2), 0);
      71       87485 :                         } else if (getFunctionId(p) == crossRef) {
      72       11130 :                                 newRows(1, 2,
      73             :                                                 ((log((double) c1) + log((double) c2) >
      74             :                                                   log(INT_MAX) ? INT_MAX : c1 * c2 + 1)), 0);
      75             :                                 /* log sets errno if it cannot compute the log. This will then screw with code that checks errno */
      76       11130 :                                 if (errno == ERANGE || errno == EDOM) {
      77       11130 :                                         errno = 0;
      78             :                                 }
      79             :                         }
      80    21380801 :                 } else if (getModuleId(p) == batcalcRef) {
      81      216850 :                         if (getFunctionId(p) == ifthenelseRef) {
      82        4411 :                                 if (isaBatType(getArgType(mb, p, 2))) {
      83          94 :                                         newRows(2, 2, c1, 0);
      84             :                                 } else {
      85        4317 :                                         newRows(3, 3, c1, 0);
      86             :                                 }
      87      212439 :                         } else if (isaBatType(getArgType(mb, p, 1))) {
      88      210596 :                                 newRows(1, 1, c1, 0);
      89             :                         } else {
      90        1843 :                                 newRows(2, 2, c2, 0);
      91             :                         }
      92    21163951 :                 } else if (getModuleId(p) == batstrRef) {
      93        3096 :                         newRows(1, 1, c1, 0);
      94    21160855 :                 } else if (getModuleId(p) == batRef) {
      95      798308 :                         if (getFunctionId(p) == appendRef) {
      96             :                                 /*
      97             :                                  * Updates are a little more complicated, because you have to
      98             :                                  * propagate changes in the expected size up the expression tree.
      99             :                                  * For example, the SQL snippet:
     100             :                                  *       _49:bat[:oid,:oid]{rows=0,bid=622}  := sql.bind_dbat("sys","example",3);
     101             :                                  *       _54 := bat.setWriteMode(_49);
     102             :                                  *       bat.append(_54,_47,true);
     103             :                                  * shows what is produced when it encounters a deletion. If a non-empty
     104             :                                  * append is not properly passed back to _49, the emptySet
     105             :                                  * optimizer might remove the complete deletion code.
     106             :                                  * The same holds for replacement operations, which add information to
     107             :                                  * an initially empty insertion BAT.
     108             :                                  */
     109      210758 :                                 if (isaBatType(getArgType(mb, p, 2))) {
     110             :                                         /* insert BAT */
     111      208885 :                                         newRows(1, 2, (c1 + c2 + 1), 1);
     112             :                                 } else {
     113             :                                         /* insert scalars */
     114        1873 :                                         newRows(1, 1, (c1 + 1), 1);
     115             :                                 }
     116      587550 :                         } else if (getFunctionId(p) == deleteRef) {
     117           6 :                                 if (isaBatType(getArgType(mb, p, 2))) {
     118             :                                         /* delete BAT */
     119           2 :                                         newRows(1, 2, (c2 >= c1 ? 1 : c1 - c2), 1);
     120             :                                 } else {
     121             :                                         /* insert scalars */
     122           4 :                                         newRows(1, 1, (c1 <= 1 ? 1 : c1 - 1), 1);
     123             :                                 }
     124             :                         }
     125    20362547 :                 } else if (getModuleId(p) == groupRef) {
     126       27500 :                         if (getFunctionId(p) == subgroupRef || getFunctionId(p) == groupRef) {
     127        6034 :                                 newRows(1, 1, (c1 / 10 + 1), 0);
     128             :                         } else {
     129       21466 :                                 newRows(1, 1, c1, 0);
     130             :                         }
     131    20335047 :                 } else if (getModuleId(p) == aggrRef) {
     132       55593 :                         if (getFunctionId(p) == sumRef || getFunctionId(p) == minRef
     133       49836 :                                 || getFunctionId(p) == maxRef || getFunctionId(p) == avgRef) {
     134        7210 :                                 newRows(1, 1, (c1 != 0 ? c1 : 1), 0);
     135       48383 :                         } else if (getFunctionId(p) == countRef) {
     136       41251 :                                 newRows(1, 1, 1, 0);
     137             :                         }
     138    20279454 :                 } else if (p->token == ASSIGNsymbol && p->argc == 2) {
     139             :                         /* copy the rows property */
     140     2749927 :                         c1 = getRowCnt(mb, getArg(p, 1));
     141             :                         /* just to ensure that rowcnt was/is never set to -1 */
     142     2749927 :                         if (c1 != (BUN) -1 && c1 != BUN_NONE)
     143     2749928 :                                 setRowCnt(mb, getArg(p, 0), c1);
     144             :                 }
     145             :         }
     146             :         /* Defense line against incorrect plans */
     147             :         /* plan remains unaffected */
     148             :         // msg = chkTypes(cntxt->usermodule, mb, FALSE);
     149             :         // if (!msg)
     150             :         //      msg = chkFlow(mb);
     151             :         // if (!msg)
     152             :         //      msg = chkDeclarations(mb);
     153             : 
     154             :         /* keep actions taken as a fake argument */
     155      467671 :         (void) pushInt(mb, pci, 1);
     156      467671 :         return msg;
     157             : }

Generated by: LCOV version 1.14