├── bower.json ├── LICENSE ├── angular-websql.min.js ├── README.md └── angular-websql.js /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-websql", 3 | "description": "Helps you generating websql simple queries without writing any sql code.", 4 | "author": "Paulo Caldeira", 5 | "main": "./angular-websql.min.js", 6 | "license": "MIT", 7 | "homepage": "https://github.com/paulocaldeira17/angular-websql", 8 | "dependencies": { 9 | "angular": ">=1.2.0 <1.5.0" 10 | }, 11 | "ignore": [ 12 | "**/.*", 13 | "node_modules", 14 | "components", 15 | "LICENSE", 16 | "Makefile", 17 | "README.md", 18 | "demo", 19 | "src" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Ito Fumito 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /angular-websql.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * angular-websql 3 | * Helps you generate and run websql queries with angular services. 4 | * © MIT License 5 | * @version 1.0.2 6 | */ 7 | "use strict";angular.module("angular-websql",[]).factory("$webSql",["$q",function(a){return{openDatabase:function(b,c,d,e){try{var f=openDatabase(b,c,d,e);if("undefined"==typeof openDatabase)throw"Browser does not support web sql";return{executeQuery:function(b,c){var d=a.defer();return f.transaction(function(a){a.executeSql(b,c,function(a,b){d.resolve(b)},function(a,b){console.log("There has been an error: "+b.message),d.reject()})}),d.promise},executeQueries:function(b,c){var d=a.defer();return f.transaction(function(a){for(var e=0;e0){c+=" {extras} ";for(var e in b){d+=" "+b[e].operator+" ";for(var f in b[e].columns)d+="`"+b[e].columns[f]+"`,";d=d.substring(0,d.length-1)+" ","undefined"!=typeof b[e].postOperator&&(c+=b[e].postOperator+" ")}c+=";"}return this.executeQuery(this.replace(c,{"{tableName}":a,"{extras}":d}),[])},selectAllLimit:function(a,b){if(isNaN(b))throw"Limit must be a number.";return this.executeQuery("SELECT * FROM `"+a+"` LIMIT "+b+"; ",[])},selectOne:function(a){return this.selectAllLimit(a,1)},whereClause:function(a){var b="",c=[];for(var d in a)"undefined"==typeof a[d]||"object"==typeof a[d]||"string"!=typeof a[d]||a[d].match(/NULL/gi)?"undefined"!=typeof a[d]&&"object"!=typeof a[d]&&"number"==typeof a[d]?c.push(a[d]):"undefined"==typeof a[d].value||"object"!=typeof a[d]||"number"!=typeof a[d].value&&a[d].value.match(/NULL/gi)||c.push(a[d].value):c.push(a[d]),b+="object"==typeof a[d]?"undefined"==typeof a[d].union?"string"==typeof a[d].value&&a[d].value.match(/NULL/gi)?"`"+d+"` "+a[d].value:"undefined"!=typeof a[d].operator?"`"+d+"` "+a[d].operator+" ? ":"`"+d+"` = ?":"string"==typeof a[d].value&&a[d].value.match(/NULL/gi)?"`"+d+"` "+a[d].value+" "+a[d].union+" ":"undefined"!=typeof a[d].operator?"`"+d+"` "+a[d].operator+" ? "+a[d].union+" ":"`"+d+"` = ? "+a[d].union+" ":"string"==typeof a[d]&&a[d].match(/NULL/gi)?"`"+d+"` "+a[d]:"`"+d+"` = ?";return{w:b,p:c}},replace:function(a,b){for(var c in b)a=a.replace(new RegExp(c,"ig"),b[c]);return a},addColumns:function(a,b){var c=[],d=[];for(var e in b){var f="ALTER TABLE `{tableName}` ADD COLUMN {fields}; ",g="{type} {null}",h=[],i="`"+e+"` ";"undefined"==typeof b[e].null&&(b[e].null="NULL");for(var j in b[e])g=g.replace(new RegExp("{"+j+"}","ig"),b[e][j]);i+=g,"undefined"!=typeof b[e].default&&(i+=" DEFAULT "+b[e].default),"undefined"!=typeof b[e].primary&&(i+=" PRIMARY KEY"),"undefined"!=typeof b[e].auto_increment&&(i+=" AUTOINCREMENT"),Object.keys(b)[Object.keys(b).length-1]!=e&&(i+=","),"undefined"!=typeof b[e].primary&&b[e].primary&&h.push(e);var k={tableName:a,fields:i};for(var l in k)f=f.replace(new RegExp("{"+l+"}","ig"),k[l]);c.push(f),d.push([])}return this.executeQueries(c,d)},createTable:function(a,b){var c="CREATE TABLE IF NOT EXISTS `{tableName}` ({fields}); ",d=[],e="";for(var f in b){var g="{type} {null}";e+="`"+f+"` ","undefined"==typeof b[f].null&&(b[f].null="NULL");for(var h in b[f])g=g.replace(new RegExp("{"+h+"}","ig"),b[f][h]);e+=g,"undefined"!=typeof b[f].default&&(e+=" DEFAULT "+b[f].default),"undefined"!=typeof b[f].primary&&(e+=" PRIMARY KEY"),"undefined"!=typeof b[f].auto_increment&&(e+=" AUTOINCREMENT"),Object.keys(b)[Object.keys(b).length-1]!=f&&(e+=","),"undefined"!=typeof b[f].primary&&b[f].primary&&d.push(f)}var i={tableName:a,fields:e};for(var j in i)c=c.replace(new RegExp("{"+j+"}","ig"),i[j]);return this.executeQuery(c,[])},createOrAlterTable:function(a,b){var c=this;return c.select("sqlite_master",{type:{value:"table",union:"AND"},tbl_name:a}).then(function(d){if(d.rows.length<=0)return c.createTable(a,b);for(var e=0;e=`, `<=` and `LIKE`. You can use also `IS NULL` and `NOT NULL` as condition values. 285 | 286 | Contributors 287 | --------------------- 288 | Thanks to github community, our libraries do not depend only from our work but also from work of contributors. I want to thank all those who in any way participated in the development of this library. 289 | 290 | Special thanks to these contributors: 291 | * @gfauchart 292 | * @dbtek 293 | 294 | Changelog 295 | --------------------- 296 | ### v1.0.2 297 | * prevent empty operator in where clause 298 | * insert method update with replace flag to "INSERT OR REPLACE" queries 299 | 300 | ### v1.0.1 301 | * escape single quote or double quote value(s) 302 | * changing callback to angular promise 303 | -------------------------------------------------------------------------------- /angular-websql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * angular-websql 3 | * Helps you generate and run websql queries with angular services. 4 | * © MIT License 5 | * @version 1.0.2 6 | */ 7 | /** 8 | * angular-websql 9 | * Helps you generate and run websql queries with angular services. 10 | * © MIT License 11 | * @version 1.0.2 12 | */ 13 | "use strict"; 14 | angular.module("angular-websql", []).factory("$webSql", ["$q", 15 | function($q) { 16 | return { 17 | openDatabase: function(dbName, version, desc, size) { 18 | try { 19 | var db = openDatabase(dbName, version, desc, size); 20 | if (typeof(openDatabase) == "undefined") 21 | throw "Browser does not support web sql"; 22 | return { 23 | executeQuery: function(query, values) { 24 | var deferred = $q.defer(); 25 | db.transaction(function(tx) { 26 | tx.executeSql(query, values, function(tx, results) { 27 | deferred.resolve(results); 28 | }, function(tx, e){ 29 | console.log("There has been an error: " + e.message); 30 | deferred.reject(); 31 | }); 32 | }); 33 | return deferred.promise; 34 | }, 35 | executeQueries: function(queries, values) { 36 | var deferred = $q.defer(); 37 | db.transaction(function(tx) { 38 | for(var idx = 0; idx < queries.length; ++idx) { 39 | tx.executeSql(queries[idx], values[idx], function(tx, results) { 40 | }, function(tx, e){ 41 | console.log("There has been an error: " + e.message); 42 | deferred.reject(); 43 | }); 44 | } 45 | }, 46 | function(tx, err) { 47 | console.log("There has been an error: " + err); 48 | deferred.reject(); 49 | }, 50 | function(tx, err) { 51 | deferred.resolve(err); 52 | }); 53 | return deferred.promise; 54 | }, 55 | insert: function(c, e, r) { 56 | var f = (typeof r === "boolean" && r) ? "INSERT OR REPLACE" : "INSERT"; 57 | f += " INTO `{tableName}` ({fields}) VALUES({values});"; 58 | var a = "", 59 | b = "", 60 | v = []; 61 | for (var d in e) { 62 | a += (Object.keys(e)[Object.keys(e).length - 1] == d) ? "`" + d + "`" : "`" + d + "`, "; 63 | b += (Object.keys(e)[Object.keys(e).length - 1] == d) ? "?" : "?, "; 64 | v.push(e[d]); 65 | } 66 | return this.executeQuery(this.replace(f, { 67 | "{tableName}": c, 68 | "{fields}": a, 69 | "{values}": b 70 | }), v); 71 | }, 72 | bulkInsert: function(table, objects, r) { 73 | var deferred = $q.defer(); 74 | var self = this; 75 | if(!(objects instanceof Array)) { 76 | return this.insert(table, objects, r) 77 | } else if(typeof objects === 'undefined' || objects.length <= 0) { 78 | deferred.reject(); 79 | } else { 80 | var query = (typeof r === "boolean" && r) ? "INSERT OR REPLACE" : "INSERT"; 81 | query += " INTO `{tableName}` ({fields}) VALUES({values});"; 82 | db.transaction(function(tx) { 83 | for (var idx in objects) { 84 | var object = objects[idx] 85 | var a = "", 86 | b = "", 87 | values = []; 88 | for (var d in object) { 89 | a += (Object.keys(object)[Object.keys(object).length - 1] == d) ? "`" + d + "`" : "`" + d + "`, "; 90 | b += (Object.keys(object)[Object.keys(object).length - 1] == d) ? "?" : "?, "; 91 | values.push(object[d]); 92 | } 93 | query = self.replace(query, { 94 | "{tableName}": table, 95 | "{fields}": a, 96 | "{values}": b 97 | }) 98 | tx.executeSql(query, values, function(tx, results) { 99 | }, function(tx, e){ 100 | console.log("There has been an error: " + e.message); 101 | deferred.reject(); 102 | }); 103 | } 104 | }, 105 | function(tx, err) { 106 | console.log("There has been an error: " + err); 107 | deferred.reject(); 108 | }, 109 | function(tx, res) { 110 | deferred.resolve(res); 111 | }); 112 | } 113 | return deferred.promise; 114 | }, 115 | update: function(b, g, c) { 116 | var f = "UPDATE `{tableName}` SET {update} WHERE {where}; "; 117 | var e = ""; 118 | var v = []; 119 | for (var d in g) { 120 | e += (Object.keys(g)[Object.keys(g).length - 1] == d) ? "`" + d + "`= ?" : "`" + d + "`= ?,"; 121 | v.push(g[d]); 122 | } 123 | var a = this.whereClause(c); 124 | return this.executeQuery(this.replace(f, { 125 | "{tableName}": b, 126 | "{update}": e, 127 | "{where}": a.w 128 | }), v.concat(a.p)); 129 | }, 130 | del: function(b, c) { 131 | if (c){ 132 | var d = "DELETE FROM `{tableName}` WHERE {where}; "; 133 | var a = this.whereClause(c); 134 | }else{ 135 | var d = "DELETE FROM `{tableName}`;"; 136 | var a = {p : []}; 137 | } 138 | return this.executeQuery(this.replace(d, { 139 | "{tableName}": b, 140 | "{where}": a.w 141 | }), a.p); 142 | }, 143 | select: function(b, c) { 144 | var d = "SELECT * FROM `{tableName}` WHERE {where}; "; 145 | var a = this.whereClause(c); 146 | return this.executeQuery(this.replace(d, { 147 | "{tableName}": b, 148 | "{where}": a.w 149 | }), a.p); 150 | }, 151 | selectLimit: function(table, where, limit) { 152 | var d = "SELECT * FROM `{tableName}` WHERE {where} LIMIT {limit}; "; 153 | var a = this.whereClause(where); 154 | if (isNaN(limit)) 155 | { 156 | throw "Limit must be a number."; 157 | } 158 | return this.executeQuery(this.replace(d, { 159 | "{tableName}": table, 160 | "{where}": a.w, 161 | "{limit}": limit 162 | }), a.p); 163 | }, 164 | selectAll: function(table, options) { 165 | var query = "SELECT * FROM `{tableName}` "; 166 | var extras = "" 167 | if( typeof options !== "undefined" && options.length > 0) { 168 | query += " {extras} "; 169 | for (var sidx in options) { 170 | extras += " "+options[sidx].operator+" "; 171 | for(var idx in options[sidx].columns) { 172 | extras += "`"+options[sidx].columns[idx] + "`,"; 173 | } 174 | extras = extras.substring(0, extras.length - 1)+" "; 175 | if( typeof options[sidx].postOperator !== "undefined"){ 176 | query += options[sidx].postOperator+" "; 177 | } 178 | } 179 | query += ";"; 180 | } 181 | return this.executeQuery(this.replace(query, { 182 | "{tableName}": table, 183 | "{extras}": extras 184 | }), []); 185 | }, 186 | selectAllLimit: function(table, limit) { 187 | if (isNaN(limit)) 188 | { 189 | throw "Limit must be a number."; 190 | } 191 | return this.executeQuery("SELECT * FROM `" + table + "` LIMIT " + limit + "; ", []); 192 | }, 193 | selectOne: function(table) { 194 | return this.selectAllLimit(table,1); 195 | }, 196 | whereClause: function(b) { 197 | var a = "", 198 | v = []; 199 | for (var c in b) { 200 | if(typeof b[c] !== "undefined" && typeof b[c] !== "object" && typeof b[c] === "string" && !b[c].match(/NULL/ig)) v.push(b[c]); 201 | else if(typeof b[c] !== "undefined" && typeof b[c] !== "object" && typeof b[c] === "number") v.push(b[c]); 202 | else if(typeof b[c]["value"] !== "undefined" && typeof b[c] === "object" && (typeof b[c]["value"] === "number" || !b[c]["value"].match(/NULL/ig))) v.push(b[c]["value"]); 203 | a += (typeof b[c] === "object") ? 204 | (typeof b[c]["union"] === "undefined") ? 205 | (typeof b[c]["value"] === "string" && b[c]["value"].match(/NULL/ig)) ? 206 | "`" + c + "` " + b[c]["value"] : 207 | (typeof b[c]["operator"] !== "undefined")? 208 | "`" + c + "` " + b[c]["operator"] + " ? " : 209 | "`" + c + "` = ?" : 210 | (typeof b[c]["value"] === "string" && b[c]["value"].match(/NULL/ig)) ? 211 | "`" + c + "` " + b[c]["value"] + " " + b[c]["union"] + " " : 212 | (typeof b[c]["operator"] !== "undefined") ? 213 | "`" + c + "` " + b[c]["operator"] + " ? " + b[c]["union"] + " " : 214 | "`" + c + "` = ? " + b[c]["union"] + " " : 215 | (typeof b[c] === "string" && b[c].match(/NULL/ig)) ? 216 | "`" + c + "` " + b[c] : 217 | "`" + c + "` = ?" 218 | } 219 | return {w:a,p:v}; 220 | }, 221 | replace: function(a, c) { 222 | for (var b in c) { 223 | a = a.replace(new RegExp(b, "ig"), c[b]) 224 | } 225 | return a; 226 | }, 227 | addColumns: function(tableName, newColumns) { 228 | var queries = []; 229 | var values = []; 230 | for(var e in newColumns) { 231 | var b = "ALTER TABLE `{tableName}` ADD COLUMN {fields}; "; 232 | var l = "{type} {null}"; 233 | var c = []; 234 | var a = "`" + e + "` "; 235 | if(typeof newColumns[e]["null"]==="undefined") newColumns[e]["null"]="NULL"; 236 | for (var k in newColumns[e]) { 237 | l = l.replace(new RegExp("{" + k + "}", "ig"), newColumns[e][k]) 238 | } 239 | a += l; 240 | if (typeof newColumns[e]["default"] !== "undefined") { 241 | a += " DEFAULT " + newColumns[e]["default"] 242 | } 243 | if (typeof newColumns[e]["primary"] !== "undefined") { 244 | a += " PRIMARY KEY" 245 | } 246 | if (typeof newColumns[e]["auto_increment"] !== "undefined") { 247 | a += " AUTOINCREMENT" 248 | } 249 | if (Object.keys(newColumns)[Object.keys(newColumns).length - 1] != e) { 250 | a += "," 251 | } 252 | if (typeof newColumns[e]["primary"] !== "undefined" && newColumns[e]["primary"]) { 253 | c.push(e) 254 | } 255 | var d = { 256 | tableName: tableName, 257 | fields: a 258 | }; 259 | for (var f in d) { 260 | b = b.replace(new RegExp("{" + f + "}", "ig"), d[f]) 261 | } 262 | queries.push(b); 263 | values.push([]); 264 | } 265 | return this.executeQueries(queries, values); 266 | }, 267 | createTable: function(j, g) { 268 | var b = "CREATE TABLE IF NOT EXISTS `{tableName}` ({fields}); "; 269 | var c = []; 270 | var a = ""; 271 | for (var e in g) { 272 | var l = "{type} {null}"; 273 | a += "`" + e + "` "; 274 | if(typeof g[e]["null"]==="undefined") g[e]["null"]="NULL"; 275 | for (var k in g[e]) { 276 | l = l.replace(new RegExp("{" + k + "}", "ig"), g[e][k]) 277 | } 278 | a += l; 279 | if (typeof g[e]["default"] !== "undefined") { 280 | a += " DEFAULT " + g[e]["default"] 281 | } 282 | if (typeof g[e]["primary"] !== "undefined") { 283 | a += " PRIMARY KEY" 284 | } 285 | if (typeof g[e]["auto_increment"] !== "undefined") { 286 | a += " AUTOINCREMENT" 287 | } 288 | if (Object.keys(g)[Object.keys(g).length - 1] != e) { 289 | a += "," 290 | } 291 | if (typeof g[e]["primary"] !== "undefined" && g[e]["primary"]) { 292 | c.push(e) 293 | } 294 | } 295 | var d = { 296 | tableName: j, 297 | fields: a 298 | }; 299 | for (var f in d) { 300 | b = b.replace(new RegExp("{" + f + "}", "ig"), d[f]) 301 | } 302 | return this.executeQuery(b, []); 303 | }, 304 | createOrAlterTable: function(tableName, iColumns) { 305 | var self = this; 306 | return self.select("sqlite_master", { 307 | "type": { 308 | "value": 'table', 309 | "union": 'AND' 310 | }, 311 | "tbl_name": tableName 312 | }).then(function(results) { 313 | if(results.rows.length <= 0) { 314 | return self.createTable(tableName, iColumns) 315 | } else { 316 | for(var i=0; i < results.rows.length; ++i) { 317 | var sql = results.rows.item(i).sql 318 | var regexp = new RegExp("`[^`]+`", "ig") 319 | var currentColumns = sql.replace(/(CREATE TABLE `.*` \(|\))/gi, "").match(regexp) 320 | var newColumns = {}; 321 | for(var newColIdx in iColumns) { 322 | if(currentColumns.indexOf("`" + newColIdx + "`") == -1) { 323 | newColumns[newColIdx] = iColumns[newColIdx]; 324 | } 325 | } 326 | return self.addColumns(tableName, newColumns) 327 | } 328 | } 329 | }) 330 | }, 331 | dropTable: function(a) { 332 | return this.executeQuery("DROP TABLE IF EXISTS `" + a + "`; ", []); 333 | }, 334 | }; 335 | } catch (err) { 336 | console.error(err); 337 | } 338 | } 339 | } 340 | } 341 | ]); 342 | --------------------------------------------------------------------------------