Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  mrn_count_skip_checker.cpp   Sprache: C

 

/* -*- c-basic-offset: 2 -*- */
/*
  Copyright(C) 2010-2013 Kentoku SHIBA
  Copyright(C) 2011-2017 Kouhei Sutou <kou@clear-code.com>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1335  USA
*/


#include "mrn_count_skip_checker.hpp"

#include <item_sum.h>

// for debug
#define MRN_CLASS_NAME "mrn::CountSkipChecker"

namespace mrn {
  CountSkipChecker::CountSkipChecker(grn_ctx *ctx,
                                     TABLE *table,
                                     SELECT_LEX *select_lex,
                                     KEY *key_info,
                                     key_part_map target_key_part_map,
                                     bool is_storage_mode)
    : ctx_(ctx),
      table_(table),
      select_lex_(select_lex),
      key_info_(key_info),
      target_key_part_map_(target_key_part_map),
      is_storage_mode_(is_storage_mode) {
  }

  CountSkipChecker::~CountSkipChecker() = default;

  bool CountSkipChecker::check() {
    MRN_DBUG_ENTER_METHOD();

    if (select_lex_->item_list.elements != 1) {
      GRN_LOG(ctx_, GRN_LOG_DEBUG,
              "[mroonga][count-skip][false] not only one item: %u",
              select_lex_->item_list.elements);
      DBUG_RETURN(false);
    }
    if (select_lex_->group_list.elements > 0) {
      GRN_LOG(ctx_, GRN_LOG_DEBUG,
              "[mroonga][count-skip][false] have groups: %u",
              select_lex_->group_list.elements);
      DBUG_RETURN(false);
    }
    if (MRN_SELECT_LEX_GET_HAVING_COND(select_lex_)) {
      GRN_LOG(ctx_, GRN_LOG_DEBUG,
              "[mroonga][count-skip][false] have HAVING");
      DBUG_RETURN(false);
    }
    if (select_lex_->table_list.elements != 1) {
      GRN_LOG(ctx_, GRN_LOG_DEBUG,
              "[mroonga][count-skip][false] not only one table: %u",
              select_lex_->table_list.elements);
      DBUG_RETURN(false);
    }

    Item *info = static_cast<Item *>(select_lex_->item_list.first_node()->info);
    if (info->type() != Item::SUM_FUNC_ITEM) {
      GRN_LOG(ctx_, GRN_LOG_DEBUG,
              "[mroonga][count-skip][false] item isn't sum function: %u",
              info->type());
      DBUG_RETURN(false);
    }
    Item_sum *sum_item = static_cast<Item_sum *>(info);
    if (sum_item->sum_func() != Item_sum::COUNT_FUNC) {
      GRN_LOG(ctx_, GRN_LOG_DEBUG,
              "[mroonga][count-skip][false] not COUNT: %u",
              sum_item->sum_func());
      DBUG_RETURN(false);
    }
    if (ITEM_SUM_GET_NEST_LEVEL(sum_item) != 0 ||
        ITEM_SUM_GET_AGGR_LEVEL(sum_item) != 0 ||
        ITEM_SUM_GET_MAX_AGGR_LEVEL(sum_item) != -1 ||
        sum_item->max_sum_func_level != -1) {
      GRN_LOG(ctx_, GRN_LOG_DEBUG,
              "[mroonga][count-skip][false] not simple COUNT(*): %d:%d:%d:%d",
              ITEM_SUM_GET_NEST_LEVEL(sum_item),
              ITEM_SUM_GET_AGGR_LEVEL(sum_item),
              ITEM_SUM_GET_MAX_AGGR_LEVEL(sum_item),
              sum_item->max_sum_func_level);
      DBUG_RETURN(false);
    }

    Item *where = MRN_SELECT_LEX_GET_WHERE_COND(select_lex_);
    if (!where) {
      if (is_storage_mode_) {
        GRN_LOG(ctx_, GRN_LOG_DEBUG,
                "[mroonga][count-skip][true] no condition");
        DBUG_RETURN(true);
      } else {
        GRN_LOG(ctx_, GRN_LOG_DEBUG,
                "[mroonga][count-skip][false] no condition with wrapper mode");
        DBUG_RETURN(false);
      }
    }

    bool skippable = is_skippable(where);
    DBUG_RETURN(skippable);
  }

  bool CountSkipChecker::is_skippable(Item *where) {
    MRN_DBUG_ENTER_METHOD();

    bool skippable = false;
    switch (where->type()) {
    case Item::COND_ITEM:
      {
        Item_cond *cond_item = static_cast<Item_cond *>(where);
        skippable = is_skippable(cond_item);
        if (skippable) {
          GRN_LOG(ctx_, GRN_LOG_DEBUG,
                  "[mroonga][count-skip][true] skippable multiple conditions");
        }
      }
      break;
    case Item::FUNC_ITEM:
      {
        Item_func *func_item = static_cast<Item_func *>(where);
        if (func_item->functype() == Item_func::FT_FUNC) {
          if (select_lex_->select_n_where_fields == 1) {
            GRN_LOG(ctx_, GRN_LOG_DEBUG,
                    "[mroonga][count-skip][true] "
                    "only one full text search condition");
            DBUG_RETURN(true);
          } else {
            GRN_LOG(ctx_, GRN_LOG_DEBUG,
                    "[mroonga][count-skip][false] "
                    "full text search condition and more conditions: %u",
                    select_lex_->select_n_where_fields);
            DBUG_RETURN(false);
          }
        } else {
          skippable = is_skippable(func_item);
          if (skippable) {
            GRN_LOG(ctx_, GRN_LOG_DEBUG,
                    "[mroonga][count-skip][true] skippable condition");
          }
        }
      }
      break;
    default:
      GRN_LOG(ctx_, GRN_LOG_DEBUG,
              "[mroonga][count-skip][false] unsupported top level item: %u",
              where->type());
      break;
    }

    DBUG_RETURN(skippable);
  }

  bool CountSkipChecker::is_skippable(Item_cond *cond_item) {
    MRN_DBUG_ENTER_METHOD();

    List_iterator<Item> iterator(*(cond_item->argument_list()));
    Item *sub_item;
    while ((sub_item = iterator++)) {
      if (sub_item->type() != Item::FUNC_ITEM) {
        GRN_LOG(ctx_, GRN_LOG_DEBUG,
                "[mroonga][count-skip][false] "
                "sub condition isn't function item: %u",
                sub_item->type());
        DBUG_RETURN(false);
      }
      if (!is_skippable(static_cast<Item_func *>(sub_item))) {
        DBUG_RETURN(false);
      }
    }
    DBUG_RETURN(true);
  }

  bool CountSkipChecker::is_skippable(Item_func *func_item) {
    MRN_DBUG_ENTER_METHOD();

    switch (func_item->functype()) {
    case Item_func::EQ_FUNC:
    case Item_func::EQUAL_FUNC:
    case Item_func::NE_FUNC:
    case Item_func::LT_FUNC:
    case Item_func::LE_FUNC:
    case Item_func::GE_FUNC:
    case Item_func::GT_FUNC:
      {
        Item **arguments = func_item->arguments();
        Item *left_item = arguments[0];
        if (left_item->type() != Item::FIELD_ITEM) {
          GRN_LOG(ctx_, GRN_LOG_DEBUG,
                  "[mroonga][count-skip][false] not field: %u:%u",
                  func_item->functype(),
                  left_item->type());
          DBUG_RETURN(false);
        }

        bool skippable = is_skippable(static_cast<Item_field *>(left_item));
        DBUG_RETURN(skippable);
      }
      break;
    case Item_func::BETWEEN:
      {
        Item **arguments = func_item->arguments();
        Item *target_item = arguments[0];
        if (target_item->type() != Item::FIELD_ITEM) {
          GRN_LOG(ctx_, GRN_LOG_DEBUG,
                  "[mroonga][count-skip][false] BETWEEN target isn't field: %u",
                  target_item->type());
          DBUG_RETURN(false);
        }

        bool skippable = is_skippable(static_cast<Item_field *>(target_item));
        DBUG_RETURN(skippable);
      }
      break;
    case Item_func::MULT_EQUAL_FUNC:
#ifdef MRN_HAVE_ITEM_EQUAL_FIELDS_ITERATOR
      {
        Item_equal *equal_item = static_cast<Item_equal *>(func_item);
        Item_equal_fields_iterator iterator(*equal_item);
        Item *field_item;
        while ((field_item = iterator++)) {
          bool skippable = is_skippable(static_cast<Item_field *>(field_item));
          if (!skippable) {
            DBUG_RETURN(skippable);
          }
        }
        DBUG_RETURN(true);
      }
#endif
      break;
    default:
      break;
    }

    GRN_LOG(ctx_, GRN_LOG_DEBUG,
            "[mroonga][count-skip][false] unsupported function item: %u",
            func_item->functype());
    DBUG_RETURN(false);
  }

  bool CountSkipChecker::is_skippable(Item_field *field_item) {
    MRN_DBUG_ENTER_METHOD();

    Field *field = field_item->field;
    if (!field) {
      GRN_LOG(ctx_, GRN_LOG_DEBUG,
              "[mroonga][count-skip][false] field is missing");
      DBUG_RETURN(false);
    }

    if (field->table != table_) {
      GRN_LOG(ctx_, GRN_LOG_DEBUG,
              "[mroonga][count-skip][false] external table's field");
      DBUG_RETURN(false);
    }

    if (!key_info_) {
      GRN_LOG(ctx_, GRN_LOG_DEBUG,
              "[mroonga][count-skip][false] no active index: <%s>:<%s>",
              *(field->table_name),
              field->field_name.str);
      DBUG_RETURN(false);
    }

    uint i;
    KEY_PART_INFO *key_part = key_info_->key_part;
    for (i = 0; i < KEY_N_KEY_PARTS(key_info_); i++) {
      if (key_part[i].field == field) {
        if ((target_key_part_map_ >> i) & 1) {
          DBUG_RETURN(true);
        } else {
          GRN_LOG(ctx_, GRN_LOG_DEBUG,
                  "[mroonga][count-skip][false] "
                  "field's index are out of key part map: %u:%lu: <%s>:<%s>",
                  i,
                  target_key_part_map_,
                  *(field->table_name),
                  field->field_name.str);
          DBUG_RETURN(false);
        }
      }
    }

    GRN_LOG(ctx_, GRN_LOG_DEBUG,
            "[mroonga][count-skip][false] field isn't indexed: <%s>:<%s>",
            *(field->table_name),
            field->field_name.str);
    DBUG_RETURN(false);
  }
}

Messung V0.5 in Prozent
C=100 H=94 G=96

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet am  2026-10-08) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=1126864
#Domains=1897691