diff --git a/Build/LocalBuild.bat b/Build/LocalBuild.bat index 798bb9ac7..8e6bde7ba 100644 --- a/Build/LocalBuild.bat +++ b/Build/LocalBuild.bat @@ -16,12 +16,15 @@ ECHO SQLInstanceName: "%SQLInstanceName%" SET DBName=%~5 ECHO DBName: "%DBName%" SET DBLogin=-E +SET AntTarget=all IF NOT "%~6"=="-v" IF NOT "%~6"=="" SET DBLogin=%~6 IF NOT "%~7"=="-v" IF NOT "%~7"=="" SET SQLPackagePath=%~7 +IF NOT "%~8"=="-v" IF NOT "%~8"=="" SET AntTarget=%~8 SET VerboseOutput=ON -IF NOT "%~6"=="-v" IF NOT "%~7"=="-v" IF NOT "%~8"=="-v" SET VerboseOutput=OFF +IF NOT "%~6"=="-v" IF NOT "%~7"=="-v" IF NOT "%~8"=="-v" IF NOT "%~9"=="-v" SET VerboseOutput=OFF ECHO DBLogin: "%DBLogin%" ECHO SQLPackagePath: "%SQLPackagePath%" +ECHO AntTarget: "%AntTarget%" ECHO VerboseOutput: "%VerboseOutput%" REM CALL "%AntHome%\bin\ant" -buildfile Build\tSQLt.experiments.build.xml -Dmsbuild.path="%NET4Home%" -verbose || goto :error @@ -75,7 +78,7 @@ ECHO LogTableName: %LogTableName% IF "%VerboseOutput%"=="ON" @ECHO ON @REM -----------------------------------------------------------------------------This space character is utterly important! ----v -CALL "%AntHome%\bin\ant" -buildfile Build\tSQLt.validatebuild.xml -Ddb.server="%SQLInstanceName%" -Ddb.name=%DBName% -Ddb.login=" %DBLogin%" -Dsqlcmd.path="%SQLCMDPath%" -Dsqlpackage.path="%SQLPackagePath%" -Dlogtable.name="%LogTableName%" || goto :error +CALL "%AntHome%\bin\ant" "%AntTarget%" -buildfile Build\tSQLt.validatebuild.xml -Ddb.server="%SQLInstanceName%" -Ddb.name=%DBName% -Ddb.login=" %DBLogin%" -Dsqlcmd.path="%SQLCMDPath%" -Dsqlpackage.path="%SQLPackagePath%" -Dlogtable.name="%LogTableName%" || goto :error @ECHO OFF ECHO +-------------------------+ diff --git a/Experiments/NameResolutionResearch.sql b/Experiments/NameResolutionResearch.sql index 97f1b92ff..4cbf14805 100644 --- a/Experiments/NameResolutionResearch.sql +++ b/Experiments/NameResolutionResearch.sql @@ -180,7 +180,7 @@ tSQLt.FakeTable EXEC (@cmd); EXEC sys.sp_addextendedproperty - @name = N'tSQLt.FakeTable_OrgTableName', + @name = N'tSQLt.Private_TestDouble_OrgObjectName', @value = @newName, @level0type = N'SCHEMA', @level0name = @schemaName, -- @level1type = N'TABLE', @level1name = @tableName; -- @@ -210,7 +210,7 @@ tSQLt.ApplyConstraint WHERE class_desc = 'OBJECT_OR_COLUMN' AND major_id = OBJECT_ID(@schemaName + '.' + @tableName) -- AND minor_id = 0 - AND name = 'tSQLt.FakeTable_OrgTableName'; + AND name = 'tSQLt.Private_TestDouble_OrgObjectName'; SELECT @cmd = 'CONSTRAINT ' + name + ' CHECK' + definition FROM sys.check_constraints diff --git a/Source/ApplyConstraint_Methods.sql b/Source/ApplyConstraint_Methods.sql index c406deb5f..180cfc875 100644 --- a/Source/ApplyConstraint_Methods.sql +++ b/Source/ApplyConstraint_Methods.sql @@ -23,7 +23,7 @@ RETURN ON newtbl.object_id = p.major_id AND p.minor_id = 0 AND p.class_desc = 'OBJECT_OR_COLUMN' - AND p.name = 'tSQLt.FakeTable_OrgTableName' + AND p.name = 'tSQLt.Private_TestDouble_OrgObjectName' ON OBJECT_NAME(constraints.parent_object_id) = CAST(p.value AS NVARCHAR(4000)) AND constraints.schema_id = newtbl.schema_id AND constraints.object_id = @ConstraintObjectId; @@ -70,6 +70,8 @@ CREATE PROCEDURE tSQLt.Private_ApplyCheckConstraint AS BEGIN DECLARE @Cmd NVARCHAR(MAX); + DECLARE @NewNameOfOriginalConstraint NVARCHAR(MAX); + DECLARE @QuotedFullConstraintName NVARCHAR(MAX); SELECT @Cmd = 'CONSTRAINT ' + QUOTENAME(name) + ' CHECK' + definition FROM sys.check_constraints WHERE object_id = @ConstraintObjectId; @@ -78,13 +80,16 @@ BEGIN SELECT @QuotedTableName = QuotedTableName FROM tSQLt.Private_GetQuotedTableNameForConstraint(@ConstraintObjectId); - EXEC tSQLt.Private_RenameObjectToUniqueNameUsingObjectId @ConstraintObjectId; - SELECT @Cmd = 'ALTER TABLE ' + @QuotedTableName + ' ADD ' + @Cmd + SELECT @Cmd = 'ALTER TABLE ' + @QuotedTableName + ' ADD ' + @Cmd, + @QuotedFullConstraintName = QUOTENAME(SCHEMA_NAME(schema_id))+'.'+QUOTENAME(name) FROM sys.objects WHERE object_id = @ConstraintObjectId; + EXEC tSQLt.Private_RenameObjectToUniqueNameUsingObjectId @ConstraintObjectId, @NewName = @NewNameOfOriginalConstraint OUT; + EXEC (@Cmd); + EXEC tSQLt.Private_MarktSQLtTempObject @ObjectName = @QuotedFullConstraintName, @ObjectType = 'CONSTRAINT', @NewNameOfOriginalObject = @NewNameOfOriginalConstraint; END; GO @@ -101,11 +106,15 @@ BEGIN DECLARE @AlterTableCmd NVARCHAR(MAX); DECLARE @CreateIndexCmd NVARCHAR(MAX); DECLARE @FinalCmd NVARCHAR(MAX); + DECLARE @NewNameOfOriginalConstraint NVARCHAR(MAX); + DECLARE @QuotedFullConstraintName NVARCHAR(MAX); + SELECT @SchemaName = SchemaName, @OrgTableName = OrgTableName, @TableName = TableName, - @ConstraintName = OBJECT_NAME(@ConstraintObjectId) + @ConstraintName = OBJECT_NAME(@ConstraintObjectId), + @QuotedFullConstraintName = QUOTENAME(SchemaName)+'.'+QUOTENAME(OBJECT_NAME(@ConstraintObjectId)) FROM tSQLt.Private_GetQuotedTableNameForConstraint(@ConstraintObjectId); SELECT @CreateFkCmd = cmd, @CreateIndexCmd = CreIdxCmd @@ -114,8 +123,11 @@ BEGIN ' ADD ' + @CreateFkCmd; SELECT @FinalCmd = @CreateIndexCmd + @AlterTableCmd; - EXEC tSQLt.Private_RenameObjectToUniqueName @SchemaName, @ConstraintName; + EXEC tSQLt.Private_RenameObjectToUniqueName @SchemaName, @ConstraintName, @NewName = @NewNameOfOriginalConstraint OUTPUT; EXEC (@FinalCmd); + + EXEC tSQLt.Private_MarktSQLtTempObject @ObjectName = @QuotedFullConstraintName, @ObjectType = 'CONSTRAINT', @NewNameOfOriginalObject = @NewNameOfOriginalConstraint; + END; GO @@ -124,25 +136,28 @@ CREATE PROCEDURE tSQLt.Private_ApplyUniqueConstraint AS BEGIN DECLARE @SchemaName NVARCHAR(MAX); - DECLARE @OrgTableName NVARCHAR(MAX); DECLARE @TableName NVARCHAR(MAX); DECLARE @ConstraintName NVARCHAR(MAX); DECLARE @CreateConstraintCmd NVARCHAR(MAX); DECLARE @AlterColumnsCmd NVARCHAR(MAX); + DECLARE @NewNameOfOriginalConstraint NVARCHAR(MAX); + DECLARE @QuotedFullConstraintName NVARCHAR(MAX); SELECT @SchemaName = SchemaName, - @OrgTableName = OrgTableName, @TableName = TableName, - @ConstraintName = OBJECT_NAME(@ConstraintObjectId) + @ConstraintName = OBJECT_NAME(@ConstraintObjectId), + @QuotedFullConstraintName = QUOTENAME(SchemaName)+'.'+QUOTENAME(OBJECT_NAME(@ConstraintObjectId)) FROM tSQLt.Private_GetQuotedTableNameForConstraint(@ConstraintObjectId); SELECT @AlterColumnsCmd = NotNullColumnCmd, @CreateConstraintCmd = CreateConstraintCmd FROM tSQLt.Private_GetUniqueConstraintDefinition(@ConstraintObjectId, QUOTENAME(@SchemaName) + '.' + QUOTENAME(@TableName)); - EXEC tSQLt.Private_RenameObjectToUniqueName @SchemaName, @ConstraintName; + EXEC tSQLt.Private_RenameObjectToUniqueName @SchemaName, @ConstraintName, @NewName = @NewNameOfOriginalConstraint OUTPUT; EXEC (@AlterColumnsCmd); EXEC (@CreateConstraintCmd); + + EXEC tSQLt.Private_MarktSQLtTempObject @ObjectName = @QuotedFullConstraintName, @ObjectType = 'CONSTRAINT', @NewNameOfOriginalObject = @NewNameOfOriginalConstraint; END; GO diff --git a/Source/BuildOrder.txt b/Source/BuildOrder.txt index a30da0d31..e70ba5f24 100644 --- a/Source/BuildOrder.txt +++ b/Source/BuildOrder.txt @@ -68,7 +68,7 @@ tSQLt.Private_GetDefaultConstraintDefinition.sfn.sql tSQLt.Private_GetUniqueConstraintDefinition.sfn.sql tSQLt.Private_CreateFakeTableStatement.sfn.sql tSQLt.Private_CreateFakeOfTable.ssp.sql -tSQLt.Private_MarkFakeTable.ssp.sql +tSQLt.Private_MarktSQLtTempObject.ssp.sql tSQLt.FakeTable.ssp.sql tSQLt.Private_GenerateCreateProcedureSpyStatement.ssp.sql tSQLt.Private_CreateProcedureSpy.ssp.sql diff --git a/Source/Source.ssmssqlproj b/Source/Source.ssmssqlproj index 01fff8716..9bf6e3537 100644 --- a/Source/Source.ssmssqlproj +++ b/Source/Source.ssmssqlproj @@ -2,7 +2,6 @@ - @@ -390,11 +389,11 @@ tSQLt.Private_ListTestAnnotations.sfn.sql - + - tSQLt.Private_MarkFakeTable.ssp.sql + tSQLt.Private_MarktSQLtTempObject.ssp.sql diff --git a/Source/tSQLt.ApplyTrigger.ssp.sql b/Source/tSQLt.ApplyTrigger.ssp.sql index 1de2ed121..b5ded0b04 100644 --- a/Source/tSQLt.ApplyTrigger.ssp.sql +++ b/Source/tSQLt.ApplyTrigger.ssp.sql @@ -7,6 +7,8 @@ CREATE PROCEDURE tSQLt.ApplyTrigger AS BEGIN DECLARE @OrgTableObjectId INT; + DECLARE @NewNameOfOriginalTrigger NVARCHAR(MAX); + SELECT @OrgTableObjectId = OrgTableObjectId FROM tSQLt.Private_GetOriginalTableInfo(OBJECT_ID(@TableName)) orgTbl IF(@OrgTableObjectId IS NULL) BEGIN @@ -28,9 +30,11 @@ BEGIN RAISERROR('%s is not a trigger on %s', 16, 10, @TriggerName, @TableName); END; - EXEC tSQLt.RemoveObject @FullTriggerName; + EXEC tSQLt.RemoveObject @ObjectName = @FullTriggerName, @NewName = @NewNameOfOriginalTrigger OUTPUT; EXEC(@TriggerCode); + + EXEC tSQLt.Private_MarktSQLtTempObject @ObjectName = @FullTriggerName, @ObjectType = N'TRIGGER', @NewNameOfOriginalObject = @NewNameOfOriginalTrigger; END; ---Build- GO diff --git a/Source/tSQLt.FakeFunction.ssp.sql b/Source/tSQLt.FakeFunction.ssp.sql index e93d00a94..09b25b5cd 100644 --- a/Source/tSQLt.FakeFunction.ssp.sql +++ b/Source/tSQLt.FakeFunction.ssp.sql @@ -12,6 +12,7 @@ BEGIN DECLARE @FunctionObjectId INT; DECLARE @FakeFunctionObjectId INT; DECLARE @IsScalarFunction BIT; + DECLARE @NewNameOfOriginalFunction NVARCHAR(MAX); EXEC tSQLt.Private_ValidateObjectsCompatibleWithFakeFunction @FunctionName = @FunctionName, @@ -21,7 +22,9 @@ BEGIN @FakeFunctionObjectId = @FakeFunctionObjectId OUT, @IsScalarFunction = @IsScalarFunction OUT; - EXEC tSQLt.RemoveObject @ObjectName = @FunctionName; + EXEC tSQLt.RemoveObject + @ObjectName = @FunctionName, + @NewName = @NewNameOfOriginalFunction OUTPUT; EXEC tSQLt.Private_CreateFakeFunction @FunctionName = @FunctionName, @@ -31,5 +34,10 @@ BEGIN @FakeFunctionObjectId = @FakeFunctionObjectId, @IsScalarFunction = @IsScalarFunction; + EXEC tSQLt.Private_MarktSQLtTempObject + @ObjectName = @FunctionName, + @ObjectType = N'FUNCTION', + @NewNameOfOriginalObject = @NewNameOfOriginalFunction; + END; GO diff --git a/Source/tSQLt.FakeTable.ssp.sql b/Source/tSQLt.FakeTable.ssp.sql index a2635edba..9f7e3469b 100644 --- a/Source/tSQLt.FakeTable.ssp.sql +++ b/Source/tSQLt.FakeTable.ssp.sql @@ -9,47 +9,47 @@ CREATE PROCEDURE tSQLt.FakeTable @Defaults BIT = NULL AS BEGIN - DECLARE @OrigSchemaName NVARCHAR(MAX); - DECLARE @OrigTableName NVARCHAR(MAX); - DECLARE @NewNameOfOriginalTable NVARCHAR(4000); - DECLARE @OrigTableFullName NVARCHAR(MAX); SET @OrigTableFullName = NULL; - - SELECT @OrigSchemaName = @SchemaName, - @OrigTableName = @TableName - - IF(@OrigTableName NOT IN (PARSENAME(@OrigTableName,1),QUOTENAME(PARSENAME(@OrigTableName,1))) - AND @OrigSchemaName IS NOT NULL) + DECLARE @OrigObjectCleanQuotedSchemaName NVARCHAR(MAX); + DECLARE @OrigObjectCleanQuotedName NVARCHAR(MAX); + DECLARE @OrigObjectNewName NVARCHAR(4000); + DECLARE @OrigObjectFullName NVARCHAR(MAX) = NULL; + DECLARE @TargetObjectFullName NVARCHAR(MAX) = NULL; + + IF(@TableName NOT IN (PARSENAME(@TableName,1),QUOTENAME(PARSENAME(@TableName,1))) + AND @SchemaName IS NOT NULL) BEGIN RAISERROR('When @TableName is a multi-part identifier, @SchemaName must be NULL!',16,10); END - SELECT @SchemaName = CleanSchemaName, - @TableName = CleanTableName + SELECT @OrigObjectCleanQuotedSchemaName = CleanSchemaName, + @OrigObjectCleanQuotedName = CleanTableName FROM tSQLt.Private_ResolveFakeTableNamesForBackwardCompatibility(@TableName, @SchemaName); - EXEC tSQLt.Private_ValidateFakeTableParameters @SchemaName,@OrigTableName,@OrigSchemaName; + EXEC tSQLt.Private_ValidateFakeTableParameters @OrigObjectCleanQuotedSchemaName,@TableName,@SchemaName; + + SET @OrigObjectFullName = @OrigObjectCleanQuotedSchemaName + '.' + @OrigObjectCleanQuotedName; - EXEC tSQLt.Private_RenameObjectToUniqueName @SchemaName, @TableName, @NewNameOfOriginalTable OUTPUT; + EXEC tSQLt.Private_RenameObjectToUniqueName @OrigObjectCleanQuotedSchemaName, @OrigObjectCleanQuotedName, @OrigObjectNewName OUTPUT; - SELECT @OrigTableFullName = S.base_object_name + SELECT @TargetObjectFullName = S.base_object_name FROM sys.synonyms AS S - WHERE S.object_id = OBJECT_ID(@SchemaName + '.' + @NewNameOfOriginalTable); + WHERE S.object_id = OBJECT_ID(@OrigObjectCleanQuotedSchemaName + '.' + @OrigObjectNewName); - IF(@OrigTableFullName IS NOT NULL) + IF(@TargetObjectFullName IS NOT NULL) BEGIN - IF(COALESCE(OBJECT_ID(@OrigTableFullName,'U'),OBJECT_ID(@OrigTableFullName,'V')) IS NULL) + IF(COALESCE(OBJECT_ID(@TargetObjectFullName,'U'),OBJECT_ID(@TargetObjectFullName,'V')) IS NULL) BEGIN - RAISERROR('Cannot fake synonym %s.%s as it is pointing to %s, which is not a table or view!',16,10,@SchemaName,@TableName,@OrigTableFullName); + RAISERROR('Cannot fake synonym %s as it is pointing to %s, which is not a table or view!',16,10,@OrigObjectFullName,@TargetObjectFullName); END; END; ELSE BEGIN - SET @OrigTableFullName = @SchemaName + '.' + @NewNameOfOriginalTable; + SET @TargetObjectFullName = @OrigObjectCleanQuotedSchemaName + '.' + QUOTENAME(@OrigObjectNewName); --TODO:Test for QUOTENAME END; - EXEC tSQLt.Private_CreateFakeOfTable @SchemaName, @TableName, @OrigTableFullName, @Identity, @ComputedColumns, @Defaults; + EXEC tSQLt.Private_CreateFakeOfTable @OrigObjectCleanQuotedSchemaName, @OrigObjectCleanQuotedName, @TargetObjectFullName, @Identity, @ComputedColumns, @Defaults; - EXEC tSQLt.Private_MarkFakeTable @SchemaName, @TableName, @NewNameOfOriginalTable; + EXEC tSQLt.Private_MarktSQLtTempObject @OrigObjectFullName, N'TABLE', @OrigObjectNewName; END ---Build- GO diff --git a/Source/tSQLt.Private_GetForeignKeyDefinition.sfn.sql b/Source/tSQLt.Private_GetForeignKeyDefinition.sfn.sql index a801c465d..925bf6fae 100644 --- a/Source/tSQLt.Private_GetForeignKeyDefinition.sfn.sql +++ b/Source/tSQLt.Private_GetForeignKeyDefinition.sfn.sql @@ -79,7 +79,7 @@ RETURN SELECT 'CONSTRAINT ' + name + ' FOREIGN KEY (' + CROSS APPLY tSQLt.Private_GetForeignKeyParColumns(k.object_id) AS parCol CROSS APPLY tSQLt.Private_GetForeignKeyRefColumns(k.object_id) AS refCol LEFT JOIN sys.extended_properties e - ON e.name = 'tSQLt.FakeTable_OrgTableName' + ON e.name = 'tSQLt.Private_TestDouble_OrgObjectName' AND e.value = OBJECT_NAME(k.referenced_object_id) JOIN sys.tables refTab ON COALESCE(e.major_id,k.referenced_object_id) = refTab.object_id diff --git a/Source/tSQLt.Private_MarkFakeTable.ssp.sql b/Source/tSQLt.Private_MarkFakeTable.ssp.sql deleted file mode 100644 index df07eefb4..000000000 --- a/Source/tSQLt.Private_MarkFakeTable.ssp.sql +++ /dev/null @@ -1,20 +0,0 @@ -IF OBJECT_ID('tSQLt.Private_MarkFakeTable') IS NOT NULL DROP PROCEDURE tSQLt.Private_MarkFakeTable; -GO ----Build+ -CREATE PROCEDURE tSQLt.Private_MarkFakeTable - @SchemaName NVARCHAR(MAX), - @TableName NVARCHAR(MAX), - @NewNameOfOriginalTable NVARCHAR(4000) -AS -BEGIN - DECLARE @UnquotedSchemaName NVARCHAR(MAX);SET @UnquotedSchemaName = OBJECT_SCHEMA_NAME(OBJECT_ID(@SchemaName+'.'+@TableName)); - DECLARE @UnquotedTableName NVARCHAR(MAX);SET @UnquotedTableName = OBJECT_NAME(OBJECT_ID(@SchemaName+'.'+@TableName)); - - EXEC sys.sp_addextendedproperty - @name = N'tSQLt.FakeTable_OrgTableName', - @value = @NewNameOfOriginalTable, - @level0type = N'SCHEMA', @level0name = @UnquotedSchemaName, - @level1type = N'TABLE', @level1name = @UnquotedTableName; -END; ----Build- -GO \ No newline at end of file diff --git a/Source/tSQLt.Private_MarktSQLtTempObject.ssp.sql b/Source/tSQLt.Private_MarktSQLtTempObject.ssp.sql new file mode 100644 index 000000000..f05a2af81 --- /dev/null +++ b/Source/tSQLt.Private_MarktSQLtTempObject.ssp.sql @@ -0,0 +1,53 @@ +IF OBJECT_ID('tSQLt.Private_MarktSQLtTempObject') IS NOT NULL DROP PROCEDURE tSQLt.Private_MarktSQLtTempObject; +GO +---Build+ +CREATE PROCEDURE tSQLt.Private_MarktSQLtTempObject + @ObjectName NVARCHAR(MAX), + @ObjectType NVARCHAR(MAX), + @NewNameOfOriginalObject NVARCHAR(4000) +AS +BEGIN + DECLARE @UnquotedSchemaName NVARCHAR(MAX); + DECLARE @UnquotedObjectName NVARCHAR(MAX); + DECLARE @UnquotedParentName NVARCHAR(MAX); + DECLARE @TempObjectFlagOn BIT = 1; + SELECT + @UnquotedSchemaName = SCHEMA_NAME(O.schema_id), + @UnquotedObjectName = O.name, + @UnquotedParentName = OBJECT_NAME(O.parent_object_id) + FROM sys.objects O + WHERE O.object_id = OBJECT_ID(@ObjectName); + + IF(@UnquotedParentName IS NULL) + BEGIN + EXEC sys.sp_addextendedproperty + @name = N'tSQLt.IsTempObject', + @value = @TempObjectFlagOn, + @level0type = N'SCHEMA', @level0name = @UnquotedSchemaName, + @level1type = @ObjectType, @level1name = @UnquotedObjectName; + + EXEC sys.sp_addextendedproperty + @name = N'tSQLt.Private_TestDouble_OrgObjectName', + @value = @NewNameOfOriginalObject, + @level0type = N'SCHEMA', @level0name = @UnquotedSchemaName, + @level1type = @ObjectType, @level1name = @UnquotedObjectName; + END; + ELSE + BEGIN + EXEC sys.sp_addextendedproperty + @name = N'tSQLt.IsTempObject', + @value = @TempObjectFlagOn, + @level0type = N'SCHEMA', @level0name = @UnquotedSchemaName, + @level1type = N'TABLE', @level1name = @UnquotedParentName, + @level2type = @ObjectType, @level2name = @UnquotedObjectName; + + EXEC sys.sp_addextendedproperty + @name = N'tSQLt.Private_TestDouble_OrgObjectName', + @value = @NewNameOfOriginalObject, + @level0type = N'SCHEMA', @level0name = @UnquotedSchemaName, + @level1type = N'TABLE', @level1name = @UnquotedParentName, + @level2type = @ObjectType, @level2name = @UnquotedObjectName; + END; +END; +---Build- +GO \ No newline at end of file diff --git a/Source/tSQLt.SpyProcedure.ssp.sql b/Source/tSQLt.SpyProcedure.ssp.sql index dbf3cc6a1..4740b47f9 100644 --- a/Source/tSQLt.SpyProcedure.ssp.sql +++ b/Source/tSQLt.SpyProcedure.ssp.sql @@ -25,13 +25,16 @@ BEGIN @CreateProcedureStatement = @CreateProcedureStatement OUT, @CreateLogTableStatement = @CreateLogTableStatement OUT; + DECLARE @NewNameOfOriginalObject NVARCHAR(MAX); - EXEC tSQLt.Private_RenameObjectToUniqueNameUsingObjectId @ProcedureObjectId; + EXEC tSQLt.Private_RenameObjectToUniqueNameUsingObjectId @ProcedureObjectId, @NewName = @NewNameOfOriginalObject OUTPUT; EXEC(@CreateLogTableStatement); EXEC(@CreateProcedureStatement); + EXEC tSQLt.Private_MarktSQLtTempObject @ProcedureName, N'PROCEDURE', @NewNameOfOriginalObject; + RETURN 0; END; ---Build- diff --git a/Source/tSQLt.UndoTestDoubles.ssp.sql b/Source/tSQLt.UndoTestDoubles.ssp.sql index 81693da15..050e7c84e 100644 --- a/Source/tSQLt.UndoTestDoubles.ssp.sql +++ b/Source/tSQLt.UndoTestDoubles.ssp.sql @@ -3,12 +3,50 @@ GO ---Build+ GO CREATE PROCEDURE tSQLt.UndoTestDoubles + @Force BIT = 0 AS BEGIN DECLARE @cmd NVARCHAR(MAX); + IF (@Force = 1) + BEGIN + SET @cmd = 'EXEC tSQLt.Private_Print @Message = ''WARNING: @Force has been set to 1. Dropping the following objects that are not marked as temporary. (%s)'';'; + END; + ELSE + BEGIN + SET @cmd = 'RAISERROR(''Cannot drop these objects as they are not marked as temporary. Use @Force = 1 to override. (%s)'',16,10)'; + END; + + SELECT @cmd = REPLACE(@cmd,'%s',Collisions.List) + FROM + ( + SELECT + STUFF ( + ( + SELECT + ', ' + QUOTENAME(OBJECT_SCHEMA_NAME(TestDouble.object_id))+'.'+QUOTENAME(TestDouble.name) + FROM tSQLt.Private_RenamedObjectLog AS ROL + JOIN sys.objects AS TestDouble + ON TestDouble.object_id = OBJECT_ID(QUOTENAME(OBJECT_SCHEMA_NAME(ROL.ObjectId))+'.'+QUOTENAME(PARSENAME(ROL.OriginalName,1))) + LEFT JOIN sys.extended_properties AS EP + ON EP.class_desc = 'OBJECT_OR_COLUMN' + AND EP.major_id = TestDouble.object_id + AND EP.name = 'tSQLt.IsTempObject' + AND EP.value = 1 + WHERE EP.value IS NULL + ORDER BY 1 + FOR XML PATH (''), TYPE + ).value('.','NVARCHAR(MAX)'), + 1,2,'') + ) Collisions(List) + EXEC(@cmd); + SELECT TOP(0)A.* INTO #RenamedObjects FROM tSQLt.Private_RenamedObjectLog A RIGHT JOIN tSQLt.Private_RenamedObjectLog X ON 1=0; + + + + BEGIN TRAN; DELETE FROM tSQLt.Private_RenamedObjectLog OUTPUT Deleted.* INTO #RenamedObjects; WITH LL AS @@ -37,15 +75,24 @@ BEGIN LL.SchemaName, LL.CurrentName, LL.OriginalName, - FakeO.type ObjectType + FakeO.type ObjectType, + CASE WHEN EP.value IS NOT NULL THEN 1 ELSE 0 END IsTempObject FROM LL LEFT JOIN sys.objects FakeO ON FakeO.object_id = OBJECT_ID(QUOTENAME(LL.SchemaName)+'.'+QUOTENAME(LL.OriginalName)) + LEFT JOIN sys.extended_properties AS EP + ON EP.class_desc = 'OBJECT_OR_COLUMN' + AND EP.major_id = FakeO.object_id + AND EP.name = 'tSQLt.IsTempObject' + AND EP.value = 1 ) SELECT @cmd = ( SELECT - ISNULL(CASE WHEN L.ParentId IS NULL THEN DC.cmd+';' END,'')+ + ISNULL(CASE + WHEN L.ParentId IS NULL THEN DC.cmd+';' + ELSE NULL + END,'')+ 'EXEC tSQLt.Private_RenameObject '''+L.SchemaName+''','''+L.CurrentName+''','''+L.OriginalName+''';' FROM L CROSS APPLY tSQLt.Private_GetDropItemCmd(QUOTENAME(L.SchemaName)+'.'+QUOTENAME(L.OriginalName),L.ObjectType) DC @@ -53,8 +100,31 @@ BEGIN FOR XML PATH(''),TYPE ).value('.','NVARCHAR(MAX)') EXEC(@cmd); + + WITH L AS + ( + SELECT + TempO.Name, + SCHEMA_NAME(TempO.schema_id) SchemaName, + TempO.type ObjectType + FROM sys.objects TempO + JOIN sys.extended_properties AS EP + ON EP.class_desc = 'OBJECT_OR_COLUMN' + AND EP.major_id = TempO.object_id + AND EP.name = 'tSQLt.IsTempObject' + AND EP.value = 1 + ) + SELECT @cmd = + ( + SELECT + DC.cmd+';' + FROM L + CROSS APPLY tSQLt.Private_GetDropItemCmd(QUOTENAME(L.SchemaName)+'.'+QUOTENAME(L.Name),L.ObjectType) DC + FOR XML PATH(''),TYPE + ).value('.','NVARCHAR(MAX)') + EXEC(@cmd); + COMMIT; END; GO - diff --git a/Source/tSQLt.class.sql b/Source/tSQLt.class.sql index c4a26d0ca..3e6b92874 100644 --- a/Source/tSQLt.class.sql +++ b/Source/tSQLt.class.sql @@ -266,7 +266,7 @@ BEGIN WHERE class_desc = 'OBJECT_OR_COLUMN' AND major_id = OBJECT_ID(@SchemaName + '.' + @TableName) AND minor_id = 0 - AND name = 'tSQLt.FakeTable_OrgTableName'); + AND name = 'tSQLt.Private_TestDouble_OrgObjectName'); END; GO @@ -279,7 +279,7 @@ AS WHERE class_desc = 'OBJECT_OR_COLUMN' AND major_id = @TableObjectId AND minor_id = 0 - AND name = 'tSQLt.FakeTable_OrgTableName'; + AND name = 'tSQLt.Private_TestDouble_OrgObjectName'; GO diff --git a/Source/testoutput.sql b/Source/testoutput.sql index 915072773..925003c82 100644 --- a/Source/testoutput.sql +++ b/Source/testoutput.sql @@ -95,7 +95,7 @@ RETURN SELECT 'CONSTRAINT ' + name + ' FOREIGN KEY (' + ON refCol.object_id = c.referenced_object_id AND refCol.column_id = c.referenced_column_id LEFT JOIN sys.extended_properties e - ON e.name = 'tSQLt.FakeTable_OrgTableName' + ON e.name = 'tSQLt.Private_TestDouble_OrgObjectName' AND e.value = OBJECT_NAME(c.referenced_object_id) JOIN sys.tables refTab ON COALESCE(e.major_id,refCol.object_id) = refTab.object_id diff --git a/Tests/ApplyConstraintTests.class.sql b/Tests/ApplyConstraintTests.class.sql index e4e541383..bf96d1c45 100644 --- a/Tests/ApplyConstraintTests.class.sql +++ b/Tests/ApplyConstraintTests.class.sql @@ -1050,4 +1050,103 @@ BEGIN END; GO +CREATE PROC ApplyConstraintTests.[test ApplyConstraint calls tSQLt.Private_MarktSQLtTempObject on new check constraints] +AS +BEGIN + CREATE TABLE ApplyConstraintTests.aSimpleTable ( Id INT CONSTRAINT aSimpleTableConstraint CHECK(Id > 0)); + DECLARE @OriginalObjectId INT = OBJECT_ID('ApplyConstraintTests.aSimpleTableConstraint'); + + EXEC tSQLt.FakeTable @TableName = 'ApplyConstraintTests.aSimpleTable'; + + EXEC tSQLt.SpyProcedure @ProcedureName = 'tSQLt.Private_MarktSQLtTempObject'; + TRUNCATE TABLE tSQLt.Private_MarktSQLtTempObject_SpyProcedureLog;--Quirkiness of testing the framework that you use to run the test + + EXEC tSQLt.ApplyConstraint @TableName = 'ApplyConstraintTests.aSimpleTable', @ConstraintName = 'aSimpleTableConstraint'; + + SELECT ObjectName, ObjectType, NewNameOfOriginalObject + INTO #Actual + FROM tSQLt.Private_MarktSQLtTempObject_SpyProcedureLog; + + SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; + INSERT INTO #Expected + VALUES('[ApplyConstraintTests].[aSimpleTableConstraint]', N'CONSTRAINT', OBJECT_NAME(@OriginalObjectId)); + + EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; + +END; +GO +CREATE PROC ApplyConstraintTests.[test ApplyConstraint calls tSQLt.Private_MarktSQLtTempObject on new primary key] +AS +BEGIN + CREATE TABLE ApplyConstraintTests.aSimpleTable ( Id INT CONSTRAINT aSimpleTableConstraint PRIMARY KEY ); + DECLARE @OriginalObjectId INT = OBJECT_ID('ApplyConstraintTests.aSimpleTableConstraint'); + + EXEC tSQLt.FakeTable @TableName = 'ApplyConstraintTests.aSimpleTable'; + + EXEC tSQLt.SpyProcedure @ProcedureName = 'tSQLt.Private_MarktSQLtTempObject'; + TRUNCATE TABLE tSQLt.Private_MarktSQLtTempObject_SpyProcedureLog;--Quirkiness of testing the framework that you use to run the test + + EXEC tSQLt.ApplyConstraint @TableName = 'ApplyConstraintTests.aSimpleTable', @ConstraintName = 'aSimpleTableConstraint'; + SELECT ObjectName, ObjectType, NewNameOfOriginalObject + INTO #Actual + FROM tSQLt.Private_MarktSQLtTempObject_SpyProcedureLog; + + SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; + INSERT INTO #Expected + VALUES('[ApplyConstraintTests].[aSimpleTableConstraint]', N'CONSTRAINT', OBJECT_NAME(@OriginalObjectId)); + + EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; + +END; +GO +CREATE PROC ApplyConstraintTests.[test ApplyConstraint calls tSQLt.Private_MarktSQLtTempObject on new unique key] +AS +BEGIN + CREATE TABLE ApplyConstraintTests.aSimpleTable ( Id INT CONSTRAINT aSimpleTableConstraint UNIQUE ); + DECLARE @OriginalObjectId INT = OBJECT_ID('ApplyConstraintTests.aSimpleTableConstraint'); + + EXEC tSQLt.FakeTable @TableName = 'ApplyConstraintTests.aSimpleTable'; + + EXEC tSQLt.SpyProcedure @ProcedureName = 'tSQLt.Private_MarktSQLtTempObject'; + TRUNCATE TABLE tSQLt.Private_MarktSQLtTempObject_SpyProcedureLog;--Quirkiness of testing the framework that you use to run the test + + EXEC tSQLt.ApplyConstraint @TableName = 'ApplyConstraintTests.aSimpleTable', @ConstraintName = 'aSimpleTableConstraint'; + + SELECT ObjectName, ObjectType, NewNameOfOriginalObject + INTO #Actual + FROM tSQLt.Private_MarktSQLtTempObject_SpyProcedureLog; + + SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; + INSERT INTO #Expected + VALUES('[ApplyConstraintTests].[aSimpleTableConstraint]', N'CONSTRAINT', OBJECT_NAME(@OriginalObjectId)); + + EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; + +END; +GO +CREATE PROC ApplyConstraintTests.[test ApplyConstraint calls tSQLt.Private_MarktSQLtTempObject on new foreign key] +AS +BEGIN + CREATE TABLE ApplyConstraintTests.aForeignTable ( Id INT PRIMARY KEY ); + CREATE TABLE ApplyConstraintTests.aSimpleTable ( Id INT, fId INT CONSTRAINT aSimpleTableConstraint FOREIGN KEY REFERENCES ApplyConstraintTests.aForeignTable (Id) ); + DECLARE @OriginalObjectId INT = OBJECT_ID('ApplyConstraintTests.aSimpleTableConstraint'); + + EXEC tSQLt.FakeTable @TableName = 'ApplyConstraintTests.aSimpleTable'; + + EXEC tSQLt.SpyProcedure @ProcedureName = 'tSQLt.Private_MarktSQLtTempObject'; + TRUNCATE TABLE tSQLt.Private_MarktSQLtTempObject_SpyProcedureLog;--Quirkiness of testing the framework that you use to run the test + + EXEC tSQLt.ApplyConstraint @TableName = 'ApplyConstraintTests.aSimpleTable', @ConstraintName = 'aSimpleTableConstraint'; + + SELECT ObjectName, ObjectType, NewNameOfOriginalObject + INTO #Actual + FROM tSQLt.Private_MarktSQLtTempObject_SpyProcedureLog; + + SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; + INSERT INTO #Expected + VALUES('[ApplyConstraintTests].[aSimpleTableConstraint]', N'CONSTRAINT', OBJECT_NAME(@OriginalObjectId)); + + EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; +END; +GO diff --git a/Tests/ApplyTriggerTests.class.sql b/Tests/ApplyTriggerTests.class.sql index 26fadad3b..933309560 100644 --- a/Tests/ApplyTriggerTests.class.sql +++ b/Tests/ApplyTriggerTests.class.sql @@ -120,3 +120,29 @@ BEGIN END; GO +CREATE PROC ApplyTriggerTests.[test ApplyTrigger calls tSQLt.Private_MarktSQLtTempObject on new check constraints] +AS +BEGIN + CREATE TABLE ApplyTriggerTests.aSimpleTable ( Id INT); + EXEC('CREATE TRIGGER ApplyTriggerTests.aSimpleTrigger ON ApplyTriggerTests.aSimpleTable FOR INSERT AS RETURN;'); + DECLARE @OriginalObjectId INT = OBJECT_ID('ApplyTriggerTests.aSimpleTrigger'); + + EXEC tSQLt.FakeTable @TableName = 'ApplyTriggerTests.aSimpleTable'; + + EXEC tSQLt.SpyProcedure @ProcedureName = 'tSQLt.Private_MarktSQLtTempObject'; + TRUNCATE TABLE tSQLt.Private_MarktSQLtTempObject_SpyProcedureLog;--Quirkiness of testing the framework that you use to run the test + + EXEC tSQLt.ApplyTrigger @TableName = 'ApplyTriggerTests.aSimpleTable', @TriggerName = 'aSimpleTrigger'; + + SELECT ObjectName, ObjectType, NewNameOfOriginalObject + INTO #Actual + FROM tSQLt.Private_MarktSQLtTempObject_SpyProcedureLog; + + SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; + INSERT INTO #Expected + VALUES('[ApplyTriggerTests].[aSimpleTrigger]', N'TRIGGER', OBJECT_NAME(@OriginalObjectId)); + + EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; + +END; +GO diff --git a/Tests/FakeFunctionTests.class.sql b/Tests/FakeFunctionTests.class.sql index 9e7ab7a03..43fde701f 100644 --- a/Tests/FakeFunctionTests.class.sql +++ b/Tests/FakeFunctionTests.class.sql @@ -661,6 +661,29 @@ BEGIN EXEC tSQLt.AssertEqualsTable 'FakeFunctionTests.Expected', @NewTable; END; GO +CREATE PROC FakeFunctionTests.[test FakeFunction calls tSQLt.Private_MarktSQLtTempObject on new object] +AS +BEGIN + EXEC('CREATE FUNCTION FakeFunctionTests.AFunction() RETURNS TABLE AS RETURN (SELECT 777 AS a);'); + DECLARE @OriginalObjectId INT = OBJECT_ID('FakeFunctionTests.AFunction'); + EXEC tSQLt.SpyProcedure @ProcedureName = 'tSQLt.Private_MarktSQLtTempObject'; + TRUNCATE TABLE tSQLt.Private_MarktSQLtTempObject_SpyProcedureLog;--Quirkiness of testing the framework that you use to run the test + + EXEC tSQLt.FakeFunction @FunctionName = 'FakeFunctionTests.AFunction', @FakeDataSource = '(VALUES(1)) a(a)'; + + SELECT ObjectName, ObjectType, NewNameOfOriginalObject + INTO #Actual + FROM tSQLt.Private_MarktSQLtTempObject_SpyProcedureLog; + + SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; + INSERT INTO #Expected + VALUES('FakeFunctionTests.AFunction', N'FUNCTION', OBJECT_NAME(@OriginalObjectId)); + + EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; + +END; +GO + -- THIS CODE CREATES THE SNAPSHOT. -- When we revisit creating something like FakeFunctionWithSnapshot, we should refer back. -- DECLARE @newTbleName NVARCHAR(MAX); diff --git a/Tests/FakeTableTests.class.sql b/Tests/FakeTableTests.class.sql index a64f8d44d..2926423bf 100644 --- a/Tests/FakeTableTests.class.sql +++ b/Tests/FakeTableTests.class.sql @@ -17,30 +17,21 @@ EXEC tSQLt.NewTestClass 'FakeTableTests'; GO -CREATE PROC FakeTableTests.AssertTableIsNewObjectThatHasNoConstraints -@TableName NVARCHAR(MAX) +CREATE PROC FakeTableTests.AssertTableIsNewObjectThatHasNoChildObjects +@TableName NVARCHAR(MAX), +@OriginalObjectId INT AS BEGIN - DECLARE @OldTableObjectId INT; - IF OBJECT_ID(@TableName) IS NULL EXEC tSQLt.Fail 'Table ',@TableName,' does not exist!'; - - SELECT @OldTableObjectId = OBJECT_ID(QUOTENAME(OBJECT_SCHEMA_NAME(major_id))+'.'+QUOTENAME(CAST(value AS NVARCHAR(4000)))) - FROM sys.extended_properties WHERE major_id = OBJECT_ID(@TableName) and name = 'tSQLt.FakeTable_OrgTableName' - - IF @OldTableObjectId IS NULL - EXEC tSQLt.Fail 'Table ',@TableName,' is not a fake table!'; - IF OBJECT_ID(@TableName) = @OldTableObjectId + IF OBJECT_ID(@TableName) = @OriginalObjectId EXEC tSQLt.Fail 'Table ',@TableName,' is not a new object!'; - SELECT QUOTENAME(OBJECT_SCHEMA_NAME(object_id))+'.'+QUOTENAME(OBJECT_NAME(object_id)) ReferencingObjectName - INTO #actual FROM sys.objects WHERE parent_object_id = OBJECT_ID(@TableName); + SELECT QUOTENAME(OBJECT_SCHEMA_NAME(object_id))+'.'+QUOTENAME(OBJECT_NAME(object_id)) ReferencingObjectName, type_desc + INTO #ChildObjects FROM sys.objects WHERE parent_object_id = OBJECT_ID(@TableName); - SELECT TOP(0) * INTO #expected FROM #actual; - - EXEC tSQLt.AssertEqualsTable '#expected','#actual','Unexpected referencing objects found!'; + EXEC tSQLt.AssertEmptyTable @TableName = '#ChildObjects', @Message = 'Unexpected child objects found!'; END GO @@ -48,10 +39,13 @@ CREATE PROC FakeTableTests.[test FakeTable works with 2 part names in first para AS BEGIN CREATE TABLE FakeTableTests.TempTable1(i INT); + DECLARE @OriginalObjectId INT = OBJECT_ID('FakeTableTests.TempTable1'); EXEC tSQLt.FakeTable 'FakeTableTests.TempTable1'; - EXEC FakeTableTests.AssertTableIsNewObjectThatHasNoConstraints 'FakeTableTests.TempTable1'; + EXEC FakeTableTests.AssertTableIsNewObjectThatHasNoChildObjects + @TableName = 'FakeTableTests.TempTable1', + @OriginalObjectId = @OriginalObjectId; END; GO @@ -59,10 +53,13 @@ CREATE PROC FakeTableTests.[test FakeTable takes 2 nameless parameters containin AS BEGIN CREATE TABLE FakeTableTests.TempTable1(i INT); + DECLARE @OriginalObjectId INT = OBJECT_ID('FakeTableTests.TempTable1'); EXEC tSQLt.FakeTable 'FakeTableTests','TempTable1'; - EXEC FakeTableTests.AssertTableIsNewObjectThatHasNoConstraints 'FakeTableTests.TempTable1'; + EXEC FakeTableTests.AssertTableIsNewObjectThatHasNoChildObjects + @TableName = 'FakeTableTests.TempTable1', + @OriginalObjectId = @OriginalObjectId; END; GO @@ -161,11 +158,9 @@ CREATE PROC FakeTableTests.[test a faked table has no primary key] AS BEGIN CREATE TABLE FakeTableTests.TempTable1(i INT PRIMARY KEY); - + EXEC tSQLt.FakeTable 'FakeTableTests.TempTable1'; - EXEC FakeTableTests.AssertTableIsNewObjectThatHasNoConstraints 'FakeTableTests.TempTable1'; - INSERT INTO FakeTableTests.TempTable1 (i) VALUES (1); INSERT INTO FakeTableTests.TempTable1 (i) VALUES (1); END; @@ -178,7 +173,6 @@ BEGIN EXEC tSQLt.FakeTable 'FakeTableTests.TempTable1'; - EXEC FakeTableTests.AssertTableIsNewObjectThatHasNoConstraints 'FakeTableTests.TempTable1'; INSERT INTO FakeTableTests.TempTable1 (i) VALUES (5); END; GO @@ -187,11 +181,10 @@ CREATE PROC FakeTableTests.[test a faked table has no foreign keys] AS BEGIN CREATE TABLE FakeTableTests.TempTable0(i INT PRIMARY KEY); - CREATE TABLE FakeTableTests.TempTable1(i INT REFERENCES FakeTableTests.TempTable0(i)); + CREATE TABLE FakeTableTests.TempTable1(i INT REFERENCES FakeTableTests.TempTable0(i)); EXEC tSQLt.FakeTable 'FakeTableTests.TempTable1'; - - EXEC FakeTableTests.AssertTableIsNewObjectThatHasNoConstraints 'FakeTableTests.TempTable1'; + INSERT INTO FakeTableTests.TempTable1 (i) VALUES (5); END; GO @@ -203,12 +196,9 @@ BEGIN EXEC tSQLt.FakeTable 'FakeTableTests.TempTable1'; - EXEC FakeTableTests.AssertTableIsNewObjectThatHasNoConstraints 'FakeTableTests.TempTable1'; INSERT INTO FakeTableTests.TempTable1 (i) DEFAULT VALUES; - DECLARE @value INT; - SELECT @value = i - FROM FakeTableTests.TempTable1; + DECLARE @value INT = (SELECT i FROM FakeTableTests.TempTable1); EXEC tSQLt.AssertEquals NULL, @value; END; @@ -221,7 +211,6 @@ BEGIN EXEC tSQLt.FakeTable 'FakeTableTests.TempTable1'; - EXEC FakeTableTests.AssertTableIsNewObjectThatHasNoConstraints 'FakeTableTests.TempTable1'; INSERT INTO FakeTableTests.TempTable1 (i) VALUES (1); INSERT INTO FakeTableTests.TempTable1 (i) VALUES (1); END; @@ -235,7 +224,6 @@ BEGIN EXEC tSQLt.FakeTable 'FakeTableTests.TempTable1'; - EXEC FakeTableTests.AssertTableIsNewObjectThatHasNoConstraints 'FakeTableTests.TempTable1'; INSERT INTO FakeTableTests.TempTable1 (i) VALUES (1); INSERT INTO FakeTableTests.TempTable1 (i) VALUES (1); END; @@ -248,7 +236,6 @@ BEGIN EXEC tSQLt.FakeTable 'FakeTableTests.TempTable1'; - EXEC FakeTableTests.AssertTableIsNewObjectThatHasNoConstraints 'FakeTableTests.TempTable1'; INSERT INTO FakeTableTests.TempTable1 (i) VALUES (NULL); END; GO @@ -982,7 +969,7 @@ BEGIN CREATE TABLE FakeTableTests.TempTable1(c1 INT NULL, c2 BIGINT NULL, c3 VARCHAR(MAX) NULL); EXEC('CREATE VIEW FakeTableTests.TempView1 AS SELECT * FROM FakeTableTests.TempTable1;'); CREATE SYNONYM FakeTableTests.TempSynonym1 FOR FakeTableTests.TempView1; - + EXEC tSQLt.FakeTable 'FakeTableTests.TempSynonym1'; EXEC tSQLt.AssertEqualsTableSchema @Expected = 'FakeTableTests.TempTable1', @Actual = 'FakeTableTests.TempSynonym1'; @@ -1008,34 +995,40 @@ BEGIN END; GO - CREATE PROC FakeTableTests.[test FakeTable works with two parameters, if they are quoted] AS BEGIN CREATE TABLE FakeTableTests.TempTable1(i INT NOT NULL); + DECLARE @OriginalObjectId INT = OBJECT_ID('FakeTableTests.TempTable1'); + EXEC tSQLt.FakeTable '[FakeTableTests]','[TempTable1]'; - EXEC FakeTableTests.AssertTableIsNewObjectThatHasNoConstraints 'FakeTableTests.TempTable1'; + EXEC FakeTableTests.AssertTableIsNewObjectThatHasNoChildObjects + @TableName = 'FakeTableTests.TempTable1', + @OriginalObjectId = @OriginalObjectId; END; GO - ---CREATE PROC FakeTableTests.[test FakeTable works with cross database synonym] ---AS ---BEGIN --- CREATE TABLE tempdb.dbo.TempTable1(i INT NOT NULL); --- CREATE SYNONYM FakeTableTests.TempTable1 FOR tempdb.dbo.TempTable1 - --- EXEC tSQLt.FakeTable '[FakeTableTests]','[TempTable1]'; +CREATE PROC FakeTableTests.[test FakeTable calls tSQLt.Private_MarktSQLtTempObject on new object] +AS +BEGIN + CREATE TABLE FakeTableTests.TempTable1(i INT NOT NULL); + DECLARE @OriginalObjectId INT = OBJECT_ID('FakeTableTests.TempTable1'); + EXEC tSQLt.SpyProcedure @ProcedureName = 'tSQLt.Private_MarktSQLtTempObject'; + TRUNCATE TABLE tSQLt.Private_MarktSQLtTempObject_SpyProcedureLog;--Quirkiness of testing the framework that you use to run the test --- EXEC FakeTableTests.AssertTableIsNewObjectThatHasNoConstraints 'FakeTableTests.TempTable1'; - ---END; ---GO - - + EXEC tSQLt.FakeTable '[FakeTableTests].[TempTable1]'; + SELECT ObjectName, ObjectType, NewNameOfOriginalObject + INTO #Actual + FROM tSQLt.Private_MarktSQLtTempObject_SpyProcedureLog; + + SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; + INSERT INTO #Expected + VALUES('[FakeTableTests].[TempTable1]', N'TABLE', OBJECT_NAME(@OriginalObjectId)); ---ROLLBACK - + EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; + +END; +GO diff --git a/Tests/Private_MarktSQLtTempObjectTests.class.sql b/Tests/Private_MarktSQLtTempObjectTests.class.sql new file mode 100644 index 000000000..205caa035 --- /dev/null +++ b/Tests/Private_MarktSQLtTempObjectTests.class.sql @@ -0,0 +1,115 @@ +EXEC tSQLt.NewTestClass 'Private_MarktSQLtTempObjectTests'; +GO +CREATE PROCEDURE Private_MarktSQLtTempObjectTests.[assert creates two extended properties on object] + @ObjectName NVARCHAR(MAX), + @ObjectType NVARCHAR(MAX) +AS +BEGIN + EXEC tSQLt.Private_MarktSQLtTempObject + @ObjectName = @ObjectName, + @ObjectType = @ObjectType, + @NewNameOfOriginalObject = 'ARandomString'; + + SELECT name, CAST(value AS NVARCHAR(MAX)) value + INTO #Actual + FROM sys.extended_properties + WHERE class_desc = 'OBJECT_OR_COLUMN' + AND major_id = OBJECT_ID(@ObjectName) + AND name IN ('tSQLt.IsTempObject', 'tSQLt.Private_TestDouble_OrgObjectName') + + SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; + + INSERT INTO #Expected VALUES('tSQLt.IsTempObject', '1'), + ('tSQLt.Private_TestDouble_OrgObjectName','ARandomString'); + + EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; +END; +GO +CREATE PROCEDURE Private_MarktSQLtTempObjectTests.[test can mark a table] +AS +BEGIN + CREATE TABLE Private_MarktSQLtTempObjectTests.TempTable1(i INT NOT NULL); + EXEC Private_MarktSQLtTempObjectTests.[assert creates two extended properties on object] + @ObjectName = 'Private_MarktSQLtTempObjectTests.TempTable1', + @ObjectType = N'TABLE'; +END; +GO +CREATE PROCEDURE Private_MarktSQLtTempObjectTests.[test can mark a stored procedure] +AS +BEGIN + EXEC('CREATE PROCEDURE Private_MarktSQLtTempObjectTests.TempProcedure1 AS RETURN;'); + EXEC Private_MarktSQLtTempObjectTests.[assert creates two extended properties on object] + @ObjectName = 'Private_MarktSQLtTempObjectTests.TempProcedure1', + @ObjectType = N'PROCEDURE'; +END; +GO +CREATE PROCEDURE Private_MarktSQLtTempObjectTests.[test can mark a TV function] +AS +BEGIN + EXEC('CREATE FUNCTION Private_MarktSQLtTempObjectTests.TempTVFunction1() RETURNS @X TABLE (i INT) AS BEGIN RETURN; END;'); + EXEC Private_MarktSQLtTempObjectTests.[assert creates two extended properties on object] + @ObjectName = 'Private_MarktSQLtTempObjectTests.TempTVFunction1', + @ObjectType = N'FUNCTION'; +END; +GO +CREATE PROCEDURE Private_MarktSQLtTempObjectTests.[test can mark a ITV function] +AS +BEGIN + EXEC('CREATE FUNCTION Private_MarktSQLtTempObjectTests.TempITVFunction1() RETURNS TABLE AS RETURN SELECT 1 X;'); + EXEC Private_MarktSQLtTempObjectTests.[assert creates two extended properties on object] + @ObjectName = 'Private_MarktSQLtTempObjectTests.TempITVFunction1', + @ObjectType = N'FUNCTION'; +END; +GO +CREATE PROCEDURE Private_MarktSQLtTempObjectTests.[test can mark a SV function] +AS +BEGIN + EXEC('CREATE FUNCTION Private_MarktSQLtTempObjectTests.TempSVFunction1() RETURNS INT AS BEGIN RETURN NULL; END;'); + EXEC Private_MarktSQLtTempObjectTests.[assert creates two extended properties on object] + @ObjectName = 'Private_MarktSQLtTempObjectTests.TempSVFunction1', + @ObjectType = N'FUNCTION'; +END; +GO +CREATE PROCEDURE Private_MarktSQLtTempObjectTests.[test can mark a constraint] +AS +BEGIN + CREATE TABLE Private_MarktSQLtTempObjectTests.TempTable1(i INT CONSTRAINT aSimpleTableConstraint CHECK(i > 0)); + + EXEC Private_MarktSQLtTempObjectTests.[assert creates two extended properties on object] + @ObjectName = 'Private_MarktSQLtTempObjectTests.aSimpleTableConstraint', + @ObjectType = N'CONSTRAINT'; +END; +GO +CREATE PROCEDURE Private_MarktSQLtTempObjectTests.[test can mark a trigger] +AS +BEGIN + CREATE TABLE Private_MarktSQLtTempObjectTests.TempTable1(i INT); + EXEC('CREATE TRIGGER Private_MarktSQLtTempObjectTests.TempTrigger ON Private_MarktSQLtTempObjectTests.TempTable1 FOR INSERT AS RETURN;'); + + EXEC Private_MarktSQLtTempObjectTests.[assert creates two extended properties on object] + @ObjectName = 'Private_MarktSQLtTempObjectTests.TempTrigger', + @ObjectType = N'TRIGGER'; +END; +GO +CREATE PROCEDURE Private_MarktSQLtTempObjectTests.[test tSQLt.IsTempObject Data Type is BIT] +AS +BEGIN + CREATE TABLE Private_MarktSQLtTempObjectTests.TempTable1(i INT NOT NULL); + EXEC Private_MarktSQLtTempObjectTests.[assert creates two extended properties on object] + @ObjectName = 'Private_MarktSQLtTempObjectTests.TempTable1', + @ObjectType = N'TABLE'; + + SELECT UPPER(CAST(SQL_VARIANT_PROPERTY(EP.value,'BaseType') AS NVARCHAR(MAX))) IsTempObject_DataType + INTO #Actual + FROM sys.extended_properties AS EP + WHERE EP.class_desc = 'OBJECT_OR_COLUMN' + AND EP.major_id = OBJECT_ID('Private_MarktSQLtTempObjectTests.TempTable1') + AND EP.name = 'tSQLt.IsTempObject'; + + SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; + INSERT INTO #Expected VALUES('BIT'); + + EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; + +END; +GO \ No newline at end of file diff --git a/Tests/SpyProcedureTests.class.sql b/Tests/SpyProcedureTests.class.sql index f6e9c8e80..12d830d50 100644 --- a/Tests/SpyProcedureTests.class.sql +++ b/Tests/SpyProcedureTests.class.sql @@ -734,3 +734,46 @@ BEGIN END; GO +CREATE PROC SpyProcedureTests.[test new Procedure Spy is marked as tSQLt.IsTempObject] +AS +BEGIN + EXEC('CREATE PROCEDURE SpyProcedureTests.TempProcedure1 AS RETURN;'); + + EXEC tSQLt.SpyProcedure @ProcedureName = 'SpyProcedureTests.TempProcedure1'; + + SELECT name, value + INTO #Actual + FROM sys.extended_properties + WHERE class_desc = 'OBJECT_OR_COLUMN' + AND major_id = OBJECT_ID('SpyProcedureTests.TempProcedure1') + AND name = 'tSQLt.IsTempObject'; + + SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; + + INSERT INTO #Expected VALUES('tSQLt.IsTempObject', 1); + + EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; +END; +GO +CREATE PROC SpyProcedureTests.[test SpyProcedure calls tSQLt.Private_MarktSQLtTempObject on new object] +AS +BEGIN + DECLARE @OriginalObjectId INT = OBJECT_ID('tSQLt.Private_MarktSQLtTempObject'); + + EXEC tSQLt.SpyProcedure @ProcedureName = 'tSQLt.Private_MarktSQLtTempObject'; + --We are testing that SpyProcedure calls this ^^ after spying this ^^, so this line serves as prep and action. + + SELECT ObjectName, ObjectType, NewNameOfOriginalObject + INTO #Actual + FROM tSQLt.Private_MarktSQLtTempObject_SpyProcedureLog; + + SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; + INSERT INTO #Expected + VALUES('tSQLt.Private_MarktSQLtTempObject', N'PROCEDURE', OBJECT_NAME(@OriginalObjectId)); + + EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; + +END; +GO + + diff --git a/Tests/Tests.ssmssqlproj b/Tests/Tests.ssmssqlproj index 2d4cb4b28..c3a19eb54 100644 --- a/Tests/Tests.ssmssqlproj +++ b/Tests/Tests.ssmssqlproj @@ -216,6 +216,12 @@ Private_InstallationInfoTests.class.sql + + + + + Private_MarktSQLtTempObjectTests.class.sql + diff --git a/Tests/UndoTestDoublesTests.class.sql b/Tests/UndoTestDoublesTests.class.sql index 9eab7fe64..81cdac500 100644 --- a/Tests/UndoTestDoublesTests.class.sql +++ b/Tests/UndoTestDoublesTests.class.sql @@ -14,7 +14,6 @@ CREATE PROCEDURE UndoTestDoublesTests.[test restores a faked table] AS BEGIN CREATE TABLE UndoTestDoublesTests.aSimpleTable ( Id INT ); - DECLARE @OriginalObjectId INT = OBJECT_ID('UndoTestDoublesTests.aSimpleTable'); EXEC tSQLt.FakeTable @TableName = 'UndoTestDoublesTests.aSimpleTable'; @@ -23,7 +22,6 @@ BEGIN DECLARE @RestoredObjectId INT = OBJECT_ID('UndoTestDoublesTests.aSimpleTable'); EXEC tSQLt.AssertEquals @Expected = @OriginalObjectId, @Actual = @RestoredObjectId; - END; GO CREATE PROCEDURE UndoTestDoublesTests.[test works with names in need of quotes] @@ -303,7 +301,7 @@ BEGIN EXEC tSQLt.AssertEmptyTable @TableName = '#ShouldBeEmpty'; END; GO -CREATE PROCEDURE UndoTestDoublesTests.[test objects renamed by RemoveObject are restored and conflicting object are deleted] +CREATE PROCEDURE UndoTestDoublesTests.[test objects renamed by RemoveObject are restored and conflicting objects with IsTempObject property are deleted] AS BEGIN EXEC ('CREATE TABLE UndoTestDoublesTests.aSimpleTable(i INT);'); @@ -314,7 +312,7 @@ BEGIN EXEC tSQLt.RemoveObject @ObjectName='UndoTestDoublesTests.aSimpleTable'; EXEC ('CREATE PROCEDURE UndoTestDoublesTests.aSimpleTable AS PRINT ''Who came up with that name?'';'); - + EXEC tSQLt.Private_MarktSQLtTempObject @ObjectName = 'UndoTestDoublesTests.aSimpleTable', @ObjectType = N'PROCEDURE', @NewNameOfOriginalObject = ''; EXEC tSQLt.UndoTestDoubles; SELECT O.object_id,SCHEMA_NAME(O.schema_id) schema_name, O.name object_name, O.type_desc @@ -331,7 +329,6 @@ BEGIN EXEC tSQLt.AssertEmptyTable @TableName = '#ShouldBeEmpty'; END; GO ---tSQLt.Run UndoTestDoublesTests CREATE PROCEDURE UndoTestDoublesTests.[test synonyms are restored] AS BEGIN @@ -342,8 +339,8 @@ BEGIN INTO #OriginalObjectIds FROM sys.objects O; - EXEC tSQLt.RemoveObject @ObjectName='UndoTestDoublesTests.aSimpleSynonym'; - EXEC ('CREATE TABLE UndoTestDoublesTests.aSimpleSynonym(i INT);'); + EXEC tSQLt.FakeTable @TableName = 'UndoTestDoublesTests.aSimpleSynonym'; + EXEC tSQLt.UndoTestDoubles; SELECT O.object_id,SCHEMA_NAME(O.schema_id) schema_name, O.name object_name, O.type_desc @@ -360,7 +357,7 @@ BEGIN EXEC tSQLt.AssertEmptyTable @TableName = '#ShouldBeEmpty'; END; GO -CREATE PROCEDURE UndoTestDoublesTests.[test doubled synonyms are deleted] +CREATE PROCEDURE UndoTestDoublesTests.[test doubled synonyms with IsTempObject property are deleted] AS BEGIN EXEC ('CREATE TABLE UndoTestDoublesTests.aSimpleTable(i INT);'); @@ -372,6 +369,7 @@ BEGIN EXEC tSQLt.RemoveObject @ObjectName='UndoTestDoublesTests.aSimpleObject'; EXEC ('CREATE SYNONYM UndoTestDoublesTests.aSimpleObject FOR UndoTestDoublesTests.aSimpleTable;'); + EXEC tSQLt.Private_MarktSQLtTempObject @ObjectName='UndoTestDoublesTests.aSimpleObject', @ObjectType='SYNONYM', @NewNameOfOriginalObject = ''; EXEC tSQLt.UndoTestDoubles; @@ -389,13 +387,193 @@ BEGIN EXEC tSQLt.AssertEmptyTable @TableName = '#ShouldBeEmpty'; END; GO -CREATE PROCEDURE UndoTestDoublesTests.[test if FakeFunctionWithSnapshot exists we need to write tests] +CREATE PROCEDURE UndoTestDoublesTests.[test drops only objects that are marked as temporary (IsTempObject = 1)] +AS +BEGIN + CREATE TABLE UndoTestDoublesTests.SimpleTable1 (i INT); + + EXEC tSQLt.RemoveObject @ObjectName = 'UndoTestDoublesTests.SimpleTable1'; + CREATE TABLE UndoTestDoublesTests.SimpleTable1 (i INT); + + EXEC tSQLt.ExpectException @ExpectedMessage = 'Cannot drop these objects as they are not marked as temporary. Use @Force = 1 to override. ([UndoTestDoublesTests].[SimpleTable1])', @ExpectedSeverity = 16, @ExpectedState = 10; + + EXEC tSQLt.UndoTestDoubles; +END; +GO +CREATE PROCEDURE UndoTestDoublesTests.[test does not drop multiple unmarked objects (IsTempObject is not set or is not 1)] +AS +BEGIN + CREATE TABLE UndoTestDoublesTests.SimpleTable1 (i INT); + CREATE TABLE UndoTestDoublesTests.SimpleTable2 (i INT); + CREATE TABLE UndoTestDoublesTests.SimpleTable3 (i INT); + + EXEC tSQLt.RemoveObject @ObjectName = 'UndoTestDoublesTests.SimpleTable1'; + EXEC tSQLt.RemoveObject @ObjectName = 'UndoTestDoublesTests.SimpleTable2'; + EXEC tSQLt.RemoveObject @ObjectName = 'UndoTestDoublesTests.SimpleTable3'; + + CREATE TABLE UndoTestDoublesTests.SimpleTable1 (i INT); + CREATE TABLE UndoTestDoublesTests.SimpleTable2 (i INT); + CREATE TABLE UndoTestDoublesTests.SimpleTable3 (i INT); + + EXEC tSQLt.ExpectException @ExpectedMessage = 'Cannot drop these objects as they are not marked as temporary. Use @Force = 1 to override. ([UndoTestDoublesTests].[SimpleTable1], [UndoTestDoublesTests].[SimpleTable2], [UndoTestDoublesTests].[SimpleTable3])', @ExpectedSeverity = 16, @ExpectedState = 10; + + EXEC tSQLt.UndoTestDoubles; +END; +GO +CREATE PROCEDURE UndoTestDoublesTests.[test does not drop marked object where IsTempObject is not 1] +AS +BEGIN + CREATE TABLE UndoTestDoublesTests.SimpleTable1 (i INT); + + EXEC tSQLt.RemoveObject @ObjectName = 'UndoTestDoublesTests.SimpleTable1'; + CREATE TABLE UndoTestDoublesTests.SimpleTable1 (i INT); + EXEC sys.sp_addextendedproperty + @name = N'tSQLt.IsTempObject', + @value = 42, + @level0type = N'SCHEMA', @level0name = 'UndoTestDoublesTests', + @level1type = N'TABLE', @level1name = 'SimpleTable1'; + + EXEC tSQLt.ExpectException @ExpectedMessage = 'Cannot drop these objects as they are not marked as temporary. Use @Force = 1 to override. ([UndoTestDoublesTests].[SimpleTable1])', @ExpectedSeverity = 16, @ExpectedState = 10; + + EXEC tSQLt.UndoTestDoubles; +END; +GO +CREATE PROCEDURE UndoTestDoublesTests.[test objects renamed by RemoveObject are restored and conflicting objects without IsTempObject property are deleted if @Force=1] +AS +BEGIN + EXEC ('CREATE TABLE UndoTestDoublesTests.aSimpleTable(i INT);'); + + SELECT O.object_id,SCHEMA_NAME(O.schema_id) schema_name, O.name object_name, O.type_desc + INTO #OriginalObjectIds + FROM sys.objects O; + + EXEC tSQLt.RemoveObject @ObjectName='UndoTestDoublesTests.aSimpleTable'; + EXEC ('CREATE PROCEDURE UndoTestDoublesTests.aSimpleTable AS PRINT ''Who came up with that name?'';'); + + EXEC tSQLt.UndoTestDoubles @Force=1; + + SELECT O.object_id,SCHEMA_NAME(O.schema_id) schema_name, O.name object_name, O.type_desc + INTO #RestoredObjectIds + FROM sys.objects O; + + SELECT * INTO #ShouldBeEmpty + FROM + ( + SELECT 'Expected' T,* FROM (SELECT * FROM #OriginalObjectIds EXCEPT SELECT * FROM #RestoredObjectIds) E + UNION ALL + SELECT 'Actual' T,* FROM (SELECT * FROM #RestoredObjectIds EXCEPT SELECT * FROM #OriginalObjectIds) A + ) T; + EXEC tSQLt.AssertEmptyTable @TableName = '#ShouldBeEmpty'; +END; +GO +CREATE PROCEDURE UndoTestDoublesTests.[test warning message is printed for objects without IsTempObject property that are deleted if @Force=1] AS BEGIN - IF EXISTS (SELECT * FROM sys.objects WHERE UPPER(name) LIKE 'FAKEFUNCTION_%') - BEGIN - EXEC tSQLt.Fail 'More tests to be written!' - -- Also remove tSQLt_TempObject_s - END; + EXEC ('CREATE TABLE UndoTestDoublesTests.aSimpleTable(i INT);'); + + EXEC tSQLt.RemoveObject @ObjectName='UndoTestDoublesTests.aSimpleTable'; + EXEC ('CREATE PROCEDURE UndoTestDoublesTests.aSimpleTable AS PRINT ''Who came up with that name?'';'); + EXEC tSQLt.SpyProcedure @ProcedureName = 'tSQLt.Private_Print'; + + EXEC tSQLt.UndoTestDoubles @Force=1; + + SELECT Message INTO #Actual FROM tSQLt.Private_Print_SpyProcedureLog; + + SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; + INSERT INTO #Expected + VALUES('WARNING: @Force has been set to 1. Dropping the following objects that are not marked as temporary. ([UndoTestDoublesTests].[aSimpleTable])'); + + EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; + +END; +GO +CREATE PROCEDURE UndoTestDoublesTests.[test objects that are replaced multiple times by objects not marked as IsTempObject are restored if @Force=1] +AS +BEGIN + EXEC ('CREATE TABLE UndoTestDoublesTests.aSimpleTable(i INT);'); + + SELECT O.object_id,SCHEMA_NAME(O.schema_id) schema_name, O.name object_name, O.type_desc + INTO #OriginalObjectIds + FROM sys.objects O; + + EXEC tSQLt.RemoveObject @ObjectName='UndoTestDoublesTests.aSimpleTable'; + EXEC ('CREATE PROCEDURE UndoTestDoublesTests.aSimpleTable AS PRINT ''Replacement 1'';'); + EXEC tSQLt.RemoveObject @ObjectName='UndoTestDoublesTests.aSimpleTable'; + EXEC ('CREATE PROCEDURE UndoTestDoublesTests.aSimpleTable AS PRINT ''Replacement 2'';'); + EXEC tSQLt.RemoveObject @ObjectName='UndoTestDoublesTests.aSimpleTable'; + EXEC ('CREATE PROCEDURE UndoTestDoublesTests.aSimpleTable AS PRINT ''Replacement 3'';'); + + EXEC tSQLt.UndoTestDoubles @Force=1; + + SELECT O.object_id,SCHEMA_NAME(O.schema_id) schema_name, O.name object_name, O.type_desc + INTO #RestoredObjectIds + FROM sys.objects O; + + SELECT * INTO #ShouldBeEmpty + FROM + ( + SELECT 'Expected' T,* FROM (SELECT * FROM #OriginalObjectIds EXCEPT SELECT * FROM #RestoredObjectIds) E + UNION ALL + SELECT 'Actual' T,* FROM (SELECT * FROM #RestoredObjectIds EXCEPT SELECT * FROM #OriginalObjectIds) A + ) T; + EXEC tSQLt.AssertEmptyTable @TableName = '#ShouldBeEmpty'; +END; +GO +CREATE PROCEDURE UndoTestDoublesTests.[test drops a marked object even if it is not conflicting with an original object] +AS +BEGIN + SELECT O.object_id,SCHEMA_NAME(O.schema_id) schema_name, O.name object_name, O.type_desc + INTO #OriginalObjectIds + FROM sys.objects O; + + CREATE TABLE UndoTestDoublesTests.SimpleTable1 (i INT); + + EXEC tSQLt.Private_MarktSQLtTempObject @ObjectName = 'UndoTestDoublesTests.SimpleTable1', @ObjectType = 'TABLE', @NewNameOfOriginalObject = NULL; + + EXEC tSQLt.UndoTestDoubles; + + SELECT O.object_id,SCHEMA_NAME(O.schema_id) schema_name, O.name object_name, O.type_desc + INTO #RestoredObjectIds + FROM sys.objects O; + + SELECT * INTO #ShouldBeEmpty + FROM + ( + SELECT 'Expected' T,* FROM (SELECT * FROM #OriginalObjectIds EXCEPT SELECT * FROM #RestoredObjectIds) E + UNION ALL + SELECT 'Actual' T,* FROM (SELECT * FROM #RestoredObjectIds EXCEPT SELECT * FROM #OriginalObjectIds) A + ) T; + EXEC tSQLt.AssertEmptyTable @TableName = '#ShouldBeEmpty'; +END; +GO +CREATE PROCEDURE UndoTestDoublesTests.[test drops multiple marked objects even if they do not conflict with an original object] +AS +BEGIN + SELECT O.object_id,SCHEMA_NAME(O.schema_id) schema_name, O.name object_name, O.type_desc + INTO #OriginalObjectIds + FROM sys.objects O; + + CREATE TABLE UndoTestDoublesTests.SimpleTable1 (i INT); + CREATE TABLE UndoTestDoublesTests.SimpleTable2 (i INT); + CREATE TABLE UndoTestDoublesTests.SimpleTable3 (i INT); + + EXEC tSQLt.Private_MarktSQLtTempObject @ObjectName = 'UndoTestDoublesTests.SimpleTable1', @ObjectType = 'TABLE', @NewNameOfOriginalObject = NULL; + EXEC tSQLt.Private_MarktSQLtTempObject @ObjectName = 'UndoTestDoublesTests.SimpleTable2', @ObjectType = 'TABLE', @NewNameOfOriginalObject = NULL; + EXEC tSQLt.Private_MarktSQLtTempObject @ObjectName = 'UndoTestDoublesTests.SimpleTable3', @ObjectType = 'TABLE', @NewNameOfOriginalObject = NULL; + + EXEC tSQLt.UndoTestDoubles; + + SELECT O.object_id,SCHEMA_NAME(O.schema_id) schema_name, O.name object_name, O.type_desc + INTO #RestoredObjectIds + FROM sys.objects O; + + SELECT * INTO #ShouldBeEmpty + FROM + ( + SELECT 'Expected' T,* FROM (SELECT * FROM #OriginalObjectIds EXCEPT SELECT * FROM #RestoredObjectIds) E + UNION ALL + SELECT 'Actual' T,* FROM (SELECT * FROM #RestoredObjectIds EXCEPT SELECT * FROM #OriginalObjectIds) A + ) T; + EXEC tSQLt.AssertEmptyTable @TableName = '#ShouldBeEmpty'; END; GO