Skip to content

Commit

Permalink
added WHERE array support
Browse files Browse the repository at this point in the history
  • Loading branch information
syntacticx committed Feb 13, 2009
1 parent 11c8ae2 commit 497b164
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 22 deletions.
19 changes: 19 additions & 0 deletions src/active_record/adapters.js
Expand Up @@ -94,6 +94,25 @@ ActiveRecord.execute = function execute()
return ActiveRecord.connection.executeSQL.apply(ActiveRecord.connection, arguments);
};

/**
* Escapes a given argument for use in a SQL string. By default
* the argument passed will also be enclosed in quotes.
* @alias ActiveRecord.escape
* @param {mixed} argument
* @param {Boolean} [supress_quotes] Defaults to false.
* @return {mixed}
* ActiveRecord.escape(5) == 5
* ActiveRecord.escape('tes"t') == '"tes\"t"';
*/
ActiveRecord.escape = function escape(argument,supress_quotes)
{
var quote = supress_quotes ? '' : '"';
return typeof(argument) == 'number'
? argument
: quote + (new String(argument)).toString().replace(/\"/g,'\\"').replace(/\\/g,'\\\\').replace(/\0/g,'\\0') + quote
;
};

Adapters.InstanceMethods = {
setValueFromFieldIfValueIsNull: function setValueFromFieldIfValueIsNull(field,value)
{
Expand Down
23 changes: 16 additions & 7 deletions src/active_record/adapters/in_memory.js
Expand Up @@ -187,10 +187,7 @@ ActiveSupport.extend(Adapters.InMemory.prototype,{
var sql_args = ActiveSupport.arrayFrom(arguments).slice(1);
for(var i = 0; i < sql_args.length; ++i)
{
sql = sql.replace(/\?/,typeof(sql_args[i]) == 'number'
? sql_args[i]
: '"' + (new String(sql_args[i])).toString().replace(/\"/g,'\\"').replace(/\\/g,'\\\\').replace(/\0/g,'\\0') + '"'
);
sql = sql.replace(/\?/,ActiveRecord.escape(sql_args[i]));
}
var response = this.paramsFromSQLString(sql);
table = response[0];
Expand Down Expand Up @@ -318,8 +315,18 @@ ActiveSupport.extend(Adapters.InMemory.prototype,{
}
},
createWhere: function createWhere(where)
{
if(typeof(where) === 'string'){
{
if(ActiveSupport.isArray(where))
{
var where_fragment = where[0];
for(var i = 1; i < where.length; ++i)
{
where_fragment = where_fragment.replace(/\?/,ActiveRecord.escape(where[i]));
}
where = where_fragment;
}
if(typeof(where) === 'string')
{
return function json_result_where_processor(result_set)
{
var response = [];
Expand All @@ -334,7 +341,9 @@ ActiveSupport.extend(Adapters.InMemory.prototype,{
}
return response;
};
}else{
}
else
{
return function json_result_where_processor(result_set)
{
var response = [];
Expand Down
10 changes: 9 additions & 1 deletion src/active_record/adapters/sql.js
Expand Up @@ -170,7 +170,15 @@ Adapters.SQL = {
buildWhereSQLFragment: function buildWhereSQLFragment(fragment, args)
{
var where, keys, i;
if(fragment && typeof(fragment) !== "string")
if(fragment && ActiveSupport.isArray(fragment))
{
for(i = 1; i < fragment.length; ++i)
{
args.push(fragment[i]);
}
return ' WHERE ' + fragment[0];
}
else if(fragment && typeof(fragment) !== "string")
{
where = '';
keys = ActiveSupport.keys(fragment);
Expand Down
6 changes: 5 additions & 1 deletion src/active_record/base.js
Expand Up @@ -267,7 +267,7 @@ ActiveSupport.extend(ActiveRecord.ClassMethods,{
* @param {mixed} params
* Can be an integer to try and find a record by id, a complete SQL statement String, or Object of params, params may contain:
* select: Array of columns to select (default ['*'])
* where: String or Object
* where: String or Object or Array
* joins: String
* order: String
* limit: Number
Expand All @@ -284,6 +284,10 @@ ActiveSupport.extend(ActiveRecord.ClassMethods,{
* id: 5
* }
* });
* var user = User.find({
* first: true,
* where: ['id = ?',5]
* });
* var users = User.find(); //finds all
* var users = User.find({
* where: 'name = "alice" AND password = "' + md5('pass') + '"',
Expand Down
1 change: 0 additions & 1 deletion test/active_record/date.js
Expand Up @@ -63,7 +63,6 @@ ActiveTest.Tests.ActiveRecord.date = function(proceed)
reload_test.reload();
reload_test.save();
reload_test.reload();
//ActiveSupport.dateFormat(reload_test.get('updated'),'yyyy-mm-dd HH:MM:ss');
assert(reload_test.get('created').toString() == old_created.toString(),'created time is preserved on update');

if(proceed)
Expand Down
5 changes: 5 additions & 0 deletions test/active_record/finders.js
Expand Up @@ -66,6 +66,11 @@ ActiveTest.Tests.ActiveRecord.finders = function(proceed)
}).title == 'b','find({first: true, where: string})');
b = Comment.find('SELECT * FROM comments WHERE title = ? LIMIT 1','b');
assert(b[0] && b[0].title == 'b','find(SQL string with WHERE, LIMIT and param substituion)');
b = Comment.find({
where: ['title = ?','b'],
limit: 1
});
assert(b[0] && b[0].title == 'b','find(SQL string with WHERE, LIMIT and param substituion via find)');

assert(Comment.find().length == 3 && Comment.find({all: true}).length == 3,'find({all: true})');

Expand Down
36 changes: 36 additions & 0 deletions test/active_view/binding.js
@@ -0,0 +1,36 @@
/* ***** BEGIN LICENSE BLOCK *****
*
* Copyright (c) 2009 Aptana, Inc.
*
* 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.
*
* ***** END LICENSE BLOCK ***** */

ActiveTest.Tests.View.binding = function(proceed)
{
with(ActiveTest)
{

if(proceed)
proceed()
}
};
27 changes: 15 additions & 12 deletions test/test.js
Expand Up @@ -497,22 +497,21 @@ ActiveTest.Tests.ActiveRecord.date = function(proceed)
var a = ModelWithDates.create({
name: 'a'
});
assert(a.get('created').match(/^\d{4}/) && a.get('updated').match(/^\d{4}/),'created and updated set via date field');
assert(ActiveSupport.dateFormat(a.get('created'),'yyyy-mm-dd HH:MM:ss').match(/^\d{4}/) && ActiveSupport.dateFormat(a.get('updated'),'yyyy-mm-dd HH:MM:ss').match(/^\d{4}/),'created and updated set via date field');
var old_date = a.get('updated');
a.set('updated','');
a.save();
var new_date = a.get('updated');
var saved_date = ModelWithDates.find(a.id).get('updated');
if(saved_date instanceof Date){
saved_date = ActiveSupport.dateFormat(saved_date,'yyyy-mm-dd HH:MM:ss',true);
}
assert(saved_date == new_date,'created and updated persist via date field');
assert(saved_date.toString() == new_date.toString(),'created and updated persist via date field');

//make sure dates are preserved
var reload_test = ModelWithDates.find(a.id);
var old_created = reload_test.get('created');
reload_test.save();
reload_test.reload();
reload_test.save();
reload_test.reload();
assert(reload_test.get('created').toString() == old_created.toString(),'created time is preserved on update');

if(proceed)
Expand Down Expand Up @@ -562,6 +561,11 @@ ActiveTest.Tests.ActiveRecord.finders = function(proceed)
}).title == 'b','find({first: true, where: string})');
b = Comment.find('SELECT * FROM comments WHERE title = ? LIMIT 1','b');
assert(b[0] && b[0].title == 'b','find(SQL string with WHERE, LIMIT and param substituion)');
b = Comment.find({
where: ['title = ?','b'],
limit: 1
});
assert(b[0] && b[0].title == 'b','find(SQL string with WHERE, LIMIT and param substituion via find)');

assert(Comment.find().length == 3 && Comment.find({all: true}).length == 3,'find({all: true})');

Expand Down Expand Up @@ -1414,7 +1418,7 @@ ActiveTest.Tests.Routes.matching = function(proceed)
var routes_without_params = new ActiveRoutes([
['index','/home',{object: 'page',method: 'index'}],
['contact','pages/contact',{object: 'page', method: 'index'}],
['/pages/about/',{object: 'page',method: 'about'}],
['/pages/about/',{object: 'page',method: 'about'}]
],test_scope);

assert(routes_without_params.match('/home').name == 'index','match() /home');
Expand All @@ -1434,7 +1438,7 @@ ActiveTest.Tests.Routes.matching = function(proceed)
//test index handling
var routes_without_params = new ActiveRoutes([
['index','pages',{object: 'page',method: 'index'}],
['contact','pages/contact',{object: 'page', method: 'index'}],
['contact','pages/contact',{object: 'page', method: 'index'}]
],test_scope);

assert(routes_without_params.match('pages').name == 'index','index match() pages');
Expand All @@ -1444,7 +1448,7 @@ ActiveTest.Tests.Routes.matching = function(proceed)

var routes_without_params = new ActiveRoutes([
['index','pages/index',{object: 'page',method: 'index'}],
['contact','pages/contact',{object: 'page', method: 'index'}],
['contact','pages/contact',{object: 'page', method: 'index'}]
],test_scope);

assert(routes_without_params.match('pages').name == 'index','index match() pages');
Expand All @@ -1456,7 +1460,6 @@ ActiveTest.Tests.Routes.matching = function(proceed)
var routes = new ActiveRoutes(test_valid_route_set,test_scope);

var match;

match = routes.match('/blog/post/5');
assert(match.name == 'post' && match.params.id == 5 && match.params.method == 'post','complex match() /blog/post/5');

Expand Down Expand Up @@ -1656,8 +1659,8 @@ ActiveTest.Tests.View.builder = function(proceed)
tr(
td(
ul(
li(),
li(span(b('test')))
li(span(b('test'))),
li()
)
),
td(
Expand All @@ -1679,8 +1682,8 @@ ActiveTest.Tests.View.builder = function(proceed)
});
var deep_instance = new DeepView();
var arguments_instance = new ArgumentsTestView();

assert(arguments_instance.container.firstChild.firstChild.nodeValue == 'one' && arguments_instance.container.firstChild.childNodes[2].tagName == 'B','mix and match of text and elements');
assert(deep_instance.container.firstChild.firstChild.firstChild.firstChild.firstChild.firstChild.firstChild.firstChild.firstChild.nodeValue == 'test','deep builder node test');

if(proceed)
proceed()
Expand Down

0 comments on commit 497b164

Please sign in to comment.