Merge pull request #75 from strongloop/refactor-discovery
Refactor SQL discovery methods
This commit is contained in:
commit
22a39025a1
297
lib/sql.js
297
lib/sql.js
|
@ -1508,3 +1508,300 @@ SQLConnector.prototype.getInsertedId = function(model, info) {
|
|||
SQLConnector.prototype.executeSQL = function(sql, params, options, callback) {
|
||||
throw new Error(g.f('{{executeSQL()}} must be implemented by the connector'));
|
||||
};
|
||||
|
||||
// Refactored Discovery methods
|
||||
|
||||
/**
|
||||
* Build sql for listing schemas
|
||||
* @param {Object} options Options for discoverDatabaseSchemas
|
||||
*/
|
||||
SQLConnector.prototype.buildQuerySchemas = function(options) {
|
||||
var sql = 'SELECT catalog_name as "catalog",' +
|
||||
' schema_name as "schema"' +
|
||||
' FROM information_schema.schemata';
|
||||
return this.paginateSQL(sql, 'schema_name', options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Paginate the results returned from database
|
||||
* @param {String} sql The sql to execute
|
||||
* @param {Object} orderBy The property name by which results are ordered
|
||||
* @param {Object} options Options for discoverDatabaseSchemas
|
||||
*/
|
||||
SQLConnector.prototype.paginateSQL = function(sql, orderBy, options) {
|
||||
throw new Error(g.f('{{paginateSQL}} must be implemented by the connector'));
|
||||
};
|
||||
/**
|
||||
* Discover database schemas
|
||||
*
|
||||
// * @param {Object} options Options for discovery
|
||||
* @param {Function} [cb] The callback function
|
||||
*/
|
||||
SQLConnector.prototype.discoverDatabaseSchemas = function(options, cb) {
|
||||
if (!cb && typeof options === 'function') {
|
||||
cb = options;
|
||||
options = {};
|
||||
}
|
||||
options = options || {};
|
||||
var self = this;
|
||||
this.execute(self.buildQuerySchemas(options), cb);
|
||||
};
|
||||
|
||||
/*!
|
||||
* Build sql for listing tables
|
||||
* @param options {all: for all owners, owner: for a given owner}
|
||||
* @returns {string} The sql statement
|
||||
*/
|
||||
// Due to the different implementation structure of information_schema across
|
||||
// connectors, each connector will have to generate its own query
|
||||
SQLConnector.prototype.buildQueryTables = function(options) {
|
||||
throw new Error(g.f('{{buildQueryTables}} must be implemented by the connector'));
|
||||
};
|
||||
|
||||
/*!
|
||||
* Build sql for listing views
|
||||
* @param options {all: for all owners, owner: for a given owner}
|
||||
* @returns {string} The sql statement
|
||||
*/
|
||||
// Due to the different implementation structure of information_schema across
|
||||
// connectors, each connector will have to generate its own query
|
||||
SQLConnector.prototype.buildQueryViews = function(options) {
|
||||
throw new Error(g.f('{{buildQueryViews}} must be implemented by the connector'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Discover model definitions
|
||||
*
|
||||
* @param {Object} options Options for discovery
|
||||
* @param {Function} [cb] The callback function
|
||||
*/
|
||||
SQLConnector.prototype.discoverModelDefinitions = function(options, cb) {
|
||||
if (!cb && typeof options === 'function') {
|
||||
cb = options;
|
||||
options = {};
|
||||
}
|
||||
options = options || {};
|
||||
|
||||
var self = this;
|
||||
var calls = [function(callback) {
|
||||
self.execute(self.buildQueryTables(options), callback);
|
||||
}];
|
||||
|
||||
if (options.views) {
|
||||
calls.push(function(callback) {
|
||||
self.execute(self.buildQueryViews(options), callback);
|
||||
});
|
||||
}
|
||||
async.parallel(calls, function(err, data) {
|
||||
if (err) {
|
||||
cb(err, data);
|
||||
} else {
|
||||
var merged = [];
|
||||
merged = merged.concat(data.shift());
|
||||
if (data.length) {
|
||||
merged = merged.concat(data.shift());
|
||||
}
|
||||
cb(err, merged);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Build sql for listing columns
|
||||
* @param {String} schema The schema name
|
||||
* @param {String} table The table name
|
||||
*/
|
||||
// Due to the different implementation structure of information_schema across
|
||||
// connectors, each connector will have to generate its own query
|
||||
SQLConnector.prototype.buildQueryColumns = function(schema, table) {
|
||||
throw new Error(g.f('{{buildQueryColumns}} must be implemented by the connector'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Map the property type from database to loopback
|
||||
* @param {Object} columnDefinition The columnDefinition of the table/schema
|
||||
* @param {Object} options The options for the connector
|
||||
*/
|
||||
SQLConnector.prototype.buildPropertyType = function(columnDefinition, options) {
|
||||
throw new Error(g.f('{{buildPropertyType}} must be implemented by the connector'));
|
||||
};
|
||||
|
||||
/*!
|
||||
* Normalize the arguments
|
||||
* @param table string, required
|
||||
* @param options object, optional
|
||||
* @param cb function, optional
|
||||
*/
|
||||
SQLConnector.prototype.getArgs = function(table, options, cb) {
|
||||
throw new Error(g.f('{{getArgs}} must be implemented by the connector'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Discover model properties from a table
|
||||
* @param {String} table The table name
|
||||
* @param {Object} options The options for discovery
|
||||
* @param {Function} [cb] The callback function
|
||||
*/
|
||||
SQLConnector.prototype.discoverModelProperties = function(table, options, cb) {
|
||||
var self = this;
|
||||
var args = self.getArgs(table, options, cb);
|
||||
var schema = args.schema;
|
||||
|
||||
table = args.table;
|
||||
options = args.options;
|
||||
|
||||
if (!schema) {
|
||||
schema = self.getDefaultSchema();
|
||||
}
|
||||
|
||||
self.setDefaultOptions(options);
|
||||
cb = args.cb;
|
||||
|
||||
var sql = self.buildQueryColumns(schema, table);
|
||||
var callback = function(err, results) {
|
||||
if (err) {
|
||||
cb(err, results);
|
||||
} else {
|
||||
results.map(function(r) {
|
||||
r.type = self.buildPropertyType(r, options);
|
||||
self.setNullableProperty(r);
|
||||
});
|
||||
cb(err, results);
|
||||
}
|
||||
};
|
||||
this.execute(sql, callback);
|
||||
};
|
||||
|
||||
/*!
|
||||
* Build the sql statement for querying primary keys of a given table
|
||||
* @param schema
|
||||
* @param table
|
||||
* @returns {string}
|
||||
*/
|
||||
// http://docs.oracle.com/javase/6/docs/api/java/sql/DatabaseMetaData.html
|
||||
// #getPrimaryKeys(java.lang.String, java.lang.String, java.lang.String)
|
||||
// Due to the different implementation structure of information_schema across
|
||||
// connectors, each connector will have to generate its own query
|
||||
SQLConnector.prototype.buildQueryPrimaryKeys = function(schema, table) {
|
||||
throw new Error(g.f('{{buildQueryPrimaryKeys}} must be implemented by the connector'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Discover primary keys for a given table
|
||||
* @param {String} table The table name
|
||||
* @param {Object} options The options for discovery
|
||||
* @param {Function} [cb] The callback function
|
||||
*/
|
||||
SQLConnector.prototype.discoverPrimaryKeys = function(table, options, cb) {
|
||||
var self = this;
|
||||
var args = self.getArgs(table, options, cb);
|
||||
var schema = args.schema;
|
||||
|
||||
if (typeof(self.getDefaultSchema) === 'function' && !schema) {
|
||||
schema = self.getDefaultSchema();
|
||||
}
|
||||
table = args.table;
|
||||
options = args.options;
|
||||
cb = args.cb;
|
||||
|
||||
var sql = self.buildQueryPrimaryKeys(schema, table);
|
||||
this.execute(sql, cb);
|
||||
};
|
||||
|
||||
/*!
|
||||
* Build the sql statement for querying foreign keys of a given table
|
||||
* @param schema
|
||||
* @param table
|
||||
* @returns {string}
|
||||
*/
|
||||
// Due to the different implementation structure of information_schema across
|
||||
// connectors, each connector will have to generate its own query
|
||||
SQLConnector.prototype.buildQueryForeignKeys = function(schema, table) {
|
||||
throw new Error(g.f('{{buildQueryForeignKeys}} must be implemented by the connector'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Discover foreign keys for a given table
|
||||
* @param {String} table The table name
|
||||
* @param {Object} options The options for discovery
|
||||
* @param {Function} [cb] The callback function
|
||||
*/
|
||||
SQLConnector.prototype.discoverForeignKeys = function(table, options, cb) {
|
||||
var self = this;
|
||||
var args = self.getArgs(table, options, cb);
|
||||
var schema = args.schema;
|
||||
|
||||
if (typeof(self.getDefaultSchema) === 'function' && !schema) {
|
||||
schema = self.getDefaultSchema();
|
||||
}
|
||||
table = args.table;
|
||||
options = args.options;
|
||||
cb = args.cb;
|
||||
|
||||
var sql = self.buildQueryForeignKeys(schema, table);
|
||||
this.execute(sql, cb);
|
||||
};
|
||||
|
||||
/*!
|
||||
* Retrieves a description of the foreign key columns that reference the
|
||||
* given table's primary key columns (the foreign keys exported by a table).
|
||||
* They are ordered by fkTableOwner, fkTableName, and keySeq.
|
||||
* @param schema
|
||||
* @param table
|
||||
* @returns {string}
|
||||
*/
|
||||
// Due to the different implementation structure of information_schema across
|
||||
// connectors, each connector will have to generate its own query
|
||||
SQLConnector.prototype.buildQueryExportedForeignKeys = function(schema, table) {
|
||||
throw new Error(g.f('{{buildQueryExportedForeignKeys}} must be implemented by' +
|
||||
'the connector'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Discover foreign keys that reference to the primary key of this table
|
||||
* @param {String} table The table name
|
||||
* @param {Object} options The options for discovery
|
||||
* @param {Function} [cb] The callback function
|
||||
*/
|
||||
SQLConnector.prototype.discoverExportedForeignKeys = function(table, options, cb) {
|
||||
var self = this;
|
||||
var args = self.getArgs(table, options, cb);
|
||||
var schema = args.schema;
|
||||
|
||||
if (typeof(self.getDefaultSchema) === 'function' && !schema) {
|
||||
schema = self.getDefaultSchema();
|
||||
}
|
||||
table = args.table;
|
||||
options = args.options;
|
||||
cb = args.cb;
|
||||
|
||||
var sql = self.buildQueryExportedForeignKeys(schema, table);
|
||||
this.execute(sql, cb);
|
||||
};
|
||||
|
||||
/**
|
||||
* Discover default schema of a database
|
||||
* @param {Object} options The options for discovery
|
||||
*/
|
||||
SQLConnector.prototype.getDefaultSchema = function(options) {
|
||||
throw new Error(g.f('{{getDefaultSchema}} must be implemented by' +
|
||||
'the connector'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Set default options for the connector
|
||||
* @param {Object} options The options for discovery
|
||||
*/
|
||||
SQLConnector.prototype.setDefaultOptions = function(options) {
|
||||
throw new Error(g.f('{{setDefaultOptions}} must be implemented by' +
|
||||
'the connector'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the nullable value for the property
|
||||
* @param {Object} property The property to set nullable
|
||||
*/
|
||||
SQLConnector.prototype.setNullableProperty = function(property) {
|
||||
throw new Error(g.f('{{setNullableProperty}} must be implemented by' +
|
||||
'the connector'));
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue