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

Generated by: LCOV version 1.14