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

MSSQL - Changed DataTypes.DATE to use DATETIMEOFFSET datatype #7201

Merged
merged 1 commit into from
Feb 7, 2017

Conversation

harshithkashyap
Copy link

@harshithkashyap harshithkashyap commented Feb 5, 2017

Pull Request check-list

  • Does npm run test or npm run test-DIALECT pass with this change (including linting)?
  • Does your issue contain a link to existing issue (Closes #[issue]) or a description of the issue you are solving?
  • Have you added new tests to prevent regressions?
  • Is a documentation update included (if this change modifies existing APIs, or introduces new ones)?
  • Have you added an entry under Future in the changelog?

Description of change

Closes #5403

@harshithkashyap
Copy link
Author

Ping @janmeier @felixfbecker @sushantdhiman.

@sushantdhiman sushantdhiman merged commit 8c2c129 into sequelize:master Feb 7, 2017
@harshithkashyap harshithkashyap deleted the fix-5403 branch February 7, 2017 05:10
@harshithkashyap
Copy link
Author

In case someone is looking to migrate existing DATETIME2 columns to DATETIMEOFFSET through migration.

const listAllDatetime2ColumnsSql = 'SELECT TABLE_NAME AS tableName, COLUMN_NAME AS columnName, DATA_TYPE AS dataType, IS_NULLABLE AS isNullable FROM INFORMATION_SCHEMA.COLUMNS WHERE DATA_TYPE=\'datetime2\';';
const listAllDatetimeOffsetColumnsSql = 'SELECT TABLE_NAME AS tableName, COLUMN_NAME AS columnName, DATA_TYPE AS dataType, IS_NULLABLE AS isNullable FROM INFORMATION_SCHEMA.COLUMNS WHERE DATA_TYPE=\'datetimeoffset\';';

module.exports = {
	up: function (queryInterface, Sequelize) {
		return queryInterface.sequelize.transaction(transaction => {
			return queryInterface
				.sequelize.query(listAllDatetime2ColumnsSql, { transaction })
				.then(result => {
					result = result[0];
					const columns = [];
					for (const row of result) {
						columns.push(queryInterface.changeColumn(row.tableName, row.columnName, {
							type: Sequelize.DATE,
							allowNull: row.isNullable === 'YES' ? true : false
						}, { transaction }));
					}

					return Promise.all(columns);
				});
		});
	},

	down: function (queryInterface, Sequelize) {
		return queryInterface.sequelize.transaction(transaction => {
			return queryInterface
				.sequelize.query(listAllDatetimeOffsetColumnsSql, { transaction })
				.then(result => {
					result = result[0];
					const columns = [];
					for (const row of result) {
						const nullSnippet = row.isNullable === 'YES' ? 'NULL' : 'NOT NULL';
						const attribute = {};
						attribute[row.columnName] = `DATETIME2 ${nullSnippet}`;
						const changeColumnSql = queryInterface.QueryGenerator.changeColumnQuery(row.tableName, attribute);
						columns.push(queryInterface.sequelize.query(changeColumnSql, { transaction }));
					}

					return Promise.all(columns);
				});
		});
	}
};

@charlieargue
Copy link

Hi! When I run this migration, I get an ERROR:

SequelizeDatabaseError: ALTER TABLE ALTER COLUMN createdAt failed because one or more objects access this column.

Apparently, I need to drop constraints (which sequelize auto-generates for my timestamps createdAt and updatedAt) first before this migration works?

Thanks!

...Trying to slog thru the ver 3 -> 4 breaking changes!

@charlieargue
Copy link

For anyone interested, here's a MS SQL Server CURSOR that DROPS those timestamp constraints ... it'll need some slight modification for your needs, I was using two tables called 'po' and 'requisition':

use ***YOUR-DATABASE***
GO

DECLARE constraints_cursor CURSOR FOR
-- #####################################
-- returns name of a column's default value constraint 
SELECT
    default_constraints.name 
FROM 
    sys.all_columns INNER JOIN sys.tables
    ON all_columns.object_id = tables.object_id
        INNER JOIN sys.schemas 
		ON tables.schema_id = schemas.schema_id
			INNER JOIN sys.default_constraints
			ON all_columns.default_object_id = default_constraints.object_id
WHERE 
        schemas.name = 'dbo'
    AND tables.name in ('requisition', 'po') -- CHANGE TO ***YOUR-TABLES***
    AND all_columns.name in ('updatedAt', 'createdAt') -- TIMESTAMP column names
-- #####################################
OPEN constraints_cursor;  
DECLARE @name varchar(500);  
FETCH NEXT FROM constraints_cursor INTO @name;  
WHILE (@@FETCH_STATUS <> -1)  
BEGIN;  
        -- ***I'M SNIFFING OUT WHICH TABLE TO EXEC on BASED ON constraint name STRING SNIPPET***
        -- ***you'll need to change __po and __req ***
	IF CHARINDEX('__po', @name) > 0
	BEGIN
		-- po
               -- change to ***YOUR-TABLE***
	   EXECUTE ('ALTER TABLE [dbo].[po] DROP CONSTRAINT ' + @name);  	
	END; 
	--  VS 
        -- ***I'M SNIFFING OUT WHICH TABLE TO EXEC on BASED ON constraint name STRING SNIPPET***
        -- ***you'll need to change __po and __req ***
	ELSE IF CHARINDEX('__req', @name) > 0
	BEGIN
		-- requisition
               -- change to ***YOUR-TABLE***
	   EXECUTE ('ALTER TABLE [dbo].[requisition] DROP CONSTRAINT ' + @name);  	
	END; 
   FETCH NEXT FROM constraints_cursor INTO @name; 
END;  
PRINT 'All datetime2 constraints have been DROPPED.';  
CLOSE constraints_cursor;  
DEALLOCATE constraints_cursor;  
GO






	-- THEN
 

--ALTER TABLE [dbo].[po] ADD  DEFAULT (N'2017-06-26T20:31:44Z') FOR [createdAt]
--GO
--ALTER TABLE [dbo].[po] ADD  DEFAULT (N'2017-06-26T20:31:44Z') FOR [updatedAt]
--GO
--ALTER TABLE [dbo].[requisition] ADD  DEFAULT (N'2017-06-26T20:31:44Z') FOR [createdAt]
--GO
--ALTER TABLE [dbo].[requisition] ADD  DEFAULT (N'2017-06-26T20:31:44Z') FOR [updatedAt]
--GO






Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants