LCOV - code coverage report
Current view: top level - root/contrail/src/contrail-analytics/contrail-query-engine - where_query.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 628 1004 62.5 %
Date: 2026-11-09 02:10:49 Functions: 15 19 78.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #include <cstdlib>
       7             : #include <limits>
       8             : #include <string>
       9             : #include <sstream>
      10             : #include <boost/foreach.hpp>
      11             : #include <boost/algorithm/string/case_conv.hpp>
      12             : #include "rapidjson/document.h"
      13             : #include <boost/foreach.hpp>
      14             : #include "query.h"
      15             : #include "json_parse.h"
      16             : #include "base/regex.h"
      17             : #include "base/string_util.h"
      18             : #include "database/gendb_constants.h"
      19             : #include "database/gendb_if.h"
      20             : #include "utils.h"
      21             : #include "query.h"
      22             : #include "stats_query.h"
      23             : 
      24             : using contrail::regex;
      25             : using contrail::regex_match;
      26             : using contrail::regex_search;
      27             : using std::string;
      28             : 
      29        2514 : static std::string ToString(const contrail_rapidjson::Value& value_value) {
      30        2514 :     std::string svalue;
      31        2514 :     if (value_value.IsString())
      32             :     {
      33        1419 :         svalue = value_value.GetString();
      34        1096 :     } else if (value_value.IsInt()){
      35             :         int int_value;
      36          72 :         std::ostringstream convert;
      37          72 :         int_value = value_value.GetInt();
      38          72 :         convert << int_value;
      39          72 :         svalue = convert.str();
      40        1096 :     } else if (value_value.IsUint()) {
      41             :         uint32_t uint_value;
      42           0 :         std::ostringstream convert;
      43           0 :         uint_value = value_value.GetUint();
      44           0 :         convert << uint_value;
      45           0 :         svalue = convert.str();
      46        1024 :     } else if (value_value.IsDouble()) {
      47             :         double dbl_value;
      48           0 :         std::ostringstream convert;
      49           0 :         dbl_value = value_value.GetDouble();
      50           0 :         convert << dbl_value;
      51           0 :         svalue = convert.str();
      52           0 :     }
      53        2513 :     return svalue;
      54           0 : }
      55             : 
      56         719 : static GenDb::DbDataValue ToDbDataValue(const std::string& value, QEOpServerProxy::VarType desc) {
      57         719 :     GenDb::DbDataValue smpl;
      58         719 :     if (desc == QEOpServerProxy::STRING ||
      59          36 :         desc == QEOpServerProxy::MAP_ELEM ||
      60             :         desc == QEOpServerProxy::LIST) {
      61         683 :         smpl = value;
      62          36 :     } else if (desc == QEOpServerProxy::UINT64) {
      63          36 :         smpl = (uint64_t) strtoul(value.c_str(), NULL, 10);
      64           0 :     } else if (desc == QEOpServerProxy::DOUBLE) {
      65           0 :         smpl = (double) strtod(value.c_str(), NULL); 
      66             :     }
      67         718 :     return smpl;
      68           0 : }
      69             : 
      70        2047 : static GenDb::DbDataValue ToDbDataValue(const contrail_rapidjson::Value& val) {
      71        2047 :     GenDb::DbDataValue ret;
      72        2047 :     if (val.IsString()) {
      73         970 :         ret = std::string(val.GetString());
      74        1077 :     } else if (val.IsUint()) {
      75          54 :         ret = (uint64_t) val.GetUint();
      76        1022 :     } else if (val.IsInt()) {
      77           0 :         ret = (uint64_t) val.GetInt();
      78        1022 :     } else if (val.IsDouble()) {
      79           2 :         ret = (double) val.GetDouble();
      80             :     }
      81        2042 :     return ret;
      82           0 : }
      83             : 
      84           0 : static QEOpServerProxy::VarType ToDbDataType(string val) {
      85           0 :     QEOpServerProxy::VarType ret = QEOpServerProxy::BLANK;
      86           0 :     if (val == "int") {
      87           0 :         ret = QEOpServerProxy::UINT64;
      88           0 :     } else if (val == "string") {
      89           0 :         ret = QEOpServerProxy::STRING;
      90           0 :     } else if (val == "uuid") {
      91           0 :         ret = QEOpServerProxy::UUID;
      92           0 :     } else if (val == "double") {
      93           0 :         ret = QEOpServerProxy::DOUBLE;
      94           0 :     } else if (val == "map") {
      95           0 :         ret = QEOpServerProxy::MAP_ELEM;
      96           0 :     } else if (val == "set" || val == "list") {
      97           0 :         ret = QEOpServerProxy::LIST;
      98             :     }
      99           0 :     return ret;
     100             : }
     101             : 
     102           0 : static StatsQuery::column_t get_column_desc(std::map<std::string,StatsQuery::column_t> table_schema, std::string pname) {
     103           0 :     StatsQuery::column_t cdesc;
     104             :     std::map<std::string,StatsQuery::column_t>::const_iterator st =
     105           0 :             table_schema.find(pname);
     106           0 :     if (st!=table_schema.end()) {
     107           0 :         cdesc = st->second;
     108             :     } else {
     109           0 :         size_t pos = pname.find_last_of(".");
     110           0 :         std::string mapstr(pname.substr(0,pos) + ".*");
     111           0 :         st = table_schema.find(mapstr);
     112           0 :         if (st != table_schema.end()) {
     113           0 :             cdesc = st->second;
     114             :         } else  {
     115           0 :             cdesc.datatype = QEOpServerProxy::BLANK;
     116           0 :             cdesc.index = false;
     117           0 :             cdesc.output = false;
     118             :         }
     119           0 :     }
     120           0 :     return cdesc;
     121           0 : }
     122             : 
     123             : bool
     124         771 : WhereQuery::StatTermParse(QueryUnit *main_query, const contrail_rapidjson::Value& where_term,
     125             :         std::string& pname, match_op& pop, GenDb::DbDataValue& pval, GenDb::DbDataValue& pval2,
     126             :         std::string& sname, match_op& sop, GenDb::DbDataValue& sval, GenDb::DbDataValue& sval2) {
     127             : 
     128         771 :     AnalyticsQuery *m_query = (AnalyticsQuery *)main_query;
     129         771 :     QE_ASSERT(m_query->is_stat_table_query(m_query->table()));
     130             : 
     131         772 :     contrail_rapidjson::Document dd;
     132         771 :     std::string srvalstr, srval2str;
     133             : 
     134         771 :     if (!where_term.HasMember(WHERE_MATCH_NAME))
     135           0 :         return false;
     136         772 :     const contrail_rapidjson::Value& name_value = where_term[WHERE_MATCH_NAME];
     137         772 :     if (!name_value.IsString()) return false;
     138         772 :     pname = name_value.GetString();
     139             : 
     140         772 :     const contrail_rapidjson::Value& prval = where_term[WHERE_MATCH_VALUE];
     141         772 :     if (!((prval.IsString() || prval.IsNumber()))) return false;
     142         772 :     contrail_rapidjson::Value prval2;
     143         772 :     if (where_term.HasMember(WHERE_MATCH_VALUE2)) {
     144         736 :         prval2.CopyFrom(where_term[WHERE_MATCH_VALUE2], dd.GetAllocator());
     145             :     }
     146             : 
     147             :     // For dynamic stat tables, convert types as per query json
     148         772 :     pval = ToDbDataValue(prval);
     149         771 :     pval2 = ToDbDataValue(prval2);
     150             : 
     151         771 :     if (!where_term.HasMember(WHERE_MATCH_OP))
     152           0 :         return false;
     153         772 :     const contrail_rapidjson::Value& op_value = where_term[WHERE_MATCH_OP];
     154         771 :     if (!op_value.IsNumber()) return false;
     155         771 :     pop = (match_op)op_value.GetInt();
     156             : 
     157         771 :     QE_TRACE(DEBUG, "StatTable Where Term Prefix " << pname << " val " << ToString(prval) 
     158             :             << " val2 " << ToString(prval2) << " op " << pop);
     159             : 
     160         772 :     sname = std::string(); 
     161         772 :     sop = (match_op)0;
     162         772 :     if (where_term.HasMember(WHERE_MATCH_SUFFIX)) {
     163         736 :         const contrail_rapidjson::Value& suffix = where_term[WHERE_MATCH_SUFFIX];
     164         736 :         if (suffix.IsObject()) {
     165             :             // For prefix-suffix where terms, prefix operator MUST be "EQUAL"
     166         252 :             if (pop != EQUAL) return false;
     167             : 
     168             :             // For prefix-suffix where terms, prefix value2 MUST be Null
     169         252 :             if (!prval2.IsNull()) return false;
     170             : 
     171         252 :             if (!suffix.HasMember(WHERE_MATCH_VALUE))
     172           0 :                 return false;
     173             :             const contrail_rapidjson::Value& svalue_value =
     174         252 :                 suffix[WHERE_MATCH_VALUE];
     175         252 :             if (!((svalue_value.IsString() || svalue_value.IsNumber()))) return false;
     176         252 :             srvalstr = ToString(svalue_value);
     177             :             // For dynamic stat tables, convert types as per query json
     178         252 :             sval = ToDbDataValue(svalue_value);
     179             : 
     180         252 :             contrail_rapidjson::Value svalue2_value;
     181         252 :             if (suffix.HasMember(WHERE_MATCH_VALUE2)) {
     182         252 :                 svalue2_value.CopyFrom(suffix[WHERE_MATCH_VALUE2],
     183             :                                        dd.GetAllocator());
     184             :             }
     185         252 :             srval2str = ToString(svalue2_value);
     186             :             // For dynamic stat tables, convert types as per query json
     187         252 :             sval2 = ToDbDataValue(svalue2_value);
     188             : 
     189         252 :             if (!suffix.HasMember(WHERE_MATCH_OP))
     190           0 :                 return false;
     191             :             const contrail_rapidjson::Value& sop_value =
     192         252 :                 suffix[WHERE_MATCH_OP];
     193         252 :             if (!sop_value.IsNumber()) return false;
     194         252 :             sop = (match_op)sop_value.GetInt();
     195             : 
     196         252 :             if (!suffix.HasMember(WHERE_MATCH_NAME))
     197           0 :                 return false;
     198             :             const contrail_rapidjson::Value& sname_value =
     199         252 :                 suffix[WHERE_MATCH_NAME];
     200         252 :             if (!sname_value.IsString()) return false;
     201         252 :             sname = sname_value.GetString();
     202         252 :         }
     203         736 :         QE_TRACE(DEBUG, "StatTable Where Term Suffix" << sname << " val " <<
     204             :                  srvalstr << " val2 " << srval2str << " op " << sop);
     205             :     }
     206             : 
     207         772 :     StatsQuery::column_t cdesc;
     208         772 :     cdesc.datatype = QEOpServerProxy::BLANK;
     209         772 :     std::map<std::string, StatsQuery::column_t> table_schema;
     210         772 :     if (m_query->stats().is_stat_table_static()) {
     211             :         // For static tables, check that prefix is valid and convert types as per schema
     212         467 :         cdesc = m_query->stats().get_column_desc(pname);
     213             :     } else {
     214             :         // Get the stable schema from query if sent
     215         305 :         AnalyticsQuery *aQuery = (AnalyticsQuery *)m_query;
     216         305 :         std::map<std::string, std::string>::iterator iter, iter2;
     217         305 :         iter = aQuery->json_api_data_.find(QUERY_TABLE_SCHEMA);
     218         305 :         if (iter != aQuery->json_api_data_.end()) {
     219         305 :             contrail_rapidjson::Document d;
     220         305 :             std::string json_string = "{ \"schema\" : " + iter->second + " }";
     221         305 :             d.Parse<0>(const_cast<char *>(json_string.c_str()));
     222         305 :             const contrail_rapidjson::Value& json_schema = d["schema"];
     223             :             // If schema is not passed, proceed without suffix information
     224         305 :             if (json_schema.Size() == 0) {
     225         305 :                 return true;
     226             :             }
     227           0 :             for (contrail_rapidjson::SizeType j = 0; j<json_schema.Size(); j++) {
     228           0 :                 if (!(json_schema[j].HasMember(WHERE_MATCH_NAME) &&
     229           0 :                       json_schema[j].HasMember(QUERY_TABLE_SCHEMA_DATATYPE) &&
     230           0 :                       json_schema[j].HasMember(QUERY_TABLE_SCHEMA_INDEX) &&
     231           0 :                       json_schema[j].HasMember(QUERY_TABLE_SCHEMA_SUFFIXES)))
     232           0 :                     return false;
     233           0 :                 const contrail_rapidjson::Value& name = json_schema[j][WHERE_MATCH_NAME];
     234             :                 const contrail_rapidjson::Value&  datatype =
     235           0 :                         json_schema[j][QUERY_TABLE_SCHEMA_DATATYPE];
     236             :                 const contrail_rapidjson::Value& index =
     237           0 :                         json_schema[j][QUERY_TABLE_SCHEMA_INDEX];
     238             :                 const contrail_rapidjson::Value& suffixes =
     239           0 :                         json_schema[j][QUERY_TABLE_SCHEMA_SUFFIXES];
     240           0 :                 StatsQuery::column_t cdesc;
     241           0 :                 std::string vstr = datatype.GetString();
     242           0 :                 cdesc.datatype = ToDbDataType(vstr);
     243           0 :                 cdesc.index = index.GetBool()? true : false;
     244             : 
     245           0 :                 if (suffixes.IsArray() && suffixes.Size() > 0) {
     246           0 :                     for (contrail_rapidjson::SizeType k = 0; k<suffixes.Size(); k++) {
     247           0 :                         const contrail_rapidjson::Value& suffix_name = suffixes[k];
     248           0 :                         cdesc.suffixes.insert(suffix_name.GetString());
     249             :                     }
     250             :                 }
     251           0 :                 table_schema[name.GetString()] = cdesc;
     252           0 :             }
     253         610 :         }
     254           0 :         cdesc = get_column_desc(table_schema, pname);
     255             :     }
     256             : 
     257         466 :     if (cdesc.datatype == QEOpServerProxy::BLANK) return false;
     258         466 :     if (!cdesc.index) return false;
     259         466 :     if (cdesc.datatype == QEOpServerProxy::LIST && pop != CONTAINS) return false;
     260             : 
     261         466 :     QE_TRACE(DEBUG, "StatTable Where prefix Schema match " << cdesc.datatype);
     262             :     // Now fill in the prefix value and value2 based on types in schema
     263         467 :     std::string vstr = ToString(prval);
     264         467 :     pval = ToDbDataValue(vstr, cdesc.datatype);
     265         467 :     if (!prval2.IsNull()) {
     266           0 :         std::string vstr = ToString(prval2);
     267           0 :         pval2 = ToDbDataValue(vstr, cdesc.datatype);
     268           0 :     }
     269             : 
     270         467 :     if (cdesc.suffixes.empty()) {
     271             :         // We need to use a onetag cf as the index
     272          36 :         if (!sname.empty()) return false;
     273          36 :         if (sop) return false;
     274          36 :         if (!srvalstr.empty()) return false;
     275          36 :         if (!srval2str.empty()) return false;
     276             :     } else {
     277             :         // We will need to use a twotag cf as the index
     278         431 :         if (sname.empty()) {
     279             :             // Where Query did not specify a suffix. Insert a NULL suffix
     280         178 :             sname = *(cdesc.suffixes.begin());
     281             : 
     282             :             // The suffix attribute MUST exist in the schema
     283         179 :             StatsQuery::column_t cdesc2;
     284         179 :             if (m_query->stats().is_stat_table_static()) {
     285         179 :                 cdesc2 = m_query->stats().get_column_desc(sname);
     286             :             } else {
     287           0 :                 cdesc2 = get_column_desc(table_schema, sname);;
     288             :             }
     289             :                 
     290         179 :             if (cdesc2.datatype == QEOpServerProxy::STRING) {
     291         179 :                 sval = std::string("");
     292           0 :             } else if (cdesc2.datatype == QEOpServerProxy::UINT64){
     293           0 :                 sval = (uint64_t) 0;
     294             :             } else {
     295           0 :                 QE_ASSERT(0);
     296             :             }
     297         178 :             QE_TRACE(DEBUG, "StatTable Where Suffix creation of " << sname);
     298         179 :         } else {
     299             :             // Where query specified a suffix. Check that it is valid
     300         252 :             if (cdesc.suffixes.find(sname)==cdesc.suffixes.end()) return false;
     301             : 
     302             :             // The suffix attribute MUST exist in the schema
     303         252 :             StatsQuery::column_t cdesc2;
     304         252 :             if (m_query->stats().is_stat_table_static()) {
     305         252 :                 cdesc2 = m_query->stats().get_column_desc(sname);
     306             :             } else {
     307           0 :                 cdesc2 = get_column_desc(table_schema, sname);;
     308             :             }
     309         252 :             QE_ASSERT ((cdesc2.datatype == QEOpServerProxy::STRING) ||
     310             :             (cdesc2.datatype == QEOpServerProxy::UINT64));
     311             : 
     312             :             // Now fill in the suffix value and value2 based on types in schema
     313         252 :             sval = ToDbDataValue(srvalstr, cdesc2.datatype);
     314         252 :             if (!srval2str.empty()) {
     315           0 :                 sval2 = ToDbDataValue(srval2str, cdesc2.datatype);
     316             :             }
     317         252 :             QE_TRACE(DEBUG, "StatTable Where Suffix match of " << cdesc2.datatype);
     318         252 :         }
     319             :     }
     320             : 
     321         467 :     return true;
     322         772 : }
     323             : 
     324           0 : static bool StatSlicer(DbQueryUnit *db_query, match_op op,
     325             :         const GenDb::DbDataValue& val, const GenDb::DbDataValue& val2) {
     326           0 :     if (val.which() == GenDb::DB_VALUE_STRING) {
     327           0 :         if (!((op == EQUAL) || (op == PREFIX))) return false;
     328             :     } else {
     329           0 :         if (!((op == EQUAL) || (op == IN_RANGE))) return false;
     330             :     }
     331           0 :     db_query->cr.start_.push_back(val);
     332           0 :     if (op == PREFIX) {
     333           0 :         std::string str_smpl2(boost::get<std::string>(val) + "\x7f");
     334           0 :         db_query->cr.finish_.push_back(str_smpl2);
     335           0 :     } else if (op == IN_RANGE) {
     336           0 :         db_query->cr.finish_.push_back(val2);
     337             :     } else {
     338           0 :         db_query->cr.finish_.push_back(val);
     339             :     }
     340           0 :     return true;
     341             : }
     342             : 
     343           0 : bool WhereQuery::StatTermProcess(const contrail_rapidjson::Value& where_term,
     344             :         QueryUnit* and_node, QueryUnit *main_query) {
     345             : 
     346           0 :     AnalyticsQuery *m_query = (AnalyticsQuery *)main_query;
     347           0 :     std::string pname,sname,cfname;
     348             :     match_op pop,sop;
     349           0 :     GenDb::DbDataValue pval, pval2, sval, sval2;
     350             : 
     351           0 :     bool res = StatTermParse(main_query, where_term,
     352             :             pname, pop, pval, pval2, sname, sop, sval, sval2);
     353             : 
     354           0 :     if (!res) return false;
     355             : 
     356           0 :     bool twotag = true;
     357           0 :     if ((sop==(match_op)0)&&(sname.empty())) {
     358             :         // We need to look at the single-tag stat index tables
     359           0 :         twotag = false;
     360           0 :         if (pval.which() == GenDb::DB_VALUE_STRING) {
     361           0 :             cfname = g_viz_constants.STATS_TABLE_BY_STR_TAG;
     362           0 :         } else if (pval.which() == GenDb::DB_VALUE_UINT64) {
     363           0 :             cfname = g_viz_constants.STATS_TABLE_BY_U64_TAG;
     364           0 :         } else if (pval.which() == GenDb::DB_VALUE_DOUBLE) {
     365           0 :             cfname = g_viz_constants.STATS_TABLE_BY_DBL_TAG;
     366             :         } else {
     367           0 :             QE_TRACE(DEBUG, "For single-tag index table, wrong WHERE type " <<
     368             :                     pval.which());
     369           0 :             return false;
     370             :         }
     371             :     } else {
     372           0 :         if (pval.which() == GenDb::DB_VALUE_STRING) {
     373           0 :             if (sval.which() == GenDb::DB_VALUE_STRING) {
     374           0 :                 cfname = g_viz_constants.STATS_TABLE_BY_STR_STR_TAG;
     375           0 :             } else if (sval.which() == GenDb::DB_VALUE_UINT64) {
     376           0 :                 cfname = g_viz_constants.STATS_TABLE_BY_STR_U64_TAG;
     377             :             } else {
     378           0 :                 QE_TRACE(DEBUG, "For two-tag STR table, wrong WHERE suffix type " <<
     379             :                         sval.which());
     380           0 :                 return false;
     381             :             }
     382           0 :         } else if (pval.which() == GenDb::DB_VALUE_UINT64) {
     383           0 :             if (sval.which() == GenDb::DB_VALUE_STRING) {
     384           0 :                 cfname = g_viz_constants.STATS_TABLE_BY_U64_STR_TAG;
     385           0 :             } else if (sval.which() == GenDb::DB_VALUE_UINT64) {
     386           0 :                 cfname = g_viz_constants.STATS_TABLE_BY_U64_U64_TAG;
     387             :             } else {
     388           0 :                 QE_TRACE(DEBUG, "For two-tag U64 table, wrong WHERE suffix type " <<
     389             :                         sval.which());
     390           0 :                 return false;
     391             :             }
     392             :         } else {
     393           0 :             QE_TRACE(DEBUG, "For two-tag index table, wrong WHERE prefix type " <<
     394             :                     pval.which());
     395           0 :             return false;
     396             :         }
     397             :     }
     398           0 :     QE_TRACE(DEBUG, "Query Stat Index " << cfname <<  " twotag " << twotag);
     399           0 :     DbQueryUnit *db_query = new DbQueryUnit(and_node, main_query);
     400             : 
     401           0 :     db_query->t_only_col = false;
     402           0 :     db_query->t_only_row = false;
     403           0 :     db_query->cfname = cfname;
     404             : 
     405             :     size_t tpos,apos;
     406           0 :     std::string tname = m_query->table();
     407           0 :     tpos = tname.find('.');
     408           0 :     apos = tname.find('.', tpos+1);
     409             : 
     410           0 :     std::string tstr = tname.substr(tpos+1, apos-tpos-1);
     411           0 :     std::string astr = tname.substr(apos+1, std::string::npos);
     412             : 
     413           0 :     db_query->row_key_suffix.push_back(tstr);
     414           0 :     db_query->row_key_suffix.push_back(astr);
     415           0 :     db_query->row_key_suffix.push_back(pname);
     416             : 
     417           0 :     if (twotag) {
     418           0 :         db_query->row_key_suffix.push_back(sname);
     419           0 :         if (sop==(match_op)0) {
     420             :             // We will only be using the prefix value for querying
     421           0 :             if (!StatSlicer(db_query, pop, pval, pval2)) return false;
     422             : 
     423           0 :             if (sval.which() == GenDb::DB_VALUE_STRING) {
     424           0 :                 db_query->cr.start_.push_back(std::string("\x00"));
     425           0 :                 db_query->cr.finish_.push_back(std::string("\x7f"));
     426             :             } else {
     427           0 :                 db_query->cr.start_.push_back((uint64_t)0);
     428           0 :                 db_query->cr.finish_.push_back((uint64_t)0xffffffffffffffff);
     429             :             }
     430             :         } else {
     431             :             // We will be using the suffix value for querying
     432           0 :             if (!(pop == EQUAL)) return false;
     433           0 :             db_query->cr.start_.push_back(pval);
     434           0 :             db_query->cr.finish_.push_back(pval);
     435             : 
     436           0 :             if (!StatSlicer(db_query, sop, sval, sval2)) return false;
     437             :         }
     438             : 
     439             :     } else {
     440           0 :         if (!StatSlicer(db_query, pop, pval, pval2)) return false;
     441             :     }
     442             : 
     443           0 :     return true;
     444           0 : }
     445             : 
     446         699 : void GetStatTableAttrName(const std::string& tname, std::string *tstr, std::string *astr) {
     447             :     size_t tpos,apos;
     448         699 :     tpos = tname.find('.');
     449         700 :     apos = tname.find('.', tpos+1);
     450             : 
     451         700 :     *tstr = tname.substr(tpos+1, apos-tpos-1);
     452         700 :     *astr = tname.substr(apos+1, std::string::npos);
     453         700 : }
     454             : 
     455         699 : void populate_stats_where_vec_list(std::vector<GenDb::WhereIndexInfoVec> *where_vec_list,
     456             :     const GenDb::WhereIndexInfoVec& where_vec_stats,
     457             :     const std::vector<GenDb::WhereIndexInfoVec>& where_vec_tags_stats) {
     458         699 :     uint16_t max_tags(0);
     459        6292 :     BOOST_FOREACH(const GenDb::WhereIndexInfoVec& where_vec, where_vec_tags_stats) {
     460        2798 :         if (max_tags < where_vec.size()) {
     461         395 :             max_tags = where_vec.size();
     462             :         }
     463             :     }
     464         699 :     if (!max_tags) {
     465         305 :         where_vec_list->push_back(where_vec_stats);
     466         305 :         return;
     467             :     } else {
     468         788 :         for (size_t i = 0; i < max_tags; ++i) {
     469         394 :             GenDb::WhereIndexInfoVec where_vec(where_vec_stats);
     470        3546 :             BOOST_FOREACH(const GenDb::WhereIndexInfoVec& where_vec_tags, where_vec_tags_stats) {
     471        1576 :                 if (i < where_vec_tags.size()) {
     472         448 :                     where_vec.push_back(where_vec_tags[i]);
     473             :                 }
     474             :             }
     475         394 :             where_vec_list->push_back(where_vec);
     476         394 :         }
     477             :     }
     478             : }
     479             : 
     480         449 : static inline unsigned int djb_hash (const char *str, size_t len) {
     481         449 :     unsigned int hash = 5381;
     482        3547 :     for (size_t i = 0 ; i < len ; i++)
     483        3098 :         hash = ((hash << 5) + hash) + str[i];
     484         449 :     return hash;
     485             : }
     486             : 
     487        1987 : WhereQuery::WhereQuery(const std::string& where_json_string, int session_type,
     488        1987 :         int is_si, int direction, int32_t or_number, QueryUnit *main_query):
     489        1986 :     QueryUnit(main_query, main_query), direction_ing(direction),
     490        1987 :     json_string_(where_json_string), wterms_(0) {
     491        1984 :     AnalyticsQuery *m_query = (AnalyticsQuery *)main_query;
     492        1984 :     where_result_.reset(new std::vector<query_result_unit_t>);
     493        1984 :     if (where_json_string == std::string(""))
     494             :     {
     495         348 :         if (or_number == -1) wterms_ = 1;
     496         348 :         DbQueryUnit *db_query = new DbQueryUnit(this, main_query);
     497             : 
     498             :         //TBD not sure if this will work for Message table or Object Log
     499         348 :         if (m_query->is_message_table_query()) {
     500          77 :             db_query->cfname = g_viz_constants.COLLECTOR_GLOBAL_TABLE;
     501          77 :             db_query->t_only_col = true;
     502          77 :             db_query->t_only_row = true;
     503         271 :         } else if 
     504         271 :         ((m_query->table() == g_viz_constants.FLOW_TABLE)
     505         271 :         || (m_query->table() == g_viz_constants.FLOW_SERIES_TABLE)) {
     506           0 :             DbQueryUnit *db_query_client = new DbQueryUnit(this, main_query);
     507             :             {
     508           0 :                 db_query->cfname = g_viz_constants.SESSION_TABLE;
     509           0 :                 db_query->row_key_suffix.push_back((uint8_t)is_si);
     510           0 :                 db_query->row_key_suffix.push_back(
     511           0 :                                 (uint8_t)SessionType::SERVER_SESSION);
     512             :                 // starting value for clustering key range
     513           0 :                 db_query->cr.start_.push_back((uint16_t)0);
     514             : 
     515             :                 // ending value for clustering key range
     516           0 :                 db_query->cr.finish_.push_back((uint16_t)0xffff);
     517           0 :                 db_query->cr.finish_.push_back((uint16_t)0xffff);
     518             :             }
     519             :             {
     520           0 :                 db_query_client->cfname = g_viz_constants.SESSION_TABLE;
     521           0 :                 db_query_client->row_key_suffix.push_back((uint8_t)is_si);
     522           0 :                 db_query_client->row_key_suffix.push_back(
     523           0 :                                 (uint8_t)SessionType::CLIENT_SESSION);
     524             :                 // starting value for clustering key range
     525           0 :                 db_query_client->cr.start_.push_back((uint16_t)0);
     526             : 
     527             :                 // ending value for clustering key range
     528           0 :                 db_query_client->cr.finish_.push_back((uint16_t)0xffff);
     529           0 :                 db_query_client->cr.finish_.push_back((uint16_t)0xffff);
     530             : 
     531             :             }
     532         271 :         } else if (m_query->is_session_query(m_query->table())) {
     533             : 
     534         215 :             db_query->row_key_suffix.push_back((uint8_t)is_si);
     535         214 :             db_query->row_key_suffix.push_back((uint8_t)session_type);
     536         214 :             db_query->cfname = g_viz_constants.SESSION_TABLE;
     537             : 
     538             :             // starting value for clustering key range
     539         215 :             db_query->cr.start_.push_back((uint16_t)0);
     540             : 
     541             :             // ending value for clustering key range
     542         215 :             db_query->cr.finish_.push_back((uint16_t)0xffff);
     543         215 :             db_query->cr.finish_.push_back((uint16_t)0xffff);
     544             : 
     545          57 :         } else if (m_query->is_object_table_query(m_query->table())) {
     546          55 :             db_query->cfname = g_viz_constants.COLLECTOR_GLOBAL_TABLE;
     547          55 :             db_query->t_only_col = true;
     548          55 :             db_query->t_only_row = true;
     549          55 :             bool object_id_specified = false;
     550             : 
     551             :             // handling where * for object table is similar to 
     552             :             // and subset of object-id=X handling
     553          55 :             handle_object_type_value(m_query, db_query, object_id_specified);
     554          55 :             QE_TRACE(DEBUG, "where * for object table" << m_query->table());
     555             : 
     556             :         }
     557             :         // This is "where *" query, no need to do JSON parsing
     558         348 :         return;
     559             :     }
     560             : 
     561             :     // Do JSON parsing
     562        1637 :     contrail_rapidjson::Document d;
     563        1637 :     std::string json_string = "{ \"where\" : " + 
     564        1635 :         where_json_string + " }";
     565             : 
     566        1638 :     QE_TRACE(DEBUG, "where query:" << json_string);
     567        1638 :     d.Parse<0>(const_cast<char *>(json_string.c_str()));
     568        1637 :     const contrail_rapidjson::Value& json_or_list = d["where"]; 
     569        1635 :     QE_PARSE_ERROR(json_or_list.IsArray());
     570             : 
     571        1635 :     QE_TRACE(DEBUG, "number of OR terms in where :" << json_or_list.Size());
     572             : 
     573        1638 :     if (or_number == -1) wterms_ = json_or_list.Size();
     574             : 
     575        3450 :     for (contrail_rapidjson::SizeType i = 0; i < json_or_list.Size(); i++) 
     576             :     {
     577        1815 :         const contrail_rapidjson::Value& json_or_node = json_or_list[i];
     578        1815 :         QE_PARSE_ERROR(json_or_list[i].IsArray());
     579        1815 :         QE_INVALIDARG_ERROR(json_or_list[i].Size() != 0);
     580             : 
     581             :         // If the or_number is -1, we are in query prepare.
     582             :         // We have no intention of actually executing the query.
     583             :         // But, we parse everything to catch errors.
     584        1815 :         if (or_number != -1) {
     585             :             // Only execute the requested OR term
     586         854 :             if (or_number != (int)i) continue;
     587             :         }
     588             : 
     589        1720 :         QE_TRACE(DEBUG, "number of AND term in " << (i+1) << 
     590             :                 "th OR term is " <<json_or_node.Size());
     591             : 
     592             :         // these are needed because flow index table queries
     593             :         // span multiple WHERE match component
     594        1720 :         bool vr_match = false; GenDb::DbDataValue vr, vr2; int vr_op = 0;
     595        1720 :         bool svn_match = false; GenDb::DbDataValue svn, svn2; int svn_op = 0;
     596        1719 :         bool dvn_match = false; GenDb::DbDataValue dvn, dvn2; int dvn_op = 0;
     597        1719 :         bool sip_match = false; GenDb::DbDataValue sip, sip2; int sip_op = 0;
     598        1719 :         bool dip_match = false; GenDb::DbDataValue dip, dip2; int dip_op = 0;
     599        1719 :         bool proto_match = false; GenDb::DbDataValue proto, proto2; int proto_op = 0;
     600        1719 :         bool sport_match = false; GenDb::DbDataValue sport, sport2; int sport_op = 0;
     601        1719 :         bool dport_match = false; GenDb::DbDataValue dport, dport2; int dport_op = 0;
     602        1720 :         bool name_match = false; GenDb::DbDataValue sname_val; int name_op = 0;
     603        1720 :         bool object_id_specified = false;
     604        1720 :         bool isSession = m_query->is_session_query(m_query->table());
     605        1719 :         GenDb::WhereIndexInfoVec labels_vec, remote_labels_vec;
     606        1719 :         GenDb::WhereIndexInfoVec custom_tags_vec, remote_custom_tags_vec;
     607        1719 :         GenDb::WhereIndexInfoVec where_vec_session_rest, where_vec_stats;
     608        1720 :         std::vector<GenDb::WhereIndexInfoVec> where_vec_tags_stats(4);
     609        1719 :         std::vector<filter_match_t> filter_and;
     610             : 
     611             :         // All where parameters in subquery are AND.
     612             :         // So they are in the same msg_table_db_query object.
     613             :         // If there are no where-params, this would result in no-op.
     614        1719 :         DbQueryUnit *msg_table_db_query = NULL;
     615        2908 :         if (m_query->is_message_table_query() ||
     616        2908 :             m_query->is_object_table_query(m_query->table())) {
     617             : 
     618         869 :             msg_table_db_query = new DbQueryUnit(this, main_query);
     619         870 :             msg_table_db_query->cfname = g_viz_constants.COLLECTOR_GLOBAL_TABLE;
     620         870 :             msg_table_db_query->t_only_row = true;
     621         870 :             msg_table_db_query->t_only_col = true;
     622             :         }
     623             : 
     624        3842 :         for (contrail_rapidjson::SizeType j = 0; j < json_or_node.Size(); j++)
     625             :         {
     626        2123 :             QE_PARSE_ERROR((json_or_node[j].HasMember(WHERE_MATCH_NAME) &&
     627             :                 json_or_node[j].HasMember(WHERE_MATCH_VALUE) &&
     628             :                 json_or_node[j].HasMember(WHERE_MATCH_OP)));
     629             :             const contrail_rapidjson::Value& name_value =
     630        2122 :                 json_or_node[j][WHERE_MATCH_NAME];
     631             :             const contrail_rapidjson::Value&  value_value =
     632        2121 :                 json_or_node[j][WHERE_MATCH_VALUE];
     633             :             const contrail_rapidjson::Value& op_value =
     634        2122 :                 json_or_node[j][WHERE_MATCH_OP];
     635             : 
     636             :             // do some validation checks
     637        2121 :             QE_INVALIDARG_ERROR(name_value.IsString());
     638        2121 :             QE_INVALIDARG_ERROR
     639             :                 ((value_value.IsString() || value_value.IsNumber()));
     640        2121 :             QE_INVALIDARG_ERROR(op_value.IsNumber());
     641             : 
     642        2121 :             std::string name = name_value.GetString();
     643        2121 :             QE_INVALIDARG_ERROR(m_query->is_valid_where_field(name));
     644             : 
     645             :             // extract value after type conversion
     646        2122 :             std::string value;
     647             :             {
     648        2122 :                 if (value_value.IsString())
     649             :                 {
     650        1958 :                     value = value_value.GetString();
     651         164 :                 } else if (value_value.IsInt()){
     652             :                     int int_value;
     653         164 :                     std::ostringstream convert;
     654         164 :                     int_value = value_value.GetInt();
     655         164 :                     convert << int_value;
     656         164 :                     value = convert.str();
     657         164 :                 } else if (value_value.IsUint()) {
     658             :                     uint32_t uint_value;
     659           0 :                     std::ostringstream convert;
     660           0 :                     uint_value = value_value.GetUint();
     661           0 :                     convert << uint_value;
     662           0 :                     value = convert.str();
     663           0 :                 } else if (value_value.IsDouble()) {
     664             :                     double dbl_value;
     665           0 :                     std::ostringstream convert;
     666           0 :                     dbl_value = value_value.GetDouble();
     667           0 :                     convert << dbl_value;
     668           0 :                     value = convert.str();
     669           0 :                 }
     670             :             }
     671             : 
     672        2122 :             match_op op = (match_op)op_value.GetInt();
     673             : 
     674        2122 :             name = get_column_name(name); // Get actual Cassandra name
     675             :            
     676             :             // this is for range queries
     677        2121 :             std::string value2;
     678        2121 :             if (op == IN_RANGE)
     679             :             {
     680           0 :                 QE_PARSE_ERROR(json_or_node[j].HasMember(WHERE_MATCH_VALUE2));
     681             :                 const contrail_rapidjson::Value&  value_value2 =
     682           0 :                 json_or_node[j][WHERE_MATCH_VALUE2];
     683             : 
     684             :                 // extract value2 after type conversion
     685           0 :                 if (value_value2.IsString())
     686             :                 {
     687           0 :                     value2 = value_value2.GetString();
     688           0 :                 } else if (value_value2.IsInt()){
     689             :                     int int_value;
     690           0 :                     std::ostringstream convert;
     691           0 :                     int_value = value_value2.GetInt();
     692           0 :                     convert << int_value;
     693           0 :                     value2 = convert.str();
     694           0 :                 } else if (value_value2.IsUint()) {
     695             :                     uint32_t uint_value;
     696           0 :                     std::ostringstream convert;
     697           0 :                     uint_value = value_value2.GetUint();
     698           0 :                     convert << uint_value;
     699           0 :                     value2 = convert.str();
     700           0 :                 } else if (value_value2.IsDouble()) {
     701             :                     double dbl_value;
     702           0 :                     std::ostringstream convert;
     703           0 :                     dbl_value = value_value2.GetDouble();
     704           0 :                     convert << dbl_value;
     705           0 :                     value2 = convert.str();
     706           0 :                 }
     707             :             }
     708             : 
     709        2121 :             bool isStat = m_query->is_stat_table_query(m_query->table());
     710        2123 :             if ((name == g_viz_constants.SOURCE) && (!isStat))
     711             :             {
     712         299 :                 QE_INVALIDARG_ERROR((op == EQUAL) || (op == PREFIX));
     713         299 :                 QE_INVALIDARG_ERROR(populate_where_vec(m_query,
     714             :                     &(msg_table_db_query->where_vec), name,
     715             :                     get_gendb_op_from_op(op), value));
     716         297 :                 QE_TRACE(DEBUG, "where match term for source " << value);
     717             :             }
     718             : 
     719             : 
     720        2122 :             if ((name == g_viz_constants.MODULE) && (!isStat))
     721             :             {
     722         365 :                 QE_INVALIDARG_ERROR((op == EQUAL) || (op == PREFIX));
     723         365 :                 QE_INVALIDARG_ERROR(populate_where_vec(m_query, 
     724             :                     &(msg_table_db_query->where_vec), name,
     725             :                     get_gendb_op_from_op(op), value));
     726             : 
     727             :                 // dont filter query engine logs if the query is about query
     728             :                 // engine
     729         367 :                 if (value == m_query->sandesh_moduleid)
     730         180 :                     m_query->filter_qe_logs = false;
     731             : 
     732         367 :                 QE_TRACE(DEBUG, "where match term for module " << value);
     733             :             }
     734             : 
     735        2124 :             if ((name == g_viz_constants.MESSAGE_TYPE) && (!isStat))
     736             :             {
     737          34 :                 QE_INVALIDARG_ERROR((op == EQUAL) || (op == PREFIX));
     738          34 :                 QE_INVALIDARG_ERROR(populate_where_vec(m_query,
     739             :                     &(msg_table_db_query->where_vec), name,
     740             :                     get_gendb_op_from_op(op), value));
     741          34 :                 QE_TRACE(DEBUG, "where match term for msg-type " << value);
     742             :             }
     743             : 
     744        2124 :             if (name == OBJECTID)
     745             :             {
     746         340 :                 QE_INVALIDARG_ERROR((op == EQUAL) || (op == PREFIX));
     747             : 
     748             :                 // Object-id is saved in column[6..11] in MessageTablev2 in the format
     749             :                 // T2:ObjectType:ObjectId
     750             :                 // T2: is prefixed later, we need to prefix ObjectType: here.
     751         680 :                 std::string val = m_query->table() + ":" + value;
     752         340 :                 std::string col_name = g_viz_constants.OBJECT_TYPE_NAME1;
     753         340 :                 QE_INVALIDARG_ERROR(populate_where_vec(m_query,
     754             :                     &(msg_table_db_query->where_vec),
     755             :                     col_name, get_gendb_op_from_op(op), val));
     756         340 :                 object_id_specified = true;
     757         340 :                 QE_TRACE(DEBUG, "where match term for objectid " << value);
     758         340 :             }
     759             : 
     760        2123 :             if (m_query->is_session_query(m_query->table())) {
     761         264 :                 if (name == g_viz_constants.SessionRecordNames[
     762         264 :                                 SessionRecordFields::SESSION_PROTOCOL])
     763             :                 {
     764          58 :                     proto_match = true; proto_op = op;
     765             :                     uint16_t proto_value, proto_value2;
     766          58 :                     std::istringstream(value) >> proto_value;
     767          58 :                     proto = proto_value;
     768          58 :                     if (proto_op == IN_RANGE)
     769             :                     {
     770           0 :                         std::istringstream(value2) >> proto_value2;
     771           0 :                         proto2 = proto_value2;
     772             :                     } else {
     773          58 :                         QE_INVALIDARG_ERROR(proto_op == EQUAL);
     774             :                     }
     775          58 :                     QE_TRACE(DEBUG, "where match term for proto_value " << value);
     776             :                 }
     777         206 :                 else if (name == g_viz_constants.SessionRecordNames[
     778         206 :                                 SessionRecordFields::SESSION_SPORT])
     779             :                 {
     780          58 :                     sport_match = true; sport_op = op;
     781             :                     uint16_t sport_value, sport_value2;
     782          58 :                     std::istringstream(value) >> sport_value;
     783          58 :                     sport = sport_value;
     784          58 :                     if (sport_op == IN_RANGE)
     785             :                     {
     786           0 :                         std::istringstream(value2) >> sport_value2;
     787           0 :                         sport2 = sport_value2;
     788             :                     } else {
     789          58 :                         QE_INVALIDARG_ERROR(sport_op == EQUAL);
     790             :                     }
     791          58 :                     QE_TRACE(DEBUG, "where match term for sport_value " << value);
     792         148 :                 } else if (name == g_viz_constants.SessionRecordNames[
     793         148 :                                  SessionRecordFields::SESSION_LABELS]) {
     794          34 :                     QE_INVALIDARG_ERROR(op == CONTAINS);
     795          34 :                     value = "%" + value;
     796          34 :                     QE_INVALIDARG_ERROR(populate_where_vec(m_query,
     797             :                         &labels_vec, name, GenDb::Op::LIKE, value));
     798         114 :                 } else if (name == g_viz_constants.SessionRecordNames[
     799         114 :                                  SessionRecordFields::SESSION_REMOTE_LABELS]) {
     800          22 :                     QE_INVALIDARG_ERROR(op == CONTAINS);
     801          22 :                     value = "%" + value;
     802          22 :                     QE_INVALIDARG_ERROR(populate_where_vec(m_query,
     803             :                         &remote_labels_vec, name, GenDb::Op::LIKE, value));
     804          92 :                 } else if (name == g_viz_constants.SessionRecordNames[
     805          92 :                                  SessionRecordFields::SESSION_CUSTOM_TAGS]) {
     806          10 :                     QE_INVALIDARG_ERROR(op == CONTAINS);
     807          10 :                     value = "%" + value;
     808          10 :                     QE_INVALIDARG_ERROR(populate_where_vec(m_query,
     809             :                         &custom_tags_vec, name, GenDb::Op::LIKE, value));
     810          82 :                 } else if (name == g_viz_constants.SessionRecordNames[
     811          82 :                                  SessionRecordFields::SESSION_REMOTE_CUSTOM_TAGS]) {
     812          10 :                     QE_INVALIDARG_ERROR(op == CONTAINS);
     813          10 :                     value = "%" + value;
     814          10 :                     QE_INVALIDARG_ERROR(populate_where_vec(m_query,
     815             :                         &remote_custom_tags_vec, name, GenDb::Op::LIKE, value));
     816             :                 } else {
     817             :                     GenDb::Op::type comparator;
     818          72 :                     if (op == PREFIX) {
     819           0 :                         comparator = GenDb::Op::LIKE;
     820             :                     } else {
     821          72 :                         comparator = GenDb::Op::EQ;
     822             :                     }
     823          72 :                     QE_INVALIDARG_ERROR(populate_where_vec(m_query,
     824             :                         &where_vec_session_rest, name, comparator, value));
     825             :                 }
     826        1858 :             } else if (m_query->is_flow_query(m_query->table())){
     827          48 :                 if (name == g_viz_constants.FlowRecordNames[
     828          48 :                                 FlowRecordFields::FLOWREC_PROTOCOL])
     829             :                 {
     830          12 :                     proto_match = true; proto_op = op;
     831             :                     uint16_t proto_value, proto_value2;
     832          12 :                     std::istringstream(value) >> proto_value;
     833          12 :                     proto = proto_value;
     834          12 :                     if (proto_op == IN_RANGE)
     835             :                     {
     836           0 :                         std::istringstream(value2) >> proto_value2;
     837           0 :                         proto2 = proto_value2;
     838             :                     } else {
     839          12 :                         QE_INVALIDARG_ERROR(proto_op == EQUAL);
     840             :                     }
     841          12 :                     QE_TRACE(DEBUG, "where match term for proto_value " << value);
     842             :                 }
     843          48 :                 if (name == g_viz_constants.FlowRecordNames[
     844          48 :                                 FlowRecordFields::FLOWREC_SOURCEVN])
     845             :                 {
     846          24 :                     svn_match = true; svn_op = op;
     847          24 :                     svn = value;
     848          24 :                     QE_INVALIDARG_ERROR((svn_op == EQUAL)||(svn_op == PREFIX));
     849             : 
     850          24 :                     QE_TRACE(DEBUG, "where match term for sourcevn " << value);
     851             :                 }
     852          48 :                 if (name == g_viz_constants.FlowRecordNames[
     853          48 :                                 FlowRecordFields::FLOWREC_DESTVN])
     854             :                 {
     855          12 :                     dvn_match = true; dvn_op = op;
     856          12 :                     dvn = value;
     857          12 :                     QE_INVALIDARG_ERROR((dvn_op == EQUAL)||(dvn_op == PREFIX));
     858             : 
     859          12 :                     QE_TRACE(DEBUG, "where match term for sourcevn " << value);
     860             :                 }
     861          48 :                 if (name == g_viz_constants.FlowRecordNames[
     862          48 :                                 FlowRecordFields::FLOWREC_SOURCEIP])
     863             :                 {
     864           0 :                     sip_match = true; sip_op = op;
     865           0 :                     sip = value;
     866           0 :                     QE_TRACE(DEBUG, "where match term for sourceip " << value);
     867           0 :                     if (sip_op == IN_RANGE)
     868             :                     {
     869           0 :                         sip2 = value2;
     870             :                     } else {
     871           0 :                         QE_INVALIDARG_ERROR(sip_op == EQUAL);
     872             :                     }
     873           0 :                     if (direction_ing == 0) {
     874           0 :                         filter_match_t filter;
     875           0 :                         filter.name = "sourceip";
     876           0 :                         filter.op = (match_op)sip_op;
     877           0 :                         filter.value = boost::get<std::string>(sip);
     878           0 :                         filter_and.push_back(filter);
     879           0 :                         additional_select_.push_back(filter.name);
     880           0 :                     }
     881             :                 }
     882          48 :                 if (name == g_viz_constants.FlowRecordNames[
     883          48 :                                 FlowRecordFields::FLOWREC_DESTIP])
     884             :                 {
     885           0 :                     dip_match = true; dip_op = op;
     886           0 :                     dip = value;
     887           0 :                     QE_TRACE(DEBUG, "where match term for destip " << value);
     888           0 :                     if (dip_op == IN_RANGE)
     889             :                     {
     890           0 :                         dip2 = value2;
     891             :                     } else {
     892           0 :                         QE_INVALIDARG_ERROR(dip_op == EQUAL);
     893             :                     }
     894           0 :                     if (direction_ing == 1) {
     895           0 :                         filter_match_t filter;
     896           0 :                         filter.name = "destip";
     897           0 :                         filter.op = (match_op)dip_op;
     898           0 :                         filter.value = boost::get<std::string>(dip);
     899           0 :                         filter_and.push_back(filter);
     900           0 :                         additional_select_.push_back(filter.name);
     901           0 :                     }
     902             :                 }
     903          48 :                 if (name == g_viz_constants.FlowRecordNames[FlowRecordFields::FLOWREC_SPORT])
     904             :                 {
     905           0 :                     sport_match = true; sport_op = op;
     906             : 
     907             :                     uint16_t sport_value;
     908           0 :                     std::istringstream(value) >> sport_value;
     909             : 
     910           0 :                     sport = sport_value;
     911           0 :                     if (sport_op == IN_RANGE)
     912             :                     {
     913             :                         uint16_t sport_value2;
     914           0 :                         std::istringstream(value2) >> sport_value2;
     915           0 :                         sport2 = sport_value2;
     916             :                     } else {
     917           0 :                         QE_INVALIDARG_ERROR(sport_op == EQUAL);
     918             :                     }
     919             : 
     920           0 :                     filter_match_t filter;
     921           0 :                     filter.name = "sport";
     922           0 :                     filter.op = (match_op)sport_op;
     923           0 :                     std::ostringstream convert;
     924           0 :                     convert << boost::get<uint16_t>(sport);
     925           0 :                     filter.value = convert.str();
     926           0 :                     filter_and.push_back(filter);
     927           0 :                     additional_select_.push_back(filter.name);
     928             : 
     929           0 :                     QE_TRACE(DEBUG, "where match term for sport " << value);
     930           0 :                 }
     931          48 :                 if (name == g_viz_constants.FlowRecordNames[FlowRecordFields::FLOWREC_DPORT])
     932             :                 {
     933           0 :                     dport_match = true; dport_op = op;
     934             : 
     935             :                     uint16_t dport_value;
     936           0 :                     std::istringstream(value) >> dport_value;
     937           0 :                     dport = dport_value;
     938           0 :                     if (dport_op == IN_RANGE)
     939             :                     {
     940             :                         uint16_t dport_value2;
     941           0 :                         std::istringstream(value2) >> dport_value2;
     942           0 :                         dport2 = dport_value2;
     943             :                     } else {
     944           0 :                         QE_INVALIDARG_ERROR(dport_op == EQUAL);
     945             :                     }
     946             : 
     947           0 :                     filter_match_t filter;
     948           0 :                     filter.name = "dport";
     949           0 :                     filter.op = (match_op)dport_op;
     950           0 :                     std::ostringstream convert;
     951           0 :                     convert << boost::get<uint16_t>(dport);
     952           0 :                     filter.value = convert.str();
     953           0 :                     filter_and.push_back(filter);
     954           0 :                     additional_select_.push_back(filter.name);
     955             : 
     956           0 :                     QE_TRACE(DEBUG, "where match term for dport " << value);
     957           0 :                 }
     958          48 :                 if (name == g_viz_constants.FlowRecordNames[FlowRecordFields::FLOWREC_VROUTER])
     959             :                 {
     960           0 :                     vr_match = true;
     961           0 :                     vr_op = op;
     962           0 :                     vr = value;
     963           0 :                     QE_INVALIDARG_ERROR((vr_op == EQUAL)||(vr_op == PREFIX));
     964             : 
     965           0 :                     QE_TRACE(DEBUG, "where match term for vrouter " << value);
     966           0 :                     filter_match_t filter;
     967           0 :                     filter.name = "vrouter";
     968           0 :                     if (vr_op != PREFIX) {
     969           0 :                         filter.op = (match_op)vr_op;
     970             :                     } else {
     971           0 :                         filter.op = REGEX_MATCH;
     972             :                     }
     973           0 :                     filter.value = boost::get<std::string>(vr);
     974           0 :                     if (filter.op == REGEX_MATCH) {
     975           0 :                         filter.match_e = regex(filter.value);
     976             :                     }
     977             :                     if (vr_match) {
     978             :                     }
     979           0 :                     filter_and.push_back(filter);
     980           0 :                     additional_select_.push_back(filter.name);
     981           0 :                 }
     982             :             }
     983        2123 :             if (isStat)
     984             :             {   
     985         772 :                 if (oldDataExists) {
     986             :                     // Call StatTermProcess to handle the query into older tables
     987           0 :                     StatTermProcess(json_or_node[j], this, main_query);
     988             :                 }
     989             : 
     990         772 :                 std::string pname, sname;
     991             :                 match_op pop,sop;
     992         772 :                 GenDb::DbDataValue pval, pval2, sval, sval2;
     993             : 
     994         771 :                 if (!StatTermParse(main_query, json_or_node[j],
     995             :                     pname, pop, pval, pval2, sname, sop, sval, sval2)) {
     996           0 :                     QE_INVALIDARG_ERROR(false);
     997             :                 }
     998             : 
     999         772 :                 if (pname == g_viz_constants.STATS_NAME_FIELD) {
    1000         575 :                     name_match = true;
    1001         575 :                     sname_val = pval;
    1002         575 :                     name_op = pop;
    1003         197 :                 } else if (pname == g_viz_constants.STATS_SOURCE_FIELD ||
    1004         394 :                     boost::algorithm::ends_with(pname, g_viz_constants.STATS_KEY_FIELD) ||
    1005         197 :                     boost::algorithm::ends_with(pname, g_viz_constants.STATS_PROXY_FIELD)) {
    1006           0 :                     if (boost::algorithm::ends_with(pname, g_viz_constants.STATS_KEY_FIELD)) {
    1007           0 :                         pname = g_viz_constants.STATS_KEY_FIELD;
    1008             :                     }
    1009           0 :                     if (boost::algorithm::ends_with(pname, g_viz_constants.STATS_PROXY_FIELD)) {
    1010           0 :                         pname = g_viz_constants.STATS_PROXY_FIELD;
    1011             :                     }
    1012           0 :                     QE_INVALIDARG_ERROR(pop == EQUAL || pop == PREFIX);
    1013             :                     GenDb::Op::type db_op;
    1014           0 :                     if (pop == EQUAL) {
    1015           0 :                         db_op = GenDb::Op::EQ;
    1016           0 :                         QE_INVALIDARG_ERROR(populate_where_vec(m_query, &where_vec_stats,
    1017             :                             pname, db_op, GenDb::DbDataValueToString(pval)));
    1018             :                     } else {
    1019           0 :                         std::string val(GenDb::DbDataValueToString(pval));
    1020           0 :                         if (!val.empty()) {
    1021           0 :                             db_op = GenDb::Op::LIKE;
    1022           0 :                             QE_INVALIDARG_ERROR(populate_where_vec(m_query, &where_vec_stats,
    1023             :                                 pname, db_op, val));
    1024             :                         }
    1025           0 :                     }
    1026             :                 } else {
    1027             :                     GenDb::Op::type db_op;
    1028         197 :                     pval = "%" + pname + "=" + GenDb::DbDataValueToString(pval);
    1029         197 :                     db_op = GenDb::Op::LIKE;
    1030         197 :                     size_t idx = djb_hash(pname.c_str(), pname.length())
    1031         197 :                         % g_viz_constants.NUM_STATS_TAGS_FIELD;
    1032         197 :                     QE_INVALIDARG_ERROR(populate_where_vec(m_query, &where_vec_tags_stats[idx],
    1033             :                         g_viz_constants.STATS_TAGS_FIELD + integerToString(idx),
    1034             :                         db_op, GenDb::DbDataValueToString(pval)));
    1035             :                 }
    1036         772 :                 if (sop != 0) {
    1037         252 :                     if (sname == g_viz_constants.STATS_NAME_FIELD) {
    1038           0 :                         name_match = true;
    1039           0 :                         sname_val = sval;
    1040           0 :                         name_op = sop;
    1041         252 :                     } else if (sname == g_viz_constants.STATS_SOURCE_FIELD ||
    1042         504 :                         boost::algorithm::ends_with(pname, g_viz_constants.STATS_KEY_FIELD) ||
    1043         252 :                         boost::algorithm::ends_with(pname, g_viz_constants.STATS_PROXY_FIELD)) {
    1044           0 :                         if (boost::algorithm::ends_with(pname, g_viz_constants.STATS_KEY_FIELD)) {
    1045           0 :                             pname = g_viz_constants.STATS_KEY_FIELD;
    1046             :                         }
    1047           0 :                         if (boost::algorithm::ends_with(pname, g_viz_constants.STATS_PROXY_FIELD)) {
    1048           0 :                             pname = g_viz_constants.STATS_PROXY_FIELD;
    1049             :                         }
    1050             : 
    1051           0 :                         QE_INVALIDARG_ERROR(sop == EQUAL || sop == PREFIX);
    1052             :                         GenDb::Op::type db_op;
    1053           0 :                         if (sop == EQUAL) {
    1054           0 :                             db_op = GenDb::Op::EQ;
    1055             :                         } else {
    1056           0 :                             db_op = GenDb::Op::LIKE;
    1057             :                         }
    1058           0 :                         QE_INVALIDARG_ERROR(populate_where_vec(m_query, &where_vec_stats,
    1059             :                             sname, db_op, GenDb::DbDataValueToString(sval)));
    1060             :                     } else {
    1061         252 :                         QE_INVALIDARG_ERROR(sop == EQUAL || sop == PREFIX);
    1062             :                         GenDb::Op::type db_op;
    1063         252 :                         sval = "%" + sname + "=" + GenDb::DbDataValueToString(sval);
    1064         252 :                         db_op = GenDb::Op::LIKE;
    1065         252 :                         size_t idx = djb_hash(sname.c_str(), sname.length())
    1066         252 :                             % g_viz_constants.NUM_STATS_TAGS_FIELD;
    1067         252 :                         QE_INVALIDARG_ERROR(populate_where_vec(m_query, &where_vec_tags_stats[idx], 
    1068             :                             g_viz_constants.STATS_TAGS_FIELD + integerToString(idx),
    1069             :                             db_op, GenDb::DbDataValueToString(sval)));
    1070             :                     }
    1071             :                 }
    1072         771 :                 object_id_specified = true;
    1073         771 :             }
    1074        2123 :         }
    1075             : 
    1076        1719 :         if (m_query->is_stat_table_query(m_query->table())) {
    1077         700 :             std::vector<GenDb::WhereIndexInfoVec> where_vec_list;
    1078         700 :             populate_stats_where_vec_list(&where_vec_list, where_vec_stats,
    1079             :                 where_vec_tags_stats);
    1080        2096 :             BOOST_FOREACH(const GenDb::WhereIndexInfoVec &where_vec, where_vec_list) {
    1081         699 :                 DbQueryUnit *db_query = new DbQueryUnit(this, main_query);
    1082         699 :                 db_query->cfname = g_viz_constants.STATS_TABLE;
    1083         699 :                 std::string tstr, astr;
    1084         699 :                 GetStatTableAttrName(m_query->table(), &tstr, &astr);
    1085         700 :                 db_query->row_key_suffix.push_back(tstr);
    1086         698 :                 db_query->row_key_suffix.push_back(astr);
    1087         698 :                 db_query->where_vec = where_vec;
    1088         700 :                 if (name_match) {
    1089         575 :                     db_query->cr.start_.push_back(sname_val);
    1090         575 :                     if (name_op == EQUAL) {
    1091         558 :                         db_query->cr.finish_.push_back(sname_val);
    1092          17 :                     } else if (name_op == PREFIX) {
    1093          17 :                         db_query->cr.finish_.push_back(
    1094          34 :                             GenDb::DbDataValueToString(sname_val) + "\x7f");
    1095             :                     } else {
    1096           0 :                         QE_INVALIDARG_ERROR(false);
    1097             :                     }
    1098             :                 } else {
    1099         125 :                     db_query->cr.start_.push_back("\x00");
    1100         125 :                     db_query->cr.finish_.push_back("\x7f");
    1101             :                 }
    1102         698 :             }
    1103         699 :         }
    1104             : 
    1105             :         // common handling similar to object table where * case
    1106        2907 :         if (m_query->is_message_table_query() ||
    1107        2908 :             m_query->is_object_table_query(m_query->table())) {
    1108         870 :             handle_object_type_value(m_query, msg_table_db_query,
    1109             :                                      object_id_specified);
    1110             :         }
    1111             : 
    1112        1718 :         if (isSession) {
    1113         114 :             std::vector<GenDb::WhereIndexInfoVec> where_vec_list;
    1114         114 :             populate_session_where_vec_list(&where_vec_list, where_vec_session_rest, labels_vec, remote_labels_vec,
    1115             :                 custom_tags_vec, remote_custom_tags_vec);
    1116             : 
    1117         364 :             BOOST_FOREACH(const GenDb::WhereIndexInfoVec &where_vec, where_vec_list) {
    1118         125 :                 DbQueryUnit *session_db_query = new DbQueryUnit(this, main_query);
    1119         124 :                 session_db_query->cfname = g_viz_constants.SESSION_TABLE;
    1120         124 :                 session_db_query->row_key_suffix.push_back((uint8_t)is_si);
    1121         124 :                 session_db_query->row_key_suffix.push_back((uint8_t)session_type);
    1122         124 :                 session_db_query->where_vec = where_vec;
    1123             : 
    1124         126 :                 if (proto_match) {
    1125          58 :                     session_db_query->cr.start_.push_back(proto);
    1126          58 :                     if (proto_op == EQUAL) {
    1127          58 :                         session_db_query->cr.finish_.push_back(proto);
    1128           0 :                     } else if (proto_op == IN_RANGE) {
    1129           0 :                         session_db_query->cr.finish_.push_back(proto2);
    1130             :                     }
    1131             :                 } else {
    1132          68 :                     session_db_query->cr.start_.push_back((uint16_t)0);
    1133          68 :                     session_db_query->cr.finish_.push_back((uint16_t)0xffff);
    1134             :                 }
    1135         126 :                 if (sport_match) {
    1136          58 :                     QE_INVALIDARG_ERROR(proto_match);
    1137          58 :                     session_db_query->cr.start_.push_back(sport);
    1138          58 :                     if(sport_op == EQUAL) {
    1139          58 :                         session_db_query->cr.finish_.push_back(sport);
    1140           0 :                     } else if (sport_op == IN_RANGE) {
    1141           0 :                         session_db_query->cr.finish_.push_back(sport2);
    1142             :                     }
    1143             :                 } else {
    1144          68 :                     session_db_query->cr.finish_.push_back((uint16_t)0xffff);
    1145             :                 }
    1146             :             }
    1147         114 :         }
    1148        1604 :         else if (m_query->is_flow_query(m_query->table())) {
    1149          36 :             if (!filter_and.empty()) {
    1150           0 :                 filter_list_.push_back(filter_and);
    1151             :             }
    1152             :             {
    1153          36 :                 DbQueryUnit *client_session_query = new DbQueryUnit(this, main_query);
    1154          36 :                 client_session_query->cfname = g_viz_constants.SESSION_TABLE;
    1155          36 :                 client_session_query->row_key_suffix.push_back(
    1156          36 :                                         (uint8_t)SessionType::CLIENT_SESSION);
    1157          36 :                 if (proto_match) {
    1158          12 :                     client_session_query->cr.start_.push_back(proto);
    1159          12 :                     if (proto_op == EQUAL) {
    1160          12 :                         client_session_query->cr.finish_.push_back(proto);
    1161           0 :                     } else if (proto_op == IN_RANGE) {
    1162           0 :                         client_session_query->cr.finish_.push_back(proto2);
    1163             :                     }
    1164             :                 } else {
    1165          24 :                     client_session_query->cr.start_.push_back(((uint16_t)0));
    1166          24 :                     client_session_query->cr.finish_.push_back(((uint16_t)0xffff));
    1167             :                 }
    1168          36 :                 if ((direction_ing == 0 && sport_match) ||
    1169          36 :                     (direction_ing == 1 && dport_match)) {
    1170           0 :                     QE_INVALIDARG_ERROR(proto_match);
    1171           0 :                     client_session_query->cr.start_.push_back(direction_ing?
    1172             :                             dport:sport);
    1173           0 :                     int op = direction_ing?dport_op:sport_op;
    1174           0 :                     if (op == EQUAL) {
    1175           0 :                         client_session_query->cr.finish_.push_back(direction_ing?
    1176             :                             dport:sport);
    1177           0 :                     } else if (op == IN_RANGE) {
    1178           0 :                         client_session_query->cr.finish_.push_back(direction_ing?
    1179             :                             dport2:sport2);
    1180             :                     }
    1181           0 :                 } else {
    1182          36 :                     client_session_query->cr.finish_.push_back((uint16_t)0xffff);
    1183             :                 }
    1184          36 :                 if ((direction_ing == 0 && dip_match) ||
    1185          36 :                     (direction_ing == 1 && sip_match)) {
    1186             : 
    1187           0 :                     int op = direction_ing?sip_op:dip_op;
    1188           0 :                     std::string val = direction_ing?
    1189           0 :                         (boost::get<std::string>(sip)):(boost::get<std::string>(dip));
    1190             :                     GenDb::Op::type comparator;
    1191           0 :                     if (op == PREFIX) {
    1192           0 :                         comparator = GenDb::Op::LIKE;
    1193             :                     } else {
    1194           0 :                         comparator = GenDb::Op::EQ;
    1195             :                     }
    1196           0 :                     QE_INVALIDARG_ERROR(populate_where_vec(m_query,
    1197             :                         &(client_session_query->where_vec), "local_ip", comparator, val));
    1198           0 :                 }
    1199          36 :                 if ((direction_ing == 0 && dvn_match) ||
    1200          36 :                     (direction_ing == 1 && svn_match)) {
    1201          24 :                     int op = direction_ing?svn_op:dvn_op;
    1202          24 :                     std::string val = direction_ing?
    1203          24 :                         (boost::get<std::string>(svn)):(boost::get<std::string>(dvn));
    1204             :                     GenDb::Op::type comparator;
    1205          24 :                     if (op == PREFIX) {
    1206          12 :                         comparator = GenDb::Op::LIKE;
    1207             :                     } else {
    1208          12 :                         comparator = GenDb::Op::EQ;
    1209             :                     }
    1210          24 :                     QE_INVALIDARG_ERROR(populate_where_vec(m_query,
    1211             :                         &(client_session_query->where_vec), "vn", comparator, val));
    1212          23 :                 }
    1213          35 :                 if ((direction_ing == 0 && svn_match) ||
    1214          35 :                     (direction_ing == 1 && dvn_match)) {
    1215          11 :                     int op = (direction_ing?dvn_op:svn_op);
    1216             :                     GenDb::Op::type comparator;
    1217          11 :                     std::string val = direction_ing?
    1218          11 :                         (boost::get<std::string>(dvn)):(boost::get<std::string>(svn));
    1219          11 :                     if (op == PREFIX) {
    1220           0 :                         comparator = GenDb::Op::LIKE;
    1221             :                     } else {
    1222          11 :                         comparator = GenDb::Op::EQ;
    1223             :                     }
    1224          11 :                     QE_INVALIDARG_ERROR(populate_where_vec(m_query,
    1225             :                         &(client_session_query->where_vec), "remote_vn", comparator, val));
    1226          12 :                 }
    1227             :             }
    1228             :             {
    1229          36 :                 DbQueryUnit *server_session_query = new DbQueryUnit(this, main_query);
    1230          36 :                 server_session_query->cfname = g_viz_constants.SESSION_TABLE;
    1231          36 :                 server_session_query->row_key_suffix.push_back(
    1232          36 :                                         (uint8_t)SessionType::SERVER_SESSION);
    1233          36 :                 if (proto_match) {
    1234          12 :                     server_session_query->cr.start_.push_back(proto);
    1235          12 :                     if(proto_op == EQUAL) {
    1236          12 :                         server_session_query->cr.finish_.push_back(proto);
    1237             :                     }
    1238           0 :                     else if (proto_op == IN_RANGE) {
    1239           0 :                         server_session_query->cr.finish_.push_back(proto2);
    1240             :                     }
    1241             :                 } else {
    1242          24 :                     server_session_query->cr.start_.push_back(((uint16_t)0));
    1243          24 :                     server_session_query->cr.finish_.push_back(((uint16_t)0xffff));
    1244             :                 }
    1245          36 :                 if ((direction_ing == 0 && dport_match) ||
    1246          36 :                     (direction_ing == 1 && sport_match)) {
    1247           0 :                     QE_INVALIDARG_ERROR(proto_match);
    1248           0 :                     server_session_query->cr.start_.push_back(direction_ing?
    1249             :                             sport:dport);
    1250           0 :                     int op = direction_ing?sport_op:dport_op;
    1251           0 :                     if(op == EQUAL) {
    1252           0 :                         server_session_query->cr.finish_.push_back(direction_ing?
    1253             :                             sport:dport);
    1254           0 :                     } else if (op == IN_RANGE) {
    1255           0 :                         server_session_query->cr.finish_.push_back(direction_ing?
    1256             :                             sport2:dport2);
    1257             :                     }
    1258           0 :                 } else {
    1259          36 :                     server_session_query->cr.finish_.push_back((uint16_t)0xffff);
    1260             :                 }
    1261          36 :                 if ((direction_ing == 0 && dip_match) ||
    1262          36 :                     (direction_ing == 1 && sip_match)) {
    1263           0 :                     int op = direction_ing?sip_op:dip_op;
    1264           0 :                     std::string val = direction_ing?
    1265           0 :                         (boost::get<std::string>(sip)):(boost::get<std::string>(dip));
    1266             :                     GenDb::Op::type comparator;
    1267           0 :                     if (op == PREFIX) {
    1268           0 :                         comparator = GenDb::Op::LIKE;
    1269             :                     } else {
    1270           0 :                         comparator = GenDb::Op::EQ;
    1271             :                     }
    1272           0 :                     QE_INVALIDARG_ERROR(populate_where_vec(m_query,
    1273             :                         &(server_session_query->where_vec), "local_ip", comparator, val));
    1274           0 :                 }
    1275          36 :                 if ((direction_ing == 0 && dvn_match) ||
    1276          36 :                     (direction_ing == 1 && svn_match)) {
    1277          24 :                     int op = (direction_ing?svn_op:dvn_op);
    1278          24 :                     std::string val = direction_ing?
    1279          24 :                         (boost::get<std::string>(svn)):(boost::get<std::string>(dvn));
    1280             :                     GenDb::Op::type comparator;
    1281          24 :                     if (op == PREFIX) {
    1282          12 :                         comparator = GenDb::Op::LIKE;
    1283             :                     } else {
    1284          12 :                         comparator = GenDb::Op::EQ;
    1285             :                     }
    1286          24 :                     QE_INVALIDARG_ERROR(populate_where_vec(m_query,
    1287             :                         &(server_session_query->where_vec), "vn", comparator, val));
    1288          24 :                 }
    1289          36 :                 if ((direction_ing == 0 && svn_match) ||
    1290          36 :                     (direction_ing == 1 && dvn_match)) {
    1291          12 :                     int op = (direction_ing?dvn_op:svn_op);
    1292             :                     GenDb::Op::type comparator;
    1293          12 :                     std::string val = direction_ing?
    1294          12 :                         (boost::get<std::string>(dvn)):(boost::get<std::string>(svn));
    1295          12 :                     if (op == PREFIX) {
    1296           0 :                         comparator = GenDb::Op::LIKE;
    1297             :                     } else {
    1298          12 :                         comparator = GenDb::Op::EQ;
    1299             :                     }
    1300          12 :                     QE_INVALIDARG_ERROR(populate_where_vec(m_query,
    1301             :                         &(server_session_query->where_vec), "remote_vn", comparator, val));
    1302          12 :                 }
    1303             :             }
    1304             :         }
    1305        1721 :     }
    1306        1635 : }
    1307             : 
    1308             : // For UT
    1309           1 : WhereQuery::WhereQuery(QueryUnit *mq): QueryUnit(mq, mq){
    1310           1 : }
    1311             : 
    1312         114 : void WhereQuery::populate_session_where_vec_list(std::vector<GenDb::WhereIndexInfoVec> *where_vec_list,
    1313             :     const GenDb::WhereIndexInfoVec &rest_where_vec,
    1314             :     const GenDb::WhereIndexInfoVec &labels_vec,
    1315             :     const GenDb::WhereIndexInfoVec &remote_labels_vec,
    1316             :     const GenDb::WhereIndexInfoVec &custom_tags_vec,
    1317             :     const GenDb::WhereIndexInfoVec &remote_custom_tags_vec) {
    1318             : 
    1319         114 :     uint16_t max_random_attr = std::max(std::max(std::max(labels_vec.size(),
    1320         114 :         remote_labels_vec.size()), custom_tags_vec.size()),
    1321         114 :         remote_custom_tags_vec.size());
    1322         114 :     if (max_random_attr == 0) {
    1323          82 :         where_vec_list->push_back(rest_where_vec);
    1324             :     } else  {
    1325          76 :         for (size_t i = 0; i < max_random_attr; ++i) {
    1326          44 :             GenDb::WhereIndexInfoVec where_vec(rest_where_vec);
    1327          44 :             if (i < labels_vec.size()) {
    1328          34 :                 where_vec.push_back(labels_vec[i]);
    1329             :             }
    1330          44 :             if (i < remote_labels_vec.size()) {
    1331          22 :                 where_vec.push_back(remote_labels_vec[i]);
    1332             :             }
    1333          44 :             if (i < custom_tags_vec.size()) {
    1334          10 :                 where_vec.push_back(custom_tags_vec[i]);
    1335             :             }
    1336          44 :             if (i < remote_custom_tags_vec.size()) {
    1337          10 :                 where_vec.push_back(remote_custom_tags_vec[i]);
    1338             :             }
    1339          44 :             where_vec_list->push_back(where_vec);
    1340          43 :         }
    1341             :     }
    1342         113 : }
    1343             : 
    1344        1799 : void WhereQuery::subquery_processed(QueryUnit *subquery) {
    1345        1799 :     AnalyticsQuery *m_query = (AnalyticsQuery *)main_query;
    1346             :     {
    1347        1799 :         std::scoped_lock lock(vector_push_mutex_);
    1348        1799 :         int sub_query_id = ((DbQueryUnit *)subquery)->sub_query_id;
    1349        1799 :         if (((DbQueryUnit *)subquery)->cfname == g_viz_constants.OBJECT_TABLE) {
    1350           0 :             inp.insert(inp.begin(), sub_queries[sub_query_id]->query_result.get());
    1351        1799 :         } else if (((DbQueryUnit *)subquery)->cfname == g_viz_constants.STATS_TABLE) {
    1352         312 :             inp_new_data.push_back((sub_queries[sub_query_id]->query_result.get()));
    1353             :         } else {
    1354        1487 :             inp.push_back((sub_queries[sub_query_id]->query_result.get()));
    1355             :         }
    1356        1799 :         if (subquery->query_status == QUERY_FAILURE) {
    1357           0 :             QE_QUERY_FETCH_ERROR();
    1358             :         }
    1359        1799 :         if (sub_queries.size() != inp.size() + inp_new_data.size()) {
    1360         901 :             return;
    1361             :         }
    1362        1799 :     }
    1363             : 
    1364             :     // Handle if any of the sub query has failed.
    1365         898 :     if (m_query->qperf_.error) {
    1366           0 :         m_query->qperf_.chunk_where_time =
    1367           0 :         static_cast<uint32_t>((UTCTimestampUsec() - m_query->where_start_)
    1368           0 :         /1000);
    1369           0 :         where_query_cb_(m_query->handle_, m_query->qperf_, std::auto_ptr<std::vector<query_result_unit_t>>(where_result_.release()));
    1370           0 :         return;
    1371             :     }
    1372        2694 :     if (m_query->is_message_table_query()
    1373        1540 :         || m_query->is_object_table_query(m_query->table())
    1374        1540 :         || m_query->is_flow_query(m_query->table())
    1375             :         ) {
    1376         447 :         SetOperationUnit::op_or(((AnalyticsQuery *)(this->main_query))->query_id,
    1377         447 :             *where_result_, inp);
    1378         451 :     } else if (m_query->is_stat_table_query(m_query->table())) {
    1379         312 :         std::vector<WhereResultT*> inp_final;
    1380         312 :         if (inp.size() != 0) {
    1381             :             std::unique_ptr<WhereResultT>
    1382           0 :                 where_result_old(new std::vector<query_result_unit_t>);
    1383           0 :             SetOperationUnit::op_and(((AnalyticsQuery *)(this->main_query))->query_id,
    1384           0 :                 *where_result_old, inp);
    1385           0 :             inp_final.push_back(where_result_old.get());
    1386           0 :         }
    1387             :         std::unique_ptr<WhereResultT>
    1388         312 :             where_result_new(new std::vector<query_result_unit_t>);
    1389         312 :         SetOperationUnit::op_and(((AnalyticsQuery *)(this->main_query))->query_id,
    1390         312 :             *where_result_new, inp_new_data);
    1391         312 :         inp_final.push_back(where_result_new.get());
    1392         624 :         SetOperationUnit::op_or(((AnalyticsQuery *)(this->main_query))->query_id,
    1393         312 :             *where_result_, inp_final);
    1394         312 :     } else {
    1395         139 :         SetOperationUnit::op_and(((AnalyticsQuery *)(this->main_query))->query_id,
    1396         139 :             *where_result_, inp);
    1397             :     }
    1398         898 :     m_query->query_status = query_status;
    1399             : 
    1400         898 :     QE_TRACE(DEBUG, "Set ops returns # of rows:" << where_result_->size());
    1401             : 
    1402             :     // Have the result ready and processing is done
    1403         898 :     QE_TRACE(DEBUG, "WHERE processing done row #s:" <<
    1404             :          where_result_->size());
    1405         898 :     QE_TRACE_NOQID(DEBUG, " Finished where processing for QID " << m_query->query_id
    1406             :         << " chunk:" << m_query->parallel_batch_num);
    1407         898 :     status_details = 0;
    1408         898 :     parent_query->subquery_processed(this);
    1409         898 :     m_query->status_details = status_details;
    1410         898 :     m_query->qperf_.chunk_where_time =
    1411         898 :         static_cast<uint32_t>((UTCTimestampUsec() - m_query->where_start_)
    1412         898 :         /1000);
    1413         898 :     where_query_cb_(m_query->handle_, m_query->qperf_,std::auto_ptr<std::vector<query_result_unit_t>>(where_result_.release()));
    1414             : }
    1415             : 
    1416         904 : query_status_t WhereQuery::process_query()
    1417             : {
    1418         904 :     AnalyticsQuery *m_query = (AnalyticsQuery *)main_query;
    1419             : 
    1420         904 :     if (status_details != 0)
    1421             :     {
    1422           0 :         QE_TRACE(DEBUG, 
    1423             :              "No need to process query, as there were errors previously");
    1424           0 :         return QUERY_FAILURE;
    1425             :     }
    1426             : 
    1427         904 :     QE_TRACE(DEBUG, "WhereQuery" );
    1428             : 
    1429         904 :     QE_TRACE(DEBUG, "Starting processing of " << sub_queries.size() <<
    1430             :             " subqueries");
    1431             : 
    1432         904 :     if (m_query->table() == g_viz_constants.OBJECT_VALUE_TABLE) {
    1433           7 :         status_details = 0;
    1434           7 :         parent_query->subquery_processed(this);
    1435           7 :         return QUERY_SUCCESS;
    1436             :     }
    1437         897 :     unsigned int v_size = sub_queries.size();
    1438             :     // invoke processing of all the sub queries
    1439             :     // TBD: Handle ASYNC processing
    1440        2694 :     for (unsigned int i = 0; i < v_size; i++)
    1441             :     {
    1442        1797 :         query_status = sub_queries[i]->process_query();
    1443        1797 :         if (query_status == QUERY_FAILURE) {
    1444           0 :             return query_status;
    1445             :         }
    1446             :     }
    1447         897 :     return query_status;
    1448             : }
    1449             : 
    1450             : // We need to cover 2 cases here in MessageTablev2
    1451             : // (a) --object-type is specified without any --object-id
    1452             : // (b) --object-type and --object-id are specified
    1453             : 
    1454             : // (a) ObjectTypeValue fields are stored in following format
    1455             : //  T2:ObjectType:ObjectId
    1456             : //  We need to query for T2:ObjectType*
    1457             : // (b) We have 6 columns to save OBJECTID.
    1458             : // Any OBJECTID could be in any of the 6 columns.
    1459             : // For OBJECTID query, we need to check each of the 6 columns.
    1460             : // Since its an OR operation, we need to create 6 queries, one
    1461             : // for each column.
    1462             : // Combining (a) & (b) we end up creating 6 queries 1 for each
    1463             : // ObjectTypeValue[1..6] column.
    1464         925 : void WhereQuery::handle_object_type_value(
    1465             :                                     AnalyticsQuery *m_query,
    1466             :                                     DbQueryUnit *db_query,
    1467             :                                     bool object_id_specified)
    1468             : {
    1469         925 :     if (m_query->is_object_table_query(m_query->table())) {
    1470         395 :         QE_TRACE(DEBUG, "object-type-value handling");
    1471             :         std::string column1 = query_column_to_cass_column(m_query,
    1472         395 :                                         g_viz_constants.OBJECT_TYPE_NAME1);
    1473         395 :         if (column1.empty()) {
    1474           0 :             QE_INVALIDARG_ERROR(false);
    1475             :         }
    1476         395 :         if (object_id_specified == false) {
    1477             :             // create db_query entry for OBJECT_TYPE_NAME1
    1478             :             // as done for OBJECTID case above.
    1479             :             // rest falls in place as with --object-id case.
    1480          55 :             match_op op = PREFIX;
    1481          55 :             std::string val(m_query->table() + ":");
    1482          55 :             std::string col_name = g_viz_constants.OBJECT_TYPE_NAME1;
    1483          55 :             QE_INVALIDARG_ERROR(populate_where_vec(m_query, &(db_query->where_vec),
    1484             :                 col_name, get_gendb_op_from_op(op), val));
    1485          55 :         }
    1486             : 
    1487             :         // regular --object-id processing from here
    1488         395 :         int index = 0;
    1489         790 :         BOOST_FOREACH(GenDb::WhereIndexInfo &where_info, db_query->where_vec) {
    1490         395 :             if (column1 == where_info.get<0>()) {
    1491         395 :                 break;
    1492             :             }
    1493           0 :             index++;
    1494             :         }
    1495             : 
    1496             :         // OBJECT_TYPE_NAME1 is already done above
    1497        2370 :         for (int i = 2;
    1498        2370 :              i <= g_viz_constants.MSG_TABLE_MAX_OBJECTS_PER_MSG;
    1499             :              i++) {
    1500        1975 :             DbQueryUnit *msg_table_db_query2 = new DbQueryUnit(this, main_query);
    1501        1974 :             msg_table_db_query2->cfname = g_viz_constants.COLLECTOR_GLOBAL_TABLE;
    1502        1974 :             msg_table_db_query2->t_only_row = true;
    1503        1974 :             msg_table_db_query2->t_only_col = true;
    1504        1974 :             msg_table_db_query2->where_vec = db_query->where_vec;
    1505             : 
    1506        1975 :             GenDb::WhereIndexInfo *where_info2 = &msg_table_db_query2->where_vec[index];
    1507        1975 :             std::string col_name = g_viz_constants.OBJECT_TYPE_NAME_PFX;
    1508        1975 :             col_name.append(integerToString(i));
    1509             : 
    1510        1975 :             std::string columnN = query_column_to_cass_column(m_query, col_name);
    1511        1975 :             if (column1.empty()) {
    1512           0 :                 QE_INVALIDARG_ERROR(false);
    1513             :             }
    1514        1975 :             where_info2->get<0>() = columnN;
    1515        1974 :         }
    1516         395 :     }
    1517             : }
    1518             : 
    1519        1762 : bool WhereQuery::populate_where_vec(AnalyticsQuery *m_query,
    1520             :                                     GenDb::WhereIndexInfoVec *where_vec,
    1521             :                                     const std::string& query_col,
    1522             :                                     const GenDb::Op::type db_op,
    1523             :                                     const std::string& value) {
    1524        1762 :     std::string columnN = query_column_to_cass_column(m_query, query_col);
    1525        1763 :     if (columnN.empty()) {
    1526           0 :         return false;
    1527             :     }
    1528        1763 :     std::string val(value);
    1529        1763 :     switch (db_op) {
    1530         655 :         case GenDb::Op::LIKE:
    1531             :         {
    1532         655 :             val += "%";
    1533         655 :             break;
    1534             :         }
    1535        1108 :         default:
    1536        1108 :             break;
    1537             :     }
    1538        1763 :     if (val == "%") {
    1539          24 :         return true;
    1540             :     }
    1541             :     GenDb::WhereIndexInfo where_info =
    1542        1739 :             boost::make_tuple(columnN, db_op, val);
    1543        1736 :     where_vec->push_back(where_info);
    1544        1737 :     return true;
    1545        1759 : }
    1546             : 
    1547        4132 : std::string WhereQuery::query_column_to_cass_column(AnalyticsQuery *m_query,
    1548             :                                                     const std::string& query_column) {
    1549        4132 :     std::map<std::string, table_schema> schema;
    1550        4132 :     std::string table_name;
    1551       11697 :     if (m_query->is_message_table_query(m_query->table()) ||
    1552        7564 :         m_query->is_object_table_query(m_query->table())) {
    1553        3463 :         schema = g_viz_constants._VIZD_TABLE_SCHEMA;
    1554        3460 :         table_name = g_viz_constants.COLLECTOR_GLOBAL_TABLE;
    1555        1859 :     } else if (m_query->is_session_query(m_query->table()) ||
    1556        1190 :         m_query->is_flow_query(m_query->table())) {
    1557         220 :         schema = g_viz_constants._VIZD_SESSION_TABLE_SCHEMA;
    1558         219 :         table_name = g_viz_constants.SESSION_TABLE;
    1559         449 :     } else if (m_query->is_stat_table_query(m_query->table())) {
    1560         449 :         schema = g_viz_constants._VIZD_STAT_TABLE_SCHEMA;
    1561         449 :         table_name = g_viz_constants.STATS_TABLE;
    1562             :     }
    1563        4131 :     std::map<std::string, table_schema>::const_iterator it = schema.find(table_name);
    1564        4130 :     QE_ASSERT(it != schema.end());
    1565             :     std::map<string, string>::const_iterator itr =
    1566        4130 :         it->second.index_column_to_column.find(query_column);
    1567        4130 :     if (itr == (it->second.index_column_to_column.end())) {
    1568           0 :         return "";
    1569             :     }
    1570        4130 :     return itr->second;
    1571        4128 : }

Generated by: LCOV version 1.14