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

4 participants
@harshithkashyap
Member

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

This comment has been minimized.

Show comment
Hide comment
Member

harshithkashyap commented Feb 5, 2017

@felixfbecker felixfbecker requested a review from sushantdhiman Feb 6, 2017

@sushantdhiman sushantdhiman merged commit 8c2c129 into sequelize:master Feb 7, 2017

4 checks passed

codecov/patch 100% of diff hit (target 94.96%)
Details
codecov/project Absolute coverage decreased by -<.01% but relative coverage increased by +5.03% compared to 729575e
Details
continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details

@harshithkashyap harshithkashyap deleted the harshithkashyap:fix-5403 branch Feb 7, 2017

@harshithkashyap

This comment has been minimized.

Show comment
Hide comment
@harshithkashyap

harshithkashyap Feb 10, 2017

Member

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);
				});
		});
	}
};
Member

harshithkashyap commented Feb 10, 2017

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

This comment has been minimized.

Show comment
Hide comment
@charlieargue

charlieargue Aug 25, 2017

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 commented Aug 25, 2017

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

This comment has been minimized.

Show comment
Hide comment
@charlieargue

charlieargue Aug 25, 2017

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






charlieargue commented Aug 25, 2017

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