0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

`sql-formatter`はOracleのPL/SQL区切り文字`/`を正しく整形してくれない

0
Posted at

背景

VSCodeマクロでsql-formatterライブラリを使ったSQL整形機能を実装する際、8方言対応やオプション選択は素直に実装できましたが、Oracle PL/SQL特有の区切り文字/だけは後処理が必要でした。

1. sql-formatterはオプション指定だけで方言対応が完結する

import { format } from 'sql-formatter';

const formattedSql = format(sql, {
    language: 'mysql',       // MySQL/PostgreSQL/tsql/plsql/db2/redshift等
    keywordCase: 'upper',    // upper/lower/preserve
    tabWidth: 2,
    useTabs: false,
    linesBetweenQueries: 2
});

languageオプションを切り替えるだけで、MySQLのバッククォート記法やPostgreSQLの型キャスト(::)、SQL Serverの[]識別子などをそれぞれ正しく解釈してくれます。1つのライブラリで8方言をカバーできるのは実務上かなり便利です。

2. Oracle PL/SQLの/は整形後に行末へくっついてしまう

-- 期待する出力
BEGIN
  INSERT INTO users (id, name) VALUES (1, 'Test');
  COMMIT;
END;
/

-- sql-formatterの実際の出力(/が行末にくっつく)
END; /

Oracle SQL*Plusでは、PL/SQLブロックの終端を示す/が独立した行にないと正しく認識されません。しかしsql-formatterはこの区切り文字の意味を理解していないため、直前のトークンと同じ行に整形してしまいます。

3. 正規表現による後処理で解決

function postProcessSlashSeparator(sql: string): string {
    // 行末のスラッシュの前に改行を挿入
    return sql.replace(/\s+\/\s*$/gm, '\n/');
}

format()の出力に対して、行末の空白+/というパターンを\n/に置換する後処理を1つ追加するだけで解決します。gmフラグ(グローバル+複数行)を指定することで、複数のPL/SQLブロックが含まれる場合でもすべての/区切りに対応できます。ライブラリ側の制約を、ライブラリを改造せず後処理1関数で吸収した形です。

4. パースエラー時は原因を特定できるメッセージを出す

if (error.message && error.message.includes('Parse error')) {
    const message =
        'SQL整形に失敗しました。\n\n' +
        '原因:SQLとして認識できない文字が含まれています。\n' +
        '(例:△、●、■などの記号、不正なSQL構文)\n\n' +
        '対処法:\n' +
        '1. SQL以外のテキストやコメントを削除してください\n' +
        '2. 特殊文字(△など)を削除してください';
    vscode.window.showErrorMessage(message, { modal: true });
}

sql-formatterのパースエラーはメッセージがそっけないため、エラーメッセージにParse errorという文字列が含まれるかで判定し、日本語での原因説明と対処法を独自にラップして表示しています。ログから抽出したSQLには全角記号(△や●)が混入していることが多く、この分岐が実務でも頻繁に役立ちました。

まとめ

ライブラリの対応範囲外(Oracle固有の/区切り)を正規表現の後処理1つで補う設計と、パースエラーメッセージの日本語ラップ、この2点が実務で使えるSQL整形ツールにする上でのポイントでした。8方言・インデント幅の選択肢を含む完全なコードは元記事にまとめています。

→ SQL整形ツールを実現するTypeScriptマクロ(ブログ)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?