MXS-1702: Canonicalize negative numbers
The new canonicalization function now processes negative numbers correctly. It uses a look-behind operation to detect whether the operation is a negation of a number or a subtraction from another value.
This commit is contained in:
		@ -1254,6 +1254,30 @@ static std::pair<bool, mxs::Buffer::iterator> probe_number(mxs::Buffer::iterator
 | 
				
			|||||||
    return rval;
 | 
					    return rval;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool is_negation(const std::string& str)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    bool rval = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!str.empty() && str[str.size() - 1] == '-')
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Possibly a negative number
 | 
				
			||||||
 | 
					        rval = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (auto it = std::next(str.rbegin()); it != str.rend(); it++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (!isspace(*it))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                /** If we find a previously converted value, we know that it
 | 
				
			||||||
 | 
					                 * is not a negation but a subtraction. */
 | 
				
			||||||
 | 
					                rval = *it != '?';
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return rval;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char* modutil_get_new_canonical(GWBUF* querybuf)
 | 
					char* modutil_get_new_canonical(GWBUF* querybuf)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    std::string rval;
 | 
					    std::string rval;
 | 
				
			||||||
@ -1267,8 +1291,6 @@ char* modutil_get_new_canonical(GWBUF* querybuf)
 | 
				
			|||||||
        BACKTICK
 | 
					        BACKTICK
 | 
				
			||||||
    } my_state = NONE;
 | 
					    } my_state = NONE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char prev = ' ';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (auto it = std::next(buf.begin(), MYSQL_HEADER_LEN + 1); // Skip packet header and command
 | 
					    for (auto it = std::next(buf.begin(), MYSQL_HEADER_LEN + 1); // Skip packet header and command
 | 
				
			||||||
         it != buf.end(); it++)
 | 
					         it != buf.end(); it++)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -1281,6 +1303,8 @@ char* modutil_get_new_canonical(GWBUF* querybuf)
 | 
				
			|||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        char prev = rval.empty() ? ' ' : rval[rval.size() - 1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        switch (my_state)
 | 
					        switch (my_state)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            case BACKTICK:
 | 
					            case BACKTICK:
 | 
				
			||||||
@ -1318,6 +1342,11 @@ char* modutil_get_new_canonical(GWBUF* querybuf)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                     if (num_end.first)
 | 
					                     if (num_end.first)
 | 
				
			||||||
                     {
 | 
					                     {
 | 
				
			||||||
 | 
					                         if (is_negation(rval))
 | 
				
			||||||
 | 
					                         {
 | 
				
			||||||
 | 
					                             // Remove the sign
 | 
				
			||||||
 | 
					                             rval.resize(rval.size() - 1);
 | 
				
			||||||
 | 
					                         }
 | 
				
			||||||
                         rval += '?';
 | 
					                         rval += '?';
 | 
				
			||||||
                         it = num_end.second;
 | 
					                         it = num_end.second;
 | 
				
			||||||
                         continue;
 | 
					                         continue;
 | 
				
			||||||
@ -1342,8 +1371,6 @@ char* modutil_get_new_canonical(GWBUF* querybuf)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        prev = *it;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    buf.release();
 | 
					    buf.release();
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user