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

Commit b896ba4d by Mirko Jotic Committed by Sushant

fix(query-generator): fix addColumn create comment (#10117)

1 parent 11f56fcd
...@@ -110,12 +110,7 @@ class MSSQLQueryGenerator extends AbstractQueryGenerator { ...@@ -110,12 +110,7 @@ class MSSQLQueryGenerator extends AbstractQueryGenerator {
const query = (table, attrs) => `IF OBJECT_ID('${table}', 'U') IS NULL CREATE TABLE ${table} (${attrs})`, const query = (table, attrs) => `IF OBJECT_ID('${table}', 'U') IS NULL CREATE TABLE ${table} (${attrs})`,
primaryKeys = [], primaryKeys = [],
foreignKeys = {}, foreignKeys = {},
attrStr = [], attrStr = [];
commentTemplate = (comment, table, column) => ' EXEC sp_addextendedproperty ' +
`@name = N\'MS_Description\', @value = ${comment}, ` +
'@level0type = N\'Schema\', @level0name = \'dbo\', ' +
`@level1type = N\'Table\', @level1name = ${table}, ` +
`@level2type = N\'Column\', @level2name = ${column};`;
let commentStr = ''; let commentStr = '';
...@@ -127,7 +122,7 @@ class MSSQLQueryGenerator extends AbstractQueryGenerator { ...@@ -127,7 +122,7 @@ class MSSQLQueryGenerator extends AbstractQueryGenerator {
if (dataType.includes('COMMENT ')) { if (dataType.includes('COMMENT ')) {
const commentMatch = dataType.match(/^(.+) (COMMENT.*)$/); const commentMatch = dataType.match(/^(.+) (COMMENT.*)$/);
const commentText = commentMatch[2].replace('COMMENT', '').trim(); const commentText = commentMatch[2].replace('COMMENT', '').trim();
commentStr += commentTemplate(this.escape(commentText), this.quoteIdentifier(tableName), this.quoteIdentifier(attr)); commentStr += this.commentTemplate(commentText, tableName, attr);
// remove comment related substring from dataType // remove comment related substring from dataType
dataType = commentMatch[1]; dataType = commentMatch[1];
} }
...@@ -239,11 +234,28 @@ class MSSQLQueryGenerator extends AbstractQueryGenerator { ...@@ -239,11 +234,28 @@ class MSSQLQueryGenerator extends AbstractQueryGenerator {
// FIXME: attributeToSQL SHOULD be using attributes in addColumnQuery // FIXME: attributeToSQL SHOULD be using attributes in addColumnQuery
// but instead we need to pass the key along as the field here // but instead we need to pass the key along as the field here
dataType.field = key; dataType.field = key;
let commentStr = '';
if (dataType.comment && _.isString(dataType.comment)) {
commentStr = this.commentTemplate(dataType.comment, table, key);
// attributeToSQL will try to include `COMMENT 'Comment Text'` when it returns if the comment key
// is present. This is needed for createTable statement where that part is extracted with regex.
// Here we can intercept the object and remove comment property since we have the original object.
delete dataType['comment'];
}
const def = this.attributeToSQL(dataType, { const def = this.attributeToSQL(dataType, {
context: 'addColumn' context: 'addColumn'
}); });
return `ALTER TABLE ${this.quoteTable(table)} ADD ${this.quoteIdentifier(key)} ${def};`; return `ALTER TABLE ${this.quoteTable(table)} ADD ${this.quoteIdentifier(key)} ${def};${commentStr}`;
}
commentTemplate(comment, table, column) {
return ' EXEC sp_addextendedproperty ' +
`@name = N\'MS_Description\', @value = ${this.escape(comment)}, ` +
'@level0type = N\'Schema\', @level0name = \'dbo\', ' +
`@level1type = N\'Table\', @level1name = ${this.quoteIdentifier(table)}, ` +
`@level2type = N\'Column\', @level2name = ${this.quoteIdentifier(column)};`;
} }
removeColumnQuery(tableName, attributeName) { removeColumnQuery(tableName, attributeName) {
......
...@@ -245,7 +245,7 @@ class PostgresQueryGenerator extends AbstractQueryGenerator { ...@@ -245,7 +245,7 @@ class PostgresQueryGenerator extends AbstractQueryGenerator {
addColumnQuery(table, key, dataType) { addColumnQuery(table, key, dataType) {
const dbDataType = this.attributeToSQL(dataType, { context: 'addColumn' }); const dbDataType = this.attributeToSQL(dataType, { context: 'addColumn', table, key });
const definition = this.dataTypeMapping(table, key, dbDataType); const definition = this.dataTypeMapping(table, key, dbDataType);
const quotedKey = this.quoteIdentifier(key); const quotedKey = this.quoteIdentifier(key);
const quotedTable = this.quoteTable(this.extractTableDetails(table)); const quotedTable = this.quoteTable(this.extractTableDetails(table));
...@@ -453,7 +453,7 @@ class PostgresQueryGenerator extends AbstractQueryGenerator { ...@@ -453,7 +453,7 @@ class PostgresQueryGenerator extends AbstractQueryGenerator {
return fragment; return fragment;
} }
attributeToSQL(attribute) { attributeToSQL(attribute, options) {
if (!_.isPlainObject(attribute)) { if (!_.isPlainObject(attribute)) {
attribute = { attribute = {
type: attribute type: attribute
...@@ -536,7 +536,13 @@ class PostgresQueryGenerator extends AbstractQueryGenerator { ...@@ -536,7 +536,13 @@ class PostgresQueryGenerator extends AbstractQueryGenerator {
} }
if (attribute.comment && _.isString(attribute.comment)) { if (attribute.comment && _.isString(attribute.comment)) {
sql += ` COMMENT ${attribute.comment}`; if (options && options.context === 'addColumn') {
const quotedAttr = this.quoteIdentifier(options.key);
const escapedCommentText = this.escape(attribute.comment);
sql += `; COMMENT ON COLUMN ${this.quoteTable(options.table)}.${quotedAttr} IS ${escapedCommentText}`;
} else {
sql += ` COMMENT ${attribute.comment}`;
}
} }
return sql; return sql;
......
...@@ -193,6 +193,22 @@ if (current.dialect.name === 'mssql') { ...@@ -193,6 +193,22 @@ if (current.dialect.name === 'mssql') {
}); });
}); });
it('addColumnQuery', function() {
expectsql(this.queryGenerator.addColumnQuery('myTable', 'myColumn', { type: 'VARCHAR(255)' }), {
mssql: 'ALTER TABLE [myTable] ADD [myColumn] VARCHAR(255) NULL;'
});
});
it('addColumnQuery with comment', function() {
expectsql(this.queryGenerator.addColumnQuery('myTable', 'myColumn', { type: 'VARCHAR(255)', comment: 'This is a comment' }), {
mssql: 'ALTER TABLE [myTable] ADD [myColumn] VARCHAR(255) NULL; EXEC sp_addextendedproperty ' +
'@name = N\'MS_Description\', @value = N\'This is a comment\', ' +
'@level0type = N\'Schema\', @level0name = \'dbo\', ' +
'@level1type = N\'Table\', @level1name = [myTable], ' +
'@level2type = N\'Column\', @level2name = [myColumn];'
});
});
it('removeColumnQuery', function() { it('removeColumnQuery', function() {
expectsql(this.queryGenerator.removeColumnQuery('myTable', 'myColumn'), { expectsql(this.queryGenerator.removeColumnQuery('myTable', 'myColumn'), {
mssql: 'ALTER TABLE [myTable] DROP COLUMN [myColumn];' mssql: 'ALTER TABLE [myTable] DROP COLUMN [myColumn];'
......
...@@ -124,7 +124,10 @@ if (dialect.startsWith('postgres')) { ...@@ -124,7 +124,10 @@ if (dialect.startsWith('postgres')) {
arguments: [{id: {type: 'INTEGER', unique: true, comment: 'This is my comment'}}], arguments: [{id: {type: 'INTEGER', unique: true, comment: 'This is my comment'}}],
expectation: {id: 'INTEGER UNIQUE COMMENT This is my comment'} expectation: {id: 'INTEGER UNIQUE COMMENT This is my comment'}
}, },
{
arguments: [{id: {type: 'INTEGER', unique: true, comment: 'This is my comment'}}, {context: 'addColumn', key: 'column', table: {schema: 'foo', tableName: 'bar'}}],
expectation: {id: 'INTEGER UNIQUE; COMMENT ON COLUMN "foo"."bar"."column" IS \'This is my comment\''}
},
// New references style // New references style
{ {
arguments: [{id: {type: 'INTEGER', references: { model: 'Bar' }}}], arguments: [{id: {type: 'INTEGER', references: { model: 'Bar' }}}],
......
...@@ -50,6 +50,15 @@ if (current.dialect.name === 'mysql') { ...@@ -50,6 +50,15 @@ if (current.dialect.name === 'mysql') {
mysql: 'ALTER TABLE `users` ADD `test_added_col_first` VARCHAR(255) FIRST;' mysql: 'ALTER TABLE `users` ADD `test_added_col_first` VARCHAR(255) FIRST;'
}); });
}); });
it('properly generates alter queries with column level comment', () => {
return expectsql(sql.addColumnQuery(Model.getTableName(), 'column_with_comment', current.normalizeAttribute({
type: DataTypes.STRING,
comment: 'This is a comment'
})), {
mysql: 'ALTER TABLE `users` ADD `column_with_comment` VARCHAR(255) COMMENT \'This is a comment\';'
});
});
}); });
}); });
} }
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!