MXS-1364 Collect columns referred to by group_concat
This commit is contained in:
@ -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.
|
||||
*/
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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*);
|
||||
|
Reference in New Issue
Block a user