Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#293 Support for @OutputServerName in sp_BlitzCache #419

Closed
wants to merge 4 commits into from

Conversation

hariscodes
Copy link
Contributor

@hariscodes hariscodes commented Aug 10, 2016

Fixes #293 for sp_BlitzCache.

Changes proposed in this pull request:

  • Support for @OutputServerName
  • Updated error checking for @OutputDatabaseName variables for both linked and local servers

How to test this code:

  • Run procedure output with @expertmode = 1 (for comparison)
  • Run procedure with valid @OutputDatabaseName/SchemaName/TableName specified (should succeed in creating local table)
  • Run procedure with @OutputServerName specified as valid linked server along with other Output variables (should succeed in creating remote table on linked server)
  • Rerun both tests above without deleting testing tables to ensure that procedure doesn't try and create new table (it should dump results to the same table; tests IF EXISTS logic in permanent table creation)
  • Run procedure with invalid @OutputServerName (server that is not linked and random name; both should fail)
  • Run procedure with invalid local DB name (should fail)
  • Run procedure with invalid linked DB name (Specify valid @OutputServerName; should fail)

Use the output from the @expertmode = 1 run to compare the output on both the local and remote tables...they should be the same.

Has been tested on:

  • SQL Server 2008
  • SQL Server 2008 R2
  • SQL Server 2012
  • (UPDATE) SQL Server 2016

Haris Khan added 4 commits August 8, 2016 10:42
Started working on this, brought out output logic into it's own block
like I did with sp_Blitz. Not functional yet.
This variable now works on sp_BlitzCache! Same limitations as sp_Blitz
when trying to populate an XML field cross server, so query plans return
as NVARCHAR(MAX).
@hariscodes
Copy link
Contributor Author

Tested this on SQL Server 2016 (Got my instance connected to my domain) :)

BEGIN
IF EXISTS (SELECT server_id FROM sys.servers WHERE QUOTENAME([name]) = @OutputServerName)
BEGIN
SET @LinkedServerDBCheck = 'SELECT 1 WHERE EXISTS (SELECT * FROM '+@OutputServerName+'.master.sys.databases WHERE QUOTENAME([name]) = '''+@OutputDatabaseName+''')'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work if someone only has permissions to a single database, but not to master.sys.databases? I think generally in linked server situations, the cross-server account users don't have a lot of permissions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As long as they are in the Public role it should be fine. If the DBA/Vendor has removed all of the precreated roles for their own, the linked server account needs to have VIEW ANY DATABASE permission.

From the docs on sys.databases:

By default, the public role has the VIEW ANY DATABASE permission, allowing all logins to see database information. To block a login from the ability to detect a database, REVOKE the VIEW ANY DATABASE permission from public, or DENY the VIEW ANY DATABASE permission for individual logins.

Copy link
Member

@BrentOzar BrentOzar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Just a few small changes.

QueryText NVARCHAR(MAX),
QueryPlan XML,
NumberOfPlans INT,
NumberOfDistinctPlans INT,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uh oh - looks like maybe this was started from an older version, and it didn't have all of the current fields. Can you add the ones from lines 2182-2187 in the last version, and test that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure thing!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, just update the issue when that code has been added. (Just went in and checked and it still wasn't there, so noting in here in case you were missing that.)

BEGIN
SET @insert_sql = REPLACE(@insert_sql,''''+@OutputSchemaName+'''',''''''+@OutputSchemaName+'''''')
SET @insert_sql = REPLACE(@insert_sql,''''+@OutputTableName+'''',''''''+@OutputTableName+'''''')
SET @insert_sql = REPLACE(@insert_sql,'''DBCC FREEPROCCACHE ('' + CONVERT(VARCHAR(128), [PlanHandle], 1) + '');''','''''DBCC FREEPROCCACHE ('''' + QUOTENAME(CONVERT(VARCHAR(128), [PlanHandle], 1), CHAR(39)) + '''');''''')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dumb question - what are we search/replacing this part for? (I'm guessing you found something neat during testing, but if there's an easier way to fix it than doing search/replace, I'm totally down with that - replacing in long strings can be pretty slow.)

Copy link
Contributor Author

@hariscodes hariscodes Sep 29, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I have to use sp_executesql on the other box:

EXEC('EXEC('''+@insert_sql+''') AT ' + @OutputServerName);

...I end up needing extra single-quotes in the dynamic SQL string to make it function.

For the Plan Handles and the Query Hashes, it's the same problem. Without the correct number of single-quotes I end up inserting Plan Handle/Query Hash with a pair of single quotes around it into the output table rather than the code itself.

EDIT: Was using brain upside down when I wrote this the first time...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should also note that I did it this way for code reuse; and that performance was never an issue here since the insert_sql string is not insanely long or anything. If we were updating a ton of strings it would probably be an issue though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nah, you don't want to do that - let's not try to execute SQL on other servers. (I can see that being a security nightmare.)

END + N' DESC '

SET @insert_sql += N' OPTION (RECOMPILE) ; '
SELECT @insert_sql += N' ORDER BY ' + CASE @SortOrder WHEN 'cpu' THEN ' TotalCPU '
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we still be doing an order by in the insert, come to think of it?

@BrentOzar
Copy link
Member

This still hasn't been fixed after a few months, so I'm going to go ahead and close it. Thanks though.

@BrentOzar BrentOzar closed this Jan 16, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants