Merge branch '2.3' into 2.4

This commit is contained in:
Johan Wikman
2019-09-16 09:50:05 +03:00
7 changed files with 110 additions and 18 deletions

View File

@ -87,7 +87,7 @@ static const char* BUILTIN_FUNCTIONS[] =
"subtime",
"sysdate",
"time",
"timediff"
"timediff",
"timestamp",
"timestampadd",
"timestampdiff",

View File

@ -1264,6 +1264,18 @@ public:
const ExprList* pExclude,
compound_approach_t compound_approach = ANALYZE_COMPOUND_SELECTS)
{
if (pSelect->pLimit)
{
// In case there is an ORDER BY statement without a LIMIT, which is
// not accepted by sqlite, a pseudo LIMIT with the value of -1 is injected.
// We need to detect that so as not to incorrectly claim that there is
// a clause. See maxscale_create_pseudo_limit() in parse.y.
if (pSelect->pLimit->op != TK_INTEGER || pSelect->pLimit->u.iValue != -1)
{
m_has_clause = true;
}
}
if (pSelect->pSrc)
{
const SrcList* pSrc = pSelect->pSrc;
@ -1330,6 +1342,14 @@ public:
#endif
}
if (pSelect->pOrderBy)
{
update_field_infos_from_exprlist(&aliases,
context,
pSelect->pOrderBy,
pSelect->pEList);
}
if (pSelect->pWith)
{
update_field_infos_from_with(&aliases, context, pSelect->pWith);
@ -1872,6 +1892,9 @@ public:
QcAliases aliases;
uint32_t context = 0;
update_field_infos_from_select(aliases, context, pSelect, NULL);
// Non-sensical to claim that a "CREATE ... SELECT ... WHERE ..." statement has a clause.
m_has_clause = false;
}
else if (pOldTable)
{
@ -2038,7 +2061,7 @@ public:
m_type_mask = QUERY_TYPE_WRITE;
m_operation = QUERY_OP_UPDATE;
update_names_from_srclist(&aliases, pTabList);
m_has_clause = (pWhere ? true : false);
m_has_clause = ((pWhere && pWhere->op != TK_IN) ? true : false);
if (pChanges)
{

View File

@ -135,6 +135,8 @@ extern void maxscaleUse(Parse*, Token*);
extern void maxscale_update_function_info(const char* name, const Expr* pExpr);
extern void maxscale_set_type_mask(unsigned int type_mask);
static Expr* maxscale_create_pseudo_limit(Parse* pParse, Token* pToken, ExprSpan* pLimit);
// Exposed utility functions
void exposed_sqlite3ExprDelete(sqlite3 *db, Expr *pExpr)
{
@ -1528,12 +1530,14 @@ cmd ::= with(C) DELETE FROM fullname(X) indexed_opt(I) where_opt(W)
sqlite3WithPush(pParse, C, 1);
sqlite3SrcListIndexedBy(pParse, X, &I);
#ifdef MAXSCALE
// We are not interested in the order by or limit information.
// Thus we simply delete it. sqlite also has some limitations, which
// will not bother us if we hide the information from it.
sqlite3ExprListDelete(pParse->db, O);
sqlite3ExprDelete(pParse->db, L.pLimit);
sqlite3ExprDelete(pParse->db, L.pOffset);
Token token;
ExprSpan limit;
if (O && !L.pLimit) {
L.pLimit = maxscale_create_pseudo_limit(pParse, &token, &limit);
sqlite3ExprDelete(pParse->db, L.pOffset);
L.pOffset = 0;
}
W = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset, "DELETE");
mxs_sqlite3DeleteFrom(pParse,X,W,0);
#else
W = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset, "DELETE");
@ -1690,12 +1694,15 @@ cmd ::= with(C) UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y)
sqlite3SrcListIndexedBy(pParse, X, &I);
sqlite3ExprListCheckLength(pParse,Y,"set list");
#ifdef MAXSCALE
// We are not interested in the order by or limit information.
// Thus we simply delete it. sqlite also has some limitations, which
// will not bother us if we hide the information from it.
sqlite3ExprListDelete(pParse->db, O);
sqlite3ExprDelete(pParse->db, L.pLimit);
sqlite3ExprDelete(pParse->db, L.pOffset);
Token token;
ExprSpan limit;
if (O && !L.pLimit) {
L.pLimit = maxscale_create_pseudo_limit(pParse, &token, &limit);
sqlite3ExprDelete(pParse->db, L.pOffset);
L.pOffset = 0;
}
W = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset, "UPDATE");
mxs_sqlite3Update(pParse,X,Y,W,R);
#else
W = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset, "UPDATE");
@ -3525,3 +3532,21 @@ cmd ::= DECLARE. {
}
%endif
%include {
static Expr* maxscale_create_pseudo_limit(Parse* pParse, Token* pToken, ExprSpan* pLimit)
{
// sqlite3 does not accept a ORDER BY without LIMIT, but MariaDB
// does. Thus, to make sqlite3LimitWhere return non-NULL we need
// to inject a LIMIT if there is none. We use a value of -1 to
// tell update_field_infos_from_select() that this LIMIT should
// not be counted as a limiting clause.
static char one[] = "-1";
pToken->z = one;
pToken->n = 1;
spanExpr(pLimit, pParse, TK_INTEGER, pToken);
return pLimit->pExpr;
}
}