Command-line SQL compare breaks FileStream - but not GUI
kodexe
Posts: 5
I have a table with a FileStream blob field and a PK Guid ID, declared thusly:
When I synchronize two versions of this database, using the command-line SQL compare, even if there are no changes to this table, but only other tables, this table gets silently rebuilt, and broken in the process. By "silently" I mean that this table does not show up in the output - probably because there are no differences, so the changes just get added to the list of "related objects affected" (like views that need refreshing etc). And by "broken" I mean that the table gets rebuilt, but the primary key is not added back after the rebuild.
When I do the same thing using the GUI SQL Compare, the sync script looks fine and the table isn't affected.
The command line used is this:
Here's the sync SQL that gets added by the command-line SQL Compare but not by the GUI SQL Compare and that breaks the table:
To a layman such as myself, it looks like the primary key constraint is simply forgotten, which means it won't be there after the rebuild.
But why is this table rebuilt at all when there are no differences in it? Is it because of the FileStream? Or because of the RowGuidCol?
And why does the command-line tool differ from the GUI tool? That made it kind of hard to track this down. :-)
Thanks in advance.
Using latest 8.5 (with all updates).
EDIT: Just tested with 9.0; exact same results.
EDIT: This very old post seems to cover the same bug. It ends with Red Gate not being able to reproduce. Please put more effort this time, the bug is real. Sample data available on request! Specifically this:
EDIT: It seems that a "reason for rebuild" is "Changing the filegroup specification for a table". This hasn't happened here - and even if it had, there are other mysteries (GUI vs CLI, non-related change etc). But it sounds related.
CREATE TABLE [dbo].[MyTable]( [Id] [uniqueidentifier] ROWGUIDCOL NOT NULL, [Data] [varbinary](max) FILESTREAM NULL, CONSTRAINT [PK_MyTable] PRIMARY KEY CLUSTERED ( [Id] ASC ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] FILESTREAM_ON [FileStreamGroup1], UNIQUE NONCLUSTERED ( [Id] ASC ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] FILESTREAM_ON [FileStreamGroup1](If you're wondering about ROWGUIDCOL, it's because SQL Server requires this on filestream guid table fields.)
When I synchronize two versions of this database, using the command-line SQL compare, even if there are no changes to this table, but only other tables, this table gets silently rebuilt, and broken in the process. By "silently" I mean that this table does not show up in the output - probably because there are no differences, so the changes just get added to the list of "related objects affected" (like views that need refreshing etc). And by "broken" I mean that the table gets rebuilt, but the primary key is not added back after the rebuild.
When I do the same thing using the GUI SQL Compare, the sync script looks fine and the table isn't affected.
The command line used is this:
sqlcompare.exe /server1:x /username1:x /password1:x /db1:%sourcedb% /server2:x /username2:x /password2:x /db2:x /Exclude:user /Exclude:role /Exclude:Schema /Synchronize /rad /r:report.txt /sf:change.sql
Here's the sync SQL that gets added by the command-line SQL Compare but not by the GUI SQL Compare and that breaks the table:
PRINT N'Rebuilding [dbo].[MyTable]' GO CREATE TABLE [dbo].[tmp_rg_xx_MyTable] ( [Id] [uniqueidentifier] NOT NULL ROWGUIDCOL, [Data] [varbinary] (max) FILESTREAM NULL CONSTRAINT [tmp_rg_xx_UQ__MyTable__3214EC060EC32C7A] UNIQUE NONCLUSTERED ([Id]) ) GO IF @@ERROR<>0 AND @@TRANCOUNT>0 ROLLBACK TRANSACTION GO IF @@TRANCOUNT=0 BEGIN INSERT INTO #tmpErrors (Error) SELECT 1 BEGIN TRANSACTION END GO INSERT INTO [dbo].[tmp_rg_xx_MyTable]([Id], [Data]) SELECT [Id], [Data] FROM [dbo].[MyTable] GO IF @@ERROR<>0 AND @@TRANCOUNT>0 ROLLBACK TRANSACTION GO IF @@TRANCOUNT=0 BEGIN INSERT INTO #tmpErrors (Error) SELECT 1 BEGIN TRANSACTION END GO DROP TABLE [dbo].[MyTable] GO IF @@ERROR<>0 AND @@TRANCOUNT>0 ROLLBACK TRANSACTION GO IF @@TRANCOUNT=0 BEGIN INSERT INTO #tmpErrors (Error) SELECT 1 BEGIN TRANSACTION END GO EXEC sp_rename N'[dbo].[tmp_rg_xx_MyTable]', N'MyTable' EXEC sp_rename N'[dbo].[MyTable].[tmp_rg_xx_UQ__MyTable__3214EC060EC32C7A]', N'UQ__MyTable__3214EC060EC32C7A', N'INDEX'
To a layman such as myself, it looks like the primary key constraint is simply forgotten, which means it won't be there after the rebuild.
But why is this table rebuilt at all when there are no differences in it? Is it because of the FileStream? Or because of the RowGuidCol?
And why does the command-line tool differ from the GUI tool? That made it kind of hard to track this down. :-)
Thanks in advance.
Using latest 8.5 (with all updates).
EDIT: Just tested with 9.0; exact same results.
EDIT: This very old post seems to cover the same bug. It ends with Red Gate not being able to reproduce. Please put more effort this time, the bug is real. Sample data available on request! Specifically this:
Brian Donahue wrote:The reasons for table rebuilds are here: http://www.red-gate.com/supportcenter/C ... 000113.htm
When the rebuild is scripted, primary keys are not added back into the table.
Does that sound like an accurate description of the problem?
EDIT: It seems that a "reason for rebuild" is "Changing the filegroup specification for a table". This hasn't happened here - and even if it had, there are other mysteries (GUI vs CLI, non-related change etc). But it sounds related.
Comments
The other critical bit of information left out from my quote was that this only happened comparing scripts to a live database. There can be some oddness because on the live side we have to do a table rebuild in some cases and on the scripts side we don't (can't?).
If you could let us know if this is a live database on both sides, the schema script on both sides, and the default collation of the databases, hopefully we can reproduce it.
Yes, this is a compare between two live running databases (if I understand your question correctly). There are no scripts involved (other than perhaps the generated scripts used during the operation). We haven't tried it in any other scenario. If you want us to, please advise on how that should be done.
Not sure what you mean by "schema script", but here is "script as create to new query window":
The create script for the source and target databases are identical, except for the names and file names.
The default collation for both databases is
I can also provide you with actual database backup files if needed.