Comparing version 1.1.1 to 1.1.2
# Changelog for [squel](https://github.com/hiddentao/squel) | ||
## 2 Jun 2013 (1.1.2) | ||
* Parameterised WHERE clauses now supported. | ||
* Custom value types can now be handled in a special way. Global and per-instance handlers supported. | ||
## 27 Mar 2013 (1.1) | ||
@@ -5,0 +10,0 @@ * Squel can now be customized to include proprietary commands and queries. |
{ | ||
"name": "squel", | ||
"description": "SQL query string builder", | ||
"version": "1.1.1", | ||
"author": "Ramesh Nair <ram@hiddentao.com> (http://www.hiddentao.com/)", | ||
"contributors": [ | ||
"name" : "squel", | ||
"description" : "SQL query string builder", | ||
"version" : "1.1.2", | ||
"author" : "Ramesh Nair <ram@hiddentao.com> (http://www.hiddentao.com/)", | ||
"contributors" : [ | ||
"Ramesh Nair <ram@hiddentao.com> (http://www.hiddentao.com/)", | ||
@@ -12,15 +12,15 @@ "nl_0 <nl.imbecile@gmail.com>" | ||
"devDependencies": { | ||
"coffee-script": "1.3", | ||
"docco": "0.3", | ||
"uglify-js": "1.3", | ||
"mocha": "1.6.0", | ||
"chai": "1.3.0", | ||
"sinon": "1.5.0", | ||
"underscore": "1.4.3" | ||
"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" :{ | ||
"keywords" : ["sql", "database", "rdbms"], | ||
"main" : "squel", | ||
"repository" : { | ||
"type" : "git", | ||
"url" : "https://github.com/hiddentao/squel.git" | ||
"url" : "https://github.com/hiddentao/squel.git" | ||
}, | ||
@@ -27,0 +27,0 @@ "engines": { "node": ">= 0.6.0" } |
@@ -14,3 +14,3 @@ # squel - SQL query string builder for Javascript | ||
* Well tested (~240 tests). | ||
* Small: ~3.6 KB minified and gzipped | ||
* Small: ~4 KB minified and gzipped | ||
@@ -115,3 +115,3 @@ ## Installation | ||
.from("table1") | ||
.where("table1.id = 2") | ||
.where("table1.id = ?", 2) | ||
.order("id", false) | ||
@@ -151,2 +151,22 @@ .limit(2) | ||
**Custom value types** | ||
By default Squel does not support the use of object instances as field values. Instead it lets you tell it how you want | ||
specific object types to be handled: | ||
// handler for objects of type Date | ||
squel.registerValueHandler(Date, function(date) { | ||
return date.getFullYear() + '/' + date.getMonth() + '/' + date.getDate(); | ||
}); | ||
squel.update(). | ||
.table('students') | ||
.set('start_date', new Date(2013, 5, 1)) | ||
.toString() | ||
// UPDATE students SET start_date = '2013/5/1' | ||
_Note that custom value handlers can be overridden on a per-instance basis (see the [docs](http://squeljs.org/))_ | ||
**Custom queries** | ||
@@ -153,0 +173,0 @@ |
110
squel.js
@@ -30,3 +30,3 @@ // Generated by CoffeeScript 1.3.3 | ||
(function() { | ||
var cls, squel, _extend, | ||
var cls, getValueHandler, registerValueHandler, squel, _extend, | ||
__slice = [].slice, | ||
@@ -63,5 +63,48 @@ __hasProp = {}.hasOwnProperty, | ||
fieldAliasQuoteCharacter: '"', | ||
usingValuePlaceholders: false | ||
usingValuePlaceholders: false, | ||
valueHandlers: [] | ||
}; | ||
cls.globalValueHandlers = []; | ||
registerValueHandler = function(handlers, type, handler) { | ||
var typeHandler, _i, _len; | ||
if ('function' !== typeof type) { | ||
throw new Error("type must be a class constructor"); | ||
} | ||
if ('function' !== typeof handler) { | ||
throw new Error("handler must be a function"); | ||
} | ||
for (_i = 0, _len = handlers.length; _i < _len; _i++) { | ||
typeHandler = handlers[_i]; | ||
if (typeHandler.type === type) { | ||
typeHandler.handler = handler; | ||
return; | ||
} | ||
} | ||
return handlers.push({ | ||
type: type, | ||
handler: handler | ||
}); | ||
}; | ||
getValueHandler = function() { | ||
var handlerLists, handlers, typeHandler, value, _i, _j, _len, _len1; | ||
value = arguments[0], handlerLists = 2 <= arguments.length ? __slice.call(arguments, 1) : []; | ||
for (_i = 0, _len = handlerLists.length; _i < _len; _i++) { | ||
handlers = handlerLists[_i]; | ||
for (_j = 0, _len1 = handlers.length; _j < _len1; _j++) { | ||
typeHandler = handlers[_j]; | ||
if (value instanceof typeHandler.type) { | ||
return typeHandler.handler; | ||
} | ||
} | ||
} | ||
return void 0; | ||
}; | ||
cls.registerValueHandler = function(type, handler) { | ||
return registerValueHandler(cls.globalValueHandlers, type, handler); | ||
}; | ||
cls.Cloneable = (function() { | ||
@@ -86,5 +129,12 @@ | ||
function BaseBuilder(options) { | ||
this.options = _extend({}, cls.DefaultQueryBuilderOptions, options); | ||
var defaults; | ||
defaults = JSON.parse(JSON.stringify(cls.DefaultQueryBuilderOptions)); | ||
this.options = _extend({}, defaults, options); | ||
} | ||
BaseBuilder.prototype.registerValueHandler = function(type, handler) { | ||
registerValueHandler(this.options.valueHandlers, type, handler); | ||
return this; | ||
}; | ||
BaseBuilder.prototype._getObjectClassName = function(obj) { | ||
@@ -161,3 +211,3 @@ var arr; | ||
if (0 > value || isNaN(value)) { | ||
throw new Error("limit/offset must be >=0"); | ||
throw new Error("limit/offset must be >= 0"); | ||
} | ||
@@ -168,6 +218,13 @@ return value; | ||
BaseBuilder.prototype._sanitizeValue = function(item) { | ||
var t; | ||
t = typeof item; | ||
if (null !== item && "string" !== t && "number" !== t && "boolean" !== t) { | ||
throw new Error("field value must be a string, number, boolean or null"); | ||
var itemType, typeIsValid; | ||
itemType = typeof item; | ||
if (null === item) { | ||
} else if ("string" === itemType || "number" === itemType || "boolean" === itemType) { | ||
} else { | ||
typeIsValid = void 0 !== getValueHandler(item, this.options.valueHandlers, cls.globalValueHandlers); | ||
if (!typeIsValid) { | ||
throw new Error("field value must be a string, number, boolean, null or one of the registered custom value types"); | ||
} | ||
} | ||
@@ -178,2 +235,7 @@ return item; | ||
BaseBuilder.prototype._formatValue = function(value) { | ||
var customHandler; | ||
customHandler = getValueHandler(value, this.options.valueHandlers, cls.globalValueHandlers); | ||
if (customHandler) { | ||
value = customHandler(value); | ||
} | ||
if (null === value) { | ||
@@ -705,4 +767,20 @@ value = "NULL"; | ||
WhereBlock.prototype.where = function(condition) { | ||
WhereBlock.prototype.where = function() { | ||
var condition, inValues, item, value, values, _i, _j, _len, _len1; | ||
condition = arguments[0], values = 2 <= arguments.length ? __slice.call(arguments, 1) : []; | ||
condition = this._sanitizeCondition(condition); | ||
for (_i = 0, _len = values.length; _i < _len; _i++) { | ||
value = values[_i]; | ||
if (Array.isArray(value)) { | ||
inValues = []; | ||
for (_j = 0, _len1 = value.length; _j < _len1; _j++) { | ||
item = value[_j]; | ||
inValues.push(this._formatValue(this._sanitizeValue(item))); | ||
} | ||
value = "(" + (inValues.join(', ')) + ")"; | ||
} else { | ||
value = this._formatValue(this._sanitizeValue(value)); | ||
} | ||
condition = condition.replace('?', value); | ||
} | ||
if ("" !== condition) { | ||
@@ -911,2 +989,13 @@ return this.wheres.push(condition); | ||
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]; | ||
block.registerValueHandler(type, handler); | ||
} | ||
QueryBuilder.__super__.registerValueHandler.call(this, type, handler); | ||
return this; | ||
}; | ||
QueryBuilder.prototype.updateOptions = function(options) { | ||
@@ -1041,3 +1130,4 @@ var block, _i, _len, _ref, _results; | ||
return new cls.Delete(options, blocks); | ||
} | ||
}, | ||
registerValueHandler: cls.registerValueHandler | ||
}; | ||
@@ -1044,0 +1134,0 @@ |
296
41568
5
948