MXS-1688 Handle ...INTERVAL N <unit>

"INTERVAL N <unit>" is now handled as an expression in itself and
as asuch will cause both statements such as

  "SELECT '2008-12-31 23:59:59' + INTERVAL 1 SECOND;"

and

  "select id from db2.t1 where DATE_ADD("2017-06-15", INTERVAL 10 DAY) < "2017-06-15";"

to be handled correctly. The compare test program contains some
heuristic checking, as the the embedded parser will in all cases
report date manipulation as the use of the add_date_interval()
function.
This commit is contained in:
Johan Wikman 2018-02-27 02:55:05 +02:00
parent b7cc793c40
commit 0c206ff428
2 changed files with 61 additions and 3 deletions

View File

@ -1948,10 +1948,10 @@ expr(A) ::= expr(X) BITAND|BITOR|LSHIFT|RSHIFT(OP) expr(Y).
expr(A) ::= expr(X) PLUS|MINUS(OP) expr(Y).
{spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
%ifdef MAXSCALE
expr(A) ::= expr(X) PLUS|MINUS INTERVAL INTEGER id. {
expr(A) ::= INTERVAL INTEGER(X) id. {
// Here we could check that id is one of MICROSECOND, SECOND, MINUTE
// HOUR, DAY, WEEK, etc.
A=X;
spanExpr(&A, pParse, @X, &X);
}
%endif
expr(A) ::= expr(X) STAR|SLASH|REM(OP) expr(Y).

View File

@ -1069,6 +1069,11 @@ public:
return rv;
}
const std::string& name() const
{
return m_name;
}
void print(ostream& out) const
{
out << m_name;
@ -1118,6 +1123,19 @@ bool operator == (const QcFunctionInfo& lhs, const QcFunctionInfo& rhs)
return lhs.eq(rhs);
}
void collect_missing_function_names(const std::set<QcFunctionInfo>& one,
const std::set<QcFunctionInfo>& other,
std::set<std::string>* pNames)
{
for (std::set<QcFunctionInfo>::const_iterator i = one.begin(); i != one.end(); ++i)
{
if (other.count(*i) == 0)
{
pNames->insert(i->name());
}
}
}
bool compare_get_function_info(QUERY_CLASSIFIER* pClassifier1, GWBUF* pCopy1,
QUERY_CLASSIFIER* pClassifier2, GWBUF* pCopy2)
{
@ -1151,7 +1169,47 @@ bool compare_get_function_info(QUERY_CLASSIFIER* pClassifier1, GWBUF* pCopy1,
}
else
{
ss << "ERR: " << f1 << " != " << f2;
std::set<std::string> names1;
collect_missing_function_names(f1, f2, &names1);
std::set<std::string> names2;
collect_missing_function_names(f2, f1, &names2);
bool real_error = false;
// We assume that names1 are from the qc_mysqlembedded and names2 from qc_sqlite.
// The embedded parser reports all date_add(), adddate(), date_sub() and subdate()
// functions as date_add_interval(). Further, all "DATE + INTERVAL ..." cases become
// use of date_add_interval() functions.
for (std::set<std::string>::iterator i = names1.begin(); i != names1.end(); ++i)
{
if (*i == "date_add_interval")
{
if ((names2.count("date_add") == 0) &&
(names2.count("adddate") == 0) &&
(names2.count("date_sub") == 0) &&
(names2.count("subdate") == 0) &&
(names2.count("+") == 0) &&
(names2.count("-") == 0))
{
real_error = true;
}
}
else
{
real_error = true;
}
}
if (real_error)
{
ss << "ERR: " << f1 << " != " << f2;
}
else
{
ss << "Ok : " << f1 << " != " << f2;
success = true;
}
}
report(success, ss.str());