Fix postgres adapter

This commit is contained in:
Anatoliy Chakkaev 2012-01-10 19:43:32 +04:00
parent 029b020946
commit c3835d089b
3 changed files with 45 additions and 24 deletions

View File

@ -155,7 +155,11 @@ AbstractClass.create = function (data) {
}; };
AbstractClass.exists = function exists(id, cb) { AbstractClass.exists = function exists(id, cb) {
this.schema.adapter.exists(this.modelName, id, cb); if (id) {
this.schema.adapter.exists(this.modelName, id, cb);
} else {
cb(new Error('Model::exists requires positive id argument'));
}
}; };
AbstractClass.find = function find(id, cb) { AbstractClass.find = function find(id, cb) {

View File

@ -3,6 +3,7 @@
*/ */
var Client = require('pg').Client; var Client = require('pg').Client;
var Hash = require('hashish'); var Hash = require('hashish');
exports.initialize = function initializeSchema(schema, callback) { exports.initialize = function initializeSchema(schema, callback) {
var s = schema.settings; var s = schema.settings;
schema.client = new Client(s.url ? s.url : { schema.client = new Client(s.url ? s.url : {
@ -38,7 +39,7 @@ PG.prototype.query = function (sql, callback) {
var log = this.log; var log = this.log;
this.client.query(sql, function (err, data) { this.client.query(sql, function (err, data) {
log(sql, time); log(sql, time);
callback(err, Hash(data.rows)); callback(err, data ? Hash(data.rows) : null);
}); });
}; };
@ -62,8 +63,10 @@ PG.prototype.create = function (model, data, callback) {
} else { } else {
sql += ' VALUES ()'; sql += ' VALUES ()';
} }
sql += ' RETURNING id';
this.query(sql, function (err, info) { this.query(sql, function (err, info) {
callback(err, info && info.insertId); if (err) return callback(err);
callback(err, info && info.items[0] && info.items[0].id);
}); });
}; };
@ -91,21 +94,21 @@ PG.prototype.toFields = function (model, data, forCreate) {
}; };
PG.prototype.toDatabase = function (prop, val) { PG.prototype.toDatabase = function (prop, val) {
if (prop.type.name === 'Number') return val;
if (val === null) return 'NULL'; if (val === null) return 'NULL';
if (prop.type.name === 'Number') return val;
if (prop.type.name === 'Date') { if (prop.type.name === 'Date') {
if (!val) return 'NULL'; if (!val) return 'NULL';
if (!val.toUTCString) { if (!val.toUTCString) {
val = new Date(val); val = new Date(val);
} }
val = [ val = [
val.getFullYear(), val.getUTCFullYear(),
val.getMonth() + 1, val.getUTCMonth() + 1,
val.getDate() val.getUTCDate()
].join('-') + ' ' + [ ].join('-') + ' ' + [
val.getHours(), val.getUTCHours(),
val.getMinutes(), val.getUTCMinutes(),
val.getSeconds() val.getUTCSeconds()
].join(':'); ].join(':');
return escape(val); return escape(val);
} }
@ -129,24 +132,24 @@ PG.prototype.exists = function (model, id, callback) {
var sql = 'SELECT 1 FROM "' + model + '" WHERE "id" = ' + id + ' LIMIT 1'; var sql = 'SELECT 1 FROM "' + model + '" WHERE "id" = ' + id + ' LIMIT 1';
this.query(sql, function (err, data) { this.query(sql, function (err, data) {
if (err) return callback(err); if (err) return callback(err);
callback(null, data.length === 1); callback(null, data.items.length === 1);
}); });
}; };
PG.prototype.find = function find(model, id, callback) { PG.prototype.find = function find(model, id, callback) {
var sql = 'SELECT * FROM "' + model + '" WHERE "id" = ' + id + ' LIMIT 1'; var sql = 'SELECT * FROM "' + model + '" WHERE "id" = ' + id + ' LIMIT 1';
this.query(sql, function (err, data) { this.query(sql, function (err, data) {
if (data && data.length === 1) { if (data && data.items && data.items.length === 1) {
data[0].id = id; data.items[0].id = id;
} else { } else {
data = [null]; data = { items: [null] };
} }
callback(err, this.fromDatabase(model, data[0])); callback(err, this.fromDatabase(model, data.items[0]));
}.bind(this)); }.bind(this));
}; };
PG.prototype.destroy = function destroy(model, id, callback) { PG.prototype.destroy = function destroy(model, id, callback) {
var sql = 'DELETE FROM "' + model + '" WHERE "id" = ' + id + ' LIMIT 1'; var sql = 'DELETE FROM "' + model + '" WHERE "id" = ' + id;
this.query(sql, function (err) { this.query(sql, function (err) {
callback(err); callback(err);
}); });
@ -154,28 +157,39 @@ PG.prototype.destroy = function destroy(model, id, callback) {
// TODO: hook up where, order, limit and offset conditions // TODO: hook up where, order, limit and offset conditions
PG.prototype.all = function all(model, filter, callback) { PG.prototype.all = function all(model, filter, callback) {
this.query('SELECT * FROM "' + model + '"' + this.toFilter(model,filter), function (err, data) { this.query('SELECT * FROM "' + model + '"' + this.toFilter(model, filter), function (err, data) {
if (err) { if (err) {
return callback(err, []); return callback(err, []);
} }
callback(err, filter ? data.filter(applyFilter(filter)) : data); callback(err, filter ? data.items.filter(applyFilter(filter)) : data.items);
}.bind(this)); }.bind(this));
}; };
PG.prototype.toFilter = function (model, filter) { PG.prototype.toFilter = function (model, filter) {
if (typeof filter.where === 'function') { if (filter && typeof filter.where === 'function') {
return filter(); return filter();
} }
if (!filter) return '';
var props = this._models[model].properties; var props = this._models[model].properties;
var out=''; var out='';
if(filter.where){ if (filter.where) {
var fields = []; var fields = [];
Object.keys(filter.where).forEach(function (key) { Object.keys(filter.where).forEach(function (key) {
if (filter.where[key] && filter.where[key].constructor.name === 'RegExp') {
return;
}
if (props[key]) { if (props[key]) {
fields.push('"' + key + '" = ' + this.toDatabase(props[key], filter.where[key])); var filterValue = this.toDatabase(props[key], filter.where[key]);
if (filterValue === 'NULL') {
fields.push('"' + key + '" IS ' + filterValue);
} else {
fields.push('"' + key + '" = ' + filterValue);
}
} }
}.bind(this)); }.bind(this));
out += ' where ' + fields.join(' AND '); if (fields.length) {
out += ' where ' + fields.join(' AND ');
}
} }
return out; return out;
}; };
@ -216,7 +230,8 @@ PG.prototype.destroyAll = function destroyAll(model, callback) {
PG.prototype.count = function count(model, callback) { PG.prototype.count = function count(model, callback) {
this.query('SELECT count(*) as cnt FROM "' + model + '"', function (err, res) { this.query('SELECT count(*) as cnt FROM "' + model + '"', function (err, res) {
callback(err, err ? null : res[0].cnt); if (err) return callback(err);
callback(err, res && res.items[0] && res.items[0].cnt);
}); });
}; };

View File

@ -34,6 +34,7 @@ Object.keys(schemas).forEach(function (schemaName) {
if (process.env.ONLY && process.env.ONLY !== schemaName) return; if (process.env.ONLY && process.env.ONLY !== schemaName) return;
context(schemaName, function () { context(schemaName, function () {
var schema = new Schema(schemaName, schemas[schemaName]); var schema = new Schema(schemaName, schemas[schemaName]);
// schema.log = console.log;
testOrm(schema); testOrm(schema);
if (specificTest[schemaName]) specificTest[schemaName](schema); if (specificTest[schemaName]) specificTest[schemaName](schema);
}); });
@ -137,7 +138,7 @@ function testOrm(schema) {
it('should create object', function (test) { it('should create object', function (test) {
Post.create(function (err, post) { Post.create(function (err, post) {
if (err) throw err; if (err) throw err;
test.ok(post.id); test.ok(post.id, 'Id present');
test.ok(!post.title, 'Title is blank'); test.ok(!post.title, 'Title is blank');
Post.exists(post.id, function (err, exists) { Post.exists(post.id, function (err, exists) {
if (err) throw err; if (err) throw err;
@ -315,6 +316,7 @@ function testOrm(schema) {
// matching null // matching null
Post.all({where: {title: null}}, function (err, res) { Post.all({where: {title: null}}, function (err, res) {
var pass = true; var pass = true;
res.forEach(function (r) { res.forEach(function (r) {
if (r.title != null) pass = false; if (r.title != null) pass = false;