Add support to discover related schemas by foreign keys
This commit is contained in:
parent
ad14bd9dbc
commit
2d62b5ba6a
|
@ -415,22 +415,37 @@ function fromDBName(dbName, camelCase) {
|
||||||
return parts.join('');
|
return parts.join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DataSource.prototype.discoverSchema = function (owner, table, cb) {
|
||||||
|
this.discoverSchemas(owner, table, {visited: {}, associations: false}, function(err, schemas) {
|
||||||
|
if(err) {
|
||||||
|
cb && cb(err, schemas);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(var s in schemas) {
|
||||||
|
cb && cb(null, schemas[s]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Discover schema from a given table/view
|
* Discover schema from a given table/view
|
||||||
* @param owner
|
* @param owner
|
||||||
* @param table
|
* @param table
|
||||||
* @param cb
|
* @param cb
|
||||||
*/
|
*/
|
||||||
DataSource.prototype.discoverSchema = function (owner, table, cb) {
|
DataSource.prototype.discoverSchemas = function (owner, table, options, cb) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var dataSourceName = this.name || this.adapter.name;
|
var dataSourceName = this.name || this.adapter.name;
|
||||||
|
|
||||||
async.parallel(
|
var tasks = [
|
||||||
[
|
|
||||||
this.discoverModelProperties.bind(this, owner, table),
|
this.discoverModelProperties.bind(this, owner, table),
|
||||||
this.discoverPrimaryKeys.bind(this, owner, table),
|
this.discoverPrimaryKeys.bind(this, owner, table) ];
|
||||||
this.discoverForeignKeys.bind(this, owner, table)
|
|
||||||
], function (err, results) {
|
if (options.associations) {
|
||||||
|
tasks.push(this.discoverForeignKeys.bind(this, owner, table));
|
||||||
|
}
|
||||||
|
|
||||||
|
async.parallel(tasks, function (err, results) {
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
cb && cb(err);
|
cb && cb(err);
|
||||||
|
@ -438,39 +453,22 @@ DataSource.prototype.discoverSchema = function (owner, table, cb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var columns = results[0];
|
var columns = results[0];
|
||||||
var primaryKeys = results[1];
|
|
||||||
var pks = {}, fks = {};
|
|
||||||
primaryKeys.forEach(function(pk) {
|
|
||||||
pks[pk.columnName] = pk.keySeq;
|
|
||||||
});
|
|
||||||
|
|
||||||
if(self.settings.debug) {
|
|
||||||
console.log('Primary keys: ', pks);
|
|
||||||
}
|
|
||||||
|
|
||||||
var foreignKeys = results[2];
|
|
||||||
foreignKeys.forEach(function(fk) {
|
|
||||||
var fkInfo = {
|
|
||||||
keySeq: fk.keySeq,
|
|
||||||
owner: fk.pkOwner,
|
|
||||||
tableName: fk.pkTableName,
|
|
||||||
columnName: fk.pkColumnName
|
|
||||||
};
|
|
||||||
if(fks[fk.fkName]) {
|
|
||||||
fks[fk.fkName].push(fkInfo);
|
|
||||||
} else {
|
|
||||||
fks[fk.fkName] = [fkInfo];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if(self.settings.debug) {
|
|
||||||
console.log('Foreign keys: ', fks);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!columns) {
|
if (!columns) {
|
||||||
cb && cb();
|
cb && cb();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle primary keys
|
||||||
|
var primaryKeys = results[1];
|
||||||
|
var pks = {};
|
||||||
|
primaryKeys.forEach(function (pk) {
|
||||||
|
pks[pk.columnName] = pk.keySeq;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (self.settings.debug) {
|
||||||
|
console.log('Primary keys: ', pks);
|
||||||
|
}
|
||||||
|
|
||||||
var schema = {
|
var schema = {
|
||||||
name: fromDBName(table, false),
|
name: fromDBName(table, false),
|
||||||
options: {
|
options: {
|
||||||
|
@ -481,22 +479,21 @@ DataSource.prototype.discoverSchema = function (owner, table, cb) {
|
||||||
};
|
};
|
||||||
|
|
||||||
schema.options[dataSourceName] = {
|
schema.options[dataSourceName] = {
|
||||||
schema: owner,
|
schema: columns[0].owner,
|
||||||
table: table
|
table: table
|
||||||
};
|
};
|
||||||
|
|
||||||
columns.forEach(function (item) {
|
columns.forEach(function (item) {
|
||||||
var i = item;
|
var i = item;
|
||||||
|
|
||||||
|
|
||||||
var propName = fromDBName(item.columnName, true);
|
var propName = fromDBName(item.columnName, true);
|
||||||
schema.properties[propName] =
|
schema.properties[propName] = {
|
||||||
{
|
|
||||||
type: item.type,
|
type: item.type,
|
||||||
required: (item.nullable === 'N'),
|
required: (item.nullable === 'N'),
|
||||||
length: item.dataLength
|
length: item.dataLength
|
||||||
};
|
};
|
||||||
|
|
||||||
if(pks[item.columnName]) {
|
if (pks[item.columnName]) {
|
||||||
schema.properties[propName].id = pks[item.columnName];
|
schema.properties[propName].id = pks[item.columnName];
|
||||||
}
|
}
|
||||||
schema.properties[propName][dataSourceName] = {
|
schema.properties[propName][dataSourceName] = {
|
||||||
|
@ -507,7 +504,62 @@ DataSource.prototype.discoverSchema = function (owner, table, cb) {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
cb && cb(null, schema);
|
// Add current table to the visited tables
|
||||||
|
options.visited = options.visited || {};
|
||||||
|
var schemaKey = columns[0].owner + '.' + table;
|
||||||
|
if (!options.visited.hasOwnProperty(schemaKey)) {
|
||||||
|
if(self.settings.debug) {
|
||||||
|
console.log('Adding schema for ' + schemaKey);
|
||||||
|
}
|
||||||
|
options.visited[schemaKey] = schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
var otherTables = {};
|
||||||
|
if (options.associations) {
|
||||||
|
// Handle foreign keys
|
||||||
|
var fks = {};
|
||||||
|
var foreignKeys = results[2];
|
||||||
|
foreignKeys.forEach(function (fk) {
|
||||||
|
var fkInfo = {
|
||||||
|
keySeq: fk.keySeq,
|
||||||
|
owner: fk.pkOwner,
|
||||||
|
tableName: fk.pkTableName,
|
||||||
|
columnName: fk.pkColumnName
|
||||||
|
};
|
||||||
|
if (fks[fk.fkName]) {
|
||||||
|
fks[fk.fkName].push(fkInfo);
|
||||||
|
} else {
|
||||||
|
fks[fk.fkName] = [fkInfo];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (self.settings.debug) {
|
||||||
|
console.log('Foreign keys: ', fks);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreignKeys.forEach(function (fk) {
|
||||||
|
var key = fk.pkOwner + '.' + fk.pkTableName;
|
||||||
|
if (!options.visited.hasOwnProperty(key) && !otherTables.hasOwnProperty(key)) {
|
||||||
|
otherTables[key] = {owner: fk.pkOwner, tableName: fk.pkTableName};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.keys(otherTables).length === 0) {
|
||||||
|
cb && cb(null, options.visited);
|
||||||
|
} else {
|
||||||
|
var moreTasks = [];
|
||||||
|
for (var t in otherTables) {
|
||||||
|
if(self.settings.debug) {
|
||||||
|
console.log('Discovering related schema for ' + schemaKey);
|
||||||
|
}
|
||||||
|
moreTasks.push(DataSource.prototype.discoverSchemas.bind(self, otherTables[t].owner, otherTables[t].tableName, options));
|
||||||
|
}
|
||||||
|
async.parallel(moreTasks, function (err, results) {
|
||||||
|
var result = results && results[0];
|
||||||
|
cb && cb(err, result);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue