diff --git a/lib/adl.js b/lib/adl.js index 88a68168..eeb41c47 100644 --- a/lib/adl.js +++ b/lib/adl.js @@ -131,11 +131,28 @@ Schema.prototype.define = function defineClass(className, properties, settings) settings: settings }; - ModelClass.prototype.__defineGetter__('id', function () { - return this.__data.id; - }); + var idInjection = settings.idInjection; + for(var p in properties) { + if(properties[p].id) { + idInjection = false; + ModelClass.prototype.__defineGetter__('id', function () { + return this.__data[p]; + }); + break; + } + } + // Add the id property + if (idInjection !== false) { + ModelClass.prototype.__defineGetter__('id', function () { + return this.__data.id; + }); - properties.id = properties.id || { type: Number }; + // Set up the id property + properties.id = properties.id || { type: Number, id: true }; + if (!properties.id.id) { + properties.id.id = true; + } + } ModelClass.forEachProperty = function (cb) { Object.keys(properties).forEach(cb); diff --git a/lib/datasource.js b/lib/datasource.js index af9a17ac..9eed0d47 100644 --- a/lib/datasource.js +++ b/lib/datasource.js @@ -9,6 +9,7 @@ var EventEmitter = require('events').EventEmitter; var util = require('util'); var path = require('path'); var fs = require('fs'); +var async = require('async'); var existsSync = fs.existsSync || path.existsSync; @@ -372,47 +373,76 @@ function fromDBName(dbName, camelCase) { * @param table * @param cb */ -DataSource.prototype.discoverSchema = function(owner, table, cb) { - var dataSourceName = this.name; - this.discoverModelProperties(owner, table, function (err, columns) { - if (err) { - cb && cb(err); - return; - } - if(!columns) { - cb && cb(); - return; - } - var schema = { - name: fromDBName(table, false), - options: { - }, - properties: { +DataSource.prototype.discoverSchema = function (owner, table, cb) { + var dataSourceName = this.name || this.adapter.name; + + async.parallel( + [ + this.discoverModelProperties.bind(this, owner, table), + this.discoverPrimaryKeys.bind(this, owner, table), + this.discoverForeignKeys.bind(this, owner, table) + ], function (err, results) { + + if (err) { + cb && cb(err); + return; } - }; - schema.options[dataSourceName] = { - schema: owner, - table: table - }; - columns.forEach(function (item) { - var i = item; - var propName = fromDBName(item.columnName, true); - schema.properties[propName] = - { - type: item.type, - required: (item.nullable === 'N'), - length: item.dataLength + var columns = results[0]; + var primaryKeys = results[1]; + var pks = {}, fks = {}; + primaryKeys.forEach(function(pk) { + pks[pk.columnName] = pk.keySeq; + }); + + console.log(pks); + + var foreignKeys = results[2]; + foreignKeys.forEach(function(fk) { + fks[fk.fkColumnName] = fk.keySeq; + }); + + if (!columns) { + cb && cb(); + return; + } + var schema = { + name: fromDBName(table, false), + options: { + idInjection: false // DO NOT add id property + }, + properties: { + } }; - schema.properties[propName][dataSourceName] = { - columnName: i.columnName, - dataType: i.dataType, - nullable: i.nullable + + schema.options[dataSourceName] = { + schema: owner, + table: table }; + columns.forEach(function (item) { + var i = item; + + + var propName = fromDBName(item.columnName, true); + schema.properties[propName] = + { + type: item.type, + required: (item.nullable === 'N'), + length: item.dataLength + }; + + if(pks[item.columnName]) { + schema.properties[propName].id = pks[item.columnName]; + } + schema.properties[propName][dataSourceName] = { + columnName: i.columnName, + dataType: i.dataType, + nullable: i.nullable + }; + }); + + cb && cb(null, schema); }); - - cb && cb(null, schema); - }); } /** @@ -452,9 +482,72 @@ DataSource.prototype.freeze = function freeze() { * @param {String} modelName */ DataSource.prototype.tableName = function (modelName) { - return this.definitions[modelName].settings.table = this.definitions[modelName].settings.table || modelName + var settings = this.definitions[modelName].settings; + if(settings[this.adapter.name]) { + return settings[this.adapter.name].table || modelName; + } else { + return modelName; + } }; +/** + * Return column name for specified modelName and propertyName + * @param modelName + * @param propertyName + * @returns {String} columnName + */ +DataSource.prototype.columnName = function (modelName, propertyName) { + var property = this.definitions[modelName].properties[propertyName]; + if(property[this.adapter.name]) { + return property[this.adapter.name].columnName || propertyName; + } else { + return propertyName; + } +}; + +/** + * Return column names for specified modelName + * @param modelName + * @returns {[String]} column names + */ +DataSource.prototype.columnNames = function (modelName) { + var props = this.definitions[modelName].properties; + var cols = []; + for(var p in props) { + if(props[p][this.adapter.name]) { + cols.push(props[p][this.adapter.name].columnName || p); + } else { + cols.push(p); + } + } + return cols; +}; + +/** + * Find the ID column name + * @param modelName + * @returns {String} columnName for ID + */ +DataSource.prototype.getIDColumnName = function(modelName) { + var props = this.definitions[modelName].properties; + var self = this; + Object.keys(props).forEach(function(key) { + var columnInfo = props[key][self.adapter.name]; + if(columnInfo && columnInfo.id) { + if(columnInfo.columnName) { + return columnInfo.columnName; + } else { + return key; + } + } + }); + if(props.id) { + return 'id'; + } + return null; +} + + /** * Define foreign key * @param {String} className diff --git a/lib/sql.js b/lib/sql.js index a68f9d75..aa9b7b98 100644 --- a/lib/sql.js +++ b/lib/sql.js @@ -25,6 +25,10 @@ BaseSQL.prototype.table = function (model) { return this._models[model].model.schema.tableName(model); }; +BaseSQL.prototype.column = function (model, property) { + return this._models[model].model.schema.columnName(model, property); +}; + BaseSQL.prototype.escapeName = function (name) { throw new Error('escapeName method should be declared in adapter'); }; @@ -33,6 +37,10 @@ BaseSQL.prototype.tableEscaped = function (model) { return this.escapeName(this.table(model)); }; +BaseSQL.prototype.columnEscaped = function (model, property) { + return this.escapeName(this.column(model, property)); +}; + BaseSQL.prototype.define = function (descr) { if (!descr.settings) descr.settings = {}; this._models[descr.model.modelName] = descr; diff --git a/package.json b/package.json index e32e701d..9eeb5c4d 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "mocha": "~1.8.2" }, "dependencies": { + "async": "latest", "inflection": "~1.2.5" } }