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

Commit cb48ef17 by Sushant Committed by GitHub

feat(describeTable): support autoIncrement for mysql (#9894)

1 parent 5dfb7188
......@@ -146,6 +146,7 @@ class Query extends AbstractQuery {
allowNull: _result.Null === 'YES',
defaultValue: _result.Default,
primaryKey: _result.Key === 'PRI',
autoIncrement: _result.hasOwnProperty('Extra') && _result.Extra.toLowerCase() === 'auto_increment',
comment: _result.Comment ? _result.Comment : null
};
}
......
......@@ -100,29 +100,27 @@ class PostgresQueryGenerator extends AbstractQueryGenerator {
}
describeTableQuery(tableName, schema) {
if (!schema) {
schema = 'public';
}
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) || (CASE WHEN c.character_maximum_length IS NOT NULL THEN \'(\' || c.character_maximum_length || \')\' ELSE \'\' 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", ' +
'(SELECT pgd.description FROM pg_catalog.pg_statio_all_tables AS st ' +
'INNER JOIN pg_catalog.pg_description pgd on (pgd.objoid=st.relid) ' +
'WHERE c.ordinal_position=pgd.objsubid AND c.table_name=st.relname) AS "Comment" ' +
'FROM information_schema.columns c ' +
'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 ' +
if (!schema) schema = 'public';
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) || (CASE WHEN c.character_maximum_length IS NOT NULL THEN \'(\' || c.character_maximum_length || \')\' ELSE \'\' 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", ' +
'(SELECT pgd.description FROM pg_catalog.pg_statio_all_tables AS st INNER JOIN pg_catalog.pg_description pgd on (pgd.objoid=st.relid) WHERE c.ordinal_position=pgd.objsubid AND c.table_name=st.relname) AS "Comment" ' +
'FROM information_schema.columns c ' +
'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)} `;
}
......@@ -856,22 +854,22 @@ class PostgresQueryGenerator extends AbstractQueryGenerator {
*/
_getForeignKeyReferencesQueryPrefix() {
return 'SELECT ' +
'DISTINCT tc.constraint_name as constraint_name, ' +
'tc.constraint_schema as constraint_schema, ' +
'tc.constraint_catalog as constraint_catalog, ' +
'tc.table_name as table_name,' +
'tc.table_schema as table_schema,' +
'tc.table_catalog as table_catalog,' +
'kcu.column_name as column_name,' +
'ccu.table_schema AS referenced_table_schema,' +
'ccu.table_catalog AS referenced_table_catalog,' +
'ccu.table_name AS referenced_table_name,' +
'ccu.column_name AS referenced_column_name ' +
'DISTINCT tc.constraint_name as constraint_name, ' +
'tc.constraint_schema as constraint_schema, ' +
'tc.constraint_catalog as constraint_catalog, ' +
'tc.table_name as table_name,' +
'tc.table_schema as table_schema,' +
'tc.table_catalog as table_catalog,' +
'kcu.column_name as column_name,' +
'ccu.table_schema AS referenced_table_schema,' +
'ccu.table_catalog AS referenced_table_catalog,' +
'ccu.table_name AS referenced_table_name,' +
'ccu.column_name AS referenced_column_name ' +
'FROM information_schema.table_constraints AS tc ' +
'JOIN information_schema.key_column_usage AS kcu ' +
'ON tc.constraint_name = kcu.constraint_name ' +
'JOIN information_schema.constraint_column_usage AS ccu ' +
'ON ccu.constraint_name = tc.constraint_name ';
'JOIN information_schema.key_column_usage AS kcu ' +
'ON tc.constraint_name = kcu.constraint_name ' +
'JOIN information_schema.constraint_column_usage AS ccu ' +
'ON ccu.constraint_name = tc.constraint_name ';
}
/**
......
......@@ -143,128 +143,6 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => {
});
});
describe('describeTable', () => {
it('reads the metadata of the table', function() {
const self = this;
const Users = self.sequelize.define('_Users', {
username: DataTypes.STRING,
city: {
type: DataTypes.STRING,
defaultValue: null,
comment: 'Users City'
},
isAdmin: DataTypes.BOOLEAN,
enumVals: DataTypes.ENUM('hello', 'world')
}, { freezeTableName: true });
return Users.sync({ force: true }).then(() => {
return self.queryInterface.describeTable('_Users').then(metadata => {
const id = metadata.id;
const username = metadata.username;
const city = metadata.city;
const isAdmin = metadata.isAdmin;
const enumVals = metadata.enumVals;
expect(id.primaryKey).to.be.ok;
let assertVal = 'VARCHAR(255)';
switch (dialect) {
case 'postgres':
assertVal = 'CHARACTER VARYING(255)';
break;
case 'mssql':
assertVal = 'NVARCHAR';
break;
}
expect(username.type).to.equal(assertVal);
expect(username.allowNull).to.be.true;
switch (dialect) {
case 'sqlite':
expect(username.defaultValue).to.be.undefined;
break;
default:
expect(username.defaultValue).to.be.null;
}
switch (dialect) {
case 'sqlite':
expect(city.defaultValue).to.be.null;
break;
}
assertVal = 'TINYINT(1)';
switch (dialect) {
case 'postgres':
assertVal = 'BOOLEAN';
break;
case 'mssql':
assertVal = 'BIT';
break;
}
expect(isAdmin.type).to.equal(assertVal);
expect(isAdmin.allowNull).to.be.true;
switch (dialect) {
case 'sqlite':
expect(isAdmin.defaultValue).to.be.undefined;
break;
default:
expect(isAdmin.defaultValue).to.be.null;
}
if (dialect === 'postgres' || dialect === 'postgres-native') {
expect(enumVals.special).to.be.instanceof(Array);
expect(enumVals.special).to.have.length(2);
} else if (dialect === 'mysql') {
expect(enumVals.type).to.eql('ENUM(\'hello\',\'world\')');
}
if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'mssql') {
expect(city.comment).to.equal('Users City');
expect(username.comment).to.equal(null);
}
});
});
});
it('should correctly determine the primary key columns', function() {
const self = this;
const Country = self.sequelize.define('_Country', {
code: {type: DataTypes.STRING, primaryKey: true },
name: {type: DataTypes.STRING, allowNull: false}
}, { freezeTableName: true });
const 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(() => {
return self.queryInterface.describeTable('_Country').then(metacountry => {
expect(metacountry.code.primaryKey).to.eql(true);
expect(metacountry.name.primaryKey).to.eql(false);
return Alumni.sync({ force: true }).then(() => {
return self.queryInterface.describeTable('_Alumni').then(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);
});
});
});
});
});
});
describe('renameColumn', () => {
it('rename a simple column', function() {
const self = this;
......
'use strict';
const chai = require('chai');
const expect = chai.expect;
const Support = require(__dirname + '/../support');
const DataTypes = require(__dirname + '/../../../lib/data-types');
const dialect = Support.getTestDialect();
describe(Support.getTestDialectTeaser('QueryInterface'), () => {
beforeEach(function () {
this.sequelize.options.quoteIdenifiers = true;
this.queryInterface = this.sequelize.getQueryInterface();
});
afterEach(function () {
return this.sequelize.dropAllSchemas();
});
describe('describeTable', () => {
it('reads the metadata of the table', function() {
const self = this;
const Users = self.sequelize.define('_Users', {
username: DataTypes.STRING,
city: {
type: DataTypes.STRING,
defaultValue: null,
comment: 'Users City'
},
isAdmin: DataTypes.BOOLEAN,
enumVals: DataTypes.ENUM('hello', 'world')
}, { freezeTableName: true });
return Users.sync({ force: true }).then(() => {
return self.queryInterface.describeTable('_Users').then(metadata => {
const id = metadata.id;
const username = metadata.username;
const city = metadata.city;
const isAdmin = metadata.isAdmin;
const enumVals = metadata.enumVals;
expect(id.primaryKey).to.be.true;
if (['mysql', 'mssql'].includes(dialect)) {
expect(id.autoIncrement).to.be.true;
}
let assertVal = 'VARCHAR(255)';
switch (dialect) {
case 'postgres':
assertVal = 'CHARACTER VARYING(255)';
break;
case 'mssql':
assertVal = 'NVARCHAR';
break;
}
expect(username.type).to.equal(assertVal);
expect(username.allowNull).to.be.true;
switch (dialect) {
case 'sqlite':
expect(username.defaultValue).to.be.undefined;
break;
default:
expect(username.defaultValue).to.be.null;
}
switch (dialect) {
case 'sqlite':
expect(city.defaultValue).to.be.null;
break;
}
assertVal = 'TINYINT(1)';
switch (dialect) {
case 'postgres':
assertVal = 'BOOLEAN';
break;
case 'mssql':
assertVal = 'BIT';
break;
}
expect(isAdmin.type).to.equal(assertVal);
expect(isAdmin.allowNull).to.be.true;
switch (dialect) {
case 'sqlite':
expect(isAdmin.defaultValue).to.be.undefined;
break;
default:
expect(isAdmin.defaultValue).to.be.null;
}
if (dialect.match(/^postgres/)) {
expect(enumVals.special).to.be.instanceof(Array);
expect(enumVals.special).to.have.length(2);
} else if (dialect === 'mysql') {
expect(enumVals.type).to.eql('ENUM(\'hello\',\'world\')');
}
if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'mssql') {
expect(city.comment).to.equal('Users City');
expect(username.comment).to.equal(null);
}
});
});
});
it('should correctly determine the primary key columns', function() {
const self = this;
const Country = self.sequelize.define('_Country', {
code: {type: DataTypes.STRING, primaryKey: true },
name: {type: DataTypes.STRING, allowNull: false}
}, { freezeTableName: true });
const 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(() => {
return self.queryInterface.describeTable('_Country').then(metacountry => {
expect(metacountry.code.primaryKey).to.eql(true);
expect(metacountry.name.primaryKey).to.eql(false);
return Alumni.sync({ force: true }).then(() => {
return self.queryInterface.describeTable('_Alumni').then(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);
});
});
});
});
});
});
});
\ No newline at end of file
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!