Skip to content

Commit 65ecc79

Browse files
Merge pull request #770 from erikdarlingdata/dev
dev → main: bug template @debug field + sp_IndexCleanup uptime/UDF fixes
2 parents 8ef95a2 + 4706985 commit 65ecc79

2 files changed

Lines changed: 106 additions & 63 deletions

File tree

.github/ISSUE_TEMPLATE/bug_report.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,16 @@ body:
8989
validations:
9090
required: false
9191

92+
- type: textarea
93+
id: debug
94+
attributes:
95+
label: Debug Output
96+
description: |
97+
If the script supports `@debug = 1` (sp_QuickieStore, sp_HealthParser, sp_PressureDetector, sp_PerfCheck, sp_IndexCleanup, sp_LogHunter, sp_HumanEvents, sp_QueryStoreCleanup, sp_QueryReproBuilder), please re-run with `@debug = 1` and paste the **Messages tab** output — especially the last `current_table` value and the failing dynamic SQL block. This pinpoints which section is broken and is usually all we need to ship a fix.
98+
render: text
99+
validations:
100+
required: false
101+
92102
- type: textarea
93103
id: context
94104
attributes:

sp_IndexCleanup/sp_IndexCleanup.sql

Lines changed: 96 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1786,49 +1786,60 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17861786
column_name = c.name,
17871787
definition = cc.definition,
17881788
/*
1789-
UDF detection: Looks for schema-qualified object references like [schema].[function]
1790-
Note: This is a heuristic check and may have rare false positives if ].[ appears
1791-
in string literals or comments within the computed column definition
1789+
UDF detection: Uses sys.sql_expression_dependencies, filtered to user-defined
1790+
function object types (FN, IF, TF, FS, FT). This avoids the false positives
1791+
the previous string-heuristic produced for schema-qualified type names,
1792+
system functions called as [sys].[fn_xxx](), and ].[ embedded in string
1793+
literals or comments.
17921794
*/
17931795
contains_udf =
17941796
CASE
1795-
WHEN cc.definition LIKE ''%|].|[%'' ESCAPE ''|''
1796-
AND cc.definition LIKE ''%|].|[%(%'' ESCAPE ''|''
1797+
WHEN refs.udf_names IS NOT NULL
17971798
THEN 1
17981799
ELSE 0
17991800
END,
1800-
udf_names =
1801-
CASE
1802-
WHEN cc.definition LIKE ''%|].|[%'' ESCAPE ''|''
1803-
AND cc.definition LIKE ''%|].|[%(%'' ESCAPE ''|''
1804-
AND CHARINDEX(N''['', cc.definition) > 0
1805-
AND CHARINDEX(N''].['', cc.definition) > 0
1806-
AND CHARINDEX(N'']'', cc.definition, CHARINDEX(N''].['', cc.definition) + 3) > 0
1807-
THEN
1808-
SUBSTRING
1809-
(
1810-
cc.definition,
1811-
CHARINDEX(N''['', cc.definition),
1812-
CHARINDEX
1813-
(
1814-
N'']'',
1815-
cc.definition,
1816-
CHARINDEX
1817-
(
1818-
N''].['',
1819-
cc.definition
1820-
) + 3
1821-
) -
1822-
CHARINDEX(N''['', cc.definition) + 1
1823-
)
1824-
ELSE NULL
1825-
END
1801+
udf_names = refs.udf_names
18261802
FROM #filtered_objects AS fo
18271803
JOIN ' + QUOTENAME(@current_database_name) + N'.sys.columns AS c
18281804
ON fo.object_id = c.object_id
18291805
JOIN ' + QUOTENAME(@current_database_name) + N'.sys.computed_columns AS cc
18301806
ON c.object_id = cc.object_id
18311807
AND c.column_id = cc.column_id
1808+
OUTER APPLY
1809+
(
1810+
SELECT
1811+
udf_names =
1812+
STUFF
1813+
(
1814+
(
1815+
SELECT
1816+
N'', '' +
1817+
QUOTENAME(s.name) +
1818+
N''.'' +
1819+
QUOTENAME(o.name)
1820+
FROM ' + QUOTENAME(@current_database_name) + N'.sys.sql_expression_dependencies AS sed
1821+
JOIN ' + QUOTENAME(@current_database_name) + N'.sys.objects AS o
1822+
ON o.object_id = sed.referenced_id
1823+
JOIN ' + QUOTENAME(@current_database_name) + N'.sys.schemas AS s
1824+
ON s.schema_id = o.schema_id
1825+
WHERE sed.referencing_id = cc.object_id
1826+
AND sed.referencing_minor_id = cc.column_id
1827+
AND sed.referencing_class = 1
1828+
AND sed.referenced_class = 1
1829+
AND o.type IN (N''FN'', N''IF'', N''TF'', N''FS'', N''FT'')
1830+
ORDER BY
1831+
s.name,
1832+
o.name
1833+
FOR
1834+
XML
1835+
PATH(N''''),
1836+
TYPE
1837+
).value(''.'', ''nvarchar(max)''),
1838+
1,
1839+
2,
1840+
N''''
1841+
)
1842+
) AS refs
18321843
OPTION(RECOMPILE);';
18331844

18341845
IF @debug = 1
@@ -1883,46 +1894,56 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18831894
constraint_name = cc.name,
18841895
definition = cc.definition,
18851896
/*
1886-
UDF detection: Looks for schema-qualified object references like [schema].[function]
1887-
Note: This is a heuristic check and may have rare false positives if ].[ appears
1888-
in string literals or comments within the computed column definition
1897+
UDF detection: Uses sys.sql_expression_dependencies, filtered to user-defined
1898+
function object types (FN, IF, TF, FS, FT). This avoids the false positives
1899+
the previous string-heuristic produced for schema-qualified type names,
1900+
system functions called as [sys].[fn_xxx](), and ].[ embedded in string
1901+
literals or comments.
18891902
*/
18901903
contains_udf =
18911904
CASE
1892-
WHEN cc.definition LIKE ''%|].|[%'' ESCAPE ''|''
1893-
AND cc.definition LIKE ''%|].|[%(%'' ESCAPE ''|''
1905+
WHEN refs.udf_names IS NOT NULL
18941906
THEN 1
18951907
ELSE 0
18961908
END,
1897-
udf_names =
1898-
CASE
1899-
WHEN cc.definition LIKE ''%|].|[%'' ESCAPE ''|''
1900-
AND cc.definition LIKE ''%|].|[%(%'' ESCAPE ''|''
1901-
AND CHARINDEX(N''['', cc.definition) > 0
1902-
AND CHARINDEX(N''].['', cc.definition) > 0
1903-
AND CHARINDEX(N'']'', cc.definition, CHARINDEX(N''].['', cc.definition) + 3) > 0
1904-
THEN
1905-
SUBSTRING
1906-
(
1907-
cc.definition,
1908-
CHARINDEX(N''['', cc.definition),
1909-
CHARINDEX
1910-
(
1911-
N'']'',
1912-
cc.definition,
1913-
CHARINDEX
1914-
(
1915-
N''].['',
1916-
cc.definition
1917-
) + 3
1918-
) -
1919-
CHARINDEX(N''['', cc.definition) + 1
1920-
)
1921-
ELSE NULL
1922-
END
1909+
udf_names = refs.udf_names
19231910
FROM #filtered_objects AS fo
19241911
JOIN ' + QUOTENAME(@current_database_name) + N'.sys.check_constraints AS cc
19251912
ON fo.object_id = cc.parent_object_id
1913+
OUTER APPLY
1914+
(
1915+
SELECT
1916+
udf_names =
1917+
STUFF
1918+
(
1919+
(
1920+
SELECT
1921+
N'', '' +
1922+
QUOTENAME(s.name) +
1923+
N''.'' +
1924+
QUOTENAME(o.name)
1925+
FROM ' + QUOTENAME(@current_database_name) + N'.sys.sql_expression_dependencies AS sed
1926+
JOIN ' + QUOTENAME(@current_database_name) + N'.sys.objects AS o
1927+
ON o.object_id = sed.referenced_id
1928+
JOIN ' + QUOTENAME(@current_database_name) + N'.sys.schemas AS s
1929+
ON s.schema_id = o.schema_id
1930+
WHERE sed.referencing_id = cc.object_id
1931+
AND sed.referencing_class = 1
1932+
AND sed.referenced_class = 1
1933+
AND o.type IN (N''FN'', N''IF'', N''TF'', N''FS'', N''FT'')
1934+
ORDER BY
1935+
s.name,
1936+
o.name
1937+
FOR
1938+
XML
1939+
PATH(N''''),
1940+
TYPE
1941+
).value(''.'', ''nvarchar(max)''),
1942+
1,
1943+
2,
1944+
N''''
1945+
)
1946+
) AS refs
19261947
OPTION(RECOMPILE);';
19271948

19281949
IF @debug = 1
@@ -4127,7 +4148,19 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
41274148
),
41284149
table_name = N'brought to you by erikdarling.com',
41294150
index_name = N'for support: https://code.erikdarling.com/',
4130-
consolidation_rule = N'run date: ' + CONVERT(nvarchar(30), SYSDATETIME(), 120),
4151+
consolidation_rule =
4152+
N'run date: ' +
4153+
CONVERT(nvarchar(30), SYSDATETIME(), 120) +
4154+
N' | ' +
4155+
CASE
4156+
WHEN @uptime_warning = 1
4157+
THEN N'WARNING: Server uptime only ' +
4158+
@uptime_days +
4159+
N' days - usage data may be incomplete!'
4160+
ELSE N'Server uptime: ' +
4161+
@uptime_days +
4162+
N' days'
4163+
END,
41314164
script_type = N'Index Cleanup Scripts',
41324165
additional_info = N'A detailed index analysis report appears after these scripts',
41334166
target_index_name = N'ALWAYS TEST THESE RECOMMENDATIONS',

0 commit comments

Comments
 (0)