diff --git a/TablePro/Core/Autocomplete/SQLContextAnalyzer.swift b/TablePro/Core/Autocomplete/SQLContextAnalyzer.swift index 4efe9887f..b6734dee5 100644 --- a/TablePro/Core/Autocomplete/SQLContextAnalyzer.swift +++ b/TablePro/Core/Autocomplete/SQLContextAnalyzer.swift @@ -337,13 +337,20 @@ final class SQLContextAnalyzer { // Check if immediately after comma let isAfterComma = checkIfAfterComma(textBeforeCursor) + // Clause detection runs on the text BEFORE the token being typed: the + // prefix is what completion filters on, so it cannot also count as a + // committed clause keyword ("SELECT|" must still suggest the SELECT + // keyword, not switch to select-list completions). + let nsBeforeCursor = textBeforeCursor as NSString + let textBeforePrefix = nsBeforeCursor.substring(to: min(prefixStart, nsBeforeCursor.length)) + // For subquery context, extract text from the innermost subquery // so clause detection works on the subquery's SQL, not the outer query let clauseText: String if nestingLevel > 0 { - clauseText = extractInnermostSubqueryText(from: textBeforeCursor) + clauseText = extractInnermostSubqueryText(from: textBeforePrefix) } else { - clauseText = textBeforeCursor + clauseText = textBeforePrefix } // Determine clause type diff --git a/TableProTests/Core/Autocomplete/SQLContextAnalyzerTests.swift b/TableProTests/Core/Autocomplete/SQLContextAnalyzerTests.swift index 5cdf9b08c..ff739f4b1 100644 --- a/TableProTests/Core/Autocomplete/SQLContextAnalyzerTests.swift +++ b/TableProTests/Core/Autocomplete/SQLContextAnalyzerTests.swift @@ -766,7 +766,7 @@ struct SQLContextAnalyzerTests { @Test("Multiple block comments with code between") func testMultipleBlockComments() { - let context = analyzer.analyze(query: "/* c1 */ SELECT /* c2 */ * FROM ", cursorPosition: 31) + let context = analyzer.analyze(query: "/* c1 */ SELECT /* c2 */ * FROM ", cursorPosition: 32) #expect(context.isInsideComment == false) #expect(context.clauseType == .from) }