不要怂,就是干,撸起袖子干!

Commit 55948897 by Antonio Begines Committed by Jan Aagaard Meier

Fix "describeTable returns a wrong value for primaryKey" #5756 (#6966)

* issue #5756 correct PKs with describeTable

* #5756 FIXED

* #5756 FIXED describeTable

* #5736 fixed

* #5736 test & fixes (describeTable PK)

* #5756  hash and link
1 parent 727ae363
# Future
- [FIXED] describeTable returns a wrong value for primaryKey [#5756] (https://github.com/sequelize/sequelize/issues/5756)
- [FIXED] MSSQL LIMIT IN UPDATE [#6636](https://github.com/sequelize/sequelize/issues/6636)
- [FIXED] Custom error message not used for `notNull` validation [#6531](https://github.com/sequelize/sequelize/issues/6531)
- [FIXED] N:M `through` option naming collisions [#4597](https://github.com/sequelize/sequelize/issues/4597)
......
......@@ -118,15 +118,21 @@ var QueryGenerator = {
"c.CHARACTER_MAXIMUM_LENGTH AS 'Length',",
"c.IS_NULLABLE as 'IsNull',",
"COLUMN_DEFAULT AS 'Default',",
"tc.CONSTRAINT_TYPE AS 'Constraint'",
"pk.CONSTRAINT_TYPE AS 'Constraint'",
'FROM',
'INFORMATION_SCHEMA.TABLES t',
'INNER JOIN',
'INFORMATION_SCHEMA.COLUMNS c ON t.TABLE_NAME = c.TABLE_NAME AND t.TABLE_SCHEMA = c.TABLE_SCHEMA',
'LEFT JOIN',
'INFORMATION_SCHEMA.KEY_COLUMN_USAGE cu ON t.TABLE_NAME = cu.TABLE_NAME AND cu.COLUMN_NAME = c.COLUMN_NAME AND t.TABLE_SCHEMA = cu.TABLE_SCHEMA',
'LEFT JOIN',
'INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc ON t.TABLE_NAME = tc.TABLE_NAME AND cu.COLUMN_NAME = c.COLUMN_NAME AND tc.CONSTRAINT_TYPE = \'PRIMARY KEY\'',
'LEFT JOIN (SELECT tc.table_schema, tc.table_name, ',
'cu.column_name, tc.constraint_type ',
'FROM information_schema.TABLE_CONSTRAINTS tc ',
'JOIN information_schema.KEY_COLUMN_USAGE cu ',
'ON tc.table_schema=cu.table_schema and tc.table_name=cu.table_name ',
'and tc.constraint_name=cu.constraint_name ',
'and tc.constraint_type=\'PRIMARY KEY\') pk ',
'ON pk.table_schema=c.table_schema ',
'AND pk.table_name=c.table_name ',
'AND pk.column_name=c.column_name ',
'WHERE t.TABLE_NAME =', wrapSingleQuote(tableName)
].join(' ');
......
......@@ -101,14 +101,23 @@ const QueryGenerator = {
if (!schema) {
schema = 'public';
}
return 'SELECT tc.constraint_type as "Constraint", c.column_name as "Field", c.column_default as "Default", c.is_nullable as "Null", ' +
"CASE WHEN c.udt_name = 'hstore' " +
'THEN c.udt_name ELSE c.data_type END as "Type", (SELECT array_agg(e.enumlabel) ' +
'FROM pg_catalog.pg_type t JOIN pg_catalog.pg_enum e ON t.oid=e.enumtypid WHERE t.typname=c.udt_name) AS "special" ' +
return 'SELECT pk.constraint_type as "Constraint", c.column_name as "Field", ' +
'c.column_default as "Default", c.is_nullable as "Null", ' +
'CASE WHEN c.udt_name = \'hstore\' THEN c.udt_name ELSE c.data_type END as "Type", ' +
'(SELECT array_agg(e.enumlabel) ' +
'FROM pg_catalog.pg_type t JOIN pg_catalog.pg_enum e ON t.oid=e.enumtypid ' +
'WHERE t.typname=c.udt_name) AS "special" ' +
'FROM information_schema.columns c ' +
'LEFT JOIN information_schema.key_column_usage cu ON c.table_name = cu.table_name AND cu.column_name = c.column_name ' +
'LEFT JOIN information_schema.table_constraints tc ON c.table_name = tc.table_name AND cu.column_name = c.column_name AND tc.constraint_type = \'PRIMARY KEY\' ' +
'LEFT JOIN (SELECT tc.table_schema, tc.table_name, ' +
'cu.column_name, tc.constraint_type ' +
'FROM information_schema.TABLE_CONSTRAINTS tc ' +
'JOIN information_schema.KEY_COLUMN_USAGE cu ' +
'ON tc.table_schema=cu.table_schema and tc.table_name=cu.table_name ' +
'and tc.constraint_name=cu.constraint_name ' +
'and tc.constraint_type=\'PRIMARY KEY\') pk ' +
'ON pk.table_schema=c.table_schema ' +
'AND pk.table_name=c.table_name ' +
'AND pk.column_name=c.column_name ' +
`WHERE c.table_name = ${this.escape(tableName)} AND c.table_schema = ${this.escape(schema)} `;
},
......
......@@ -213,7 +213,7 @@ class Query extends AbstractQuery {
type: _result.type,
allowNull: (_result.notnull === 0),
defaultValue,
primaryKey : (_result.pk === 1)
primaryKey: (_result.pk !== 0)
};
if (result[_result.name].type === 'TINYINT(1)') {
......
......@@ -206,6 +206,43 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() {
});
});
});
it('should correctly determine the primary key columns', function () {
var self = this;
var Country = self.sequelize.define('_Country', {
code: {type: DataTypes.STRING, primaryKey: true },
name: {type: DataTypes.STRING, allowNull: false}
}, { freezeTableName: true });
var Alumni = self.sequelize.define('_Alumni', {
year: {type: DataTypes.INTEGER, primaryKey: true },
num: {type: DataTypes.INTEGER, primaryKey: true },
username: {type: DataTypes.STRING, allowNull: false, unique: true },
dob: {type: DataTypes.DATEONLY, allowNull: false },
dod: {type: DataTypes.DATEONLY, allowNull: true },
city: {type: DataTypes.STRING, allowNull: false},
ctrycod: {type: DataTypes.STRING, allowNull: false,
references: { model: Country, key: 'code'}}
}, { freezeTableName: true });
return Country.sync({ force: true }).then(function() {
return self.queryInterface.describeTable('_Country').then(function(metacountry) {
expect(metacountry.code.primaryKey).to.eql(true);
expect(metacountry.name.primaryKey).to.eql(false);
return Alumni.sync({ force: true }).then(function() {
return self.queryInterface.describeTable('_Alumni').then(function(metalumni) {
expect(metalumni.year.primaryKey).to.eql(true);
expect(metalumni.num.primaryKey).to.eql(true);
expect(metalumni.username.primaryKey).to.eql(false);
expect(metalumni.dob.primaryKey).to.eql(false);
expect(metalumni.dod.primaryKey).to.eql(false);
expect(metalumni.ctrycod.primaryKey).to.eql(false);
expect(metalumni.city.primaryKey).to.eql(false);
});
});
});
});
});
});
// FIXME: These tests should make assertions against the created table using describeTable
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!