anbt-sql-formatter 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,79 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require "pp"
4
+
5
+ class AnbtSql
6
+ class TokenConstants
7
+
8
+ # 空文字. TAB,CR等も1つの文字列として含む。
9
+ SPACE = :space
10
+
11
+ # 記号. " <="のような2つで1つの記号もある。
12
+ SYMBOL = :symbol
13
+
14
+ # キーワード. "SELECT", "ORDER"など.
15
+ KEYWORD = :keyword
16
+
17
+ # 名前. テーブル名、列名など。
18
+ # ダブルクォーテーションが付く場合がある。
19
+ NAME = :name
20
+
21
+ # 値. 数値(整数、実数)、文字列など。
22
+ VALUE = :value
23
+
24
+ # コメント. シングルラインコメントとマルチラインコメントがある。
25
+ COMMENT = :comment
26
+
27
+ # SQL文の終わり.
28
+ END_OF_SQL = :end_of_sql
29
+
30
+ # 解析不可能なトークン. 通常のSQLではありえない。
31
+ UNKNOWN = :unknown
32
+ end
33
+
34
+
35
+ ##
36
+ # [_type] type of token
37
+ # [string] string of token
38
+ # [pos] ソース文字列の先頭からのトークンの位置をあらわす。
39
+ # 値は ゼロ(ZERO)オリジン。
40
+ # デフォルト値 -1 の場合には「位置情報に意味がない」ことをあらわす。
41
+ #
42
+ class AbstractToken
43
+ attr_accessor :_type, :string, :pos
44
+
45
+ @_type = nil
46
+
47
+ @string = nil
48
+
49
+ @pos = -1
50
+
51
+ #
52
+ # このバリューオブジェクトの文字列表現を取得する。
53
+ #
54
+ # オブジェクトのシャロー範囲でしか to_s されない点に注意。
55
+ #
56
+ # @return:: バリューオブジェクトの文字列表現。
57
+ #
58
+ def to_s
59
+ buf = ""
60
+ buf << "AbstractAnbtSqlToken["
61
+ buf << "_type=" + @_type
62
+ buf << ",string=" + @string
63
+ buf << ",pos=" + @pos
64
+ buf << "]"
65
+
66
+ buf
67
+ end
68
+ end
69
+
70
+
71
+ class Token < AbstractToken
72
+ def initialize(type, string, pos=nil)
73
+ @_type = type
74
+ @string = string
75
+
76
+ @pos = pos || -1
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,7 @@
1
+ module Anbt
2
+ module Sql
3
+ module Formatter
4
+ VERSION = "0.0.1"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,65 @@
1
+ #! /usr/bin/ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ require "pp"
5
+
6
+ require "anbt-sql-formatter/formatter"
7
+
8
+ =begin
9
+ rule のプロパティを修正するだけではなく
10
+ さらに踏み込んでカスタマイズしたい場合は
11
+ formatter.rb 内の AnbtSql::Formatter#format_list_main_loop
12
+ などをオーバーライドすると良いでしょう。
13
+
14
+ Ruby に詳しくない場合は「Ruby オープンクラス」
15
+ 「Ruby モンキーパッチ」で検索してみてください。
16
+
17
+ 継承の方が分かりやすいという場合は
18
+ 継承でも良いと思います。
19
+ =end
20
+
21
+ # class AnbtSql::Formatter
22
+ # def format_list_main_loop(tokens)
23
+ # # メソッドの処理を書き換える
24
+ # end
25
+ # end
26
+
27
+
28
+ if $0 == __FILE__
29
+ src = ""
30
+ while line = gets
31
+ src << line
32
+ end
33
+
34
+ rule = AnbtSql::Rule.new
35
+
36
+ # rule のプロパティを修正することで
37
+ # 動作をカスタマイズします。
38
+ # 詳細については rule.rb をご覧ください。
39
+
40
+ # キーワードを大文字・小文字に変換しない
41
+ rule.keyword = AnbtSql::Rule::KEYWORD_NONE
42
+
43
+ # 複数単語のキーワードを登録
44
+ rule.kw_multi_words << "INNER JOIN"
45
+ rule.kw_nl_x << "INNER JOIN"
46
+
47
+ # "THEN" の前で改行するのをやめさせる
48
+ rule.kw_nl_x -= ["THEN"]
49
+ # "WHEN" の前で改行させるようにする
50
+ rule.kw_nl_x << "WHEN"
51
+
52
+ # User defined additional functions:
53
+ # ユーザ定義関数の追加:
54
+ %w(count sum substr date).each{|func_name|
55
+ rule.function_names << func_name.upcase
56
+ }
57
+
58
+ #rule.indent_string = " "
59
+ #rule.indent_string = "('-')"
60
+ rule.indent_string = "| "
61
+
62
+ formatter = AnbtSql::Formatter.new(rule)
63
+ result = formatter.format(src)
64
+ print result
65
+ end
@@ -0,0 +1,165 @@
1
+ // ���� 3�‚̃p�X�����g���̊‹��ɍ��킹�ď��������Ă��������B
2
+
3
+ // ruby.exe �̏ꏊ
4
+ var envPath = "C:\\ruby\\bin\\ruby.exe";
5
+
6
+ // �T�N���G�f�B�^�̃}�N����u���Ă���t�H���_
7
+ var macroDir = "C:\\apps\\sakuraW_rXXXX\\macros\\";
8
+
9
+ // anbt-sql-formatter �̃t�H���_
10
+ var asfHome = "C:\\apps\\anbt-sql-formatter\\";
11
+
12
+
13
+ //================================
14
+
15
+
16
+ function checkPath( path ){
17
+ if( ! path.match( /\\$/ ) ){
18
+ path += "\\";
19
+ }
20
+
21
+ return path;
22
+ }
23
+
24
+ macroDir = checkPath( macroDir );
25
+ asfHome = checkPath( asfHome );
26
+
27
+
28
+ //================================
29
+
30
+
31
+ var scriptPath = asfHome + "bin\\anbt-sql-formatter";
32
+ var libDir = asfHome + "lib";
33
+
34
+ var macroPath = macroDir + "anbt-sql-formatter-for-sakura-editor.js";
35
+ var tempFileSrc = macroDir + "____temp_src.txt";
36
+ var tempFileDest = macroDir + "____temp_dest.txt";
37
+
38
+ var timeoutSec = 10;
39
+
40
+
41
+ //================================
42
+
43
+
44
+ var ForReading = 1;
45
+ var ForWriting = 2;
46
+
47
+ var wShell = new ActiveXObject( "WScript.Shell" );
48
+
49
+
50
+ //================================
51
+
52
+
53
+ function pathExists( varName, type ){
54
+ var path = eval(varName);
55
+ var fso = new ActiveXObject( "Scripting.FileSystemObject" );
56
+ var typeMsg;
57
+ var result = true;
58
+
59
+ switch(type){
60
+ case "file":
61
+ typeMsg = "�t�@�C��";
62
+ if( ! fso.FileExists( path ) ){
63
+ result = false;
64
+ }
65
+ break;
66
+ case "folder":
67
+ typeMsg = "�t�H���_";
68
+ if( ! fso.FolderExists( path ) ){
69
+ result = false;
70
+ }
71
+ break;
72
+ default:
73
+ wShell.Popup( "�ϐ� type �̎w�肪�Ԉ���Ă��܂��B" );
74
+ return;
75
+ }
76
+
77
+ if( ! result ){
78
+ wShell.Popup( typeMsg + ' "' + path + "\" �����‚���܂���B\n�ϐ� " + varName + " �̃p�X�w����m�F���Ă��������B" );
79
+ return false;
80
+ }else{
81
+ return true;
82
+ }
83
+ }
84
+
85
+
86
+ //================================
87
+
88
+
89
+ function writeFile( path, content ){
90
+ var fso = new ActiveXObject( "Scripting.FileSystemObject" );
91
+ var fout = fso.CreateTextFile( path );
92
+ fout.WriteLine( content );
93
+ fout.Close();
94
+ }
95
+
96
+
97
+ function readFile( path ){
98
+ var fso = new ActiveXObject( "Scripting.FileSystemObject" );
99
+ var fout = fso.OpenTextFile( path, ForReading );
100
+ var content = fout.ReadAll();
101
+ fout.Close();
102
+ return content;
103
+ }
104
+
105
+
106
+ //================================
107
+
108
+
109
+ function callFromSakuraEditor(){
110
+ if( ! pathExists( "envPath" , "file" )
111
+ || ! pathExists( "macroDir", "folder" )
112
+ || ! pathExists( "asfHome" , "folder" )
113
+ ){
114
+ return;
115
+ }
116
+
117
+ var selectedStr = GetSelectedString(0);
118
+ var fso = new ActiveXObject( "Scripting.FileSystemObject" );
119
+ if( fso.FileExists( tempFileSrc ) ){ fso.GetFile( tempFileSrc ).Delete(); }
120
+ if( fso.FileExists( tempFileDest ) ){ fso.GetFile( tempFileDest ).Delete(); }
121
+
122
+ writeFile( tempFileSrc, selectedStr );
123
+
124
+ var commandStr = 'cscript "' + macroPath + '"';
125
+ var vbHide = 0; //�E�B���h�E���\��
126
+ wShell.Run( commandStr, vbHide, true );
127
+
128
+ insText( readFile( tempFileDest ) );
129
+
130
+ if( fso.FileExists( tempFileSrc ) ){ fso.GetFile( tempFileSrc ).Delete(); }
131
+ if( fso.FileExists( tempFileDest ) ){ fso.GetFile( tempFileDest ).Delete(); }
132
+ }
133
+
134
+
135
+ function callFromCScript(){
136
+ var commandStr = 'cmd /c ' + envPath + ' -I ' + libDir + ' "' + scriptPath +'" "'+ tempFileSrc + '"' ;
137
+ var execObj = wShell.Exec( commandStr );
138
+
139
+ // �������I�����邩�A�܂��̓^�C���A�E�g����܂ő҂�
140
+ var startSec = (new Date()).getTime();
141
+ while( execObj.status == 0){
142
+ WScript.Sleep( 500 );
143
+ if( (new Date()).getTime() - startSec > timeoutSec ){ break; }
144
+ }
145
+
146
+ var result;
147
+ if( execObj.exitCode == 0){
148
+ result = execObj.StdOut.ReadAll();
149
+ }else{
150
+ result = execObj.StdErr.ReadAll();
151
+ }
152
+ writeFile( tempFileDest, result );
153
+ }
154
+
155
+
156
+ //================================
157
+
158
+
159
+ if( typeof(Editor) != "undefined" ){
160
+ callFromSakuraEditor();
161
+ }else if( typeof(WScript) != "undefined" ){
162
+ callFromCScript();
163
+ }else{
164
+ wShell.Popup( "�Ăяo�������킩��܂���B" );
165
+ }
@@ -0,0 +1,107 @@
1
+ = anbt-sql-formatter
2
+
3
+ (C) 2010 sonota <yosiot8753@gmail.com>
4
+
5
+
6
+ == 概要
7
+
8
+ Java製の SQL整形ツール BlancoSqlFormatter
9
+
10
+ blancoSqlFormatter - SQL整形ライブラリ
11
+ http://www.igapyon.jp/blanco/blancosqlformatter.html
12
+
13
+ を Ruby に移植したものです。
14
+ 完全な移植を目指したものではなく、改造が加わっています。
15
+
16
+
17
+ == インストール
18
+
19
+ $ ruby setup.rb
20
+
21
+
22
+ == 使い方
23
+
24
+ 標準入力で SQL を渡します。
25
+
26
+ $ echo "select a,b from c;" | anbt-sql-formatter
27
+ SELECT
28
+ a
29
+ , b
30
+ FROM
31
+ c
32
+ ;
33
+ $
34
+
35
+ 後は適宜 Emacs などエディタと連携させたりして使ってください。
36
+
37
+
38
+ == ライセンス
39
+
40
+ GNU Lesser General Public License.
41
+
42
+
43
+ == 著者
44
+
45
+ sonota:: Ruby へ移植
46
+
47
+ 次はオリジナルの Java版のクレジットの写しです。
48
+
49
+ 渡辺義則 / Yoshinori WATANABE / A-san:: 初期バージョンの開発
50
+ 伊賀敏樹 (Tosiki Iga / いがぴょん):: 維持メンテ担当
51
+
52
+
53
+ == Java版からの変更点覚書
54
+
55
+ === 全般
56
+
57
+ * 名前空間 AnbtSql を導入。また、ファイル名を
58
+ AnbtSqlFormatter.java → formatter.rb
59
+ といったように変更。
60
+
61
+ === formatter.rb / coarse-tokenizer.rb
62
+
63
+ * #format_list から #format_list_main_loop などを分離した。
64
+ * 粗トーカナイズ処理を coarse-tokenizer.rb に分離。
65
+ おそらく Java版からの一番大きな変更。
66
+ 本質的に SQL とは関係の薄い文字列とコメントのトーカナイズだけを別に行う。
67
+
68
+
69
+ == その他の変更点
70
+
71
+ * フロントエンドのサンプル追加。
72
+ * テストを追加(特に単体テスト)。
73
+
74
+
75
+ == 処理の概要
76
+
77
+ 1. AnbtSql::Parser
78
+ 1. 粗トークン(文字列、コメント、それ以外)に分割
79
+ 2. トークンに分割
80
+ 2. AnbtSql::Formatter
81
+ 1. トークンのリストを元にインデント等を整形
82
+
83
+
84
+ == カスタマイズ
85
+
86
+ * formatter に与える rule に追加
87
+ * 関数として扱うキーワードの追加
88
+ * 特定の改行・インデンテーション規則に対応するキーワードを追加
89
+ * インデントに用いる文字を指定
90
+ * キーワードの大文字・小文字指定
91
+ * もっと細かくカスタマイズしたい場合は
92
+ AnbtSql::Formatter#format_list_main_loop を
93
+ 継承、またはモンキーパッチング等で修正(オーバーライド)してください。
94
+
95
+
96
+ == テスト
97
+
98
+ $ ruby setup.rb test
99
+
100
+
101
+ == その他
102
+
103
+ * 一行コメントの次でインデントが乱れる点が修正候補となっていたため
104
+ 修正した。
105
+ AnbtSql::Formatter#format_list_main_loop 内で対処したが、
106
+ やっていることは末尾の改行を削っているだけなので
107
+ もっと前のトークン分割時に対処した方が良いかも。
@@ -0,0 +1,58 @@
1
+ = anbt-sql-formatter
2
+
3
+ (C) 2010 sonota (yosiot8753@gmail.com)
4
+
5
+
6
+ == Description
7
+
8
+ A tool for SQL formatting ported from
9
+ {BlancoSqlFormatter}[http://sourceforge.jp/projects/blancofw/releases/?package_id=4732].
10
+
11
+
12
+ == Install
13
+
14
+ $ ruby setup.rb
15
+
16
+
17
+ == Usage
18
+
19
+ $ echo "select a,b from c;" | anbt-sql-formatter
20
+ SELECT
21
+ a
22
+ , b
23
+ FROM
24
+ c
25
+ ;
26
+ $
27
+
28
+
29
+ == License
30
+
31
+ GNU Lesser General Public License.
32
+
33
+
34
+ == Authors
35
+
36
+ sonota:: Porting to Ruby
37
+
38
+ Following are Authors of BlancoSqlFormatter(original Java version).
39
+
40
+ 渡辺義則 / Yoshinori WATANABE / A-san:: Early development
41
+ 伊賀敏樹 (Tosiki Iga / いがぴょん):: Maintainance
42
+
43
+
44
+ == Customize
45
+
46
+ * In AnbtSql::Rule:
47
+ * Function names
48
+ * Rules for linefeed and indentation
49
+ * Characters for indentation
50
+ * Upcase or Downcase
51
+ * More farther:
52
+ Override AnbtSql::Formatter#format_list_main_loop
53
+ by inheritance or monkeypathcing.
54
+
55
+
56
+ == Test
57
+
58
+ $ ruby setup.rb test