【プログラム】クエリフォーマット(javascript)+サクラエディタ

f:id:albahoudori:20190826232258j:plain
毎回勉強がてらという理由でプログラミングしていますが、だいたいのきっかけが「あ、これやってみよう!」という興味だけです。
今回は サクラエディタで利用する クエリ成形用マクロ(javascript) を作ってみました。 が、あまりいい出来ではないというか、美しさが足りないというか・・・
またテストも十分じゃないので、今後問題が見つかり次第直します。

■機能
インラインに対応したインデント整形を行います。条件文のクエリ(サブクエリ)はインデント一個足りなくなるぅぅぅぅ・・・
■使い方
●設定
①下部の プログラムソース の内容をコピーしてファイルを作成する。ファイル名は "formatSQL_v1.0.js" とする。
サクラエディタ を開き [設定] → [共通設定] → [マクロ] をひらく。
③[参照]ボタンから ①のファイルを格納したフォルダを参照し、画像通りの以下の設定を行い[設定]を押下する。
④種別:外部マクロ を選択し、対象の機能(queryFormat)を選択する。以下の画像通りに設定し(Shift + Ctrl + ALt は好きに選択を) 割付 を押下する。
⑤[OK]を押下する

●使い方
サクラエディタを開き、対象のクエリを張り付ける。張り付けたクエリをすべて選択し、設定④ で設定した"キー"を押下する

●プログラムソース

/**
 * Version:1.0
 */

/**
 * メンテナンス
 */
var DEBUG = 0;
var debugTextArray = [];

/**
 * イニシャライズメソッド.
 * データインプット情報を一元化する.
 */
function initialize(text){
    
    //文字統一
    var keywordArray = [" FROM\\(" , " JOIN\\(" , " GROUP BY\\(" , "HAVING\\(" , " WHERE\\(" , " AND\\(", "ORDER BY\\(" ];
    text = text.toUpperCase();
    text = replaceAll(text,"\r\n"," ");
    text = replaceAll(text,"\r"," ");
    text = replaceAll(text,"\n"," ");
    text = replaceAll(text,"\t"," ");
    text = replaceAll(text,"★","");
    text = replaceAll(text,"☆","");
    for(i=1; i<keywordArray.length-1; i++)
    {
        var beforeText = keywordArray[i];
        var afterText = beforeText.replace("("," (");
        var text = replaceAll(text,beforeText,afterText);
    }

    text = text.replace(/\s+/g, " ")// 2つ以上の空白を排除
    
    return text;
}
/**
 * メイン処理を行うメソッド
 * インデント調整等を行う.
 */
function formatSql(allText){

    //1.初期化
    allText = initialize(allText);
    var returnValue = "";
    
    var searchText901 = " INNER JOIN \\(";
    var searchText902 = " FROM \\(";
    var searchText903 = " LEFT JOIN \\(";
    var searchText904 = " LEFT OUTER JOIN \\(";
    var searchText905 = " IN \\(";
    
    allText = replaceAll(allText, searchText901," INNER JOIN ★(");
    allText = replaceAll(allText, searchText902," FROM ★(");
    allText = replaceAll(allText, searchText903," LEFT JOIN ★(");
    allText = replaceAll(allText, searchText904," LEFT OUTER JOIN ★(");
    allText = replaceAll(allText, searchText905," IN ★(");
    
    if (DEBUG == 1){ debugTextArray.push("[DEBUG]#1:" + allText + "\r\n")}

    //2.一文字ずつチェックし、内部クエリのSTARTとENDの"かっこ"を紐づける
    charList = allText.split("");
    var q = 0;
    var s = 0;
    var allKakkoCountArray = [];
    var inQueryKakkoCountArray = []; //インクエリ判別用の配列
    var flag = "0";
    
    // すべての"(" ")"にIDを割り当てを行い、紐づける
    // "(" : "★", ")" : "☆" が後の処理の指標となる
    for(k=0; k<charList.length; k++){
        var charValue = charList[k];
        
        if(charValue == "★"){
            flag = "1";
        }
        
        if(charValue == "("){
            s = s + 1 ;
            allKakkoCountArray.push(s);
            if (flag == "1")
            {
                inQueryKakkoCountArray.push(s);
                flag = "0";
            }
            
        }
        
        if(charValue == ")"){
            tmpValue = allKakkoCountArray.pop();
            for(n=0; n<inQueryKakkoCountArray.length; n++){
              if(tmpValue == inQueryKakkoCountArray[n])
              {
                  charList[k] = "☆)";
              }
            }
        }
    }
    
    allText = charList.join("");// すべての文字を結合する
    if (DEBUG == 1){ debugTextArray.push("[DEBUG]#2:" + allText + "\r\n")}

    //3.基本的なキーワードで改行する
    var array =[];
    var selectBlockArray = allText.split("SELECT ")
    var tmpBasicQuery = "";
    for(i=1; i<selectBlockArray.length; i++){
        text = "\r\n" + "SELECT\r\n\t"+ selectBlockArray[i];
        text = replaceKeyword(text);
        tmpBasicQuery = tmpBasicQuery + text;
    }
    if (DEBUG == 1){ debugTextArray.push("[DEBUG]#3:" + tmpBasicQuery + "\r\n")}

    //4.インクエリの整形を行う
    baseTabCount = 0;
    baseTabText = "";
    var flag = 0; //インクエリ整形実行用のフラグ
    var rnBlockTextArray = tmpBasicQuery.split("\r\n");
    for(i=1; i<rnBlockTextArray.length; i++)
    {
        //flagが0以外の時→インクエリによるインデント調整
        if (flag != 0)
        {
            baseTabText = "";
            for(n=0; n<baseTabCount; n++)
            {
                baseTabText = baseTabText + "\t";
            }
            flag = 0;
        }

        tmpText =  rnBlockTextArray[i];
        if (tmpText.indexOf("★") != -1)
        {
            returnValue = returnValue + baseTabText + tmpText.replace("★","") + "\r\n";
            baseTabCount = baseTabCount + 1;
            flag = 1
            continue;
        }
        
        if (tmpText.indexOf("☆") != -1)
        {
            tmpText = replaceAll(tmpText,"☆\\)","\r\n" + baseTabText + "☆)" );
            returnValue = returnValue + baseTabText + tmpText.replace("\t☆","") + "\r\n";
            baseTabCount = baseTabCount - 1;
            flag = 2
            continue;
        }
        
        if (tmpText.indexOf("★") == -1 && tmpText.indexOf("☆") == -1)
        {
            returnValue =  returnValue + baseTabText + tmpText + "\r\n";
        }
    }
    if (DEBUG == 1){ debugTextArray.push("[DEBUG]#3:" + returnValue + "\r\n")}
 
    if (DEBUG == 1){ return debugTextArray.join("");}
    return returnValue;
}
/**
 * 置換メソッド.
 * 全件置換を行う際に利用する.
 */
