alasql
Version:
AlaSQL.js - JavaScript SQL database library for relational and graph data manipulation with support of localStorage, IndexedDB, and Excel
239 lines (203 loc) • 6.32 kB
JavaScript
/*
//
// Functions for Alasql.js
// Date: 03.11.2014
// (c) 2014, Andrey Gershun
//
*/
yy.FuncValue = function(params){ return yy.extend(this, params); }
yy.FuncValue.prototype.toString = function() {
var s = '';
if(alasql.fn[this.funcid]) s += this.funcid;
else if(alasql.aggr[this.funcid]) s += this.funcid;
else if(alasql.stdlib[this.funcid.toUpperCase()] || alasql.stdfn[this.funcid.toUpperCase()]) s += this.funcid.toUpperCase();
s += '(';
if(this.args && this.args.length > 0) {
s += this.args.map(function(arg){
return arg.toString();
}).join(',');
};
s += ')';
if(this.as) s += ' AS '+this.as.toString();
// if(this.alias) s += ' AS '+this.alias;
return s;
}
yy.FuncValue.prototype.findAggregator = function(query) {
if(this.args && this.args.length > 0) {
this.args.forEach(function(arg){
if(arg.findAggregator) arg.findAggregator(query);
});
}
};
yy.FuncValue.prototype.toJavaScript = function(context, tableid, defcols) {
var s = '';
var funcid = this.funcid;
// IF this is standard compile functions
if(alasql.fn[funcid]) {
// This is user-defined run-time function
// TODO arguments!!!
// var s = '';
if(this.newid) s+= 'new ';
s += 'alasql.fn.'+this.funcid+'(';
// if(this.args) s += this.args.toJavaScript(context, tableid);
if(this.args && this.args.length > 0) {
s += this.args.map(function(arg){
return arg.toJavaScript(context, tableid, defcols);
}).join(',');
};
s += ')';
} else if(alasql.stdlib[funcid.toUpperCase()]) {
if(this.args && this.args.length > 0) {
s += alasql.stdlib[funcid.toUpperCase()].apply(this, this.args.map(function(arg) {return arg.toJavaScript(context, tableid)}));
} else {
s += alasql.stdlib[funcid.toUpperCase()]();
}
} else if(alasql.stdfn[funcid.toUpperCase()]) {
if(this.newid) s+= 'new ';
s += 'alasql.stdfn.'+this.funcid.toUpperCase()+'(';
// if(this.args) s += this.args.toJavaScript(context, tableid);
if(this.args && this.args.length > 0) {
s += this.args.map(function(arg){
return arg.toJavaScript(context, tableid, defcols);
}).join(',');
};
s += ')';
} else {
// Aggregator
}
//console.log('userfn:',s,this);
// if(this.alias) s += ' AS '+this.alias;
return s;
}
// // Functions compiler
// nodes.FunctionValue.prototype.toJavaScript = function (context, tableid) {
// var s = '';
// s += fns[this.name.toUpperCase()].apply(null,this.arguments.map(function(arg){
// if(arg) return arg.toJavaScript(context, tableid);
// else return '';
// }));
// return s;
// };
//
// SQL FUNCTIONS COMPILERS
// Based on SQLite functions
// IMPORTANT: These are compiled functions
//alasql.fn = {}; // Keep for compatibility
//alasql.userlib = alasql.fn;
var stdlib = alasql.stdlib = {}
var stdfn = alasql.stdfn = {}
stdlib.ABS = function(a) {return 'Math.abs('+a+')'};
stdlib.CLONEDEEP = function(a) {return 'alasql.utils.cloneDeep('+a+')'};
stdlib.IIF = function(a,b,c) {
if(arguments.length == 3) {
return '(('+a+')?('+b+'):('+c+'))';
} else {
throw new Error('Number of arguments of IFF is not equals to 3');
};
};
stdlib.IFNULL = function(a,b) {return '('+a+'||'+b+')'};
stdlib.INSTR = function(s,p) {return '(('+s+').indexOf('+p+')+1)'};
//stdlib.LEN = stdlib.LENGTH = function(s) {return '('+s+'+"").length';};
stdlib.LEN = stdlib.LENGTH = function(s) {return '('+s+').length';};
//stdlib.LENGTH = function(s) {return '('+s+').length'};
stdlib.LOWER = stdlib.LCASE = function(s) {return '('+s+').toLowerCase()';}
//stdlib.LCASE = function(s) {return '('+s+').toLowerCase()';}
// LTRIM
stdlib.MAX = stdlib.GREATEST = function(){
return 'Math.max('+Array.prototype.join.call(arguments, ',')+')'
};
stdlib.MIN = stdlib.LEAST = function(){
return 'Math.min('+Array.prototype.join.call(arguments, ',')+')'
};
stdlib.MID = function(a,b,c){
if(arguments.length == 2) return '('+a+').substr('+b+'-1)';
else if(arguments.length == 3) return '('+a+').substr('+b+'-1,'+c+')';
};
// Here we uses undefined instead of null
stdlib.NULLIF = function(a,b){return '('+a+'=='+b+'?undefined:'+a+')'};
stdlib.POWER = function(a,b) {return 'Math.pow('+a+','+b+')'};
stdlib.RANDOM = function(r) {
if(arguments.length == 0) {
return 'Math.random()';
} else {
return '(Math.random()*('+r+')|0)';
}
}
stdlib.ROUND = function(s,d) {
if(arguments.length == 2) {
return 'Math.round('+s+'*Math.pow(10,'+d+'))/Math.pow(10,'+d+')';
} else {
return 'Math.round('+s+')';
}
}
stdlib.SQRT = function(s) {return 'Math.sqrt('+s+')'};
stdlib.TRIM = function(s) {return s+'.trim()'};
stdlib.UPPER = stdlib.UCASE = function(s) {return '('+s+').toUpperCase()';}
//stdlib.UCASE = function(s) {return '('+s+').toUpperCase()';}
//REPLACE
// RTRIM
// SUBSTR
// TRIM
//REPLACE
// RTRIM
// SUBSTR
// TRIM
// Aggregator for joining strings
alasql.aggr.GROUP_CONCAT = function(v,s){
if(typeof s == "undefined") return v; else return s+','+v;
};
// Median
alasql.aggr.MEDIAN = function(v,s,acc){
// Init
if(typeof acc.arr == 'undefined') {
acc.arr = [v];
return v;
// Pass
} else {
acc.arr.push(v);
var p = acc.arr.sort();
return p[(p.length/2)|0];
};
};
// Standard deviation
alasql.aggr.VAR = function(v,s,acc){
if(typeof acc.arr == 'undefined') {
acc.arr = [v];
acc.sum = v;
} else {
acc.arr.push(v);
acc.sum += v;
}
var N = acc.arr.length;
var avg = acc.sum / N;
var std = 0;
for(var i=0;i<N;i++) {
std += (acc.arr[i]-avg)*(acc.arr[i]-avg);
}
std = std/(N-1);
return std;
};
alasql.aggr.STDEV = function(v,s,acc){
return Math.sqrt(alasql.aggr.VAR(v,s,acc));
}
// Standard deviation
alasql.aggr.VARP = function(v,s,acc){
if(typeof acc.arr == 'undefined') {
acc.arr = [v];
acc.sum = v;
} else {
acc.arr.push(v);
acc.sum += v;
}
var N = acc.arr.length;
var avg = acc.sum / N;
var std = 0;
for(var i=0;i<N;i++) {
std += (acc.arr[i]-avg)*(acc.arr[i]-avg);
}
std = std/N;
return std;
};
alasql.aggr.STD = alasql.aggr.STDDEV = alasql.aggr.STDEVP = function(v,s,acc){
return Math.sqrt(alasql.aggr.VARP(v,s,acc));
}