UNPKG

alasql

Version:

AlaSQL.js - JavaScript SQL database library for relational and graph data manipulation with support of localStorage, IndexedDB, and Excel

761 lines (674 loc) 22.6 kB
/* // // Utilities for Alasql.js // Date: 03.11.2014 // (c) 2014, Andrey Gershun // */ /** Alasql utility functions */ var utils = alasql.utils = {}; /** Return true. Stub for non-ecisting WHERE clause, because is faster then if(whenrfn) whenfn() @return {boolean} true */ function returnTrue () {return true}; /** Return undefined Stub for non-ecisting WHERE clause, because is faster then if(whenrfn) whenfn() @return undefined */ function returnUndefined() {}; /** Escape quotes @param {string} s Source string @return {string} Escaped string */ var escapeq = utils.escapeq = function(s) { // console.log(s); return s.replace(/\'/g,'\\\''); } /** Double quotes @param {string} s Source string @return {string} Escaped string */ var escapeqq = utils.undoubleq = function(s) { return s.replace(/(\')/g,'\'\''); } /** Replace double quotes @param {string} s Source string @return {string} Replaced string */ var doubleq = utils.doubleq = function(s) { return s.replace(/(\'\')/g,'\\\''); } /** Replace sigle quote to escaped single quote @param {string} s Source string @return {string} Replaced string */ var doubleqq = utils.doubleqq = function(s) { return s.replace(/\'/g,"\'"); } var cutbom = function(s) { if(s[0] == String.fromCharCode(65279)) s = s.substr(1); return s; }; /** Load text file from anywhere @param {string} path File path @param {boolean} asy True - async call, false - sync call @param {function} success Success function @param {function} error Error function */ var loadFile = utils.loadFile = function(path, asy, success, error) { if(typeof exports == 'object') { // For Node.js var fs = require('fs'); // console.log(36,path); // console.log(typeof path); if(!path) { var buff = ''; process.stdin.setEncoding('utf8'); process.stdin.on('readable', function() { var chunk = process.stdin.read(); if (chunk !== null) { buff += chunk.toString(); } }); process.stdin.on('end', function() { success(cutbom(buff)); }); } else { // var data = fs.readFileSync(path); // success(data.toString()); if(asy) { fs.readFile(path,function(err,data){ if(err) { throw err; } success(cutbom(data.toString())); }); } else { var data = fs.readFileSync(path); success(cutbom(data.toString())); } } } else if(typeof cordova == 'object') { // console.log('CORDOVA'+path); // console.log(cordova); // console.log('CORDOVA'+path); // Cordova window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fileSystem) { fileSystem.root.getFile(path, {create:false}, function (fileEntry) { // var reader = new FileReader(); // // console.log('READ FILE 2'); // reader.onloadend = function(e) { // // console.log('READ FILE 3',this.result); // success(this.result); // }; // reader.readAsText(file); fileEntry.file(function(file){ var fileReader = new FileReader(); fileReader.onloadend = function(e){ success(cutbom(this.result)); }; fileReader.readAsText(file); }); // }); }); }); /* var paths = path.split('/'); var filename = paths[paths.length-1]; var dirpath = path.substr(0,path.length-filename.length); // console.log('CORDOVA',filename,dirpath); //return success('[{"a":"'+filename+'"}]'); window.resolveLocalFileSystemURL(dirpath, function(dir) { dir.getFile(filename, null, function(file) { file.file(function(file) { var reader = new FileReader(); // console.log('READ FILE 2'); reader.onloadend = function(e) { // console.log('READ FILE 3',this.result); success(this.result); }; reader.readAsText(file); }); }); }); */ } else { // if(typeof path == "string") { // } if(typeof path == "string") { // For browser read from tag if((path.substr(0,1) == '#') && (typeof document != 'undefined')) { var data = document.querySelector(path).textContent; success(data); } else { // For browser var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState === XMLHttpRequest.DONE) { if (xhr.status === 200) { if (success) success(cutbom(xhr.responseText)); } else { if (error) error(xhr); } } }; xhr.open("GET", path, asy); // Async xhr.send(); } } else if(path instanceof Event) { // console.log("event"); var files = path.target.files; var reader = new FileReader(); var name = files[0].name; reader.onload = function(e) { var data = e.target.result; success(cutbom(data)); }; reader.readAsText(files[0]); } } }; /** Load binary file from anywhere @param {string} path File path @param {boolean} asy True - async call, false - sync call @param {function} success Success function @param {function} error Error function @return 1 for Async, data - for sync version */ var loadBinaryFile = utils.loadBinaryFile = function(path, asy, success, error) { if(typeof exports == 'object') { // For Node.js var fs = require('fs'); if(asy) { fs.readFile(path,function(err,data){ if(err) { throw err; } var arr = new Array(); for(var i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]); success(arr.join("")); }); } else { var data = fs.readFileSync(path); var arr = new Array(); for(var i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]); success(arr.join("")); } // success(data); } else { if(typeof path == "string") { // For browser var xhr = new XMLHttpRequest(); xhr.open("GET", path, asy); // Async xhr.responseType = "arraybuffer"; xhr.onload = function() { var data = new Uint8Array(xhr.response); var arr = new Array(); for(var i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]); success(arr.join("")); }; xhr.send(); } else if(path instanceof Event) { // console.log("event"); var files = path.target.files; var reader = new FileReader(); var name = files[0].name; reader.onload = function(e) { var data = e.target.result; success(data); }; reader.readAsBinaryString(files[0]); } }; }; var removeFile = utils.removeFile = function(path,cb) { if(typeof exports == 'object') { var fs = require('fs'); fs.remove(path,cb); } else if(typeof cordova == 'object') { window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fileSystem) { fileSystem.root.getFile(path, {create:false}, function (fileEntry) { fileEntry.remove(cb); if(cb) cb(); }, function(){ if(cb) cb(); }); }); } else { throw new Error('You can remove files only in Node.js and Apache Cordova'); }; }; var deleteFile = utils.deleteFile = function(path,cb){ if(typeof exports == 'object') { var fs = require('fs'); fs.unlink(path, cb); }; }; var fileExists = utils.fileExists = function(path,cb){ if(typeof exports == 'object') { var fs = require('fs'); fs.exists(path,cb); } else if(typeof cordova == 'object') { window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fileSystem) { fileSystem.root.getFile(path, {create:false}, function (fileEntry) { cb(true); }, function(){ cb(false); }); }); /* function fail(){ callback(false); } try { // Cordova var paths = path.split('/'); var filename = paths[paths.length-1]; var dirpath = path.substr(0,path.length-filename.length); window.resolveLocalFileSystemURL(dirpath, function(dir) { dir.getFile(filename, null, function(file) { file.file(function(file) { callback(true); },fail); },fail); },fail); } catch(err) { fail(); }; */ } else { // TODO Cordova, etc. throw new Error('You can use exists() only in Node.js or Apach Cordova'); } }; /** Save text file from anywhere @param {string} path File path @param {array of objects} data Data object @param {function} cb Callback */ var saveFile = utils.saveFile = function(path, data, cb) { var res = 1; if(typeof path == 'undefined') { // // Return data into result variable // like: alasql('SELECT * INTO TXT() FROM ?',[data]); // res = data; if(cb) res = cb(res); } else { if(typeof exports == 'object') { // For Node.js var fs = require('fs'); var data = fs.writeFileSync(path,data); if(cb) res = cb(res); } else if(typeof cordova == 'object') { // For Apache Cordova window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fileSystem) { // alasql.utils.removeFile(path,function(){ fileSystem.root.getFile(path, {create:true}, function (fileEntry) { fileEntry.createWriter(function(fileWriter) { fileWriter.onwriteend = function(){ if(cb) res = cb(res); }; fileWriter.write(data); }); }); // }); }); /* } else if((typeof cordova == 'object') && cordova.file) { // console.log('saveFile 1'); // Cordova var paths = path.split('/'); var filename = paths[paths.length-1]; var dirpath = path.substr(0,path.length-filename.length); // console.log('CORDOVA',filename,dirpath); //return success('[{"a":"'+filename+'"}]'); window.resolveLocalFileSystemURL(dirpath, function(dir) { // console.log('saveFile 2'); dir.getFile(filename, {create:true}, function(file) { // console.log('saveFile 3'); // file.file(function(file) { // console.log('saveFile 4'); file.createWriter(function(fileWriter) { // fileWriter.seek(fileWriter.length); var blob = new Blob([data], {type:'text/plain'}); fileWriter.write(blob); fileWriter.onwriteend = function(){ if(cb) cb(); }; // console.log("ok, in theory i worked"); }); */ /* // Corodva function writeFinish() { // ... your done code here... return cb() }; var written = 0; var BLOCK_SIZE = 1*1024*1024; // write 1M every time of write function writeNext(cbFinish) { var sz = Math.min(BLOCK_SIZE, data.length - written); var sub = data.slice(written, written+sz); writer.write(sub); written += sz; writer.onwrite = function(evt) { if (written < data.length) writeNext(cbFinish); else cbFinish(); }; } writeNext(writeFinish); } */ // }); // }); // }); } else { if(isIE() == 9) { // Solution was taken from // http://megatuto.com/formation-JAVASCRIPT.php?JAVASCRIPT_Example=Javascript+Save+CSV+file+in+IE+8/IE+9+without+using+window.open()+Categorie+javascript+internet-explorer-8&category=&article=7993 // var URI = 'data:text/plain;charset=utf-8,'; // Prepare data var ndata = data.replace(/\r\n/g,'&#A;&#D;'); ndata = ndata.replace(/\n/g,'&#D;'); ndata = ndata.replace(/\t/g,'&#9;'); var testlink = window.open("about:blank", "_blank"); testlink.document.write(ndata); //fileData has contents for the file testlink.document.close(); testlink.document.execCommand('SaveAs', false, path); testlink.close(); } else { var blob = new Blob([data], {type: "text/plain;charset=utf-8"}); saveAs(blob, path); if(cb) res = cb(res); } } }; return res; }; // For compatibility issues function isIE () { var myNav = navigator.userAgent.toLowerCase(); return (myNav.indexOf('msie') != -1) ? parseInt(myNav.split('msie')[1]) : false; } // For LOAD // var saveBinaryFile = utils.saveFile = function(path, data, cb) { // if(typeof exports == 'object') { // // For Node.js // var fs = require('fs'); // var data = fs.writeFileSync(path,data); // } else { // var blob = new Blob([data], {type: "text/plain;charset=utf-8"}); // saveAs(blob, path); // } // }; // Fast hash function /** Hash string to integer number @param {string} str Source string @return {integer} hash number */ var hash = utils.hash = function hash(str){ var h = 0; if (str.length == 0) return h; for (var i = 0; i < str.length; i++) { h = ((h<<5)-h)+str.charCodeAt(i); h = h & h; } return h; }; /** Union arrays */ var arrayUnion = utils.arrayUnion = function (a,b) { var r = b.slice(0); a.forEach(function(i) { if (r.indexOf(i) < 0) r.push(i); }); return r; }; /** Array Difference */ var arrayDiff = utils.arrayDiff = function (a,b) { return a.filter(function(i) {return b.indexOf(i) < 0;}); }; /** Arrays deep intersect (with records) */ var arrayIntersect = utils.arrayIntersect = function(a,b) { var r = []; a.forEach(function(ai) { var found = false; b.forEach(function(bi){ found = found || (ai==bi); }); if(found) { r.push(ai); } }); return r; }; /** Arrays deep union (with records) */ var arrayUnionDeep = utils.arrayUnionDeep = function (a,b) { var r = b.slice(0); a.forEach(function(ai) { var found = false; r.forEach(function(ri){ // found = found || equalDeep(ai, ri, true); found = found || deepEqual(ai, ri); }); if(!found) { r.push(ai); } }); return r; }; /** Arrays deep union (with records) */ var arrayExceptDeep = utils.arrayExceptDeep = function (a,b) { var r = []; a.forEach(function(ai) { var found = false; b.forEach(function(bi){ // found = found || equalDeep(ai, bi, true); found = found || deepEqual(ai, bi); }); if(!found) { r.push(ai); } }); return r; }; /** Arrays deep intersect (with records) */ var arrayIntersectDeep = utils.arrayIntersectDeep = function(a,b) { var r = []; a.forEach(function(ai) { var found = false; b.forEach(function(bi){ // found = found || equalDeep(ai, bi, true); found = found || deepEqual(ai, bi, true); }); if(found) { r.push(ai); } }); return r; }; /** Deep clone obects */ var cloneDeep = utils.cloneDeep = function cloneDeep(obj) { if(obj == null || typeof(obj) != 'object') return obj; var temp = obj.constructor(); // changed for(var key in obj) { if(obj.hasOwnProperty(key)) { temp[key] = cloneDeep(obj[key]); } } return temp; } /** Check equality of objects */ var equalDeep = utils.equalDeep = function equalDeep (x, y, deep) { if (deep) { if (x == y) return true; var p; for (p in y) { if (typeof (x[p]) == 'undefined') { return false; } } for (p in y) { if (y[p]) { switch (typeof (y[p])) { case 'object': if (!equalDeep(y[p],x[p])) { return false; } break; case 'function': if (typeof (x[p]) == 'undefined' || (p != 'equals' && y[p].toString() != x[p].toString())) return false; break; default: if (y[p] != x[p]) { return false; } } } else { if (x[p]) return false; } } for (p in x) { if (typeof (y[p]) == 'undefined') { return false; } } return true; } return x == y; }; /** COmpare two object in deep */ var deepEqual = utils.deepEqual = function (x, y) { if ((typeof x == "object" && x != null) && (typeof y == "object" && y != null)) { if (Object.keys(x).length != Object.keys(y).length) return false; for (var prop in x) { if (y.hasOwnProperty(prop)) { if (! deepEqual(x[prop], y[prop])) return false; } else return false; } return true; } else if (x !== y) return false; else return true; } /** Extend object */ var extend = utils.extend = function extend (a,b){ if(typeof a == 'undefined') a = {}; for(var key in b) { if(b.hasOwnProperty(key)) { a[key] = b[key] } } return a; };; /** Flat array by first row */ var flatArray = utils.flatArray = function(a) { if(!a || a.length == 0) return []; var key = Object.keys(a[0])[0]; if(typeof key == 'undefined') return []; return a.map(function(ai) {return ai[key]}); }; /** Convert array of objects to array of arrays */ var arrayOfArrays = utils.arrayOfArrays = function (a) { return a.map(function(aa){ var ar = []; for(var key in aa) ar.push(aa[key]); return ar; }); }; /** Excel:convert number to Excel column, like 1 => 'A' @param {integer} i Column number, starting with 0 @return {string} Column name, starting with 'A' */ var xlsnc = utils.xlsnc = function(i) { var addr = String.fromCharCode(65+i%26); if(i>=26) { i=((i/26)|0)-1; addr = String.fromCharCode(65+i%26)+addr; if(i>26) { i=((i/26)|0)-1; addr = String.fromCharCode(65+i%26)+addr; }; }; return addr; }; /** Excel:conver Excel column name to number @param {integer} i Column number, like 'A' or 'BE' @return {string} Column name, starting with 0 */ var xlscn = utils.xlscn = function(s) { var n = s.charCodeAt(0)-65; if(s.length>1) { n = (n+1)*26+s.charCodeAt(1)-65; // console.log(n, s.charCodeAt(0)-65, s.charCodeAt(1)-65); if(s.length>2) { n = (n+1)*26+s.charCodeAt(2)-65; } } return n; }; var domEmptyChildren = utils.domEmptyChildren = function (container){ var len = container.childNodes.length; while (len--) { container.removeChild(container.lastChild); }; }; var distinctArray = utils.distinctArray = function(data) { var uniq = {}; // TODO: Speedup, because Object.keys is slow for(var i=0,ilen=data.length;i<ilen;i++) { if(typeof data[i] == 'object') { var uix = Object.keys(data[i]).sort().map(function(k){return k+'`'+data[i][k]}).join('`'); } else { var uix = data[i]; } uniq[uix] = data[i]; }; var res = []; for(var key in uniq) res.push(uniq[key]); return res; }