function replaceAll(str, beforeStr, afterStr){
    var reg = new RegExp(beforeStr, "g");
    return str.replace(reg, afterStr);
}


/**
 * 基本的な改行判定してよいクエリ文字を規定し、置換するメソッド
 */
function replaceKeyword(text){
    searchText001 = " FROM ★\\(";
    searchText002 = " FROM ";
    searchText003 = " INNER JOIN ★\\(";
    searchText004 = " INNER JOIN ";
    searchText005 = " LEFT JOIN ★\\(";
    searchText006 = " LEFT JOIN ";
    searchText007 = " LEFT OUTER JOIN ★\\(";
    searchText008 = " LEFT OUTER JOIN ";
    searchText099 = ","
    
    searchText101 = " WHERE ";
    searchText102 = " GROUP BY ";
    searchText103 = " HAVING "
    searchText104 = " AND "
    searchText105 = " ORDER BY "
    searchText106 = "☆"
    
    //FROM・JOIN
    text = replaceAll(text, searchText001, "\r\n" + "FROM\r\n"       + "★(");
    text = replaceAll(text, searchText002, "\r\n" + "FROM\r\n"       + "\t");
    text = replaceAll(text, searchText003, "\r\n" + "INNER JOIN\r\n" +"★(");
    text = replaceAll(text, searchText004, "\r\n" + "INNER JOIN\r\n");
    text = replaceAll(text, searchText005, "\r\n" + "LEFT JOIN\r\n"  +"★(");
    text = replaceAll(text, searchText006, "\r\n" + "LEFT JOIN\r\n");
    text = replaceAll(text, searchText007, "\r\n" + "LEFT OUTER JOIN\r\n"  +"★(");
    text = replaceAll(text, searchText008, "\r\n" + "LEFT OUTER JOIN\r\n");
    
    //OTHER
    text = replaceAll(text, searchText101,  "\r\n" + "WHERE\r\n"    +  "\t" );
    text = replaceAll(text, searchText102,  "\r\n" + "GROUP BY\r\n" +  "\t" );
    text = replaceAll(text, searchText103,  "\r\n" + "HAVING\r\n"   +  "\t" );
    text = replaceAll(text, searchText104,  "\r\n" + "\t" + "AND ");
    text = replaceAll(text, searchText099,"\r\n" + "\t" + ",");
    text = replaceAll(text, searchText105,  "\r\n" + "ORDER BY\r\n" +  "\t" );
    text = replaceAll(text, searchText106,  "\r\n☆");
    return text;
}

/**
 * 実行
 */
var text = Editor.GetSelectedString(0);
if ( text !== "" ) Editor.InsText(formatSql(text));