Add sync versions of discovery

This commit is contained in:
Raymond Feng 2013-06-01 23:03:25 -07:00
parent 56af9673c1
commit a2da90867f
2 changed files with 217 additions and 10 deletions

View File

@ -327,6 +327,15 @@ DataSource.prototype.discoverModels = function (options, cb) {
}
};
DataSource.prototype.discoverModelsSync = function (options) {
this.freeze();
if (this.adapter.discoverModelsSync) {
return this.adapter.discoverModelsSync(options);
}
return null;
};
/**
* Discover properties for a given model.
* @param owner The owner
@ -343,6 +352,14 @@ DataSource.prototype.discoverModelProperties = function (owner, table, cb) {
}
};
DataSource.prototype.discoverModelPropertiesSync = function (owner, table) {
this.freeze();
if (this.adapter.discoverModelPropertiesSync) {
return this.adapter.discoverModelPropertiesSync(owner, table);
}
return null;
};
/**
* Discover primary keys for a given owner/table
*
@ -366,6 +383,14 @@ DataSource.prototype.discoverPrimaryKeys= function(owner, table, cb) {
}
}
DataSource.prototype.discoverPrimaryKeysSync= function(owner, table) {
this.freeze();
if (this.adapter.discoverPrimaryKeysSync) {
return this.adapter.discoverPrimaryKeysSync(owner, table);
}
return null;
}
/**
* Discover foreign keys for a given owner/table
*
@ -393,6 +418,14 @@ DataSource.prototype.discoverForeignKeys= function(owner, table, cb) {
}
}
DataSource.prototype.discoverForeignKeysSync= function(owner, table) {
this.freeze();
if (this.adapter.discoverForeignKeysSync) {
return this.adapter.discoverForeignKeysSync(owner, table);
}
return null;
}
function capitalize(str) {
if (!str) {
return str;
@ -413,8 +446,8 @@ function fromDBName(dbName, camelCase) {
return parts.join('');
}
DataSource.prototype.discoverSchema = function (owner, table, cb) {
this.discoverSchemas(owner, table, {visited: {}, associations: false}, function(err, schemas) {
DataSource.prototype.discoverSchema = function (owner, tableOrView, cb) {
this.discoverSchemas(owner, tableOrView, {visited: {}, associations: false}, function(err, schemas) {
if(err) {
cb && cb(err, schemas);
return;
@ -425,22 +458,23 @@ DataSource.prototype.discoverSchema = function (owner, table, cb) {
}
});
}
/**
* Discover schema from a given table/view
* @param owner
* @param table
* @param cb
*/
DataSource.prototype.discoverSchemas = function (owner, table, options, cb) {
DataSource.prototype.discoverSchemas = function (owner, tableOrView, options, cb) {
var self = this;
var dataSourceName = this.name || this.adapter.name;
var tasks = [
this.discoverModelProperties.bind(this, owner, table),
this.discoverPrimaryKeys.bind(this, owner, table) ];
this.discoverModelProperties.bind(this, owner, tableOrView),
this.discoverPrimaryKeys.bind(this, owner, tableOrView) ];
if (options.associations) {
tasks.push(this.discoverForeignKeys.bind(this, owner, table));
tasks.push(this.discoverForeignKeys.bind(this, owner, tableOrView));
}
async.parallel(tasks, function (err, results) {
@ -468,7 +502,7 @@ DataSource.prototype.discoverSchemas = function (owner, table, options, cb) {
}
var schema = {
name: fromDBName(table, false),
name: fromDBName(tableOrView, false),
options: {
idInjection: false // DO NOT add id property
},
@ -478,7 +512,7 @@ DataSource.prototype.discoverSchemas = function (owner, table, options, cb) {
schema.options[dataSourceName] = {
schema: columns[0].owner,
table: table
table: tableOrView
};
columns.forEach(function (item) {
@ -502,9 +536,9 @@ DataSource.prototype.discoverSchemas = function (owner, table, options, cb) {
};
});
// Add current table to the visited tables
// Add current tableOrView to the visited tables
options.visited = options.visited || {};
var schemaKey = columns[0].owner + '.' + table;
var schemaKey = columns[0].owner + '.' + tableOrView;
if (!options.visited.hasOwnProperty(schemaKey)) {
if(self.settings.debug) {
console.log('Adding schema for ' + schemaKey);
@ -570,6 +604,178 @@ DataSource.prototype.discoverSchemas = function (owner, table, options, cb) {
});
}
/**
* Discover schema from a given table/view
* @param owner
* @param table
* @param cb
*/
DataSource.prototype.discoverSchemasSync = function (owner, tableOrView, options) {
var self = this;
var dataSourceName = this.name || this.adapter.name;
var columns = this.discoverModelPropertiesSync(owner, tableOrView);
if (!columns) {
return [];
}
// Handle primary keys
var primaryKeys = this.discoverPrimaryKeysSync(owner, tableOrView);
var pks = {};
primaryKeys.forEach(function (pk) {
pks[pk.columnName] = pk.keySeq;
});
if (self.settings.debug) {
console.log('Primary keys: ', pks);
}
var schema = {
name: fromDBName(tableOrView, false),
options: {
idInjection: false // DO NOT add id property
},
properties: {
}
};
schema.options[dataSourceName] = {
schema: columns[0].owner,
table: tableOrView
};
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,
dataLength: i.dataLength,
nullable: i.nullable
};
});
// Add current tableOrView to the visited tables
options.visited = options.visited || {};
var schemaKey = columns[0].owner + '.' + tableOrView;
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 = this.discoverForeignKeysSync(owner, tableOrView);
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 propName = fromDBName(fk.pkTableName, true);
schema.properties[propName] = {
type: fromDBName(fk.pkTableName, false),
association: {
type: 'belongsTo',
foreignKey: fromDBName(fk.pkColumnName, true)
}
};
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) {
return options.visited;
} else {
var moreTasks = [];
for (var t in otherTables) {
if (self.settings.debug) {
console.log('Discovering related schema for ' + schemaKey);
}
self.discoverSchemasSync(otherTables[t].owner, otherTables[t].tableName, options);
}
return options.visited;
}
}
/**
* Discover and build models from the given owner/tableOrView
* @param owner
* @param tableOrView
* @param options
* @param cb
*/
DataSource.prototype.discoverAndBuildModels = function (owner, tableOrView, options, cb) {
this.discoverSchemas(owner, tableOrView, options, function (err, schemas) {
if (err) {
cb && cb(err, schemas);
return;
}
var schemaList = [];
for (var s in schemas) {
var schema = schemas[s];
schemaList.push(schema);
}
;
var models = this.buildModels(schemaList);
cb && cb(err, models);
});
}
/**
* Discover and build models from the given owner/tableOrView synchronously
* @param owner
* @param tableOrView
* @param options
*/
DataSource.prototype.discoverAndBuildModelsSync = function (owner, tableOrView, options) {
var schemas = this.discoverSchemasSync(owner, tableOrView, options);
var schemaList = [];
for (var s in schemas) {
var schema = schemas[s];
schemaList.push(schema);
}
var models = this.buildModels(schemaList);
return models;
}
/**
* Check whether migrations needed
* This method make sense only for sql adapters.

View File

@ -391,6 +391,7 @@ function getSchemaType(type) {
if (type.type) {
return getSchemaType(type.type);
} else {
console.error(type);
throw new Error('Missing type property');
}
}