From 4bedf2200c0b8e25062ffb7df3ce28af40f25355 Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Sun, 21 Jul 2013 22:57:19 -0700 Subject: [PATCH] Add discovery test cases --- example/table.sql | 82 +++++++++++++++ lib/discovery.js | 11 +- test/mysql.discover.test.js | 202 ++++++++++++++++++++++++++++++++++++ 3 files changed, 291 insertions(+), 4 deletions(-) create mode 100644 example/table.sql create mode 100644 test/mysql.discover.test.js diff --git a/example/table.sql b/example/table.sql new file mode 100644 index 0000000..3db25c0 --- /dev/null +++ b/example/table.sql @@ -0,0 +1,82 @@ +CREATE SCHEMA IF NOT EXISTS STRONGLOOP DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ; + +USE STRONGLOOP; + + +CREATE TABLE STRONGLOOP.PRODUCT + (ID VARCHAR(20) NOT NULL, + NAME VARCHAR(64), + AUDIBLE_RANGE DECIMAL(12,2), + EFFECTIVE_RANGE DECIMAL(12,2), + ROUNDS DECIMAL(10,0), + EXTRAS VARCHAR(64), + FIRE_MODES VARCHAR(64), + PRIMARY KEY (ID)); + +CREATE TABLE STRONGLOOP.LOCATION + (ID VARCHAR(20) NOT NULL, + STREET VARCHAR(20), + CITY VARCHAR(20), + ZIPCODE VARCHAR(20), + NAME VARCHAR(20), + PRIMARY KEY (ID)); + +CREATE TABLE STRONGLOOP.CUSTOMER + (ID VARCHAR(20) NOT NULL, + NAME VARCHAR(40), + MILITARY_AGENCY VARCHAR(20), + PRIMARY KEY (ID)); + +CREATE TABLE STRONGLOOP.INVENTORY + (PRODUCT_ID VARCHAR(20) NOT NULL, + LOCATION_ID VARCHAR(20) NOT NULL, + AVAILABLE INT, + TOTAL INT, + PRIMARY KEY (PRODUCT_ID, LOCATION_ID), + CONSTRAINT PRODUCT_FK FOREIGN KEY (PRODUCT_ID) + REFERENCES STRONGLOOP.PRODUCT (ID), + CONSTRAINT LOCATION_FK FOREIGN KEY (LOCATION_ID) + REFERENCES STRONGLOOP.LOCATION (ID) + ); + +CREATE TABLE STRONGLOOP.RESERVATION + (ID VARCHAR(20) NOT NULL, + PRODUCT_ID VARCHAR(20) NOT NULL, + LOCATION_ID VARCHAR(20) NOT NULL, + CUSTOMER_ID VARCHAR(20) NOT NULL, + QTY INT, + STATUS VARCHAR(20), + RESERVE_DATE DATE, + PICKUP_DATE DATE, + RETURN_DATE DATE, + PRIMARY KEY(ID), + CONSTRAINT RESERVATION_PRODUCT_FK FOREIGN KEY (PRODUCT_ID) + REFERENCES STRONGLOOP.PRODUCT (ID), + CONSTRAINT RESERVATION_LOCATION_FK FOREIGN KEY (LOCATION_ID) + REFERENCES STRONGLOOP.LOCATION (ID), + CONSTRAINT RESERVATION_CUSTOMER_FK FOREIGN KEY (CUSTOMER_ID) + REFERENCES STRONGLOOP.CUSTOMER (ID) + ); + + + CREATE OR REPLACE VIEW STRONGLOOP.INVENTORY_VIEW + (ID, PRODUCT_ID, PRODUCT_NAME, AUDIBLE_RANGE, EFFECTIVE_RANGE, ROUNDS, EXTRAS, FIRE_MODES, LOCATION_ID, LOCATION, CITY, ZIPCODE, AVAILABLE) AS + SELECT + CONCAT(CONCAT(P.ID, ':'), L.ID) AS ID, + P.ID AS PRODUCT_ID, + P.NAME AS PRODUCT_NAME, + P.AUDIBLE_RANGE, + P.EFFECTIVE_RANGE, + P.ROUNDS, + P.EXTRAS, + P.FIRE_MODES, + L.ID AS LOCATION_ID, + L.NAME AS LOCATION, + L.CITY, + L.ZIPCODE, + I.AVAILABLE + + FROM INVENTORY I, PRODUCT P, LOCATION L + + WHERE P.ID = I.PRODUCT_ID AND L.ID = I.LOCATION_ID; + \ No newline at end of file diff --git a/lib/discovery.js b/lib/discovery.js index 47b1cbb..f45e901 100644 --- a/lib/discovery.js +++ b/lib/discovery.js @@ -3,15 +3,18 @@ module.exports = mixinDiscovery; function mixinDiscovery(MySQL) { var async = require('async'); - function paginateSQL(sql, options) { + function paginateSQL(sql, orderBy, options) { options = options || {}; var limit = ''; if (options.offset || options.skip || options.limit) { - limit = 'LIMIT ' + (options.offset || options.skip || 1); + limit = ' LIMIT ' + (options.offset || options.skip || 0); // Offset starts from 0 if (options.limit) { - limit = limit + ' ' + options.limit; + limit = limit + ',' + options.limit; } } + if(!orderBy) { + sql += ' ORDER BY ' + orderBy; + } return sql + limit; } @@ -56,7 +59,7 @@ function mixinDiscovery(MySQL) { } else if (owner) { sqlViews = paginateSQL('SELECT \'view\' AS "type", table_name AS "name",' + ' table_schema AS "owner" FROM information_schema.views WHERE table_schema=\'' + owner + '\'', - 'owner, table_name', options); + 'table_schema, table_name', options); } else { sqlViews = paginateSQL('SELECT \'view\' AS "type", table_name AS "name",' + ' SUBSTRING_INDEX(USER(), \'@\', 1) AS "owner" FROM information_schema.views', diff --git a/test/mysql.discover.test.js b/test/mysql.discover.test.js new file mode 100644 index 0000000..51ad6bd --- /dev/null +++ b/test/mysql.discover.test.js @@ -0,0 +1,202 @@ +process.env.NODE_ENV = 'test'; +require('should'); + +var assert = require('assert'); + +var Schema = require('loopback-data').Schema; +var db; + +before(function() { + + db = new Schema(require('../'), { + host: '127.0.0.1', + port: 3306, + database: 'STRONGLOOP', + username: 'strongloop', + password: 'password' + }); + +}); + +describe('discoverModels', function() { + describe('Discover models including views', function() { + it('should return an array of tables and views', function(done) { + + db.discoverModelDefinitions({ + views : true, + limit : 3 + }, function(err, models) { + if (err) { + console.error(err); + done(err); + } else { + var views = false; + models.forEach(function(m) { + console.dir(m); + if (m.type === 'view') { + views = true; + } + }); + assert(views, 'Should have views'); + done(null, models); + } + }); + }); + }); + + describe('Discover models excluding views', function() { + it('should return an array of only tables', function(done) { + + db.discoverModelDefinitions({ + views : false, + limit : 3 + }, function(err, models) { + if (err) { + console.error(err); + done(err); + } else { + var views = false; + models.forEach(function(m) { + console.dir(m); + if (m.type === 'view') { + views = true; + } + }); + models.should.have.length(3); + assert(!views, 'Should not have views'); + done(null, models); + } + }); + }); + }); +}); + +describe('Discover models including other users', function() { + it('should return an array of all tables and views', function(done) { + + db.discoverModelDefinitions({ + all : true, + limit : 3 + }, function(err, models) { + if (err) { + console.error(err); + done(err); + } else { + var others = false; + models.forEach(function(m) { + console.dir(m); + if (m.owner !== 'STRONGLOOP') { + others = true; + } + }); + assert(others, 'Should have tables/views owned by others'); + done(err, models); + } + }); + }); +}); + +describe('Discover model properties', function() { + describe('Discover a named model', function() { + it('should return an array of columns for PRODUCT', function(done) { + db.discoverModelProperties('PRODUCT', function(err, models) { + if (err) { + console.error(err); + done(err); + } else { + models.forEach(function(m) { + console.dir(m); + assert(m.tableName === 'PRODUCT'); + }); + done(null, models); + } + }); + }); + }); + +}); + +describe('Discover model primary keys', function () { + it('should return an array of primary keys for PRODUCT', function (done) { + db.discoverPrimaryKeys('PRODUCT',function (err, models) { + if (err) { + console.error(err); + done(err); + } else { + models.forEach(function (m) { + console.dir(m); + assert(m.tableName === 'PRODUCT'); + }); + done(null, models); + } + }); + }); + + it('should return an array of primary keys for STRONGLOOP.PRODUCT', function (done) { + db.discoverPrimaryKeys('PRODUCT', {owner: 'STRONGLOOP'}, function (err, models) { + if (err) { + console.error(err); + done(err); + } else { + models.forEach(function (m) { + console.dir(m); + assert(m.tableName === 'PRODUCT'); + }); + done(null, models); + } + }); + }); +}); + +describe('Discover model foreign keys', function () { + it('should return an array of foreign keys for INVENTORY', function (done) { + db.discoverForeignKeys('INVENTORY',function (err, models) { + if (err) { + console.error(err); + done(err); + } else { + models.forEach(function (m) { + console.dir(m); + assert(m.fkTableName === 'INVENTORY'); + }); + done(null, models); + } + }); + }); + it('should return an array of foreign keys for STRONGLOOP.INVENTORY', function (done) { + db.discoverForeignKeys('INVENTORY', {owner: 'STRONGLOOP'}, function (err, models) { + if (err) { + console.error(err); + done(err); + } else { + models.forEach(function (m) { + console.dir(m); + assert(m.fkTableName === 'INVENTORY'); + }); + done(null, models); + } + }); + }); +}); + +describe('Discover ADL schema from a table', function () { + it('should return an ADL schema for INVENTORY', function (done) { + db.discoverSchema('INVENTORY', {owner: 'STRONGLOOP'}, function (err, schema) { + console.log('%j', schema); + assert(schema.name === 'Inventory'); + assert(schema.options.mysql.schema === 'STRONGLOOP'); + assert(schema.options.mysql.table === 'INVENTORY'); + assert(schema.properties.productId); + assert(schema.properties.productId.type === 'String'); + assert(schema.properties.productId.mysql.columnName === 'PRODUCT_ID'); + assert(schema.properties.locationId); + assert(schema.properties.locationId.type === 'String'); + assert(schema.properties.locationId.mysql.columnName === 'LOCATION_ID'); + assert(schema.properties.available); + assert(schema.properties.available.type === 'Number'); + assert(schema.properties.total); + assert(schema.properties.total.type === 'Number'); + done(null, schema); + }); + }); +});