Lukla Data Studio Docs

Docs Editor

Code analysis and quick fixes

Errors and code analysis as you type, quick fixes with ⌥↩ or ⌘., declaring variables, schema-qualifying names, type mismatches, suppressions and your own rules.

On this page
  1. Errors as you type
  2. Quick fixes
  3. Example: a variable that doesn't fit its column
  4. The rules
  5. Suppressing a finding
  6. Settings per project: .luklalint.json
  7. Your own rules
  8. Problems
  9. External linters

The editor checks your SQL as you type: red underlines for errors from the server's own parser, and yellow and blue ones for code-analysis findings. Most come with a fix one keystroke away.

The editor flagging a number given to an nchar variable, SELECT *, a missing schema and a DELETE without WHERE
Findings are underlined in the text and marked in the scroll bar; the count and arrows at the top right step through them.

#Errors as you type

The statement is parsed as you type and again by the server (its PARSEONLY check), so the red underlines are SQL Server's own messages: hover one to read it. Errors from a run are underlined too, and Messages links each one to its line.

PARSEONLY checks syntax only, so a name that doesn't exist isn't a server error until the query runs. The editor checks names itself, against the schema it has loaded:

  • An unknown table or view is underlined wherever it appears: FROM dbo.Custmers.
  • An unknown column is underlined when it's written with its table or alias, c.Contry, and that alias names one known table. A bare Contry isn't checked, because the editor can't tell which table it should belong to.

Both are yellow warnings, and when there's a name close to it, ⌥↩ offers to change it:

Recorded in the app: c.Contry is flagged as you type, and the quick fix corrects it before the query runs.

A misspelled column you only find out about from a run (Invalid column name) is marked on its statement, without a fix: write it as alias.column to get one.

#Quick fixes

Put the cursor on an underline and press ⌥↩ (or ⌘. in the Lukla and SSMS keymaps). A lightbulb in the gutter shows when there's a fix on the line. Fixes include:

FixWhen
Declare @x intA variable is used but never declared (Must declare the scalar variable). The type comes from how it's used: WHERE C.CustomerID = @x declares it as CustomerID's type. The cursor lands where its value goes.
Declare all undeclared variablesSeveral are missing in the same batch.
Qualify with schema / Qualify all with schema (N)FROM Customers → FROM dbo.Customers, for one name or every one in the statement or script.
Change to CountryAn unknown table, or an unknown alias.column, close to a real one: two letters off, or up to a third of a long name (see above).
Write N'1'A number given to a string variable (see below).
Declare @x as nchar(5)A variable compared with a column of another type.
Expand * into columnsSELECT * on known tables.
Suppress on this lineAny analysis finding.

When a rule finds several fixable issues, one entry fixes them all, in the statement or in the whole script.

#Example: a variable that doesn't fit its column

T-SQL
DECLARE @CustomerID nchar(5) = 1;          -- LK020: a number given to an nchar

SELECT ProductName, Total = SUM(Quantity)
FROM dbo.Products P, dbo.[Order Details] OD, dbo.Orders O, dbo.Customers C
WHERE C.CustomerID = @CustomerID
  AND C.CustomerID = O.CustomerID
  AND O.OrderID = OD.OrderID
  AND OD.ProductID = P.ProductID
GROUP BY ProductName;

1 is underlined: giving a number to a string variable makes SQL Server compare as numbers, so string columns get converted (no index seek) and non-numeric values fail. The quick fix writes N'1'.

The same rule catches:

  • 'abc' given to an int (an error: it fails when it runs),
  • '42' given to an int (a hint: write the number without quotes),
  • a string longer than its varchar(n) (it's silently cut),
  • with the schema loaded, a variable compared with a column of another type, such as an int variable against an nvarchar column, or an nvarchar variable against a varchar column. SQL Server converts the column on every row, so an index on it can't seek. The fix declares the variable with the column's type.

#The rules

Rules from SQL Server Data Tools (SR…) and Lukla's own (LK…). Change any rule's level, or turn it off, in Settings ▸ Code Analysis; expand a rule there to read why it matters and what to do instead.

RuleWhat it flagsCategoryDefault
SR0001Avoid SELECT *DesignWarning
SR0005Avoid LIKE patterns that start with %PerformanceInfo
SR0006Keep columns bare in WHERE and JOIN comparisonsPerformanceWarning
SR0008Use SCOPE_IDENTITY() instead of @@IDENTITYCorrectnessWarning
SR0009Avoid variable-length types of size 1 or 2DesignInfo
SR0010Avoid old-style joinsDeprecatedWarning
SR0011Avoid special characters in object namesNamingInfo
SR0012Avoid reserved words as namesNamingWarning
SR0016Avoid the sp_ prefix for proceduresNamingWarning
LK001Avoid NOLOCKCorrectnessWarning
LK002UPDATE or DELETE without WHERECorrectnessWarning
LK003Use IS NULL instead of = NULLCorrectnessError
LK004NOT IN with a subqueryCorrectnessWarning
LK005INSERT without a column listDesignWarning
LK006Procedure without SET NOCOUNT ONPerformanceInfo
LK007Object reference without a schemaPerformanceInfo
LK008Character type without a lengthCorrectnessWarning
LK009TOP without ORDER BYCorrectnessInfo
LK010ORDER BY a column numberStyleInfo
LK011Dynamic SQL with EXEC()SecurityWarning
LK012Deprecated syntaxDeprecatedWarning
LK013Transaction without COMMIT or ROLLBACKCorrectnessWarning
LK014CursorPerformanceInfo
LK015Unused variableDesignInfo
LK016OS access or inline credentialsSecurityWarning
LK017SELECT … INTO a permanent tableDesignInfo
LK018Linked-server four-part nameDesignInfo
LK019GOTOStyleInfo
LK020Value doesn't fit its typeCorrectnessWarning

LK007 (missing schema) needs the database's schema loaded, so it's quiet until the tab is connected.

Settings ▸ Code Analysis: rules by category with their level
Settings ▸ Code Analysis.

#Suppressing a finding

A comment turns rules off where you need to:

T-SQL
-- lukla-disable-next-line SR0001
SELECT * FROM dbo.Orders;

/* lukla-disable LK001 */
SELECT * FROM dbo.Orders WITH (NOLOCK);
/* lukla-enable LK001 */

-- lukla-disable-file LK014

Without rule IDs, the comment covers every rule. Suppress on this line in the quick-fix menu writes the first form for you.

#Settings per project: .luklalint.json

A .luklalint.json in a script's folder, or any folder above it, overrides your settings for scripts there, so a repository can carry its team's rules:

JSON
{
  "rules": { "SR0001": "off", "LK007": "warning" },
  "customRules": [
    {
      "id": "no-nolock-hint",
      "message": "Use READ COMMITTED SNAPSHOT instead of NOLOCK",
      "severity": "warning",
      "scope": "statement",
      "match": "\\bNOLOCK\\b"
    }
  ]
}

#Your own rules

Add rules in Settings ▸ Code Analysis ▸ Custom Rules, or in .luklalint.json:

  • Pattern rules flag a regular expression (match), optionally unless another one matches (unless), per statement, batch or file.
  • JavaScript rules get the parsed script and return findings, with optional fixes. They run in a sandbox with no network, file or timer access, and a rule that runs over its time limit is turned off until the app restarts.
JavaScript
// Flag a DELETE that has no WHERE in the same statement.
function check(context) {
  return context.statements
    .filter(s => s.kind === "DELETE" && !s.tokens.some(t => t.text.toUpperCase() === "WHERE"))
    .map(s => ({ offset: s.offset, length: s.length, message: "DELETE without WHERE", severity: "warning" }));
}

Each rule sees context.text, context.tokens (kind, text, offset, length, isString, isComment), context.statements (offset, length, kind, tokens) and context.schema (null when none is loaded). Offsets are UTF-16, as JavaScript string indexes are.

#Problems

  • F2 and ⇧F2 jump to the next and previous problem in the editor.
  • Query ▸ Analyze Script (⌥⇧⌘A) lists every finding in the script in a Problems tab.
  • Analyze Folder in a folder's menu in the Files pane checks every .sql file under it, with progress and Cancel.
  • Query ▸ Code Analysis ▸ Enabled turns checking as you type off and on.

#External linters

If you use sqlfluff or TSQLLint, add them in Settings ▸ Code Analysis ▸ External Linters. Analyze Script and Analyze Folder run them too (not while you type), and their findings show with IDs such as sqlfluff:LT01 and tsqllint:select-star.