0) {
+
+ var tcol = xcolumns[col.columnid];
+
+ if (undefined === tcol) {
+ throw new Error('Column does not exist: ' + col.columnid);
+ }
+
+ var coldef = {
+ columnid: col.as || col.columnid,
+ dbtypeid: tcol.dbtypeid,
+ dbsize: tcol.dbsize,
+ dbpecision: tcol.dbprecision,
+ dbenum: tcol.dbenum,
+ };
+
+ query.columns.push(coldef);
+ query.xcolumns[coldef.columnid] = coldef;
+ } else {
+ var coldef = {
+ columnid: col.as || col.columnid,
+ // dbtypeid:tcol.dbtypeid,
+ // dbsize:tcol.dbsize,
+ // dbpecision:tcol.dbprecision,
+ // dbenum: tcol.dbenum,
+ };
+
+ query.columns.push(coldef);
+ query.xcolumns[coldef.columnid] = coldef;
+
+ query.dirtyColumns = true;
+ }
+ } else {
+ var coldef = {
+ columnid: col.as || col.columnid,
+ // dbtypeid:tcol.dbtypeid,
+ // dbsize:tcol.dbsize,
+ // dbpecision:tcol.dbprecision,
+ // dbenum: tcol.dbenum,
+ };
+
+ query.columns.push(coldef);
+ query.xcolumns[coldef.columnid] = coldef;
+ // This is a subquery?
+ // throw new Error('There is now such table \''+col.tableid+'\'');
+ }
+ }
+ } else if (col instanceof yy.AggrValue) {
+ if (!self.group) {
+ // self.group=[new yy.Column({columnid:'q',as:'q' })];
+ self.group = [''];
+ }
+ if (!col.as) {
+ col.as = escapeq(col.toString());
+ }
+
+ if (
+ col.aggregatorid === 'SUM' ||
+ col.aggregatorid === 'MAX' ||
+ col.aggregatorid === 'MIN' ||
+ col.aggregatorid === 'FIRST' ||
+ col.aggregatorid === 'LAST' ||
+ col.aggregatorid === 'AVG' ||
+ col.aggregatorid === 'ARRAY' ||
+ col.aggregatorid === 'REDUCE'
+ ) {
+ ss.push(
+ "'" +
+ escapeq(col.as) +
+ "':" +
+ n2u(col.expression.toJS('p', query.defaultTableid, query.defcols))
+ );
+ } else if (col.aggregatorid === 'COUNT') {
+ ss.push("'" + escapeq(col.as) + "':1");
+ // Nothing
+ }
+ // todo: confirm that no default action must be implemented
+
+ // query.selectColumns[col.aggregatorid+'('+escapeq(col.expression.toString())+')'] = thtd;
+
+ var coldef = {
+ columnid: col.as || col.columnid || col.toString(),
+ // dbtypeid:tcol.dbtypeid,
+ // dbsize:tcol.dbsize,
+ // dbpecision:tcol.dbprecision,
+ // dbenum: tcol.dbenum,
+ };
+
+ query.columns.push(coldef);
+ query.xcolumns[coldef.columnid] = coldef;
+
+ // else if (col.aggregatorid == 'MAX') {
+ // ss.push((col.as || col.columnid)+':'+col.toJS("p.",query.defaultTableid))
+ // } else if (col.aggregatorid == 'MIN') {
+ // ss.push((col.as || col.columnid)+':'+col.toJS("p.",query.defaultTableid))
+ // }
+ } else {
+
+ ss.push(
+ "'" +
+ escapeq(col.as || col.columnid || col.toString()) +
+ "':" +
+ n2u(col.toJS('p', query.defaultTableid, query.defcols))
+ );
+ // ss.push('\''+escapeq(col.toString())+'\':'+col.toJS("p",query.defaultTableid));
+ //if(col instanceof yy.Expression) {
+ query.selectColumns[escapeq(col.as || col.columnid || col.toString())] = true;
+
+ var coldef = {
+ columnid: col.as || col.columnid || col.toString(),
+ // dbtypeid:tcol.dbtypeid,
+ // dbsize:tcol.dbsize,
+ // dbpecision:tcol.dbprecision,
+ // dbenum: tcol.dbenum,
+ };
+
+ query.columns.push(coldef);
+ query.xcolumns[coldef.columnid] = coldef;
+ }
+ });
+ s += ss.join(',') + '};' + sp;
+ return s;
+
+};
+yy.Select.prototype.compileSelect2 = function(query, params) {
+ var s = query.selectfns;
+ if (this.orderColumns && this.orderColumns.length > 0) {
+ this.orderColumns.forEach(function(v, idx) {
+ var key = '$$$' + idx;
+ if (v instanceof yy.Column && query.xcolumns[v.columnid]) {
+ s += "r['" + key + "']=r['" + v.columnid + "'];";
+ } else if (v instanceof yy.ParamValue && query.xcolumns[params[v.param]]) {
+ s += "r['" + key + "']=r['" + params[v.param] + "'];";
+ } else {
+ s += "r['" + key + "']=" + v.toJS('p', query.defaultTableid, query.defcols) + ';';
+ }
+ query.removeKeys.push(key);
+ });
+ }
+
+ return new Function('p,params,alasql', 'var y;' + s + 'return r');
+};
+
+yy.Select.prototype.compileSelectGroup0 = function(query) {
+ var self = this;
+ self.columns.forEach(function(col, idx) {
+ if (!(col instanceof yy.Column && col.columnid === '*')) {
+ var colas;
+ // = col.as;
+ if (col instanceof yy.Column) {
+ colas = escapeq(col.columnid);
+ } else {
+ colas = escapeq(col.toString(true));
+
+ }
+ for (var i = 0; i < idx; i++) {
+ if (colas === self.columns[i].nick) {
+ colas = self.columns[i].nick + ':' + idx;
+ break;
+ }
+ }
+ // }
+ col.nick = colas;
+
+ if (self.group) {
+ var groupIdx = self.group.findIndex(function(gp) {
+ return gp.columnid === col.columnid && gp.tableid === col.tableid;
+ })
+ if (groupIdx > -1) {
+ self.group[groupIdx].nick = colas;
+ }
+ }
+
+ if (
+ col.funcid &&
+ (col.funcid.toUpperCase() === 'ROWNUM' || col.funcid.toUpperCase() === 'ROW_NUMBER')
+ ) {
+ query.rownums.push(col.as);
+ }
+
+ // }
+ } else {
+ query.groupStar = col.tableid || 'default';
+ }
+ });
+
+ this.columns.forEach(function(col) {
+ if (col.findAggregator) {
+ col.findAggregator(query);
+ }
+ });
+
+ if (this.having) {
+ if (this.having.findAggregator) {
+ this.having.findAggregator(query);
+ }
+ }
+};
+
+yy.Select.prototype.compileSelectGroup1 = function(query) {
+ var self = this;
+ var s = 'var r = {};';
+
+ self.columns.forEach(function(col) {
+
+ if (col instanceof yy.Column && col.columnid === '*') {
+ // s += 'for(var k in g){r[k]=g[k]};';
+ // s += 'for(var k in this.query.groupColumns){r[k]=g[this.query.groupColumns[k]]};';
+
+ s += 'for(var k in g) {r[k]=g[k]};';
+ return '';
+
+ } else {
+ // var colas = col.as;
+ var colas = col.as;
+ if (colas === undefined) {
+ if (col instanceof yy.Column) {
+ colas = escapeq(col.columnid);
+ } else {
+ colas = col.nick;
+ }
+ }
+ query.groupColumns[colas] = col.nick;
+
+ // if(col.as) {
+ s += "r['" + colas + "']=";
+ // // } else {
+ // // s += 'r[\''+escapeq()+'\']=';
+ // // };
+ // // s += ';';
+
+ s += n2u(col.toJS('g', '')) + ';';
+
+ for (var i = 0; i < query.removeKeys.length; i++) {
+ // THis part should be intellectual
+ if (query.removeKeys[i] === colas) {
+ query.removeKeys.splice(i, 1);
+ break;
+ }
+ }
+ }
+ });
+ // return new Function('g,params,alasql',s+'return r');
+ return s;
+};
+
+yy.Select.prototype.compileSelectGroup2 = function(query) {
+ var self = this;
+ var s = query.selectgfns;
+ self.columns.forEach(function(col) {
+
+ if (query.ingroup.indexOf(col.nick) > -1) {
+ s += "r['" + (col.as || col.nick) + "']=g['" + col.nick + "'];";
+ }
+ });
+
+ if (this.orderColumns && this.orderColumns.length > 0) {
+ this.orderColumns.forEach(function(v, idx) {
+
+ var key = '$$$' + idx;
+
+ if (v instanceof yy.Column && query.groupColumns[v.columnid]) {
+ s += "r['" + key + "']=r['" + v.columnid + "'];";
+ } else {
+ s += "r['" + key + "']=" + v.toJS('g', '') + ';';
+ }
+ query.removeKeys.push(key);
+ });
+ }
+
+ return new Function('g,params,alasql', 'var y;' + s + 'return r');
+};
+
+// SELECY * REMOVE [COLUMNS] col-list, LIKE ''
+yy.Select.prototype.compileRemoveColumns = function(query) {
+ var self = this;
+ if (typeof this.removecolumns !== 'undefined') {
+ query.removeKeys = query.removeKeys.concat(
+ this.removecolumns
+ .filter(function(column) {
+ return typeof column.like === 'undefined';
+ })
+ .map(function(column) {
+ return column.columnid;
+ })
+ );
+
+ query.removeLikeKeys = this.removecolumns
+ .filter(function(column) {
+ return typeof column.like !== 'undefined';
+ })
+ .map(function(column) {
+ // return new RegExp((column.like.value||'').replace(/\%/g,'.*').replace(/\?|_/g,'.'),'g');
+ return column.like.value;
+ });
+ }
+};
+
+/* global yy */
+
+yy.Select.prototype.compileHaving = function(query) {
+ if (this.having) {
+ var s = this.having.toJS('g', -1);
+ query.havingfns = s;
+
+ return new Function('g,params,alasql', 'var y;return ' + s);
+ }
+
+ return function() {
+ return true;
+ };
+};
+
+yy.Select.prototype.compileOrder = function(query, params) {
+ var self = this;
+ self.orderColumns = [];
+ if (this.order) {
+
+ if (
+ this.order &&
+ this.order.length == 1 &&
+ this.order[0].expression &&
+ typeof this.order[0].expression == 'function'
+ ) {
+
+ var func = this.order[0].expression;
+
+ var nullsOrder =
+ this.order[0].nullsOrder == 'FIRST' ? -1 :
+ this.order[0].nullsOrder == 'LAST' ? +1 : 0
+ return function(a, b) {
+ var ra = func(a),
+ rb = func(b);
+ if (nullsOrder) {
+ if (ra == null) return rb == null ? 0 : nullsOrder;
+ if (rb == null) return -nullsOrder;
+ }
+ if (ra > rb) return 1;
+ if (ra == rb) return 0;
+ return -1;
+ };
+ }
+
+ var s = '';
+ var sk = '';
+ this.order.forEach(function(ord, idx) {
+
+ if (ord.expression instanceof yy.NumValue) {
+ var v = self.columns[ord.expression.value - 1];
+ } else {
+ var v = ord.expression;
+ }
+ self.orderColumns.push(v);
+
+ var key = '$$$' + idx;
+
+ // Date conversion
+ var dg = '';
+ //if(alasql.options.valueof)
+ if (ord.expression instanceof yy.Column) {
+ var columnid = ord.expression.columnid;
+ if (query.xcolumns[columnid]) {
+ var dbtypeid = query.xcolumns[columnid].dbtypeid;
+ if (dbtypeid == 'DATE' || dbtypeid == 'DATETIME' || dbtypeid == 'DATETIME2')
+ dg = '.valueOf()';
+ // TODO Add other types mapping
+ } else {
+ if (alasql.options.valueof) dg = '.valueOf()'; // TODO Check
+ }
+ // dg = '.valueOf()';
+ }
+ if (ord.expression instanceof yy.ParamValue) {
+ var columnid = params[ord.expression.param];
+ if (query.xcolumns[columnid]) {
+ var dbtypeid = query.xcolumns[columnid].dbtypeid;
+ if (dbtypeid == 'DATE' || dbtypeid == 'DATETIME' || dbtypeid == 'DATETIME2')
+ dg = '.valueOf()';
+ // TODO Add other types mapping
+ } else {
+ if (alasql.options.valueof) dg = '.valueOf()'; // TODO Check
+ }
+ // dg = '.valueOf()';
+ }
+ // COLLATE NOCASE
+ if (ord.nocase) dg += '.toUpperCase()';
+
+ if (ord.nullsOrder) {
+ if (ord.nullsOrder == 'FIRST') {
+ s += "if((a['" + key + "'] != null) && (b['" + key + "'] == null)) return 1;";
+ } else if (ord.nullsOrder == 'LAST') {
+ s += "if((a['" + key + "'] == null) && (b['" + key + "'] != null)) return 1;";
+ }
+ s += "if((a['" + key + "'] == null) == (b['" + key + "'] == null)) {";
+ sk += '}';
+ }
+
+ s +=
+ "if((a['" +
+ key +
+ "']||'')" +
+ dg +
+ (ord.direction == 'ASC' ? '>' : '<') +
+ "(b['" +
+ key +
+ "']||'')" +
+ dg +
+ ')return 1;';
+ s += "if((a['" + key + "']||'')" + dg + "==(b['" + key + "']||'')" + dg + '){';
+
+ /*
+if(false) {
+
+ if(ord.expression instanceof yy.NumValue) {
+ ord.expression = self.columns[ord.expression.value-1];
+
+ ord.expression = new yy.Column({columnid:ord.expression.nick});
+ };
+
+ if(ord.expression instanceof yy.Column) {
+ var columnid = ord.expression.columnid;
+ if(query.xcolumns[columnid]) {
+ var dbtypeid = query.xcolumns[columnid].dbtypeid;
+ if( dbtypeid == 'DATE' || dbtypeid == 'DATETIME' || dbtypeid == 'DATETIME2') dg = '.valueOf()';
+ // TODO Add other types mapping
+ } else {
+ if(alasql.options.valueof) dg = '.valueOf()'; // TODO Check
+ }
+ // COLLATE NOCASE
+ if(ord.nocase) dg += '.toUpperCase()';
+
+ s += 'if((a[\''+columnid+"']||'')"+dg+(ord.direction == 'ASC'?'>':'<')+'(b[\''+columnid+"']||'')"+dg+')return 1;';
+ s += 'if((a[\''+columnid+"']||'')"+dg+'==(b[\''+columnid+"']||'')"+dg+'){';
+
+ } else {
+ dg = '.valueOf()';
+ // COLLATE NOCASE
+ if(ord.nocase) dg += '.toUpperCase()';
+ s += 'if(('+ord.toJS('a','')+"||'')"+dg+(ord.direction == 'ASC'?'>(':'<(')+ord.toJS('b','')+"||'')"+dg+')return 1;';
+ s += 'if(('+ord.toJS('a','')+"||'')"+dg+'==('+ord.toJS('b','')+"||'')"+dg+'){';
+ }
+
+ // TODO Add date comparision
+
+}
+*/
+ sk += '}';
+ });
+ s += 'return 0;';
+ s += sk + 'return -1';
+ query.orderfns = s;
+
+ return new Function('a,b', 'var y;' + s);
+ }
+};
+
+// Pivot functions
+/**
+ Compile Pivot functions
+ @param {object} query Source query
+ @return {function} Pivoting functions
+*/
+yy.Select.prototype.compilePivot = function(query) {
+ var self = this;
+ /** @type {string} Main pivoting column */
+
+ var columnid = self.pivot.columnid;
+ var aggr = self.pivot.expr.aggregatorid;
+ var inlist = self.pivot.inlist;
+
+ var exprcolid = null;
+
+ if (self.pivot.expr.expression.hasOwnProperty('columnid')) {
+ exprcolid = self.pivot.expr.expression.columnid;
+ } else {
+ exprcolid = self.pivot.expr.expression.expression.columnid;
+ }
+
+ if (null == exprcolid) {
+ throw 'columnid not found';
+ }
+
+ if (inlist) {
+ inlist = inlist.map(function(l) {
+ return l.expr.columnid;
+ });
+ }
+
+ // Function for PIVOT post production
+ return function() {
+ var query = this;
+ var cols = query.columns
+ .filter(function(col) {
+ return col.columnid != columnid && col.columnid != exprcolid;
+ })
+ .map(function(col) {
+ return col.columnid;
+ });
+
+ var newcols = [];
+ var gnewcols = {};
+ var gr = {};
+ var ga = {};
+ var data = [];
+ query.data.forEach(function(d) {
+ if (!inlist || inlist.indexOf(d[columnid]) > -1) {
+ var gx = cols
+ .map(function(colid) {
+ return d[colid];
+ })
+ .join('`');
+ var g = gr[gx];
+ if (!g) {
+ g = {};
+ gr[gx] = g;
+ data.push(g);
+ cols.forEach(function(colid) {
+ g[colid] = d[colid];
+ });
+ }
+
+ if (!ga[gx]) {
+ ga[gx] = {};
+ }
+
+ if (ga[gx][d[columnid]]) {
+ ga[gx][d[columnid]]++;
+ } else {
+ ga[gx][d[columnid]] = 1;
+ }
+
+ if (!gnewcols[d[columnid]]) {
+ gnewcols[d[columnid]] = true;
+ newcols.push(d[columnid]);
+ }
+
+ if (aggr == 'SUM' || aggr == 'AVG') {
+ if (typeof g[d[columnid]] == 'undefined') g[d[columnid]] = 0;
+ g[d[columnid]] += +d[exprcolid];
+ } else if (aggr == 'COUNT') {
+ if (typeof g[d[columnid]] == 'undefined') g[d[columnid]] = 0;
+ g[d[columnid]]++;
+ } else if (aggr == 'MIN') {
+ if (typeof g[d[columnid]] == 'undefined') g[d[columnid]] = d[exprcolid];
+ if (d[exprcolid] < g[d[columnid]]) g[d[columnid]] = d[exprcolid];
+ } else if (aggr == 'MAX') {
+ if (typeof g[d[columnid]] == 'undefined') g[d[columnid]] = d[exprcolid];
+ if (d[exprcolid] > g[d[columnid]]) g[d[columnid]] = d[exprcolid];
+ } else if (aggr == 'FIRST') {
+ if (typeof g[d[columnid]] == 'undefined') g[d[columnid]] = d[exprcolid];
+ } else if (aggr == 'LAST') {
+ g[d[columnid]] = d[exprcolid];
+ } else if (alasql.aggr[aggr]) {
+ // Custom aggregator
+ alasql.aggr[aggr](g[d[columnid]], d[exprcolid]);
+ } else {
+ throw new Error('Wrong aggregator in PIVOT clause');
+ }
+ }
+ });
+
+ if (aggr == 'AVG') {
+ for (var gx in gr) {
+ var d = gr[gx];
+ for (var colid in d) {
+ if (cols.indexOf(colid) == -1 && colid != exprcolid) {
+ d[colid] = d[colid] / ga[gx][colid];
+ }
+ }
+ }
+ }
+
+ // columns
+ query.data = data;
+
+ if (inlist) newcols = inlist;
+
+ var ncol = query.columns.filter(function(col) {
+ return col.columnid == exprcolid;
+ })[0];
+ query.columns = query.columns.filter(function(col) {
+ return !(col.columnid == columnid || col.columnid == exprcolid);
+ });
+ newcols.forEach(function(colid) {
+ var nc = cloneDeep(ncol);
+ nc.columnid = colid;
+ query.columns.push(nc);
+ });
+ };
+};
+
+// var columnid = this.pivot.columnid;
+
+// return function(data){
+
+// if(false) {
+
+// }
+
+// if(false) {
+
+// }
+// };
+
+/**
+ Compile UNPIVOT clause
+ @param {object} query Query object
+ @return {function} Function for unpivoting
+*/
+yy.Select.prototype.compileUnpivot = function(query) {
+ var self = this;
+ var tocolumnid = self.unpivot.tocolumnid;
+ var forcolumnid = self.unpivot.forcolumnid;
+ var inlist = self.unpivot.inlist.map(function(l) {
+ return l.columnid;
+ });
+
+ return function() {
+ var data = [];
+
+ var xcols = query.columns
+ .map(function(col) {
+ return col.columnid;
+ })
+ .filter(function(colid) {
+ return inlist.indexOf(colid) == -1 && colid != forcolumnid && colid != tocolumnid;
+ });
+
+ query.data.forEach(function(d) {
+ inlist.forEach(function(colid) {
+ var nd = {};
+ xcols.forEach(function(xcolid) {
+ nd[xcolid] = d[xcolid];
+ });
+ nd[forcolumnid] = colid;
+ nd[tocolumnid] = d[colid];
+ data.push(nd);
+ });
+ });
+
+ query.data = data;
+
+ // });
+ };
+};
+
+/*
+//
+// ROLLUP(), CUBE(), GROUPING SETS() for Alasql.js
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+/**
+ Calculate ROLLUP() combination
+ */
+
+var rollup = function(a, query) {
+ var rr = [];
+ var mask = 0;
+ var glen = a.length;
+ for (var g = 0; g < glen + 1; g++) {
+ var ss = [];
+ for (var i = 0; i < glen; i++) {
+ if (a[i] instanceof yy.Column) {
+ a[i].nick = escapeq(a[i].columnid);
+
+ query.groupColumns[escapeq(a[i].columnid)] = a[i].nick;
+ var aaa = a[i].nick + '\t' + a[i].toJS('p', query.sources[0].alias, query.defcols);
+ } else {
+ query.groupColumns[escapeq(a[i].toString())] = escapeq(a[i].toString());
+ var aaa =
+ escapeq(a[i].toString()) +
+ '\t' +
+ a[i].toJS('p', query.sources[0].alias, query.defcols);
+ }
+
+ if (mask & (1 << i)) ss.push(aaa);
+ }
+ rr.push(ss);
+ mask = (mask << 1) + 1;
+ }
+ return rr;
+};
+
+/**
+ Calculate CUBE()
+ */
+var cube = function(a, query) {
+ var rr = [];
+ var glen = a.length;
+ var glenCube = 1 << glen;
+ for (var g = 0; g < glenCube; g++) {
+ var ss = [];
+ for (var i = 0; i < glen; i++) {
+ if (g & (1 << i))
+ //ss.push(a[i]);
+ //ss = cartes(ss,decartes(a[i]));
+
+ // var aaa = a[i].toString()+'\t'
+ // +a[i].toJS('p',query.sources[0].alias,query.defcols);
+
+ ss = ss.concat(decartes(a[i], query));
+ //
+ }
+ rr.push(ss);
+ }
+ return rr;
+};
+
+/**
+ GROUPING SETS()
+ */
+var groupingsets = function(a, query) {
+ return a.reduce(function(acc, d) {
+ acc = acc.concat(decartes(d, query));
+ return acc;
+ }, []);
+};
+
+/**
+ Cartesian production
+ */
+var cartes = function(a1, a2) {
+ var rrr = [];
+ for (var i1 = 0; i1 < a1.length; i1++) {
+ for (var i2 = 0; i2 < a2.length; i2++) {
+ rrr.push(a1[i1].concat(a2[i2]));
+ }
+ }
+ return rrr;
+};
+
+/**
+ Prepare groups function
+ */
+function decartes(gv, query) {
+
+ if (Array.isArray(gv)) {
+ var res = [[]];
+ for (var t = 0; t < gv.length; t++) {
+ if (gv[t] instanceof yy.Column) {
+
+ gv[t].nick = gv[t].nick ? escapeq(gv[t].nick) : escapeq(gv[t].columnid);
+ query.groupColumns[gv[t].nick] = gv[t].nick;
+ res = res.map(function(r) {
+ return r.concat(
+ gv[t].nick + '\t' + gv[t].toJS('p', query.sources[0].alias, query.defcols)
+ );
+ });
+ // res = res.map(function(r){return r.concat(gv[t].columnid)});
+ } else if (gv[t] instanceof yy.FuncValue) {
+ query.groupColumns[escapeq(gv[t].toString())] = escapeq(gv[t].toString());
+ res = res.map(function(r) {
+ return r.concat(
+ escapeq(gv[t].toString()) +
+ '\t' +
+ gv[t].toJS('p', query.sources[0].alias, query.defcols)
+ );
+ });
+ // to be defined
+ } else if (gv[t] instanceof yy.GroupExpression) {
+ if (gv[t].type == 'ROLLUP') res = cartes(res, rollup(gv[t].group, query));
+ else if (gv[t].type == 'CUBE') res = cartes(res, cube(gv[t].group, query));
+ else if (gv[t].type == 'GROUPING SETS')
+ res = cartes(res, groupingsets(gv[t].group, query));
+ else throw new Error('Unknown grouping function');
+ } else if (gv[t] === '') {
+
+ res = [['1\t1']];
+ } else {
+ // if(gv[t])
+
+ res = res.map(function(r) {
+ query.groupColumns[escapeq(gv[t].toString())] = escapeq(gv[t].toString());
+ return r.concat(
+ escapeq(gv[t].toString()) +
+ '\t' +
+ gv[t].toJS('p', query.sources[0].alias, query.defcols)
+ );
+ });
+ // res = res.concat(gv[t]);
+ }
+
+ }
+ return res;
+ } else if (gv instanceof yy.FuncValue) {
+
+ query.groupColumns[escapeq(gv.toString())] = escapeq(gv.toString());
+ return [gv.toString() + '\t' + gv.toJS('p', query.sources[0].alias, query.defcols)];
+ } else if (gv instanceof yy.Column) {
+ gv.nick = escapeq(gv.columnid);
+ query.groupColumns[gv.nick] = gv.nick;
+ return [gv.nick + '\t' + gv.toJS('p', query.sources[0].alias, query.defcols)]; // Is this ever happened?
+ // } else if(gv instanceof yy.Expression) {
+ // return [gv.columnid]; // Is this ever happened?
+ } else {
+ query.groupColumns[escapeq(gv.toString())] = escapeq(gv.toString());
+ return [
+ escapeq(gv.toString()) + '\t' + gv.toJS('p', query.sources[0].alias, query.defcols),
+ ];
+ // throw new Error('Single argument in the group without array');
+ }
+
+}
+
+/*
+//
+// Select run-time part for Alasql.js
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+yy.Select.prototype.compileDefCols = function(query, databaseid) {
+
+ var defcols = {'.': {}};
+ if (this.from) {
+ this.from.forEach(function(fr) {
+ defcols['.'][fr.as || fr.tableid] = true;
+ if (fr instanceof yy.Table) {
+ var alias = fr.as || fr.tableid;
+
+ var table = alasql.databases[fr.databaseid || databaseid].tables[fr.tableid];
+
+ if (undefined === table) {
+ throw new Error('Table does not exist: ' + fr.tableid);
+ }
+
+ if (table.columns) {
+ table.columns.forEach(function(col) {
+ if (defcols[col.columnid]) {
+ defcols[col.columnid] = '-'; // Ambigous
+ } else {
+ defcols[col.columnid] = alias;
+ }
+ });
+ }
+ } else if (fr instanceof yy.Select) {
+ } else if (fr instanceof yy.Search) {
+ } else if (fr instanceof yy.ParamValue) {
+ } else if (fr instanceof yy.VarValue) {
+ } else if (fr instanceof yy.FuncValue) {
+ } else if (fr instanceof yy.FromData) {
+ } else if (fr instanceof yy.Json) {
+ } else if (fr.inserted) {
+ } else {
+
+ throw new Error('Unknown type of FROM clause');
+ }
+ });
+ }
+
+ if (this.joins) {
+ this.joins.forEach(function(jn) {
+ defcols['.'][jn.as || jn.table.tableid] = true;
+
+ if (jn.table) {
+ var alias = jn.table.tableid;
+ if (jn.as) alias = jn.as;
+ var alias = jn.as || jn.table.tableid;
+ var table =
+ alasql.databases[jn.table.databaseid || databaseid].tables[jn.table.tableid];
+
+ if (table.columns) {
+ table.columns.forEach(function(col) {
+ if (defcols[col.columnid]) {
+ defcols[col.columnid] = '-'; // Ambigous
+ } else {
+ defcols[col.columnid] = alias;
+ }
+ });
+ }
+ } else if (jn.select) {
+ } else if (jn.param) {
+ } else if (jn.func) {
+ } else {
+ throw new Error('Unknown type of FROM clause');
+ }
+ });
+ }
+ // for(var k in defcols) {
+ // if(defcols[k] == '-') defcols[k] = undefined;
+ // }
+
+ return defcols;
+};
+
+/*
+//
+// UNION for Alasql.js
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+// SELECT UNION statement
+
+yy.Union = function(params) {
+ return yy.extend(this, params);
+};
+yy.Union.prototype.toString = function() {
+ return 'UNION';
+};
+
+yy.Union.prototype.compile = function(tableid) {
+ return null;
+};
+
+/*
+//
+// CROSS AND OUTER APPLY for Alasql.js
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+yy.Apply = function(params) {
+ return yy.extend(this, params);
+};
+
+yy.Apply.prototype.toString = function() {
+ var s = this.applymode + ' APPLY (' + this.select.toString() + ')';
+
+ if (this.as) s += ' AS ' + this.as;
+
+ return s;
+};
+
+/*
+//
+// CROSS AND OUTER APPLY for Alasql.js
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+yy.Over = function(params) {
+ return yy.extend(this, params);
+};
+yy.Over.prototype.toString = function() {
+ var s = 'OVER (';
+ if (this.partition) {
+ s += 'PARTITION BY ' + this.partition.toString();
+ if (this.order) s += ' ';
+ }
+ if (this.order) {
+ s += 'ORDER BY ' + this.order.toString();
+ }
+ s += ')';
+ return s;
+};
+
+/*
+//
+// Expressions for Alasql.js
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+/**
+ Expression statement ( = 2*2; )
+ @class
+ @param {object} params Initial parameters
+*/
+yy.ExpressionStatement = function(params) {
+ return yy.extend(this, params);
+};
+
+/**
+ Convert AST to string
+ @this ExpressionStatement
+ @return {string}
+*/
+yy.ExpressionStatement.prototype.toString = function() {
+ return this.expression.toString();
+};
+/**
+ Execute statement
+ @param {string} databaseid Database identificatro
+ @param {object} params Statement parameters
+ @param {statement-callback} cb Callback
+ @return {object} Result value
+*/
+yy.ExpressionStatement.prototype.execute = function(databaseid, params, cb) {
+ if (this.expression) {
+
+ alasql.precompile(this, databaseid, params); // Precompile queries
+ var exprfn = new Function(
+ 'params,alasql,p',
+ 'var y;return ' + this.expression.toJS('({})', '', null)
+ ).bind(this);
+ var res = exprfn(params, alasql);
+ if (cb) {
+ res = cb(res);
+ }
+ return res;
+ }
+};
+
+/**
+ Expression class
+ @class
+ @param {object} params Initial parameters
+*/
+
+yy.Expression = function(params) {
+ return yy.extend(this, params);
+};
+
+/**
+ Convert AST to string
+ @this ExpressionStatement
+ @return {string}
+*/
+yy.Expression.prototype.toString = function(dontas) {
+ var s = this.expression.toString(dontas);
+ if (this.order) {
+ s += ' ' + this.order.toString();
+ }
+ if (this.nocase) {
+ s += ' COLLATE NOCASE';
+ }
+ if (this.direction) {
+ s += ' ' + this.direction;
+ }
+ return s;
+};
+
+/**
+ Find aggregator in AST subtree
+ @this ExpressionStatement
+ @param {object} query Query object
+*/
+yy.Expression.prototype.findAggregator = function(query) {
+ if (this.expression.findAggregator) {
+ this.expression.findAggregator(query);
+ }
+};
+
+/**
+ Convert AST to JavaScript expression
+ @this ExpressionStatement
+ @param {string} context Context string, e.g. 'p','g', or 'x'
+ @param {string} tableid Default table name
+ @param {object} defcols Default columns dictionary
+ @return {string} JavaScript expression
+*/
+
+yy.Expression.prototype.toJS = function(context, tableid, defcols) {
+
+ if (this.expression.reduced) {
+ return 'true';
+ }
+ return this.expression.toJS(context, tableid, defcols);
+};
+
+/**
+ Compile AST to JavaScript expression
+ @this ExpressionStatement
+ @param {string} context Context string, e.g. 'p','g', or 'x'
+ @param {string} tableid Default table name
+ @param {object} defcols Default columns dictionary
+ @return {string} JavaScript expression
+*/
+
+yy.Expression.prototype.compile = function(context, tableid, defcols) {
+
+ if (this.reduced) {
+ return returnTrue();
+ }
+ return new Function('p', 'var y;return ' + this.toJS(context, tableid, defcols));
+};
+
+/**
+ JavaScript class
+ @class
+*/
+yy.JavaScript = function(params) {
+ return yy.extend(this, params);
+};
+yy.JavaScript.prototype.toString = function() {
+ var s = '``' + this.value + '``';
+ return s;
+};
+
+yy.JavaScript.prototype.toJS = function(/* context, tableid, defcols*/) {
+
+ return '(' + this.value + ')';
+};
+yy.JavaScript.prototype.execute = function(databaseid, params, cb) {
+ var res = 1;
+ var expr = new Function('params,alasql,p', this.value);
+ expr(params, alasql);
+ if (cb) {
+ res = cb(res);
+ }
+ return res;
+};
+
+/**
+ Literal class
+ @class
+ @example
+ MyVar, [My vairable], `MySQL variable`
+*/
+
+yy.Literal = function(params) {
+ return yy.extend(this, params);
+};
+yy.Literal.prototype.toString = function(dontas) {
+ var s = this.value;
+ if (this.value1) {
+ s = this.value1 + '.' + s;
+ }
+ if (this.alias && !dontas) s += ' AS ' + this.alias;
+ // else s = tableid+'.'+s;
+ return s;
+};
+
+/**
+ Join class
+ @class
+*/
+
+yy.Join = function(params) {
+ return yy.extend(this, params);
+};
+yy.Join.prototype.toString = function() {
+ var s = ' ';
+ if (this.joinmode) {
+ s += this.joinmode + ' ';
+ }
+ s += 'JOIN ' + this.table.toString();
+ return s;
+};
+
+// }
+
+/**
+ Table class
+ @class
+*/
+
+yy.Table = function(params) {
+ return yy.extend(this, params);
+};
+yy.Table.prototype.toString = function() {
+ var s = this.tableid;
+ // if(this.joinmode)
+ if (this.databaseid) {
+ s = this.databaseid + '.' + s;
+ }
+ return s;
+};
+
+/**
+ View class
+ @class
+*/
+
+yy.View = function(params) {
+ return yy.extend(this, params);
+};
+yy.View.prototype.toString = function() {
+ var s = this.viewid;
+ // if(this.joinmode)
+ if (this.databaseid) {
+ s = this.databaseid + '.' + s;
+ }
+ return s;
+};
+
+/**
+ Binary operation class
+ @class
+*/
+yy.Op = function(params) {
+ return yy.extend(this, params);
+};
+yy.Op.prototype.toString = function() {
+ if (this.op === 'IN' || this.op === 'NOT IN') {
+ return this.left.toString() + ' ' + this.op + ' (' + this.right.toString() + ')';
+ }
+ if (this.allsome) {
+ return (
+ this.left.toString() +
+ ' ' +
+ this.op +
+ ' ' +
+ this.allsome +
+ ' (' +
+ this.right.toString() +
+ ')'
+ );
+ }
+ if (this.op === '->' || this.op === '!') {
+ var s = this.left.toString() + this.op;
+
+ if (typeof this.right !== 'string' && typeof this.right !== 'number') {
+ s += '(';
+ }
+
+ s += this.right.toString();
+
+ if (typeof this.right !== 'string' && typeof this.right !== 'number') {
+ s += ')';
+ }
+
+ return s;
+ }
+ if (this.op === 'BETWEEN') {
+ var s = this.left.toString() + ' ' + this.op + ' '
+ + this.right1.toString() + ' AND ' + this.right2.toString();
+
+ return s;
+ }
+ return (
+ this.left.toString() +
+ ' ' +
+ this.op +
+ ' ' +
+ (this.allsome ? this.allsome + ' ' : '') +
+ this.right.toString()
+ );
+};
+
+yy.Op.prototype.findAggregator = function(query) {
+
+ if (this.left && this.left.findAggregator) {
+ this.left.findAggregator(query);
+ }
+ // Do not go in > ALL
+ if (this.right && this.right.findAggregator && !this.allsome) {
+ this.right.findAggregator(query);
+ }
+};
+
+yy.Op.prototype.toType = function(tableid) {
+ if (['-', '*', '/', '%', '^'].indexOf(this.op) > -1) {
+ return 'number';
+ }
+ if (['||'].indexOf(this.op) > -1) {
+ return 'string';
+ }
+ if (this.op === '+') {
+ if (this.left.toType(tableid) === 'string' || this.right.toType(tableid) === 'string') {
+ return 'string';
+ }
+ if (this.left.toType(tableid) === 'number' || this.right.toType(tableid) === 'number') {
+ return 'number';
+ }
+ }
+
+ if (
+ [
+ 'AND',
+ 'OR',
+ 'NOT',
+ '=',
+ '==',
+ '===',
+ '!=',
+ '!==',
+ '!===',
+ '>',
+ '>=',
+ '<',
+ '<=',
+ 'IN',
+ 'NOT IN',
+ 'LIKE',
+ 'NOT LIKE',
+ 'REGEXP',
+ 'GLOB',
+ ].indexOf(this.op) > -1
+ ) {
+ return 'boolean';
+ }
+
+ if (
+ this.op === 'BETWEEN' ||
+ this.op === 'NOT BETWEEN' ||
+ this.op === 'IS NULL' ||
+ this.op === 'IS NOT NULL'
+ ) {
+ return 'boolean';
+ }
+
+ if (this.allsome) {
+ return 'boolean';
+ }
+
+ if (!this.op) {
+ return this.left.toType();
+ }
+
+ return 'unknown';
+};
+
+yy.Op.prototype.toJS = function(context, tableid, defcols) {
+
+ var s;
+ var refs = [];
+ var op = this.op;
+ var _this = this;
+ //var leftJS = function(){return _this.left.toJS(context,tableid, defcols)};
+ //var rightJS = function(){return _this.right.toJS(context,tableid, defcols)};
+ var accessedLeft = false,
+ accessedRight = false;
+ var ref = function(expr) {
+ if (expr.toJS) {
+ expr = expr.toJS(context, tableid, defcols);
+ }
+ var i = refs.push(expr) - 1;
+ return 'y[' + i + ']';
+ };
+ var leftJS = function() {
+ return ref(_this.left);
+ };
+ var rightJS = function() {
+ return ref(_this.right);
+ };
+
+ if (this.op === '=') {
+ op = '===';
+ } else if (this.op === '<>') {
+ op = '!=';
+ } else if (this.op === 'OR') {
+ op = '||';
+ }
+
+ // Arrow operator
+ if (this.op === '->') {
+ // Expression to prevent error if object is empty (#344)
+ var ljs = '(' + leftJS() + '||{})';
+
+ if (typeof this.right === 'string') {
+ s = ljs + '["' + this.right + '"]';
+ } else if (typeof this.right === 'number') {
+ s = ljs + '[' + this.right + ']';
+ } else if (this.right instanceof yy.FuncValue) {
+ var ss = [];
+ if (!(!this.right.args || 0 === this.right.args.length)) {
+ var ss = this.right.args.map(ref);
+ }
+ s = '' + ljs + "['" + this.right.funcid + "'](" + ss.join(',') + ')';
+ } else {
+ s = '' + ljs + '[' + rightJS() + ']';
+ }
+ }
+
+ if (this.op === '!') {
+ if (typeof this.right === 'string') {
+ s =
+ '' +
+ 'alasql.databases[alasql.useid].objects[' +
+ leftJS() +
+ ']["' +
+ this.right +
+ '"]';
+ }
+ // TODO - add other cases
+ }
+
+ if (this.op === 'IS') {
+ s =
+ '' +
+ '(' +
+ '(' +
+ leftJS() +
+ '==null)' + // Cant be ===
+ ' === ' +
+ '(' +
+ rightJS() +
+ '==null)' + // Cant be ===
+ ')';
+ }
+
+ if (this.op === '==') {
+ s = '' + 'alasql.utils.deepEqual(' + leftJS() + ',' + rightJS() + ')';
+ }
+
+ if (this.op === '===' || this.op === '!===') {
+ s =
+ '' +
+ '(' +
+ (this.op === '!===' ? '!' : '') +
+ '(' +
+ '(' +
+ leftJS() +
+ ').valueOf()' +
+ '===' +
+ '(' +
+ rightJS() +
+ ').valueOf()' +
+ ')' +
+ ')';
+ }
+
+ if (this.op === '!==') {
+ s = '' + '(!alasql.utils.deepEqual(' + leftJS() + ',' + rightJS() + '))';
+ }
+ if (this.op === '||') {
+ s = '' + "(''+(" + leftJS() + "||'')+(" + rightJS() + '||""))';
+ }
+ if (this.op === 'LIKE' || this.op === 'NOT LIKE') {
+ var s =
+ '(' +
+ (this.op === 'NOT LIKE' ? '!' : '') +
+ 'alasql.utils.like(' +
+ rightJS() +
+ ',' +
+ leftJS();
+ if (this.escape) {
+ s += ',' + ref(this.escape);
+ }
+ s += '))';
+ }
+ if (this.op === 'REGEXP') {
+ s = 'alasql.stdfn.REGEXP_LIKE(' + leftJS() + ',' + rightJS() + ')';
+ }
+ if (this.op === 'GLOB') {
+ s = 'alasql.utils.glob(' + leftJS() + ',' + rightJS() + ')';
+ }
+
+ if (this.op === 'BETWEEN' || this.op === 'NOT BETWEEN') {
+ var left = leftJS();
+ s =
+ '' +
+ '(' +
+ (this.op === 'NOT BETWEEN' ? '!' : '') +
+ '(' +
+ '(' +
+ ref(this.right1) +
+ '<=' +
+ left +
+ ') && (' +
+ left +
+ '<=' +
+ ref(this.right2) +
+ ')' +
+ ')' +
+ ')';
+
+ }
+
+ if (this.op === 'IN') {
+ if (this.right instanceof yy.Select) {
+ s = '(';
+ // s += 'this.query.queriesdata['+this.queriesidx+']';
+ // s += 'alasql.utils.flatArray(this.query.queriesfn['+(this.queriesidx)+'](params,null,context))';
+ s +=
+ 'alasql.utils.flatArray(this.queriesfn[' +
+ this.queriesidx +
+ '](params,null,' +
+ context +
+ '))';
+ s += '.indexOf(';
+ s += leftJS() + ')>-1)';
+ } else if (Array.isArray(this.right)) {
+ // if(this.right.length == 0) return 'false';
+ s = '([' + this.right.map(ref).join(',') + '].indexOf(' + leftJS() + ')>-1)';
+
+ } else {
+ s = '(' + rightJS() + '.indexOf(' + leftJS() + ')>-1)';
+
+ // } else {
+ // throw new Error('Wrong IN operator without SELECT part');
+ }
+ }
+
+ if (this.op === 'NOT IN') {
+ if (this.right instanceof yy.Select) {
+ s = '(';
+ //this.query.queriesdata['+this.queriesidx+']
+ // s += 'alasql.utils.flatArray(this.query.queriesfn['+(this.queriesidx)+'](params,null,p))';
+ s += 'alasql.utils.flatArray(this.queriesfn[' + this.queriesidx + '](params,null,p))';
+ s += '.indexOf(';
+ s += leftJS() + ')<0)';
+ } else if (Array.isArray(this.right)) {
+ // if(this.right.length == 0) return 'true';
+ s = '([' + this.right.map(ref).join(',') + '].indexOf(';
+ s += leftJS() + ')<0)';
+ } else {
+ s = '(' + rightJS() + '.indexOf(';
+ s += leftJS() + ')==-1)';
+
+ // throw new Error('Wrong NOT IN operator without SELECT part');
+ }
+ }
+
+ if (this.allsome === 'ALL') {
+ var s;
+ if (this.right instanceof yy.Select) {
+ // var s = 'this.query.queriesdata['+this.queriesidx+']';
+ s =
+ 'alasql.utils.flatArray(this.query.queriesfn[' +
+ this.queriesidx +
+ '](params,null,p))';
+
+ s += '.every(function(b){return (';
+ s += leftJS() + ')' + op + 'b})';
+ } else if (Array.isArray(this.right)) {
+ s =
+ '' +
+ (this.right.length == 1
+ ? ref(this.right[0])
+ : '[' + this.right.map(ref).join(',') + ']');
+ s += '.every(function(b){return (';
+ s += leftJS() + ')' + op + 'b})';
+ } else {
+ throw new Error('NOT IN operator without SELECT');
+ }
+ }
+
+ if (this.allsome === 'SOME' || this.allsome === 'ANY') {
+ var s;
+ if (this.right instanceof yy.Select) {
+ // var s = 'this.query.queriesdata['+this.queriesidx+']';
+ s =
+ 'alasql.utils.flatArray(this.query.queriesfn[' +
+ this.queriesidx +
+ '](params,null,p))';
+ s += '.some(function(b){return (';
+ s += leftJS() + ')' + op + 'b})';
+ } else if (Array.isArray(this.right)) {
+ s =
+ '' +
+ (this.right.length == 1
+ ? ref(this.right[0])
+ : '[' + this.right.map(ref).join(',') + ']');
+ s += '.some(function(b){return (';
+ s += leftJS() + ')' + op + 'b})';
+ } else {
+ throw new Error('SOME/ANY operator without SELECT');
+ }
+ }
+
+ // Special case for AND optimization (if reduced)
+ if (this.op === 'AND') {
+ if (this.left.reduced) {
+ if (this.right.reduced) {
+ return 'true';
+ } else {
+ s = rightJS();
+ }
+ } else if (this.right.reduced) {
+ s = leftJS();
+ }
+
+ // Otherwise process as regular operation (see below)
+ op = '&&';
+ }
+
+ // if(this.op === '^') {
+ // // return 'Math.pow('
+ // // + leftJS()
+ // // + ','
+ // // + rightJS()
+ // // + ')';
+ // }
+
+ // Change names
+
+ var expr = s || '(' + leftJS() + op + rightJS() + ')';
+
+ var declareRefs = 'y=[(' + refs.join('), (') + ')]';
+
+ if (op === '&&' || op === '||' || op === 'IS' || op === 'IS NULL' || op === 'IS NOT NULL') {
+ return '(' + declareRefs + ', ' + expr + ')';
+ }
+
+ return (
+ '(' + declareRefs + ', ' + 'y.some(function(e){return e == null}) ? void 0 : ' + expr + ')'
+ );
+};
+
+yy.VarValue = function(params) {
+ return yy.extend(this, params);
+};
+yy.VarValue.prototype.toString = function() {
+ return '@' + this.variable;
+};
+
+yy.VarValue.prototype.toType = function() {
+ return 'unknown';
+};
+
+yy.VarValue.prototype.toJS = function() {
+ return "alasql.vars['" + this.variable + "']";
+};
+
+yy.NumValue = function(params) {
+ return yy.extend(this, params);
+};
+yy.NumValue.prototype.toString = function() {
+ return this.value.toString();
+};
+
+yy.NumValue.prototype.toType = function() {
+ return 'number';
+};
+
+yy.NumValue.prototype.toJS = function() {
+ return '' + this.value;
+};
+
+yy.StringValue = function(params) {
+ return yy.extend(this, params);
+};
+yy.StringValue.prototype.toString = function() {
+ return "'" + this.value.toString() + "'";
+};
+
+yy.StringValue.prototype.toType = function() {
+ return 'string';
+};
+
+yy.StringValue.prototype.toJS = function() {
+
+ // return "'"+doubleqq(this.value)+"'";
+ return "'" + escapeq(this.value) + "'";
+};
+
+yy.DomainValueValue = function(params) {
+ return yy.extend(this, params);
+};
+yy.DomainValueValue.prototype.toString = function() {
+ return 'VALUE';
+};
+
+yy.DomainValueValue.prototype.toType = function() {
+ return 'object';
+};
+
+yy.DomainValueValue.prototype.toJS = function(context, tableid, defcols) {
+
+ // return "'"+doubleqq(this.value)+"'";
+ return context;
+};
+
+yy.ArrayValue = function(params) {
+ return yy.extend(this, params);
+};
+yy.ArrayValue.prototype.toString = function() {
+ return 'ARRAY[]';
+};
+
+yy.ArrayValue.prototype.toType = function() {
+ return 'object';
+};
+
+yy.ArrayValue.prototype.toJS = function(context, tableid, defcols) {
+
+ // return "'"+doubleqq(this.value)+"'";
+ return (
+ '[(' +
+ this.value
+ .map(function(el) {
+ return el.toJS(context, tableid, defcols);
+ })
+ .join('), (') +
+ ')]'
+ );
+};
+
+yy.LogicValue = function(params) {
+ return yy.extend(this, params);
+};
+yy.LogicValue.prototype.toString = function() {
+ return this.value ? 'TRUE' : 'FALSE';
+};
+
+yy.LogicValue.prototype.toType = function() {
+ return 'boolean';
+};
+
+yy.LogicValue.prototype.toJS = function() {
+ return this.value ? 'true' : 'false';
+};
+
+yy.NullValue = function(params) {
+ return yy.extend(this, params);
+};
+yy.NullValue.prototype.toString = function() {
+ return 'NULL';
+};
+yy.NullValue.prototype.toJS = function() {
+ return 'undefined';
+ // return 'undefined';
+};
+
+yy.ParamValue = function(params) {
+ return yy.extend(this, params);
+};
+yy.ParamValue.prototype.toString = function() {
+ return '$' + this.param;
+};
+yy.ParamValue.prototype.toJS = function() {
+ if (typeof this.param === 'string') {
+ return "params['" + this.param + "']";
+ }
+
+ return 'params[' + this.param + ']';
+};
+
+yy.UniOp = function(params) {
+ return yy.extend(this, params);
+};
+yy.UniOp.prototype.toString = function() {
+ var s;
+ s = void 0;
+ if (this.op === '~') {
+ s = this.op + this.right.toString();
+ }
+ if (this.op === '-') {
+ s = this.op + this.right.toString();
+ }
+ if (this.op === '+') {
+ s = this.op + this.right.toString();
+ }
+ if (this.op === '#') {
+ s = this.op + this.right.toString();
+ }
+ if (this.op === 'NOT') {
+ s = this.op + '(' + this.right.toString() + ')';
+ }
+ if (this.op === null) {
+ s = '(' + this.right.toString() + ')';
+ }
+ if (!s) {
+ s = '(' + this.right.toString() + ')';
+ }
+ return s;
+};
+
+yy.UniOp.prototype.findAggregator = function(query) {
+ if (this.right.findAggregator) {
+ this.right.findAggregator(query);
+ }
+};
+
+yy.UniOp.prototype.toType = function() {
+ if (this.op === '-') {
+ return 'number';
+ }
+
+ if (this.op === '+') {
+ return 'number';
+ }
+
+ if (this.op === 'NOT') {
+ return 'boolean';
+ }
+
+ // Todo: implement default case
+};
+
+yy.UniOp.prototype.toJS = function(context, tableid, defcols) {
+ if (this.op === '~') {
+ return '(~(' + this.right.toJS(context, tableid, defcols) + '))';
+ }
+
+ if (this.op === '-') {
+ return '(-(' + this.right.toJS(context, tableid, defcols) + '))';
+ }
+
+ if (this.op === '+') {
+ return '(' + this.right.toJS(context, tableid, defcols) + ')';
+ }
+
+ if (this.op === 'NOT') {
+ return '!(' + this.right.toJS(context, tableid, defcols) + ')';
+ }
+
+ if (this.op === '#') {
+ if (this.right instanceof yy.Column) {
+ return "(alasql.databases[alasql.useid].objects['" + this.right.columnid + "'])";
+ } else {
+ return (
+ '(alasql.databases[alasql.useid].objects[' +
+ this.right.toJS(context, tableid, defcols) +
+ '])'
+ );
+ }
+ }
+
+ // Please avoid === here
+ if (this.op == null) {
+ // jshint ignore:line
+ return '(' + this.right.toJS(context, tableid, defcols) + ')';
+ }
+
+ // Todo: implement default case.
+};
+
+yy.Column = function(params) {
+ return yy.extend(this, params);
+};
+yy.Column.prototype.toString = function(dontas) {
+ var s;
+ if (this.columnid == +this.columnid) {
+ // jshint ignore:line
+ s = '[' + this.columnid + ']';
+ } else {
+ s = this.columnid;
+ }
+ if (this.tableid) {
+ if (+this.columnid === this.columnid) {
+ s = this.tableid + s;
+ } else {
+ s = this.tableid + '.' + s;
+ }
+ if (this.databaseid) {
+ s = this.databaseid + '.' + s;
+ }
+ }
+ if (this.alias && !dontas) s += ' AS ' + this.alias;
+ return s;
+};
+
+yy.Column.prototype.toJS = function(context, tableid, defcols) {
+
+ var s = '';
+ if (!this.tableid && tableid === '' && !defcols) {
+ if (this.columnid !== '_') {
+ s = context + "['" + this.columnid + "']";
+ } else {
+ if (context === 'g') {
+ s = "g['_']";
+ } else {
+ s = context;
+ }
+ }
+ } else {
+ if (context === 'g') {
+ // if(this.columnid == '_') {
+ // } else {
+ s = "g['" + this.nick + "']";
+ // }
+ } else if (this.tableid) {
+ if (this.columnid !== '_') {
+ // if() {
+ // s = context+'[\''+tableid + '\'][\''+this.tableid+'\'][\''+this.columnid+'\']';
+ // } else {
+ s = context + "['" + this.tableid + "']['" + this.columnid + "']";
+ // }
+ } else {
+ if (context === 'g') {
+ s = "g['_']";
+ } else {
+ s = context + "['" + this.tableid + "']";
+ }
+ }
+ } else if (defcols) {
+ var tbid = defcols[this.columnid];
+ if (tbid === '-') {
+ throw new Error(
+ 'Cannot resolve column "' +
+ this.columnid +
+ '" because it exists in two source tables'
+ );
+ } else if (tbid) {
+ if (this.columnid !== '_') {
+ s = context + "['" + tbid + "']['" + this.columnid + "']";
+ } else {
+ s = context + "['" + tbid + "']";
+ }
+
+ } else {
+ if (this.columnid !== '_') {
+ // if(defcols['.'][this.tableid]) {
+
+ // s = context+'[\''+tableid + '\'][\''+this.tableid + '\'][\''+this.columnid+'\']';
+ // } else {
+ s = context + "['" + (this.tableid || tableid) + "']['" + this.columnid + "']";
+ // }
+ } else {
+ s = context + "['" + (this.tableid || tableid) + "']";
+ }
+ }
+ } else if (tableid === -1) {
+ // if(this.columnid != '') {
+ s = context + "['" + this.columnid + "']";
+ // } else {
+ // s = context;
+ // }
+ } else {
+ if (this.columnid !== '_') {
+ s = context + "['" + (this.tableid || tableid) + "']['" + this.columnid + "']";
+ } else {
+ s = context + "['" + (this.tableid || tableid) + "']";
+ }
+ }
+ }
+
+ // console.trace(new Error());
+
+ return s;
+};
+
+yy.AggrValue = function(params) {
+ return yy.extend(this, params);
+};
+yy.AggrValue.prototype.toString = function(dontas) {
+ var s = '';
+ if (this.aggregatorid === 'REDUCE') {
+ s += this.funcid + '(';
+ } else {
+ s += this.aggregatorid + '(';
+ }
+
+ if (this.distinct) {
+ s += 'DISTINCT ';
+ }
+
+ if (this.expression) {
+ s += this.expression.toString();
+ }
+
+ s += ')';
+
+ if (this.over) {
+ s += ' ' + this.over.toString();
+ }
+
+ if (this.alias && !dontas) s += ' AS ' + this.alias;
+ // if(this.alias) s += ' AS '+this.alias;
+ return s;
+};
+
+yy.AggrValue.prototype.findAggregator = function(query) {
+
+ // var colas = this.as || this.toString();
+
+ var colas = escapeq(this.toString()) + ':' + query.selectGroup.length;
+
+ // if(!query.selectColumns[colas]) {
+ // }
+
+ var found = false;
+
+ if (!found) {
+ if (!this.nick) {
+ this.nick = colas;
+ var found = false;
+ for (var i = 0; i < query.removeKeys.length; i++) {
+ if (query.removeKeys[i] === colas) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ query.removeKeys.push(colas);
+ }
+ }
+ query.selectGroup.push(this);
+ }
+
+ // this.reduced = true;
+ return;
+};
+
+yy.AggrValue.prototype.toType = function() {
+ if (
+ ['SUM', 'COUNT', 'AVG', 'MIN', 'MAX', 'AGGR', 'VAR', 'STDDEV'].indexOf(this.aggregatorid) >
+ -1
+ ) {
+ return 'number';
+ }
+
+ if (['ARRAY'].indexOf(this.aggregatorid) > -1) {
+ return 'array';
+ }
+
+ if (['FIRST', 'LAST'].indexOf(this.aggregatorid) > -1) {
+ return this.expression.toType();
+ }
+
+ // todo: implement default;
+};
+
+yy.AggrValue.prototype.toJS = function(/*context, tableid, defcols*/) {
+
+ var colas = this.nick;
+ if (colas === undefined) {
+ colas = this.toString();
+ }
+ return "g['" + colas + "']";
+};
+
+yy.OrderExpression = function(params) {
+ return yy.extend(this, params);
+};
+yy.OrderExpression.prototype.toString = yy.Expression.prototype.toString;
+
+yy.GroupExpression = function(params) {
+ return yy.extend(this, params);
+};
+yy.GroupExpression.prototype.toString = function() {
+ return this.type + '(' + this.group.toString() + ')';
+};
+
+// Alasql Linq library
+
+yy.FromData = function (params) {
+ return yy.extend(this, params);
+};
+yy.FromData.prototype.toString = function () {
+ if (this.data) return 'DATA(' + ((Math.random() * 10e15) | 0) + ')';
+ else return '?';
+};
+yy.FromData.prototype.toJS = function () {
+
+};
+
+yy.Select.prototype.exec = function (params, cb) {
+ if (this.preparams) params = this.preparams.concat(params);
+
+ var databaseid = alasql.useid;
+ var db = alasql.databases[databaseid];
+ var sql = this.toString();
+ var hh = hash(sql);
+
+ var statement = this.compile(databaseid);
+ if (!statement) return;
+ statement.sql = sql;
+ statement.dbversion = db.dbversion;
+
+ // Secure sqlCache size
+ if (db.sqlCacheSize > alasql.MAXSQLCACHESIZE) {
+ db.resetSqlCache();
+ }
+ db.sqlCacheSize++;
+ db.sqlCache[hh] = statement;
+ var res = (alasql.res = statement(params, cb));
+ return res;
+};
+
+yy.Select.prototype.Select = function () {
+ var self = this;
+ var args = [];
+ if (arguments.length > 1) {
+ args = Array.prototype.slice.call(arguments);
+ } else if (arguments.length == 1) {
+ if (Array.isArray(arguments[0])) {
+ args = arguments[0];
+ } else {
+ args = [arguments[0]];
+ }
+ } else {
+ throw new Error('Wrong number of arguments of Select() function');
+ }
+
+ self.columns = [];
+
+ args.forEach(function (arg) {
+ if (typeof arg == 'string') {
+ self.columns.push(new yy.Column({columnid: arg}));
+ } else if (typeof arg == 'function') {
+ var pari = 0;
+ if (self.preparams) {
+ pari = self.preparams.length;
+ } else {
+ self.preparams = [];
+ }
+ self.preparams.push(arg);
+ self.columns.push(new yy.Column({columnid: '*', func: arg, param: pari}));
+ } else {
+ // Unknown type
+ }
+ });
+
+ return self;
+};
+
+yy.Select.prototype.From = function (tableid) {
+ var self = this;
+ if (!self.from) self.from = [];
+ if (Array.isArray(tableid)) {
+ var pari = 0;
+ if (self.preparams) {
+ pari = self.preparams.length;
+ } else {
+ self.preparams = [];
+ }
+ self.preparams.push(tableid);
+ self.from.push(new yy.ParamValue({param: pari}));
+ } else if (typeof tableid == 'string') {
+ self.from.push(new yy.Table({tableid: tableid}));
+ } else {
+ throw new Error('Unknown arguments in From() function');
+ }
+ return self;
+};
+
+yy.Select.prototype.OrderBy = function () {
+ var self = this;
+ var args = [];
+
+ self.order = [];
+
+ if (arguments.length == 0) {
+ // self.order.push(new yy.OrderExpression({expression: new yy.Column({columnid:"_"}), direction:'ASC'}));
+ args = ['_'];
+ } else if (arguments.length > 1) {
+ args = Array.prototype.slice.call(arguments);
+ } else if (arguments.length == 1) {
+ if (Array.isArray(arguments[0])) {
+ args = arguments[0];
+ } else {
+ args = [arguments[0]];
+ }
+ } else {
+ throw new Error('Wrong number of arguments of Select() function');
+ }
+
+ if (args.length > 0) {
+ args.forEach(function (arg) {
+ var expr = new yy.Column({columnid: arg});
+ if (typeof arg == 'function') {
+ expr = arg;
+ }
+ self.order.push(new yy.OrderExpression({expression: expr, direction: 'ASC'}));
+ });
+ }
+ return self;
+};
+
+yy.Select.prototype.Top = function (topnum) {
+ var self = this;
+ self.top = new yy.NumValue({value: topnum});
+ return self;
+};
+
+yy.Select.prototype.GroupBy = function () {
+ var self = this;
+ var args = [];
+
+ if (arguments.length > 1) {
+ args = Array.prototype.slice.call(arguments);
+ } else if (arguments.length == 1) {
+ if (Array.isArray(arguments[0])) {
+ args = arguments[0];
+ } else {
+ args = [arguments[0]];
+ }
+ } else {
+ throw new Error('Wrong number of arguments of Select() function');
+ }
+
+ self.group = [];
+
+ args.forEach(function (arg) {
+ var expr = new yy.Column({columnid: arg});
+ self.group.push(expr);
+ });
+
+ return self;
+};
+
+yy.Select.prototype.Where = function (expr) {
+ var self = this;
+ if (typeof expr == 'function') {
+ self.where = expr;
+ }
+ return self;
+};
+
+/*
+//
+// 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(dontas) {
+ 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();
+
+ if (this.funcid !== 'CURRENT_TIMESTAMP') {
+ s += '(';
+ if (this.args && this.args.length > 0) {
+ s += this.args
+ .map(function(arg) {
+ return arg.toString();
+ })
+ .join(',');
+ }
+ s += ')';
+ }
+
+ if (this.as && !dontas) s += ' AS ' + this.as.toString();
+ // if(this.alias) s += ' AS '+this.alias;
+ return s;
+};
+
+yy.FuncValue.prototype.execute = function(databaseid, params, cb) {
+ var res = 1;
+ alasql.precompile(this, databaseid, params); // Precompile queries
+
+ var expr = new Function('params,alasql', 'var y;return ' + this.toJS('', '', null));
+ expr(params, alasql);
+ if (cb) res = cb(res);
+ return res;
+};
+
+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.toJS = function(context, tableid, defcols) {
+ var s = '';
+ var funcid = this.funcid;
+ // IF this is standard compile functions
+ if (!alasql.fn[funcid] && 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.toJS(context, tableid);
+ })
+ );
+ } else {
+ s += alasql.stdlib[funcid.toUpperCase()]();
+ }
+ } else if (!alasql.fn[funcid] && alasql.stdfn[funcid.toUpperCase()]) {
+ if (this.newid) s += 'new ';
+ s += 'alasql.stdfn.' + this.funcid.toUpperCase() + '(';
+ // if(this.args) s += this.args.toJS(context, tableid);
+ if (this.args && this.args.length > 0) {
+ s += this.args
+ .map(function(arg) {
+ return arg.toJS(context, tableid, defcols);
+ })
+ .join(',');
+ }
+ s += ')';
+ } else {
+ // 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.toJS(context, tableid);
+ if (this.args && this.args.length > 0) {
+ s += this.args
+ .map(function(arg) {
+ return arg.toJS(context, tableid, defcols);
+ })
+ .join(',');
+ }
+ s += ')';
+ }
+
+ // if(this.alias) s += ' AS '+this.alias;
+ return s;
+};
+
+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 + ')';
+};
+
+stdfn.CONCAT = function() {
+ return Array.prototype.slice.call(arguments).join('');
+};
+stdlib.EXP = function(a) {
+ return 'Math.pow(Math.E,' + 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 und(s, 'y.length');
+};
+//stdlib.LENGTH = function(s) {return '('+s+').length'};
+
+stdlib.LOWER = stdlib.LCASE = function(s) {
+ return und(s, 'String(y).toLowerCase()');
+};
+//stdlib.LCASE = function(s) {return '('+s+').toLowerCase()';}
+
+// Returns a character expression after it removes leading blanks.
+// see https://docs.microsoft.com/en-us/sql/t-sql/functions/ltrim-transact-sql
+stdlib.LTRIM = function(s) {
+ return und(s, 'y.replace(/^[ ]+/,"")');
+};
+
+// Returns a character string after truncating all trailing spaces.
+// see https://docs.microsoft.com/en-us/sql/t-sql/functions/rtrim-transact-sql
+stdlib.RTRIM = function(s) {
+ return und(s, 'y.replace(/[ ]+$/,"")');
+};
+
+stdlib.MAX = stdlib.GREATEST = function() {
+ return (
+ '[' +
+ Array.prototype.join.call(arguments, ',') +
+ '].reduce(function (a, b) { return a > b ? a : b; })'
+ );
+};
+
+stdlib.MIN = stdlib.LEAST = function() {
+ return (
+ '[' +
+ Array.prototype.join.call(arguments, ',') +
+ '].reduce(function (a, b) { return a < b ? a : b; })'
+ );
+};
+
+stdlib.SUBSTRING = stdlib.SUBSTR = stdlib.MID = function(a, b, c) {
+ if (arguments.length == 2) return und(a, 'y.substr(' + b + '-1)');
+ else if (arguments.length == 3) return und(a, 'y.substr(' + b + '-1,' + c + ')');
+};
+
+stdfn.REGEXP_LIKE = function(a, b, c) {
+
+ return (a || '').search(RegExp(b, c)) > -1;
+};
+
+// Here we uses undefined instead of null
+stdlib.ISNULL = 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.CEIL = stdlib.CEILING = function(s) {
+ return 'Math.ceil(' + s + ')';
+};
+stdlib.FLOOR = function(s) {
+ return 'Math.floor(' + s + ')';
+};
+
+stdlib.ROWNUM = function() {
+ return '1';
+};
+stdlib.ROW_NUMBER = function() {
+ return '1';
+};
+
+stdlib.SQRT = function(s) {
+ return 'Math.sqrt(' + s + ')';
+};
+
+stdlib.TRIM = function(s) {
+ return und(s, 'y.trim()');
+};
+
+stdlib.UPPER = stdlib.UCASE = function(s) {
+ return und(s, 'String(y).toUpperCase()');
+};
+
+// Concatination of strings
+stdfn.CONCAT_WS = function() {
+ var args = Array.prototype.slice.call(arguments);
+ return args.slice(1, args.length).join(args[0]);
+};
+
+//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, stage) {
+ if (stage === 1) {
+ return '' + v;
+ } else if (stage === 2) {
+ s += ',' + v;
+ return s;
+ }
+ return s;
+};
+
+alasql.aggr.MEDIAN = function(v, s, stage) {
+ if (stage === 2) {
+ if (v !== null) {
+ s.push(v);
+ }
+ return s;
+ } else if (stage === 1) {
+ if (v === null) {
+ return [];
+ }
+ return [v];
+ } else {
+ if (!s.length) {
+ return s;
+ }
+
+ var r = s.sort(function(a, b) {
+ if (a === b) {
+ return 0;
+ }
+ if (a > b) {
+ return 1;
+ }
+ return -1;
+ });
+ var p = (r.length + 1) / 2;
+ if (Number.isInteger(p)) {
+ return r[p - 1];
+ }
+
+ if (typeof r[Math.floor(p - 1)] !== 'number') {
+ return r[Math.floor(p - 1)];
+ }
+
+ return (r[Math.floor(p - 1)] + r[Math.ceil(p - 1)]) / 2;
+ }
+};
+
+alasql.aggr.QUART = function(v, s, stage, nth) {
+ //Quartile (first quartile per default or input param)
+ if (stage === 2) {
+ if (v !== null) {
+ s.push(v);
+ }
+ return s;
+ } else if (stage === 1) {
+ if (v === null) {
+ return [];
+ }
+ return [v];
+ } else {
+ if (!s.length) {
+ return s;
+ }
+
+ nth = !nth ? 1 : nth;
+ var r = s.sort(function(a, b) {
+ if (a === b) {
+ return 0;
+ }
+ if (a > b) {
+ return 1;
+ }
+ return -1;
+ });
+ var p = (nth * (r.length + 1)) / 4;
+ if (Number.isInteger(p)) {
+ return r[p - 1]; //Integer value
+ }
+ return r[Math.floor(p)]; //Math.ceil -1 or Math.floor
+ }
+};
+
+alasql.aggr.QUART2 = function(v, s, stage) {
+ //Second Quartile
+ return alasql.aggr.QUART(v, s, stage, 2);
+};
+alasql.aggr.QUART3 = function(v, s, stage) {
+ //Third Quartile
+ return alasql.aggr.QUART(v, s, stage, 3);
+};
+
+// Standard deviation
+alasql.aggr.VAR = function(v, s, stage) {
+ if (stage === 1) {
+ if (v === null) {
+ return {arr: [], sum: 0};
+ }
+ return {arr: [v], sum: v};
+ } else if (stage === 2) {
+ if (v === null) {
+ return s;
+ }
+ s.arr.push(v);
+ s.sum += v;
+ return s;
+ } else {
+ var N = s.arr.length;
+ var avg = s.sum / N;
+ var std = 0;
+ for (var i = 0; i < N; i++) {
+ std += (s.arr[i] - avg) * (s.arr[i] - avg);
+ }
+ std = std / (N - 1);
+ return std;
+ }
+};
+
+alasql.aggr.STDEV = function(v, s, stage) {
+ if (stage === 1 || stage === 2) {
+ return alasql.aggr.VAR(v, s, stage);
+ } else {
+ return Math.sqrt(alasql.aggr.VAR(v, s, stage));
+ }
+};
+
+// Standard deviation
+// alasql.aggr.VARP = function(v,s,acc){
+
+// };
+
+alasql.aggr.VARP = function(v, s, stage) {
+ if (stage == 1) {
+ return {arr: [v], sum: v};
+ } else if (stage == 2) {
+ s.arr.push(v);
+ s.sum += v;
+ return s;
+ } else {
+ var N = s.arr.length;
+ var avg = s.sum / N;
+ var std = 0;
+ for (var i = 0; i < N; i++) {
+ std += (s.arr[i] - avg) * (s.arr[i] - avg);
+ }
+ std = std / N;
+ return std;
+ }
+};
+
+alasql.aggr.STD = alasql.aggr.STDDEV = alasql.aggr.STDEVP = function(v, s, stage) {
+ if (stage == 1 || stage == 2) {
+ return alasql.aggr.VARP(v, s, stage);
+ } else {
+ return Math.sqrt(alasql.aggr.VARP(v, s, stage));
+ }
+};
+
+alasql._aggrOriginal = alasql.aggr;
+alasql.aggr = {};
+Object.keys(alasql._aggrOriginal).forEach(function(k) {
+ alasql.aggr[k] = function(v, s, stage) {
+ if (stage === 3 && typeof s === 'undefined') return undefined;
+ return alasql._aggrOriginal[k].apply(null, arguments);
+ };
+});
+
+// String functions
+stdfn.REPLACE = function(target, pattern, replacement) {
+ return (target || '').split(pattern).join(replacement);
+};
+
+// This array is required for fast GUID generation
+var lut = [];
+for (var i = 0; i < 256; i++) {
+ lut[i] = (i < 16 ? '0' : '') + i.toString(16);
+}
+
+stdfn.NEWID = stdfn.UUID = stdfn.GEN_RANDOM_UUID = function() {
+ var d0 = (Math.random() * 0xffffffff) | 0;
+ var d1 = (Math.random() * 0xffffffff) | 0;
+ var d2 = (Math.random() * 0xffffffff) | 0;
+ var d3 = (Math.random() * 0xffffffff) | 0;
+ return (
+ lut[d0 & 0xff] +
+ lut[(d0 >> 8) & 0xff] +
+ lut[(d0 >> 16) & 0xff] +
+ lut[(d0 >> 24) & 0xff] +
+ '-' +
+ lut[d1 & 0xff] +
+ lut[(d1 >> 8) & 0xff] +
+ '-' +
+ lut[((d1 >> 16) & 0x0f) | 0x40] +
+ lut[(d1 >> 24) & 0xff] +
+ '-' +
+ lut[(d2 & 0x3f) | 0x80] +
+ lut[(d2 >> 8) & 0xff] +
+ '-' +
+ lut[(d2 >> 16) & 0xff] +
+ lut[(d2 >> 24) & 0xff] +
+ lut[d3 & 0xff] +
+ lut[(d3 >> 8) & 0xff] +
+ lut[(d3 >> 16) & 0xff] +
+ lut[(d3 >> 24) & 0xff]
+ );
+};
+
+/*
+//
+// CASE for Alasql.js
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+yy.CaseValue = function(params) {
+ return yy.extend(this, params);
+};
+yy.CaseValue.prototype.toString = function() {
+ var s = 'CASE ';
+ if (this.expression) s += this.expression.toString();
+ if (this.whens) {
+ s += this.whens
+ .map(function(w) {
+ return ' WHEN ' + w.when.toString() + ' THEN ' + w.then.toString();
+ })
+ .join();
+ }
+ s += ' END';
+ return s;
+};
+
+yy.CaseValue.prototype.findAggregator = function(query) {
+
+ if (this.expression && this.expression.findAggregator) this.expression.findAggregator(query);
+ if (this.whens && this.whens.length > 0) {
+ this.whens.forEach(function(w) {
+ if (w.when.findAggregator) w.when.findAggregator(query);
+ if (w.then.findAggregator) w.then.findAggregator(query);
+ });
+ }
+ if (this.elses && this.elses.findAggregator) this.elses.findAggregator(query);
+};
+
+yy.CaseValue.prototype.toJS = function(context, tableid, defcols) {
+ var s = '((function(' + context + ',params,alasql){var y,r;';
+ if (this.expression) {
+ // this.expression.toJS(context, tableid)
+ s += 'v=' + this.expression.toJS(context, tableid, defcols) + ';';
+ s += (this.whens || [])
+ .map(function(w) {
+ return (
+ ' if(v==' +
+ w.when.toJS(context, tableid, defcols) +
+ ') {r=' +
+ w.then.toJS(context, tableid, defcols) +
+ '}'
+ );
+ })
+ .join(' else ');
+ if (this.elses) s += ' else {r=' + this.elses.toJS(context, tableid, defcols) + '}';
+ } else {
+ s += (this.whens || [])
+ .map(function(w) {
+ return (
+ ' if(' +
+ w.when.toJS(context, tableid, defcols) +
+ ') {r=' +
+ w.then.toJS(context, tableid, defcols) +
+ '}'
+ );
+ })
+ .join(' else ');
+ if (this.elses) s += ' else {r=' + this.elses.toJS(context, tableid, defcols) + '}';
+ }
+ // TODO remove bind from CASE
+ s += ';return r;}).bind(this))(' + context + ',params,alasql)';
+
+ return s;
+};
+
+/*
+//
+// JSON for Alasql.js
+// Date: 19.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+yy.Json = function(params) {
+ return yy.extend(this, params);
+};
+yy.Json.prototype.toString = function() {
+ var s = ''; // '@'
+ s += JSONtoString(this.value);
+ s += '';
+ return s;
+};
+
+var JSONtoString = (alasql.utils.JSONtoString = function(obj) {
+ var s = '';
+ if (typeof obj == 'string') s = '"' + obj + '"';
+ else if (typeof obj == 'number') s = obj;
+ else if (typeof obj == 'boolean') s = obj;
+ else if (typeof obj == 'object') {
+ if (Array.isArray(obj)) {
+ s +=
+ '[' +
+ obj
+ .map(function(b) {
+ return JSONtoString(b);
+ })
+ .join(',') +
+ ']';
+ } else if (!obj.toJS || obj instanceof yy.Json) {
+ // to prevent recursion
+ s = '{';
+ var ss = [];
+ for (var k in obj) {
+ var s1 = '';
+ if (typeof k == 'string') s1 += '"' + k + '"';
+ else if (typeof k == 'number') s1 += k;
+ else if (typeof k == 'boolean') s1 += k;
+ else {
+ throw new Error('THis is not ES6... no expressions on left side yet');
+ }
+ s1 += ':' + JSONtoString(obj[k]);
+ ss.push(s1);
+ }
+ s += ss.join(',') + '}';
+ } else if (obj.toString) {
+ s = obj.toString();
+ } else {
+ throw new Error('1Can not show JSON object ' + JSON.stringify(obj));
+ }
+ } else {
+ throw new Error('2Can not show JSON object ' + JSON.stringify(obj));
+ }
+
+ return s;
+});
+
+function JSONtoJS(obj, context, tableid, defcols) {
+ var s = '';
+ if (typeof obj == 'string') s = '"' + obj + '"';
+ else if (typeof obj == 'number') s = '(' + obj + ')';
+ else if (typeof obj == 'boolean') s = obj;
+ else if (typeof obj == 'object') {
+ if (Array.isArray(obj)) {
+ s +=
+ '[' +
+ obj
+ .map(function(b) {
+ return JSONtoJS(b, context, tableid, defcols);
+ })
+ .join(',') +
+ ']';
+ } else if (!obj.toJS || obj instanceof yy.Json) {
+ // to prevent recursion
+ s = '{';
+ var ss = [];
+ for (var k in obj) {
+ var s1 = '';
+ if (typeof k == 'string') s1 += '"' + k + '"';
+ else if (typeof k == 'number') s1 += k;
+ else if (typeof k == 'boolean') s1 += k;
+ else {
+ throw new Error('THis is not ES6... no expressions on left side yet');
+ }
+ s1 += ':' + JSONtoJS(obj[k], context, tableid, defcols);
+ ss.push(s1);
+ }
+ s += ss.join(',') + '}';
+ } else if (obj.toJS) {
+ s = obj.toJS(context, tableid, defcols);
+ } else {
+ throw new Error('1Can not parse JSON object ' + JSON.stringify(obj));
+ }
+ } else {
+ throw new Error('2Can not parse JSON object ' + JSON.stringify(obj));
+ }
+
+ return s;
+}
+
+yy.Json.prototype.toJS = function(context, tableid, defcols) {
+ // TODO redo
+ return JSONtoJS(this.value, context, tableid, defcols);
+};
+
+/*
+//
+// CAST and CONVERT functions
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+yy.Convert = function(params) {
+ return yy.extend(this, params);
+};
+yy.Convert.prototype.toString = function() {
+ var s = 'CONVERT(';
+ s += this.dbtypeid;
+ if (typeof this.dbsize != 'undefined') {
+ s += '(' + this.dbsize;
+ if (this.dbprecision) s += ',' + this.dbprecision;
+ s += ')';
+ }
+ s += ',' + this.expression.toString();
+ if (this.style) s += ',' + this.style;
+ s += ')';
+ return s;
+};
+yy.Convert.prototype.toJS = function(context, tableid, defcols) {
+ // if(this.style) {
+ return (
+ 'alasql.stdfn.CONVERT(' +
+ this.expression.toJS(context, tableid, defcols) +
+ ',{dbtypeid:"' +
+ this.dbtypeid +
+ '",dbsize:' +
+ this.dbsize +
+ ',dbprecision:' +
+ this.dbprecision +
+ ',style:' +
+ this.style +
+ '})'
+ );
+ // }
+
+ throw new Error('There is not such type conversion for ' + this.toString());
+};
+
+/**
+ Convert one type to another
+ */
+alasql.stdfn.CONVERT = function(value, args) {
+ var val = value;
+
+ if (args.style) {
+ // TODO 9,109, 20,120,21,121,126,130,131 conversions
+ var t;
+ if (/\d{8}/.test(val)) {
+ t = new Date(+val.substr(0, 4), +val.substr(4, 2) - 1, +val.substr(6, 2));
+ } else {
+ t = new Date(val);
+ }
+ switch (args.style) {
+ case 1: // mm/dd/yy
+ val =
+ ('0' + (t.getMonth() + 1)).substr(-2) +
+ '/' +
+ ('0' + t.getDate()).substr(-2) +
+ '/' +
+ ('0' + t.getYear()).substr(-2);
+ break;
+ case 2: // yy.mm.dd
+ val =
+ ('0' + t.getYear()).substr(-2) +
+ '.' +
+ ('0' + (t.getMonth() + 1)).substr(-2) +
+ '.' +
+ ('0' + t.getDate()).substr(-2);
+ break;
+ case 3: // dd/mm/yy
+ val =
+ ('0' + t.getDate()).substr(-2) +
+ '/' +
+ ('0' + (t.getMonth() + 1)).substr(-2) +
+ '/' +
+ ('0' + t.getYear()).substr(-2);
+ break;
+ case 4: // dd.mm.yy
+ val =
+ ('0' + t.getDate()).substr(-2) +
+ '.' +
+ ('0' + (t.getMonth() + 1)).substr(-2) +
+ '.' +
+ ('0' + t.getYear()).substr(-2);
+ break;
+ case 5: // dd-mm-yy
+ val =
+ ('0' + t.getDate()).substr(-2) +
+ '-' +
+ ('0' + (t.getMonth() + 1)).substr(-2) +
+ '-' +
+ ('0' + t.getYear()).substr(-2);
+ break;
+ case 6: // dd mon yy
+ val =
+ ('0' + t.getDate()).substr(-2) +
+ ' ' +
+ t
+ .toString()
+ .substr(4, 3)
+ .toLowerCase() +
+ ' ' +
+ ('0' + t.getYear()).substr(-2);
+ break;
+ case 7: // Mon dd,yy
+ val =
+ t.toString().substr(4, 3) +
+ ' ' +
+ ('0' + t.getDate()).substr(-2) +
+ ',' +
+ ('0' + t.getYear()).substr(-2);
+ break;
+ case 8: // hh:mm:ss
+ case 108: // hh:mm:ss
+ val =
+ ('0' + t.getHours()).substr(-2) +
+ ':' +
+ ('0' + t.getMinutes()).substr(-2) +
+ ':' +
+ ('0' + t.getSeconds()).substr(-2);
+ break;
+ case 10: // mm-dd-yy
+ val =
+ ('0' + (t.getMonth() + 1)).substr(-2) +
+ '-' +
+ ('0' + t.getDate()).substr(-2) +
+ '-' +
+ ('0' + t.getYear()).substr(-2);
+ break;
+ case 11: // yy/mm/dd
+ val =
+ ('0' + t.getYear()).substr(-2) +
+ '/' +
+ ('0' + (t.getMonth() + 1)).substr(-2) +
+ '/' +
+ ('0' + t.getDate()).substr(-2);
+ break;
+ case 12: // yymmdd
+ val =
+ ('0' + t.getYear()).substr(-2) +
+ ('0' + (t.getMonth() + 1)).substr(-2) +
+ ('0' + t.getDate()).substr(-2);
+ break;
+ case 101: // mm/dd/yyyy
+ val =
+ ('0' + (t.getMonth() + 1)).substr(-2) +
+ '/' +
+ ('0' + t.getDate()).substr(-2) +
+ '/' +
+ t.getFullYear();
+ break;
+ case 102: // yyyy.mm.dd
+ val =
+ t.getFullYear() +
+ '.' +
+ ('0' + (t.getMonth() + 1)).substr(-2) +
+ '.' +
+ ('0' + t.getDate()).substr(-2);
+ break;
+ case 103: // dd/mm/yyyy
+ val =
+ ('0' + t.getDate()).substr(-2) +
+ '/' +
+ ('0' + (t.getMonth() + 1)).substr(-2) +
+ '/' +
+ t.getFullYear();
+ break;
+ case 104: // dd.mm.yyyy
+ val =
+ ('0' + t.getDate()).substr(-2) +
+ '.' +
+ ('0' + (t.getMonth() + 1)).substr(-2) +
+ '.' +
+ t.getFullYear();
+ break;
+ case 105: // dd-mm-yyyy
+ val =
+ ('0' + t.getDate()).substr(-2) +
+ '-' +
+ ('0' + (t.getMonth() + 1)).substr(-2) +
+ '-' +
+ t.getFullYear();
+ break;
+ case 106: // dd mon yyyy
+ val =
+ ('0' + t.getDate()).substr(-2) +
+ ' ' +
+ t
+ .toString()
+ .substr(4, 3)
+ .toLowerCase() +
+ ' ' +
+ t.getFullYear();
+ break;
+ case 107: // Mon dd,yyyy
+ val =
+ t.toString().substr(4, 3) +
+ ' ' +
+ ('0' + t.getDate()).substr(-2) +
+ ',' +
+ t.getFullYear();
+ break;
+ case 110: // mm-dd-yyyy
+ val =
+ ('0' + (t.getMonth() + 1)).substr(-2) +
+ '-' +
+ ('0' + t.getDate()).substr(-2) +
+ '-' +
+ t.getFullYear();
+ break;
+ case 111: // yyyy/mm/dd
+ val =
+ t.getFullYear() +
+ '/' +
+ ('0' + (t.getMonth() + 1)).substr(-2) +
+ '/' +
+ ('0' + t.getDate()).substr(-2);
+ break;
+
+ case 112: // yyyymmdd
+ val =
+ t.getFullYear() +
+ ('0' + (t.getMonth() + 1)).substr(-2) +
+ ('0' + t.getDate()).substr(-2);
+ break;
+ default:
+ throw new Error('The CONVERT style ' + args.style + ' is not realized yet.');
+ }
+ }
+
+ var udbtypeid = args.dbtypeid.toUpperCase();
+
+ if (args.dbtypeid == 'Date') {
+ return new Date(val);
+ } else if (udbtypeid == 'DATE') {
+ var d = new Date(val);
+ var s =
+ d.getFullYear() +
+ '.' +
+ ('0' + (d.getMonth() + 1)).substr(-2) +
+ '.' +
+ ('0' + d.getDate()).substr(-2);
+ return s;
+ } else if (udbtypeid == 'DATETIME' || udbtypeid == 'DATETIME2') {
+ var d = new Date(val);
+ var s =
+ d.getFullYear() +
+ '.' +
+ ('0' + (d.getMonth() + 1)).substr(-2) +
+ '.' +
+ ('0' + d.getDate()).substr(-2);
+ s +=
+ ' ' +
+ ('0' + d.getHours()).substr(-2) +
+ ':' +
+ ('0' + d.getMinutes()).substr(-2) +
+ ':' +
+ ('0' + d.getSeconds()).substr(-2);
+ s += '.' + ('00' + d.getMilliseconds()).substr(-3);
+ return s;
+ } else if (['MONEY'].indexOf(udbtypeid) > -1) {
+ var m = +val;
+ return (m | 0) + ((m * 100) % 100) / 100;
+ } else if (['BOOLEAN'].indexOf(udbtypeid) > -1) {
+ return !!val;
+ } else if (
+ ['INT', 'INTEGER', 'SMALLINT', 'BIGINT', 'SERIAL', 'SMALLSERIAL', 'BIGSERIAL'].indexOf(
+ args.dbtypeid.toUpperCase()
+ ) > -1
+ ) {
+ return val | 0;
+ } else if (
+ ['STRING', 'VARCHAR', 'NVARCHAR', 'CHARACTER VARIABLE'].indexOf(
+ args.dbtypeid.toUpperCase()
+ ) > -1
+ ) {
+ if (args.dbsize) return ('' + val).substr(0, args.dbsize);
+ else return '' + val;
+ } else if (['CHAR', 'CHARACTER', 'NCHAR'].indexOf(udbtypeid) > -1) {
+ return (val + new Array(args.dbsize + 1).join(' ')).substr(0, args.dbsize);
+ //else return ""+val.substr(0,1);
+ } else if (['NUMBER', 'FLOAT', 'DECIMAL', 'NUMERIC'].indexOf(udbtypeid) > -1) {
+ var m = +val;
+ //toPrecision sets the number of numbers total in the result
+ m = args.dbsize !== undefined ? parseFloat(m.toPrecision(args.dbsize)) : m;
+ //toFixed sets the number of numbers to the right of the decimal
+ m = args.dbprecision !== undefined ? parseFloat(m.toFixed(args.dbprecision)) : m;
+ return m;
+ } else if (['JSON'].indexOf(udbtypeid) > -1) {
+ if (typeof val == 'object') return val;
+ try {
+ return JSON.parse(val);
+ } catch (err) {
+ throw new Error('Cannot convert string to JSON');
+ }
+ }
+ return val;
+};
+
+/*
+//
+// CREATE TABLE for Alasql.js
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+/* global alasql, yy, hash */
+
+yy.ColumnDef = function (params) {
+ return yy.extend(this, params);
+};
+yy.ColumnDef.prototype.toString = function () {
+ var s = this.columnid;
+ if (this.dbtypeid) {
+ s += ' ' + this.dbtypeid;
+ }
+
+ if (this.dbsize) {
+ s += '(' + this.dbsize;
+ if (this.dbprecision) {
+ s += ',' + this.dbprecision;
+ }
+ s += ')';
+ }
+
+ if (this.primarykey) {
+ s += ' PRIMARY KEY';
+ }
+
+ if (this.notnull) {
+ s += ' NOT NULL';
+ }
+
+ return s;
+};
+
+yy.CreateTable = function (params) {
+ return yy.extend(this, params);
+};
+yy.CreateTable.prototype.toString = function () {
+ var s = 'CREATE';
+ if (this.temporary) {
+ s += ' TEMPORARY';
+ }
+
+ if (this.view) {
+ s += ' VIEW';
+ } else {
+ s += ' ' + (this["class"] ? 'CLASS' : 'TABLE');
+ }
+ if (this.ifnotexists) {
+ s += ' IF NOT EXISTS';
+ }
+ s += ' ' + this.table.toString();
+ if (this.viewcolumns) {
+ s +=
+ '(' +
+ this.viewcolumns
+ .map(function (vcol) {
+ return vcol.toString();
+ })
+ .join(',') +
+ ')';
+ }
+ if (this.as) {
+ s += ' AS ' + this.as;
+ } else {
+ var ss = this.columns.map(function (col) {
+ return col.toString();
+ });
+ s += ' (' + ss.join(',') + ')';
+ }
+
+ if (this.view && this.select) {
+ s += ' AS ' + this.select.toString();
+ }
+
+ return s;
+};
+
+// CREATE TABLE
+//yy.CreateTable.prototype.compile = returnUndefined;
+yy.CreateTable.prototype.execute = function (databaseid, params, cb) {
+ // var self = this;
+ var db = alasql.databases[this.table.databaseid || databaseid];
+
+ var tableid = this.table.tableid;
+ if (!tableid) {
+ throw new Error('Table name is not defined');
+ }
+
+ // var ifnotexists = this.ifnotexists;
+ var columns = this.columns;
+ // if(false) {
+ // if(!columns) {
+ // throw new Error('Columns are not defined');
+ // }
+ // }
+ var constraints = this.constraints || [];
+
+ // IF NOT EXISTS
+ if (this.ifnotexists && db.tables[tableid]) {
+ return cb ? cb(0) : 0;
+ }
+
+ if (db.tables[tableid]) {
+ throw new Error(
+ "Can not create table '" +
+ tableid +
+ "', because it already exists in the database '" +
+ db.databaseid +
+ "'"
+ );
+ }
+
+ var table = (db.tables[tableid] = new alasql.Table()); // TODO Can use special object?
+ // If this is a class
+ if (this["class"]) {
+ table.isclass = true;
+ }
+
+ var ss = []; // DEFAULT function components
+ var uss = []; // ON UPDATE function components
+ if (columns) {
+ columns.forEach(function (col) {
+ var dbtypeid = col.dbtypeid;
+ if (!alasql.fn[dbtypeid]) {
+ dbtypeid = dbtypeid.toUpperCase();
+ }
+
+ // Process SERIAL data type like Postgress
+ if (['SERIAL', 'SMALLSERIAL', 'BIGSERIAL'].indexOf(dbtypeid) > -1) {
+ col.identity = {value: 1, step: 1};
+ }
+
+ var newcol = {
+ columnid: col.columnid,
+ dbtypeid: dbtypeid,
+ dbsize: col.dbsize, // Fixed issue #150
+ dbprecision: col.dbprecision, // Fixed issue #150
+ notnull: col.notnull,
+ identity: col.identity,
+ };
+ if (col.identity) {
+ table.identities[col.columnid] = {
+ value: +col.identity.value,
+ step: +col.identity.step,
+ };
+ // ss.push('\''+col.columnid+'\':(alasql.databases[\''+db.databaseid+'\'].tables[\''
+ // +tableid+'\'].identities[\''+col.columnid+'\'].value)');
+ }
+ if (col.check) {
+ table.checks.push({
+ id: col.check.constrantid,
+ fn: new Function('r', 'var y;return ' + col.check.expression.toJS('r', '')),
+ });
+ }
+
+ if (col["default"]) {
+ ss.push("'" + col.columnid + "':" + col["default"].toJS('r', ''));
+ }
+
+ // Check for primary key
+ if (col.primarykey) {
+ var pk = (table.pk = {});
+ pk.columns = [col.columnid];
+ pk.onrightfns = "r['" + col.columnid + "']";
+ pk.onrightfn = new Function('r', 'var y;return ' + pk.onrightfns);
+ pk.hh = hash(pk.onrightfns);
+ table.uniqs[pk.hh] = {};
+ }
+
+ // UNIQUE clause
+ if (col.unique) {
+ var uk = {};
+ table.uk = table.uk || [];
+ table.uk.push(uk);
+ uk.columns = [col.columnid];
+ uk.onrightfns = "r['" + col.columnid + "']";
+ uk.onrightfn = new Function('r', 'var y;return ' + uk.onrightfns);
+ uk.hh = hash(uk.onrightfns);
+ table.uniqs[uk.hh] = {};
+ }
+
+ // UNIQUE clause
+ if (col.foreignkey) {
+
+ var fk = col.foreignkey.table;
+ var fktable = alasql.databases[fk.databaseid || databaseid].tables[fk.tableid];
+ if (typeof fk.columnid === 'undefined') {
+ if (fktable.pk.columns && fktable.pk.columns.length > 0) {
+ fk.columnid = fktable.pk.columns[0];
+ } else {
+ throw new Error('FOREIGN KEY allowed only to tables with PRIMARY KEYs');
+ }
+ }
+
+ var fkfn = function (r) {
+ var rr = {};
+ if (typeof r[col.columnid] === 'undefined') {
+ return true;
+ }
+ rr[fk.columnid] = r[col.columnid];
+ var addr = fktable.pk.onrightfn(rr);
+
+ if (!fktable.uniqs[fktable.pk.hh][addr]) {
+ throw new Error(
+ // 'Foreign key "' +
+ // r[col.columnid] +
+ // '" is not found in table ' +
+ // fktable.tableid
+ 'Foreign key violation' //changed error message
+ );
+ }
+ return true;
+ };
+ table.checks.push({fn: fkfn});
+
+ }
+
+ if (col.onupdate) {
+ uss.push("r['" + col.columnid + "']=" + col.onupdate.toJS('r', ''));
+ }
+
+ table.columns.push(newcol);
+ table.xcolumns[newcol.columnid] = newcol;
+ });
+ }
+ table.defaultfns = ss.join(',');
+ table.onupdatefns = uss.join(';');
+
+ // if(constraints) {
+ constraints.forEach(function (con) {
+
+ var checkfn;
+
+ if (con.type === 'PRIMARY KEY') {
+ if (table.pk) {
+ throw new Error('Primary key already exists');
+ }
+ var pk = (table.pk = {});
+ pk.columns = con.columns;
+ pk.onrightfns = pk.columns
+ .map(function (columnid) {
+ return "r['" + columnid + "']";
+ })
+ .join("+'`'+");
+ pk.onrightfn = new Function('r', 'var y;return ' + pk.onrightfns);
+ pk.hh = hash(pk.onrightfns);
+ table.uniqs[pk.hh] = {};
+ } else if (con.type === 'CHECK') {
+
+ checkfn = new Function('r', 'var y;return ' + con.expression.toJS('r', ''));
+ } else if (con.type === 'UNIQUE') {
+
+ var uk = {};
+ table.uk = table.uk || [];
+ table.uk.push(uk);
+ uk.columns = con.columns;
+ uk.onrightfns = uk.columns
+ .map(function (columnid) {
+ return "r['" + columnid + "']";
+ })
+ .join("+'`'+");
+ uk.onrightfn = new Function('r', 'var y;return ' + uk.onrightfns);
+ uk.hh = hash(uk.onrightfns);
+ table.uniqs[uk.hh] = {};
+ } else if (con.type === 'FOREIGN KEY') {
+ var fk = con.fktable;
+ if (con.fkcolumns && con.fkcolumns.length > 0) {
+ //Composite foreign keys
+ fk.fkcolumns = con.fkcolumns;
+ }
+ var fktable = alasql.databases[fk.databaseid || databaseid].tables[fk.tableid];
+ if (typeof fk.fkcolumns === 'undefined') {
+ //Composite foreign keys
+ fk.fkcolumns = fktable.pk.columns;
+ }
+ fk.columns = con.columns;
+
+ if (fk.fkcolumns.length > fk.columns.length) {
+ throw new Error('Invalid foreign key on table ' + table.tableid);
+ }
+
+ checkfn = function (r) {
+ var rr = {};
+
+ //Composite foreign keys
+ fk.fkcolumns.forEach(function (colFk, i) {
+ if (r[fk.columns[i]] != null) {
+ rr[colFk] = r[fk.columns[i]];
+ }
+ });
+
+ if (Object.keys(rr).length === 0) {
+ //all values of foreign key was null
+ return true;
+ }
+ if (Object.keys(rr).length !== fk.columns.length) {
+ throw new Error('Invalid foreign key on table ' + table.tableid);
+ }
+ //reset fkTable as we need an up to date uniqs
+ var fktable = alasql.databases[fk.databaseid || databaseid].tables[fk.tableid];
+ var addr = fktable.pk.onrightfn(rr);
+
+ if (!fktable.uniqs[fktable.pk.hh][addr]) {
+ throw new Error(
+ 'Foreign key violation' //changed error message
+ );
+ }
+ return true;
+ };
+ }
+ if (checkfn) {
+ table.checks.push({fn: checkfn, id: con.constraintid, fk: con.type === 'FOREIGN KEY'});
+ }
+ });
+
+ if (this.view && this.viewcolumns) {
+ var self = this;
+ this.viewcolumns.forEach(function (vcol, idx) {
+ self.select.columns[idx].as = vcol.columnid;
+ });
+ }
+
+ //Used in 420from queryfn when table.view = true!
+ if (this.view && this.select) {
+ table.view = true;
+
+ table.select = this.select.compile(this.table.databaseid || databaseid);
+ }
+
+ if (db.engineid) {
+
+ return alasql.engines[db.engineid].createTable(
+ this.table.databaseid || databaseid,
+ tableid,
+ this.ifnotexists,
+ cb
+ );
+
+ // return res1;
+ }
+
+ // }
+ // if(table.pk) {
+
+ table.insert = function (r, orreplace) {
+ var oldinserted = alasql.inserted;
+ alasql.inserted = [r];
+
+ var table = this;
+
+ var toreplace = false; // For INSERT OR REPLACE
+
+ /*
+ // IDENTINY or AUTO_INCREMENT
+ // if(table.identities && table.identities.length>0) {
+ // table.identities.forEach(function(ident){
+ // r[ident.columnid] = ident.value;
+ // });
+ // }
+*/
+ // Trigger prevent functionality
+ var prevent = false;
+ for (var tr in table.beforeinsert) {
+ var trigger = table.beforeinsert[tr];
+ if (trigger) {
+ if (trigger.funcid) {
+ if (alasql.fn[trigger.funcid](r) === false) prevent = prevent || true;
+ } else if (trigger.statement) {
+ if (trigger.statement.execute(databaseid) === false) prevent = prevent || true;
+ }
+ }
+ }
+ if (prevent) return;
+
+ // Trigger prevent functionality
+ var escape = false;
+ for (tr in table.insteadofinsert) {
+ escape = true;
+ trigger = table.insteadofinsert[tr];
+ if (trigger) {
+ if (trigger.funcid) {
+ alasql.fn[trigger.funcid](r);
+ } else if (trigger.statement) {
+ trigger.statement.execute(databaseid);
+ }
+ }
+ }
+ if (escape) return;
+
+ for (var columnid in table.identities) {
+ var ident = table.identities[columnid];
+
+ r[columnid] = ident.value;
+
+ }
+
+ if (table.checks && table.checks.length > 0) {
+ table.checks.forEach(function (check) {
+ if (!check.fn(r)) {
+ // if(orreplace) toreplace=true; else
+ throw new Error('Violation of CHECK constraint ' + (check.id || ''));
+ }
+ });
+ }
+
+ table.columns.forEach(function (column) {
+ if (column.notnull && typeof r[column.columnid] === 'undefined') {
+ throw new Error('Wrong NULL value in NOT NULL column ' + column.columnid);
+ }
+ });
+ if (table.pk) {
+ var pk = table.pk;
+ var addr = pk.onrightfn(r);
+
+ if (typeof table.uniqs[pk.hh][addr] !== 'undefined') {
+
+ if (orreplace) toreplace = table.uniqs[pk.hh][addr];
+ else
+ throw new Error('Cannot insert record, because it already exists in primary key index');
+ }
+ // table.uniqs[pk.hh][addr]=r;
+ }
+
+ if (table.uk && table.uk.length) {
+ table.uk.forEach(function (uk) {
+ var ukaddr = uk.onrightfn(r);
+ if (typeof table.uniqs[uk.hh][ukaddr] !== 'undefined') {
+ if (orreplace) toreplace = table.uniqs[uk.hh][ukaddr];
+ else throw new Error('Cannot insert record, because it already exists in unique index');
+ }
+ // table.uniqs[uk.hh][ukaddr]=r;
+ });
+ }
+
+ if (toreplace) {
+ // Do UPDATE!!!
+
+ table.update(
+ function (t) {
+ for (var f in r) t[f] = r[f];
+ },
+ table.data.indexOf(toreplace),
+ params
+ );
+ } else {
+ table.data.push(r);
+
+ // Final change before insert
+
+ // Update indices
+
+ for (var columnid in table.identities) {
+ var ident = table.identities[columnid];
+
+ ident.value += ident.step;
+
+ }
+
+ if (table.pk) {
+ var pk = table.pk;
+ var addr = pk.onrightfn(r);
+ table.uniqs[pk.hh][addr] = r;
+ }
+ if (table.uk && table.uk.length) {
+ table.uk.forEach(function (uk) {
+ var ukaddr = uk.onrightfn(r);
+ table.uniqs[uk.hh][ukaddr] = r;
+ });
+ }
+ }
+
+ // Trigger prevent functionality
+ for (var tr in table.afterinsert) {
+ var trigger = table.afterinsert[tr];
+ if (trigger) {
+ if (trigger.funcid) {
+ alasql.fn[trigger.funcid](r);
+ } else if (trigger.statement) {
+ trigger.statement.execute(databaseid);
+ }
+ }
+ }
+ alasql.inserted = oldinserted;
+ };
+
+ table["delete"] = function (index) {
+ var table = this;
+ var r = table.data[index];
+
+ // Prevent trigger
+ var prevent = false;
+ for (var tr in table.beforedelete) {
+ var trigger = table.beforedelete[tr];
+ if (trigger) {
+ if (trigger.funcid) {
+ if (alasql.fn[trigger.funcid](r) === false) prevent = prevent || true;
+ } else if (trigger.statement) {
+ if (trigger.statement.execute(databaseid) === false) prevent = prevent || true;
+ }
+ }
+ }
+ if (prevent) return false;
+
+ // Trigger prevent functionality
+ var escape = false;
+ for (var tr in table.insteadofdelete) {
+ escape = true;
+ var trigger = table.insteadofdelete[tr];
+ if (trigger) {
+ if (trigger.funcid) {
+ alasql.fn[trigger.funcid](r);
+ } else if (trigger.statement) {
+ trigger.statement.execute(databaseid);
+ }
+ }
+ }
+ if (escape) return;
+
+ if (this.pk) {
+ var pk = this.pk;
+ var addr = pk.onrightfn(r);
+ if (typeof this.uniqs[pk.hh][addr] === 'undefined') {
+ throw new Error('Something wrong with primary key index on table');
+ } else {
+ this.uniqs[pk.hh][addr] = undefined;
+ }
+ }
+ if (table.uk && table.uk.length) {
+ table.uk.forEach(function (uk) {
+ var ukaddr = uk.onrightfn(r);
+ if (typeof table.uniqs[uk.hh][ukaddr] === 'undefined') {
+ throw new Error('Something wrong with unique index on table');
+ }
+ table.uniqs[uk.hh][ukaddr] = undefined;
+ });
+ }
+ };
+
+ table.deleteall = function () {
+ this.data.length = 0;
+ if (this.pk) {
+ // var r = this.data[i];
+ this.uniqs[this.pk.hh] = {};
+ }
+ if (table.uk && table.uk.length) {
+ table.uk.forEach(function (uk) {
+ table.uniqs[uk.hh] = {};
+ });
+ }
+ };
+
+ table.update = function (assignfn, i, params) {
+ // TODO: Analyze the speed
+ var r = cloneDeep(this.data[i]);
+
+ var pk;
+ // PART 1 - PRECHECK
+ if (this.pk) {
+ pk = this.pk;
+ pk.pkaddr = pk.onrightfn(r, params);
+ if (typeof this.uniqs[pk.hh][pk.pkaddr] === 'undefined') {
+ throw new Error('Something wrong with index on table');
+ }
+ }
+ if (table.uk && table.uk.length) {
+ table.uk.forEach(function (uk) {
+ uk.ukaddr = uk.onrightfn(r);
+ if (typeof table.uniqs[uk.hh][uk.ukaddr] === 'undefined') {
+ throw new Error('Something wrong with unique index on table');
+ }
+ });
+ }
+
+ assignfn(r, params, alasql);
+
+ // Prevent trigger
+ var prevent = false;
+ for (var tr in table.beforeupdate) {
+ var trigger = table.beforeupdate[tr];
+ if (trigger) {
+ if (trigger.funcid) {
+ if (alasql.fn[trigger.funcid](this.data[i], r) === false) prevent = prevent || true;
+ } else if (trigger.statement) {
+ if (trigger.statement.execute(databaseid) === false) prevent = prevent || true;
+ }
+ }
+ }
+ if (prevent) return false;
+
+ // Trigger prevent functionality
+ var escape = false;
+ for (var tr in table.insteadofupdate) {
+ escape = true;
+ var trigger = table.insteadofupdate[tr];
+ if (trigger) {
+ if (trigger.funcid) {
+ alasql.fn[trigger.funcid](this.data[i], r);
+ } else if (trigger.statement) {
+ trigger.statement.execute(databaseid);
+ }
+ }
+ }
+ if (escape) return;
+
+ // PART 2 - POST CHECK
+ if (table.checks && table.checks.length > 0) {
+ table.checks.forEach(function (check) {
+ if (!check.fn(r)) {
+ throw new Error('Violation of CHECK constraint ' + (check.id || ''));
+ }
+ });
+ }
+
+ table.columns.forEach(function (column) {
+ if (column.notnull && typeof r[column.columnid] === 'undefined') {
+ throw new Error('Wrong NULL value in NOT NULL column ' + column.columnid);
+ }
+ });
+ if (this.pk) {
+ pk.newpkaddr = pk.onrightfn(r);
+ if (typeof this.uniqs[pk.hh][pk.newpkaddr] !== 'undefined' && pk.newpkaddr !== pk.pkaddr) {
+ throw new Error('Record already exists');
+ }
+ }
+
+ if (table.uk && table.uk.length) {
+ table.uk.forEach(function (uk) {
+ uk.newukaddr = uk.onrightfn(r);
+ if (typeof table.uniqs[uk.hh][uk.newukaddr] !== 'undefined' && uk.newukaddr !== uk.ukaddr) {
+ throw new Error('Record already exists');
+ }
+ });
+ }
+
+ // PART 3 UPDATE
+ if (this.pk) {
+ this.uniqs[pk.hh][pk.pkaddr] = undefined;
+ this.uniqs[pk.hh][pk.newpkaddr] = r;
+ }
+ if (table.uk && table.uk.length) {
+ table.uk.forEach(function (uk) {
+ table.uniqs[uk.hh][uk.ukaddr] = undefined;
+ table.uniqs[uk.hh][uk.newukaddr] = r;
+ });
+ }
+
+ this.data[i] = r;
+
+ // Trigger prevent functionality
+ for (var tr in table.afterupdate) {
+ var trigger = table.afterupdate[tr];
+ if (trigger) {
+ if (trigger.funcid) {
+ alasql.fn[trigger.funcid](this.data[i], r);
+ } else if (trigger.statement) {
+ trigger.statement.execute(databaseid);
+ }
+ }
+ }
+ };
+
+ var res;
+
+ if (!alasql.options.nocount) {
+ res = 1;
+ }
+
+ if (cb) res = cb(res);
+ return res;
+};
+
+//
+// Date functions
+//
+// (c) 2014, Andrey Gershun
+//
+
+/** Standard JavaScript data types */
+
+alasql.fn.Date = Object;
+alasql.fn.Date = Date;
+alasql.fn.Number = Number;
+alasql.fn.String = String;
+alasql.fn.Boolean = Boolean;
+
+/** Extend Object with properties */
+stdfn.EXTEND = alasql.utils.extend;
+
+stdfn.CHAR = String.fromCharCode.bind(String);
+stdfn.ASCII = function(a) {
+ return a.charCodeAt(0);
+};
+
+/**
+ Return first non-null argument
+ See https://msdn.microsoft.com/en-us/library/ms190349.aspx
+*/
+stdfn.COALESCE = function() {
+ for (var i = 0; i < arguments.length; i++) {
+ if (typeof arguments[i] == 'undefined') continue;
+ if (typeof arguments[i] == 'number' && isNaN(arguments[i])) continue;
+ return arguments[i];
+ }
+ return undefined;
+};
+
+stdfn.USER = function() {
+ return 'alasql';
+};
+
+stdfn.OBJECT_ID = function(objid) {
+ return !!alasql.tables[objid];
+};
+
+stdfn.DATE = function(d) {
+ if (/\d{8}/.test(d)) return new Date(+d.substr(0, 4), +d.substr(4, 2) - 1, +d.substr(6, 2));
+ return new Date(d);
+};
+
+stdfn.NOW = function() {
+ var d = new Date();
+ var s =
+ d.getFullYear() +
+ '.' +
+ ('0' + (d.getMonth() + 1)).substr(-2) +
+ '.' +
+ ('0' + d.getDate()).substr(-2);
+ s +=
+ ' ' +
+ ('0' + d.getHours()).substr(-2) +
+ ':' +
+ ('0' + d.getMinutes()).substr(-2) +
+ ':' +
+ ('0' + d.getSeconds()).substr(-2);
+ s += '.' + ('00' + d.getMilliseconds()).substr(-3);
+ return s;
+};
+
+stdfn.GETDATE = stdfn.NOW;
+stdfn.CURRENT_TIMESTAMP = stdfn.NOW;
+
+stdfn.SECOND = function(d) {
+ var d = new Date(d);
+ return d.getSeconds();
+};
+
+stdfn.MINUTE = function(d) {
+ var d = new Date(d);
+ return d.getMinutes();
+};
+
+stdfn.HOUR = function(d) {
+ var d = new Date(d);
+ return d.getHours();
+};
+
+stdfn.DAYOFWEEK = stdfn.WEEKDAY = function(d) {
+ var d = new Date(d);
+ return d.getDay();
+};
+
+stdfn.DAY = stdfn.DAYOFMONTH = function(d) {
+ var d = new Date(d);
+ return d.getDate();
+};
+
+stdfn.MONTH = function(d) {
+ var d = new Date(d);
+ return d.getMonth() + 1;
+};
+
+stdfn.YEAR = function(d) {
+ var d = new Date(d);
+ return d.getFullYear();
+};
+
+var PERIODS = {
+ year: 1000 * 3600 * 24 * 365,
+ quarter: (1000 * 3600 * 24 * 365) / 4,
+ month: 1000 * 3600 * 24 * 30,
+ week: 1000 * 3600 * 24 * 7,
+ day: 1000 * 3600 * 24,
+ dayofyear: 1000 * 3600 * 24,
+ weekday: 1000 * 3600 * 24,
+ hour: 1000 * 3600,
+ minute: 1000 * 60,
+ second: 1000,
+ millisecond: 1,
+ microsecond: 0.001,
+};
+
+alasql.stdfn.DATEDIFF = function(period, d1, d2) {
+ var interval = new Date(d2).getTime() - new Date(d1).getTime();
+ return interval / PERIODS[period.toLowerCase()];
+};
+
+alasql.stdfn.DATEADD = function(period, interval, d) {
+ var nd = new Date(d).getTime() + interval * PERIODS[period.toLowerCase()];
+ return new Date(nd);
+};
+
+alasql.stdfn.INTERVAL = function(interval, period) {
+ return interval * PERIODS[period.toLowerCase()];
+};
+
+alasql.stdfn.DATE_ADD = alasql.stdfn.ADDDATE = function(d, interval) {
+ var nd = new Date(d).getTime() + interval;
+ return new Date(nd);
+};
+
+alasql.stdfn.DATE_SUB = alasql.stdfn.SUBDATE = function(d, interval) {
+ var nd = new Date(d).getTime() - interval;
+ return new Date(nd);
+};
+
+/*
+//
+// DROP TABLE for Alasql.js
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+yy.DropTable = function(params) {
+ return yy.extend(this, params);
+};
+yy.DropTable.prototype.toString = function() {
+ var s = 'DROP' + ' ';
+ if (this.view) s += 'VIEW';
+ else s += 'TABLE';
+ if (this.ifexists) s += ' IF EXISTS';
+ s += ' ' + this.tables.toString();
+ return s;
+};
+
+// DROP TABLE
+/**
+ Drop tables
+ @param {string} databaseid Database id
+ @param {object} params Parameters
+ @param {callback} cb Callback function
+ @return Number of dropped tables
+ @example
+ DROP TABLE one;
+ DROP TABLE IF NOT EXISTS two, three;
+*/
+yy.DropTable.prototype.execute = function(databaseid, params, cb) {
+ var ifexists = this.ifexists;
+ var res = 0; // No tables removed
+ var count = 0;
+ var tlen = this.tables.length;
+
+ // For each table in the list
+ this.tables.forEach(function(table) {
+ var db = alasql.databases[table.databaseid || databaseid];
+ var tableid = table.tableid;
+
+ /** @todo Test with AUTOCOMMIT flag is ON */
+ /** @todo Test with IndexedDB and multiple tables */
+
+ if (!ifexists || (ifexists && db.tables[tableid])) {
+ if (!db.tables[tableid]) {
+ if (!alasql.options.dropifnotexists) {
+ throw new Error(
+ "Can not drop table '" +
+ table.tableid +
+ "', because it does not exist in the database."
+ );
+ }
+ } else {
+ if (db.engineid /*&& alasql.options.autocommit*/) {
+ alasql.engines[db.engineid].dropTable(
+ table.databaseid || databaseid,
+ tableid,
+ ifexists,
+ function(res1) {
+ delete db.tables[tableid];
+ res += res1;
+ count++;
+ if (count == tlen && cb) cb(res);
+ }
+ );
+ } else {
+ delete db.tables[tableid];
+ res++;
+ count++;
+ if (count == tlen && cb) cb(res);
+ }
+ }
+ } else {
+ count++;
+ if (count == tlen && cb) cb(res);
+ }
+ });
+ // if(cb) res = cb(res);
+ return res;
+};
+
+yy.TruncateTable = function(params) {
+ return yy.extend(this, params);
+};
+yy.TruncateTable.prototype.toString = function() {
+ var s = 'TRUNCATE TABLE';
+ s += ' ' + this.table.toString();
+ return s;
+};
+
+yy.TruncateTable.prototype.execute = function(databaseid, params, cb) {
+ var db = alasql.databases[this.table.databaseid || databaseid];
+ var tableid = this.table.tableid;
+ if (db.engineid) {
+ return alasql.engines[db.engineid].truncateTable(
+ this.table.databaseid || databaseid,
+ tableid,
+ this.ifexists,
+ cb
+ );
+ }
+ if (db.tables[tableid]) {
+ db.tables[tableid].data = [];
+ } else {
+ throw new Error('Cannot truncate table becaues it does not exist');
+ }
+ return cb ? cb(0) : 0;
+};
+
+/*
+//
+// CREATE VERTEX for AlaSQL
+// Date: 21.04.2015
+// (c) 2015, Andrey Gershun
+//
+*/
+
+yy.CreateVertex = function(params) {
+ return yy.extend(this, params);
+};
+yy.CreateVertex.prototype.toString = function() {
+ var s = 'CREATE VERTEX ';
+ if (this["class"]) {
+ s += this["class"] + ' ';
+ }
+ if (this.sharp) {
+ s += '#' + this.sharp + ' ';
+ }
+ if (this.sets) {
+ s += this.sets.toString();
+ } else if (this.content) {
+ s += this.content.toString();
+ } else if (this.select) {
+ s += this.select.toString();
+ }
+
+ return s;
+};
+
+yy.CreateVertex.prototype.toJS = function(context) {
+
+ var s = 'this.queriesfn[' + (this.queriesidx - 1) + '](this.params,null,' + context + ')';
+ // var s = '';
+ return s;
+};
+
+// CREATE TABLE
+
+yy.CreateVertex.prototype.compile = function(databaseid) {
+ var dbid = databaseid;
+
+ // CREATE VERTEX #id
+ var sharp = this.sharp;
+
+ // CREATE VERTEX "Name"
+ if (typeof this.name !== 'undefined') {
+ var s = 'x.name=' + this.name.toJS();
+ var namefn = new Function('x', s);
+ }
+
+ if (this.sets && this.sets.length > 0) {
+ var s = this.sets
+ .map(function(st) {
+ return "x['" + st.column.columnid + "']=" + st.expression.toJS('x', '');
+ })
+ .join(';');
+ var setfn = new Function('x,params,alasql', s);
+ }
+
+ // Todo: check for content, select and default
+
+ var statement = function(params, cb) {
+ var res;
+
+ // CREATE VERTEX without parameters
+ var db = alasql.databases[dbid];
+ var id;
+ if (typeof sharp !== 'undefined') {
+ id = sharp;
+ } else {
+ id = db.counter++;
+ }
+ var vertex = {$id: id, $node: 'VERTEX'};
+ db.objects[vertex.$id] = vertex;
+ res = vertex;
+ if (namefn) {
+ namefn(vertex);
+ }
+ if (setfn) {
+ setfn(vertex, params, alasql);
+ }
+
+ if (cb) {
+ res = cb(res);
+ }
+ return res;
+ };
+ return statement;
+};
+
+yy.CreateEdge = function(params) {
+ return yy.extend(this, params);
+};
+yy.CreateEdge.prototype.toString = function() {
+
+ var s = 'CREATE EDGE' + ' ';
+ if (this["class"]) {
+ s += this["class"] + ' ';
+ }
+ // todo: SET
+ // todo: CONTENT
+ // todo: SELECT
+ return s;
+};
+
+yy.CreateEdge.prototype.toJS = function(context) {
+ var s = 'this.queriesfn[' + (this.queriesidx - 1) + '](this.params,null,' + context + ')';
+ return s;
+};
+
+// CREATE TABLE
+
+yy.CreateEdge.prototype.compile = function(databaseid) {
+ var dbid = databaseid;
+ var fromfn = new Function('params,alasql', 'var y;return ' + this.from.toJS());
+ var tofn = new Function('params,alasql', 'var y;return ' + this.to.toJS());
+
+ // CREATE VERTEX "Name"
+ if (typeof this.name !== 'undefined') {
+ var s = 'x.name=' + this.name.toJS();
+ var namefn = new Function('x', s);
+ }
+
+ if (this.sets && this.sets.length > 0) {
+ var s = this.sets
+ .map(function(st) {
+ return "x['" + st.column.columnid + "']=" + st.expression.toJS('x', '');
+ })
+ .join(';');
+ var setfn = new Function('x,params,alasql', 'var y;' + s);
+ }
+
+ /*
+ todo: handle content, select and default
+ else if(this.content) {
+
+ } else if(this.select) {
+
+ } else {
+ }
+ */
+
+ var statement = function(params, cb) {
+ var res = 0;
+ // CREATE VERTEX without parameters
+ var db = alasql.databases[dbid];
+ var edge = {$id: db.counter++, $node: 'EDGE'};
+ var v1 = fromfn(params, alasql);
+ var v2 = tofn(params, alasql);
+ // Set link
+ edge.$in = [v1.$id];
+ edge.$out = [v2.$id];
+ // Set sides
+ if (v1.$out === undefined) {
+ v1.$out = [];
+ }
+ v1.$out.push(edge.$id);
+
+ if (typeof v2.$in === undefined) {
+ v2.$in = [];
+ }
+ v2.$in.push(edge.$id);
+
+ // Save in objects
+ db.objects[edge.$id] = edge;
+ res = edge;
+ if (namefn) {
+ namefn(edge);
+ }
+
+ if (setfn) {
+ setfn(edge, params, alasql);
+ }
+
+ if (cb) {
+ res = cb(res);
+ }
+
+ return res;
+ };
+ return statement;
+};
+
+yy.CreateGraph = function(params) {
+ return yy.extend(this, params);
+};
+yy.CreateGraph.prototype.toString = function() {
+ var s = 'CREATE GRAPH' + ' ';
+ if (this["class"]) {
+ s += this["class"] + ' ';
+ }
+ return s;
+};
+
+yy.CreateGraph.prototype.execute = function(databaseid, params, cb) {
+ var res = [];
+ if (this.from) {
+ if (alasql.from[this.from.funcid]) {
+ this.graph = alasql.from[this.from.funcid.toUpperCase()];
+ }
+ }
+
+ // stop;
+ this.graph.forEach(function(g) {
+ if (g.source) {
+ // GREATE EDGE
+ var e = {};
+ if (typeof g.as !== 'undefined') {
+ alasql.vars[g.as] = e;
+ }
+
+ if (typeof g.prop !== 'undefined') {
+ // e[g.prop] = e;
+ // v.$id = g.prop; // We do not create $id for edge automatically
+ e.name = g.prop;
+ }
+ if (typeof g.sharp !== 'undefined') {
+ e.$id = g.sharp;
+ }
+ if (typeof g.name !== 'undefined') {
+ e.name = g.name;
+ }
+ if (typeof g["class"] !== 'undefined') {
+ e.$class = g["class"];
+ }
+
+ var db = alasql.databases[databaseid];
+ if (typeof e.$id === 'undefined') {
+ e.$id = db.counter++;
+ }
+ e.$node = 'EDGE';
+ if (typeof g.json !== 'undefined') {
+ extend(
+ e,
+ new Function('params,alasql', 'var y;return ' + g.json.toJS())(params, alasql)
+ );
+ }
+
+ var v1;
+ if (g.source.vars) {
+ var vo = alasql.vars[g.source.vars];
+ if (typeof vo === 'object') {
+ v1 = vo;
+ } else {
+ v1 = db.objects[vo];
+ }
+ } else {
+ var av1 = g.source.sharp;
+ if (typeof av1 === 'undefined') {
+ av1 = g.source.prop;
+ }
+ v1 = alasql.databases[databaseid].objects[av1];
+ if (
+ typeof v1 === 'undefined' &&
+ alasql.options.autovertex &&
+ (typeof g.source.prop !== 'undefined' || typeof g.source.name !== 'undefined')
+ ) {
+ v1 = findVertex(g.source.prop || g.source.name);
+ if (typeof v1 === 'undefined') {
+ v1 = createVertex(g.source);
+ }
+ }
+ }
+
+ var v2;
+ if (g.source.vars) {
+ var vo = alasql.vars[g.target.vars];
+ if (typeof vo === 'object') {
+ v2 = vo;
+ } else {
+ v2 = db.objects[vo];
+ }
+ } else {
+ var av2 = g.target.sharp;
+ if (typeof av2 === 'undefined') {
+ av2 = g.target.prop;
+ }
+ v2 = alasql.databases[databaseid].objects[av2];
+ if (
+ typeof v2 === 'undefined' &&
+ alasql.options.autovertex &&
+ (typeof g.target.prop !== 'undefined' || typeof g.target.name !== 'undefined')
+ ) {
+ v2 = findVertex(g.target.prop || g.target.name);
+ if (typeof v2 === 'undefined') {
+ v2 = createVertex(g.target);
+ }
+ }
+ }
+
+ // Set link
+ e.$in = [v1.$id];
+ e.$out = [v2.$id];
+ // Set sides
+ if (typeof v1.$out === 'undefined') {
+ v1.$out = [];
+ }
+ v1.$out.push(e.$id);
+ if (typeof v2.$in === 'undefined') {
+ v2.$in = [];
+ }
+ v2.$in.push(e.$id);
+
+ db.objects[e.$id] = e;
+ if (typeof e.$class !== 'undefined') {
+ if (typeof alasql.databases[databaseid].tables[e.$class] === 'undefined') {
+ throw new Error('No such class. Pleace use CREATE CLASS');
+ } else {
+ // TODO - add insert()
+ alasql.databases[databaseid].tables[e.$class].data.push(e);
+ }
+ }
+
+ res.push(e.$id);
+ } else {
+ createVertex(g);
+ }
+ });
+
+ if (cb) {
+ res = cb(res);
+ }
+ return res;
+
+ // Find vertex by name
+ function findVertex(name) {
+ var objects = alasql.databases[alasql.useid].objects;
+ for (var k in objects) {
+ if (objects[k].name === name) {
+ return objects[k];
+ }
+ }
+ return undefined;
+ }
+
+ function createVertex(g) {
+ // GREATE VERTEX
+ var v = {};
+ if (typeof g.as !== 'undefined') {
+ alasql.vars[g.as] = v;
+ }
+
+ if (typeof g.prop !== 'undefined') {
+ // v[g.prop] = true;
+ v.$id = g.prop;
+ v.name = g.prop;
+ }
+
+ if (typeof g.sharp !== 'undefined') {
+ v.$id = g.sharp;
+ }
+ if (typeof g.name !== 'undefined') {
+ v.name = g.name;
+ }
+ if (typeof g["class"] !== 'undefined') {
+ v.$class = g["class"];
+ }
+
+ var db = alasql.databases[databaseid];
+ if (typeof v.$id === 'undefined') {
+ v.$id = db.counter++;
+ }
+ v.$node = 'VERTEX';
+ if (typeof g.json !== 'undefined') {
+ extend(
+ v,
+ new Function('params,alasql', 'var y;return ' + g.json.toJS())(params, alasql)
+ );
+ }
+ db.objects[v.$id] = v;
+ if (typeof v.$class !== 'undefined') {
+ if (typeof alasql.databases[databaseid].tables[v.$class] === 'undefined') {
+ throw new Error('No such class. Pleace use CREATE CLASS');
+ } else {
+ // TODO - add insert()
+ alasql.databases[databaseid].tables[v.$class].data.push(v);
+ }
+ }
+
+ res.push(v.$id);
+ return v;
+ }
+};
+
+yy.CreateGraph.prototype.compile1 = function(databaseid) {
+ var dbid = databaseid;
+ var fromfn = new Function('params,alasql', 'var y;return ' + this.from.toJS());
+ var tofn = new Function('params,alasql', 'var y;return ' + this.to.toJS());
+
+ // CREATE VERTEX "Name"
+ if (typeof this.name !== 'undefined') {
+ var s = 'x.name=' + this.name.toJS();
+ var namefn = new Function('x', s);
+ }
+
+ if (this.sets && this.sets.length > 0) {
+ var s = this.sets
+ .map(function(st) {
+ return "x['" + st.column.columnid + "']=" + st.expression.toJS('x', '');
+ })
+ .join(';');
+ var setfn = new Function('x,params,alasql', 'var y;' + s);
+ }
+
+ // Todo: handle content, select and default
+
+ var statement = function(params, cb) {
+ var res = 0;
+ // CREATE VERTEX without parameters
+ var db = alasql.databases[dbid];
+ var edge = {$id: db.counter++, $node: 'EDGE'};
+ var v1 = fromfn(params, alasql);
+ var v2 = tofn(params, alasql);
+ // Set link
+ edge.$in = [v1.$id];
+ edge.$out = [v2.$id];
+ // Set sides
+ if (typeof v1.$out === 'undefined') {
+ v1.$out = [];
+ }
+ v1.$out.push(edge.$id);
+
+ if (typeof v2.$in === 'undefined') {
+ v2.$in = [];
+ }
+ v2.$in.push(edge.$id);
+ // Save in objects
+ db.objects[edge.$id] = edge;
+ res = edge;
+ if (namefn) {
+ namefn(edge);
+ }
+ if (setfn) {
+ setfn(edge, params, alasql);
+ }
+
+ if (cb) {
+ res = cb(res);
+ }
+ return res;
+ };
+ return statement;
+};
+
+/*
+//
+// ALTER TABLE for Alasql.js
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+/* global alasql yy */
+
+// ALTER TABLE table1 RENAME TO table2
+yy.AlterTable = function (params) {
+ return yy.extend(this, params);
+};
+yy.AlterTable.prototype.toString = function () {
+ var s = 'ALTER TABLE ' + this.table.toString();
+ if (this.renameto) s += ' RENAME TO ' + this.renameto;
+ return s;
+};
+
+yy.AlterTable.prototype.execute = function (databaseid, params, cb) {
+ var db = alasql.databases[databaseid];
+ db.dbversion = Date.now();
+
+ if (this.renameto) {
+ var oldtableid = this.table.tableid;
+ var newtableid = this.renameto;
+ var res = 1;
+ if (db.tables[newtableid]) {
+ throw new Error(
+ "Can not rename a table '" +
+ oldtableid +
+ "' to '" +
+ newtableid +
+ "', because the table with this name already exists"
+ );
+ } else if (newtableid === oldtableid) {
+ throw new Error("Can not rename a table '" + oldtableid + "' to itself");
+ } else {
+ db.tables[newtableid] = db.tables[oldtableid];
+ delete db.tables[oldtableid];
+ res = 1;
+ }
+ if (cb) cb(res);
+ return res;
+ } else if (this.addcolumn) {
+ db = alasql.databases[this.table.databaseid || databaseid];
+ db.dbversion++;
+ var tableid = this.table.tableid;
+ var table = db.tables[tableid];
+ var columnid = this.addcolumn.columnid;
+ if (table.xcolumns[columnid]) {
+ throw new Error(
+ 'Cannot add column "' +
+ columnid +
+ '", because it already exists in the table "' +
+ tableid +
+ '"'
+ );
+ }
+
+ var col = {
+ columnid: columnid,
+ dbtypeid: this.addcolumn.dbtypeid,
+ dbsize: this.dbsize,
+ dbprecision: this.dbprecision,
+ dbenum: this.dbenum,
+ defaultfns: null, // TODO defaultfns!!!
+ };
+
+ var defaultfn = function () {};
+
+ table.columns.push(col);
+ table.xcolumns[columnid] = col;
+
+ for (var i = 0, ilen = table.data.length; i < ilen; i++) {
+
+ table.data[i][columnid] = defaultfn();
+ }
+
+ // TODO
+ return cb ? cb(1) : 1;
+ } else if (this.modifycolumn) {
+ var db = alasql.databases[this.table.databaseid || databaseid];
+ db.dbversion++;
+ var tableid = this.table.tableid;
+ var table = db.tables[tableid];
+ var columnid = this.modifycolumn.columnid;
+
+ if (!table.xcolumns[columnid]) {
+ throw new Error(
+ 'Cannot modify column "' +
+ columnid +
+ '", because it was not found in the table "' +
+ tableid +
+ '"'
+ );
+ }
+
+ col = table.xcolumns[columnid];
+ col.dbtypeid = this.dbtypeid;
+ col.dbsize = this.dbsize;
+ col.dbprecision = this.dbprecision;
+ col.dbenum = this.dbenum;
+
+ // TODO
+ return cb ? cb(1) : 1;
+ } else if (this.renamecolumn) {
+ var db = alasql.databases[this.table.databaseid || databaseid];
+ db.dbversion++;
+
+ var tableid = this.table.tableid;
+ var table = db.tables[tableid];
+ var columnid = this.renamecolumn;
+ var tocolumnid = this.to;
+
+ var col;
+ if (!table.xcolumns[columnid]) {
+ throw new Error('Column "' + columnid + '" is not found in the table "' + tableid + '"');
+ }
+ if (table.xcolumns[tocolumnid]) {
+ throw new Error('Column "' + tocolumnid + '" already exists in the table "' + tableid + '"');
+ }
+
+ if (columnid != tocolumnid) {
+ for (var j = 0; j < table.columns.length; j++) {
+ if (table.columns[j].columnid == columnid) {
+ table.columns[j].columnid = tocolumnid;
+ }
+ }
+
+ table.xcolumns[tocolumnid] = table.xcolumns[columnid];
+ delete table.xcolumns[columnid];
+
+ for (var i = 0, ilen = table.data.length; i < ilen; i++) {
+
+ table.data[i][tocolumnid] = table.data[i][columnid];
+ delete table.data[i][columnid];
+ }
+ return table.data.length;
+ } else {
+ return cb ? cb(0) : 0;
+ }
+ } else if (this.dropcolumn) {
+ var db = alasql.databases[this.table.databaseid || databaseid];
+ db.dbversion++;
+ var tableid = this.table.tableid;
+ var table = db.tables[tableid];
+ var columnid = this.dropcolumn;
+
+ var found = false;
+ for (var j = 0; j < table.columns.length; j++) {
+ if (table.columns[j].columnid == columnid) {
+ found = true;
+ table.columns.splice(j, 1);
+ break;
+ }
+ }
+
+ if (!found) {
+ throw new Error(
+ 'Cannot drop column "' +
+ columnid +
+ '", because it was not found in the table "' +
+ tableid +
+ '"'
+ );
+ }
+
+ delete table.xcolumns[columnid];
+
+ for (i = 0, ilen = table.data.length; i < ilen; i++) {
+ delete table.data[i][columnid];
+ }
+ return cb ? cb(table.data.length) : table.data.length;
+ } else {
+ throw Error('Unknown ALTER TABLE method');
+ }
+};
+
+/*
+//
+// CREATE TABLE for Alasql.js
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+yy.CreateIndex = function(params) {
+ return yy.extend(this, params);
+};
+yy.CreateIndex.prototype.toString = function() {
+ var s = 'CREATE';
+ if (this.unique) s += ' UNIQUE';
+ s += ' INDEX ' + this.indexid + ' ON ' + this.table.toString();
+ s += '(' + this.columns.toString() + ')';
+ return s;
+};
+
+// CREATE TABLE
+yy.CreateIndex.prototype.execute = function(databaseid, params, cb) {
+ // var self = this;
+ var db = alasql.databases[databaseid];
+ var tableid = this.table.tableid;
+ var table = db.tables[tableid];
+ var indexid = this.indexid;
+ db.indices[indexid] = tableid;
+
+ var rightfns = this.columns
+ .map(function(expr) {
+ return expr.expression.toJS('r', '');
+ })
+ .join("+'`'+");
+
+ var rightfn = new Function('r,params,alasql', 'return ' + rightfns);
+
+ if (this.unique) {
+ table.uniqdefs[indexid] = {
+ rightfns: rightfns,
+ };
+ var ux = (table.uniqs[indexid] = {});
+ if (table.data.length > 0) {
+ for (var i = 0, ilen = table.data.length; i < ilen; i++) {
+ var addr = rightfns(table.data[i]);
+ if (!ux[addr]) {
+ ux[addr] = {num: 0};
+ }
+ ux[addr].num++;
+ }
+ }
+ } else {
+ var hh = hash(rightfns);
+ table.inddefs[indexid] = {rightfns: rightfns, hh: hh};
+ table.indices[hh] = {};
+
+ var ix = (table.indices[hh] = {});
+ if (table.data.length > 0) {
+ for (var i = 0, ilen = table.data.length; i < ilen; i++) {
+ var addr = rightfn(table.data[i], params, alasql);
+ if (!ix[addr]) {
+ ix[addr] = [];
+ }
+ ix[addr].push(table.data[i]);
+ }
+ }
+ }
+ var res = 1;
+ if (cb) res = cb(res);
+ return res;
+};
+
+yy.Reindex = function(params) {
+ return yy.extend(this, params);
+};
+yy.Reindex.prototype.toString = function() {
+ var s = 'REINDEX ' + this.indexid;
+ return s;
+};
+
+// CREATE TABLE
+yy.Reindex.prototype.execute = function(databaseid, params, cb) {
+ // var self = this;
+ var db = alasql.databases[databaseid];
+ var indexid = this.indexid;
+
+ var tableid = db.indices[indexid];
+ var table = db.tables[tableid];
+ table.indexColumns();
+ var res = 1;
+ if (cb) res = cb(res);
+ return res;
+};
+
+/*
+//
+// DROP TABLE for Alasql.js
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+yy.DropIndex = function(params) {
+ return yy.extend(this, params);
+};
+yy.DropIndex.prototype.toString = function() {
+ return 'DROP INDEX' + this.indexid;
+};
+
+// DROP TABLE
+yy.DropIndex.prototype.compile = function(db) {
+ var indexid = this.indexid;
+ return function() {
+ return 1;
+ };
+};
+
+/*
+//
+// WITH SELECT for Alasql.js
+// Date: 11.01.2015
+// (c) 2015, Andrey Gershun
+//
+*/
+
+yy.WithSelect = function(params) {
+ return yy.extend(this, params);
+};
+yy.WithSelect.prototype.toString = function() {
+ var s = 'WITH ';
+ s +=
+ this.withs
+ .map(function(w) {
+ return w.name + ' AS (' + w.select.toString() + ')';
+ })
+ .join(',') + ' ';
+ s += this.select.toString();
+ return s;
+};
+
+yy.WithSelect.prototype.execute = function(databaseid, params, cb) {
+ var self = this;
+ // Create temporary tables
+ var savedTables = [];
+ self.withs.forEach(function(w) {
+ savedTables.push(alasql.databases[databaseid].tables[w.name]);
+ var tb = (alasql.databases[databaseid].tables[w.name] = new Table({tableid: w.name}));
+ tb.data = w.select.execute(databaseid, params);
+ });
+
+ var res = 1;
+ res = this.select.execute(databaseid, params, function(data) {
+ // Clear temporary tables
+ // setTimeout(function(){
+ self.withs.forEach(function(w, idx) {
+ if (savedTables[idx]) alasql.databases[databaseid].tables[w.name] = savedTables[idx];
+ else delete alasql.databases[databaseid].tables[w.name];
+ });
+ // },0);
+
+ if (cb) data = cb(data);
+ return data;
+ });
+ return res;
+};
+
+/*
+//
+// IF for Alasql.js
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+yy.If = function(params) {
+ return yy.extend(this, params);
+};
+yy.If.prototype.toString = function() {
+ var s = 'IF' + ' ';
+ s += this.expression.toString();
+ s += ' ' + this.thenstat.toString();
+ if (this.elsestat) s += ' ELSE ' + this.thenstat.toString();
+ return s;
+};
+
+// CREATE TABLE
+
+yy.If.prototype.execute = function(databaseid, params, cb) {
+ var res;
+
+ var fn = new Function(
+ 'params,alasql,p',
+ 'var y;return ' + this.expression.toJS('({})', '', null)
+ ).bind(this);
+
+ if (fn(params, alasql)) res = this.thenstat.execute(databaseid, params, cb);
+ else {
+ if (this.elsestat) res = this.elsestat.execute(databaseid, params, cb);
+ else {
+ if (cb) res = cb(res);
+ }
+ }
+ // else res = this.elsestat.execute(databaseid,params,cb,scope);
+ return res;
+};
+
+/*
+//
+// CREATE VIEW for Alasql.js
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+yy.While = function(params) {
+ return yy.extend(this, params);
+};
+yy.While.prototype.toString = function() {
+ var s = 'WHILE ';
+ s += this.expression.toString();
+ s += ' ' + this.loopstat.toString();
+ return s;
+};
+
+yy.While.prototype.execute = function(databaseid, params, cb) {
+ var self = this;
+ var res = [];
+
+ var fn = new Function('params,alasql,p', 'var y;return ' + this.expression.toJS());
+
+ if (cb) {
+ var first = false;
+ var loop = function(data) {
+ if (first) {
+ res.push(data);
+ } else {
+ first = true;
+ }
+ setTimeout(function() {
+ if (fn(params, alasql)) {
+ self.loopstat.execute(databaseid, params, loop);
+ } else {
+ res = cb(res);
+ }
+ }, 0);
+ };
+ loop();
+ } else {
+ while (fn(params, alasql)) {
+ var res1 = self.loopstat.execute(databaseid, params);
+ res.push(res1);
+ }
+ }
+ return res;
+};
+
+yy.Break = function(params) {
+ return yy.extend(this, params);
+};
+yy.Break.prototype.toString = function() {
+ var s = 'BREAK';
+ return s;
+};
+
+yy.Break.prototype.execute = function(databaseid, params, cb, scope) {
+ var res = 1;
+ if (cb) res = cb(res);
+ return res;
+};
+
+yy.Continue = function(params) {
+ return yy.extend(this, params);
+};
+yy.Continue.prototype.toString = function() {
+ var s = 'CONTINUE';
+ return s;
+};
+
+yy.Continue.prototype.execute = function(databaseid, params, cb, scope) {
+ var res = 1;
+ if (cb) res = cb(res);
+ return res;
+};
+
+yy.BeginEnd = function(params) {
+ return yy.extend(this, params);
+};
+yy.BeginEnd.prototype.toString = function() {
+ var s = 'BEGIN ' + this.statements.toString() + ' END';
+ return s;
+};
+
+yy.BeginEnd.prototype.execute = function(databaseid, params, cb, scope) {
+ var self = this;
+ var res = [];
+
+ var idx = 0;
+ runone();
+ function runone() {
+ self.statements[idx].execute(databaseid, params, function(data) {
+ res.push(data);
+ idx++;
+ if (idx < self.statements.length) return runone();
+ if (cb) res = cb(res);
+ });
+ }
+ return res;
+};
+
+/*
+//
+// INSERT for Alasql.js
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+/* global yy alasql*/
+yy.Insert = function(params) {
+ return yy.extend(this, params);
+};
+yy.Insert.prototype.toString = function() {
+ var s = 'INSERT ';
+ if (this.orreplace) s += 'OR REPLACE ';
+ if (this.replaceonly) s = 'REPLACE ';
+ s += 'INTO ' + this.into.toString();
+ if (this.columns) s += '(' + this.columns.toString() + ')';
+ if (this.values) {
+ var values = this.values.map(function(value) {
+ return '(' + value.toString() + ')';
+ });
+ s += ' VALUES ' + values.join(',');
+ }
+ if (this.select) s += ' ' + this.select.toString();
+ return s;
+};
+
+yy.Insert.prototype.toJS = function(context, tableid, defcols) {
+
+ // if(this.expression.reduced) return 'true';
+ // return this.expression.toJS(context, tableid, defcols);
+
+ // var s = 'this.queriesdata['+(this.queriesidx-1)+'][0]';
+
+ var s = 'this.queriesfn[' + (this.queriesidx - 1) + '](this.params,null,' + context + ')';
+
+ return s;
+};
+
+yy.Insert.prototype.compile = function(databaseid) {
+ var self = this;
+ databaseid = self.into.databaseid || databaseid;
+ var db = alasql.databases[databaseid];
+
+ var tableid = self.into.tableid;
+ var table = db.tables[tableid];
+
+ if (!table) {
+ throw "Table '" + tableid + "' could not be found";
+ }
+
+ // Check, if this dirty flag is required
+ var s = '';
+ var sw = '';
+ var s = "db.tables['" + tableid + "'].dirty=true;";
+ var s3 = 'var a,aa=[],x;';
+
+ var s33;
+
+ // INSERT INTO table VALUES
+ if (this.values) {
+ if (this.exists) {
+ this.existsfn = this.exists.map(function(ex) {
+ var nq = ex.compile(databaseid);
+ nq.query.modifier = 'RECORDSET';
+ return nq;
+ });
+ }
+ if (this.queries) {
+ this.queriesfn = this.queries.map(function(q) {
+ var nq = q.compile(databaseid);
+ nq.query.modifier = 'RECORDSET';
+ return nq;
+ });
+ }
+
+ self.values.forEach(function(values) {
+ var ss = [];
+
+ // s += 'db.tables[\''+tableid+'\'].data.push({';
+
+ // s += '';
+ if (self.columns) {
+ self.columns.forEach(function(col, idx) {
+
+ // ss.push(col.columnid +':'+ self.values[idx].value.toString());
+
+ // if(rec[f.name.value] == "NULL") rec[f.name.value] = undefined;
+
+ // if(table.xflds[f.name.value].dbtypeid == "INT") rec[f.name.value] = +rec[f.name.value]|0;
+ // else if(table.xflds[f.name.value].dbtypeid == "FLOAT") rec[f.name.value] = +rec[f.name.value];
+ var q = "'" + col.columnid + "':";
+ if (table.xcolumns && table.xcolumns[col.columnid]) {
+ if (
+ ['INT', 'FLOAT', 'NUMBER', 'MONEY'].indexOf(
+ table.xcolumns[col.columnid].dbtypeid
+ ) >= 0
+ ) {
+ //q += ''
+ q += '(x=' + values[idx].toJS() + ',x==undefined?undefined:+x)';
+ } else if (alasql.fn[table.xcolumns[col.columnid].dbtypeid]) {
+ q += '(new ' + table.xcolumns[col.columnid].dbtypeid + '(';
+ q += values[idx].toJS();
+ q += '))';
+ } else {
+ q += values[idx].toJS();
+ }
+ } else {
+ q += values[idx].toJS();
+ }
+ ss.push(q);
+ });
+ } else {
+ // var table = db.tables[tableid];
+
+ if (Array.isArray(values) && table.columns && table.columns.length > 0) {
+ table.columns.forEach(function(col, idx) {
+ var q = "'" + col.columnid + "':";
+ // var val = values[idx].toJS();
+
+ if (['INT', 'FLOAT', 'NUMBER', 'MONEY'].indexOf(col.dbtypeid) >= 0) {
+ q += '+' + values[idx].toJS();
+ } else if (alasql.fn[col.dbtypeid]) {
+ q += '(new ' + col.dbtypeid + '(';
+ q += values[idx].toJS();
+ q += '))';
+ } else {
+ q += values[idx].toJS();
+ }
+
+ ss.push(q);
+
+ });
+ } else {
+
+ // sw = 'var w='+JSONtoJS(values)+';for(var k in w){r[k]=w[k]};';
+ sw = JSONtoJS(values);
+ }
+ }
+
+ if (db.tables[tableid].defaultfns) {
+ ss.unshift(db.tables[tableid].defaultfns);
+ }
+ if (sw) {
+ s += 'a=' + sw + ';';
+ } else {
+ s += 'a={' + ss.join(',') + '};';
+ }
+
+ // If this is a class
+ if (db.tables[tableid].isclass) {
+ s += "var db=alasql.databases['" + databaseid + "'];";
+ s += 'a.$class="' + tableid + '";';
+ s += 'a.$id=db.counter++;';
+ s += 'db.objects[a.$id]=a;';
+ }
+ // s += 'db.tables[\''+tableid+'\'].insert(r);';
+ if (db.tables[tableid].insert) {
+ s += "var db=alasql.databases['" + databaseid + "'];";
+ s +=
+ "db.tables['" +
+ tableid +
+ "'].insert(a," +
+ (self.orreplace ? 'true' : 'false') +
+ ');';
+ } else {
+ s += 'aa.push(a);';
+ }
+ });
+
+ s33 = s3 + s;
+
+ if (db.tables[tableid].insert) {
+ // s += 'alasql.databases[\''+databaseid+'\'].tables[\''+tableid+'\'].insert(r);';
+ } else {
+ s +=
+ "alasql.databases['" +
+ databaseid +
+ "'].tables['" +
+ tableid +
+ "'].data=" +
+ "alasql.databases['" +
+ databaseid +
+ "'].tables['" +
+ tableid +
+ "'].data.concat(aa);";
+ }
+
+ if (db.tables[tableid].insert) {
+ if (db.tables[tableid].isclass) {
+ s += 'return a.$id;';
+ } else {
+ s += 'return ' + self.values.length;
+ }
+ } else {
+ s += 'return ' + self.values.length;
+ }
+
+ var insertfn = new Function('db, params, alasql', 'var y;' + s3 + s).bind(this);
+
+ // INSERT INTO table SELECT
+ } else if (this.select) {
+ this.select.modifier = 'RECORDSET';
+ var selectfn = this.select.compile(databaseid);
+ if (db.engineid && alasql.engines[db.engineid].intoTable) {
+ var statement = function(params, cb) {
+ var aa = selectfn(params);
+ var res = alasql.engines[db.engineid].intoTable(
+ db.databaseid,
+ tableid,
+ aa.data,
+ null,
+ cb
+ );
+ return res;
+ };
+ return statement;
+ } else {
+
+ var defaultfns = 'return alasql.utils.extend(r,{' + table.defaultfns + '})';
+ var defaultfn = new Function('r,db,params,alasql', defaultfns);
+ var insertfn = function(db, params, alasql) {
+ var res = selectfn(params).data;
+ if (db.tables[tableid].insert) {
+ // If insert() function exists (issue #92)
+ for (var i = 0, ilen = res.length; i < ilen; i++) {
+ var r = cloneDeep(res[i]);
+ defaultfn(r, db, params, alasql);
+ db.tables[tableid].insert(r, self.orreplace);
+ }
+ } else {
+ db.tables[tableid].data = db.tables[tableid].data.concat(res);
+ }
+ if (alasql.options.nocount) return;
+ else return res.length;
+ };
+ }
+ } else if (this["default"]) {
+ var insertfns =
+ "db.tables['" + tableid + "'].data.push({" + table.defaultfns + '});return 1;';
+ var insertfn = new Function('db,params,alasql', insertfns);
+ } else {
+ throw new Error('Wrong INSERT parameters');
+ }
+
+ if (db.engineid && alasql.engines[db.engineid].intoTable && alasql.options.autocommit) {
+ var statement = function(params, cb) {
+ var aa = new Function('db,params', 'var y;' + s33 + 'return aa;')(db, params);
+
+ var res = alasql.engines[db.engineid].intoTable(db.databaseid, tableid, aa, null, cb);
+ // if(cb) cb(res);
+ return res;
+ };
+ } else {
+ var statement = function(params, cb) {
+
+ var db = alasql.databases[databaseid];
+
+ if (alasql.options.autocommit && db.engineid) {
+ alasql.engines[db.engineid].loadTableData(databaseid, tableid);
+ }
+
+ var res = insertfn(db, params, alasql);
+
+ if (alasql.options.autocommit && db.engineid) {
+ alasql.engines[db.engineid].saveTableData(databaseid, tableid);
+ }
+ // var res = insertfn(db, params);
+ if (alasql.options.nocount) res = undefined;
+ if (cb) cb(res);
+ return res;
+ };
+ }
+
+ return statement;
+};
+
+yy.Insert.prototype.execute = function(databaseid, params, cb) {
+ return this.compile(databaseid)(params, cb);
+ // throw new Error('Insert statement is should be compiled')
+};
+
+/*
+//
+// TRIGGER for Alasql.js
+// Date: 29.12.2015
+//
+*/
+
+yy.CreateTrigger = function(params) {
+ return yy.extend(this, params);
+};
+yy.CreateTrigger.prototype.toString = function() {
+ var s = 'CREATE TRIGGER ' + this.trigger + ' ';
+ if (this.when) s += this.when + ' ';
+ s += this.action + ' ON ';
+ if (this.table.databaseid) s += this.table.databaseid + '.';
+ s += this.table.tableid + ' ';
+ s += this.statement.toString();
+ return s;
+};
+
+yy.CreateTrigger.prototype.execute = function(databaseid, params, cb) {
+ var res = 1; // No tables removed
+ var triggerid = this.trigger;
+ databaseid = this.table.databaseid || databaseid;
+ var db = alasql.databases[databaseid];
+ var tableid = this.table.tableid;
+
+ var trigger = {
+ action: this.action,
+ when: this.when,
+ statement: this.statement,
+ funcid: this.funcid,
+ tableid: this.table.tableid,
+ };
+
+ db.triggers[triggerid] = trigger;
+ if (trigger.action == 'INSERT' && trigger.when == 'BEFORE') {
+ db.tables[tableid].beforeinsert[triggerid] = trigger;
+ } else if (trigger.action == 'INSERT' && trigger.when == 'AFTER') {
+ db.tables[tableid].afterinsert[triggerid] = trigger;
+ } else if (trigger.action == 'INSERT' && trigger.when == 'INSTEADOF') {
+ db.tables[tableid].insteadofinsert[triggerid] = trigger;
+ } else if (trigger.action == 'DELETE' && trigger.when == 'BEFORE') {
+ db.tables[tableid].beforedelete[triggerid] = trigger;
+ } else if (trigger.action == 'DELETE' && trigger.when == 'AFTER') {
+ db.tables[tableid].afterdelete[triggerid] = trigger;
+ } else if (trigger.action == 'DELETE' && trigger.when == 'INSTEADOF') {
+ db.tables[tableid].insteadofdelete[triggerid] = trigger;
+ } else if (trigger.action == 'UPDATE' && trigger.when == 'BEFORE') {
+ db.tables[tableid].beforeupdate[triggerid] = trigger;
+ } else if (trigger.action == 'UPDATE' && trigger.when == 'AFTER') {
+ db.tables[tableid].afterupdate[triggerid] = trigger;
+ } else if (trigger.action == 'UPDATE' && trigger.when == 'INSTEADOF') {
+ db.tables[tableid].insteadofupdate[triggerid] = trigger;
+ }
+
+ if (cb) res = cb(res);
+ return res;
+};
+
+yy.DropTrigger = function(params) {
+ return yy.extend(this, params);
+};
+yy.DropTrigger.prototype.toString = function() {
+ var s = 'DROP TRIGGER ' + this.trigger;
+ return s;
+};
+
+/**
+ Drop trigger
+ @param {string} databaseid Database id
+ @param {object} params Parameters
+ @param {callback} cb Callback function
+ @return Number of dropped triggers
+ @example
+ DROP TRIGGER one;
+*/
+yy.DropTrigger.prototype.execute = function(databaseid, params, cb) {
+ var res = 0; // No tables removed
+ var db = alasql.databases[databaseid];
+ var triggerid = this.trigger;
+
+ // get the trigger
+ var trigger = db.triggers[triggerid];
+
+ // if the trigger exists
+ if (trigger) {
+ var tableid = db.triggers[triggerid].tableid;
+
+ if (tableid) {
+ res = 1;
+ delete db.tables[tableid].beforeinsert[triggerid];
+ delete db.tables[tableid].afterinsert[triggerid];
+ delete db.tables[tableid].insteadofinsert[triggerid];
+ delete db.tables[tableid].beforedelete[triggerid];
+ delete db.tables[tableid].afterdelete[triggerid];
+ delete db.tables[tableid].insteadofdelete[triggerid];
+ delete db.tables[tableid].beforeupdate[triggerid];
+ delete db.tables[tableid].afterupdate[triggerid];
+ delete db.tables[tableid].insteadofupdate[triggerid];
+ delete db.triggers[triggerid];
+ } else {
+ throw new Error('Trigger Table not found');
+ }
+ } else {
+ throw new Error('Trigger not found');
+ }
+ if (cb) res = cb(res);
+ return res;
+};
+
+/*
+//
+// DELETE for Alasql.js
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+yy.Delete = function(params) {
+ return yy.extend(this, params);
+};
+yy.Delete.prototype.toString = function() {
+ var s = 'DELETE FROM ' + this.table.toString();
+ if (this.where) s += ' WHERE ' + this.where.toString();
+ return s;
+};
+
+yy.Delete.prototype.compile = function(databaseid) {
+
+ databaseid = this.table.databaseid || databaseid;
+ var tableid = this.table.tableid;
+ var statement;
+ var db = alasql.databases[databaseid];
+
+ if (this.where) {
+
+ // this.query = {};
+
+ if (this.exists) {
+ this.existsfn = this.exists.map(function(ex) {
+ var nq = ex.compile(databaseid);
+ nq.query.modifier = 'RECORDSET';
+ return nq;
+ });
+ }
+ if (this.queries) {
+ this.queriesfn = this.queries.map(function(q) {
+ var nq = q.compile(databaseid);
+ nq.query.modifier = 'RECORDSET';
+ return nq;
+ });
+ }
+
+ // try {
+
+ // var query = {};
+
+ var wherefn = new Function(
+ 'r,params,alasql',
+ 'var y;return (' + this.where.toJS('r', '') + ')'
+ ).bind(this);
+
+ statement = function(params, cb) {
+ if (db.engineid && alasql.engines[db.engineid].deleteFromTable) {
+ return alasql.engines[db.engineid].deleteFromTable(
+ databaseid,
+ tableid,
+ wherefn,
+ params,
+ cb
+ );
+ }
+
+ if (alasql.options.autocommit && db.engineid && (db.engineid == 'LOCALSTORAGE' || db.engineid == 'FILESTORAGE')) {
+ alasql.engines[db.engineid].loadTableData(databaseid, tableid);
+ }
+
+ var table = db.tables[tableid];
+ // table.dirty = true;
+ var orignum = table.data.length;
+
+ var newtable = [];
+ for (var i = 0, ilen = table.data.length; i < ilen; i++) {
+ if (wherefn(table.data[i], params, alasql)) {
+ // Check for transaction - if it is not possible then return all back
+ if (table["delete"]) {
+ table["delete"](i, params, alasql);
+ } else {
+ // Simply do not push
+ }
+ } else newtable.push(table.data[i]);
+ }
+ // table.data = table.data.filter(function(r){return !;});
+ table.data = newtable;
+
+ // Trigger prevent functionality
+ for (var tr in table.afterdelete) {
+ var trigger = table.afterdelete[tr];
+ if (trigger) {
+ if (trigger.funcid) {
+ alasql.fn[trigger.funcid]();
+ } else if (trigger.statement) {
+ trigger.statement.execute(databaseid);
+ }
+ }
+ }
+
+ var res = orignum - table.data.length;
+ if (alasql.options.autocommit && db.engineid && (db.engineid == 'LOCALSTORAGE' || db.engineid == 'FILESTORAGE')) {
+ alasql.engines[db.engineid].saveTableData(databaseid, tableid);
+ }
+
+ if (cb) cb(res);
+ return res;
+ };
+ // .bind(query);
+
+ // if(!this.queries) return;
+ // query.queriesfn = this.queries.map(function(q) {
+ // return q.compile(alasql.useid);
+ // });
+ } else {
+ statement = function(params, cb) {
+ if (alasql.options.autocommit && db.engineid) {
+ alasql.engines[db.engineid].loadTableData(databaseid, tableid);
+ }
+
+ var table = db.tables[tableid];
+ table.dirty = true;
+ var orignum = db.tables[tableid].data.length;
+ //table.deleteall();
+ // Delete all records from the array
+ db.tables[tableid].data.length = 0;
+
+ // Reset PRIMARY KEY and indexes
+ for (var ix in db.tables[tableid].uniqs) {
+ db.tables[tableid].uniqs[ix] = {};
+ }
+
+ for (var ix in db.tables[tableid].indices) {
+ db.tables[tableid].indices[ix] = {};
+ }
+
+ if (alasql.options.autocommit && db.engineid) {
+ alasql.engines[db.engineid].saveTableData(databaseid, tableid);
+ }
+
+ if (cb) cb(orignum);
+ return orignum;
+ };
+ }
+
+ return statement;
+};
+
+yy.Delete.prototype.execute = function(databaseid, params, cb) {
+ return this.compile(databaseid)(params, cb);
+};
+
+/*
+//
+// UPDATE for Alasql.js
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+/* global yy alasql */
+
+yy.Update = function(params) {
+ return yy.extend(this, params);
+};
+yy.Update.prototype.toString = function() {
+ var s = 'UPDATE ' + this.table.toString();
+ if (this.columns) s += ' SET ' + this.columns.toString();
+ if (this.where) s += ' WHERE ' + this.where.toString();
+ return s;
+};
+
+yy.SetColumn = function(params) {
+ return yy.extend(this, params);
+};
+yy.SetColumn.prototype.toString = function() {
+ return this.column.toString() + '=' + this.expression.toString();
+};
+
+yy.Update.prototype.compile = function(databaseid) {
+
+ databaseid = this.table.databaseid || databaseid;
+ var tableid = this.table.tableid;
+
+ if (this.where) {
+ if (this.exists) {
+ this.existsfn = this.exists.map(function(ex) {
+ var nq = ex.compile(databaseid);
+ nq.query.modifier = 'RECORDSET';
+ return nq;
+ });
+ }
+ if (this.queries) {
+ this.queriesfn = this.queries.map(function(q) {
+ var nq = q.compile(databaseid);
+ nq.query.modifier = 'RECORDSET';
+ return nq;
+ });
+ }
+
+ var wherefn = new Function(
+ 'r,params,alasql',
+ 'var y;return ' + this.where.toJS('r', '')
+ ).bind(this);
+ }
+
+ // Construct update function
+ var s = alasql.databases[databaseid].tables[tableid].onupdatefns || '';
+ s += ';';
+ this.columns.forEach(function(col) {
+ s += "r['" + col.column.columnid + "']=" + col.expression.toJS('r', '') + ';';
+ });
+
+ var assignfn = new Function('r,params,alasql', 'var y;' + s);
+
+ var statement = function(params, cb) {
+ var db = alasql.databases[databaseid];
+
+ if (db.engineid && alasql.engines[db.engineid].updateTable) {
+
+ return alasql.engines[db.engineid].updateTable(
+ databaseid,
+ tableid,
+ assignfn,
+ wherefn,
+ params,
+ cb
+ );
+ }
+
+ if (alasql.options.autocommit && db.engineid) {
+ alasql.engines[db.engineid].loadTableData(databaseid, tableid);
+ }
+
+ var table = db.tables[tableid];
+ if (!table) {
+ throw new Error("Table '" + tableid + "' not exists");
+ }
+ // table.dirty = true;
+ var numrows = 0;
+ for (var i = 0, ilen = table.data.length; i < ilen; i++) {
+ if (!wherefn || wherefn(table.data[i], params, alasql)) {
+ if (table.update) {
+ table.update(assignfn, i, params);
+ } else {
+ assignfn(table.data[i], params, alasql);
+ }
+ numrows++;
+ }
+ }
+
+ if (alasql.options.autocommit && db.engineid) {
+ alasql.engines[db.engineid].saveTableData(databaseid, tableid);
+ }
+
+ if (cb) cb(numrows);
+ return numrows;
+ };
+ return statement;
+};
+
+yy.Update.prototype.execute = function(databaseid, params, cb) {
+ return this.compile(databaseid)(params, cb);
+};
+
+/*
+//
+// SET for Alasql.js
+// Date: 01.12.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+/* global alasql, yy */
+
+yy.Merge = function(params) {
+ return yy.extend(this, params);
+};
+yy.Merge.prototype.toString = function() {
+ var s = 'MERGE ';
+ s += this.into.tableid + ' ';
+ if (this.into.as) s += 'AS ' + this.into.as + ' ';
+ s += 'USING ' + this.using.tableid + ' ';
+ if (this.using.as) s += 'AS ' + this.using.as + ' ';
+ s += 'ON ' + this.on.toString() + ' ';
+ this.matches.forEach(function(m) {
+ s += 'WHEN ';
+ if (!m.matched) s += 'NOT ';
+ s += 'MATCHED ';
+ if (m.bytarget) s += 'BY TARGET ';
+ if (m.bysource) s += 'BY SOURCE ';
+ if (m.expr) s += 'AND' + ' ' + m.expr.toString() + ' ';
+ s += 'THEN ';
+ if (m.action["delete"]) s += 'DELETE ';
+ if (m.action.insert) {
+ s += 'INSERT ';
+ if (m.action.columns) s += '(' + m.action.columns.toString() + ') ';
+ if (m.action.values) s += 'VALUES (' + m.action.values.toString() + ') ';
+ if (m.action.defaultvalues) s += 'DEFAULT VALUES ';
+ }
+ if (m.action.update) {
+ s += 'UPDATE ';
+ s +=
+ m.action.update
+ .map(function(u) {
+ return u.toString();
+ })
+ .join(',') + ' ';
+ }
+ });
+
+ return s;
+};
+
+yy.Merge.prototype.execute = function(databaseid, params, cb) {
+ var res = 1;
+
+ if (cb) res = cb(res);
+ return res;
+};
+
+/*
+//
+// UPDATE for Alasql.js
+// Date: 03.11.2014
+// Modified: 16.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+/* global yy alasql */
+
+// CREATE DATABASE databaseid
+yy.CreateDatabase = function(params) {
+ return yy.extend(this, params);
+};
+yy.CreateDatabase.prototype.toString = function() {
+ var s = 'CREATE';
+ if (this.engineid) s += ' ' + this.engineid;
+ s += ' DATABASE';
+ if (this.ifnotexists) s += ' IF NOT EXISTS';
+ s += ' ' + this.databaseid;
+ if (this.args && this.args.length > 0) {
+ s +=
+ '(' +
+ this.args
+ .map(function(arg) {
+ return arg.toString();
+ })
+ .join(', ') +
+ ')';
+ }
+ if (this.as) s += ' AS ' + this.as;
+ return s;
+};
+//yy.CreateDatabase.prototype.compile = returnUndefined;
+yy.CreateDatabase.prototype.execute = function(databaseid, params, cb) {
+ var args;
+ if (this.args && this.args.length > 0) {
+ args = this.args.map(function(arg) {
+
+ return new Function('params,alasql', 'var y;return ' + arg.toJS())(params, alasql);
+ });
+ }
+ if (this.engineid) {
+ var res = alasql.engines[this.engineid].createDatabase(
+ this.databaseid,
+ this.args,
+ this.ifnotexists,
+ this.as,
+ cb
+ );
+ return res;
+ } else {
+ var dbid = this.databaseid;
+ if (alasql.databases[dbid]) {
+ throw new Error("Database '" + dbid + "' already exists");
+ }
+ var a = new alasql.Database(dbid);
+ var res = 1;
+ if (cb) return cb(res);
+ return res;
+ }
+};
+
+// CREATE DATABASE databaseid
+yy.AttachDatabase = function(params) {
+ return yy.extend(this, params);
+};
+yy.AttachDatabase.prototype.toString = function(args) {
+ var s = 'ATTACH';
+ if (this.engineid) s += ' ' + this.engineid;
+ s += ' DATABASE' + ' ' + this.databaseid;
+ // TODO add params
+ if (args) {
+ s += '(';
+ if (args.length > 0) {
+ s += args
+ .map(function(arg) {
+ return arg.toString();
+ })
+ .join(', ');
+ }
+ s += ')';
+ }
+ if (this.as) s += ' AS' + ' ' + this.as;
+ return s;
+};
+//yy.CreateDatabase.prototype.compile = returnUndefined;
+yy.AttachDatabase.prototype.execute = function(databaseid, params, cb) {
+ if (!alasql.engines[this.engineid]) {
+ throw new Error('Engine "' + this.engineid + '" is not defined.');
+ }
+ var res = alasql.engines[this.engineid].attachDatabase(
+ this.databaseid,
+ this.as,
+ this.args,
+ params,
+ cb
+ );
+ return res;
+};
+
+// CREATE DATABASE databaseid
+yy.DetachDatabase = function(params) {
+ return yy.extend(this, params);
+};
+yy.DetachDatabase.prototype.toString = function() {
+ var s = 'DETACH';
+ s += ' DATABASE' + ' ' + this.databaseid;
+ return s;
+};
+//yy.CreateDatabase.prototype.compile = returnUndefined;
+yy.DetachDatabase.prototype.execute = function(databaseid, params, cb) {
+ if (!alasql.databases[this.databaseid].engineid) {
+ throw new Error(
+ 'Cannot detach database "' + this.engineid + '", because it was not attached.'
+ );
+ }
+ var res;
+
+ var dbid = this.databaseid;
+
+ if (dbid === alasql.DEFAULTDATABASEID) {
+ throw new Error('Drop of default database is prohibited');
+ }
+
+ if (!alasql.databases[dbid]) {
+ if (!this.ifexists) {
+ throw new Error("Database '" + dbid + "' does not exist");
+ } else {
+ res = 0;
+ }
+ } else {
+ // Usually databases are detached and then dropped. Detaching will delete
+ // the database object from memory. While this is OK for in-memory and
+ // other persistent databases, for FileStorage DBs, we will
+ // not be able to delete the DB file (.json) since we would have lost
+ // the filename by deleting the in-memory database object here.
+ // For this reason, to delete the associated JSON file,
+ // keeping the name of the file alone as a property inside the db object
+ // until it gets DROPped subsequently (only for FileStorage DBs)
+ var isFS = alasql.databases[dbid].engineid && alasql.databases[dbid].engineid == 'FILESTORAGE',
+ filename = alasql.databases[dbid].filename || "";
+
+ delete alasql.databases[dbid];
+
+ if (isFS) {
+ // Create a detached FS database
+ alasql.databases[dbid] = {};
+ alasql.databases[dbid].isDetached = true;
+ alasql.databases[dbid].filename = filename;
+ }
+
+ if (dbid === alasql.useid) {
+ alasql.use();
+ }
+ res = 1;
+ }
+ if (cb) cb(res);
+ return res;
+ // var res = alasql.engines[this.engineid].attachDatabase(this.databaseid, this.as, cb);
+ // return res;
+};
+
+// USE DATABSE databaseid
+// USE databaseid
+yy.UseDatabase = function(params) {
+ return yy.extend(this, params);
+};
+yy.UseDatabase.prototype.toString = function() {
+ return 'USE' + ' ' + 'DATABASE' + ' ' + this.databaseid;
+};
+//yy.UseDatabase.prototype.compile = returnUndefined;
+yy.UseDatabase.prototype.execute = function(databaseid, params, cb) {
+ var dbid = this.databaseid;
+ if (!alasql.databases[dbid]) {
+ throw new Error("Database '" + dbid + "' does not exist");
+ }
+ alasql.use(dbid);
+ var res = 1;
+ if (cb) cb(res);
+ return res;
+};
+
+// DROP DATABASE databaseid
+yy.DropDatabase = function(params) {
+ return yy.extend(this, params);
+};
+yy.DropDatabase.prototype.toString = function() {
+ var s = 'DROP';
+ if (this.ifexists) s += ' IF EXISTS';
+ s += ' DATABASE ' + this.databaseid;
+ return s;
+};
+//yy.DropDatabase.prototype.compile = returnUndefined;
+yy.DropDatabase.prototype.execute = function(databaseid, params, cb) {
+ if (this.engineid) {
+ return alasql.engines[this.engineid].dropDatabase(this.databaseid, this.ifexists, cb);
+ }
+ var res;
+
+ var dbid = this.databaseid;
+
+ if (dbid === alasql.DEFAULTDATABASEID) {
+ throw new Error('Drop of default database is prohibited');
+ }
+ if (!alasql.databases[dbid]) {
+ if (!this.ifexists) {
+ throw new Error("Database '" + dbid + "' does not exist");
+ } else {
+ res = 0;
+ }
+ } else {
+ if (alasql.databases[dbid].engineid) {
+ throw new Error(
+ "Cannot drop database '" + dbid + "', because it is attached. Detach it."
+ );
+ }
+
+ delete alasql.databases[dbid];
+ if (dbid === alasql.useid) {
+ alasql.use();
+ }
+ res = 1;
+ }
+ if (cb) cb(res);
+ return res;
+};
+
+/*
+//
+// SET for Alasql.js
+// Date: 01.12.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+yy.Declare = function(params) {
+ return yy.extend(this, params);
+};
+yy.Declare.prototype.toString = function() {
+ var s = 'DECLARE ';
+ if (this.declares && this.declares.length > 0) {
+ s = this.declares
+ .map(function(declare) {
+ var s = '';
+ s += '@' + declare.variable + ' ';
+ s += declare.dbtypeid;
+ if (this.dbsize) {
+ s += '(' + this.dbsize;
+ if (this.dbprecision) {
+ s += ',' + this.dbprecision;
+ }
+ s += ')';
+ }
+ if (declare.expression) {
+ s += ' = ' + declare.expression.toString();
+ }
+ return s;
+ })
+ .join(',');
+ }
+ return s;
+};
+
+yy.Declare.prototype.execute = function(databaseid, params, cb) {
+ var res = 1;
+ if (this.declares && this.declares.length > 0) {
+ this.declares.map(function(declare) {
+ var dbtypeid = declare.dbtypeid;
+ if (!alasql.fn[dbtypeid]) {
+ dbtypeid = dbtypeid.toUpperCase();
+ }
+ alasql.declares[declare.variable] = {
+ dbtypeid: dbtypeid,
+ dbsize: declare.dbsize,
+ dbprecision: declare.dbprecision,
+ };
+
+ // Set value
+ if (declare.expression) {
+
+ alasql.vars[declare.variable] = new Function(
+ 'params,alasql',
+ 'return ' + declare.expression.toJS('({})', '', null)
+ )(params, alasql);
+ if (alasql.declares[declare.variable]) {
+ alasql.vars[declare.variable] = alasql.stdfn.CONVERT(
+ alasql.vars[declare.variable],
+ alasql.declares[declare.variable]
+ );
+ }
+ }
+ });
+ }
+ if (cb) {
+ res = cb(res);
+ }
+ return res;
+};
+
+/*
+//
+// SHOW for Alasql.js
+// Date: 19.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+yy.ShowDatabases = function(params) {
+ return yy.extend(this, params);
+};
+yy.ShowDatabases.prototype.toString = function() {
+ var s = 'SHOW DATABASES';
+ if (this.like) s += 'LIKE ' + this.like.toString();
+ return s;
+};
+yy.ShowDatabases.prototype.execute = function(databaseid, params, cb) {
+ if (this.engineid) {
+ return alasql.engines[this.engineid].showDatabases(this.like, cb);
+ } else {
+ var self = this;
+ var res = [];
+ for (var dbid in alasql.databases) {
+ res.push({databaseid: dbid});
+ }
+ if (self.like && res && res.length > 0) {
+ res = res.filter(function(d) {
+ // return d.databaseid.match(new RegExp((self.like.value||'').replace(/\%/g,'.*').replace(/\?|_/g,'.'),'g'));
+ return alasql.utils.like(self.like.value, d.databaseid);
+ });
+ }
+ if (cb) cb(res);
+ return res;
+ }
+};
+
+yy.ShowTables = function(params) {
+ return yy.extend(this, params);
+};
+yy.ShowTables.prototype.toString = function() {
+ var s = 'SHOW TABLES';
+ if (this.databaseid) s += ' FROM ' + this.databaseid;
+ if (this.like) s += ' LIKE ' + this.like.toString();
+ return s;
+};
+yy.ShowTables.prototype.execute = function(databaseid, params, cb) {
+ var db = alasql.databases[this.databaseid || databaseid];
+
+ var self = this;
+ var res = [];
+ for (var tableid in db.tables) {
+ res.push({tableid: tableid});
+ }
+ if (self.like && res && res.length > 0) {
+ res = res.filter(function(d) {
+ //return d.tableid.match(new RegExp((self.like.value||'').replace(/\%/g,'.*').replace(/\?|_/g,'.'),'g'));
+ return alasql.utils.like(self.like.value, d.tableid);
+ });
+ }
+ if (cb) cb(res);
+ return res;
+};
+
+yy.ShowColumns = function(params) {
+ return yy.extend(this, params);
+};
+yy.ShowColumns.prototype.toString = function() {
+ var s = 'SHOW COLUMNS';
+ if (this.table.tableid) s += ' FROM ' + this.table.tableid;
+ if (this.databaseid) s += ' FROM ' + this.databaseid;
+ return s;
+};
+
+yy.ShowColumns.prototype.execute = function(databaseid, params, cb) {
+ var db = alasql.databases[this.databaseid || databaseid];
+ var table = db.tables[this.table.tableid];
+
+ if (table && table.columns) {
+ var res = table.columns.map(function(col) {
+ return {columnid: col.columnid, dbtypeid: col.dbtypeid, dbsize: col.dbsize};
+ });
+ if (cb) cb(res);
+ return res;
+ } else {
+ if (cb) cb([]);
+ return [];
+ }
+};
+
+yy.ShowIndex = function(params) {
+ return yy.extend(this, params);
+};
+yy.ShowIndex.prototype.toString = function() {
+ var s = 'SHOW INDEX';
+ if (this.table.tableid) s += ' FROM ' + this.table.tableid;
+ if (this.databaseid) s += ' FROM ' + this.databaseid;
+ return s;
+};
+yy.ShowIndex.prototype.execute = function(databaseid, params, cb) {
+ var db = alasql.databases[this.databaseid || databaseid];
+ var table = db.tables[this.table.tableid];
+ var res = [];
+ if (table && table.indices) {
+ for (var ind in table.indices) {
+ res.push({hh: ind, len: Object.keys(table.indices[ind]).length});
+ }
+ }
+
+ if (cb) cb(res);
+ return res;
+};
+
+yy.ShowCreateTable = function(params) {
+ return yy.extend(this, params);
+};
+yy.ShowCreateTable.prototype.toString = function() {
+ var s = 'SHOW CREATE TABLE ' + this.table.tableid;
+ if (this.databaseid) s += ' FROM ' + this.databaseid;
+ return s;
+};
+yy.ShowCreateTable.prototype.execute = function(databaseid) {
+ var db = alasql.databases[this.databaseid || databaseid];
+ var table = db.tables[this.table.tableid];
+ if (table) {
+ var s = 'CREATE TABLE ' + this.table.tableid + ' (';
+ var ss = [];
+ if (table.columns) {
+ table.columns.forEach(function(col) {
+ var a = col.columnid + ' ' + col.dbtypeid;
+ if (col.dbsize) a += '(' + col.dbsize + ')';
+ if (col.primarykey) a += ' PRIMARY KEY';
+ // TODO extend
+ ss.push(a);
+ });
+ s += ss.join(', ');
+ }
+ s += ')';
+ return s;
+ } else {
+ throw new Error('There is no such table "' + this.table.tableid + '"');
+ }
+};
+
+/*
+//
+// SET for Alasql.js
+// Date: 01.12.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+yy.SetVariable = function(params) {
+ return yy.extend(this, params);
+};
+yy.SetVariable.prototype.toString = function() {
+ var s = 'SET ';
+ if (typeof this.value != 'undefined')
+ s += this.variable.toUpperCase() + ' ' + (this.value ? 'ON' : 'OFF');
+ if (this.expression) s += this.method + this.variable + ' = ' + this.expression.toString();
+ return s;
+};
+
+yy.SetVariable.prototype.execute = function(databaseid, params, cb) {
+
+ if (typeof this.value != 'undefined') {
+ var val = this.value;
+ if (val == 'ON') val = true;
+ else if (val == 'OFF') val = false;
+ // if(this.method == '@') {
+ alasql.options[this.variable] = val;
+ // } else {
+ // params[this.variable] = val;
+ // }
+ } else if (this.expression) {
+ if (this.exists) {
+ this.existsfn = this.exists.map(function(ex) {
+ var nq = ex.compile(databaseid);
+ if (nq.query && !nq.query.modifier) nq.query.modifier = 'RECORDSET';
+ return nq;
+ // return ex.compile(databaseid);
+ // TODO Include modifier
+ });
+ }
+ if (this.queries) {
+ this.queriesfn = this.queries.map(function(q) {
+ var nq = q.compile(databaseid);
+ if (nq.query && !nq.query.modifier) nq.query.modifier = 'RECORDSET';
+ return nq;
+ // TODO Include modifier
+ });
+ }
+
+ var res = new Function(
+ 'params,alasql',
+ 'return ' + this.expression.toJS('({})', '', null)
+ ).bind(this)(params, alasql);
+ if (alasql.declares[this.variable]) {
+ res = alasql.stdfn.CONVERT(res, alasql.declares[this.variable]);
+ }
+ if (this.props && this.props.length > 0) {
+ if (this.method == '@') {
+ var fs = "alasql.vars['" + this.variable + "']";
+ } else {
+ var fs = "params['" + this.variable + "']";
+ }
+ fs += this.props
+ .map(function(prop) {
+ if (typeof prop == 'string') {
+ return "['" + prop + "']";
+ } else if (typeof prop == 'number') {
+ return '[' + prop + ']';
+ } else {
+
+ return '[' + prop.toJS() + ']';
+ // } else {
+
+ // throw new Error('Wrong SET property');
+ }
+ })
+ .join();
+
+ new Function('value,params,alasql', 'var y;' + fs + '=value')(res, params, alasql);
+ } else {
+ if (this.method == '@') {
+ alasql.vars[this.variable] = res;
+ } else {
+ params[this.variable] = res;
+ }
+ }
+ }
+ var res = 1;
+ if (cb) res = cb(res);
+ return res;
+};
+
+// Console functions
+
+/* global alasql, yy */
+
+alasql.test = function (name, times, fn) {
+ if (arguments.length === 0) {
+ alasql.log(alasql.con.results);
+ return;
+ }
+
+ var tm = Date.now();
+
+ if (arguments.length === 1) {
+ fn();
+ alasql.con.log(Date.now() - tm);
+ return;
+ }
+
+ if (arguments.length === 2) {
+ fn = times;
+ times = 1;
+ }
+
+ for (var i = 0; i < times; i++) {
+ fn();
+ }
+ alasql.con.results[name] = Date.now() - tm;
+};
+
+// Console
+// alasql.log = function(sql, params) {
+
+// };
+
+/* global alasql, yy, utils */
+
+// Console
+alasql.log = function (sql, params) {
+ var olduseid = alasql.useid;
+ var target = alasql.options.logtarget;
+ // For node other
+ if (utils.isNode) {
+ target = 'console';
+ }
+
+ var res;
+ if (typeof sql === 'string') {
+ res = alasql(sql, params);
+ } else {
+ res = sql;
+ }
+
+ // For Node and console.output
+ if (target === 'console' || utils.isNode) {
+ if (typeof sql === 'string' && alasql.options.logprompt) {
+ console.log(olduseid + '>', sql);
+ }
+
+ if (Array.isArray(res)) {
+ if (console.table) {
+ // For Chrome and other consoles
+ console.table(res);
+ } else {
+ // Add print procedure
+ console.log(JSONtoString(res));
+ }
+ } else {
+ console.log(JSONtoString(res));
+ }
+ } else {
+ var el;
+ if (target === 'output') {
+ el = document.getElementsByTagName('output')[0];
+ } else {
+ if (typeof target === 'string') {
+ el = document.getElementById(target);
+ } else {
+ // in case of DOM
+ el = target;
+ }
+ }
+
+ var s = '';
+
+ if (typeof sql === 'string' && alasql.options.logprompt) {
+ // s += ''+olduseid+'> '+alasql.pretty(sql)+'
';
+ s += '' + alasql.pretty(sql) + '
';
+ }
+
+ if (Array.isArray(res)) {
+ if (res.length === 0) {
+ s += '[ ]
';
+ } else if (typeof res[0] !== 'object' || Array.isArray(res[0])) {
+ for (var i = 0, ilen = res.length; i < ilen; i++) {
+ s += '' + loghtml(res[i]) + '
';
+ }
+ } else {
+ s += loghtml(res);
+ }
+ } else {
+ s += loghtml(res);
+ }
+ el.innerHTML += s;
+ }
+};
+
+alasql.clear = function () {
+ var target = alasql.options.logtarget;
+ // For node other
+
+ if (utils.isNode || utils.isMeteorServer) {
+ if (console.clear) {
+ console.clear();
+ }
+ } else {
+ var el;
+ if (target === 'output') {
+ el = document.getElementsByTagName('output')[0];
+ } else {
+ if (typeof target === 'string') {
+ el = document.getElementById(target);
+ } else {
+ // in case of DOM
+ el = target;
+ }
+ }
+ el.innerHTML = '';
+ }
+};
+
+alasql.write = function (s) {
+
+ var target = alasql.options.logtarget;
+ // For node other
+ if (utils.isNode || utils.isMeteorServer) {
+ if (console.log) {
+ console.log(s);
+ }
+ } else {
+ var el;
+ if (target === 'output') {
+ el = document.getElementsByTagName('output')[0];
+ } else {
+ if (typeof target === 'string') {
+ el = document.getElementById(target);
+ } else {
+ // in case of DOM
+ el = target;
+ }
+ }
+ el.innerHTML += s;
+ }
+};
+
+function loghtml(res) {
+
+ var s = '';
+ if (res === undefined) {
+ s += 'undefined';
+ } else if (Array.isArray(res)) {
+ s += '';
+ s += '';
+ var cols = [];
+ for (var colid in res[0]) {
+ cols.push(colid);
+ }
+ s += '#';
+ cols.forEach(function (colid) {
+ s += ' | ' + colid;
+ });
+ for (var i = 0, ilen = res.length; i < ilen; i++) {
+ s += ' |
---|
' + (i + 1);
+ cols.forEach(function (colid) {
+ s += ' | ';
+ if (res[i][colid] == +res[i][colid]) {
+ // jshint ignore:line
+ s += ' ';
+ if (typeof res[i][colid] === 'undefined') {
+ s += 'NULL';
+ } else {
+ s += res[i][colid];
+ }
+ s += ' ';
+ } else {
+ if (typeof res[i][colid] === 'undefined') {
+ s += 'NULL';
+ } else if (typeof res[i][colid] === 'string') {
+ s += res[i][colid];
+ } else {
+ s += JSONtoString(res[i][colid]);
+ }
+ // s += res[i][colid];
+ }
+ });
+ }
+
+ s += ' |
---|
';
+ } else {
+ s += '' + JSONtoString(res) + '
';
+ }
+ // if() {}
+
+ // if(typeof res == 'object') {
+ // s += ''+JSON.stringify(res)+'
';
+ // } else {
+ // }
+ return s;
+}
+
+function scrollTo(element, to, duration) {
+ if (duration <= 0) {
+ return;
+ }
+ var difference = to - element.scrollTop;
+ var perTick = (difference / duration) * 10;
+
+ setTimeout(function () {
+ if (element.scrollTop === to) {
+ return;
+ }
+ element.scrollTop = element.scrollTop + perTick;
+ scrollTo(element, to, duration - 10);
+ }, 10);
+}
+
+alasql.prompt = function (el, useidel, firstsql) {
+ if (utils.isNode) {
+ throw new Error('The prompt not realized for Node.js');
+ }
+
+ var prompti = 0;
+
+ if (typeof el === 'string') {
+ el = document.getElementById(el);
+ }
+
+ if (typeof useidel === 'string') {
+ useidel = document.getElementById(useidel);
+ }
+
+ useidel.textContent = alasql.useid;
+
+ if (firstsql) {
+ alasql.prompthistory.push(firstsql);
+ prompti = alasql.prompthistory.length;
+ try {
+ var tm = Date.now();
+ alasql.log(firstsql);
+ alasql.write('' + (Date.now() - tm) + ' ms
');
+ } catch (err) {
+ alasql.write('' + alasql.useid + '> ' + firstsql + '
');
+ alasql.write('' + err + '
');
+ }
+ }
+
+ var y = el.getBoundingClientRect().top + document.getElementsByTagName('body')[0].scrollTop;
+ scrollTo(document.getElementsByTagName('body')[0], y, 500);
+
+ el.onkeydown = function (event) {
+ if (event.which === 13) {
+ var sql = el.value;
+ var olduseid = alasql.useid;
+ el.value = '';
+ alasql.prompthistory.push(sql);
+ prompti = alasql.prompthistory.length;
+ try {
+ var tm = Date.now();
+ alasql.log(sql);
+ alasql.write('
' + (Date.now() - tm) + ' ms
');
+ } catch (err) {
+ alasql.write('' + olduseid + '> ' + alasql.pretty(sql, false) + '
');
+ alasql.write('' + err + '
');
+ }
+ el.focus();
+
+ useidel.textContent = alasql.useid;
+ var y = el.getBoundingClientRect().top + document.getElementsByTagName('body')[0].scrollTop;
+ scrollTo(document.getElementsByTagName('body')[0], y, 500);
+ } else if (event.which === 38) {
+ prompti--;
+ if (prompti < 0) {
+ prompti = 0;
+ }
+ if (alasql.prompthistory[prompti]) {
+ el.value = alasql.prompthistory[prompti];
+ event.preventDefault();
+ }
+ } else if (event.which === 40) {
+ prompti++;
+ if (prompti >= alasql.prompthistory.length) {
+ prompti = alasql.prompthistory.length;
+ el.value = '';
+ } else if (alasql.prompthistory[prompti]) {
+ el.value = alasql.prompthistory[prompti];
+ event.preventDefault();
+ }
+ }
+ };
+};
+
+/*
+//
+// Commit for Alasql.js
+// Date: 01.12.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+yy.BeginTransaction = function(params) {
+ return yy.extend(this, params);
+};
+yy.BeginTransaction.prototype.toString = function() {
+ return 'BEGIN TRANSACTION';
+};
+
+yy.BeginTransaction.prototype.execute = function(databaseid, params, cb) {
+ var res = 1;
+ if (alasql.databases[databaseid].engineid) {
+ return alasql.engines[alasql.databases[alasql.useid].engineid].begin(databaseid, cb);
+ } else {
+ // alasql commit!!!
+ }
+ if (cb) cb(res);
+ return res;
+};
+
+yy.CommitTransaction = function(params) {
+ return yy.extend(this, params);
+};
+yy.CommitTransaction.prototype.toString = function() {
+ return 'COMMIT TRANSACTION';
+};
+
+yy.CommitTransaction.prototype.execute = function(databaseid, params, cb) {
+ var res = 1;
+ if (alasql.databases[databaseid].engineid) {
+ return alasql.engines[alasql.databases[alasql.useid].engineid].commit(databaseid, cb);
+ } else {
+ // alasql commit!!!
+ }
+ if (cb) cb(res);
+ return res;
+};
+
+yy.RollbackTransaction = function(params) {
+ return yy.extend(this, params);
+};
+yy.RollbackTransaction.prototype.toString = function() {
+ return 'ROLLBACK TRANSACTION';
+};
+
+yy.RollbackTransaction.prototype.execute = function(databaseid, params, cb) {
+ var res = 1;
+ if (alasql.databases[databaseid].engineid) {
+ return alasql.engines[alasql.databases[databaseid].engineid].rollback(databaseid, cb);
+ } else {
+ // alasql commit!!!
+ }
+ if (cb) cb(res);
+ return res;
+};
+
+if (alasql.options.tsql) {
+ //
+ // Check tables and views
+ // IF OBJECT_ID('dbo.Employees') IS NOT NULL
+ // DROP TABLE dbo.Employees;
+ // IF OBJECT_ID('dbo.VSortedOrders', 'V') IS NOT NULL
+ // DROP VIEW dbo.VSortedOrders;
+
+ alasql.stdfn.OBJECT_ID = function(name, type) {
+ if (typeof type == 'undefined') type = 'T';
+ type = type.toUpperCase();
+
+ var sname = name.split('.');
+ var dbid = alasql.useid;
+ var objname = sname[0];
+ if (sname.length == 2) {
+ dbid = sname[0];
+ objname = sname[1];
+ }
+
+ var tables = alasql.databases[dbid].tables;
+ dbid = alasql.databases[dbid].databaseid;
+ for (var tableid in tables) {
+ if (tableid == objname) {
+ // TODO: What OBJECT_ID actually returns
+
+ if (tables[tableid].view && type == 'V') return dbid + '.' + tableid;
+ if (!tables[tableid].view && type == 'T') return dbid + '.' + tableid;
+ return undefined;
+ }
+ }
+
+ return undefined;
+ };
+}
+
+if (alasql.options.mysql) {
+}
+
+if (alasql.options.mysql || alasql.options.sqlite) {
+ // Pseudo INFORMATION_SCHEMA function
+ alasql.from.INFORMATION_SCHEMA = function(filename, opts, cb, idx, query) {
+ if (filename == 'VIEWS' || filename == 'TABLES') {
+ var res = [];
+ for (var databaseid in alasql.databases) {
+ var tables = alasql.databases[databaseid].tables;
+ for (var tableid in tables) {
+ if (
+ (tables[tableid].view && filename == 'VIEWS') ||
+ (!tables[tableid].view && filename == 'TABLES')
+ ) {
+ res.push({TABLE_CATALOG: databaseid, TABLE_NAME: tableid});
+ }
+ }
+ }
+ if (cb) res = cb(res, idx, query);
+ return res;
+ }
+ throw new Error('Unknown INFORMATION_SCHEMA table');
+ };
+}
+
+if (alasql.options.postgres) {
+}
+
+if (alasql.options.oracle) {
+}
+
+if (alasql.options.sqlite) {
+}
+
+//
+// into functions
+//
+// (c) 2014 Andrey Gershun
+//
+
+alasql.into.SQL = function(filename, opts, data, columns, cb) {
+ var res;
+ if (typeof filename === 'object') {
+ opts = filename;
+ filename = undefined;
+ }
+ var opt = {};
+ alasql.utils.extend(opt, opts);
+ if (typeof opt.tableid === 'undefined') {
+ throw new Error('Table for INSERT TO is not defined.');
+ }
+
+ var s = '';
+ if (columns.length === 0) {
+ if (typeof data[0] === 'object') {
+ columns = Object.keys(data[0]).map(function(columnid) {
+ return {columnid: columnid};
+ });
+ } else {
+ // What should I do?
+ // columns = [{columnid:"_"}];
+ }
+ }
+
+ for (var i = 0, ilen = data.length; i < ilen; i++) {
+ s += 'INSERT INTO ' + opts.tableid + '(';
+ s += columns
+ .map(function(col) {
+ return col.columnid;
+ })
+ .join(',');
+ s += ') VALUES (';
+ s += columns.map(function(col) {
+ var val = data[i][col.columnid];
+ if (col.typeid) {
+ if (
+ col.typeid === 'STRING' ||
+ col.typeid === 'VARCHAR' ||
+ col.typeid === 'NVARCHAR' ||
+ col.typeid === 'CHAR' ||
+ col.typeid === 'NCHAR'
+ ) {
+ val = "'" + escapeqq(val) + "'";
+ }
+ } else {
+ if (typeof val == 'string') {
+ val = "'" + escapeqq(val) + "'";
+ }
+ }
+ return val;
+ });
+ s += ');\n';
+ }
+ // if(filename === '') {
+ // res = s;
+ // } else {
+ // res = data.length;
+ filename = alasql.utils.autoExtFilename(filename, 'sql', opts);
+ res = alasql.utils.saveFile(filename, s);
+ if (cb) {
+ res = cb(res);
+ }
+ return res;
+};
+
+alasql.into.HTML = function(selector, opts, data, columns, cb) {
+ var res = 1;
+ if (typeof exports !== 'object') {
+ var opt = {headers: true};
+ alasql.utils.extend(opt, opts);
+
+ var sel = document.querySelector(selector);
+ if (!sel) {
+ throw new Error('Selected HTML element is not found');
+ }
+
+ if (columns.length === 0) {
+ if (typeof data[0] === 'object') {
+ columns = Object.keys(data[0]).map(function(columnid) {
+ return {columnid: columnid};
+ });
+ } else {
+ // What should I do?
+ // columns = [{columnid:"_"}];
+ }
+ }
+
+ var tbe = document.createElement('table');
+ var thead = document.createElement('thead');
+ tbe.appendChild(thead);
+ if (opt.headers) {
+ var tre = document.createElement('tr');
+ for (var i = 0; i < columns.length; i++) {
+ var the = document.createElement('th');
+ the.textContent = columns[i].columnid;
+ tre.appendChild(the);
+ }
+ thead.appendChild(tre);
+ }
+
+ var tbody = document.createElement('tbody');
+ tbe.appendChild(tbody);
+ for (var j = 0; j < data.length; j++) {
+ var tre = document.createElement('tr');
+ for (var i = 0; i < columns.length; i++) {
+ var the = document.createElement('td');
+ the.textContent = data[j][columns[i].columnid];
+ tre.appendChild(the);
+ }
+ tbody.appendChild(tre);
+ }
+ alasql.utils.domEmptyChildren(sel);
+
+ sel.appendChild(tbe);
+ }
+ if (cb) {
+ res = cb(res);
+ }
+ return res;
+};
+
+alasql.into.JSON = function(filename, opts, data, columns, cb) {
+ var res = 1;
+ if (typeof filename === 'object') {
+ opts = filename;
+ filename = undefined;
+ }
+ var s = JSON.stringify(data);
+
+ filename = alasql.utils.autoExtFilename(filename, 'json', opts);
+ res = alasql.utils.saveFile(filename, s);
+ if (cb) {
+ res = cb(res);
+ }
+ return res;
+};
+
+alasql.into.TXT = function(filename, opts, data, columns, cb) {
+ // If columns is empty
+ if (columns.length === 0 && data.length > 0) {
+ columns = Object.keys(data[0]).map(function(columnid) {
+ return {columnid: columnid};
+ });
+ }
+ // If one parameter
+ if (typeof filename === 'object') {
+ opts = filename;
+ filename = undefined;
+ }
+
+ var res = data.length;
+ var s = '';
+ if (data.length > 0) {
+ var key = columns[0].columnid;
+ s += data
+ .map(function(d) {
+ return d[key];
+ })
+ .join('\n');
+ }
+
+ // } else {
+ // if(utils.isNode) {
+ // process.stdout.write(s);
+ // } else {
+
+ // };
+ // }
+ filename = alasql.utils.autoExtFilename(filename, 'txt', opts);
+ res = alasql.utils.saveFile(filename, s);
+ if (cb) {
+ res = cb(res);
+ }
+ return res;
+};
+
+alasql.into.TAB = alasql.into.TSV = function(filename, opts, data, columns, cb) {
+ var opt = {};
+ alasql.utils.extend(opt, opts);
+ opt.separator = '\t';
+ filename = alasql.utils.autoExtFilename(filename, 'tab', opts);
+ opt.autoExt = false;
+ return alasql.into.CSV(filename, opt, data, columns, cb);
+};
+
+alasql.into.CSV = function(filename, opts, data, columns, cb) {
+ if (columns.length === 0 && data.length > 0) {
+ columns = Object.keys(data[0]).map(function(columnid) {
+ return {columnid: columnid};
+ });
+ }
+ if (typeof filename === 'object') {
+ opts = filename;
+ filename = undefined;
+ }
+
+ var opt = {headers: true};
+ //opt.separator = ',';
+ opt.separator = ';';
+ opt.quote = '"';
+
+ opt.utf8Bom = true;
+ if (opts && !opts.headers && typeof opts.headers !== 'undefined') {
+ opt.utf8Bom = false;
+ }
+
+ alasql.utils.extend(opt, opts);
+ var res = data.length;
+ var s = opt.utf8Bom ? '\ufeff' : '';
+ if (opt.headers) {
+ s +=
+ opt.quote +
+ columns
+ .map(function(col) {
+ return col.columnid.trim();
+ })
+ .join(opt.quote + opt.separator + opt.quote) +
+ opt.quote +
+ '\r\n';
+ }
+
+ data.forEach(function(d) {
+ s +=
+ columns
+ .map(function(col) {
+ var s = d[col.columnid];
+ // escape the character wherever it appears in the field
+ if (opt.quote !== '') {
+ s = (s + '').replace(
+ new RegExp('\\' + opt.quote, 'g'),
+ opt.quote + opt.quote
+ );
+ }
+ // if((s+"").indexOf(opt.separator) > -1 || (s+"").indexOf(opt.quote) > -1) s = opt.quote + s + opt.quote;
+
+ //Excel 2013 needs quotes around strings - thanks for _not_ complying with RFC for CSV
+ if (+s != s) {
+ // jshint ignore:line
+ s = opt.quote + s + opt.quote;
+ }
+
+ return s;
+ })
+ .join(opt.separator) + '\r\n';
+ });
+
+ filename = alasql.utils.autoExtFilename(filename, 'csv', opts);
+ res = alasql.utils.saveFile(filename, s, null, {disableAutoBom: true});
+ if (cb) {
+ res = cb(res);
+ }
+ return res;
+};
+
+//
+// 831xl.js - Coloring Excel
+// 18.04.2015
+// Generate XLS file with colors and styles
+// with Excel
+
+alasql.into.XLS = function(filename, opts, data, columns, cb) {
+ // If filename is not defined then output to the result
+ if (typeof filename == 'object') {
+ opts = filename;
+ filename = undefined;
+ }
+
+ // Set sheets
+ var sheets = {};
+ if (opts && opts.sheets) {
+ sheets = opts.sheets;
+ }
+
+ // Default sheet
+ var sheet = {headers: true};
+ if (typeof sheets['Sheet1'] != 'undefined') {
+ sheet = sheets[0];
+ } else {
+ if (typeof opts != 'undefined') {
+ sheet = opts;
+ }
+ }
+
+ // Set sheet name and default is 'Sheet1'
+ if (typeof sheet.sheetid == 'undefined') {
+ sheet.sheetid = 'Sheet1';
+ }
+
+ var s = toHTML();
+
+ // File is ready to save
+ filename = alasql.utils.autoExtFilename(filename, 'xls', opts);
+ var res = alasql.utils.saveFile(filename, s);
+ if (cb) res = cb(res);
+ return res;
+
+ function toHTML() {
+ // Generate prologue
+ var s =
+ '
\
+ \
+ ';
+
+ // Generate body
+ s += '';
+ s += '';
+ if (typeof sheet.caption != 'undefined') {
+ var caption = sheet.caption;
+ if (typeof caption == 'string') {
+ caption = {title: caption};
+ }
+ s += '';
+ s += caption.title;
+ s += '';
+ }
+
+ // Columns
+
+ // var columns = [];
+
+ // If columns defined in sheet, then take them
+ if (typeof sheet.columns != 'undefined') {
+ columns = sheet.columns;
+ } else {
+ // Autogenerate columns if they are passed as parameters
+ if (columns.length == 0 && data.length > 0) {
+ if (typeof data[0] == 'object') {
+ if (Array.isArray(data[0])) {
+ columns = data[0].map(function(d, columnidx) {
+ return {columnid: columnidx};
+ });
+ } else {
+ columns = Object.keys(data[0]).map(function(columnid) {
+ return {columnid: columnid};
+ });
+ }
+ }
+ }
+ }
+
+ // Prepare columns
+ columns.forEach(function(column, columnidx) {
+ if (typeof sheet.column != 'undefined') {
+ extend(column, sheet.column);
+ }
+
+ if (typeof column.width == 'undefined') {
+ if (sheet.column && sheet.column.width != 'undefined') {
+ column.width = sheet.column.width;
+ } else {
+ column.width = '120px';
+ }
+ }
+ if (typeof column.width == 'number') column.width = column.width + 'px';
+ if (typeof column.columnid == 'undefined') column.columnid = columnidx;
+ if (typeof column.title == 'undefined') column.title = '' + column.columnid.trim();
+ if (sheet.headers && Array.isArray(sheet.headers))
+ column.title = sheet.headers[columnidx];
+ });
+
+ // Set columns widths
+ s += '';
+ columns.forEach(function(column) {
+ s += '';
+ });
+ s += '';
+
+ // Headers
+ if (sheet.headers) {
+ s += '';
+ s += '';
+
+ // TODO: Skip columns to body
+
+ // Headers
+ columns.forEach(function(column, columnidx) {
+ s += '';
+
+ // Column title
+ if (typeof column.title != 'undefined') {
+ if (typeof column.title == 'function') {
+ s += column.title(sheet, column, columnidx);
+ } else {
+ s += column.title;
+ }
+ }
+ s += ' | ';
+ });
+
+ s += '
';
+ s += '';
+ }
+
+ s += '';
+
+ // TODO: Skip lines between header and body
+
+ if (data && data.length > 0) {
+ // TODO: Skip columns to body
+
+ // Loop over data rows
+ data.forEach(function(row, rowidx) {
+ // Limit number of rows on the sheet
+ if (rowidx > sheet.limit) return;
+ // Create row
+ s += '';
+ // Loop over columns
+ columns.forEach(function(column, columnidx) {
+ // Parameters
+ var cell = {};
+ extend(cell, sheet.cell);
+ extend(cell, srow.cell);
+ if (typeof sheet.column != 'undefined') {
+ extend(cell, sheet.column.cell);
+ }
+ extend(cell, column.cell);
+ if (sheet.cells && sheet.cells[rowidx] && sheet.cells[rowidx][columnidx]) {
+ extend(cell, sheet.cells[rowidx][columnidx]);
+ }
+
+ // Create value
+ var value = row[column.columnid];
+ if (typeof cell.value == 'function') {
+ value = cell.value(value, sheet, row, column, cell, rowidx, columnidx);
+ }
+
+ // Define cell type
+ var typeid = cell.typeid;
+ if (typeof typeid == 'function') {
+ typeid = typeid(value, sheet, row, column, cell, rowidx, columnidx);
+ }
+
+ if (typeof typeid == 'undefined') {
+ if (typeof value == 'number') typeid = 'number';
+ else if (typeof value == 'string') typeid = 'string';
+ else if (typeof value == 'boolean') typeid = 'boolean';
+ else if (typeof value == 'object') {
+ if (value instanceof Date) typeid = 'date';
+ }
+ }
+
+ var typestyle = '';
+
+ if (typeid == 'money') {
+ typestyle =
+ 'mso-number-format:"\\#\\,\\#\\#0\\\\ _р_\\.";white-space:normal;';
+ } else if (typeid == 'number') {
+ typestyle = ' ';
+ } else if (typeid == 'date') {
+ typestyle = 'mso-number-format:"Short Date";';
+ } else {
+ // FOr other types is saved
+ if (opts.types && opts.types[typeid] && opts.types[typeid].typestyle) {
+ typestyle = opts.types[typeid].typestyle;
+ }
+ }
+
+ // TODO Replace with extend...
+ typestyle = typestyle || 'mso-number-format:"\\@";'; // Default type style
+
+ s += "';
+
+ // TODO Replace with extend...
+ var format = cell.format;
+ if (typeof value == 'undefined') {
+ s += '';
+ } else if (typeof format != 'undefined') {
+ if (typeof format == 'function') {
+ s += format(value);
+ } else if (typeof format == 'string') {
+ s += value; // TODO - add string format
+ } else {
+ throw new Error('Unknown format type. Should be function or string');
+ }
+ } else {
+ if (typeid == 'number' || typeid == 'date') {
+ s += value.toString();
+ } else if (typeid == 'money') {
+ s += (+value).toFixed(2);
+ } else {
+ s += value;
+ }
+ }
+ s += ' | ';
+ });
+
+ s += '
';
+ });
+ }
+
+ s += '';
+
+ // Generate epilogue
+ s += '
';
+ s += '';
+ s += '';
+
+ return s;
+ }
+
+ // Style function
+ function style(a) {
+ var s = ' style="';
+ if (a && typeof a.style != 'undefined') {
+ s += a.style + ';';
+ }
+ s += '" ';
+ return s;
+ }
+};
+
+alasql.into.XLSXML = function(filename, opts, data, columns, cb) {
+ opts = opts || {};
+
+ // If filename is not defined then output to the result
+ if (typeof filename == 'object') {
+ opts = filename;
+ filename = undefined;
+ }
+
+ // Set sheets
+ var sheets = {};
+ var sheetsdata;
+ var sheetscolumns;
+ if (opts && opts.sheets) {
+ sheets = opts.sheets;
+ // data and columns are already an array for the sheets
+ sheetsdata = data;
+ sheetscolumns = columns;
+ } else {
+ sheets.Sheet1 = opts;
+ // wrapd ata and columns array for single sheet
+ sheetsdata = [data];
+ sheetscolumns = [columns];
+ }
+
+ // File is ready to save
+ filename = alasql.utils.autoExtFilename(filename, 'xls', opts);
+ var res = alasql.utils.saveFile(filename, toXML());
+ if (cb) res = cb(res);
+ return res;
+
+ function toXML() {
+ var s1 =
+ ' \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ 0 \
+ \
+ \
+ ';
+
+ var s2 = ''; // for styles
+
+ var s3 = ' ';
+
+ var styles = {}; // hash based storage for styles
+ var stylesn = 62; // First style
+
+ // Generate style
+ function hstyle(st) {
+ // Prepare string
+ var s = '';
+ for (var key in st) {
+ s += '<' + key;
+ for (var attr in st[key]) {
+ s += ' ';
+ if (attr.substr(0, 2) == 'x:') {
+ s += attr;
+ } else {
+ s += 'ss:';
+ }
+ s += attr + '="' + st[key][attr] + '"';
+ }
+ s += '/>';
+ }
+
+ var hh = hash(s);
+ // Store in hash
+ if (styles[hh]) {
+ } else {
+ styles[hh] = {styleid: stylesn};
+ s2 += '';
+ stylesn++;
+ }
+ return 's' + styles[hh].styleid;
+ }
+
+ function values(obj) {
+ try {
+ return Object.values(obj);
+ } catch (e) {
+ // support for older runtimes
+ return Object.keys(obj).map(function(e) {
+ return obj[e];
+ });
+ }
+ }
+
+ var sheetidx = 0;
+ for (var sheetid in sheets) {
+ var sheet = sheets[sheetid];
+ var idx = typeof sheet.dataidx != 'undefined' ? sheet.dataidx : sheetidx++;
+ var data = values(sheetsdata[idx]);
+ // If columns defined in sheet, then take them
+ var columns = undefined;
+ if (typeof sheet.columns != 'undefined') {
+ columns = sheet.columns;
+ } else {
+ // Autogenerate columns if they are passed as parameters
+ columns = sheetscolumns[idx];
+ if (columns === undefined || (columns.length == 0 && data.length > 0)) {
+ if (typeof data[0] == 'object') {
+ if (Array.isArray(data[0])) {
+ columns = data[0].map(function(d, columnidx) {
+ return {columnid: columnidx};
+ });
+ } else {
+ columns = Object.keys(data[0]).map(function(columnid) {
+ return {columnid: columnid};
+ });
+ }
+ }
+ }
+ }
+
+ // Prepare columns
+ columns.forEach(function(column, columnidx) {
+ if (typeof sheet.column != 'undefined') {
+ extend(column, sheet.column);
+ }
+
+ if (typeof column.width == 'undefined') {
+ if (sheet.column && typeof sheet.column.width != 'undefined') {
+ column.width = sheet.column.width;
+ } else {
+ column.width = 120;
+ }
+ }
+ if (typeof column.width == 'number') column.width = column.width;
+ if (typeof column.columnid == 'undefined') column.columnid = columnidx;
+ if (typeof column.title == 'undefined') column.title = '' + column.columnid.trim();
+ if (sheet.headers && Array.isArray(sheet.headers))
+ column.title = sheet.headers[columnidx];
+ });
+
+ // Header
+ s3 +=
+ ' \
+ ';
+
+ columns.forEach(function(column, columnidx) {
+ s3 +=
+ '';
+ });
+
+ // Headers
+ if (sheet.headers) {
+ s3 += '';
+
+ // TODO: Skip columns to body
+
+ // Headers
+ columns.forEach(function(column, columnidx) {
+ s3 += '';
+
+ // Column title
+ if (typeof column.title != 'undefined') {
+ if (typeof column.title == 'function') {
+ s3 += column.title(sheet, column, columnidx);
+ } else {
+ s3 += column.title;
+ }
+ }
+ s3 += ' | ';
+ });
+
+ s3 += '
';
+ }
+
+ // Data
+ if (data && data.length > 0) {
+ // Loop over data rows
+ data.forEach(function(row, rowidx) {
+ // Limit number of rows on the sheet
+ if (rowidx > sheet.limit) return;
+
+ // Extend row properties
+ var srow = {};
+ extend(srow, sheet.row);
+ if (sheet.rows && sheet.rows[rowidx]) {
+ extend(srow, sheet.rows[rowidx]);
+ }
+
+ s3 += ''; //'ss:AutoFitHeight="0">'
+
+ // Data
+ columns.forEach(function(column, columnidx) {
+ // Parameters
+ var cell = {};
+ extend(cell, sheet.cell);
+ extend(cell, srow.cell);
+ if (typeof sheet.column != 'undefined') {
+ extend(cell, sheet.column.cell);
+ }
+ extend(cell, column.cell);
+ if (sheet.cells && sheet.cells[rowidx] && sheet.cells[rowidx][columnidx]) {
+ extend(cell, sheet.cells[rowidx][columnidx]);
+ }
+
+ // Create value
+ var value = row[column.columnid];
+ if (typeof cell.value == 'function') {
+ value = cell.value(value, sheet, row, column, cell, rowidx, columnidx);
+ }
+
+ // Define cell type
+ var typeid = cell.typeid;
+ if (typeof typeid == 'function') {
+ typeid = typeid(value, sheet, row, column, cell, rowidx, columnidx);
+ }
+
+ if (typeof typeid == 'undefined') {
+ if (typeof value == 'number') typeid = 'number';
+ else if (typeof value == 'string') typeid = 'string';
+ else if (typeof value == 'boolean') typeid = 'boolean';
+ else if (typeof value == 'object') {
+ if (value instanceof Date) typeid = 'date';
+ }
+ }
+
+ var Type = 'String';
+ if (typeid == 'number') Type = 'Number';
+ else if (typeid == 'date') Type = 'Date';
+ // TODO: What else?
+
+ // Prepare Data types styles
+ var typestyle = '';
+
+ if (typeid == 'money') {
+ typestyle =
+ 'mso-number-format:"\\#\\,\\#\\#0\\\\ _р_\\.";white-space:normal;';
+ } else if (typeid == 'number') {
+ typestyle = ' ';
+ } else if (typeid == 'date') {
+ typestyle = 'mso-number-format:"Short Date";';
+ } else {
+ // For other types is saved
+ if (opts.types && opts.types[typeid] && opts.types[typeid].typestyle) {
+ typestyle = opts.types[typeid].typestyle;
+ }
+ }
+
+ // TODO Replace with extend...
+ typestyle = typestyle || 'mso-number-format:"\\@";'; // Default type style
+
+ s3 += '';
+
+ s3 += '';
+
+ // TODO Replace with extend...
+ var format = cell.format;
+ if (typeof value == 'undefined') {
+ s3 += '';
+ } else if (typeof format != 'undefined') {
+ if (typeof format == 'function') {
+ s3 += format(value);
+ } else if (typeof format == 'string') {
+ s3 += value; // TODO - add string format
+ } else {
+ throw new Error(
+ 'Unknown format type. Should be function or string'
+ );
+ }
+ } else {
+ if (typeid == 'number' || typeid == 'date') {
+ s3 += value.toString();
+ } else if (typeid == 'money') {
+ s3 += (+value).toFixed(2);
+ } else {
+ s3 += value;
+ }
+ }
+
+ // s3 += row[column.columnid];
+ s3 += ' | ';
+ });
+
+ s3 += '
';
+ });
+ }
+ // Finish
+ s3 += '
';
+ }
+
+ s3 += '';
+
+ return s1 + s2 + s3;
+ }
+};
+
+/**
+ Export to XLSX function
+ @function
+ @param {string|object} filename Filename or options
+ @param {object|undefined} opts Options or undefined
+ @param {array} data Data
+ @param {array} columns Columns
+ @parab {callback} cb Callback function
+ @return {number} Number of files processed
+*/
+
+alasql.into.XLSX = function(filename, opts, data, columns, cb) {
+ /** @type {number} result */
+ var res = 1;
+
+ if (deepEqual(columns, [{columnid: '_'}])) {
+ data = data.map(function(dat) {
+ return dat._;
+ });
+ columns = undefined;
+ // res = [{_:1}];
+ } else {
+ // data = data1;
+ }
+
+ filename = alasql.utils.autoExtFilename(filename, 'xlsx', opts);
+
+ var XLSX = getXLSX();
+
+ /* If called without filename, use opts */
+ if (typeof filename == 'object') {
+ opts = filename;
+ filename = undefined;
+ }
+
+ /** @type {object} Workbook */
+ var wb = {SheetNames: [], Sheets: {}};
+
+ // ToDo: check if cb must be treated differently here
+ if (opts.sourcefilename) {
+ alasql.utils.loadBinaryFile(opts.sourcefilename, !!cb, function(data) {
+ wb = XLSX.read(data, {type: 'binary'});
+ doExport();
+ });
+ } else {
+ doExport();
+ }
+
+ /* Return result */
+ if (cb) res = cb(res);
+ return res;
+
+ /**
+ Export workbook
+ @function
+ */
+ function doExport() {
+ /*
+ If opts is array of arrays then this is a
+ multisheet workboook, else it is a singlesheet
+ */
+ if (typeof opts == 'object' && Array.isArray(opts)) {
+ if (data && data.length > 0) {
+ data.forEach(function(dat, idx) {
+ prepareSheet(opts[idx], dat, undefined, idx + 1);
+ });
+ }
+ } else {
+ prepareSheet(opts, data, columns, 1);
+ }
+
+ saveWorkbook(cb);
+ }
+
+ /**
+ Prepare sheet
+ @params {object} opts
+ @params {array|object} data
+ @params {array} columns Columns
+ */
+ function prepareSheet(opts, data, columns, idx) {
+ /** Default options for sheet */
+ var opt = {sheetid: 'Sheet ' + idx, headers: true};
+ alasql.utils.extend(opt, opts);
+
+ var dataLength = Object.keys(data).length;
+
+ // Generate columns if they are not defined
+ if ((!columns || columns.length == 0) && dataLength > 0) {
+ columns = Object.keys(data[0]).map(function(columnid) {
+ return {columnid: columnid};
+ });
+ }
+
+ var cells = {};
+
+ if (wb.SheetNames.indexOf(opt.sheetid) > -1) {
+ cells = wb.Sheets[opt.sheetid];
+ } else {
+ wb.SheetNames.push(opt.sheetid);
+ wb.Sheets[opt.sheetid] = {};
+ cells = wb.Sheets[opt.sheetid];
+ }
+
+ var range = 'A1';
+ if (opt.range) range = opt.range;
+
+ var col0 = alasql.utils.xlscn(range.match(/[A-Z]+/)[0]);
+ var row0 = +range.match(/[0-9]+/)[0] - 1;
+
+ if (wb.Sheets[opt.sheetid]['!ref']) {
+ var rangem = wb.Sheets[opt.sheetid]['!ref'];
+ var colm = alasql.utils.xlscn(rangem.match(/[A-Z]+/)[0]);
+ var rowm = +rangem.match(/[0-9]+/)[0] - 1;
+ } else {
+ var colm = 1,
+ rowm = 1;
+ }
+ var colmax = Math.max(col0 + columns.length, colm);
+ var rowmax = Math.max(row0 + dataLength + 2, rowm);
+
+ var i = row0 + 1;
+
+ wb.Sheets[opt.sheetid]['!ref'] = 'A1:' + alasql.utils.xlsnc(colmax) + rowmax;
+ // var i = 1;
+
+ if (opt.headers) {
+ columns.forEach(function(col, idx) {
+ cells[alasql.utils.xlsnc(col0 + idx) + '' + i] = {v: col.columnid.trim()};
+ });
+ i++;
+ }
+
+ for (var j = 0; j < dataLength; j++) {
+ columns.forEach(function(col, idx) {
+ var cell = {v: data[j][col.columnid]};
+ if (typeof data[j][col.columnid] == 'number') {
+ cell.t = 'n';
+ } else if (typeof data[j][col.columnid] == 'string') {
+ cell.t = 's';
+ } else if (typeof data[j][col.columnid] == 'boolean') {
+ cell.t = 'b';
+ } else if (typeof data[j][col.columnid] == 'object') {
+ if (data[j][col.columnid] instanceof Date) {
+ cell.t = 'd';
+ }
+ }
+ cells[alasql.utils.xlsnc(col0 + idx) + '' + i] = cell;
+ });
+ i++;
+ }
+ }
+
+ /**
+ Save Workbook
+ @params {array} wb Workbook
+ @params {callback} cb Callback
+ */
+ function saveWorkbook(cb) {
+
+ var XLSX;
+
+ if (typeof filename == 'undefined') {
+ res = wb;
+ } else {
+ XLSX = getXLSX();
+
+ if (utils.isNode || utils.isMeteorServer) {
+ XLSX.writeFile(wb, filename);
+ } else {
+ var wopts = {bookType: 'xlsx', bookSST: false, type: 'binary'};
+ var wbout = XLSX.write(wb, wopts);
+
+ var s2ab = function(s) {
+ var buf = new ArrayBuffer(s.length);
+ var view = new Uint8Array(buf);
+ for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;
+ return buf;
+ };
+
+ /* the saveAs call downloads a file on the local machine */
+ // saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), '"'+filename+'"')
+ // saveAs(new Blob([s2ab(wbout)],{type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}), filename)
+ // saveAs(new Blob([s2ab(wbout)],{type:"application/vnd.ms-excel"}), '"'+filename+'"');
+ if (isIE() == 9) {
+ throw new Error(
+ 'Cannot save XLSX files in IE9. Please use XLS() export function'
+ );
+ // var URI = 'data:text/plain;charset=utf-8,';
+
+ /** @todo Check if this code is required */
+
+ // alert('ie9');
+ } else {
+ saveAs(new Blob([s2ab(wbout)], {type: 'application/octet-stream'}), filename);
+ }
+ }
+ }
+
+ }
+};
+
+/*
+//
+// FROM functions Alasql.js
+// Date: 11.12.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+/**
+ Meteor
+ */
+
+/* global alasql Tabletop document Event */
+
+alasql.from.METEOR = function(filename, opts, cb, idx, query) {
+ var res = filename.find(opts).fetch();
+ if (cb) {
+ res = cb(res, idx, query);
+ }
+ return res;
+};
+
+/**
+ Google Spreadsheet reader
+ */
+alasql.from.TABLETOP = function(key, opts, cb, idx, query) {
+ var res = [];
+
+ var opt = {headers: true, simpleSheet: true, key: key};
+ alasql.utils.extend(opt, opts);
+ opt.callback = function(data) {
+ res = data;
+ if (cb) {
+ res = cb(res, idx, query);
+ }
+ };
+
+ Tabletop.init(opt);
+ return null;
+};
+
+alasql.from.HTML = function(selector, opts, cb, idx, query) {
+ var opt = {};
+ alasql.utils.extend(opt, opts);
+
+ var sel = document.querySelector(selector);
+ if (!sel && sel.tagName !== 'TABLE') {
+ throw new Error('Selected HTML element is not a TABLE');
+ }
+
+ var res = [];
+ var headers = opt.headers;
+
+ if (headers && !Array.isArray(headers)) {
+ headers = [];
+ var ths = sel.querySelector('thead tr').children;
+ for (var i = 0; i < ths.length; i++) {
+ if (
+ !(ths.item(i).style && ths.item(i).style.display === 'none' && opt.skipdisplaynone)
+ ) {
+ headers.push(ths.item(i).textContent);
+ } else {
+ headers.push(undefined);
+ }
+ }
+ }
+
+ var trs = sel.querySelectorAll('tbody tr');
+
+ for (var j = 0; j < trs.length; j++) {
+ var tds = trs.item(j).children;
+ var r = {};
+ for (i = 0; i < tds.length; i++) {
+ if (
+ !(tds.item(i).style && tds.item(i).style.display === 'none' && opt.skipdisplaynone)
+ ) {
+ if (headers) {
+ r[headers[i]] = tds.item(i).textContent;
+ } else {
+ r[i] = tds.item(i).textContent;
+
+ }
+ }
+ }
+ res.push(r);
+ }
+
+ if (cb) {
+ res = cb(res, idx, query);
+ }
+ return res;
+};
+
+alasql.from.RANGE = function(start, finish, cb, idx, query) {
+ var res = [];
+ for (var i = start; i <= finish; i++) {
+ res.push(i);
+ }
+ // res = new alasql.Recordset({data:res,columns:{columnid:'_'}});
+ if (cb) {
+ res = cb(res, idx, query);
+ }
+ return res;
+};
+
+// Read data from any file
+alasql.from.FILE = function(filename, opts, cb, idx, query) {
+ var fname;
+ if (typeof filename === 'string') {
+ fname = filename;
+ } else if (filename instanceof Event) {
+ fname = filename.target.files[0].name;
+ } else {
+ throw new Error('Wrong usage of FILE() function');
+ }
+
+ var parts = fname.split('.');
+
+ var ext = parts[parts.length - 1].toUpperCase();
+
+ if (alasql.from[ext]) {
+
+ return alasql.from[ext](filename, opts, cb, idx, query);
+ } else {
+ throw new Error('Cannot recognize file type for loading');
+ }
+};
+
+// Read JSON file
+
+alasql.from.JSON = function(filename, opts, cb, idx, query) {
+ var res;
+
+ filename = alasql.utils.autoExtFilename(filename, 'json', opts);
+ alasql.utils.loadFile(filename, !!cb, function(data) {
+
+ // res = [{a:1}];
+ res = JSON.parse(data);
+ if (cb) {
+ res = cb(res, idx, query);
+ }
+ });
+ return res;
+};
+
+alasql.from.TXT = function(filename, opts, cb, idx, query) {
+ var res;
+ filename = alasql.utils.autoExtFilename(filename, 'txt', opts);
+ alasql.utils.loadFile(filename, !!cb, function(data) {
+ res = data.split(/\r?\n/);
+
+ // Remove last line if empty
+ if (res[res.length - 1] === '') {
+ res.pop();
+ }
+ for (var i = 0, ilen = res.length; i < ilen; i++) {
+ // Please avoid '===' here
+ if (res[i] == +res[i]) {
+ // eslint:ignore
+ // jshint ignore:line
+ res[i] = +res[i];
+ }
+ res[i] = [res[i]];
+ }
+ if (cb) {
+ res = cb(res, idx, query);
+ }
+ });
+ return res;
+};
+
+alasql.from.TAB = alasql.from.TSV = function(filename, opts, cb, idx, query) {
+ opts = opts || {};
+ opts.separator = '\t';
+ filename = alasql.utils.autoExtFilename(filename, 'tab', opts);
+ opts.autoext = false;
+ return alasql.from.CSV(filename, opts, cb, idx, query);
+};
+
+alasql.from.CSV = function(contents, opts, cb, idx, query) {
+ contents = ''+contents;
+ var opt = {
+ separator: ',',
+ quote: '"',
+ headers: true,
+ };
+ alasql.utils.extend(opt, opts);
+ var res;
+ var hs = [];
+ function parseText(text) {
+ var delimiterCode = opt.separator.charCodeAt(0);
+ var quoteCode = opt.quote.charCodeAt(0);
+
+ var EOL = {},
+ EOF = {},
+ rows = [],
+ N = text.length,
+ I = 0,
+ n = 0,
+ t,
+ eol;
+ function token() {
+ if (I >= N) {
+ return EOF;
+ }
+ if (eol) {
+ return (eol = false, EOL);
+ }
+ var j = I;
+ if (text.charCodeAt(j) === quoteCode) {
+ var i = j;
+ while (i++ < N) {
+ if (text.charCodeAt(i) === quoteCode) {
+ if (text.charCodeAt(i + 1) !== quoteCode) {
+ break;
+ }
+ ++i;
+ }
+ }
+ I = i + 2;
+ var c = text.charCodeAt(i + 1);
+ if (c === 13) {
+ eol = true;
+ if (text.charCodeAt(i + 2) === 10) {
+ ++I;
+ }
+ } else if (c === 10) {
+ eol = true;
+ }
+ return text.substring(j + 1, i).replace(/""/g, '"');
+ }
+ while (I < N) {
+ var c = text.charCodeAt(I++),
+ k = 1;
+ if (c === 10) {
+ eol = true;
+ } else if (c === 13) {
+ eol = true;
+ if (text.charCodeAt(I) === 10) {
+ ++I;
+ ++k;
+ }
+ } else if (c !== delimiterCode) {
+ continue;
+ }
+ return text.substring(j, I - k);
+ }
+ return text.substring(j);
+ }
+
+ while ((t = token()) !== EOF) {
+ var a = [];
+ while (t !== EOL && t !== EOF) {
+ a.push(t.trim());
+ t = token();
+ }
+
+ if (opt.headers) {
+ if (n === 0) {
+ if (typeof opt.headers === 'boolean') {
+ hs = a;
+ } else if (Array.isArray(opt.headers)) {
+ hs = opt.headers;
+ var r = {};
+ hs.forEach(function(h, idx) {
+ r[h] = a[idx];
+ // Please avoid === here
+ if (
+ typeof r[h] !== 'undefined' &&
+ r[h].length !== 0 &&
+ r[h].trim() == +r[h]
+ ) {
+ // jshint ignore:line
+ r[h] = +r[h];
+ }
+ });
+ rows.push(r);
+ }
+ } else {
+ var r = {};
+ hs.forEach(function(h, idx) {
+ r[h] = a[idx];
+ if (
+ typeof r[h] !== 'undefined' &&
+ r[h].length !== 0 &&
+ r[h].trim() == +r[h]
+ ) {
+ // jshint ignore:line
+ r[h] = +r[h];
+ }
+ });
+ rows.push(r);
+ }
+ n++;
+ } else {
+ rows.push(a);
+ }
+ }
+
+ res = rows;
+
+ if (opt.headers) {
+ if (query && query.sources && query.sources[idx]) {
+ var columns = (query.sources[idx].columns = []);
+ hs.forEach(function(h) {
+ columns.push({columnid: h});
+ });
+ }
+ }
+
+ if (cb) {
+ res = cb(res, idx, query);
+ }
+ }
+ if (new RegExp('\n').test(contents)) {
+ parseText(contents);
+ } else {
+ contents = alasql.utils.autoExtFilename(contents, 'csv', opts);
+ alasql.utils.loadFile(contents, !!cb, parseText, query.cb);
+ }
+ return res;
+};
+
+function XLSXLSX(X, filename, opts, cb, idx, query) {
+ var opt = {};
+ opts = opts || {};
+ alasql.utils.extend(opt, opts);
+ if (typeof opt.headers === 'undefined') {
+ opt.headers = true;
+ }
+ var res;
+
+ /**
+ * see https://github.com/SheetJS/js-xlsx/blob/5ae6b1965bfe3764656a96f536b356cd1586fec7/README.md
+ * for example of using readAsArrayBuffer under `Parsing Workbooks`
+ */
+ function fixdata(data) {
+ var o = '',
+ l = 0,
+ w = 10240;
+ for (; l < data.byteLength / w; ++l)
+ o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w, l * w + w)));
+ o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w)));
+ return o;
+ }
+ function getHeaderText(text) {
+ // if casesensitive option is set to false and there is a text value return lowercase value of text
+ if (text && alasql.options.casesensitive === false) {
+ return text.toLowerCase();
+ } else {
+ return text;
+ }
+ }
+ filename = alasql.utils.autoExtFilename(filename, 'xls', opts);
+ alasql.utils.loadBinaryFile(
+ filename,
+ !!cb,
+ function(data) {
+ // function processData(data) {
+ if (data instanceof ArrayBuffer) {
+ var arr = fixdata(data);
+ var workbook = X.read(btoa(arr), {type: 'base64'});
+ } else {
+ var workbook = X.read(data, {type: 'binary'});
+ }
+
+ var sheetid;
+ if (typeof opt.sheetid === 'undefined') {
+ sheetid = workbook.SheetNames[0];
+ } else if (typeof opt.sheetid === 'number') {
+ sheetid = workbook.SheetNames[opt.sheetid];
+ } else {
+ sheetid = opt.sheetid;
+ }
+ var range;
+ var res = [];
+ if (typeof opt.range === 'undefined') {
+ range = workbook.Sheets[sheetid]['!ref'];
+ } else {
+ range = opt.range;
+ if (workbook.Sheets[sheetid][range]) {
+ range = workbook.Sheets[sheetid][range];
+ }
+ }
+ // if range has some value then data is present in the current sheet
+ // else current sheet is empty
+ if (range) {
+ var rg = range.split(':');
+ var col0 = rg[0].match(/[A-Z]+/)[0];
+ var row0 = +rg[0].match(/[0-9]+/)[0];
+ var col1 = rg[1].match(/[A-Z]+/)[0];
+ var row1 = +rg[1].match(/[0-9]+/)[0];
+
+ var hh = {};
+ var xlscnCol0 = alasql.utils.xlscn(col0);
+ var xlscnCol1 = alasql.utils.xlscn(col1);
+ for (var j = xlscnCol0; j <= xlscnCol1; j++) {
+ var col = alasql.utils.xlsnc(j);
+ if (opt.headers) {
+ if (workbook.Sheets[sheetid][col + '' + row0]) {
+ hh[col] = getHeaderText(workbook.Sheets[sheetid][col + '' + row0].v);
+ } else {
+ hh[col] = getHeaderText(col);
+ }
+ } else {
+ hh[col] = col;
+ }
+ }
+ if (opt.headers) {
+ row0++;
+ }
+ for (var i = row0; i <= row1; i++) {
+ var row = {};
+ for (var j = xlscnCol0; j <= xlscnCol1; j++) {
+ var col = alasql.utils.xlsnc(j);
+ if (workbook.Sheets[sheetid][col + '' + i]) {
+ row[hh[col]] = workbook.Sheets[sheetid][col + '' + i].v;
+ }
+ }
+ res.push(row);
+ }
+ } else {
+ res.push([]);
+ }
+
+ // Remove last empty line (issue #548)
+ if (
+ res.length > 0 &&
+ res[res.length - 1] &&
+ Object.keys(res[res.length - 1]).length == 0
+ ) {
+ res.pop();
+ }
+
+ if (cb) {
+ res = cb(res, idx, query);
+ }
+ },
+ function(err) {
+ throw err;
+ }
+ );
+
+ return res;
+}
+
+alasql.from.XLS = function(filename, opts, cb, idx, query) {
+ opts = opts || {};
+ filename = alasql.utils.autoExtFilename(filename, 'xls', opts);
+ opts.autoExt = false;
+ return XLSXLSX(getXLSX(), filename, opts, cb, idx, query);
+};
+
+alasql.from.XLSX = function(filename, opts, cb, idx, query) {
+ opts = opts || {};
+ filename = alasql.utils.autoExtFilename(filename, 'xlsx', opts);
+ opts.autoExt = false;
+ return XLSXLSX(getXLSX(), filename, opts, cb, idx, query);
+};
+
+alasql.from.ODS = function(filename, opts, cb, idx, query) {
+ opts = opts || {};
+ filename = alasql.utils.autoExtFilename(filename, 'ods', opts);
+ opts.autoExt = false;
+ return XLSXLSX(getXLSX(), filename, opts, cb, idx, query);
+};
+
+alasql.from.XML = function(filename, opts, cb, idx, query) {
+ var res;
+
+ alasql.utils.loadFile(filename, !!cb, function(data) {
+
+ // res = [{a:1}];
+
+ res = xmlparse(data).root;
+
+ if (cb) res = cb(res, idx, query);
+ });
+ return res;
+};
+
+/**
+ * Parse the given string of `xml`.
+ *
+ * @param {String} xml
+ * @return {Object}
+ * @api public
+ */
+
+function xmlparse(xml) {
+ xml = xml.trim();
+
+ // strip comments
+ xml = xml.replace(//g, '');
+
+ return document();
+
+ /**
+ * XML document.
+ */
+
+ function document() {
+ return {
+ declaration: declaration(),
+ root: tag(),
+ };
+ }
+
+ /**
+ * Declaration.
+ */
+
+ function declaration() {
+ var m = match(/^<\?xml\s*/);
+ if (!m) return;
+
+ // tag
+ var node = {
+ attributes: {},
+ };
+
+ // attributes
+ while (!(eos() || is('?>'))) {
+ var attr = attribute();
+ if (!attr) return node;
+ node.attributes[attr.name] = attr.value;
+ }
+
+ match(/\?>\s*/);
+
+ return node;
+ }
+
+ /**
+ * Tag.
+ */
+
+ function tag() {
+ var m = match(/^<([\w-:.]+)\s*/);
+ if (!m) return;
+
+ // name
+ var node = {
+ name: m[1],
+ attributes: {},
+ children: [],
+ };
+
+ // attributes
+ while (!(eos() || is('>') || is('?>') || is('/>'))) {
+ var attr = attribute();
+ if (!attr) return node;
+ node.attributes[attr.name] = attr.value;
+ }
+
+ // self closing tag
+ if (match(/^\s*\/>\s*/)) {
+ return node;
+ }
+
+ match(/\??>\s*/);
+
+ // content
+ node.content = content();
+
+ // children
+ var child;
+ while ((child = tag())) {
+ node.children.push(child);
+ }
+
+ // closing
+ match(/^<\/[\w-:.]+>\s*/);
+
+ return node;
+ }
+
+ /**
+ * Text content.
+ */
+
+ function content() {
+ var m = match(/^([^<]*)/);
+ if (m) return m[1];
+ return '';
+ }
+
+ /**
+ * Attribute.
+ */
+
+ function attribute() {
+ var m = match(/([\w:-]+)\s*=\s*("[^"]*"|'[^']*'|\w+)\s*/);
+ if (!m) return;
+ return {name: m[1], value: strip(m[2])};
+ }
+
+ /**
+ * Strip quotes from `val`.
+ */
+
+ function strip(val) {
+ return val.replace(/^['"]|['"]$/g, '');
+ }
+
+ /**
+ * Match `re` and advance the string.
+ */
+
+ function match(re) {
+ var m = xml.match(re);
+ if (!m) return;
+ xml = xml.slice(m[0].length);
+ return m;
+ }
+
+ /**
+ * End-of-source.
+ */
+
+ function eos() {
+ return 0 == xml.length;
+ }
+
+ /**
+ * Check for `prefix`.
+ */
+
+ function is(prefix) {
+ return 0 == xml.indexOf(prefix);
+ }
+}
+
+alasql.from.GEXF = function(filename, opts, cb, idx, query) {
+ var res;
+ alasql('SEARCH FROM XML(' + filename + ')', [], function(data) {
+ res = data;
+
+ if (cb) res = cb(res);
+ });
+ return res;
+};
+
+/*
+//
+// HELP for Alasql.js
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+/* globals: alasql, yy */
+
+/**
+ Print statement
+ @class
+ @param {object} params Initial setup properties
+*/
+
+/* global alasql, yy */
+
+yy.Print = function(params) {
+ return yy.extend(this, params);
+};
+
+/**
+ Generate SQL string
+ @this Print statement object
+*/
+yy.Print.prototype.toString = function() {
+ var s = 'PRINT';
+ if (this.statement) s += ' ' + this.statement.toString();
+ return s;
+};
+
+/**
+ Print result of select statement or expression
+ @param {string} databaseid Database identificator
+ @param {object} params Query parameters
+ @param {statement-callback} cb Callback function
+ @this Print statement object
+*/
+yy.Print.prototype.execute = function(databaseid, params, cb) {
+
+ var self = this;
+ var res = 1;
+
+ alasql.precompile(this, databaseid, params); /** @todo Change from alasql to this */
+
+ if (this.exprs && this.exprs.length > 0) {
+ var rs = this.exprs.map(function(expr) {
+
+ var exprfn = new Function(
+ 'params,alasql,p',
+ 'var y;return ' + expr.toJS('({})', '', null)
+ ).bind(self);
+ var r = exprfn(params, alasql);
+ return JSONtoString(r);
+ });
+ console.log.apply(console, rs);
+ } else if (this.select) {
+ var r = this.select.execute(databaseid, params);
+ console.log(JSONtoString(r));
+ } else {
+ console.log();
+ }
+
+ if (cb) res = cb(res);
+ return res;
+};
+
+/*
+//
+// HELP for Alasql.js
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+yy.Source = function(params) {
+ return yy.extend(this, params);
+};
+yy.Source.prototype.toString = function() {
+ var s = 'SOURCE';
+ if (this.url) s += " '" + this.url + " '";
+ return s;
+};
+
+// SOURCE FILE
+yy.Source.prototype.execute = function(databaseid, params, cb) {
+
+ var res;
+ loadFile(
+ this.url,
+ !!cb,
+ function(data) {
+
+ // res = 1;
+ res = alasql(data);
+ if (cb) res = cb(res);
+ return res;
+ },
+ function(err) {
+ throw err;
+ }
+ );
+ return res;
+};
+
+/*
+//
+// HELP for Alasql.js
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+/* global alasql, yy */
+
+yy.Require = function(params) {
+ return yy.extend(this, params);
+};
+yy.Require.prototype.toString = function() {
+ var s = 'REQUIRE';
+ if (this.paths && this.paths.length > 0) {
+ s += this.paths
+ .map(function(path) {
+ return path.toString();
+ })
+ .join(',');
+ }
+ if (this.plugins && this.plugins.length > 0) {
+ s += this.plugins
+ .map(function(plugin) {
+ return plugin.toUpperCase();
+ })
+ .join(',');
+ }
+ return s;
+};
+
+/**
+ Attach plug-in for Alasql
+ */
+yy.Require.prototype.execute = function(databaseid, params, cb) {
+ var self = this;
+ var res = 0;
+ var ss = '';
+
+ if (this.paths && this.paths.length > 0) {
+ this.paths.forEach(function(path) {
+ loadFile(path.value, !!cb, function(data) {
+ res++;
+
+ ss += data;
+ if (res < self.paths.length) return;
+
+ new Function('params,alasql', ss)(params, alasql);
+ if (cb) res = cb(res);
+ });
+ });
+ } else if (this.plugins && this.plugins.length > 0) {
+ this.plugins.forEach(function(plugin) {
+ // If plugin is not loaded already
+ if (!alasql.plugins[plugin]) {
+ loadFile(alasql.path + '/alasql-' + plugin.toLowerCase() + '.js', !!cb, function(
+ data
+ ) {
+ // Execute all plugins at the same time
+ res++;
+ ss += data;
+ if (res < self.plugins.length) return;
+
+ new Function('params,alasql', ss)(params, alasql);
+ alasql.plugins[plugin] = true; // Plugin is loaded
+ if (cb) res = cb(res);
+ });
+ }
+ });
+ } else {
+ if (cb) res = cb(res);
+ }
+ return res;
+};
+
+/*
+//
+// HELP for Alasql.js
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+yy.Assert = function(params) {
+ return yy.extend(this, params);
+};
+yy.Source.prototype.toString = function() {
+ var s = 'ASSERT';
+ if (this.value) s += ' ' + JSON.stringify(this.value);
+ return s;
+};
+
+// SOURCE FILE
+yy.Assert.prototype.execute = function(databaseid) {
+
+ if (!deepEqual(alasql.res, this.value)) {
+ // if(this.message) {
+ // throw this.
+ // } else {
+ throw new Error(
+ (this.message || 'Assert wrong') +
+ ': ' +
+ JSON.stringify(alasql.res) +
+ ' == ' +
+ JSON.stringify(this.value)
+ );
+ // }
+ }
+ return 1;
+};
+
+//
+// 91websql.js
+// WebSQL database support
+// (c) 2014, Andrey Gershun
+//
+
+var WEBSQL = (alasql.engines.WEBSQL = function () {});
+
+WEBSQL.createDatabase = function (wdbid, args, dbid, cb) {
+ var res = 1;
+ var wdb = openDatabase(wdbid, args[0], args[1], args[2]);
+ if (this.dbid) {
+ var db = alasql.createDatabase(this.dbid);
+ db.engineid = 'WEBSQL';
+ db.wdbid = wdbid;
+ db.wdb = db;
+ }
+ if (!wdb) {
+ throw new Error('Cannot create WebSQL database "' + this.dbid + '"');
+ }
+ if (cb) cb(res);
+ return res;
+};
+
+WEBSQL.dropDatabase = function (databaseid) {
+ throw new Error('This is impossible to drop WebSQL database.');
+};
+
+WEBSQL.attachDatabase = function (databaseid, dbid, args, params, cb) {
+ var res = 1;
+ if (alasql.databases[dbid]) {
+ throw new Error('Unable to attach database as "' + dbid + '" because it already exists');
+ }
+ alasql.openDatabase(databaseid, args[0], args[1], args[2]);
+ return res;
+};
+
+//
+// 91indexeddb.js
+// AlaSQL IndexedDB module
+// Date: 18.04.2015
+// (c) Andrey Gershun
+//
+
+/* global alasql, yy, utils*/
+
+var IDB = (alasql.engines.INDEXEDDB = function() {
+ '';
+});
+
+if (utils.hasIndexedDB) {
+ // For Chrome it work normally, for Firefox - simple shim
+ if (typeof utils.global.indexedDB.webkitGetDatabaseNames == 'function') {
+ IDB.getDatabaseNames = utils.global.indexedDB.webkitGetDatabaseNames.bind(
+ utils.global.indexedDB
+ );
+ } else {
+ IDB.getDatabaseNames = function() {
+ var request = {};
+ var result = {
+ contains: function(name) {
+ return true; // Always return true
+ },
+ notsupported: true,
+ };
+ setTimeout(function() {
+ var event = {target: {result: result}};
+ request.onsuccess(event);
+ }, 0);
+ return request;
+ };
+ IDB.getDatabaseNamesNotSupported = true;
+ }
+}
+
+//
+// SHOW DATABASES
+// work only in chrome
+//
+IDB.showDatabases = function(like, cb) {
+
+ var request = IDB.getDatabaseNames();
+ request.onsuccess = function(event) {
+ var dblist = event.target.result;
+ if (IDB.getDatabaseNamesNotSupported) {
+ throw new Error('SHOW DATABASE is not supported in this browser');
+ }
+ var res = [];
+ if (like) {
+ var relike = new RegExp(like.value.replace(/\%/g, '.*'), 'g');
+ }
+ for (var i = 0; i < dblist.length; i++) {
+ if (!like || dblist[i].match(relike)) {
+ res.push({databaseid: dblist[i]});
+ }
+ }
+ cb(res);
+ };
+};
+
+IDB.createDatabase = function(ixdbid, args, ifnotexists, dbid, cb) {
+
+ var indexedDB = utils.global.indexedDB;
+ if (ifnotexists) {
+ var request2 = indexedDB.open(ixdbid, 1);
+ request2.onsuccess = function(event) {
+ event.target.result.close();
+ if (cb) cb(1);
+ };
+ } else {
+ var request1 = indexedDB.open(ixdbid, 1);
+ request1.onupgradeneeded = function(e) {
+
+ e.target.transaction.abort();
+ };
+ request1.onsuccess = function(e) {
+
+ if (ifnotexists) {
+ if (cb) cb(0);
+ } else {
+ throw new Error(
+ 'IndexedDB: Cannot create new database "' +
+ ixdbid +
+ '" because it already exists'
+ );
+ }
+ };
+ }
+
+};
+
+IDB.createDatabase = function(ixdbid, args, ifnotexists, dbid, cb) {
+ var indexedDB = utils.global.indexedDB;
+ if (IDB.getDatabaseNamesNotSupported) {
+ // Hack for Firefox
+ if (ifnotexists) {
+
+ var dbExists = true;
+ var request2 = indexedDB.open(ixdbid);
+
+ request2.onupgradeneeded = function(e) {
+
+ dbExists = false;
+ // e.target.transaction.abort();
+ // cb(0);
+ };
+ request2.onsuccess = function(event) {
+
+ event.target.result.close();
+ if (dbExists) {
+ if (cb) cb(0);
+ } else {
+ if (cb) cb(1);
+ }
+ };
+ } else {
+
+ var request1 = indexedDB.open(ixdbid);
+ request1.onupgradeneeded = function(e) {
+ e.target.transaction.abort();
+ };
+ request1.onabort = function(event) {
+ if (cb) cb(1);
+ };
+ request1.onsuccess = function(event) {
+ event.target.result.close();
+ throw new Error(
+ 'IndexedDB: Cannot create new database "' +
+ ixdbid +
+ '" because it already exists'
+ );
+ // cb(0);
+ };
+ }
+ } else {
+ var request1 = IDB.getDatabaseNames();
+ request1.onsuccess = function(event) {
+ var dblist = event.target.result;
+ if (dblist.contains(ixdbid)) {
+ if (ifnotexists) {
+ if (cb) cb(0);
+ return;
+ } else {
+ throw new Error(
+ 'IndexedDB: Cannot create new database "' +
+ ixdbid +
+ '" because it already exists'
+ );
+ }
+ }
+
+ var request2 = indexedDB.open(ixdbid, 1);
+ request2.onsuccess = function(event) {
+ event.target.result.close();
+ if (cb) cb(1);
+ };
+ };
+ }
+};
+
+IDB.dropDatabase = function(ixdbid, ifexists, cb) {
+ var indexedDB = utils.global.indexedDB;
+ var request1 = IDB.getDatabaseNames();
+ request1.onsuccess = function(event) {
+ var dblist = event.target.result;
+ if (!dblist.contains(ixdbid)) {
+ if (ifexists) {
+ if (cb) cb(0);
+ return;
+ } else {
+ throw new Error(
+ 'IndexedDB: Cannot drop new database "' + ixdbid + '" because it does not exist'
+ );
+ }
+ }
+ var request2 = indexedDB.deleteDatabase(ixdbid);
+ request2.onsuccess = function(event) {
+
+ if (cb) cb(1);
+ };
+ };
+};
+
+IDB.attachDatabase = function(ixdbid, dbid, args, params, cb) {
+ if (!utils.hasIndexedDB) {
+ throw new Error('The current browser does not support IndexedDB');
+ }
+ var indexedDB = utils.global.indexedDB;
+ var request1 = IDB.getDatabaseNames();
+ request1.onsuccess = function(event) {
+ var dblist = event.target.result;
+ if (!dblist.contains(ixdbid)) {
+ throw new Error(
+ 'IndexedDB: Cannot attach database "' + ixdbid + '" because it does not exist'
+ );
+ }
+ var request2 = indexedDB.open(ixdbid);
+ request2.onsuccess = function(event) {
+ var ixdb = event.target.result;
+ var db = new alasql.Database(dbid || ixdbid);
+ db.engineid = 'INDEXEDDB';
+ db.ixdbid = ixdbid;
+ db.tables = [];
+ var tblist = ixdb.objectStoreNames;
+ for (var i = 0; i < tblist.length; i++) {
+ db.tables[tblist[i]] = {};
+ }
+
+ event.target.result.close();
+ if (cb) cb(1);
+ };
+ };
+};
+
+IDB.createTable = function(databaseid, tableid, ifnotexists, cb) {
+ var indexedDB = utils.global.indexedDB;
+
+ var ixdbid = alasql.databases[databaseid].ixdbid;
+
+ var request1 = IDB.getDatabaseNames();
+ request1.onsuccess = function(event__) {
+ var dblist = event__.target.result;
+ if (!dblist.contains(ixdbid)) {
+ throw new Error(
+ 'IndexedDB: Cannot create table in database "' +
+ ixdbid +
+ '" because it does not exist'
+ );
+ }
+ var request2 = indexedDB.open(ixdbid);
+ request2.onversionchange = function(event_) {
+
+ event_.target.result.close();
+ };
+ request2.onsuccess = function(event_) {
+ var version = event_.target.result.version;
+ event_.target.result.close();
+
+ var request3 = indexedDB.open(ixdbid, version + 1);
+ request3.onupgradeneeded = function(event) {
+ var ixdb = event.target.result;
+
+ var store = ixdb.createObjectStore(tableid, {autoIncrement: true});
+
+ };
+ request3.onsuccess = function(event) {
+
+ event.target.result.close();
+ if (cb) cb(1);
+ };
+ request3.onerror = function(event) {
+ throw event;
+
+ };
+ request3.onblocked = function(event) {
+ throw new Error(
+ 'Cannot create table "' +
+ tableid +
+ '" because database "' +
+ databaseid +
+ '" is blocked'
+ );
+
+ };
+ };
+ };
+};
+
+IDB.dropTable = function(databaseid, tableid, ifexists, cb) {
+ var indexedDB = utils.global.indexedDB;
+ var ixdbid = alasql.databases[databaseid].ixdbid;
+
+ var request1 = IDB.getDatabaseNames();
+ request1.onsuccess = function(event) {
+ var dblist = event.target.result;
+
+ if (!dblist.contains(ixdbid)) {
+ throw new Error(
+ 'IndexedDB: Cannot drop table in database "' +
+ ixdbid +
+ '" because it does not exist'
+ );
+ }
+
+ var request2 = indexedDB.open(ixdbid);
+ request2.onversionchange = function(event) {
+ event.target.result.close();
+ };
+
+ request2.onsuccess = function(event) {
+ var version = event.target.result.version;
+ event.target.result.close();
+
+ var request3 = indexedDB.open(ixdbid, version + 1);
+ request3.onupgradeneeded = function(event) {
+ var ixdb = event.target.result;
+ if (ixdb.objectStoreNames.contains(tableid)) {
+ ixdb.deleteObjectStore(tableid);
+ delete alasql.databases[databaseid].tables[tableid];
+ } else {
+ if (!ifexists) {
+ throw new Error(
+ 'IndexedDB: Cannot drop table "' +
+ tableid +
+ '" because it does not exist'
+ );
+ }
+ }
+ // var store = ixdb.createObjectStore(tableid);
+
+ };
+ request3.onsuccess = function(event) {
+
+ event.target.result.close();
+ if (cb) cb(1);
+ };
+ request3.onerror = function(event) {
+
+ throw event;
+ };
+ request3.onblocked = function(event) {
+ throw new Error(
+ 'Cannot drop table "' +
+ tableid +
+ '" because database "' +
+ databaseid +
+ '" is blocked'
+ );
+
+ };
+ };
+ };
+};
+
+IDB.intoTable = function(databaseid, tableid, value, columns, cb) {
+
+ // console.trace();
+
+ var indexedDB = utils.global.indexedDB;
+ var ixdbid = alasql.databases[databaseid].ixdbid;
+ var request1 = indexedDB.open(ixdbid);
+ request1.onsuccess = function(event) {
+ var ixdb = event.target.result;
+ var tx = ixdb.transaction([tableid], 'readwrite');
+ var tb = tx.objectStore(tableid);
+
+ for (var i = 0, ilen = value.length; i < ilen; i++) {
+ tb.add(value[i]);
+ }
+ tx.oncomplete = function() {
+ ixdb.close();
+
+ if (cb) cb(ilen);
+ };
+ };
+
+};
+
+IDB.fromTable = function(databaseid, tableid, cb, idx, query) {
+
+ // console.trace();
+ var indexedDB = utils.global.indexedDB;
+ var ixdbid = alasql.databases[databaseid].ixdbid;
+ var request = indexedDB.open(ixdbid);
+ request.onsuccess = function(event) {
+ var res = [];
+ var ixdb = event.target.result;
+
+ var tx = ixdb.transaction([tableid]);
+ var store = tx.objectStore(tableid);
+ var cur = store.openCursor();
+
+ cur.onblocked = function(event) {
+
+ };
+ cur.onerror = function(event) {
+
+ };
+ cur.onsuccess = function(event) {
+
+ var cursor = event.target.result;
+
+ if (cursor) {
+ res.push(cursor.value);
+ cursor["continue"]();
+ } else {
+
+ ixdb.close();
+ if (cb) cb(res, idx, query);
+ }
+ };
+ };
+};
+
+IDB.deleteFromTable = function(databaseid, tableid, wherefn, params, cb) {
+
+ // console.trace();
+ var indexedDB = utils.global.indexedDB;
+ var ixdbid = alasql.databases[databaseid].ixdbid;
+ var request = indexedDB.open(ixdbid);
+ request.onsuccess = function(event) {
+ var res = [];
+ var ixdb = event.target.result;
+
+ var tx = ixdb.transaction([tableid], 'readwrite');
+ var store = tx.objectStore(tableid);
+ var cur = store.openCursor();
+ var num = 0;
+
+ cur.onblocked = function(event) {
+
+ };
+ cur.onerror = function(event) {
+
+ };
+ cur.onsuccess = function(event) {
+
+ var cursor = event.target.result;
+
+ if (cursor) {
+ if (!wherefn || wherefn(cursor.value, params)) {
+
+ cursor["delete"]();
+ num++;
+ }
+ cursor["continue"]();
+ } else {
+
+ ixdb.close();
+ if (cb) cb(num);
+ }
+ };
+ };
+};
+
+IDB.updateTable = function(databaseid, tableid, assignfn, wherefn, params, cb) {
+
+ // console.trace();
+ var indexedDB = utils.global.indexedDB;
+ var ixdbid = alasql.databases[databaseid].ixdbid;
+ var request = indexedDB.open(ixdbid);
+ request.onsuccess = function(event) {
+ var res = [];
+ var ixdb = event.target.result;
+
+ var tx = ixdb.transaction([tableid], 'readwrite');
+ var store = tx.objectStore(tableid);
+ var cur = store.openCursor();
+ var num = 0;
+
+ cur.onblocked = function(event) {
+
+ };
+ cur.onerror = function(event) {
+
+ };
+ cur.onsuccess = function(event) {
+
+ var cursor = event.target.result;
+
+ if (cursor) {
+ if (!wherefn || wherefn(cursor.value, params)) {
+
+ var r = cursor.value;
+ assignfn(r, params);
+
+ cursor.update(r);
+ num++;
+ }
+ cursor["continue"]();
+ } else {
+
+ ixdb.close();
+ if (cb) cb(num);
+ }
+ };
+ };
+};
+
+//
+// 91localstorage.js
+// localStorage and DOM-Storage engine
+// Date: 09.12.2014
+// (c) Andrey Gershun
+//
+
+/* global alasql, yy, localStorage*/
+
+var LS = (alasql.engines.LOCALSTORAGE = function() {});
+
+/**
+ Read data from localStorage with security breaks
+ @param key {string} Address in localStorage
+ @return {object} JSON object
+*/
+LS.get = function(key) {
+ var s = localStorage.getItem(key);
+ if (typeof s === 'undefined') return;
+ var v;
+ try {
+ v = JSON.parse(s);
+ } catch (err) {
+ throw new Error('Cannot parse JSON object from localStorage' + s);
+ }
+ return v;
+};
+
+/**
+ Store data into localStorage with security breaks
+ @param key {string} Address in localStorage
+ @return {object} JSON object
+*/
+LS.set = function(key, value) {
+ if (typeof value === 'undefined') localStorage.removeItem(key);
+ else localStorage.setItem(key, JSON.stringify(value));
+};
+
+/**
+ Store table structure and data into localStorage
+ @param databaseid {string} AlaSQL database id (not external localStorage)
+ @param tableid {string} Table name
+ @return Nothing
+*/
+LS.storeTable = function(databaseid, tableid) {
+ var db = alasql.databases[databaseid];
+ var table = db.tables[tableid];
+ // Create empty structure for table
+ var tbl = {};
+ tbl.columns = table.columns;
+ tbl.data = table.data;
+ tbl.identities = table.identities;
+ // TODO: May be add indexes, objects and other fields?
+ LS.set(db.lsdbid + '.' + tableid, tbl);
+};
+
+/**
+ Restore table structure and data
+ @param databaseid {string} AlaSQL database id (not external localStorage)
+ @param tableid {string} Table name
+ @return Nothing
+*/
+LS.restoreTable = function(databaseid, tableid) {
+ var db = alasql.databases[databaseid];
+ var tbl = LS.get(db.lsdbid + '.' + tableid);
+ var table = new alasql.Table();
+ for (var f in tbl) {
+ table[f] = tbl[f];
+ }
+ db.tables[tableid] = table;
+ table.indexColumns();
+ // We need to add other things here
+ return table;
+};
+
+/**
+ Remove table from localStorage
+ @param databaseid {string} AlaSQL database id (not external localStorage)
+ @param tableid {string} Table name
+*/
+
+LS.removeTable = function(databaseid, tableid) {
+ var db = alasql.databases[databaseid];
+ localStorage.removeItem(db.lsdbid + '.' + tableid);
+};
+
+/**
+ Create database in localStorage
+ @param lsdbid {string} localStorage database id
+ @param args {array} List of parameters (not used in localStorage)
+ @param ifnotexists {boolean} Check if database does not exist
+ @param databaseid {string} AlaSQL database id (not external localStorage)
+ @param cb {function} Callback
+*/
+
+LS.createDatabase = function(lsdbid, args, ifnotexists, databaseid, cb) {
+ var res = 1;
+ var ls = LS.get('alasql'); // Read list of all databases
+ if (!(ifnotexists && ls && ls.databases && ls.databases[lsdbid])) {
+ if (!ls) ls = {databases: {}}; // Empty record
+ if (ls.databases && ls.databases[lsdbid]) {
+ throw new Error(
+ 'localStorage: Cannot create new database "' +
+ lsdbid +
+ '" because it already exists'
+ );
+ }
+ ls.databases[lsdbid] = true;
+ LS.set('alasql', ls);
+ LS.set(lsdbid, {databaseid: lsdbid, tables: {}}); // Create database record
+ } else {
+ res = 0;
+ }
+ if (cb) res = cb(res);
+ return res;
+};
+
+/**
+ Drop external database
+ @param lsdbid {string} localStorage database id
+ @param ifexists {boolean} Check if database exists
+ @param cb {function} Callback
+*/
+LS.dropDatabase = function(lsdbid, ifexists, cb) {
+ var res = 1;
+ var ls = LS.get('alasql');
+ if (!(ifexists && ls && ls.databases && !ls.databases[lsdbid])) {
+ // 1. Remove record from 'alasql' record
+ if (!ls) {
+ if (!ifexists) {
+ throw new Error('There is no any AlaSQL databases in localStorage');
+ } else {
+ return cb ? cb(0) : 0;
+ }
+ }
+
+ if (ls.databases && !ls.databases[lsdbid]) {
+ throw new Error(
+ 'localStorage: Cannot drop database "' +
+ lsdbid +
+ '" because there is no such database'
+ );
+ }
+ delete ls.databases[lsdbid];
+ LS.set('alasql', ls);
+
+ // 2. Remove tables definitions
+ var db = LS.get(lsdbid);
+ for (var tableid in db.tables) {
+ localStorage.removeItem(lsdbid + '.' + tableid);
+ }
+
+ // 3. Remove database definition
+ localStorage.removeItem(lsdbid);
+ } else {
+ res = 0;
+ }
+ if (cb) res = cb(res);
+ return res;
+};
+
+/**
+ Attach existing localStorage database to AlaSQL database
+ @param lsdibid {string} localStorage database id
+ @param
+*/
+
+LS.attachDatabase = function(lsdbid, databaseid, args, params, cb) {
+ var res = 1;
+ if (alasql.databases[databaseid]) {
+ throw new Error(
+ 'Unable to attach database as "' + databaseid + '" because it already exists'
+ );
+ }
+ if (!databaseid) databaseid = lsdbid;
+ var db = new alasql.Database(databaseid);
+ db.engineid = 'LOCALSTORAGE';
+ db.lsdbid = lsdbid;
+ db.tables = LS.get(lsdbid).tables;
+ // IF AUTOABORT IS OFF then copy data to memory
+ if (!alasql.options.autocommit) {
+ if (db.tables) {
+ for (var tbid in db.tables) {
+ LS.restoreTable(databaseid, tbid);
+ // db.tables[tbid].data = LS.get(db.lsdbid+'.'+tbid);
+ }
+ }
+ }
+ if (cb) res = cb(res);
+ return res;
+};
+
+/**
+ Show list of databases from localStorage
+ @param like {string} Mathing pattern
+ @param cb {function} Callback
+*/
+LS.showDatabases = function(like, cb) {
+ var res = [];
+ var ls = LS.get('alasql');
+ if (like) {
+ // TODO: If we have a special function for LIKE patterns?
+ var relike = new RegExp(like.value.replace(/%/g, '.*'), 'g');
+ }
+ if (ls && ls.databases) {
+ for (var dbid in ls.databases) {
+ res.push({databaseid: dbid});
+ }
+ if (like && res && res.length > 0) {
+ res = res.filter(function(d) {
+ return d.databaseid.match(relike);
+ });
+ }
+ }
+ if (cb) res = cb(res);
+ return res;
+};
+
+/**
+ Create table in localStorage database
+ @param databaseid {string} AlaSQL database id
+ @param tableid {string} Table id
+ @param ifnotexists {boolean} If not exists flag
+ @param cb {function} Callback
+*/
+
+LS.createTable = function(databaseid, tableid, ifnotexists, cb) {
+ var res = 1;
+ var lsdbid = alasql.databases[databaseid].lsdbid;
+ var tb = LS.get(lsdbid + '.' + tableid);
+ // Check if such record exists
+ if (tb && !ifnotexists) {
+ throw new Error(
+ 'Table "' + tableid + '" alsready exists in localStorage database "' + lsdbid + '"'
+ );
+ }
+ var lsdb = LS.get(lsdbid);
+ var table = alasql.databases[databaseid].tables[tableid];
+
+ // TODO: Check if required
+ lsdb.tables[tableid] = true;
+
+ LS.set(lsdbid, lsdb);
+ LS.storeTable(databaseid, tableid);
+
+ if (cb) res = cb(res);
+ return res;
+};
+
+/**
+ Empty table and reset identities
+ @param databaseid {string} AlaSQL database id (not external localStorage)
+ @param tableid {string} Table name
+ @param ifexists {boolean} If exists flag
+ @param cb {function} Callback
+ @return 1 on success
+*/
+LS.truncateTable = function(databaseid, tableid, ifexists, cb) {
+ var res = 1;
+ var lsdbid = alasql.databases[databaseid].lsdbid;
+ var lsdb;
+ if (alasql.options.autocommit) {
+ lsdb = LS.get(lsdbid);
+ } else {
+ lsdb = alasql.databases[databaseid];
+ }
+
+ if (!ifexists && !lsdb.tables[tableid]) {
+ throw new Error(
+ 'Cannot truncate table "' + tableid + '" in localStorage, because it does not exist'
+ );
+ }
+
+ //load table
+ var tbl = LS.restoreTable(databaseid, tableid);
+
+ //clear data from table
+ tbl.data = [];
+ //TODO reset all identities
+ //but identities are not working on LOCALSTORAGE
+ //See test 607 for details
+
+ //store table
+ LS.storeTable(databaseid, tableid);
+
+ if (cb) res = cb(res);
+ return res;
+};
+
+/**
+ Create table in localStorage database
+ @param databaseid {string} AlaSQL database id
+ @param tableid {string} Table id
+ @param ifexists {boolean} If exists flag
+ @param cb {function} Callback
+*/
+
+LS.dropTable = function(databaseid, tableid, ifexists, cb) {
+ var res = 1;
+ var lsdbid = alasql.databases[databaseid].lsdbid;
+ var lsdb;
+
+ if (alasql.options.autocommit) {
+ lsdb = LS.get(lsdbid);
+ } else {
+ lsdb = alasql.databases[databaseid];
+ }
+ if (!ifexists && !lsdb.tables[tableid]) {
+ throw new Error(
+ 'Cannot drop table "' + tableid + '" in localStorage, because it does not exist'
+ );
+ }
+ delete lsdb.tables[tableid];
+ LS.set(lsdbid, lsdb);
+ // localStorage.removeItem(lsdbid+'.'+tableid);
+ LS.removeTable(databaseid, tableid);
+ if (cb) res = cb(res);
+ return res;
+};
+
+/**
+ Read all data from table
+*/
+
+LS.fromTable = function(databaseid, tableid, cb, idx, query) {
+
+ var lsdbid = alasql.databases[databaseid].lsdbid;
+ // var res = LS.get(lsdbid+'.'+tableid);
+
+ var res = LS.restoreTable(databaseid, tableid).data;
+
+ if (cb) res = cb(res, idx, query);
+ return res;
+};
+
+/**
+ Insert data into the table
+ @param databaseid {string} Database id
+ @param tableid {string} Table id
+ @param value {array} Array of values
+ @param columns {array} Columns (not used)
+ @param cb {function} Callback
+*/
+
+LS.intoTable = function(databaseid, tableid, value, columns, cb) {
+
+ var lsdbid = alasql.databases[databaseid].lsdbid;
+ var res = value.length;
+ // var tb = LS.get(lsdbid+'.'+tableid);
+ var tb = LS.restoreTable(databaseid, tableid);
+ for (var columnid in tb.identities) {
+ var ident = tb.identities[columnid];
+
+ for (var index in value) {
+ value[index][columnid] = ident.value;
+ ident.value += ident.step;
+ }
+ }
+ if (!tb.data) tb.data = [];
+ tb.data = tb.data.concat(value);
+ // LS.set(lsdbid+'.'+tableid, tb);
+ LS.storeTable(databaseid, tableid);
+
+ if (cb) res = cb(res);
+
+ return res;
+};
+
+/**
+ Laad data from table
+*/
+LS.loadTableData = function(databaseid, tableid) {
+ var db = alasql.databases[databaseid];
+ var lsdbid = alasql.databases[databaseid].lsdbid;
+ LS.restoreTable(databaseid, tableid);
+ // db.tables[tableid].data = LS.get(lsdbid+'.'+tableid);
+};
+
+/**
+ Save data to the table
+*/
+
+LS.saveTableData = function(databaseid, tableid) {
+ var db = alasql.databases[databaseid];
+ var lsdbid = alasql.databases[databaseid].lsdbid;
+ LS.storeTable(lsdbid, tableid);
+ // LS.set(lsdbid+'.'+tableid,db.tables[tableid].data);
+ db.tables[tableid].data = undefined;
+};
+
+/**
+ Commit
+*/
+
+LS.commit = function(databaseid, cb) {
+
+ var db = alasql.databases[databaseid];
+ var lsdbid = alasql.databases[databaseid].lsdbid;
+ var lsdb = {databaseid: lsdbid, tables: {}};
+ if (db.tables) {
+ for (var tbid in db.tables) {
+ // TODO: Question - do we need this line
+ lsdb.tables[tbid] = true;
+ LS.storeTable(databaseid, tbid);
+ // LS.set(lsdbid+'.'+tbid, db.tables[tbid].data);
+ }
+ }
+ LS.set(lsdbid, lsdb);
+ return cb ? cb(1) : 1;
+};
+
+/**
+ Alias BEGIN = COMMIT
+*/
+LS.begin = LS.commit;
+
+/**
+ ROLLBACK
+*/
+
+LS.rollback = function(databaseid, cb) {
+ // This does not work and should be fixed
+ // Plus test 151 and 231
+
+ return;
+
+ var db = alasql.databases[databaseid];
+ db.dbversion++;
+
+ var lsdbid = alasql.databases[databaseid].lsdbid;
+ var lsdb = LS.get(lsdbid);
+ // if(!alasql.options.autocommit) {
+
+ delete alasql.databases[databaseid];
+ alasql.databases[databaseid] = new alasql.Database(databaseid);
+ extend(alasql.databases[databaseid], lsdb);
+ alasql.databases[databaseid].databaseid = databaseid;
+ alasql.databases[databaseid].engineid = 'LOCALSTORAGE';
+
+ if (lsdb.tables) {
+ for (var tbid in lsdb.tables) {
+ // var tb = new alasql.Table({columns: db.tables[tbid].columns});
+ // extend(tb,lsdb.tables[tbid]);
+ // lsdb.tables[tbid] = true;
+
+ // if(!alasql.options.autocommit) {
+
+ // lsdb.tables[tbid].data = LS.get(db.lsdbid+'.'+tbid);
+ LS.restoreTable(databaseid, tbid);
+ // }
+ // lsdb.tables[tbid].indexColumns();
+
+ // index columns
+ // convert types
+ }
+ }
+ // }
+
+};
+
+//
+// 91websql.js
+// WebSQL database support
+// (c) 2014, Andrey Gershun
+//
+
+var SQLITE = (alasql.engines.SQLITE = function () {});
+
+SQLITE.createDatabase = function (wdbid, args, ifnotexists, dbid, cb) {
+ throw new Error('Connot create SQLITE database in memory. Attach it.');
+};
+
+SQLITE.dropDatabase = function (databaseid) {
+ throw new Error('This is impossible to drop SQLite database. Detach it.');
+};
+
+SQLITE.attachDatabase = function (sqldbid, dbid, args, params, cb) {
+ var res = 1;
+ if (alasql.databases[dbid]) {
+ throw new Error('Unable to attach database as "' + dbid + '" because it already exists');
+ }
+
+ if ((args[0] && args[0] instanceof yy.StringValue) || args[0] instanceof yy.ParamValue) {
+ if (args[0] instanceof yy.StringValue) {
+ var value = args[0].value;
+ } else if (args[0] instanceof yy.ParamValue) {
+ var value = params[args[0].param];
+ }
+ alasql.utils.loadBinaryFile(
+ value,
+ true,
+ function (data) {
+ var db = new alasql.Database(dbid || sqldbid);
+ db.engineid = 'SQLITE';
+ db.sqldbid = sqldbid;
+ var sqldb = (db.sqldb = new SQL.Database(data));
+ db.tables = [];
+ var tables = sqldb.exec("SELECT * FROM sqlite_master WHERE type='table'")[0].values;
+
+ tables.forEach(function (tbl) {
+ db.tables[tbl[1]] = {};
+ var columns = (db.tables[tbl[1]].columns = []);
+ var ast = alasql.parse(tbl[4]);
+
+ var coldefs = ast.statements[0].columns;
+ if (coldefs && coldefs.length > 0) {
+ coldefs.forEach(function (cd) {
+ columns.push(cd);
+ });
+ }
+ });
+
+ cb(1);
+ },
+ function (err) {
+ throw new Error('Cannot open SQLite database file "' + args[0].value + '"');
+ }
+ );
+ return res;
+ } else {
+ throw new Error('Cannot attach SQLite database without a file');
+ }
+
+ return res;
+};
+
+SQLITE.fromTable = function (databaseid, tableid, cb, idx, query) {
+ var data = alasql.databases[databaseid].sqldb.exec('SELECT * FROM ' + tableid);
+ var columns = (query.sources[idx].columns = []);
+ if (data[0].columns.length > 0) {
+ data[0].columns.forEach(function (columnid) {
+ columns.push({columnid: columnid});
+ });
+ }
+
+ var res = [];
+ if (data[0].values.length > 0) {
+ data[0].values.forEach(function (d) {
+ var r = {};
+ columns.forEach(function (col, idx) {
+ r[col.columnid] = d[idx];
+ });
+ res.push(r);
+ });
+ }
+ if (cb) cb(res, idx, query);
+};
+
+SQLITE.intoTable = function (databaseid, tableid, value, columns, cb) {
+ var sqldb = alasql.databases[databaseid].sqldb;
+ for (var i = 0, ilen = value.length; i < ilen; i++) {
+ var s = 'INSERT INTO ' + tableid + ' (';
+ var d = value[i];
+ var keys = Object.keys(d);
+ s += keys.join(',');
+ s += ') VALUES (';
+ s += keys
+ .map(function (k) {
+ var v = d[k];
+ if (typeof v == 'string') v = "'" + v + "'";
+ return v;
+ })
+ .join(',');
+ s += ')';
+ sqldb.exec(s);
+ }
+ var res = ilen;
+ if (cb) cb(res);
+ return res;
+};
+
+//
+// 91localstorage.js
+// localStorage and DOM-Storage engine
+// Date: 09.12.2014
+// (c) Andrey Gershun
+//
+
+var FS = (alasql.engines.FILESTORAGE = alasql.engines.FILE = function() {});
+
+FS.createDatabase = function(fsdbid, args, ifnotexists, dbid, cb) {
+
+ var res = 1;
+ var filename = args[0].value;
+
+ alasql.utils.fileExists(filename, function(fex) {
+
+ if (fex) {
+ if (ifnotexists) {
+ res = 0;
+ if (cb) res = cb(res);
+ return res;
+ } else {
+ throw new Error('Cannot create new database file, because it already exists');
+ }
+ } else {
+ var data = {tables: {}};
+ alasql.utils.saveFile(filename, JSON.stringify(data), function(data) {
+ if (cb) res = cb(res);
+ });
+ }
+ });
+ return res;
+};
+
+FS.dropDatabase = function(fsdbid, ifexists, cb) {
+ var res;
+ var filename = "";
+
+ if (typeof fsdbid === 'object' && fsdbid.value) {
+ // Existing tests (test225.js) had DROP directly without DETACH and
+ // without a database id / name. It instead used the filename directly.
+ // This block will handle that
+ filename = fsdbid.value;
+ } else {
+ // When a database id / name is specified in DROP, it will be handled by this block.
+ // Note: Both DETACH + DROP and direct DROP without DETACH will be handled by this block
+ // We will be deleting the database object and the file either way.
+ // However, in the future, if we would like to have a stricter implementation
+ // where we cannot DROP without DETACHing it first, we can handle that case using
+ // the 'isDetached' property of the database object.
+ // (i.e) alasql.databases[fsdbid].isDetached will be set if it is
+ // has been detached first
+ var db = alasql.databases[fsdbid] || {};
+
+ filename = db.filename || '';
+ delete alasql.databases[fsdbid];
+ }
+ alasql.utils.fileExists(filename, function(fex) {
+ if (fex) {
+ res = 1;
+ alasql.utils.deleteFile(filename, function() {
+ res = 1;
+ if (cb) res = cb(res);
+ });
+ } else {
+ if (!ifexists) {
+ throw new Error('Cannot drop database file, because it does not exist');
+ }
+ res = 0;
+ if (cb) res = cb(res);
+ }
+ });
+ return res;
+};
+
+FS.attachDatabase = function(fsdbid, dbid, args, params, cb) {
+
+ var res = 1;
+ if (alasql.databases[dbid]) {
+ throw new Error('Unable to attach database as "' + dbid + '" because it already exists');
+ }
+ var db = new alasql.Database(dbid || fsdbid);
+ db.engineid = 'FILESTORAGE';
+ // db.fsdbid = fsdbid;
+ db.filename = args[0].value;
+ loadFile(db.filename, !!cb, function(s) {
+ try {
+ db.data = JSON.parse(s);
+ } catch (err) {
+ throw new Error('Data in FileStorage database are corrupted');
+ }
+ db.tables = db.data.tables;
+ // IF AUTOCOMMIT IS OFF then copy data to memory
+ if (!alasql.options.autocommit) {
+ if (db.tables) {
+ for (var tbid in db.tables) {
+ db.tables[tbid].data = db.data[tbid];
+ }
+ }
+ }
+ if (cb) res = cb(res);
+ });
+ return res;
+};
+
+FS.createTable = function(databaseid, tableid, ifnotexists, cb) {
+ var db = alasql.databases[databaseid];
+ var tb = db.data[tableid];
+ var res = 1;
+
+ if (tb && !ifnotexists) {
+ throw new Error('Table "' + tableid + '" alsready exists in the database "' + fsdbid + '"');
+ }
+ var table = alasql.databases[databaseid].tables[tableid];
+ db.data.tables[tableid] = {columns: table.columns};
+ db.data[tableid] = [];
+
+ FS.updateFile(databaseid);
+
+ if (cb) cb(res);
+ return res;
+};
+
+FS.updateFile = function(databaseid) {
+
+ var db = alasql.databases[databaseid];
+ if (db.issaving) {
+ db.postsave = true;
+ return;
+ }
+ db.issaving = true;
+ db.postsave = false;
+ alasql.utils.saveFile(db.filename, JSON.stringify(db.data), function() {
+ db.issaving = false;
+
+ if (db.postsave) {
+ setTimeout(function() {
+ FS.updateFile(databaseid);
+ }, 50); // TODO Test with different timeout parameters
+ }
+ });
+};
+
+FS.dropTable = function(databaseid, tableid, ifexists, cb) {
+ var res = 1;
+ var db = alasql.databases[databaseid];
+ if (!ifexists && !db.tables[tableid]) {
+ throw new Error(
+ 'Cannot drop table "' + tableid + '" in fileStorage, because it does not exist'
+ );
+ }
+ delete db.tables[tableid];
+ delete db.data.tables[tableid];
+ delete db.data[tableid];
+ FS.updateFile(databaseid);
+ if (cb) cb(res);
+ return res;
+};
+
+FS.fromTable = function(databaseid, tableid, cb, idx, query) {
+
+ var db = alasql.databases[databaseid];
+ var res = db.data[tableid];
+ if (cb) res = cb(res, idx, query);
+ return res;
+};
+
+FS.intoTable = function(databaseid, tableid, value, columns, cb) {
+ var db = alasql.databases[databaseid];
+ var res = value.length;
+ var tb = db.data[tableid];
+ if (!tb) tb = [];
+ db.data[tableid] = tb.concat(value);
+ FS.updateFile(databaseid);
+ if (cb) cb(res);
+ return res;
+};
+
+FS.loadTableData = function(databaseid, tableid) {
+ var db = alasql.databases[databaseid];
+ db.tables[tableid].data = db.data[tableid];
+};
+
+FS.saveTableData = function(databaseid, tableid) {
+ var db = alasql.databases[databaseid];
+ db.data[tableid] = db.tables[tableid].data;
+ db.tables[tableid].data = null;
+ FS.updateFile(databaseid);
+};
+
+FS.commit = function(databaseid, cb) {
+
+ var db = alasql.databases[databaseid];
+ var fsdb = {tables: {}};
+ if (db.tables) {
+ for (var tbid in db.tables) {
+ db.data.tables[tbid] = {columns: db.tables[tbid].columns};
+ db.data[tbid] = db.tables[tbid].data;
+ }
+ }
+ FS.updateFile(databaseid);
+ return cb ? cb(1) : 1;
+};
+
+FS.begin = FS.commit;
+
+FS.rollback = function(databaseid, cb) {
+ var res = 1;
+ var db = alasql.databases[databaseid];
+ db.dbversion++;
+
+ // var lsdbid = alasql.databases[databaseid].lsdbid;
+ // lsdb = LS.get(lsdbid);
+ wait();
+ function wait() {
+ setTimeout(function() {
+ if (db.issaving) {
+ return wait();
+ } else {
+ alasql.loadFile(db.filename, !!cb, function(data) {
+ db.data = data;
+ db.tables = {};
+ for (var tbid in db.data.tables) {
+ var tb = new alasql.Table({columns: db.data.tables[tbid].columns});
+ extend(tb, db.data.tables[tbid]);
+ db.tables[tbid] = tb;
+ if (!alasql.options.autocommit) {
+ db.tables[tbid].data = db.data[tbid];
+ }
+ db.tables[tbid].indexColumns();
+
+ // index columns
+ // convert types
+ }
+
+ delete alasql.databases[databaseid];
+ alasql.databases[databaseid] = new alasql.Database(databaseid);
+ extend(alasql.databases[databaseid], db);
+ alasql.databases[databaseid].engineid = 'FILESTORAGE';
+ alasql.databases[databaseid].filename = db.filename;
+
+ if (cb) res = cb(res);
+ // Todo: check why no return
+ });
+ }
+ }, 100);
+ }
+
+ // if(!alasql.options.autocommit) {
+
+};
+
+if(utils.isBrowser && !utils.isWebWorker) {
+
+alasql = alasql || false;
+
+if (!alasql) {
+ throw new Error('alasql was not found');
+}
+
+alasql.worker = function() {
+ throw new Error('Can find webworker in this enviroment');
+};
+
+if (typeof Worker !== 'undefined') {
+ alasql.worker = function(path, paths, cb) {
+ // var path;
+ if (path === true) {
+ path = undefined;
+ }
+
+ if (typeof path === 'undefined') {
+ var sc = document.getElementsByTagName('script');
+ for (var i = 0; i < sc.length; i++) {
+ if (sc[i].src.substr(-16).toLowerCase() === 'alasql-worker.js') {
+ path = sc[i].src.substr(0, sc[i].src.length - 16) + 'alasql.js';
+ break;
+ } else if (sc[i].src.substr(-20).toLowerCase() === 'alasql-worker.min.js') {
+ path = sc[i].src.substr(0, sc[i].src.length - 20) + 'alasql.min.js';
+ break;
+ } else if (sc[i].src.substr(-9).toLowerCase() === 'alasql.js') {
+ path = sc[i].src;
+ break;
+ } else if (sc[i].src.substr(-13).toLowerCase() === 'alasql.min.js') {
+ path = sc[i].src.substr(0, sc[i].src.length - 13) + 'alasql.min.js';
+ break;
+ }
+ }
+ }
+
+ if (typeof path === 'undefined') {
+ throw new Error('Path to alasql.js is not specified');
+ } else if (path !== false) {
+ var js = "importScripts('";
+ js += path;
+ js +=
+ "');self.onmessage = function(event) {" +
+ 'alasql(event.data.sql,event.data.params, function(data){' +
+ 'postMessage({id:event.data.id, data:data});});}';
+
+ var blob = new Blob([js], {type: 'text/plain'});
+ alasql.webworker = new Worker(URL.createObjectURL(blob));
+
+ alasql.webworker.onmessage = function(event) {
+ var id = event.data.id;
+
+ alasql.buffer[id](event.data.data);
+ delete alasql.buffer[id];
+ };
+
+ alasql.webworker.onerror = function(e) {
+ throw e;
+ };
+
+ if (arguments.length > 1) {
+ var sql =
+ 'REQUIRE ' +
+ paths
+ .map(function(p) {
+ return '"' + p + '"';
+ })
+ .join(',');
+ alasql(sql, [], cb);
+ }
+ } else if (path === false) {
+ delete alasql.webworker;
+ return;
+ }
+ };
+}
+
+/* FileSaver.js
+ * A saveAs() FileSaver implementation.
+ * 1.3.2
+ * 2016-06-16 18:25:19
+ *
+ * By Eli Grey, http://eligrey.com
+ * License: MIT
+ * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
+ */
+
+/*global self */
+/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
+
+/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
+
+var saveAs =
+ saveAs ||
+ (function(view) {
+ 'use strict';
+ // IE <10 is explicitly unsupported
+ if (
+ typeof view === 'undefined' ||
+ (typeof navigator !== 'undefined' && /MSIE [1-9]\./.test(navigator.userAgent))
+ ) {
+ return;
+ }
+ var doc = view.document,
+ // only get URL when necessary in case Blob.js hasn't overridden it yet
+ get_URL = function() {
+ return view.URL || view.webkitURL || view;
+ },
+ save_link = doc.createElementNS('http://www.w3.org/1999/xhtml', 'a'),
+ can_use_save_link = 'download' in save_link,
+ click = function(node) {
+ var event = new MouseEvent('click');
+ node.dispatchEvent(event);
+ },
+ is_safari = /constructor/i.test(view.HTMLElement) || view.safari,
+ is_chrome_ios = /CriOS\/[\d]+/.test(navigator.userAgent),
+ throw_outside = function(ex) {
+ (view.setImmediate || view.setTimeout)(function() {
+ throw ex;
+ }, 0);
+ },
+ force_saveable_type = 'application/octet-stream',
+ // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to
+ arbitrary_revoke_timeout = 1000 * 40, // in ms
+ revoke = function(file) {
+ var revoker = function() {
+ if (typeof file === 'string') {
+ // file is an object URL
+ get_URL().revokeObjectURL(file);
+ } else {
+ // file is a File
+ file.remove();
+ }
+ };
+ setTimeout(revoker, arbitrary_revoke_timeout);
+ },
+ dispatch = function(filesaver, event_types, event) {
+ event_types = [].concat(event_types);
+ var i = event_types.length;
+ while (i--) {
+ var listener = filesaver['on' + event_types[i]];
+ if (typeof listener === 'function') {
+ try {
+ listener.call(filesaver, event || filesaver);
+ } catch (ex) {
+ throw_outside(ex);
+ }
+ }
+ }
+ },
+ auto_bom = function(blob) {
+ // prepend BOM for UTF-8 XML and text/* types (including HTML)
+ // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
+ if (
+ /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(
+ blob.type
+ )
+ ) {
+ return new Blob([String.fromCharCode(0xfeff), blob], {type: blob.type});
+ }
+ return blob;
+ },
+ FileSaver = function(blob, name, no_auto_bom) {
+ if (!no_auto_bom) {
+ blob = auto_bom(blob);
+ }
+ // First try a.download, then web filesystem, then object URLs
+ var filesaver = this,
+ type = blob.type,
+ force = type === force_saveable_type,
+ object_url,
+ dispatch_all = function() {
+ dispatch(filesaver, 'writestart progress write writeend'.split(' '));
+ },
+ // on any filesys errors revert to saving with object URLs
+ fs_error = function() {
+ if ((is_chrome_ios || (force && is_safari)) && view.FileReader) {
+ // Safari doesn't allow downloading of blob urls
+ var reader = new FileReader();
+ reader.onloadend = function() {
+ var url = is_chrome_ios
+ ? reader.result
+ : reader.result.replace(
+ /^data:[^;]*;/,
+ 'data:attachment/file;'
+ );
+ var popup = view.open(url, '_blank');
+ if (!popup) view.location.href = url;
+ url = undefined; // release reference before dispatching
+ filesaver.readyState = filesaver.DONE;
+ dispatch_all();
+ };
+ reader.readAsDataURL(blob);
+ filesaver.readyState = filesaver.INIT;
+ return;
+ }
+ // don't create more object URLs than needed
+ if (!object_url) {
+ object_url = get_URL().createObjectURL(blob);
+ }
+ if (force) {
+ view.location.href = object_url;
+ } else {
+ var opened = view.open(object_url, '_blank');
+ if (!opened) {
+ // Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html
+ view.location.href = object_url;
+ }
+ }
+ filesaver.readyState = filesaver.DONE;
+ dispatch_all();
+ revoke(object_url);
+ };
+ filesaver.readyState = filesaver.INIT;
+
+ if (can_use_save_link) {
+ object_url = get_URL().createObjectURL(blob);
+ setTimeout(function() {
+ save_link.href = object_url;
+ save_link.download = name;
+ click(save_link);
+ dispatch_all();
+ revoke(object_url);
+ filesaver.readyState = filesaver.DONE;
+ });
+ return;
+ }
+
+ fs_error();
+ },
+ FS_proto = FileSaver.prototype,
+ saveAs = function(blob, name, no_auto_bom) {
+ return new FileSaver(blob, name || blob.name || 'download', no_auto_bom);
+ };
+ // IE 10+ (native saveAs)
+ if (typeof navigator !== 'undefined' && navigator.msSaveOrOpenBlob) {
+ return function(blob, name, no_auto_bom) {
+ name = name || blob.name || 'download';
+
+ if (!no_auto_bom) {
+ blob = auto_bom(blob);
+ }
+ return navigator.msSaveOrOpenBlob(blob, name);
+ };
+ }
+
+ FS_proto.abort = function() {};
+ FS_proto.readyState = FS_proto.INIT = 0;
+ FS_proto.WRITING = 1;
+ FS_proto.DONE = 2;
+
+ FS_proto.error = FS_proto.onwritestart = FS_proto.onprogress = FS_proto.onwrite = FS_proto.onabort = FS_proto.onerror = FS_proto.onwriteend = null;
+
+ return saveAs;
+ })(
+ (typeof self !== 'undefined' && self) ||
+ (typeof window !== 'undefined' && window) ||
+ this.content
+ );
+// `self` is undefined in Firefox for Android content script context
+// while `this` is nsIContentFrameMessageManager
+// with an attribute `content` that corresponds to the window
+
+if (typeof module !== 'undefined' && module.exports) {
+ module.exports.saveAs = saveAs;
+} else if (typeof define !== 'undefined' && define !== null && define.amd !== null) {
+ define('FileSaver.js', function() {
+ return saveAs;
+ });
+}
+
+/* eslint-disable */
+
+/*
+//
+// Last part of Alasql.js
+// Date: 03.11.2014
+// (c) 2014, Andrey Gershun
+//
+*/
+
+// This is a final part of Alasql
+
+//*only-for-browser/*
+if(utils.isCordova || utils.isMeteorServer || utils.isNode ){
+ console.warn('It looks like you are using the browser version of AlaSQL. Please use the alasql.fs.js file instead.')
+}
+//*/
+
+// FileSaveAs
+alasql.utils.saveAs = saveAs;
+
+};
+
+// Create default database
+new Database("alasql");
+
+// Set default database
+alasql.use("alasql");
+
+return alasql;
+}));
+
diff --git a/content/espanol/sql_workshop/default/db.js b/content/espanol/sql_workshop/default/db.js
new file mode 100644
index 0000000000..c4e31cf3ac
--- /dev/null
+++ b/content/espanol/sql_workshop/default/db.js
@@ -0,0 +1,54 @@
+// Galaxy database
+alasql("CREATE TABLE galaxy(planet_number INT, planet STRING, leader STRING, population INT, coordinates INT)");
+
+alasql("INSERT INTO galaxy VALUES (1,'Puzzle Land','Thomas Stewart',10000,1)");
+alasql("INSERT INTO galaxy VALUES (2,'Planet of Mold','Lucy Stewart',90000,3)");
+alasql("INSERT INTO galaxy VALUES (3,'Ice Cream Freezer Land','James Dunkeld',20000,5)");
+alasql("INSERT INTO galaxy VALUES (4,'Planet of Fun','Olivia Windsor',20000,6)");
+alasql("INSERT INTO galaxy VALUES (5,'Desert Quadrant','Chloe Canmore',60000,7)");
+alasql("INSERT INTO galaxy VALUES (6,'Planet of Boredom','N/A',90000,8)");
+alasql("INSERT INTO galaxy VALUES (7,'Nebula Planet','Harry Windsor',60000,9)");
+alasql("INSERT INTO galaxy VALUES (8,'Ocean World','Oliver Stuart',10000,10)");
+alasql("INSERT INTO galaxy VALUES (9,'Space Zone','N/A',0,11)");
+alasql("INSERT INTO galaxy VALUES (10,'Eeh-Eeh','Amelia Tudor',90000,24)");
+alasql("INSERT INTO galaxy VALUES (11,'Planet of Pizza','N/A',10000,27)");
+alasql("INSERT INTO galaxy VALUES (12,'Planet of Tacos','Jack Planta',900,60)");
+
+// Planet database
+alasql("CREATE TABLE planet(city_number INT, name STRING, population INT, favorite_food STRING)");
+alasql("INSERT INTO planet VALUES (1,'LEGO City',1500,'Pizza')");
+alasql("INSERT INTO planet VALUES (2,'Playground City',1000,'Pizza')");
+alasql("INSERT INTO planet VALUES (3,'City of Games',6000,'Hotdog')");
+alasql("INSERT INTO planet VALUES (4,'Fun Capital',9500,'Hamburger')");
+alasql("INSERT INTO planet VALUES (5,'Seriously Fun',2000,'Taco')");
+
+// Items database
+alasql("CREATE TABLE items(object STRING, date_created DATE, location STRING, color STRING, height INT, short_description STRING)");
+
+alasql("INSERT INTO items VALUES ('totem','1738-09-12','City of Fun', 'sprinkles',10,'Confetti Cannon')");
+alasql("INSERT INTO items VALUES ('totem','1738-10-12','Fun Capital','blue',10,'Infinite Buffet Table')");
+alasql("INSERT INTO items VALUES ('totem','1738-11-02','Playground City','red',10,'Red stuff goes boom')");
+alasql("INSERT INTO items VALUES ('totem','1729-01-03','UNKNOWN','gold',30,'UNKNOWN')");
+
+alasql("INSERT INTO items VALUES ('ladder','1738-09-01','Fun Capital','red',100,'Tall ladder')");
+alasql("INSERT INTO items VALUES ('ladder','1738-09-02','Fun Capital','green',60,'Medium ladder')");
+alasql("INSERT INTO items VALUES ('ladder','1738-09-03','Fun Capital','yellow',20,'Short ladder')");
+
+alasql("INSERT INTO items VALUES ('key','1738-09-04','Fun Capital','gold',3,'3 loops key')");
+alasql("INSERT INTO items VALUES ('key','1738-09-05','Fun Capital','gold',2,'2 loops key')");
+alasql("INSERT INTO items VALUES ('key','1738-09-06','Fun Capital','gold',1,'1 loop key')");
+
+
+// People database
+alasql("CREATE TABLE people(name STRING, favorite_food STRING, city_location STRING, favorite_subject STRING, favorite_movie STRING)");
+
+alasql("INSERT INTO people VALUES ('Olivia Windsor','Hamburger','Fun Capital', 'science','Hidden Figures')");
+alasql("INSERT INTO people VALUES ('Mr. Emmet','Pizza','LEGO City', 'engineering','The LEGO movie')");
+alasql("INSERT INTO people VALUES ('Dr. Phi','Pizza','Playground City', 'math','Big Hero 6')");
+alasql("INSERT INTO people VALUES ('Caroline Jones','Hotdog','City of Games', 'technology','Meet the Robinsons')");
+alasql("INSERT INTO people VALUES ('Eve Dragonheart','Taco','Seriously Fun', 'science','WALL-E')");
+alasql("INSERT INTO people VALUES ('Duchess Leia','Pizza','Playground City', 'engineering','Star Wars')");
+
+alasql("CREATE TABLE command_center(name STRING)");
+alasql("INSERT INTO command_center VALUES ('Kim')");
+alasql("INSERT INTO command_center VALUES ('Justin')");
\ No newline at end of file
diff --git a/content/espanol/sql_workshop/media/Accept.png b/content/espanol/sql_workshop/media/Accept.png
new file mode 100644
index 0000000000..e37f3b5882
Binary files /dev/null and b/content/espanol/sql_workshop/media/Accept.png differ
diff --git a/content/espanol/sql_workshop/media/Galaxy.png b/content/espanol/sql_workshop/media/Galaxy.png
new file mode 100644
index 0000000000..de922fd7db
Binary files /dev/null and b/content/espanol/sql_workshop/media/Galaxy.png differ
diff --git a/content/espanol/sql_workshop/media/Terminal.png b/content/espanol/sql_workshop/media/Terminal.png
new file mode 100644
index 0000000000..c94d56050c
Binary files /dev/null and b/content/espanol/sql_workshop/media/Terminal.png differ
diff --git a/content/espanol/sql_workshop/media/Terminal2.png b/content/espanol/sql_workshop/media/Terminal2.png
new file mode 100644
index 0000000000..7542cb4b94
Binary files /dev/null and b/content/espanol/sql_workshop/media/Terminal2.png differ
diff --git a/content/espanol/sql_workshop/media/Terminal_old.png b/content/espanol/sql_workshop/media/Terminal_old.png
new file mode 100644
index 0000000000..6d5d35502d
Binary files /dev/null and b/content/espanol/sql_workshop/media/Terminal_old.png differ
diff --git a/content/espanol/sql_workshop/media/green.png b/content/espanol/sql_workshop/media/green.png
new file mode 100644
index 0000000000..381f6e7686
Binary files /dev/null and b/content/espanol/sql_workshop/media/green.png differ
diff --git a/content/espanol/sql_workshop/syntax_explanation/_index.md b/content/espanol/sql_workshop/syntax_explanation/_index.md
new file mode 100644
index 0000000000..068849b9f4
--- /dev/null
+++ b/content/espanol/sql_workshop/syntax_explanation/_index.md
@@ -0,0 +1,51 @@
+---
+title: "Tutorial 2: Explicar la Sintaxis"
+description: "Explicar la sintaxis"
+date: 2020-07-15
+prereq: "Comando SELECT, condicionales (comando WHERE)"
+difficulty: "Principiante"
+draft: false
+---
+
+## ¿Un Email de parte de la Federación Gálactica?
+A la mitad de tu viaje, de pronto recibes un mensaje de la Federación Gálactica. ¿Sobre qué se tratará?
+
+
+
+Remitente: La Federación Gálactica
+
+Destinatario: Cadete Espacial
+
+Asunto: Terminal mejorada
+
+
+
+Querido Cadete Espacial,
+
+
+
+Nuestros archivos indican que haz aprendido los suficientes comandos para aprender la estructura básica de los comandos de SQL.
+
+**La Federación Gálactica ha tomado nota de tus logros y ha decidido otorgarte una terminal mejorada.**
+Durante tu viaje, vas a necesitar una terminal útil para desplegar información sobre el planeta. ¡Ahora te será posible escribir comandos!
+
+
+
+Siguiendo los lineamientos de Explorador Espacial, ahora te enseñaremos la estructura central de un comando de SQL deseando que podrás superar los obstáculos que aparezcan en tu camino.
+
+![Syntax](assets/Tutorial.png)
+
+
+
+Con suerte nuestro consejo te ayudará en tu viaje. ¡Buena suerte, Cadete Espacial!
+
+
+
+Deseándote la mejor aventura,
+
+
+
+La Federación Gálactica
diff --git a/content/espanol/sql_workshop/syntax_explanation/assets/Tutorial.png b/content/espanol/sql_workshop/syntax_explanation/assets/Tutorial.png
new file mode 100644
index 0000000000..9ccbd183c4
Binary files /dev/null and b/content/espanol/sql_workshop/syntax_explanation/assets/Tutorial.png differ