diff --git a/lib/datasource.js b/lib/datasource.js index 0ca42831..dd91a4f8 100644 --- a/lib/datasource.js +++ b/lib/datasource.js @@ -1308,6 +1308,40 @@ DataSource.prototype.discoverPrimaryKeys = function(modelName, options, cb) { return cb.promise; }; +/** + * Discover unique keys for a given modelName. + * Callback function return value is an object that can have the following properties: + * + *| Key | Type | Description | + *|-----|------|-------------| + *| owner |String | Table schema or owner (may be null). Owner defaults to current user. + *| tableName |String| Table name + *| columnName |String| Column name + * See [ID Properties](./Model-definition-JSON-file.html#id-properties) for more + * information. + * @param {String} modelName The model name + * @options {Object} options The options + * @param {Function} [cb] The callback function + * @returns {Promise} A promise with an array of Primary Keys (Property[]) + */ +DataSource.prototype.discoverUniqueKeys = function(modelName, options, cb) { + this.freeze(); + + if (cb === undefined && typeof options === 'function') { + cb = options; + options = {}; + } + options = options || {}; + cb = cb || utils.createPromiseCallback(); + + if (this.connector.discoverUniqueKeys) { + this.connector.discoverUniqueKeys(modelName, options, cb); + } else if (cb) { + process.nextTick(cb); + } + return cb.promise; +}; + /*! Method will be completely removed in LoopBack.next */ /** @@ -1619,7 +1653,8 @@ DataSource.prototype.discoverSchemas = function(tableName, options, cb) { const tasks = [ this.discoverModelProperties.bind(this, tableName, options), - this.discoverPrimaryKeys.bind(this, tableName, options)]; + this.discoverPrimaryKeys.bind(this, tableName, options), + this.discoverUniqueKeys.bind(this, tableName, options)]; const followingRelations = options.associations || options.relations; if (followingRelations) { @@ -1633,6 +1668,14 @@ DataSource.prototype.discoverSchemas = function(tableName, options, cb) { } const columns = results[0]; + const uniqueKeyArray = results[2] || []; + + let uniqueKeys = []; + + uniqueKeyArray.forEach(key => { + uniqueKeys.push(key['columnName']); + }); + if (!columns || columns.length === 0) { cb(new Error(g.f('Table \'%s\' does not exist.', tableName))); return cb.promise; @@ -1649,6 +1692,7 @@ DataSource.prototype.discoverSchemas = function(tableName, options, cb) { debug('Primary keys: ', pks); } + uniqueKeys = uniqueKeys.filter(item => !pks.hasOwnProperty(item)); const schema = { name: nameMapper('table', tableName), options: { @@ -1677,6 +1721,9 @@ DataSource.prototype.discoverSchemas = function(tableName, options, cb) { if (pks[item.columnName]) { schema.properties[propName].id = pks[item.columnName]; } + if (uniqueKeys.includes(propName)) { + schema.properties[propName]['index'] = {unique: true}; + } const dbSpecific = schema.properties[propName][dbType] = { columnName: item.columnName, dataType: item.dataType,