Skip to content

Skip the engine's own functions in rule 23 - #584

Merged
erikdarlingdata merged 1 commit into
devfrom
fix/rule23-builtin-tvf
Sep 28, 2026
Merged

erikdarlingdata merged 1 commit into
devfrom
fix/rule23-builtin-tvf

Conversation

@erikdarlingdata

Copy link
Copy Markdown
Owner

What does this PR do?

Rule 23 (Table-Valued Function) no longer flags functions that SQL Server supplies. Its message tells the user to rewrite a multi-statement TVF as an inline function or to stage its rows in a #temp table. That advice is for code the user wrote.

The engine's own functions run as the same operator. I captured estimated plans on SQL Server 2025 for eight of them. Each one had an Object element with a Table attribute and no Database or Schema:

Query Object Table
STRING_SPLIT STRING_SPLIT
OPENJSON OPENJSON_DEFAULT
GENERATE_SERIES GENERATE_SERIES
sys.dm_exec_requests SYSREQUESTS
sys.dm_exec_sql_text FNGETSQL
sys.dm_db_index_physical_stats INDEXANALYSIS
sys.fn_dblog DBLOG
sys.fn_get_audit_file FN_GET_AUDIT_FILE

A user function has both parts, as in the tvf_plan.sqlplan fixture (Database="[StackOverflow2013]" Schema="[dbo]"). So before this change, rule 23 warned on every query that reads a DMV and on every STRING_SPLIT or OPENJSON call.

The changes:

  1. PlanNode has a new SchemaName property. The parser sets it from the Object element, next to DatabaseName.
  2. Rule 23 skips an operator whose object has no database and no schema. An object with only one of the two parts still gets the warning.

The question came from #580. That PR turned the WHILE (SELECT ...) condition in eager_table_spool_plan.sqlplan into its own statement, and rule 23 then flagged the condition's INDEXANALYSIS operator. The owner decided that rule 23 must skip such functions.

Which component(s) does this affect?

  • Desktop App (PlanViewer.App)
  • Core Library (PlanViewer.Core)
  • CLI Tool (PlanViewer.Cli)
  • SSMS Extension (PlanViewer.Ssms)
  • Tests
  • Documentation

How was this tested?

  • New tests in PlanAnalyzerTests:
    • The eager_table_spool_plan.sqlplan fixture still has its INDEXANALYSIS operator, and rule 23 no longer warns on it.
    • Four cases built in code check the rule's condition. No database and no schema gives no warning. Database and schema, database only, or schema only each give the warning.
  • The existing tvf_plan.sqlplan test still finds the user function GetTopPosts.
  • WarningBaseline.txt lost one line, the INDEXANALYSIS warning. No other finding in the 60 fixture plans changed.
  • Full suite: 894 passed, 0 failed, 1 skipped. The Release build has 0 compiler warnings. Windows only.

Checklist

  • I have read the contributing guide
  • My code builds with zero warnings (Release build through dotnet test)
  • All tests pass (dotnet test)
  • I have not introduced any hardcoded credentials or server names

🤖 Generated with Claude Code

https://claude.ai/code/session_01G625JBNh45iTR1hpT4CxNR

STRING_SPLIT, OPENJSON, GENERATE_SERIES and every DMV and DMF run as a Table-valued
function operator whose Object has no Database and no Schema. A user function always has
both. Rule 23's advice (rewrite as an inline function, or stage the rows in a #temp table)
is for code the user wrote, so the rule now skips an operator with neither part. The parser
records the schema on PlanNode.SchemaName for the check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G625JBNh45iTR1hpT4CxNR
@claude

claude Bot commented Sep 28, 2026

Copy link
Copy Markdown

Reviewed. This is a small, well-scoped fix and I don't see correctness issues.

  • The engine-function heuristic (DatabaseName and SchemaName both empty) is applied consistently: SchemaName is now parsed right next to DatabaseName in ShowPlanParser.RelOp.cs (both bracket-stripped the same way), and Rule 23 checks both before suppressing the warning, so a partially-qualified object (schema-only or db-only) still warns as intended.
  • Verified the eager_table_spool_plan.sqlplan fixture backs up the claim: <Object Table="[INDEXANALYSIS]" /> has no Database/Schema attributes, matching the new test and the updated WarningBaseline.txt.
  • PlanModels.cs and ShowPlanParser.RelOp.cs are pre-existing linked <Compile Include> files in PlanViewer.Web.csproj, so no new linkage is needed for the Blazor viewer.
  • No untrusted-input/SQL-generation concerns — this only reads XML attributes and adds a null/empty check.

Nothing to flag.

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.

1 participant