diff --git a/lib/discovery.js b/lib/discovery.js index 615c54da..fc4bbfeb 100644 --- a/lib/discovery.js +++ b/lib/discovery.js @@ -157,37 +157,90 @@ function mixinDiscovery(MySQL, mysql) { MySQL.prototype.buildQueryColumns = function(schema, table, options = {}) { let sql = null; if (schema) { - sql = paginateSQL('SELECT table_schema AS "owner",' + - ' table_name AS "tableName",' + - ' column_name AS "columnName",' + - ' data_type AS "dataType",' + - ' character_maximum_length AS "dataLength",' + - ' numeric_precision AS "dataPrecision",' + - ' numeric_scale AS "dataScale",' + - ' column_type AS "columnType",' + - ' is_nullable = \'YES\' AS "nullable",' + - ' CASE WHEN extra LIKE \'%auto_increment%\' THEN 1 ELSE 0 END AS "generated"' + - ' FROM information_schema.columns' + - ' WHERE table_schema=' + mysql.escape(schema) + - (table ? ' AND table_name=' + mysql.escape(table) : ''), - 'table_name, ordinal_position', {}); + sql = paginateSQL( + `SELECT + cols.table_schema AS "owner", + cols.table_name AS "tableName", + cols.column_name AS "columnName", + cols.data_type AS "dataType", + cols.character_maximum_length AS "dataLength", + cols.numeric_precision AS "dataPrecision", + cols.numeric_scale AS "dataScale", + cols.column_type AS "columnType", + cols.is_nullable = 'YES' AS "nullable", + CASE WHEN cols.extra LIKE '%auto_increment%' THEN 1 ELSE 0 END AS "generated", + indexes.index_name AS "indexName", + indexes.non_unique AS "nonUnique", + indexes.seq_in_index AS "seqInIndex", + indexes.cardinality AS "cardinality", + indexes.index_type AS "indexType", + CASE WHEN fk.column_name IS NOT NULL THEN 1 ELSE 0 END AS "isForeignKey" + FROM + information_schema.columns cols + LEFT JOIN + information_schema.statistics indexes + ON + cols.table_schema = indexes.table_schema + AND cols.table_name = indexes.table_name + AND cols.column_name = indexes.column_name + LEFT JOIN + information_schema.KEY_COLUMN_USAGE fk + ON + cols.table_schema = fk.table_schema + AND cols.table_name = fk.table_name + AND cols.column_name = fk.column_name + AND fk.referenced_table_name IS NOT NULL + WHERE + cols.table_schema = ${mysql.escape(schema)} + ${table ? ' AND cols.table_name = ' + mysql.escape(table) : ''} + `, + 'cols.table_name, cols.ordinal_position', + {}, + ); } else { - sql = paginateSQL('SELECT table_schema AS "owner",' + - ' table_name AS "tableName",' + - ' column_name AS "columnName",' + - ' data_type AS "dataType",' + - ' character_maximum_length AS "dataLength",' + - ' numeric_precision AS "dataPrecision",' + - ' numeric_scale AS "dataScale",' + - ' column_type AS "columnType",' + - ' is_nullable = \'YES\' AS "nullable",' + - ' CASE WHEN extra LIKE \'%auto_increment%\' THEN 1 ELSE 0 END AS "generated"' + - ' FROM information_schema.columns' + - (table ? ' WHERE table_name=' + mysql.escape(table) : ''), - 'table_name, ordinal_position', {}); + sql = paginateSQL( + `SELECT + cols.table_schema AS "owner", + cols.table_name AS "tableName", + cols.column_name AS "columnName", + cols.data_type AS "dataType", + cols.character_maximum_length AS "dataLength", + cols.numeric_precision AS "dataPrecision", + cols.numeric_scale AS "dataScale", + cols.column_type AS "columnType", + cols.is_nullable = 'YES' AS "nullable", + CASE WHEN cols.extra LIKE '%auto_increment%' THEN 1 ELSE 0 END AS "generated", + indexes.index_name AS "indexName", + indexes.seq_in_index AS "indexColumnOrder", + indexes.non_unique AS "nonUnique", + indexes.cardinality AS "cardinality", + indexes.index_type AS "indexType", + CASE WHEN fk.column_name IS NOT NULL THEN 1 ELSE 0 END AS "isForeignKey" + FROM + information_schema.columns AS cols + LEFT JOIN + information_schema.statistics AS indexes + ON + cols.table_schema = indexes.table_schema + AND cols.table_name = indexes.table_name + AND cols.column_name = indexes.column_name + LEFT JOIN + information_schema.KEY_COLUMN_USAGE AS fk + ON + cols.table_schema = fk.table_schema + AND cols.table_name = fk.table_name + AND cols.column_name = fk.column_name + AND fk.referenced_table_name IS NOT NULL + WHERE + cols.table_schema = ${mysql.escape(schema)} + ${table ? ' AND cols.table_name = ' + mysql.escape(table) : ''} + `, + 'cols.table_name, cols.ordinal_position', + {}, + ); } if (options.orderBy) { - sql += ' ORDER BY ' + options.orderBy; + sql += ' ORDER BY ' + 'cols.' + options.orderBy; } return sql; }; diff --git a/test/mysql.discover.test.js b/test/mysql.discover.test.js index b6d9c9c2..ed60abba 100644 --- a/test/mysql.discover.test.js +++ b/test/mysql.discover.test.js @@ -199,6 +199,23 @@ describe('Discover model primary keys', function() { }); }); +describe('Discover user model with index', function() { + it('should return user with index', function(done) { + db.discoverModelProperties('user', function(err, models) { + if (err) { + console.error(err); + done(err); + } else { + models.forEach(function(m) { + assert(m.tableName.toLowerCase() === 'user'); + assert(m.properties.email.index); + }); + 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) { diff --git a/test/schema.sql b/test/schema.sql index 62d3acad..7c09b1f7 100644 --- a/test/schema.sql +++ b/test/schema.sql @@ -208,6 +208,21 @@ LOCK TABLES `RESERVATION` WRITE; /*!40000 ALTER TABLE `RESERVATION` ENABLE KEYS */; UNLOCK TABLES; +DROP TABLE IF EXISTS `USER`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; + +CREATE TABLE `USER` ( + `ID` VARCHAR(20) NOT NULL, + `NAME` VARCHAR(100) NOT NULL, + `EMAIL` VARCHAR(255) NOT NULL, + `PASSWORD` VARCHAR(255) NOT NULL, + `CREATED_AT` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + `UPDATED_AT` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`ID`), + UNIQUE KEY `USER_EMAIL_UNIQUE` (`EMAIL`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + -- -- Table structure for table `TESTGEN` --