Skip to content

Commit

Permalink
add Date values support, #22
Browse files Browse the repository at this point in the history
  • Loading branch information
artzhookov committed Jan 25, 2017
1 parent 32aa01b commit 1b5b89e
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 53 deletions.
6 changes: 5 additions & 1 deletion lib/builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,20 @@ Builder.prototype._pushValue = function(value) {
return 'null';
} else if (_.isNumber(value) || _.isBoolean(value)) {
return String(value);
} else if (_.isString(value)) {
} else if (_.isString(value) || _.isDate(value)) {
if (this.options.separatedValues) {
var placeholder = this._getPlaceholder();

if (this.options.namedValues) {
this._values[placeholder] = value;
} else {
this._values.push(value);
}

return this._wrapPlaceholder(placeholder);
} else {
if (_.isDate(value)) value = value.toISOString();

return '\'' + value + '\'';
}
} else {
Expand Down
34 changes: 8 additions & 26 deletions lib/dialects/base/blocks.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

var _ = require('underscore');
var objectUtils = require('../../utils/object');

var removeTopBrackets = function(condition) {
if (condition.length && condition[0] === '(' &&
Expand All @@ -11,29 +12,9 @@ var removeTopBrackets = function(condition) {
return condition;
};

// check if object contains any of expected keys
var hasSome = function(obj, keys) {
var objKeys = _(obj).keys();
return _(keys).some(function(key) {
return _(objKeys).contains(key);
});
};

var termKeys = ['select', 'query', 'field', 'value', 'func', 'expression'];
var isTerm = function(obj) {
return _.isObject(obj) && !_.isArray(obj) && hasSome(obj, termKeys);
};

var isSimpleValue = function(value) {
return (
_.isString(value) ||
_.isNumber(value) ||
_.isBoolean(value) ||
_.isNull(value) ||
_.isUndefined(value) ||
_.isRegExp(value) ||
_.isDate(value)
);
return objectUtils.isObjectObject(obj) && objectUtils.hasSome(obj, termKeys);
};

module.exports = function(dialect) {
Expand All @@ -53,7 +34,7 @@ module.exports = function(dialect) {
// If fields is array: ['a', {b: 'c'}, {name: '', table: 't', alias: 'r'}]
if (_.isArray(fields)) {
fields = _(fields).map(function(field) {
if (isSimpleValue(field) || isTerm(field) || _.has(field, 'name')) {
if (objectUtils.isSimpleValue(field) || isTerm(field) || _.has(field, 'name')) {
// if field has simple type or is field object: {name: '', table: 't', alias: 'r'}
return dialect.buildBlock('term', {term: field, type: 'field'});
} else {
Expand Down Expand Up @@ -83,11 +64,12 @@ module.exports = function(dialect) {
var term = params.term;
var type = params.type || 'field';

var notObject = isSimpleValue(term) || _.isArray(term);
var isSimpleValue = objectUtils.isSimpleValue(term);
var isArray = _.isArray(term);

if (notObject && !_.isString(term)) type = 'value';
if (isSimpleValue && !_.isString(term) || isArray) type = 'value';

if (notObject || !isTerm(term)) {
if (isSimpleValue || !isTerm(term) || isArray) {
term = _(term).chain().pick('cast', 'alias').extend(_.object([type], [term])).value();
}

Expand Down Expand Up @@ -253,7 +235,7 @@ module.exports = function(dialect) {
// if join is object -> set table name from key and make each joinItem
} else if (_.isObject(join)) {
result = _(join).map(function(joinItem, table) {
if (!hasSome(joinItem, ['table', 'query', 'select', 'expression'])) {
if (!objectUtils.hasSome(joinItem, ['table', 'query', 'select', 'expression'])) {
joinItem = _.defaults({table: table}, joinItem);
}

Expand Down
15 changes: 10 additions & 5 deletions lib/dialects/base/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

var _ = require('underscore');
var ValuesStore = require('../../utils/valuesStore');
var objectUtils = require('../../utils/object');

var templatesInit = require('./templates');
var blocksInit = require('./blocks');
Expand Down Expand Up @@ -72,7 +73,9 @@ Dialect.prototype.buildLogicalOperator = function(params) {
var operator = params.operator;
var value = params.value;

if (!_.isObject(value)) value = _.object([params.defaultFetchingOperator], [value]);
if (objectUtils.isSimpleValue(value)) {
value = _.object([params.defaultFetchingOperator], [value]);
}

if (_.isEmpty(value)) return '';

Expand All @@ -94,7 +97,9 @@ Dialect.prototype.buildLogicalOperator = function(params) {
result = _(value).map(function(item, field) {
// if field name is not a operator convert it to {$field: {name: 'a', $eq: 'b'}}
if (field[0] !== '$') {
if (!_.isObject(item) || _.isArray(item)) item = {$eq: item};
if (objectUtils.isSimpleValue(item) || _.isArray(item)) {
item = {$eq: item};
}
item = _.defaults({name: field}, item);
field = '$field';
}
Expand Down Expand Up @@ -143,7 +148,7 @@ Dialect.prototype.buildFetchingOperator = function(params) {
var field = this.operators.fetching.get(operator).fn(value, params.end);

var result;
if (params.end || !_.isObject(value)) {
if (params.end || objectUtils.isSimpleValue(value)) {
result = field;
} else {
result = this.buildOperatorsGroup({
Expand All @@ -166,7 +171,7 @@ Dialect.prototype.buildEndFetchingOperator = function(params) {
var value = params.value;
var operator;

if (_.isObject(value) && !_.isArray(value)) {
if (objectUtils.isObjectObject(value)) {
// get first query operator
operator = _(value).findKey(function(item, operator) {
return operator[0] === '$' && self.operators.fetching.has(operator);
Expand Down Expand Up @@ -199,7 +204,7 @@ Dialect.prototype.buildOperatorsGroup = function(params) {
var value = params.value;

var result;
if (_.isObject(value) && !_.isArray(value)) {
if (objectUtils.isObjectObject(value)) {
result = this.operators.logical.get(params.operator).fn(
_(value)
.chain()
Expand Down
27 changes: 27 additions & 0 deletions lib/utils/object.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use strict';

var _ = require('underscore');

// check if object contains any of expected keys
exports.hasSome = function(obj, keys) {
var objKeys = _(obj).keys();
return _(keys).some(function(key) {
return _(objKeys).contains(key);
});
};

exports.isSimpleValue = function(value) {
return (
_.isString(value) ||
_.isNumber(value) ||
_.isBoolean(value) ||
_.isNull(value) ||
_.isUndefined(value) ||
_.isRegExp(value) ||
_.isDate(value)
);
};

exports.isObjectObject = function(obj) {
return _.isObject(obj) && Object.prototype.toString.call(obj) === '[object Object]';
}
11 changes: 8 additions & 3 deletions tests/0_base.js
Original file line number Diff line number Diff line change
Expand Up @@ -297,14 +297,19 @@ describe('Builder', function() {
expect(jsonSql._values).to.not.be.ok;
expect(jsonSql._placeholderId).to.not.be.ok;

var date = new Date();
var result = jsonSql.build({
type: 'insert',
table: 'users',
values: {name: 'John', surname: 'Doe'}
values: {
name: 'John',
surname: 'Doe',
date: date
}
});

expect(result.query).to.be.equal('insert into "users" ("name", "surname") values ' +
'(\'John\', \'Doe\');');
expect(result.query).to.be.equal('insert into "users" ("name", "surname", "date") values ' +
'(\'John\', \'Doe\', \'' + date.toISOString() + '\');');
expect(result.values).to.not.be.ok;
});

Expand Down
16 changes: 11 additions & 5 deletions tests/1_select.js
Original file line number Diff line number Diff line change
Expand Up @@ -1221,31 +1221,37 @@ describe('Select', function() {
});

it('should be ok with `$or`:[`$or`, `$or`]', function() {
var date1 = new Date();
var date2 = new Date();
var result = jsonSql.build({
table: 'users',
condition: {
$or: [{
$or: {
name: 'John',
age: 12
age: 12,
date: date1
}
}, {
$or: {
name: 'Mark',
age: 14
age: 14,
date: date2
}
}]
}
});

expect(result.query).to.be.equal(
'select * from "users" ' +
'where ("name" = $p1 or "age" = 12) or ' +
'("name" = $p2 or "age" = 14);'
'where ("name" = $p1 or "age" = 12 or "date" = $p2) or ' +
'("name" = $p3 or "age" = 14 or "date" = $p4);'
);
expect(result.values).to.be.eql({
p1: 'John',
p2: 'Mark'
p2: date1,
p3: 'Mark',
p4: date2
});
});
});
Expand Down
29 changes: 19 additions & 10 deletions tests/2_insert.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,25 @@ describe('Insert', function() {
});

it('should be ok with `values` property', function() {
var date = new Date();
var result = jsonSql.build({
type: 'insert',
table: 'users',
values: {
name: 'Max'
id: 1,
name: 'Max',
date: date
}
});

expect(result.query).to.be.equal('insert into "users" ("name") values ($p1);');
expect(result.values).to.be.eql({p1: 'Max'});
expect(result.query).to.be.equal(
'insert into "users" ("id", "name", "date") values (1, $p1, $p2);'
);
expect(result.values).to.be.eql({p1: 'Max', p2: date});
});

it('should be ok with `with` property', function() {
var date = new Date();
var result = jsonSql.build({
'with': [{
name: 't_1',
Expand All @@ -40,34 +46,37 @@ describe('Insert', function() {
name: 'Max',
age: 17,
lastVisit: null,
active: true
active: true,
date: date
}
});

expect(result.query).to.be.equal(
'with "t_1" as (select * from "t_1") insert into "users" ' +
'("name", "age", "lastVisit", "active") values ($p1, 17, null, true);'
'("name", "age", "lastVisit", "active", "date") values ($p1, 17, null, true, $p2);'
);
expect(result.values).to.be.eql({p1: 'Max'});
expect(result.values).to.be.eql({p1: 'Max', p2: date});
});

it('should be ok with `returning` property', function() {
var date = new Date();
var result = jsonSql.build({
type: 'insert',
table: 'users',
values: {
name: 'Max',
age: 17,
lastVisit: null,
active: true
active: true,
date: date
},
returning: ['users.*']
});

expect(result.query).to.be.equal(
'insert into "users" ("name", "age", "lastVisit", "active") ' +
'values ($p1, 17, null, true) returning "users".*;'
'insert into "users" ("name", "age", "lastVisit", "active", "date") ' +
'values ($p1, 17, null, true, $p2) returning "users".*;'
);
expect(result.values).to.be.eql({p1: 'Max'});
expect(result.values).to.be.eql({p1: 'Max', p2: date});
});
});
8 changes: 5 additions & 3 deletions tests/3_update.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,22 @@ describe('Update', function() {
});

it('should be ok with default(`$set`)', function() {
var date = new Date();
var result = jsonSql.build({
type: 'update',
table: 'users',
modifier: {
name: 'Max',
age: 16,
lastVisit: null,
active: false
active: false,
date: date
}
});

expect(result.query).to.be.equal('update "users" set "name" = $p1, "age" = 16, ' +
'"lastVisit" = null, "active" = false;');
expect(result.values).to.be.eql({p1: 'Max'});
'"lastVisit" = null, "active" = false, "date" = $p2;');
expect(result.values).to.be.eql({p1: 'Max', p2: date});
});

it('should be ok with `$set`', function() {
Expand Down

0 comments on commit 1b5b89e

Please sign in to comment.