Comparing version 1.1.3 to 1.2.0
{ | ||
"name": "squel", | ||
"version": "1.1.3", | ||
"version": "1.2.0", | ||
"main": "squel.js", | ||
@@ -5,0 +5,0 @@ "ignore": [ |
# Changelog for [squel](https://github.com/hiddentao/squel) | ||
## 2 Oct 2013 (1.2) | ||
* Switched from Make to Grunt | ||
* Added `fields()` method to SELECT builder (#29) | ||
* Expression trees can now be cloned (#31) | ||
* Added concept of SQL 'flavours' and merged in the Postgres `RETURNING` command #33 | ||
## 10 Jun 2013 (1.1.3) | ||
@@ -5,0 +12,0 @@ * Table names in SELECT queries can now be queries themselves (i.e. SQL sub statements) |
{ | ||
"name" : "squel", | ||
"description" : "SQL query string builder", | ||
"version" : "1.1.3", | ||
"author" : "Ramesh Nair <ram@hiddentao.com> (http://www.hiddentao.com/)", | ||
"contributors" : [ | ||
"Ramesh Nair <ram@hiddentao.com> (http://www.hiddentao.com/)", | ||
"nl_0 <nl.imbecile@gmail.com>" | ||
], | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"coffee-script" : "1.6.x", | ||
"docco" : "0.6.x", | ||
"uglify-js" : "1.3.x", | ||
"chai" : "1.5.x", | ||
"mocha" : "1.9.x", | ||
"sinon" : "1.6.x", | ||
"underscore" : "1.4.x" | ||
}, | ||
"keywords" : ["sql", "database", "rdbms"], | ||
"main" : "squel", | ||
"repository" : { | ||
"type" : "git", | ||
"url" : "https://github.com/hiddentao/squel.git" | ||
}, | ||
"engines": { "node": ">= 0.6.0" } | ||
"name": "squel", | ||
"description": "SQL query string builder", | ||
"version": "1.2.0", | ||
"author": "Ramesh Nair <ram@hiddentao.com> (http://www.hiddentao.com/)", | ||
"contributors": [ | ||
"Ramesh Nair <ram@hiddentao.com> (http://www.hiddentao.com/)", | ||
"nl_0 <nl.imbecile@gmail.com>" | ||
], | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"coffee-script": "~1.6.3", | ||
"docco": "0.6.x", | ||
"uglify-js": "1.3.x", | ||
"chai": "1.5.x", | ||
"mocha": "1.9.x", | ||
"sinon": "1.6.x", | ||
"underscore": "1.4.x", | ||
"grunt-contrib-coffee": "~0.7.0", | ||
"time-grunt": "~0.1.1", | ||
"grunt-contrib-clean": "~0.5.0", | ||
"load-grunt-tasks": "~0.1.0", | ||
"grunt": "~0.4.1", | ||
"grunt-contrib-uglify": "~0.2.4", | ||
"grunt-mocha-test": "~0.6.3", | ||
"grunt-shell": "~0.4.0" | ||
}, | ||
"keywords": [ | ||
"sql", | ||
"database", | ||
"rdbms" | ||
], | ||
"main": "squel", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/hiddentao/squel.git" | ||
}, | ||
"engines": { | ||
"node": ">= 0.6.0" | ||
} | ||
} | ||
@@ -1,4 +0,5 @@ | ||
# squel - SQL query string builder for Javascript | ||
# squel - SQL query string builder | ||
[![Build Status](https://secure.travis-ci.org/hiddentao/squel.png)](http://travis-ci.org/hiddentao/squel) | ||
[![Build Status](https://secure.travis-ci.org/hiddentao/squel.png)](http://travis-ci.org/hiddentao/squel) [![NPM module](https://badge.fury.io/js/squel.png)](https://badge.fury.io/js/squel) | ||
[![NPM](https://nodei.co/npm/squel.png?stars&downloads)](https://nodei.co/npm/cucumber/) | ||
@@ -11,6 +12,7 @@ A flexible and powerful SQL query string builder for Javascript. | ||
* Supports the standard SQL queries: SELECT, UPDATE, INSERT and DELETE. | ||
* Can be customized to support non-standard queries. | ||
* Supports non-standard commands for popular DB engines such as Postgres. | ||
* Can be customized to build any query or command of your choosing. | ||
* Uses method chaining for ease of use. | ||
* Well tested (~240 tests). | ||
* Small: ~4 KB minified and gzipped | ||
* Well tested (~290 tests). | ||
* Small: <4 KB minified and gzipped | ||
@@ -33,3 +35,3 @@ ## Installation | ||
<script type="text/javascript" src="https://rawgithub.com/hiddentao/squel/master/squel.min.js"></script> | ||
<script type="text/javascript" src="https://rawgithub.com/hiddentao/squel/master/squel-basic.min.js"></script> | ||
@@ -39,2 +41,10 @@ **NOTE: It is recommended that you do NOT create queries browser-side to run on the server as this massively increases | ||
## Available files | ||
* `squel.js` - unminified version of Squel with the standard commands and all available non-standard commands added | ||
* `squel.min.js` - minified version of `squel.js` | ||
* `squel-basic.js` - unminified version of Squel with only the standard SQL commands | ||
* `squel-basic.min.js` - minified version of `squel-basic.js` | ||
## Examples | ||
@@ -255,22 +265,46 @@ | ||
## Documentation | ||
## Non-standard SQL | ||
Full API documentation is available at [http://squeljs.org/](http://squeljs.org/). | ||
Squel supports the standard SQL commands and reserved words. However a number of database engines provide their own | ||
non-standard commands. To make things easy Squel allows for different 'flavours' of SQL to be loaded and used. | ||
Annotated source code can be found in the `docs/` folder. This is built using | ||
[docco](http://jashkenas.github.com/docco/). To build it yourself you will first need to have the latest dev version | ||
of [pygment](http://pygments.org/download/) installed in your local Python environment. Then do the following inside | ||
the project folder: | ||
At the moment Squel provides a Postgres flavour which augments query builders with additional commands (e.g. `INSERT ... RETURNING`) | ||
for use with the Postgres database engine. | ||
$ npm install | ||
$ make docs | ||
To use this in node.js: | ||
## Testing | ||
var squel = require('squel').useFlavour('postgres'); | ||
Tests are written in [Mocha](http://visionmedia.github.com/mocha/) and can be found in the `test/` folder. To run them do the following: | ||
For the browser: | ||
<script type="text/javascript" src="https://rawgithub.com/hiddentao/squel/master/squel.min.js"></script> | ||
<script type="text/javascript"> | ||
squel.useFlavour('postgres'); | ||
</script> | ||
(Internally the flavour setup method simply utilizes the [custom query mechanism](http://hiddentao.github.io/squel/#custom_queries) to effect changes). | ||
Read the the [API docs](http://hiddentao.github.io/squel/api.html) to find out available commands. Flavours of SQL which get added to | ||
Squel in the future will be usable in the above manner. | ||
## Building it | ||
We use Grunt to do the build and [docco](http://jashkenas.github.com/docco/) to build annotated source code docs. | ||
$ npm install -g grunt-cli | ||
$ npm install -g docco | ||
$ npm install | ||
$ make test | ||
$ grunt <-- this will build the code and run the tests | ||
Annotated source code can be found in the `docs/` folder. | ||
Tests are written in [Mocha](http://visionmedia.github.com/mocha/) and can be found in the `test/` folder. To run them: | ||
$ grunt test | ||
## Documentation | ||
Full documentation (guide and API) is available at [http://squeljs.org/](http://squeljs.org/). | ||
## Contributing | ||
@@ -277,0 +311,0 @@ |
270
squel.js
@@ -1,3 +0,1 @@ | ||
// Generated by CoffeeScript 1.3.3 | ||
/* | ||
@@ -30,3 +28,3 @@ Copyright (c) 2012-2013 Ramesh Nair (hiddentao.com) | ||
(function() { | ||
var cls, getValueHandler, registerValueHandler, squel, _extend, | ||
var cls, getValueHandler, registerValueHandler, squel, _extend, _ref, _ref1, _ref2, | ||
__slice = [].slice, | ||
@@ -110,3 +108,2 @@ __hasProp = {}.hasOwnProperty, | ||
cls.Cloneable = (function() { | ||
function Cloneable() {} | ||
@@ -125,3 +122,2 @@ | ||
cls.BaseBuilder = (function(_super) { | ||
__extends(BaseBuilder, _super); | ||
@@ -267,5 +263,7 @@ | ||
cls.Expression = (function() { | ||
cls.Expression = (function(_super) { | ||
var _toString; | ||
__extends(Expression, _super); | ||
Expression.prototype.tree = null; | ||
@@ -364,12 +362,46 @@ | ||
/* | ||
Clone this expression. | ||
Note that the algorithm contained within this method is probably non-optimal, so please avoid cloning large | ||
expression trees. | ||
*/ | ||
Expression.prototype.clone = function() { | ||
var newInstance, _cloneTree; | ||
newInstance = new this.constructor; | ||
(_cloneTree = function(node) { | ||
var child, _i, _len, _ref, _results; | ||
_ref = node.nodes; | ||
_results = []; | ||
for (_i = 0, _len = _ref.length; _i < _len; _i++) { | ||
child = _ref[_i]; | ||
if (child.expr != null) { | ||
_results.push(newInstance.current.nodes.push(JSON.parse(JSON.stringify(child)))); | ||
} else { | ||
newInstance._begin(child.type); | ||
_cloneTree(child); | ||
if (!this.current === child) { | ||
_results.push(newInstance.end()); | ||
} else { | ||
_results.push(void 0); | ||
} | ||
} | ||
} | ||
return _results; | ||
})(this.tree); | ||
return newInstance; | ||
}; | ||
return Expression; | ||
})(); | ||
})(cls.Cloneable); | ||
cls.Block = (function(_super) { | ||
__extends(Block, _super); | ||
function Block() { | ||
return Block.__super__.constructor.apply(this, arguments); | ||
_ref = Block.__super__.constructor.apply(this, arguments); | ||
return _ref; | ||
} | ||
@@ -398,3 +430,2 @@ | ||
cls.StringBlock = (function(_super) { | ||
__extends(StringBlock, _super); | ||
@@ -416,3 +447,2 @@ | ||
cls.AbstractTableBlock = (function(_super) { | ||
__extends(AbstractTableBlock, _super); | ||
@@ -443,3 +473,3 @@ | ||
AbstractTableBlock.prototype.buildStr = function(queryBuilder) { | ||
var table, tables, _i, _len, _ref; | ||
var table, tables, _i, _len, _ref1; | ||
if (0 >= this.tables.length) { | ||
@@ -449,5 +479,5 @@ throw new Error("_table() needs to be called"); | ||
tables = ""; | ||
_ref = this.tables; | ||
for (_i = 0, _len = _ref.length; _i < _len; _i++) { | ||
table = _ref[_i]; | ||
_ref1 = this.tables; | ||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) { | ||
table = _ref1[_i]; | ||
if ("" !== tables) { | ||
@@ -473,7 +503,7 @@ tables += ", "; | ||
cls.UpdateTableBlock = (function(_super) { | ||
__extends(UpdateTableBlock, _super); | ||
function UpdateTableBlock() { | ||
return UpdateTableBlock.__super__.constructor.apply(this, arguments); | ||
_ref1 = UpdateTableBlock.__super__.constructor.apply(this, arguments); | ||
return _ref1; | ||
} | ||
@@ -493,7 +523,7 @@ | ||
cls.FromTableBlock = (function(_super) { | ||
__extends(FromTableBlock, _super); | ||
function FromTableBlock() { | ||
return FromTableBlock.__super__.constructor.apply(this, arguments); | ||
_ref2 = FromTableBlock.__super__.constructor.apply(this, arguments); | ||
return _ref2; | ||
} | ||
@@ -522,3 +552,2 @@ | ||
cls.IntoTableBlock = (function(_super) { | ||
__extends(IntoTableBlock, _super); | ||
@@ -547,3 +576,2 @@ | ||
cls.GetFieldBlock = (function(_super) { | ||
__extends(GetFieldBlock, _super); | ||
@@ -553,5 +581,15 @@ | ||
GetFieldBlock.__super__.constructor.call(this, options); | ||
this.fields = []; | ||
this._fields = []; | ||
} | ||
GetFieldBlock.prototype.fields = function(_fields) { | ||
var alias, field, _results; | ||
_results = []; | ||
for (field in _fields) { | ||
alias = _fields[field]; | ||
_results.push(this.field(field, alias)); | ||
} | ||
return _results; | ||
}; | ||
GetFieldBlock.prototype.field = function(field, alias) { | ||
@@ -565,3 +603,3 @@ if (alias == null) { | ||
} | ||
return this.fields.push({ | ||
return this._fields.push({ | ||
name: field, | ||
@@ -573,7 +611,7 @@ alias: alias | ||
GetFieldBlock.prototype.buildStr = function(queryBuilder) { | ||
var field, fields, _i, _len, _ref; | ||
var field, fields, _i, _len, _ref3; | ||
fields = ""; | ||
_ref = this.fields; | ||
for (_i = 0, _len = _ref.length; _i < _len; _i++) { | ||
field = _ref[_i]; | ||
_ref3 = this._fields; | ||
for (_i = 0, _len = _ref3.length; _i < _len; _i++) { | ||
field = _ref3[_i]; | ||
if ("" !== fields) { | ||
@@ -599,3 +637,2 @@ fields += ", "; | ||
cls.SetFieldBlock = (function(_super) { | ||
__extends(SetFieldBlock, _super); | ||
@@ -618,7 +655,7 @@ | ||
fieldNames = (function() { | ||
var _ref, _results; | ||
_ref = this.fields; | ||
var _ref3, _results; | ||
_ref3 = this.fields; | ||
_results = []; | ||
for (field in _ref) { | ||
if (!__hasProp.call(_ref, field)) continue; | ||
for (field in _ref3) { | ||
if (!__hasProp.call(_ref3, field)) continue; | ||
_results.push(field); | ||
@@ -647,3 +684,2 @@ } | ||
cls.InsertFieldValueBlock = (function(_super) { | ||
__extends(InsertFieldValueBlock, _super); | ||
@@ -659,7 +695,7 @@ | ||
fieldNames = (function() { | ||
var _ref, _results; | ||
_ref = this.fields; | ||
var _ref3, _results; | ||
_ref3 = this.fields; | ||
_results = []; | ||
for (name in _ref) { | ||
if (!__hasProp.call(_ref, name)) continue; | ||
for (name in _ref3) { | ||
if (!__hasProp.call(_ref3, name)) continue; | ||
_results.push(name); | ||
@@ -693,3 +729,2 @@ } | ||
cls.DistinctBlock = (function(_super) { | ||
__extends(DistinctBlock, _super); | ||
@@ -719,3 +754,2 @@ | ||
cls.GroupByBlock = (function(_super) { | ||
__extends(GroupByBlock, _super); | ||
@@ -734,8 +768,8 @@ | ||
GroupByBlock.prototype.buildStr = function(queryBuilder) { | ||
var f, groups, _i, _len, _ref; | ||
var f, groups, _i, _len, _ref3; | ||
groups = ""; | ||
if (0 < this.groups.length) { | ||
_ref = this.groups; | ||
for (_i = 0, _len = _ref.length; _i < _len; _i++) { | ||
f = _ref[_i]; | ||
_ref3 = this.groups; | ||
for (_i = 0, _len = _ref3.length; _i < _len; _i++) { | ||
f = _ref3[_i]; | ||
if ("" !== groups) { | ||
@@ -756,3 +790,2 @@ groups += ", "; | ||
cls.OffsetBlock = (function(_super) { | ||
__extends(OffsetBlock, _super); | ||
@@ -783,3 +816,2 @@ | ||
cls.WhereBlock = (function(_super) { | ||
__extends(WhereBlock, _super); | ||
@@ -828,3 +860,2 @@ | ||
cls.OrderByBlock = (function(_super) { | ||
__extends(OrderByBlock, _super); | ||
@@ -849,8 +880,8 @@ | ||
OrderByBlock.prototype.buildStr = function(queryBuilder) { | ||
var o, orders, _i, _len, _ref; | ||
var o, orders, _i, _len, _ref3; | ||
if (0 < this.orders.length) { | ||
orders = ""; | ||
_ref = this.orders; | ||
for (_i = 0, _len = _ref.length; _i < _len; _i++) { | ||
o = _ref[_i]; | ||
_ref3 = this.orders; | ||
for (_i = 0, _len = _ref3.length; _i < _len; _i++) { | ||
o = _ref3[_i]; | ||
if ("" !== orders) { | ||
@@ -872,3 +903,2 @@ orders += ", "; | ||
cls.LimitBlock = (function(_super) { | ||
__extends(LimitBlock, _super); | ||
@@ -899,3 +929,2 @@ | ||
cls.JoinBlock = (function(_super) { | ||
__extends(JoinBlock, _super); | ||
@@ -965,7 +994,7 @@ | ||
JoinBlock.prototype.buildStr = function(queryBuilder) { | ||
var j, joins, _i, _len, _ref; | ||
var j, joins, _i, _len, _ref3; | ||
joins = ""; | ||
_ref = this.joins || []; | ||
for (_i = 0, _len = _ref.length; _i < _len; _i++) { | ||
j = _ref[_i]; | ||
_ref3 = this.joins || []; | ||
for (_i = 0, _len = _ref3.length; _i < _len; _i++) { | ||
j = _ref3[_i]; | ||
if (joins !== "") { | ||
@@ -995,14 +1024,13 @@ joins += " "; | ||
cls.QueryBuilder = (function(_super) { | ||
__extends(QueryBuilder, _super); | ||
function QueryBuilder(options, blocks) { | ||
var block, methodBody, methodName, _fn, _i, _len, _ref, _ref1, | ||
var block, methodBody, methodName, _fn, _i, _len, _ref3, _ref4, | ||
_this = this; | ||
QueryBuilder.__super__.constructor.call(this, options); | ||
this.blocks = blocks || []; | ||
_ref = this.blocks; | ||
for (_i = 0, _len = _ref.length; _i < _len; _i++) { | ||
block = _ref[_i]; | ||
_ref1 = block.exposedMethods(); | ||
_ref3 = this.blocks; | ||
for (_i = 0, _len = _ref3.length; _i < _len; _i++) { | ||
block = _ref3[_i]; | ||
_ref4 = block.exposedMethods(); | ||
_fn = function(block, name, body) { | ||
@@ -1014,4 +1042,4 @@ return _this[name] = function() { | ||
}; | ||
for (methodName in _ref1) { | ||
methodBody = _ref1[methodName]; | ||
for (methodName in _ref4) { | ||
methodBody = _ref4[methodName]; | ||
if (this[methodName] != null) { | ||
@@ -1026,6 +1054,6 @@ throw new Error("" + (this._getObjectClassName(this)) + " already has a builder method called: " + methodName); | ||
QueryBuilder.prototype.registerValueHandler = function(type, handler) { | ||
var block, _i, _len, _ref; | ||
_ref = this.blocks; | ||
for (_i = 0, _len = _ref.length; _i < _len; _i++) { | ||
block = _ref[_i]; | ||
var block, _i, _len, _ref3; | ||
_ref3 = this.blocks; | ||
for (_i = 0, _len = _ref3.length; _i < _len; _i++) { | ||
block = _ref3[_i]; | ||
block.registerValueHandler(type, handler); | ||
@@ -1038,8 +1066,8 @@ } | ||
QueryBuilder.prototype.updateOptions = function(options) { | ||
var block, _i, _len, _ref, _results; | ||
var block, _i, _len, _ref3, _results; | ||
this.options = _extend({}, this.options, options); | ||
_ref = this.blocks; | ||
_ref3 = this.blocks; | ||
_results = []; | ||
for (_i = 0, _len = _ref.length; _i < _len; _i++) { | ||
block = _ref[_i]; | ||
for (_i = 0, _len = _ref3.length; _i < _len; _i++) { | ||
block = _ref3[_i]; | ||
_results.push(block.options = _extend({}, block.options, options)); | ||
@@ -1053,7 +1081,7 @@ } | ||
return ((function() { | ||
var _i, _len, _ref, _results; | ||
_ref = this.blocks; | ||
var _i, _len, _ref3, _results; | ||
_ref3 = this.blocks; | ||
_results = []; | ||
for (_i = 0, _len = _ref.length; _i < _len; _i++) { | ||
block = _ref[_i]; | ||
for (_i = 0, _len = _ref3.length; _i < _len; _i++) { | ||
block = _ref3[_i]; | ||
_results.push(block.buildStr(this)); | ||
@@ -1070,7 +1098,7 @@ } | ||
return new this.constructor(this.options, (function() { | ||
var _i, _len, _ref, _results; | ||
_ref = this.blocks; | ||
var _i, _len, _ref3, _results; | ||
_ref3 = this.blocks; | ||
_results = []; | ||
for (_i = 0, _len = _ref.length; _i < _len; _i++) { | ||
block = _ref[_i]; | ||
for (_i = 0, _len = _ref3.length; _i < _len; _i++) { | ||
block = _ref3[_i]; | ||
_results.push(block.clone()); | ||
@@ -1091,3 +1119,2 @@ } | ||
cls.Select = (function(_super) { | ||
__extends(Select, _super); | ||
@@ -1118,3 +1145,2 @@ | ||
cls.Update = (function(_super) { | ||
__extends(Update, _super); | ||
@@ -1135,3 +1161,2 @@ | ||
cls.Delete = (function(_super) { | ||
__extends(Delete, _super); | ||
@@ -1156,3 +1181,2 @@ | ||
cls.Insert = (function(_super) { | ||
__extends(Insert, _super); | ||
@@ -1207,2 +1231,80 @@ | ||
squel.flavours = {}; | ||
squel.useFlavour = function(flavour) { | ||
if (squel.flavours[flavour] instanceof Function) { | ||
squel.flavours[flavour].call(null, squel); | ||
} else { | ||
throw new Error("Flavour not available: " + flavour); | ||
} | ||
return squel; | ||
}; | ||
/* | ||
Copyright (c) 2012-2013 Ramesh Nair (hiddentao.com) | ||
Permission is hereby granted, free of charge, to any person | ||
obtaining a copy of this software and associated documentation | ||
files (the "Software"), to deal in the Software without | ||
restriction, including without limitation the rights to use, | ||
copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the | ||
Software is furnished to do so, subject to the following | ||
conditions: | ||
The above copyright notice and this permission notice shall be | ||
included in all copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | ||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | ||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
OTHER DEALINGS IN THE SOFTWARE. | ||
*/ | ||
squel.flavours['postgres'] = function() { | ||
cls = squel.cls; | ||
cls.ReturningBlock = (function(_super) { | ||
__extends(ReturningBlock, _super); | ||
function ReturningBlock(options) { | ||
ReturningBlock.__super__.constructor.call(this, options); | ||
this._str = null; | ||
} | ||
ReturningBlock.prototype.returning = function(ret) { | ||
return this._str = this._sanitizeField(ret); | ||
}; | ||
ReturningBlock.prototype.buildStr = function() { | ||
if (this._str) { | ||
return "RETURNING " + this._str; | ||
} else { | ||
return ""; | ||
} | ||
}; | ||
return ReturningBlock; | ||
})(cls.Block); | ||
return cls.Insert = (function(_super) { | ||
__extends(Insert, _super); | ||
function Insert(options, blocks) { | ||
if (blocks == null) { | ||
blocks = null; | ||
} | ||
blocks || (blocks = [new cls.StringBlock(options, 'INSERT'), new cls.IntoTableBlock(options), new cls.InsertFieldValueBlock(options), new cls.ReturningBlock(options)]); | ||
Insert.__super__.constructor.call(this, options, blocks); | ||
} | ||
return Insert; | ||
})(cls.QueryBuilder); | ||
}; | ||
}).call(this); |
99429
9
2184
344
15