MXS-1364 Collect columns referred to by group_concat

This commit is contained in:
Johan Wikman
2017-08-22 14:37:54 +03:00
parent 83ae19cd68
commit 2d6ac6c682
3 changed files with 108 additions and 18 deletions

View File

@ -1178,6 +1178,49 @@ no_mem:
return 0;
}
#ifdef MAXSCALE
/*
** Add an expression list to the end of an expression list. If pList
** is initially NULL, then create a new expression list.
**
** If a memory allocation error occurs, the entire list is freed and
** NULL is returned. If non-NULL is returned, then it is guaranteed
** that the list was successfully appended.
*/
ExprList *sqlite3ExprListAppendList(
Parse *pParse, /* Parsing context */
ExprList *pList, /* List to which to append. Might be NULL */
ExprList *pAppend /* List to be appended. Might be NULL */
){
sqlite3 *db = pParse->db;
int i;
assert( db!=0 );
if (!pAppend) {
return pList;
}
if (!pList) {
return pAppend;
}
for (i = 0; i < pAppend->nExpr; ++i) {
pList = sqlite3ExprListAppend(pParse, pList, pAppend->a[i].pExpr);
if (pList) {
pAppend->a[i].pExpr = NULL;
}
else {
goto no_mem;
}
}
sqlite3ExprListDelete(db, pAppend);
return pList;
no_mem:
sqlite3ExprListDelete(db, pList);
sqlite3ExprListDelete(db, pAppend);
return 0;
}
#endif
/*
** Set the sort order for the last element on the given ExprList.
*/

View File

