Skip to content

Commit b8c7bd5

Browse files
authored
Support the "total" aggregator to fix #1530
1 parent 5b8054a commit b8c7bd5

File tree

9 files changed

+650
-558
lines changed

9 files changed

+650
-558
lines changed

src/38query.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,11 @@ function queryfn3(query) {
148148
if (query.selectGroup.length > 0) {
149149
// console.log(query.selectGroup);
150150
query.selectGroup.forEach(function (sg) {
151-
if (sg.aggregatorid == 'COUNT' || sg.aggregatorid == 'SUM') {
151+
if (
152+
sg.aggregatorid == 'COUNT' ||
153+
sg.aggregatorid == 'SUM' ||
154+
sg.aggregatorid == 'TOTAL'
155+
) {
152156
g[sg.nick] = 0;
153157
} else {
154158
g[sg.nick] = undefined;

src/423groupby.js

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -142,18 +142,31 @@ if(false) {
142142
// if(col instanceof yy.Column) colas = col.columnid;
143143
// else colas = col.toString();
144144
// };
145+
let colExpIfFunIdExists = (expression) => {
146+
let colexpression = expression.args[0];
147+
return colexpression.toJS('p', tableid, defcols);
148+
};
145149
if (col instanceof yy.AggrValue) {
146150
if (col.distinct) {
147151
aft +=
148152
",g['$$_VALUES_" + colas + "']={},g['$$_VALUES_" + colas + "'][" + colexp + ']=true';
149153
}
150154
if (col.aggregatorid === 'SUM') {
151155
if ('funcid' in col.expression) {
152-
let colexpression = col.expression.args[0];
153-
let colexp1 = colexpression.toJS('p', tableid, defcols);
156+
let colexp1 = colExpIfFunIdExists(col.expression);
154157
return `'${colas}':(${colexp1})|| typeof ${colexp1} == 'number' ? ${colexp1} : null,`;
155158
}
156159
return `'${colas}':(${colexp})|| typeof ${colexp} == 'number' ? ${colexp} : null,`;
160+
} else if (col.aggregatorid === 'TOTAL') {
161+
if ('funcid' in col.expression) {
162+
let colexp1 = colExpIfFunIdExists(col.expression);
163+
return `'${colas}':(${colexp1}) || typeof ${colexp1} == 'number' ?
164+
${colexp1} : ${colexp1} == 'string' && typeof Number(${colexp1}) == 'number' ? Number(${colexp1}) :
165+
typeof ${colexp1} == 'boolean' ? Number(${colexp1}) : 0,`;
166+
}
167+
return `'${colas}':(${colexp})|| typeof ${colexp} == 'number' ?
168+
${colexp} : ${colexp} == 'string' && typeof Number(${colexp}) == 'number' ? Number(${colexp}) :
169+
typeof ${colexp} === 'boolean' ? Number(${colexp}) : 0,`;
157170
} else if (
158171
col.aggregatorid === 'FIRST' ||
159172
col.aggregatorid === 'LAST'
@@ -163,17 +176,15 @@ if(false) {
163176
return "'" + colas + "':" + colexp + ','; //f.field.arguments[0].toJS();
164177
} else if (col.aggregatorid === 'MIN') {
165178
if ('funcid' in col.expression) {
166-
let colexpression = col.expression.args[0];
167-
let colexp1 = colexpression.toJS('p', tableid, defcols);
179+
let colexp1 = colExpIfFunIdExists(col.expression);
168180
return `'${colas}': (typeof ${colexp1} == 'number' ? ${colexp1} : typeof ${colexp1} == 'object' ?
169181
typeof Number(${colexp1}) == 'number' && ${colexp1}!== null? ${colexp1} : null : null),`;
170182
}
171183
return `'${colas}': (typeof ${colexp} == 'number' ? ${colexp} : typeof ${colexp} == 'object' ?
172184
typeof Number(${colexp}) == 'number' && ${colexp}!== null? ${colexp} : null : null),`;
173185
} else if (col.aggregatorid === 'MAX') {
174186
if ('funcid' in col.expression) {
175-
let colexpression = col.expression.args[0];
176-
let colexp1 = colexpression.toJS('p', tableid, defcols);
187+
let colexp1 = colExpIfFunIdExists(col.expression);
177188
return `'${colas}' : (typeof ${colexp1} == 'number' ? ${colexp1} : typeof ${colexp1} == 'object' ?
178189
typeof Number(${colexp1}) == 'number' ? ${colexp1} : null : null),`;
179190
}
@@ -308,7 +319,10 @@ if(false) {
308319
// }
309320
*/
310321
var colexp = col.expression.toJS('p', tableid, defcols);
311-
322+
let colExpIfFunIdExists = (expression) => {
323+
let colexpression = expression.args[0];
324+
return colexpression.toJS('p', tableid, defcols);
325+
};
312326
if (col instanceof yy.AggrValue) {
313327
var pre = '',
314328
post = '';
@@ -325,11 +339,10 @@ if(false) {
325339
}
326340
if (col.aggregatorid === 'SUM') {
327341
if ('funcid' in col.expression) {
328-
let colexpression = col.expression.args[0];
329-
let colexp1 = colexpression.toJS('p', tableid, defcols);
342+
let colexp1 = colExpIfFunIdExists(col.expression);
330343
return (
331344
pre +
332-
`if(g['${colas}'] == null && ${colexp1} == null){g['${colas}'] = null}
345+
`if(g['${colas}'] == null && ${colexp1} == null){g['${colas}'] = null}
333346
else if(typeof g['${colas}']!== 'object' && typeof g['${colas}']!== 'number' && typeof ${colexp1}!== 'object' && typeof ${colexp1}!== 'number'){g['${colas}'] = null}
334347
else if(typeof g['${colas}']!== 'object' && typeof g['${colas}']!== 'number' && typeof ${colexp1} == 'number'){g['${colas}'] = ${colexp1}}
335348
else if(typeof g['${colas}']!== 'number' && typeof ${colexp1}!== 'number' && typeof ${colexp1}!== 'object'){g['${colas}'] = g['${colas}']}
@@ -352,7 +365,29 @@ if(false) {
352365
else{g['${colas}'] += ${colexp}||0}` +
353366
post
354367
);
355-
} else if (col.aggregatorid === 'COUNT') {
368+
} else if (col.aggregatorid === 'TOTAL') {
369+
if ('funcid' in col.expression) {
370+
let colexp1 = colExpIfFunIdExists(col.expression);
371+
return (
372+
pre +
373+
`if(typeof g['${colas}'] == 'string' && !isNaN(g['${colas}']) && typeof Number(g['${colas}']) == 'number' &&
374+
typeof ${colexp1} == 'string' && !isNaN(${colexp1}) && typeof Number(${colexp1}) == 'number'){g['${colas}'] = Number(g['${colas}']) + Number(${colexp1})}
375+
else if(typeof g['${colas}'] == 'string' && typeof ${colexp1} == 'string'){g['${colas}'] = 0}
376+
else if(typeof g['${colas}'] == 'string' && typeof ${colexp1} == 'number'){g['${colas}'] = ${colexp1}}
377+
else if(typeof ${colexp1} == 'string' && typeof g['${colas}'] == 'number'){g['${colas}'] = g['${colas}']}
378+
else{g['${colas}'] += ${colexp1}||0}`
379+
+ post
380+
);
381+
}
382+
return pre +
383+
`if(typeof g['${colas}'] == 'string' && !isNaN(g['${colas}']) && typeof Number(g['${colas}']) == 'number' &&
384+
typeof ${colexp} == 'string' && !isNaN(${colexp}) && typeof Number(${colexp}) == 'number'){g['${colas}'] = Number(g['${colas}']) + Number(${colexp})}
385+
else if(typeof g['${colas}'] == 'string' && typeof ${colexp} == 'string'){g['${colas}'] = 0}
386+
else if(typeof g['${colas}'] == 'string' && typeof ${colexp} == 'number'){g['${colas}'] = ${colexp}}
387+
else if(typeof ${colexp} == 'string' && typeof g['${colas}'] == 'number'){g['${colas}'] = g['${colas}']}
388+
else{g['${colas}'] += ${colexp}||0}`
389+
+ post
390+
}else if (col.aggregatorid === 'COUNT') {
356391
// console.log(221,col.expression.columnid == '*');
357392
if (col.expression.columnid === '*') {
358393
return pre + "g['" + colas + "']++;" + post;
@@ -373,8 +408,7 @@ if(false) {
373408
return pre + "g['" + colas + "'].push(" + colexp + ');' + post;
374409
} else if (col.aggregatorid === 'MIN') {
375410
if ('funcid' in col.expression) {
376-
let colexpression = col.expression.args[0];
377-
let colexp1 = colexpression.toJS('p', tableid, defcols);
411+
let colexp1 = colExpIfFunIdExists(col.expression);
378412
return (
379413
pre +
380414
`if((g['${colas}'] == null && ${colexp1}!== null) ? y = ${colexp1} : (g['${colas}']!== null &&
@@ -398,8 +432,7 @@ if(false) {
398432
);
399433
} else if (col.aggregatorid === 'MAX') {
400434
if ('funcid' in col.expression) {
401-
let colexpression = col.expression.args[0];
402-
let colexp1 = colexpression.toJS('p', tableid, defcols);
435+
let colexp1 = colExpIfFunIdExists(col.expression);
403436
return (
404437
pre +
405438
`if((y=${colexp1}) > g['${colas}']){if(typeof y == 'number'){g['${colas}'] = y;}
@@ -482,6 +515,7 @@ if(false) {
482515

483516
// s += ' group.amt += rec.emplid;';
484517
// s += 'group.count++;';
518+
//console.log(JSON.stringify(s));
485519
s += '}';
486520
});
487521

src/424select.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@ yy.Select.prototype.compileSelect1 = function (query, params) {
125125
//console.log(42,87,this.columns);
126126

127127
this.columns.forEach(function (col) {
128-
//console.log(col);
129128
if (col instanceof yy.Column) {
130129
if (col.columnid === '*') {
131130
if (col.func) {
@@ -291,7 +290,8 @@ yy.Select.prototype.compileSelect1 = function (query, params) {
291290
col.aggregatorid === 'LAST' ||
292291
col.aggregatorid === 'AVG' ||
293292
col.aggregatorid === 'ARRAY' ||
294-
col.aggregatorid === 'REDUCE'
293+
col.aggregatorid === 'REDUCE' ||
294+
col.aggregatorid === 'TOTAL'
295295
) {
296296
ss.push(
297297
"'" +
@@ -366,7 +366,6 @@ yy.Select.prototype.compileSelect2 = function (query, params) {
366366
query.removeKeys.push(key);
367367
});
368368
}
369-
370369
return new Function('p,params,alasql', 'var y;' + s + 'return r');
371370
};
372371

src/427pivot.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ yy.Select.prototype.compilePivot = function (query) {
7878
newcols.push(d[columnid]);
7979
}
8080

81-
if (aggr == 'SUM' || aggr == 'AVG') {
81+
if (aggr == 'SUM' || aggr == 'AVG' || aggr == 'TOTAL') {
8282
if (typeof g[d[columnid]] == 'undefined') g[d[columnid]] = 0;
8383
g[d[columnid]] += +d[exprcolid];
8484
} else if (aggr == 'COUNT') {

src/50expression.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1005,7 +1005,7 @@
10051005

10061006
toType() {
10071007
if (
1008-
['SUM', 'COUNT', 'AVG', 'MIN', 'MAX', 'AGGR', 'VAR', 'STDDEV'].indexOf(this.aggregatorid) >
1008+
['SUM', 'COUNT', 'AVG', 'MIN', 'MAX', 'AGGR', 'VAR', 'STDDEV', 'TOTAL'].indexOf(this.aggregatorid) >
10091009
-1
10101010
) {
10111011
return 'number';

src/alasqlparser.jison

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ SETS return 'SET'
237237
'STRATEGY' return 'STRATEGY'
238238
'STORE' return 'STORE'
239239
'SUM' return 'SUM'
240+
'TOTAL' return 'TOTAL'
240241
'TABLE' return 'TABLE'
241242
'TABLES' return 'TABLE'
242243
'TARGET' return 'TARGET'
@@ -318,7 +319,6 @@ SETS return 'SET'
318319
'~' return 'TILDA'
319320

320321
[0-9]*[a-zA-Z_]+[a-zA-Z_0-9]* return 'LITERAL'
321-
322322
<<EOF>> return 'EOF'
323323
. return 'INVALID'
324324

@@ -1355,6 +1355,7 @@ OverOrderByClause
13551355
;
13561356
Aggregator
13571357
: SUM { $$ = "SUM"; }
1358+
| TOTAL { $$ = "TOTAL"; }
13581359
| COUNT { $$ = "COUNT"; }
13591360
| MIN { $$ = "MIN"; }
13601361
| MAX { $$ = "MAX"; }

src/alasqlparser.js

Lines changed: 481 additions & 476 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/test229.js

Lines changed: 60 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -39,26 +39,26 @@ describe('Test 229 Calculating simple running totals', function () {
3939
var res = alasql(
4040
'SELECT a.id, a.[value], (SELECT SUM(b.[value]) \
4141
FROM RunTotalTestData b \
42-
WHERE b.id <= a.id) AS total \
42+
WHERE b.id <= a.id) AS c \
4343
FROM RunTotalTestData a \
4444
ORDER BY a.id;'
4545
);
4646
// console.log(res);
4747
assert.deepEqual(res, [
48-
{id: 1, value: 1, total: 1},
49-
{id: 2, value: 2, total: 3},
50-
{id: 3, value: 4, total: 7},
51-
{id: 4, value: 7, total: 14},
52-
{id: 5, value: 9, total: 23},
53-
{id: 6, value: 12, total: 35},
54-
{id: 7, value: 13, total: 48},
55-
{id: 8, value: 16, total: 64},
56-
{id: 9, value: 22, total: 86},
57-
{id: 10, value: 42, total: 128},
58-
{id: 11, value: 57, total: 185},
59-
{id: 12, value: 58, total: 243},
60-
{id: 13, value: 59, total: 302},
61-
{id: 14, value: 60, total: 362},
48+
{id: 1, value: 1, c: 1},
49+
{id: 2, value: 2, c: 3},
50+
{id: 3, value: 4, c: 7},
51+
{id: 4, value: 7, c: 14},
52+
{id: 5, value: 9, c: 23},
53+
{id: 6, value: 12, c: 35},
54+
{id: 7, value: 13, c: 48},
55+
{id: 8, value: 16, c: 64},
56+
{id: 9, value: 22, c: 86},
57+
{id: 10, value: 42, c: 128},
58+
{id: 11, value: 57, c: 185},
59+
{id: 12, value: 58, c: 243},
60+
{id: 13, value: 59, c: 302},
61+
{id: 14, value: 60, c: 362},
6262
]);
6363
//};
6464

@@ -67,28 +67,28 @@ describe('Test 229 Calculating simple running totals', function () {
6767

6868
it('3. Select accumulated sum', function (done) {
6969
var res = alasql(
70-
'SELECT a.id, a.[value], SUM(b.[value]) AS total \
70+
'SELECT a.id, a.[value], SUM(b.[value]) AS c \
7171
FROM RunTotalTestData a, \
7272
RunTotalTestData b \
7373
WHERE b.id <= a.id \
7474
GROUP BY a.id, a.[value] \
7575
ORDER BY a.id'
7676
);
7777
assert.deepEqual(res, [
78-
{id: 1, value: 1, total: 1},
79-
{id: 2, value: 2, total: 3},
80-
{id: 3, value: 4, total: 7},
81-
{id: 4, value: 7, total: 14},
82-
{id: 5, value: 9, total: 23},
83-
{id: 6, value: 12, total: 35},
84-
{id: 7, value: 13, total: 48},
85-
{id: 8, value: 16, total: 64},
86-
{id: 9, value: 22, total: 86},
87-
{id: 10, value: 42, total: 128},
88-
{id: 11, value: 57, total: 185},
89-
{id: 12, value: 58, total: 243},
90-
{id: 13, value: 59, total: 302},
91-
{id: 14, value: 60, total: 362},
78+
{id: 1, value: 1, c: 1},
79+
{id: 2, value: 2, c: 3},
80+
{id: 3, value: 4, c: 7},
81+
{id: 4, value: 7, c: 14},
82+
{id: 5, value: 9, c: 23},
83+
{id: 6, value: 12, c: 35},
84+
{id: 7, value: 13, c: 48},
85+
{id: 8, value: 16, c: 64},
86+
{id: 9, value: 22, c: 86},
87+
{id: 10, value: 42, c: 128},
88+
{id: 11, value: 57, c: 185},
89+
{id: 12, value: 58, c: 243},
90+
{id: 13, value: 59, c: 302},
91+
{id: 14, value: 60, c: 362},
9292
]);
9393

9494
done();
@@ -147,26 +147,26 @@ ORDER BY a.id;'
147147
'SELECT a.[value]%2 as even, a.id, a.[value], (SELECT SUM(b.[value]) \
148148
FROM RunTotalTestData b \
149149
WHERE b.id <= a.id \
150-
AND b.[value]%2 = a.[value]%2) as total \
150+
AND b.[value]%2 = a.[value]%2) as c \
151151
FROM RunTotalTestData a \
152152
ORDER BY [value]%2, a.id;'
153153
);
154154

155155
assert.deepEqual(res, [
156-
{even: 0, id: 2, value: 2, total: 2},
157-
{even: 0, id: 3, value: 4, total: 6},
158-
{even: 0, id: 6, value: 12, total: 18},
159-
{even: 0, id: 8, value: 16, total: 34},
160-
{even: 0, id: 9, value: 22, total: 56},
161-
{even: 0, id: 10, value: 42, total: 98},
162-
{even: 0, id: 12, value: 58, total: 156},
163-
{even: 0, id: 14, value: 60, total: 216},
164-
{even: 1, id: 1, value: 1, total: 1},
165-
{even: 1, id: 4, value: 7, total: 8},
166-
{even: 1, id: 5, value: 9, total: 17},
167-
{even: 1, id: 7, value: 13, total: 30},
168-
{even: 1, id: 11, value: 57, total: 87},
169-
{even: 1, id: 13, value: 59, total: 146},
156+
{even: 0, id: 2, value: 2, c: 2},
157+
{even: 0, id: 3, value: 4, c: 6},
158+
{even: 0, id: 6, value: 12, c: 18},
159+
{even: 0, id: 8, value: 16, c: 34},
160+
{even: 0, id: 9, value: 22, c: 56},
161+
{even: 0, id: 10, value: 42, c: 98},
162+
{even: 0, id: 12, value: 58, c: 156},
163+
{even: 0, id: 14, value: 60, c: 216},
164+
{even: 1, id: 1, value: 1, c: 1},
165+
{even: 1, id: 4, value: 7, c: 8},
166+
{even: 1, id: 5, value: 9, c: 17},
167+
{even: 1, id: 7, value: 13, c: 30},
168+
{even: 1, id: 11, value: 57, c: 87},
169+
{even: 1, id: 13, value: 59, c: 146},
170170
]);
171171

172172
done();
@@ -178,7 +178,7 @@ ORDER BY [value]%2, a.id;'
178178
};
179179

180180
var res = alasql(
181-
'SELECT [value]%2 AS even, id, [value], SUM(b.[value]) AS total \
181+
'SELECT [value]%2 AS even, id, [value], SUM(b.[value]) AS c \
182182
FROM RunTotalTestData a, \
183183
RunTotalTestData b \
184184
WHERE a.[value]%2 = b.[value]%2 \
@@ -188,20 +188,20 @@ ORDER BY [value]%2, a.id;'
188188
);
189189

190190
assert.deepEqual(res, [
191-
{even: 0, id: 2, value: 2, total: 2},
192-
{even: 0, id: 3, value: 4, total: 6},
193-
{even: 0, id: 6, value: 12, total: 18},
194-
{even: 0, id: 8, value: 16, total: 34},
195-
{even: 0, id: 9, value: 22, total: 56},
196-
{even: 0, id: 10, value: 42, total: 98},
197-
{even: 0, id: 12, value: 58, total: 156},
198-
{even: 0, id: 14, value: 60, total: 216},
199-
{even: 1, id: 1, value: 1, total: 1},
200-
{even: 1, id: 4, value: 7, total: 8},
201-
{even: 1, id: 5, value: 9, total: 17},
202-
{even: 1, id: 7, value: 13, total: 30},
203-
{even: 1, id: 11, value: 57, total: 87},
204-
{even: 1, id: 13, value: 59, total: 146},
191+
{even: 0, id: 2, value: 2, c: 2},
192+
{even: 0, id: 3, value: 4, c: 6},
193+
{even: 0, id: 6, value: 12, c: 18},
194+
{even: 0, id: 8, value: 16, c: 34},
195+
{even: 0, id: 9, value: 22, c: 56},
196+
{even: 0, id: 10, value: 42, c: 98},
197+
{even: 0, id: 12, value: 58, c: 156},
198+
{even: 0, id: 14, value: 60, c: 216},
199+
{even: 1, id: 1, value: 1, c: 1},
200+
{even: 1, id: 4, value: 7, c: 8},
201+
{even: 1, id: 5, value: 9, c: 17},
202+
{even: 1, id: 7, value: 13, c: 30},
203+
{even: 1, id: 11, value: 57, c: 87},
204+
{even: 1, id: 13, value: 59, c: 146},
205205
]);
206206

207207
done();

0 commit comments

Comments
 (0)