Changeset 19093 for trunk


Ignore:
Timestamp:
07/29/18 15:18:30 (6 years ago)
Author:
tbretz
Message:
Some improvemnts to the EXPLAIN formating -- not a nice code but for comparable simple queries, it does its job.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/FACT++/src/rootifysql.cc

    r19092 r19093  
    137137    vector<string> queries;
    138138
    139     string backsubstitute(const size_t &_idx,const size_t &indent)
    140     {
    141         string str = vec[_idx];
    142 
    143         regex reg0("\\/\\*\\ select\\#[0-9]+\\ \\*\\/\\ select\\ ");
    144 
     139    string resub(string str, size_t indent)
     140    {
     141        // search for "KEYWORD expression"
     142        regex reg("\\{[0-9]+\\}");
     143
     144        //smatch match;
    145145        smatch match;
    146         if (regex_search(str, match, reg0))
    147         {
    148             if (match.position(0)<2)
    149             {
    150                 // substitute all expressions (blah AS blah)
    151                 str = substitute(str, "([0-9]+|\\{[0-9]+\\})\\ AS\\ \\{[0-9]+\\}");
    152 
    153                 if (str[match.position(0)-1]=='(')
    154                     cout << '(' << endl;
    155 
    156                 keywords(str.substr(match.position(0)), indent+4);
    157 
    158                 if (str[match.position(0)-1]=='(')
    159                     cout << setw(indent+1) << ')' << endl;
    160 
    161                 return "";//"("+to_string(_idx)+")";
    162             }
    163         }
    164 
    165 
    166         // search for "KEYWORD expression"
    167         regex reg1("\\{[0-9]+\\}");
    168 
    169         //smatch match;
    170         while (regex_search(str, match, reg1, regex_constants::format_first_only))
     146        while (regex_search(str, match, reg, regex_constants::format_first_only))
    171147        {
    172148            const auto &len = match.length(0);
     
    176152            const auto idx = atoi(arg.c_str()+1);
    177153
    178             str.replace(pos, len, backsubstitute(idx, indent));
     154            str.replace(pos, len, resub(vec[idx], indent));
    179155        }
    180156
     
    182158    }
    183159
    184     void keywords(string str, const size_t &indent=0)
    185     {
    186         // search for "KEYWORD expression"
    187         regex reg("(\\/\\*\\ [a-z]+\\#[0-9]+\\ \\*\\/)?\\ ([a-z ]+)\\ (\\{[0-9]+\\}([, ]\\{[0-9]+\\})*)?");
     160    void expression(string expr, size_t indent=0)
     161    {
     162        if (expr[0]=='{')
     163        {
     164            const auto idx = atoi(expr.c_str()+1);
     165
     166            // This is a subquery
     167            if (vec[idx].substr(0,3)=="(/*")
     168            {
     169                cout << setw(indent) << ' ' << "(\n";
     170                find_tokens(vec[idx], indent+4);
     171                cout << setw(indent) << ' ' << ") ";
     172            }
     173            else
     174                // This is just something to substitute back
     175                if (vec[idx].substr(0,2)=="({")
     176                {
     177                    cout << setw(indent) << ' ' << "(" << resub(vec[idx], indent+4) << ") ";
     178                }
     179                else
     180                {
     181                    if (indent>0)
     182                        cout << setw(indent) << ' ';
     183                    cout << vec[idx];
     184                }
     185        }
     186        else
     187        {
     188            if (indent>0)
     189                cout << setw(indent) << ' ';
     190            cout << expr;
     191        }
     192    }
     193
     194    void find_tokens(string str, size_t indent=0)
     195    {
     196        //         (            COMMENT                  )?(  TOKEN   )?((  {NNN}     | NNN  )(           AS|ON           (   {NNN})   ))?(,)?)
     197        //regex reg("(\\/\\*\\ select\\#[0-9]+\\ \\*\\/\\ *)?([a-zA-Z ]+)?((\\{[0-9]+\\}|[0-9]+)(\\ ?([Aa][Ss]|[Oo][Nn])\\ ?(\\{[0-9]+\\}))?(,)?)");
     198
     199        const string _com = "\\/\\*\\ select\\#[0-9]+\\ \\*\\/\\ *";
     200
     201        const string _tok = "[a-zA-Z ]+";
     202
     203        const string _nnn = "\\{[0-9]+\\}|[0-9]+";
     204
     205        const string _as  = "\\ ?([Aa][Ss])\\ ?";
     206
     207        //                   (  _nnn  )     (  _as  (  _nnn  ))?(,)?     // can also match noting in between two {NNN}
     208        const string _exp = "("+_nnn+")" + "("+_as+"("+_nnn+"))?(,)?";
     209
     210        // Matche: (  _com  )?       (     (  _tok  )?   (  _exp  )      |      (  _tok  )     )
     211        regex reg("("+_com+")?"  +  "(" + "("+_tok+")?"+"("+_exp+")"  + "|" +  "("+_tok+")" + ")");
    188212
    189213        smatch match;
    190         while (regex_search(str, match, reg))
    191         {
    192             //const auto &len = match.length(0);
    193             //const auto &pos = match.position(0);
    194             const auto &com = match.str(1);      // Comment
    195             const auto &tok = match.str(2);      // Token
    196             const auto &arg = match.str(3);      // Argument
     214        while (regex_search(str, match, reg, regex_constants::format_first_only))
     215        {
     216
     217            const auto &com   = match.str(1);               // comment
     218            const auto &tok1  = Tools::Trim(match.str(3));  // token with expression
     219            const auto &arg1  = match.str(5);               // argument 1
     220            const auto &as    = match.str(7);               // as
     221            const auto &arg2  = match.str(8);               // argument 2
     222            const auto &comma = match.str(9);               // comma
     223            const auto &tok2  = Tools::Trim(match.str(10)); // token without expression
    197224
    198225            if (!com.empty())
    199226                cout << setw(indent) << ' ' << "\033[34m" << com << "\033[0m" << '\n';
    200227
    201             cout << setw(indent) << ' ' << "\033[33m" << tok << "\033[0m" << '\n';
    202             //cout << "   " << arg << '\n';
    203 
    204             vector<string> exprs;
    205             boost::split(exprs, arg, boost::is_any_of(", "));
    206             for (auto &expr : exprs)
     228            if (!tok1.empty())
     229                cout << setw(indent) << ' ' << "\033[32m" << tok1 << "\033[0m" << '\n';
     230            if (!tok2.empty())
     231                cout << setw(indent) << ' ' << "\033[32m" << tok2 << "\033[0m" << '\n';
     232
     233            if (!arg1.empty())
    207234            {
    208                 if (expr.empty())
    209                     continue;
    210 
    211                 const auto idx = atoi(expr.c_str()+1);
    212 
    213                 cout << setw(indent+4) << ' ' << backsubstitute(idx, indent+4) << (tok=="select"?',':' ') << endl;
     235                expression(arg1, indent+4);
     236
     237                if (!as.empty())
     238                    cout << " \033[33m" << as << "\033[0m ";
     239
     240                if (!arg2.empty())
     241                    expression(arg2);
     242
     243                if (!comma.empty())
     244                    cout << ',';
     245
     246                cout << '\n';
    214247            }
    215248
    216249            str = str.substr(match.position(0)+match.length(0));
    217250        }
    218 
    219251    }
    220252
     
    225257        sql = substitute(sql, "'[^']*'");
    226258
    227         // substitute all escaped sequences
    228         sql = substitute(sql, "`[^`]*`");
     259        // substitute all escaped sequences  (`something`.`something-else`)
     260        sql = substitute(sql, "`[^`]*`(\\.`[^`]*`)*");
    229261
    230262        // substitute all paranthesis
    231263        sql = substitute(sql, "\\([^\\(\\)]*\\)");
    232264
    233         // substitute all names (xxx.yyy.zzz)
    234         sql = substitute(sql, "\\{[0-9]+\\}(\\.\\{[0-9]+\\})+");
    235 
    236         // substitute all expressions (blah AS blah)
    237         sql = substitute(sql, "([0-9]+|\\{[0-9]+\\}) AS\\ \\{[0-9]+\\}");
    238 
    239         sql = regex_replace(sql, regex("\\ on\\{"), " on {");
    240 
    241         keywords(sql);
    242 
     265        //cout << sql << "\n\n";
     266        find_tokens(sql);
    243267        cout << endl;
    244268    }
    245269};
    246 
    247 void print(string sql)
    248 {
    249 
    250 }
    251270
    252271// Remove queries...
     
    254273{
    255274    ExplainParser p(sql);
    256 
    257     // (COMMENT)?(TOKEN\\ *|,\\ *|\\ *)?expr[ ]*
    258 
    259     // TOKEN = [:alnum: _]
    260     // expr  = {[0-9]+}
    261     // Special case "expr AS expr"
    262     // Special case "expr AND expr"
    263 
    264     /*
    265      COMMENT
    266      TOKEN
    267         expr AS expr,
    268         expr AS expr,
    269         expr
    270      TOKEN
    271         expr
    272      TOKEN
    273         expr AND expr
    274      */
    275275
    276276    /*
     
    573573                // 1003 //
    574574                cout << row["Level"] << '[' << row["Code"] << "]:\n";
    575                 cout << row["Message"] << '\n' << endl;
    576 
    577575                if (uint32_t(row["Code"])==1003)
    578576                    format(row["Message"].c_str());
     577                else
     578                    cout << row["Message"] << '\n' << endl;
    579579
    580580            }
Note: See TracChangeset for help on using the changeset viewer.