@ -1869,18 +1869,46 @@ expr(A) ::= CAST(X) LP expr(E) AS typetoken(T) RP(Y). {
}
%endif SQLITE_OMIT_CAST
%ifdef MAXSCALE
group_concat_colname ::= nm.
group_concat_colname ::= nm DOT nm.
group_concat_colnames ::= group_concat_colname.
group_concat_colnames ::= group_concat_colnames COMMA group_concat_colname.
%type group_concat_colname {ExprSpan}
%destructor group_concat_colname {sqlite3ExprDelete(pParse->db, $$.pExpr);}
group_concat_colnames_opt ::= .
group_concat_colnames_opt ::= COMMA group_concat_colnames.
group_concat_colname(A) ::= nm(X). {
spanExpr(&A, pParse, TK_ID, &X);
}
group_concat_order_by ::= ORDER BY INTEGER sortorder group_concat_colnames_opt.
group_concat_order_by ::= ORDER BY col_name(X) sortorder group_concat_colnames_opt. {
sqlite3ExprDelete(pParse->db, X.pExpr);
group_concat_colname(A) ::= nm(X) DOT nm(Y). {
Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y);
A.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
spanSet(&A,&X,&Y);
}
%type group_concat_colnames {ExprList*}
%destructor group_concat_colnames {sqlite3ExprListDelete(pParse->db, $$);}
group_concat_colnames(A) ::= group_concat_colname(Y). {
A = sqlite3ExprListAppend(pParse, 0, Y.pExpr);
}
group_concat_colnames(A) ::= group_concat_colnames(X) COMMA group_concat_colname(Y). {
A = sqlite3ExprListAppend(pParse, X, Y.pExpr);
}
%type group_concat_colnames_opt {ExprList*}
%destructor group_concat_colnames_opt {sqlite3ExprListDelete(pParse->db, $$);}
group_concat_colnames_opt(A) ::= . { A = NULL; }
group_concat_colnames_opt(A) ::= COMMA group_concat_colnames(X). { A = X; }
%type group_concat_order_by {ExprList*}
%destructor group_concat_order_by {sqlite3ExprListDelete(pParse->db, $$);}
group_concat_order_by(A) ::= ORDER BY INTEGER sortorder group_concat_colnames_opt(X). {
A = X;
}
group_concat_order_by(A) ::= ORDER BY col_name(X) sortorder group_concat_colnames_opt(Y). {
A = sqlite3ExprListAppend(pParse, Y, X.pExpr);
}
// TODO: The following causes conflicts.
//group_concat_order_by ::= ORDER BY expr(X) sortorder group_concat_colnames_opt. {
@ -1889,18 +1917,25 @@ group_concat_order_by ::= ORDER BY col_name(X) sortorder group_concat_colnames_o
group_concat_separator ::= SEPARATOR STRING.
group_concat_tail ::= group_concat_order_by.
group_concat_tail ::= group_concat_separator.
group_concat_tail ::= group_concat_order_by group_concat_separator.
%type group_concat_tail {ExprList*}
%destructor group_concat_tail {sqlite3ExprListDelete(pParse->db, $$);}
group_concat_tail(A) ::= group_concat_order_by(X). { A = X; }
group_concat_tail(A) ::= group_concat_separator. { A = NULL; }
group_concat_tail(A) ::= group_concat_order_by(X) group_concat_separator. { A = X; }
convert_tail ::= USING id.
// Since we don't use the arguments for anything, any function can have these
// as trailing arguments. It's ok because if used incorrectly, the server will
// reject the statement
func_arg_tail_opt ::= .
func_arg_tail_opt ::= group_concat_tail.
func_arg_tail_opt ::= convert_tail.
%type func_arg_tail_opt {ExprList*}
%destructor func_arg_tail_opt {sqlite3ExprListDelete(pParse->db, $$);}
func_arg_tail_opt(A) ::= . { A = NULL; }
func_arg_tail_opt(A) ::= group_concat_tail(X). { A = X; }
func_arg_tail_opt(A) ::= convert_tail. { A = NULL; }
wf_partition_by ::= PARTITION BY nexprlist(X). {
sqlite3ExprListDelete(pParse->db, X);
@ -1942,7 +1977,10 @@ wf_frame_opt ::= wf_frame_units wf_frame_extent wf_frame_exclusion_opt .
wf ::= OVER LP wf_window_ref_opt wf_partition_by_opt wf_order_by_opt wf_frame_opt RP.
wf ::= OVER id.
expr(A) ::= id(X) LP distinct(D) exprlist(Y) func_arg_tail_opt RP(E) wf. {
expr(A) ::= id(X) LP distinct(D) exprlist(Y) func_arg_tail_opt(Z) RP(E) wf. {
// We just append Z on Y as we are only interested in what columns
// the function used.
Y = sqlite3ExprListAppendList(pParse, Y, Z);
if( Y && Y->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
sqlite3ErrorMsg(pParse, "too many arguments on function %T", &X);
}
@ -1958,7 +1996,10 @@ expr(A) ::= id(X) LP STAR RP(E) wf. {
spanSet(&A,&X,&E);
}
expr(A) ::= id(X) LP distinct(D) exprlist(Y) func_arg_tail_opt RP(E). {
expr(A) ::= id(X) LP distinct(D) exprlist(Y) func_arg_tail_opt(Z) RP(E). {
// We just append Z on Y as we are only interested in what columns
// the function used.
Y = sqlite3ExprListAppendList(pParse, Y, Z);
%endif
%ifndef MAXSCALE
expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP(E). {
@ -1973,7 +2014,10 @@ expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP(E). {
}
}
%ifdef MAXSCALE
expr(A) ::= nm DOT nm(X) LP distinct(D) exprlist(Y) func_arg_tail_opt RP(E). {
expr(A) ::= nm DOT nm(X) LP distinct(D) exprlist(Y) func_arg_tail_opt(Z) RP(E). {
// We just append Z on Y as we are only interested in what columns
// the function used.
Y = sqlite3ExprListAppendList(pParse, Y, Z);
if( Y && Y->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
sqlite3ErrorMsg(pParse, "too many arguments on function %T", &X);
}

View File

@ -3361,6 +3361,9 @@ Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
void sqlite3ExprAssignVarNumber(Parse*, Expr*);
void sqlite3ExprDelete(sqlite3*, Expr*);
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
#ifdef MAXSCALE
ExprList *sqlite3ExprListAppendList(Parse*,ExprList*,ExprList*);
#endif
void sqlite3ExprListSetSortOrder(ExprList*,int);
void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*);