Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: fetch unique index information for columns #622

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 81 additions & 28 deletions lib/discovery.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down
17 changes: 17 additions & 0 deletions test/mysql.discover.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,23 @@ describe('Discover model primary keys', function() {
});
});

describe('Discover user model with index', function() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please add some more test cases to cover more negative scenarios and other worst cases ?

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) {
Expand Down
15 changes: 15 additions & 0 deletions test/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -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`
--
Expand Down