alasql
Version:
AlaSQL.js - JavaScript SQL database library for relational and graph data manipulation with support of localStorage, IndexedDB, and Excel
295 lines (243 loc) • 10.1 kB
JavaScript
/*
//
// Select compiler part for Alasql.js
// Date: 03.11.2014
// (c) 2014, Andrey Gershun
//
*/
/**
Compile group of statements
*/
yy.Select.prototype.compileGroup = function(query) {
// console.log(this.group);
var self = this;
if(query.sources.length > 0) {
var tableid = query.sources[0].alias;
} else {
// If SELECT contains group aggregators without source tables
var tableid = '';
}
var defcols = query.defcols;
// console.log(16,tableid, defcols);
// console.log(query.sources[0].alias,query.defcols);
var allgroup = [[]];
if(this.group) {
allgroup = decartes(this.group,query);
}
// console.log(23,allgroup);
// console.log(allgroup);
// Prepare groups
//var allgroup = [['a'], ['a','b'], ['a', 'b', 'c']];
// Union all arrays to get a maximum
var allgroups = [];
allgroup.forEach(function(a){
allgroups = arrayUnion(allgroups, a);
});
query.allgroups = allgroups;
//console.log(42,294, this.group);
//console.log(allgroups);
// console.log(42,364,query.selectColumns)
if(false) {
allgroups.forEach(function(col2){
// console.log(42,365,colid, query.selectColumns[colid])
if(query.selectColumns[colid]) {
// console.log(colid,'ok');
} else {
// if(colid.indexOf())
// console.log(colid,'bad');
var tmpid = 'default';
if(query.sources.length > 0) tmpid = query.sources[0].alias;
// console.log(new yy.Column({columnid:colid}).toJavaScript('p',query.sources[0].alias));
// query.selectfns += 'r[\''+colid+'\']=p[\''+tmpid+'\'][\''+colid+'\'];';
//console.log(374, colid);
if(Object.keys(query.selectColumns).length != 0) query.removeKeys.push(colid);
query.selectfns += 'r[\''+escapeq(colid)+'\']='+(new yy.Column({columnid:colid}).toJavaScript('p',tmpid))+';';
}
});
};
// Create negative array
var s = '';
// s+= query.selectfns;
allgroup.forEach(function(agroup) {
//console.log(agroup);
// Start of group function
s += 'var acc,g=this.xgroups[';
// var gcols = this.group.map(function(col){return col.columnid}); // Group fields with r
// Array with group columns from record
var rg = agroup.map(function(col2){
var columnid = col2.split('\t')[0];
var coljs = col2.split('\t')[1];
// Check, if aggregator exists but GROUP BY is not exists
if(columnid == '') return '1'; // Create fictive groupping column for fictive GROUP BY
// else return "r['"+columnid+"']";
else return coljs;
});
if(rg.length == 0) rg = ["''"];
// console.log('rg',rg);
s += rg.join('+"`"+');
s += '];if(!g) {this.groups.push((g=this.xgroups[';
s += rg.join('+"`"+');
s += '] = {';
// s += ']=r';
s += agroup.map(function(col2){
var columnid = col2.split('\t')[0];
var coljs = col2.split('\t')[1];
if(columnid == '') return '';
else return "'"+columnid+"':"+coljs+",";
}).join('');
var neggroup = arrayDiff(allgroups,agroup);
// console.log(neggroup);
s += neggroup.map(function(col2){
var columnid = col2.split('\t')[0];
var coljs = col2.split('\t')[1]
return "'"+columnid+"':null,";
}).join('');
var aft = '';
// s += self.columns.map(function(col){
//console.log('query.selectGroup',query.selectGroup);
s += query.selectGroup.map(function(col,idx){
//console.log(idx, col.toString(), col.as);
var colexp = col.expression.toJavaScript("p",tableid,defcols);
var colas = col.nick;
// if(typeof colas == 'undefined') {
// if(col instanceof yy.Column) colas = col.columnid;
// else colas = col.toString();
// };
if (col instanceof yy.AggrValue) {
if(col.distinct) {
aft += ',g[\'$$_VALUES_'+colas+'\']={},g[\'$$_VALUES_'+colas+'\']['+colexp+']=true';
};
if (col.aggregatorid == 'SUM'
|| col.aggregatorid == 'MIN'
|| col.aggregatorid == 'MAX'
|| col.aggregatorid == 'FIRST'
|| col.aggregatorid == 'LAST'
// || col.aggregatorid == 'AVG'
// ) { return '\''+col.as+'\':r[\''+col.as+'\'],'; }//f.field.arguments[0].toJavaScript();
) { return '\''+colas+'\':'+colexp+','; }//f.field.arguments[0].toJavaScript();
else if(col.aggregatorid == 'ARRAY') {
return '\''+colas+'\':['+colexp+'],';
} else if(col.aggregatorid == 'COUNT') {
if(col.expression.columnid == '*') {
return '\''+colas+'\':1,';
} else {
// return '\''+colas+'\':(typeof '+colexp+' != "undefined")?1:0,';
// } else {
return '\''+colas+'\':(typeof '+colexp+' != "undefined")?1:0,';
}
// else if(col.aggregatorid == 'MIN') { return '\''+col.as+'\':r[\''+col.as+'\'],'; }
// else if(col.aggregatorid == 'MAX') { return '\''+col.as+'\':r[\''+col.as+'\'],'; }
} else if(col.aggregatorid == 'AVG') {
query.removeKeys.push('_SUM_'+colas);
query.removeKeys.push('_COUNT_'+colas);
return '\''+colas+'\':'+colexp+',\'_SUM_'+colas+'\':'+colexp+',\'_COUNT_'+colas+'\':1,';
} else if(col.aggregatorid == 'AGGR') {
aft += ',g[\''+colas+'\']='+col.expression.toJavaScript('g',-1);
return '';
} else if(col.aggregatorid == 'REDUCE') {
query.removeKeys.push('_REDUCE_'+colas);
return '\''+colas+'\':alasql.aggr[\''+col.funcid+'\']('+colexp+',undefined,(acc={})),'
+'\'__REDUCE__'+colas+'\':acc,';
}
return '';
} else return '';
}).join('');
// columnid:r.columnid
// var srg = [];//rg.map(function(fn){ return (fn+':'+fn); });
// var srg = this.group.map(function(col){
// if(col == '') return '';
// else return col.columnid+':'+col.toJavaScript('r','');
// });
// Initializw aggregators
/*
this.columns.forEach(function(col){
// console.log(f);
// if(f.constructor.name == 'LiteralValue') return '';
if (col instanceof yy.AggrValue) {
if (col.aggregatorid == 'SUM') { srg.push("'"+col.as+'\':0'); }//f.field.arguments[0].toJavaScript();
else if(col.aggregatorid == 'COUNT') {srg.push( "'"+col.as+'\':0'); }
else if(col.aggregatorid == 'MIN') { srg.push( "'"+col.as+'\':Infinity'); }
else if(col.aggregatorid == 'MAX') { srg.push( "'"+col.as+'\':-Infinity'); }
// else if(col.aggregatorid == 'AVG') { srg.push(col.as+':0'); }
// return 'group.'+f.name.value+'=+(+group.'+f.name.value+'||0)+'+f.field.arguments[0].toJavaScript('rec','')+';'; //f.field.arguments[0].toJavaScript();
};
});
*/
/*****************/
// s += srg.join(',');
// var ss = [];
// gff.forEach(function(fn){
// ss.push(fn+':rec.'+fn);
// });
// s += ss.join(',');
// s += '});};';
s += '}'+aft+',g));} else {';
// console.log(s, this.columns);
// var neggroup = arrayDiff(allgroups,agroup);
// console.log(agroup,neggroup);
// s += neggroup.map(function(columnid){
// return "g['"+columnid+"']=null;";
// }).join('');
// console.log(s);
//console.log(query.selectfn);
// s += self.columns.map(function(col){
s += query.selectGroup.map(function(col,idx){
var colas = col.nick;
// if(typeof colas == 'undefined') {
// if(col instanceof yy.Column) colas = col.columnid;
// else colas = col.toString();
// }
var colexp = col.expression.toJavaScript("p",tableid,defcols);
if (col instanceof yy.AggrValue) {
if(col.distinct) {
var pre = 'if(typeof '+colexp+'!="undefined" && (!g[\'$$_VALUES_'+colas+'\']['+colexp+'])) \
{';
var post = 'g[\'$$_VALUES_'+colas+'\']['+colexp+']=true;}';
} else {
var pre = '', post = '';
}
if (col.aggregatorid == 'SUM') { return pre+'g[\''+colas+'\']+='+colexp+';'+post; }//f.field.arguments[0].toJavaScript();
else if(col.aggregatorid == 'COUNT') {
// console.log(221,col.expression.columnid == '*');
if(col.expression.columnid == '*') return pre+'g[\''+colas+'\']++;'+post;
else {
return pre+'if(typeof '+colexp+'!="undefined") g[\''+colas+'\']++;'+post;
}
}
else if(col.aggregatorid == 'ARRAY') { return pre+'g[\''+colas+'\'].push('+colexp+');'+post; }
else if(col.aggregatorid == 'MIN') { return pre+'g[\''+colas+'\']=Math.min(g[\''+colas+'\'],'+colexp+');'+post; }
else if(col.aggregatorid == 'MAX') { return pre+'g[\''+colas+'\']=Math.max(g[\''+colas+'\'],'+colexp+');'+post; }
else if(col.aggregatorid == 'FIRST') { return ''; }
else if(col.aggregatorid == 'LAST') { return pre+'g[\''+colas+'\']='+colexp+';'+post; }
else if(col.aggregatorid == 'AVG') {
return pre+'g[\'_SUM_'+colas+'\']+='+colexp+';'
+ 'g[\'_COUNT_'+colas+'\']++;'
+ 'g[\''+colas+'\']=g[\'_SUM_'+colas+'\']/g[\'_COUNT_'+colas+'\'];'+post;
// }
// else if(col.aggregatorid == 'AVG') { srg.push(colas+':0'); }
} else if(col.aggregatorid == 'AGGR') {
return pre+'g[\''+colas+'\']='+col.expression.toJavaScript('g',-1)+';'+post;
} else if(col.aggregatorid == 'REDUCE') {
return pre+'g[\''+colas+'\']=alasql.aggr.'+col.funcid+'('+colexp+',g[\''+colas+'\'],g[\'__REDUCE__'+colas+'\']);'+post;
}
return '';
} else return '';
}).join('');
// s += selectFields.map(function(f){
// console.log(f);
// if(f.constructor.name == 'LiteralValue') return '';
// if (f.field instanceof SQLParser.nodes.FunctionValue
// && (f.field.name.toUpperCase() == 'SUM' || f.field.name.toUpperCase() == 'COUNT')) {
// return 'group.'+f.name.value+'=+(+group.'+f.name.value+'||0)+'+f.field.arguments[0].toJavaScript('rec','')+';'; //f.field.arguments[0].toJavaScript();
// return 'group.'+f.name.value+'+='+f.field.arguments[0].toJavaScript('rec','')+';'; //f.field.arguments[0].toJavaScript();
// return 'group.'+f.name.value+'+=rec.'+f.name.value+';'; //f.field.arguments[0].toJavaScript();
// };
// return '';
// }).join('');
//s += ' group.amt += rec.emplid;';
//s += 'group.count++;';
s += '}';
});
// console.log('groupfn',s);
return new Function('p,params,alasql',s);
}