diff --git a/Build/tSQLt.build.xml b/Build/tSQLt.build.xml
index bebdaa837..ac0c8e917 100644
--- a/Build/tSQLt.build.xml
+++ b/Build/tSQLt.build.xml
@@ -409,6 +409,7 @@
+
@@ -422,6 +423,7 @@
+
diff --git a/Build/tSQLt.remote.class.sql b/Build/tSQLt.remote.class.sql
new file mode 100644
index 000000000..a5755ba3d
--- /dev/null
+++ b/Build/tSQLt.remote.class.sql
@@ -0,0 +1,27 @@
+---Build+
+CREATE TABLE dbo.TestTable
+ (
+ c1 INT NULL ,
+ c2 BIGINT NULL ,
+ c3 VARCHAR(MAX) NULL
+ );
+GO
+CREATE VIEW dbo.TestView
+AS
+ SELECT *
+ FROM dbo.TestTable;;
+GO
+CREATE PROCEDURE dbo.NotATable
+AS
+ RETURN;
+GO
+CREATE SCHEMA TestSchema;
+GO
+CREATE TYPE TestSchema.UDT FROM NVARCHAR(20);
+GO
+CREATE TABLE TestSchema.tbl(i TestSchema.UDT)
+GO
+CREATE TYPE TestSchema.UDTi FROM INT;
+GO
+CREATE TABLE TestSchema.tbli(i TestSchema.UDTi)
+GO
diff --git a/Build/tSQLt.validatebuild.xml b/Build/tSQLt.validatebuild.xml
index c46588b26..2c1d3cd1a 100644
--- a/Build/tSQLt.validatebuild.xml
+++ b/Build/tSQLt.validatebuild.xml
@@ -23,6 +23,7 @@
+
@@ -32,6 +33,7 @@
+
@@ -50,6 +52,7 @@
+
@@ -65,6 +68,7 @@
+
@@ -75,6 +79,7 @@
+
@@ -129,6 +134,7 @@
+
@@ -140,6 +146,7 @@
+
@@ -500,6 +507,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Source/BuildOrder.txt b/Source/BuildOrder.txt
index 301f92a2d..4f01f1cba 100644
--- a/Source/BuildOrder.txt
+++ b/Source/BuildOrder.txt
@@ -16,9 +16,19 @@ tSQLt.InstallAssemblyKey.ssp.sql
tSQLt.PrepareServer.ssp.sql
tSQLt.Private_NewTestClassList.tbl.sql
tSQLt.Private_ResetNewTestClassList.ssp.sql
+tSQLt.Private_SysColumns.svw.sql
+tSQLt.Private_SysComputedColumns.svw.sql
+tSQLt.Private_SysDefaultConstraints.svw.sql
+tSQLt.Private_SysIdentityColumns.svw.sql
+tSQLt.Private_SysObjects.svw.sql
+tSQLt.Private_SysSchemas.svw.sql
tSQLt.Private_DisallowOverwritingNonTestSchema.ssp.sql
+tSQLt.Private_AlterSysObjectForRemote.ssp.sql
+tSQLt.Private_CreateRemoteSysObjects.ssp.sql
+tSQLt.Private_GetRemoteObjectId.ssp.sql
tSQLt.Private_QuoteClassNameForNewTestClass.sfn.sql
tSQLt.Private_MarkSchemaAsTestClass.ssp.sql
+tSQLt.Private_ValidateSynonymCompatibilityWithFakeTable.ssp.sql
tSQLt.NewTestClass.ssp.sql
tSQLt.Fail.ssp.sql
tSQLt.class.sql
@@ -64,6 +74,7 @@ tSQLt.Private_GetDataTypeOrComputedColumnDefinition.sfn.sql
tSQLt.Private_GetIdentityDefinition.sfn.sql
tSQLt.Private_GetDefaultConstraintDefinition.sfn.sql
tSQLt.Private_GetUniqueConstraintDefinition.sfn.sql
+tSQLt.Private_CreateRemoteUserDefinedDataTypes.ssp.sql
tSQLt.Private_CreateFakeTableStatement.sfn.sql
tSQLt.Private_CreateFakeOfTable.ssp.sql
tSQLt.Private_MarkFakeTable.ssp.sql
diff --git a/Source/Source.ssmssqlproj b/Source/Source.ssmssqlproj
index a618b037d..701fbf3c4 100644
--- a/Source/Source.ssmssqlproj
+++ b/Source/Source.ssmssqlproj
@@ -204,6 +204,12 @@
tSQLt.NewTestClass.ssp.sql
+
+ 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:Dev_tSQLt:True
+ Dev_tSQLt
+
+ tSQLt.Private_AlterSysObjectForRemote.ssp.sql
+
@@ -240,6 +246,18 @@
tSQLt.Private_CreateFakeFunction.ssp.sql
+
+ 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:Dev_tSQLt:True
+ Dev_tSQLt
+
+ tSQLt.Private_CreateRemoteSysObjects.ssp.sql
+
+
+ 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:Dev_tSQLt:True
+ Dev_tSQLt
+
+ tSQLt.Private_CreateRemoteUserDefinedDataTypes.ssp.sql
+
@@ -330,6 +348,12 @@
tSQLt.Private_GetFullTypeName.sfn.sql
+
+ 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:Dev_tSQLt:True
+ Dev_tSQLt
+
+ tSQLt.Private_GetRemoteObjectId.ssp.sql
+
@@ -498,12 +522,48 @@
tSQLt.Private_SqlVersion.sfn.sql
+
+ 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:Dev_tSQLt:True
+ Dev_tSQLt
+
+ tSQLt.Private_SysColumns.svw.sql
+
+
+ 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:Dev_tSQLt:True
+ Dev_tSQLt
+
+ tSQLt.Private_SysComputedColumns.svw.sql
+
+
+ 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:Dev_tSQLt:True
+ Dev_tSQLt
+
+ tSQLt.Private_SysDefaultConstraints.svw.sql
+
+
+ 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:Dev_tSQLt:True
+ Dev_tSQLt
+
+ tSQLt.Private_SysIdentityColumns.svw.sql
+
tSQLt.Private_SysIndexes.svw.sql
+
+ 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:Dev_tSQLt:True
+ Dev_tSQLt
+
+ tSQLt.Private_SysObjects.svw.sql
+
+
+ 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:Dev_tSQLt:True
+ Dev_tSQLt
+
+ tSQLt.Private_SysSchemas.svw.sql
+
@@ -653,7 +713,7 @@
tSQLtCLR_CreateProcs.sql
-
+
diff --git a/Source/tSQLt.FakeTable.ssp.sql b/Source/tSQLt.FakeTable.ssp.sql
index a2635edba..680ee3f26 100644
--- a/Source/tSQLt.FakeTable.ssp.sql
+++ b/Source/tSQLt.FakeTable.ssp.sql
@@ -13,15 +13,17 @@ BEGIN
DECLARE @OrigTableName NVARCHAR(MAX);
DECLARE @NewNameOfOriginalTable NVARCHAR(4000);
DECLARE @OrigTableFullName NVARCHAR(MAX); SET @OrigTableFullName = NULL;
-
+ DECLARE @RemoteObjectID INT;
+ DECLARE @SynonymObjectId INT;
+
SELECT @OrigSchemaName = @SchemaName,
@OrigTableName = @TableName
IF(@OrigTableName NOT IN (PARSENAME(@OrigTableName,1),QUOTENAME(PARSENAME(@OrigTableName,1)))
AND @OrigSchemaName IS NOT NULL)
- BEGIN
- RAISERROR('When @TableName is a multi-part identifier, @SchemaName must be NULL!',16,10);
- END
+ BEGIN
+ RAISERROR('When @TableName is a multi-part identifier, @SchemaName must be NULL!',16,10);
+ END
SELECT @SchemaName = CleanSchemaName,
@TableName = CleanTableName
@@ -31,25 +33,27 @@ BEGIN
EXEC tSQLt.Private_RenameObjectToUniqueName @SchemaName, @TableName, @NewNameOfOriginalTable OUTPUT;
- SELECT @OrigTableFullName = S.base_object_name
- FROM sys.synonyms AS S
- WHERE S.object_id = OBJECT_ID(@SchemaName + '.' + @NewNameOfOriginalTable);
- IF(@OrigTableFullName IS NOT NULL)
- BEGIN
- IF(COALESCE(OBJECT_ID(@OrigTableFullName,'U'),OBJECT_ID(@OrigTableFullName,'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);
- END;
- END;
- ELSE
- BEGIN
- SET @OrigTableFullName = @SchemaName + '.' + @NewNameOfOriginalTable;
- END;
+ SET @OrigTableFullName = @SchemaName + '.' + @NewNameOfOriginalTable;
+ SET @SynonymObjectId = OBJECT_ID(@OrigTableFullName, 'SN');
+ IF ( @SynonymObjectId > 0)
+ BEGIN
+ EXEC tSQLt.Private_GetRemoteObjectId @SynonymObjectId = @SynonymObjectId ,
+ @RemoteObjectId = @RemoteObjectID OUTPUT,
+ @OrigTableFullName = @OrigTableFullName OUTPUT
- EXEC tSQLt.Private_CreateFakeOfTable @SchemaName, @TableName, @OrigTableFullName, @Identity, @ComputedColumns, @Defaults;
+ EXEC tSQLt.Private_ValidateSynonymCompatibilityWithFakeTable @TableName, @SchemaName, @OrigTableFullName;
+ END;
+
+ EXEC tSQLt.Private_CreateFakeOfTable @SchemaName, @TableName, @OrigTableFullName, @Identity, @ComputedColumns, @Defaults, @RemoteObjectID;
EXEC tSQLt.Private_MarkFakeTable @SchemaName, @TableName, @NewNameOfOriginalTable;
+
+ IF (@RemoteObjectID IS NOT NULL)
+ BEGIN
+ EXEC tSQLt.Private_CreateRemoteSysObjects @Instance = NULL, @Database = NULL;
+ END
+
END
---Build-
GO
diff --git a/Source/tSQLt.Private_AlterSysObjectForRemote.ssp.sql b/Source/tSQLt.Private_AlterSysObjectForRemote.ssp.sql
new file mode 100644
index 000000000..54ae020e5
--- /dev/null
+++ b/Source/tSQLt.Private_AlterSysObjectForRemote.ssp.sql
@@ -0,0 +1,49 @@
+IF OBJECT_ID('tSQLt.Private_AlterSysObjectForRemote') IS NOT NULL
+ DROP PROCEDURE tSQLt.Private_AlterSysObjectForRemote;
+GO
+---Build+
+CREATE PROCEDURE tSQLt.Private_AlterSysObjectForRemote
+ @Instance NVARCHAR(MAX) ,
+ @Database NVARCHAR(MAX) ,
+ @SysObject NVARCHAR(MAX) ,
+ @PrivateViewName NVARCHAR(MAX)
+AS
+ BEGIN
+ DECLARE @sql NVARCHAR(MAX);
+ SET @sql = 'ALTER VIEW tSQLt.' + @PrivateViewName + ' AS
+ SELECT ' +
+ CASE WHEN @SysObject = 'types' THEN '
+ name ,
+ system_type_id ,
+ user_type_id ,
+ CASE WHEN is_user_defined = 1 THEN 1
+ ELSE schema_id
+ END AS schema_id ,
+ principal_id ,
+ max_length ,
+ precision ,
+ scale ,
+ collation_name ,
+ is_nullable ,
+ is_user_defined ,
+ is_assembly_type ,
+ default_object_id ,
+ rule_object_id ,
+ is_table_type
+ ' ELSE '* ' END
+ + CASE WHEN CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR(MAX)) LIKE '9.%'
+ AND @SysObject = 'types' THEN ',0 is_table_type'
+ ELSE ''
+ END + ' FROM ' + COALESCE(QUOTENAME(@Instance) + '.', '')
+ + COALESCE(QUOTENAME(@Database) + '.', '') + 'sys.' + @SysObject
+ + ';';
+
+
+
+
+ EXEC (@sql);
+
+ RETURN 0;
+ END;
+---Build-
+GO
diff --git a/Source/tSQLt.Private_CreateFakeOfTable.ssp.sql b/Source/tSQLt.Private_CreateFakeOfTable.ssp.sql
index 55dbbd504..410e34a2f 100644
--- a/Source/tSQLt.Private_CreateFakeOfTable.ssp.sql
+++ b/Source/tSQLt.Private_CreateFakeOfTable.ssp.sql
@@ -7,12 +7,18 @@ CREATE PROCEDURE tSQLt.Private_CreateFakeOfTable
@OrigTableFullName NVARCHAR(MAX),
@Identity BIT,
@ComputedColumns BIT,
- @Defaults BIT
+ @Defaults BIT,
+ @RemoteObjectID INT
AS
BEGIN
+ IF (@RemoteObjectID IS NOT NULL)
+ BEGIN
+ EXEC tSQLt.Private_CreateRemoteUserDefinedDataTypes @RemoteObjectID = @RemoteObjectID
+ END
+
DECLARE @cmd NVARCHAR(MAX) =
(SELECT CreateTableStatement
- FROM tSQLt.Private_CreateFakeTableStatement(OBJECT_ID(@OrigTableFullName), @SchemaName+'.'+@TableName,@Identity,@ComputedColumns,@Defaults,0));
+ FROM tSQLt.Private_CreateFakeTableStatement(COALESCE(@RemoteObjectID, OBJECT_ID(@OrigTableFullName)), @SchemaName+'.'+@TableName,@Identity,@ComputedColumns,@Defaults,0));
EXEC (@cmd);
END;
---Build-
diff --git a/Source/tSQLt.Private_CreateFakeTableStatement.sfn.sql b/Source/tSQLt.Private_CreateFakeTableStatement.sfn.sql
index 7e3d17c58..7212ea713 100644
--- a/Source/tSQLt.Private_CreateFakeTableStatement.sfn.sql
+++ b/Source/tSQLt.Private_CreateFakeTableStatement.sfn.sql
@@ -30,7 +30,7 @@ RETURN
THEN ''
ELSE CASE WHEN @PreserveNOTNULL = 1 AND c.is_nullable = 0 THEN ' NOT NULL' ELSE ' NULL' END
END
- FROM sys.columns c
+ FROM tSQLt.Private_SysColumns c
CROSS APPLY tSQLt.Private_GetDataTypeOrComputedColumnDefinition(c.user_type_id, c.max_length, c.precision, c.scale, c.collation_name, c.object_id, c.column_id, @ComputedColumns) cc
CROSS APPLY tSQLt.Private_GetDefaultConstraintDefinition(c.object_id, c.column_id, @Defaults) AS dc
CROSS APPLY tSQLt.Private_GetIdentityDefinition(c.object_id, c.column_id, @Identity) AS id
diff --git a/Source/tSQLt.Private_CreateRemoteSysObjects.ssp.sql b/Source/tSQLt.Private_CreateRemoteSysObjects.ssp.sql
new file mode 100644
index 000000000..8cbb84a6d
--- /dev/null
+++ b/Source/tSQLt.Private_CreateRemoteSysObjects.ssp.sql
@@ -0,0 +1,52 @@
+IF OBJECT_ID('tSQLt.Private_CreateRemoteSysObjects') IS NOT NULL
+ DROP PROCEDURE tSQLt.Private_CreateRemoteSysObjects;
+GO
+---Build+
+CREATE PROCEDURE tSQLt.Private_CreateRemoteSysObjects
+ @Instance NVARCHAR(MAX) ,
+ @Database NVARCHAR(MAX)
+AS
+ BEGIN
+ DECLARE @SysObject NVARCHAR(MAX);
+ DECLARE @ViewName NVARCHAR(MAX);
+
+
+ DECLARE @SysObjects AS TABLE
+ (
+ SysObject NVARCHAR(MAX) ,
+ ViewName NVARCHAR(MAX)
+ );
+ INSERT INTO @SysObjects
+ VALUES ( 'types', 'Private_SysTypes' ),
+ ( 'computed_columns', 'Private_SysComputedColumns' ),
+ ( 'default_constraints', 'Private_SysDefaultConstraints' ),
+ ( 'identity_columns', 'Private_SysIdentityColumns' ),
+ ( 'columns', 'Private_SysColumns' ),
+ ( 'objects', 'Private_SysObjects' ),
+ ( 'schemas', 'Private_SysSchemas' );
+
+ DECLARE @cursor AS CURSOR;
+
+ SET @cursor = CURSOR FOR
+SELECT SysObject, ViewName
+ FROM @SysObjects;
+
+ OPEN @cursor;
+ FETCH NEXT FROM @cursor INTO @SysObject, @ViewName;
+
+ WHILE @@FETCH_STATUS = 0
+ BEGIN
+ EXEC tSQLt.Private_AlterSysObjectForRemote @Instance = @Instance,
+ @Database = @Database, @SysObject = @SysObject,
+ @PrivateViewName = @ViewName;
+
+ FETCH NEXT FROM @cursor INTO @SysObject, @ViewName;
+ END;
+
+ CLOSE @cursor;
+ DEALLOCATE @cursor;
+
+ RETURN 0;
+ END;
+---Build-
+GO
diff --git a/Source/tSQLt.Private_CreateRemoteUserDefinedDataTypes.ssp.sql b/Source/tSQLt.Private_CreateRemoteUserDefinedDataTypes.ssp.sql
new file mode 100644
index 000000000..ec805c1b5
--- /dev/null
+++ b/Source/tSQLt.Private_CreateRemoteUserDefinedDataTypes.ssp.sql
@@ -0,0 +1,58 @@
+IF OBJECT_ID('tSQLt.Private_CreateRemoteUserDefinedDataTypes') IS NOT NULL
+ DROP PROCEDURE tSQLt.Private_CreateRemoteUserDefinedDataTypes;
+GO
+---Build+
+CREATE PROCEDURE tSQLt.Private_CreateRemoteUserDefinedDataTypes @RemoteObjectID INT
+AS
+ BEGIN
+
+ DECLARE @UDDTs NVARCHAR(MAX) = '';
+
+ SELECT @UDDTs = @UDDTs + N'CREATE TYPE ' + QUOTENAME(sch.[name])
+ + N'.' + QUOTENAME(typ.[name]) + N' FROM ' + styp.[name]
+ + CASE WHEN typ.[system_type_id] IN ( 41, 42, 43, 106, 108,
+ 165, 167, 173, 175, 231,
+ 239 )
+ THEN N'('
+ + CASE WHEN typ.[max_length] = -1 -- for: VARCHAR, NVARCHAR, VARBINARY
+ THEN N'MAX'
+ WHEN typ.[system_type_id] IN ( 165, 167,
+ 173, 175 )
+ -- VARBINARY, VARCHAR, BINARY, CHAR
+ THEN CONVERT(NVARCHAR(5), typ.[max_length])
+ WHEN typ.[system_type_id] IN ( 231, 239 ) -- NVARCHAR, NCHAR
+ THEN CONVERT(NVARCHAR(5), ( typ.[max_length]
+ / 2 ))
+ WHEN typ.[system_type_id] IN ( 41, 42, 43 )
+ -- TIME, DATETIME2, DATETIMEOFFSET
+ THEN CONVERT(NVARCHAR(5), typ.[scale])
+ WHEN typ.[system_type_id] IN ( 106, 108 ) -- DECIMAL, NUMERIC
+ THEN CONVERT(NVARCHAR(5), typ.[precision])
+ + N', '
+ + CONVERT(NVARCHAR(5), typ.[scale])
+ END + N')'
+ ELSE N''
+ END + CASE typ.[is_nullable]
+ WHEN 1 THEN N' NULL'
+ ELSE ' NOT NULL'
+ END + N';'
+ FROM tSQLt.Private_SysTypes typ
+ INNER JOIN tSQLt.Private_SysSchemas sch ON sch.[schema_id] = typ.[schema_id]
+ INNER JOIN tSQLt.Private_SysTypes styp ON styp.[user_type_id] = typ.[system_type_id]
+ JOIN tSQLt.Private_SysColumns AS c ON c.user_type_id = typ.user_type_id
+ JOIN tSQLt.Private_SysObjects t ON t.object_id = c.object_id
+ WHERE typ.[is_user_defined] = 1
+ AND typ.[is_assembly_type] = 0
+ AND typ.[is_table_type] = 0
+ AND t.object_id = @RemoteObjectID
+ AND NOT EXISTS ( SELECT 1
+ FROM sys.types t
+ JOIN sys.schemas s ON s.schema_id = t.schema_id
+ AND t.[name] COLLATE SQL_Latin1_General_CP1_CI_AS = typ.[name] COLLATE SQL_Latin1_General_CP1_CI_AS
+ AND s.[name] COLLATE SQL_Latin1_General_CP1_CI_AS = sch.[name] COLLATE SQL_Latin1_General_CP1_CI_AS );
+
+ EXEC (@UDDTs);
+
+ END;
+---Build-
+GO
diff --git a/Source/tSQLt.Private_GetDataTypeOrComputedColumnDefinition.sfn.sql b/Source/tSQLt.Private_GetDataTypeOrComputedColumnDefinition.sfn.sql
index 50a397bb1..e06e9b50e 100644
--- a/Source/tSQLt.Private_GetDataTypeOrComputedColumnDefinition.sfn.sql
+++ b/Source/tSQLt.Private_GetDataTypeOrComputedColumnDefinition.sfn.sql
@@ -14,7 +14,7 @@ RETURN SELECT
' AS '+ cci.definition + CASE WHEN cci.is_persisted = 1 THEN ' PERSISTED' ELSE '' END AS ComputedColumnDefinition,
cci.object_id,
cci.column_id
- FROM sys.computed_columns cci
+ FROM tSQLt.Private_SysComputedColumns cci
)cc
ON cc.object_id = V.ObjectId
AND cc.column_id = V.ColumnId
diff --git a/Source/tSQLt.Private_GetDefaultConstraintDefinition.sfn.sql b/Source/tSQLt.Private_GetDefaultConstraintDefinition.sfn.sql
index 9c759c7a0..9ec2f30ff 100644
--- a/Source/tSQLt.Private_GetDefaultConstraintDefinition.sfn.sql
+++ b/Source/tSQLt.Private_GetDefaultConstraintDefinition.sfn.sql
@@ -9,7 +9,7 @@ RETURN SELECT
COALESCE(DefaultDefinition, '') AS DefaultDefinition
FROM (SELECT 1) X(X)
LEFT JOIN (SELECT 1 AS IsDefault,' DEFAULT '+ definition AS DefaultDefinition,parent_object_id,parent_column_id
- FROM sys.default_constraints
+ FROM tSQLt.Private_SysDefaultConstraints
)dc
ON dc.parent_object_id = @ObjectId
AND dc.parent_column_id = @ColumnId
diff --git a/Source/tSQLt.Private_GetIdentityDefinition.sfn.sql b/Source/tSQLt.Private_GetIdentityDefinition.sfn.sql
index 05cbf178e..5ec9831ff 100644
--- a/Source/tSQLt.Private_GetIdentityDefinition.sfn.sql
+++ b/Source/tSQLt.Private_GetIdentityDefinition.sfn.sql
@@ -12,7 +12,7 @@ RETURN SELECT
' IDENTITY(' + CAST(seed_value AS NVARCHAR(MAX)) + ',' + CAST(increment_value AS NVARCHAR(MAX)) + ')' AS IdentityDefinition,
object_id,
column_id
- FROM sys.identity_columns
+ FROM tSQLt.Private_SysIdentityColumns
) AS id
ON id.object_id = @ObjectId
AND id.column_id = @ColumnId
diff --git a/Source/tSQLt.Private_GetRemoteObjectId.ssp.sql b/Source/tSQLt.Private_GetRemoteObjectId.ssp.sql
new file mode 100644
index 000000000..aff4db86a
--- /dev/null
+++ b/Source/tSQLt.Private_GetRemoteObjectId.ssp.sql
@@ -0,0 +1,47 @@
+IF OBJECT_ID('tSQLt.Private_GetRemoteObjectId') IS NOT NULL
+ DROP PROCEDURE tSQLt.Private_GetRemoteObjectId;
+GO
+---Build+
+GO
+CREATE PROCEDURE tSQLt.Private_GetRemoteObjectId
+ @SynonymObjectId INT ,
+ @RemoteObjectId INT OUTPUT ,
+ @OrigTableFullName sysname OUTPUT
+AS
+ BEGIN
+ DECLARE @Database NVARCHAR(MAX);
+ DECLARE @Instance NVARCHAR(MAX);
+
+ SELECT @OrigTableFullName = S.base_object_name ,
+ @Database = PARSENAME(S.base_object_name, 3) ,
+ @Instance = PARSENAME(S.base_object_name, 4)
+ FROM sys.synonyms AS S
+ WHERE S.object_id = @SynonymObjectId;
+
+ DECLARE @RemotePath NVARCHAR(MAX) = COALESCE(QUOTENAME(PARSENAME(@OrigTableFullName,
+ 4)) + '.', '')
+ + QUOTENAME(PARSENAME(@OrigTableFullName, 3));
+ DECLARE @Cmd NVARCHAR(MAX);
+ DECLARE @params NVARCHAR(MAX) = '@RemoteObjectID INT OUT, @OrigTableFullName NVARCHAR(MAX)';
+ SET @Cmd = '
+ SELECT @RemoteObjectID = o.object_id
+ FROM ' + @RemotePath + '.sys.objects o
+ JOIN ' + @RemotePath
+ + '.sys.schemas s ON s.schema_id = o.schema_id
+ WHERE s.name = PARSENAME(@OrigTableFullName, 2)
+ AND o.name = PARSENAME(@OrigTableFullName, 1)
+ AND o.type IN ( ''U'', ''V'' );';
+
+ EXEC sp_executesql @Cmd, @params, @RemoteObjectID OUT,
+ @OrigTableFullName;
+
+
+ IF ( @RemoteObjectID > 0 )
+ BEGIN
+ EXEC tSQLt.Private_CreateRemoteSysObjects @Instance = @Instance,
+ @Database = @Database;
+ END;
+ END;
+GO
+---Build-
+GO
diff --git a/Source/tSQLt.Private_SysColumns.svw.sql b/Source/tSQLt.Private_SysColumns.svw.sql
new file mode 100644
index 000000000..e594f34bd
--- /dev/null
+++ b/Source/tSQLt.Private_SysColumns.svw.sql
@@ -0,0 +1,8 @@
+IF OBJECT_ID('tSQLt.Private_SysColumns') IS NOT NULL DROP VIEW tSQLt.Private_SysColumns;
+GO
+---Build+
+GO
+CREATE VIEW tSQLt.Private_SysColumns AS SELECT * FROM sys.columns AS cc;
+GO
+---Build-
+GO
diff --git a/Source/tSQLt.Private_SysComputedColumns.svw.sql b/Source/tSQLt.Private_SysComputedColumns.svw.sql
new file mode 100644
index 000000000..13414a842
--- /dev/null
+++ b/Source/tSQLt.Private_SysComputedColumns.svw.sql
@@ -0,0 +1,8 @@
+IF OBJECT_ID('tSQLt.Private_SysComputedColumns') IS NOT NULL DROP VIEW tSQLt.Private_SysComputedColumns;
+GO
+---Build+
+GO
+CREATE VIEW tSQLt.Private_SysComputedColumns AS SELECT * FROM sys.computed_columns AS cc;
+GO
+---Build-
+GO
diff --git a/Source/tSQLt.Private_SysDefaultConstraints.svw.sql b/Source/tSQLt.Private_SysDefaultConstraints.svw.sql
new file mode 100644
index 000000000..e6250e2bc
--- /dev/null
+++ b/Source/tSQLt.Private_SysDefaultConstraints.svw.sql
@@ -0,0 +1,8 @@
+IF OBJECT_ID('tSQLt.Private_SysDefaultConstraints') IS NOT NULL DROP VIEW tSQLt.Private_SysDefaultConstraints;
+GO
+---Build+
+GO
+CREATE VIEW tSQLt.Private_SysDefaultConstraints AS SELECT * FROM sys.default_constraints AS cc;
+GO
+---Build-
+GO
diff --git a/Source/tSQLt.Private_SysIdentityColumns.svw.sql b/Source/tSQLt.Private_SysIdentityColumns.svw.sql
new file mode 100644
index 000000000..202df612e
--- /dev/null
+++ b/Source/tSQLt.Private_SysIdentityColumns.svw.sql
@@ -0,0 +1,8 @@
+IF OBJECT_ID('tSQLt.Private_SysIdentityColumns') IS NOT NULL DROP VIEW tSQLt.Private_SysIdentityColumns;
+GO
+---Build+
+GO
+CREATE VIEW tSQLt.Private_SysIdentityColumns AS SELECT * FROM sys.identity_columns AS cc;
+GO
+---Build-
+GO
diff --git a/Source/tSQLt.Private_SysObjects.svw.sql b/Source/tSQLt.Private_SysObjects.svw.sql
new file mode 100644
index 000000000..7a8240f2f
--- /dev/null
+++ b/Source/tSQLt.Private_SysObjects.svw.sql
@@ -0,0 +1,8 @@
+IF OBJECT_ID('tSQLt.Private_SysObjects') IS NOT NULL DROP VIEW tSQLt.Private_SysObjects;
+GO
+---Build+
+GO
+CREATE VIEW tSQLt.Private_SysObjects AS SELECT * FROM sys.objects AS cc;
+GO
+---Build-
+GO
diff --git a/Source/tSQLt.Private_SysSchemas.svw.sql b/Source/tSQLt.Private_SysSchemas.svw.sql
new file mode 100644
index 000000000..2ef39844a
--- /dev/null
+++ b/Source/tSQLt.Private_SysSchemas.svw.sql
@@ -0,0 +1,8 @@
+IF OBJECT_ID('tSQLt.Private_SysSchemas') IS NOT NULL DROP VIEW tSQLt.Private_SysSchemas;
+GO
+---Build+
+GO
+CREATE VIEW tSQLt.Private_SysSchemas AS SELECT * FROM sys.schemas AS cc;
+GO
+---Build-
+GO
diff --git a/Source/tSQLt.Private_ValidateSynonymCompatibilityWithFakeTable.ssp.sql b/Source/tSQLt.Private_ValidateSynonymCompatibilityWithFakeTable.ssp.sql
new file mode 100644
index 000000000..84aa26d6b
--- /dev/null
+++ b/Source/tSQLt.Private_ValidateSynonymCompatibilityWithFakeTable.ssp.sql
@@ -0,0 +1,23 @@
+IF OBJECT_ID('tSQLt.Private_ValidateSynonymCompatibilityWithFakeTable') IS NOT NULL
+ DROP PROCEDURE tSQLt.Private_ValidateSynonymCompatibilityWithFakeTable;
+GO
+---Build+
+GO
+CREATE PROCEDURE tSQLt.Private_ValidateSynonymCompatibilityWithFakeTable
+ @TableName sysname ,
+ @SchemaName sysname ,
+ @OrigTableFullName sysname
+AS
+ BEGIN
+
+ IF NOT EXISTS ( SELECT 1
+ FROM tSQLt.Private_SysObjects o
+ JOIN tSQLt.Private_SysSchemas s ON s.schema_id = o.schema_id
+ WHERE o.type IN ( 'U', 'V' )
+ AND o.name = PARSENAME(@OrigTableFullName, 1)
+ AND s.name = PARSENAME(@OrigTableFullName, 2) )
+ 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);
+ END;
+ END;
+GO
diff --git a/TestUtil/BuildOrder.txt b/TestUtil/BuildOrder.txt
index ac9be7dd3..0a483ed88 100644
--- a/TestUtil/BuildOrder.txt
+++ b/TestUtil/BuildOrder.txt
@@ -1,4 +1,4 @@
tSQLt_testutil.class.sql
../Build/temp/tSQLtBuild/Tests/CreateTestUtilAssembly.sql
../Build/temp/tSQLtBuild/Tests/GetUnsignedEmptyBytes.sql
-tSQLtTestUtilCLR_CreateItems.sql
+tSQLtTestUtilCLR_CreateItems.sql
\ No newline at end of file
diff --git a/Tests/FakeTableTests.class.sql b/Tests/FakeTableTests.class.sql
index a64f8d44d..e624dc483 100644
--- a/Tests/FakeTableTests.class.sql
+++ b/Tests/FakeTableTests.class.sql
@@ -171,6 +171,18 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test FakeTable works with remote 2 part names in first parameter]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.TempTable1(i INT);
+ CREATE SYNONYM FakeTableTests.TempTable1 FOR tSQLt_dev_remote.dbo.TempTable1;
+
+ EXEC tSQLt.FakeTable 'FakeTableTests.TempTable1';
+
+ EXEC FakeTableTests.AssertTableIsNewObjectThatHasNoConstraints 'FakeTableTests.TempTable1';
+END;
+GO
+
CREATE PROC FakeTableTests.[test a faked table has no check constraints]
AS
BEGIN
@@ -183,6 +195,19 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test a faked remote table has no check constraints]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.TempTable1(i INT CHECK(i > 5));
+ CREATE SYNONYM FakeTableTests.TempTable1 FOR tSQLt_dev_remote.dbo.TempTable1;
+
+ EXEC tSQLt.FakeTable 'FakeTableTests.TempTable1';
+
+ EXEC FakeTableTests.AssertTableIsNewObjectThatHasNoConstraints 'FakeTableTests.TempTable1';
+ INSERT INTO FakeTableTests.TempTable1 (i) VALUES (5);
+END;
+GO
+
CREATE PROC FakeTableTests.[test a faked table has no foreign keys]
AS
BEGIN
@@ -196,6 +221,22 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test a faked remote table has no foreign keys]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.TempTable0(i INT PRIMARY KEY);
+ CREATE TABLE tSQLt_dev_remote.dbo.TempTable1(i INT REFERENCES tSQLt_dev_remote.dbo.TempTable0(i));
+
+ CREATE SYNONYM FakeTableTests.TempTable0 FOR tSQLt_dev_remote.dbo.TempTable0;
+ CREATE SYNONYM FakeTableTests.TempTable1 FOR tSQLt_dev_remote.dbo.TempTable1;
+
+ EXEC tSQLt.FakeTable 'FakeTableTests.TempTable1';
+
+ EXEC FakeTableTests.AssertTableIsNewObjectThatHasNoConstraints 'FakeTableTests.TempTable1';
+ INSERT INTO FakeTableTests.TempTable1 (i) VALUES (5);
+END;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable: a faked table has any defaults removed]
AS
BEGIN
@@ -214,6 +255,25 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable: a faked table has any defaults removed]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.TempTable1(i INT DEFAULT(77));
+ CREATE SYNONYM FakeTableTests.TempTable1 FOR tSQLt_dev_remote.dbo.TempTable1;
+
+ 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;
+
+ EXEC tSQLt.AssertEquals NULL, @value;
+END;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable: a faked table has any unique constraints removed]
AS
BEGIN
@@ -227,6 +287,20 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable: a faked table has any unique constraints removed]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.TempTable1(i INT UNIQUE);
+ CREATE SYNONYM FakeTableTests.TempTable1 FOR tSQLt_dev_remote.dbo.TempTable1;
+
+ 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;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable: a faked table has any unique indexes removed]
AS
BEGIN
@@ -241,6 +315,21 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable: a faked table has any unique indexes removed]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.TempTable1(i INT);
+ CREATE UNIQUE INDEX UQ_tSQLt_test_TempTable1_i ON tSQLt_dev_remote.dbo.TempTable1(i);
+ CREATE SYNONYM FakeTableTests.TempTable1 FOR tSQLt_dev_remote.dbo.TempTable1;
+
+ 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;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable: a faked table has any not null constraints removed]
AS
BEGIN
@@ -253,6 +342,19 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable: a faked table has any not null constraints removed]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.TempTable1(i INT NOT NULL);
+ CREATE SYNONYM FakeTableTests.TempTable1 FOR tSQLt_dev_remote.dbo.TempTable1;
+
+ EXEC tSQLt.FakeTable 'FakeTableTests.TempTable1';
+
+ EXEC FakeTableTests.AssertTableIsNewObjectThatHasNoConstraints 'FakeTableTests.TempTable1';
+ INSERT INTO FakeTableTests.TempTable1 (i) VALUES (NULL);
+END;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable works on referencedTo tables]
AS
BEGIN
@@ -274,6 +376,27 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable works on referencedTo tables]
+AS
+BEGIN
+
+ CREATE TABLE tSQLt_dev_remote.dbo.tst1(i INT PRIMARY KEY);
+ CREATE SYNONYM FakeTableTests.tst1 FOR tSQLt_dev_remote.dbo.tst1;
+
+ CREATE TABLE tSQLt_dev_remote.dbo.tst2(i INT PRIMARY KEY, tst1i INT REFERENCES tSQLt_dev_remote.dbo.tst1(i));
+
+ BEGIN TRY
+ EXEC tSQLt.FakeTable 'FakeTableTests.tst1';
+ END TRY
+ BEGIN CATCH
+ DECLARE @ErrorMessage NVARCHAR(MAX);
+ SELECT @ErrorMessage = ERROR_MESSAGE()+'{'+ISNULL(ERROR_PROCEDURE(),'NULL')+','+ISNULL(CAST(ERROR_LINE() AS VARCHAR),'NULL')+'}';
+
+ EXEC tSQLt.Fail 'FakeTable threw unexpected error:', @ErrorMessage;
+ END CATCH;
+END;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable doesn't produce output]
AS
BEGIN
@@ -295,6 +418,28 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable doesn't produce output]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.tst(i INT);
+ CREATE SYNONYM FakeTableTests.tst FOR tSQLt_dev_remote.dbo.tst;
+
+ EXEC tSQLt.CaptureOutput 'EXEC tSQLt.FakeTable ''FakeTableTests.tst''';
+
+ SELECT OutputText
+ INTO #actual
+ FROM tSQLt.CaptureOutputLog;
+
+ SELECT TOP(0) *
+ INTO #expected
+ FROM #actual;
+
+ INSERT INTO #expected(OutputText)VALUES(NULL);
+
+ EXEC tSQLt.AssertEqualsTable '#expected','#actual';
+END;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable doesn't preserve identity if @Identity parameter is not specified]
AS
BEGIN
@@ -311,6 +456,21 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable doesn't preserve identity if @Identity parameter is not specified]
+AS
+BEGIN
+
+ CREATE TABLE tSQLt_dev_remote.dbo.tst1(i INT IDENTITY(1,1));
+ CREATE SYNONYM FakeTableTests.tst1 FOR tSQLt_dev_remote.dbo.tst1;
+
+
+ EXEC tSQLt.FakeTable 'FakeTableTests.tst1';
+
+ EXEC('INSERT INTO FakeTableTests.tst1(i) VALUES(1)');
+
+END;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable doesn't preserve identity if @identity parameter is 0]
AS
BEGIN
@@ -327,6 +487,19 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable doesn't preserve identity if @identity parameter is 0]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.tst1(i INT IDENTITY(1,1));
+ CREATE SYNONYM FakeTableTests.tst1 FOR tSQLt_dev_remote.dbo.tst1;
+
+ EXEC tSQLt.FakeTable 'FakeTableTests.tst1',@Identity=0;
+
+ EXEC('INSERT INTO FakeTableTests.tst1(i) VALUES(1)');
+
+END;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable preserves identity if @identity parameter is 1]
AS
BEGIN
@@ -343,6 +516,27 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable preserves identity if @identity parameter is 1]
+AS
+BEGIN
+
+ CREATE TABLE tSQLt_dev_remote.dbo.tst1 ( i INT IDENTITY(1, 1) );
+ CREATE SYNONYM FakeTableTests.tst1 FOR tSQLt_dev_remote.dbo.tst1;
+
+
+ EXEC tSQLt.FakeTable 'FakeTableTests.tst1', @Identity = 1;
+ BEGIN TRY
+ EXEC('INSERT INTO FakeTableTests.tst1(i) VALUES(1)');
+ EXEC tSQLt.Fail @Message0 = N'Fake table has no identity column!';
+ END TRY
+ BEGIN CATCH
+ DECLARE @ErrorMessage NVARCHAR(4000);
+ SET @ErrorMessage = ERROR_MESSAGE();
+ EXEC tSQLt.AssertEquals @Expected = 'Cannot insert explicit value for identity column in table ''tst1'' when IDENTITY_INSERT is set to OFF.',
+ @Actual = @ErrorMessage;
+ END CATCH
+END;
+GO
CREATE PROC FakeTableTests.[test FakeTable works with more than one column]
AS
@@ -390,6 +584,37 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable works with more than one column]
+AS
+BEGIN
+
+ CREATE TABLE tSQLt_dev_remote.dbo.tst1(i1 INT,i2 INT,i3 INT,i4 INT,i5 INT,i6 INT,i7 INT,i8 INT);
+ CREATE SYNONYM FakeTableTests.tst1 FOR tSQLt_dev_remote.dbo.tst1;
+
+ CREATE TABLE #Actual (column_id INT, [name] NVARCHAR(500));
+ CREATE TABLE #Expected (column_id INT, [name] NVARCHAR(500));
+
+ INSERT INTO #Expected
+ SELECT column_id ,
+ c.name
+ FROM tSQLt_dev_remote.sys.columns c
+ JOIN tSQLt_dev_remote.sys.tables t ON t.object_id = c.object_id
+ JOIN tSQLt_dev_remote.sys.schemas s ON s.schema_id = t.schema_id
+ WHERE t.name = 'tst1'
+ AND s.name = 'dbo';
+
+ EXEC tSQLt.FakeTable 'FakeTableTests.tst1';
+
+ INSERT INTO #Actual
+ SELECT column_id ,
+ name
+ FROM sys.columns
+ WHERE object_id = OBJECT_ID('FakeTableTests.tst1');
+
+ EXEC tSQLt.AssertEqualsTable '#Expected', '#Actual';
+END;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable works with ugly column and table names]
AS
BEGIN
@@ -412,6 +637,37 @@ BEGIN
EXEC tSQLt.AssertEqualsTable '#Expected','#Actual';
END;
GO
+
+CREATE PROC FakeTableTests.[test remote FakeTable works with ugly column and table names]
+AS
+BEGIN
+
+ CREATE TABLE tSQLt_dev_remote.dbo.[tst!@#$%^&*()_+ 1]([col!@#$%^&*()_+ 1] INT);
+ CREATE SYNONYM FakeTableTests.[tst!@#$%^&*()_+ 1] FOR tSQLt_dev_remote.dbo.[tst!@#$%^&*()_+ 1];
+
+ CREATE TABLE #Actual (column_id INT, [name] NVARCHAR(500));
+ CREATE TABLE #Expected (column_id INT, [name] NVARCHAR(500));
+
+ INSERT INTO #Expected
+ SELECT column_id ,
+ c.name
+ FROM tSQLt_dev_remote.sys.columns c
+ JOIN tSQLt_dev_remote.sys.tables t ON t.object_id = c.object_id
+ JOIN tSQLt_dev_remote.sys.schemas s ON s.schema_id = t.schema_id
+ WHERE t.name = 'tst!@#$%^&*()_+ 1'
+ AND s.name = 'dbo';
+
+ EXEC tSQLt.FakeTable 'FakeTableTests.[tst!@#$%^&*()_+ 1]';
+
+ INSERT INTO #Actual
+ SELECT column_id ,
+ name
+ FROM sys.columns
+ WHERE object_id = OBJECT_ID('FakeTableTests.[tst!@#$%^&*()_+ 1]');
+
+ EXEC tSQLt.AssertEqualsTable '#Expected', '#Actual';
+END;
+GO
CREATE PROC FakeTableTests.[test FakeTable preserves identity base and step-size]
AS
@@ -436,6 +692,29 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable preserves identity base and step-size]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.tst1 (i INT IDENTITY(42,13));
+ CREATE SYNONYM FakeTableTests.tst1 FOR tSQLt_dev_remote.dbo.tst1;
+
+ INSERT INTO FakeTableTests.tst1 DEFAULT VALUES;
+ INSERT INTO FakeTableTests.tst1 DEFAULT VALUES;
+
+ SELECT i
+ INTO #Expected
+ FROM FakeTableTests.tst1;
+
+ EXEC tSQLt.FakeTable 'FakeTableTests.tst1',@Identity=1;
+
+ INSERT INTO FakeTableTests.tst1 DEFAULT VALUES;
+ INSERT INTO FakeTableTests.tst1 DEFAULT VALUES;
+
+ EXEC tSQLt.AssertEqualsTable '#Expected', 'FakeTableTests.tst1';
+
+END;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable preserves data type of identity column with @Identity=0]
AS
BEGIN
@@ -460,6 +739,36 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable preserves data type of identity column with @Identity=0]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.tst1 ( i INT );
+ CREATE SYNONYM FakeTableTests.tst1 FOR tSQLt_dev_remote.dbo.tst1;
+
+ CREATE TABLE #Expected(type_name NVARCHAR(500));
+ CREATE TABLE #Actual (type_name NVARCHAR(500));
+
+ INSERT INTO #Expected
+ SELECT tp.name type_name
+ FROM tSQLt_dev_remote.sys.columns c
+ JOIN tSQLt_dev_remote.sys.types tp ON tp.user_type_id = c.user_type_id
+ JOIN tSQLt_dev_remote.sys.tables t ON t.object_id = c.object_id
+ JOIN tSQLt_dev_remote.sys.schemas s ON s.schema_id = t.schema_id
+ WHERE t.name = 'tst1'
+ AND s.name = 'dbo';
+
+ EXEC tSQLt.FakeTable 'FakeTableTests.tst1', @Identity = 0;
+
+ INSERT INTO #Actual
+ SELECT TYPE_NAME(user_type_id) type_name
+ FROM sys.columns
+ WHERE object_id = OBJECT_ID('FakeTableTests.tst1');
+
+ EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'
+
+END;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable preserves data type of identity column with @Identity=1]
AS
BEGIN
@@ -484,6 +793,37 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable preserves data type of identity column with @Identity=1]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.tst1 ( i [DECIMAL](4) IDENTITY(1,1) );
+ CREATE SYNONYM FakeTableTests.tst1 FOR tSQLt_dev_remote.dbo.tst1;
+
+ CREATE TABLE #Expected(type_name NVARCHAR(500), max_length INT, precision INT, scale INT);
+ CREATE TABLE #Actual(type_name NVARCHAR(500), max_length INT, precision INT, scale INT);
+
+ INSERT INTO #Expected
+ SELECT tp.name type_name, c.max_length, c.precision, c.scale
+ FROM tSQLt_dev_remote.sys.columns c
+ JOIN tSQLt_dev_remote.sys.types tp ON tp.user_type_id = c.user_type_id
+ JOIN tSQLt_dev_remote.sys.tables t ON t.object_id = c.object_id
+ JOIN tSQLt_dev_remote.sys.schemas s ON s.schema_id = t.schema_id
+ WHERE t.name = 'tst1'
+ AND s.name = 'dbo';
+
+
+ EXEC tSQLt.FakeTable 'FakeTableTests.tst1',@Identity = 1;
+
+ INSERT INTO #Actual
+ SELECT TYPE_NAME(user_type_id) type_name,max_length,precision,scale
+ FROM sys.columns
+ WHERE object_id = OBJECT_ID('FakeTableTests.tst1');
+
+ EXEC tSQLt.AssertEqualsTable '#Expected','#Actual';
+
+END;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable works if IDENTITYCOL is not the first column (with @Identity=1)]
AS
BEGIN
@@ -508,6 +848,42 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable works if IDENTITYCOL is not the first column (with @Identity=1)]
+AS
+BEGIN
+
+ CREATE TABLE tSQLt_dev_remote.dbo.tst1(x INT, i INT IDENTITY(1,1), y VARCHAR(30));
+ CREATE TABLE #Actual
+ (
+ name VARCHAR(500) ,
+ is_identity BIT
+ );
+ CREATE TABLE #Expected
+ (
+ name VARCHAR(500) ,
+ is_identity BIT
+ );
+ INSERT INTO #Expected
+ SELECT c.name, is_identity
+ FROM tSQLt_dev_remote.sys.columns c
+ JOIN tSQLt_dev_remote.sys.tables t ON t.object_id = c.object_id
+ JOIN tSQLt_dev_remote.sys.schemas s ON s.schema_id = t.schema_id
+ WHERE t.name = 'tst1' AND s.name = 'dbo';
+
+ CREATE SYNONYM dbo.tst1 FOR tSQLt_dev_remote.dbo.tst1;
+
+ EXEC tSQLt.FakeTable 'dbo.tst1',@Identity = 1;
+
+ INSERT INTO #Actual
+ SELECT name, is_identity
+ FROM sys.columns
+ WHERE object_id = OBJECT_ID('dbo.tst1');
+
+ EXEC tSQLt.AssertEqualsTable '#Expected','#Actual';
+
+END;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable works if there is no IDENTITYCOL and @Identity = 1]
AS
BEGIN
@@ -532,33 +908,92 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable works if there is no IDENTITYCOL and @Identity = 1]
+AS
+BEGIN
+
+ CREATE TABLE tSQLt_dev_remote.dbo.tst1(x INT, y VARCHAR(30));
+ CREATE SYNONYM dbo.tst1 FOR tSQLt_dev_remote.dbo.tst1;
+
+ CREATE TABLE #Actual
+ (
+ name VARCHAR(500) ,
+ is_identity BIT
+ );
+ CREATE TABLE #Expected
+ (
+ name VARCHAR(500) ,
+ is_identity BIT
+ );
+ INSERT INTO #Expected
+ SELECT c.name, is_identity
+ FROM tSQLt_dev_remote.sys.columns c
+ JOIN tSQLt_dev_remote.sys.tables t ON t.object_id = c.object_id
+ JOIN tSQLt_dev_remote.sys.schemas s ON s.schema_id = t.schema_id
+ WHERE t.name = 'tst1' AND s.name = 'dbo';
+
+ EXEC tSQLt.FakeTable 'dbo.tst1',@Identity = 1;
+
+ INSERT INTO #Actual
+ SELECT name, is_identity
+ FROM sys.columns
+ WHERE object_id = OBJECT_ID('dbo.tst1');
+
+ EXEC tSQLt.AssertEqualsTable '#Expected','#Actual';
+
+END;
+GO
+
CREATE PROC FakeTableTests.AssertTableStructureBeforeAndAfterCommandForComputedCols
@TableName NVARCHAR(MAX),
@Cmd NVARCHAR(MAX),
@ClearComputedCols INT
AS
BEGIN
+
+ DECLARE @Database NVARCHAR(MAX),
+ @Instance NVARCHAR(MAX),
+ @Schema NVARCHAR(MAX),
+ @Table NVARCHAR(MAX);
+
+ SELECT @Instance = PARSENAME(S.base_object_name, 4),
+ @Database = PARSENAME(S.base_object_name, 3),
+ @Schema = PARSENAME(S.base_object_name, 2),
+ @Table = PARSENAME(S.base_object_name, 1)
+ FROM sys.synonyms AS S
+ WHERE S.object_id = OBJECT_ID(@TableName);
+
+ IF (@Database IS NOT NULL)
+ BEGIN
+ EXEC tSQLt.Private_CreateRemoteSysObjects @Instance = @Instance, @Database = @Database;
+ END
+ CREATE TABLE #Expected(column_id INT, IsComputedColumn BIT, is_persisted BIT, name NVARCHAR(MAX), definition NVARCHAR(MAX), user_type_id INT)
+ CREATE TABLE #Actual(column_id INT, IsComputedColumn BIT, is_persisted BIT, name NVARCHAR(MAX), definition NVARCHAR(MAX), user_type_id INT)
+
+ INSERT INTO #Expected
SELECT c.column_id, CASE WHEN cc.column_id IS NULL THEN 0 ELSE 1 END AS IsComputedColumn, cc.is_persisted, c.name, cc.definition, c.user_type_id
- INTO #Expected
- FROM sys.columns c
- LEFT OUTER JOIN sys.computed_columns cc ON cc.object_id = c.object_id
+ FROM tSQLt.Private_SysColumns c
+ JOIN tSQLt.Private_SysObjects o ON o.object_id = c.object_id
+ JOIN tSQLt.Private_SysSchemas s ON s.schema_id = o.schema_id
+ LEFT OUTER JOIN tSQLt.Private_SysComputedColumns cc ON cc.object_id = c.object_id
AND cc.column_id = c.column_id
AND @ClearComputedCols = 0
- WHERE c.object_id = OBJECT_ID('dbo.tst1');
+ WHERE o.name = COALESCE(@Table,PARSENAME(@TableName, 1)) AND s.name = COALESCE(@Schema, PARSENAME(@TableName, 2));
EXEC (@Cmd);
-
+
+ INSERT INTO #Actual
SELECT c.column_id, CASE WHEN cc.column_id IS NULL THEN 0 ELSE 1 END AS IsComputedColumn, cc.is_persisted, c.name, cc.definition, c.user_type_id
- INTO #Actual
FROM sys.columns c
LEFT OUTER JOIN sys.computed_columns cc ON cc.object_id = c.object_id
AND cc.column_id = c.column_id
- WHERE c.object_id = OBJECT_ID('dbo.tst1');
+ WHERE c.object_id = OBJECT_ID(@TableName);
EXEC tSQLt.AssertEqualsTable '#Expected','#Actual';
END;
GO
+
CREATE PROC FakeTableTests.AssertTableStructureBeforeAndAfterCommandIsSameForComputedCols
@TableName NVARCHAR(MAX),
@Cmd NVARCHAR(MAX)
@@ -588,6 +1023,16 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable preserves computed columns if @ComputedColumns = 1]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.tst1 (x INT, y AS x + 5 PERSISTED);
+ CREATE SYNONYM FakeTableTests.tst1 FOR tSQLt_dev_remote.dbo.tst1;
+
+ EXEC FakeTableTests.AssertTableStructureBeforeAndAfterCommandIsSameForComputedCols 'FakeTableTests.tst1', 'EXEC tSQLt.FakeTable ''FakeTableTests.tst1'', @ComputedColumns = 1;';
+END;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable preserves persisted computed columns if @ComputedColumns = 1]
AS
BEGIN
@@ -599,6 +1044,16 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable preserves persisted computed columns if @ComputedColumns = 1]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.tst1 (x INT, y AS x + 5 PERSISTED);
+ CREATE SYNONYM FakeTableTests.tst1 FOR tSQLt_dev_remote.dbo.tst1;
+
+ EXEC FakeTableTests.AssertTableStructureBeforeAndAfterCommandIsSameForComputedCols 'FakeTableTests.tst1', 'EXEC tSQLt.FakeTable ''FakeTableTests.tst1'', @ComputedColumns = 1;';
+END;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable does not preserve persisted computed columns if @ComputedColumns = 0]
AS
BEGIN
@@ -610,6 +1065,16 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable does not preserve persisted computed columns if @ComputedColumns = 0]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.tst1 (x INT, y AS x + 5 PERSISTED);
+ CREATE SYNONYM FakeTableTests.tst1 FOR tSQLt_dev_remote.dbo.tst1;
+
+ EXEC FakeTableTests.AssertTableAfterCommandHasNoComputedCols 'FakeTableTests.tst1', 'EXEC tSQLt.FakeTable ''FakeTableTests.tst1'', @ComputedColumns = 0;';
+END;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable does not preserve persisted computed columns if @ComputedColumns is not specified]
AS
BEGIN
@@ -621,6 +1086,16 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable does not preserve persisted computed columns if @ComputedColumns is not specified]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.tst1 (x INT, y AS x + 5 PERSISTED);
+ CREATE SYNONYM FakeTableTests.tst1 FOR tSQLt_dev_remote.dbo.tst1;
+
+ EXEC FakeTableTests.AssertTableAfterCommandHasNoComputedCols 'FakeTableTests.tst1', 'EXEC tSQLt.FakeTable ''FakeTableTests.tst1'';';
+END;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable preserves multiple mixed persisted computed columns if @ComputedColumns = 1]
AS
BEGIN
@@ -632,28 +1107,62 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable preserves multiple mixed persisted computed columns if @ComputedColumns = 1]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.tst1 (NotComputed INT, ComputedAndPersisted AS (NotComputed + 5) PERSISTED, ComputedNotPersisted AS (NotComputed + 7), AnotherComputed AS (GETDATE()));
+ CREATE SYNONYM FakeTableTests.tst1 FOR tSQLt_dev_remote.dbo.tst1;
+
+ EXEC FakeTableTests.AssertTableStructureBeforeAndAfterCommandIsSameForComputedCols 'FakeTableTests.tst1', 'EXEC tSQLt.FakeTable ''FakeTableTests.tst1'', @ComputedColumns = 1;';
+END;
+GO
+
CREATE PROC FakeTableTests.AssertTableStructureBeforeAndAfterCommandForDefaults
@TableName NVARCHAR(MAX),
@Cmd NVARCHAR(MAX),
@ClearDefaults INT
AS
BEGIN
+
+ DECLARE @Database NVARCHAR(MAX),
+ @Instance NVARCHAR(MAX),
+ @Schema NVARCHAR(MAX),
+ @Table NVARCHAR(MAX);
+
+ SELECT @Instance = PARSENAME(S.base_object_name, 4),
+ @Database = PARSENAME(S.base_object_name, 3),
+ @Schema = PARSENAME(S.base_object_name, 2),
+ @Table = PARSENAME(S.base_object_name, 1)
+ FROM sys.synonyms AS S
+ WHERE S.object_id = OBJECT_ID(@TableName);
+
+ IF (@Database IS NOT NULL)
+ BEGIN
+ EXEC tSQLt.Private_CreateRemoteSysObjects @Instance = @Instance, @Database = @Database;
+ END
+ CREATE TABLE #Expected(column_id INT, IsComputedColumn BIT, name NVARCHAR(MAX), definition NVARCHAR(MAX), user_type_id INT)
+ CREATE TABLE #Actual(column_id INT, IsComputedColumn BIT, name NVARCHAR(MAX), definition NVARCHAR(MAX), user_type_id INT)
+
+ INSERT INTO #Expected
SELECT c.column_id, CASE WHEN dc.parent_column_id IS NULL THEN 0 ELSE 1 END AS IsComputedColumn, c.name, dc.definition, c.user_type_id
- INTO #Expected
- FROM sys.columns c
- LEFT OUTER JOIN sys.default_constraints dc ON dc.parent_object_id = c.object_id
+ FROM tSQLt.Private_SysColumns c
+ JOIN tSQLt.Private_SysObjects o ON o.object_id = c.object_id
+ JOIN tSQLt.Private_SysSchemas s ON s.schema_id = o.schema_id
+ LEFT OUTER JOIN tSQLt.Private_SysDefaultConstraints dc ON dc.parent_object_id = c.object_id
AND dc.parent_column_id = c.column_id
AND @ClearDefaults = 0
- WHERE c.object_id = OBJECT_ID('dbo.tst1');
-
+ WHERE o.name = COALESCE(@Table,PARSENAME(@TableName, 1)) AND s.name = COALESCE(@Schema, PARSENAME(@TableName, 2));
+
+ IF NOT EXISTS (SELECT 1 FROM #Expected) EXEC tSQLt.Fail;
+
EXEC (@Cmd);
+ INSERT INTO #Actual
SELECT c.column_id, CASE WHEN dc.parent_column_id IS NULL THEN 0 ELSE 1 END AS IsComputedColumn, c.name, dc.definition, c.user_type_id
- INTO #Actual
FROM sys.columns c
LEFT OUTER JOIN sys.default_constraints dc ON dc.parent_object_id = c.object_id
AND dc.parent_column_id = c.column_id
- WHERE c.object_id = OBJECT_ID('dbo.tst1');
+ WHERE c.object_id = OBJECT_ID(@TableName);
EXEC tSQLt.AssertEqualsTable '#Expected','#Actual';
END;
@@ -688,6 +1197,17 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remoteFakeTable does not preserve defaults if @Defaults is not specified]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.tst1 (x INT DEFAULT(5));
+
+ CREATE SYNONYM FakeTableTests.tst1 FOR tSQLt_dev_remote.dbo.tst1;
+
+ EXEC FakeTableTests.AssertTableAfterCommandHasNoDefaults 'FakeTableTests.tst1', 'EXEC tSQLt.FakeTable ''FakeTableTests.tst1''';
+END;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable does not preserve defaults if @Defaults = 0]
AS
BEGIN
@@ -699,6 +1219,17 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable does not preserve defaults if @Defaults = 0]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.tst1 (x INT DEFAULT(5));
+
+ CREATE SYNONYM FakeTableTests.tst1 FOR tSQLt_dev_remote.dbo.tst1;
+
+ EXEC FakeTableTests.AssertTableAfterCommandHasNoDefaults 'FakeTableTests.tst1', 'EXEC tSQLt.FakeTable ''FakeTableTests.tst1'', @Defaults = 0;';
+END;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable preserves defaults if @Defaults = 1]
AS
BEGIN
@@ -710,6 +1241,17 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable preserves defaults if @Defaults = 1]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.tst1 (x INT DEFAULT(5));
+
+ CREATE SYNONYM FakeTableTests.tst1 FOR tSQLt_dev_remote.dbo.tst1;
+
+ EXEC FakeTableTests.AssertTableStructureBeforeAndAfterCommandIsSameForDefaults 'FakeTableTests.tst1', 'EXEC tSQLt.FakeTable ''FakeTableTests.tst1'', @Defaults = 1;';
+END;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable preserves defaults if @Defaults = 1 when multiple columns exist on table]
AS
BEGIN
@@ -724,6 +1266,18 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable preserves defaults if @Defaults = 1 when multiple columns exist on table]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.tst1 ( ColWithNoDefault CHAR(3),
+ ColWithDefault DATETIME DEFAULT(GETDATE()));
+
+ CREATE SYNONYM FakeTableTests.tst1 FOR tSQLt_dev_remote.dbo.tst1;
+
+ EXEC FakeTableTests.AssertTableStructureBeforeAndAfterCommandIsSameForDefaults 'FakeTableTests.tst1', 'EXEC tSQLt.FakeTable ''FakeTableTests.tst1'', @Defaults = 1;';
+END;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable preserves defaults if @Defaults = 1 when multiple varied columns exist on table]
AS
BEGIN
@@ -739,6 +1293,19 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable preserves defaults if @Defaults = 1 when multiple varied columns exist on table]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.tst1 ( ColWithNoDefault CHAR(3),
+ ColWithDefault DATETIME DEFAULT(GETDATE()),
+ ColWithDiffDefault INT DEFAULT(-3));
+
+ CREATE SYNONYM FakeTableTests.tst1 FOR tSQLt_dev_remote.dbo.tst1;
+
+ EXEC FakeTableTests.AssertTableStructureBeforeAndAfterCommandIsSameForDefaults 'FakeTableTests.tst1', 'EXEC tSQLt.FakeTable ''FakeTableTests.tst1'', @Defaults = 1;';
+END;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable preserves the collation of a column]
AS
BEGIN
@@ -764,6 +1331,35 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable preserves the collation of a column]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.tst1 (x VARCHAR(30) COLLATE Latin1_General_BIN,
+ y VARCHAR(40));
+ CREATE SYNONYM FakeTableTests.tst1 FOR tSQLt_dev_remote.dbo.tst1;
+
+ CREATE TABLE #Expected (name NVARCHAR(MAX), collation_name NVARCHAR(MAX));
+ CREATE TABLE #Actual (name NVARCHAR(MAX), collation_name NVARCHAR(MAX));
+
+ INSERT INTO #Expected
+ SELECT C.name ,C.collation_name
+ FROM tSQLt_dev_remote.sys.columns AS C
+ JOIN tSQLt_dev_remote.sys.tables AS t ON t.object_id = C.object_id
+ JOIN tSQLt_dev_remote.sys.schemas AS s ON s.schema_id = t.schema_id
+ WHERE t.name = 'tst1' AND s.name = 'dbo';
+
+
+ EXEC tSQLt.FakeTable 'FakeTableTests.tst1';
+ INSERT INTO #Actual
+ SELECT name, collation_name
+ FROM sys.columns
+ WHERE object_id = OBJECT_ID('FakeTableTests.tst1');
+
+ EXEC tSQLt.AssertEqualsTable '#Expected','#Actual';
+
+END;
+GO
+
CREATE PROCEDURE FakeTableTests.[test Private_ResolveFakeTableNamesForBackwardCompatibility returns quoted schema when schema and table provided]
AS
BEGIN
@@ -918,6 +1514,32 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable preserves UDTd]
+AS
+BEGIN
+ CREATE SYNONYM dbo.tbl FOR tSQLt_dev_remote.TestSchema.tbli;
+
+ CREATE TABLE #Expected (name NVARCHAR(255), system_type_id INT, max_length INT, precision INT, scale INT, is_nullable BIT);
+ CREATE TABLE #Actual (name NVARCHAR(255), system_type_id INT, max_length INT, precision INT, scale INT, is_nullable BIT);
+
+ INSERT INTO #Expected
+ SELECT C.name ,C.system_type_id,C.max_length,C.precision,C.scale,C.is_nullable
+ FROM tSQLt_dev_remote.sys.columns AS C
+ JOIN tSQLt_dev_remote.sys.tables AS t ON t.object_id = C.object_id
+ JOIN tSQLt_dev_remote.sys.schemas AS s ON s.schema_id = t.schema_id
+ WHERE t.name = 'tbli' AND s.name = 'TestSchema';
+
+ EXEC tSQLt.FakeTable @TableName = 'dbo.tbl';
+
+ INSERT INTO #Actual
+ SELECT C.name ,C.system_type_id,C.max_length,C.precision,C.scale,C.is_nullable
+ FROM sys.columns AS C WHERE C.object_id = OBJECT_ID('dbo.tbl');
+
+ EXEC tSQLt.AssertEqualsTable '#Expected','#Actual';
+
+END;
+GO
+
CREATE PROC FakeTableTests.[test FakeTable preserves UDTd based on char type]
AS
BEGIN
@@ -940,6 +1562,32 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable preserves UDTd based on char type]
+AS
+BEGIN
+ CREATE SYNONYM dbo.tbl FOR tSQLt_dev_remote.TestSchema.tbl;
+
+ CREATE TABLE #Expected (name NVARCHAR(255), system_type_id INT, max_length INT, precision INT, scale INT, is_nullable BIT);
+ CREATE TABLE #Actual (name NVARCHAR(255), system_type_id INT, max_length INT, precision INT, scale INT, is_nullable BIT);
+
+ INSERT INTO #Expected
+ SELECT C.name ,C.system_type_id,C.max_length,C.precision,C.scale,C.is_nullable
+ FROM tSQLt_dev_remote.sys.columns AS C
+ JOIN tSQLt_dev_remote.sys.tables AS t ON t.object_id = C.object_id
+ JOIN tSQLt_dev_remote.sys.schemas AS s ON s.schema_id = t.schema_id
+ WHERE t.name = 'tbl' AND s.name = 'TestSchema';
+
+ EXEC tSQLt.FakeTable @TableName = 'dbo.tbl';
+
+ INSERT INTO #Actual
+ SELECT C.name ,C.system_type_id,C.max_length,C.precision,C.scale,C.is_nullable
+ FROM sys.columns AS C WHERE C.object_id = OBJECT_ID('dbo.tbl');
+
+ EXEC tSQLt.AssertEqualsTable '#Expected','#Actual';
+
+END;
+GO
+
CREATE PROC FakeTableTests.[test can fake local synonym of table]
AS
BEGIN
@@ -964,6 +1612,17 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test raises appropriate error if synonym is remote but not of a table]
+AS
+BEGIN
+ CREATE SYNONYM FakeTableTests.TempSynonym1 FOR tSQLt_dev_remote.FakeTableTests.NotATable;
+
+ EXEC tSQLt.ExpectException @ExpectedMessage = 'Cannot fake synonym [FakeTableTests].[TempSynonym1] as it is pointing to [tSQLt_dev_remote].[FakeTableTests].[NotATable], which is not a table or view!';
+ EXEC tSQLt.FakeTable 'FakeTableTests.TempSynonym1';
+
+END;
+GO
+
CREATE PROC FakeTableTests.[test can fake view]
AS
BEGIN
@@ -976,6 +1635,20 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test can fake view to remote table]
+AS
+BEGIN
+
+ SELECT TOP(0) * INTO #actual FROM tSQLt_dev_remote.dbo.TestTable;
+
+ EXEC('CREATE VIEW FakeTableTests.TempView1 AS SELECT * FROM tSQLt_dev_remote.dbo.TestTable;');
+
+ EXEC tSQLt.FakeTable 'FakeTableTests.TempView1';
+
+ EXEC tSQLt.AssertEqualsTableSchema @Expected = 'FakeTableTests.TempTable1', @Actual = #actual;
+END;
+GO
+
CREATE PROC FakeTableTests.[test can fake local synonym of view]
AS
BEGIN
@@ -989,6 +1662,18 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test can fake remote synonym of view]
+AS
+BEGIN
+
+ CREATE SYNONYM FakeTableTests.TempSynonym1 FOR tSQLt_dev_remote.dbo.TestView;
+
+ EXEC tSQLt.FakeTable 'FakeTableTests.TempSynonym1';
+
+ EXEC('INSERT INTO FakeTableTests.TempSynonym1 VALUES (1,2,NULL)');
+END;
+GO
+
CREATE PROC FakeTableTests.[test raises error if @TableName is multi-part and @SchemaName is not NULL]
AS
BEGIN
@@ -1021,6 +1706,19 @@ BEGIN
END;
GO
+CREATE PROC FakeTableTests.[test remote FakeTable works with two parameters, if they are quoted]
+AS
+BEGIN
+ CREATE TABLE tSQLt_dev_remote.dbo.TempTable1 ( i INT NOT NULL );
+ CREATE SYNONYM FakeTableTests.TempTable1 FOR tSQLt_dev_remote.dbo.TempTable1;
+
+ EXEC tSQLt.FakeTable '[FakeTableTests]','[TempTable1]';
+
+ EXEC FakeTableTests.AssertTableIsNewObjectThatHasNoConstraints 'FakeTableTests.TempTable1';
+
+END;
+GO
+
--CREATE PROC FakeTableTests.[test FakeTable works with cross database synonym]
--AS
--BEGIN