• R/O
  • SSH

JdbcAcsess2: Commit

全てを再実装したJdbcAcsessです。


Commit MetaInfo

Revision9784314ce47af585b75269e3f389bff4acc6059d (tree)
Time2012-02-14 21:26:34
Authorshimakazuro
Commitershimakazuro

Log Message

パッケージとクラスの整理

Change Summary

Incremental Difference

diff -r 43a54fa1463a -r 9784314ce47a src/jdbcacsess2/main/JPanelSql.java
--- a/src/jdbcacsess2/main/JPanelSql.java Mon Feb 13 22:04:37 2012 +0900
+++ b/src/jdbcacsess2/main/JPanelSql.java Tue Feb 14 21:26:34 2012 +0900
@@ -48,7 +48,7 @@
4848 import jdbcacsess2.sqlService.DataBaseTransactionListener;
4949 import jdbcacsess2.sqlService.PropertyResultSetTableModel;
5050 import jdbcacsess2.sqlService.ResultsTableModel;
51-import jdbcacsess2.sqlService.SqlExecuteSentencies.SqlExecuteSentence;
51+import jdbcacsess2.sqlService.parse.SqlExecuteSentencies.SqlExecuteSentence;
5252 import jdbcacsess2.sqlService.SqlExecuteTask;
5353 import jdbcacsess2.sqlService.SqlExecutedListener;
5454
diff -r 43a54fa1463a -r 9784314ce47a src/jdbcacsess2/main/MainController.java
--- a/src/jdbcacsess2/main/MainController.java Mon Feb 13 22:04:37 2012 +0900
+++ b/src/jdbcacsess2/main/MainController.java Tue Feb 14 21:26:34 2012 +0900
@@ -63,8 +63,6 @@
6363 import jdbcacsess2.sqlService.DataBaseConnection;
6464 import jdbcacsess2.sqlService.DataBaseConnectionListener;
6565 import jdbcacsess2.sqlService.DataBaseTransactionListener;
66-import jdbcacsess2.sqlService.PropertyDBObjectsTableModel;
67-import jdbcacsess2.sqlService.PropertyExportedKeyTableModel;
6866 import jdbcacsess2.sqlService.ReferenceColumnResult;
6967 import jdbcacsess2.sqlService.SqlAsyncExecute;
7068 import jdbcacsess2.sqlService.SqlExecutedListener;
@@ -73,6 +71,8 @@
7371 import jdbcacsess2.sqlService.dbobject.DBObjectTables.DBObjectTable;
7472 import jdbcacsess2.sqlService.dbobject.DBObjectsRoot;
7573 import jdbcacsess2.sqlService.dbobject.DBobjectMutableTreeTableNode;
74+import jdbcacsess2.sqlService.dbobject.PropertyDBObjectsTableModel;
75+import jdbcacsess2.sqlService.dbobject.PropertyExportedKeyTableModel;
7676 import jdbcacsess2.sqlService.exception.DbConnectAlreadyException;
7777 import jdbcacsess2.sqlService.exception.DbConnectIllgalStateException;
7878 import jdbcacsess2.sqlService.history.HistryTableModel;
@@ -691,8 +691,7 @@
691691 // TABLE 系の時のみexportkey情報を表示する
692692 JTable jTable = view.getCurrentJPanelSession().getJTableExportedKey();
693693 if (dbObject instanceof DBObjectTable) {
694- List<ReferenceColumnResult> exportedKey = ((DBObjectTable) dbObject).getExportedKey();
695- jTable.setModel(new PropertyExportedKeyTableModel(exportedKey));
694+ jTable.setModel(new PropertyExportedKeyTableModel(((DBObjectTable) dbObject).getExportedKey()));
696695 } else {
697696 // TABLE系以外なので空のモデルを設定する
698697 jTable.setModel(new DefaultTableModel());
diff -r 43a54fa1463a -r 9784314ce47a src/jdbcacsess2/sqlService/PropertyDBObjectsTableModel.java
--- a/src/jdbcacsess2/sqlService/PropertyDBObjectsTableModel.java Mon Feb 13 22:04:37 2012 +0900
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
1-/*
2- * Copyright 2011 Kazuhiro Shimada
3- *
4- * Licensed under the Apache License, Version 2.0 (the "License");
5- * you may not use this file except in compliance with the License.
6- * You may obtain a copy of the License at
7- *
8- * http://www.apache.org/licenses/LICENSE-2.0
9- *
10- * Unless required by applicable law or agreed to in writing, software
11- * distributed under the License is distributed on an "AS IS" BASIS,
12- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13- * See the License for the specific language governing permissions and
14- * limitations under the License.
15- */
16-
17-package jdbcacsess2.sqlService;
18-
19-import java.util.List;
20-
21-import javax.swing.table.AbstractTableModel;
22-
23-import jdbcacsess2.sqlService.dbobject.DBObject.Property;
24-
25-/**
26- * @author sima
27- *
28- */
29-public class PropertyDBObjectsTableModel extends AbstractTableModel {
30- private static final long serialVersionUID = 3293479625219161204L;
31-
32- private List<Property> properties;
33-
34- public PropertyDBObjectsTableModel(List<Property> properties) {
35- this.properties = properties;
36- }
37-
38- @Override
39- public int getColumnCount() {
40- return 2;
41- }
42-
43- @Override
44- public int getRowCount() {
45- return properties.size();
46- }
47-
48- @Override
49- public String getColumnName(int column) {
50- if (column == 0) {
51- return "name";
52- } else {
53- return "value";
54- }
55- }
56-
57- @Override
58- public Object getValueAt(int rowIndex, int columnIndex) {
59- if (columnIndex == 0) {
60- return properties.get(rowIndex).getName();
61- } else {
62- return properties.get(rowIndex).getValue();
63- }
64- }
65-}
66-
diff -r 43a54fa1463a -r 9784314ce47a src/jdbcacsess2/sqlService/PropertyExportedKeyTableModel.java
--- a/src/jdbcacsess2/sqlService/PropertyExportedKeyTableModel.java Mon Feb 13 22:04:37 2012 +0900
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
1-/*
2- * Copyright 2011 Kazuhiro Shimada
3- *
4- * Licensed under the Apache License, Version 2.0 (the "License");
5- * you may not use this file except in compliance with the License.
6- * You may obtain a copy of the License at
7- *
8- * http://www.apache.org/licenses/LICENSE-2.0
9- *
10- * Unless required by applicable law or agreed to in writing, software
11- * distributed under the License is distributed on an "AS IS" BASIS,
12- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13- * See the License for the specific language governing permissions and
14- * limitations under the License.
15- */
16-
17-package jdbcacsess2.sqlService;
18-
19-import java.util.List;
20-
21-import javax.swing.table.AbstractTableModel;
22-
23-/**
24- * @author sima
25- *
26- */
27-public class PropertyExportedKeyTableModel extends AbstractTableModel {
28- private static final long serialVersionUID = 6816351858372050538L;
29- private List<ReferenceColumnResult> exportKey;
30-
31- public PropertyExportedKeyTableModel(List<ReferenceColumnResult> exportKey) {
32- this.exportKey = exportKey;
33- }
34-
35- @Override
36- public int getColumnCount() {
37- return 14;
38- }
39-
40- @Override
41- public int getRowCount() {
42- return exportKey.size();
43- }
44-
45- @Override
46- public String getColumnName(int column) {
47- switch (column) {
48- case 0:
49- return "PKcat";
50- case 1:
51- return "PKschem";
52- case 2:
53- return "PKtable";
54- case 3:
55- return "PKname";
56- case 4:
57- return "PKcolumn";
58-
59- case 5:
60- return "FKcat";
61- case 6:
62- return "FKschem";
63- case 7:
64- return "FKtable";
65- case 8:
66- return "FKname";
67- case 9:
68- return "FKcolumn";
69-
70- case 10:
71- return "KeySeq";
72-
73- case 11:
74- return "UpdateRule";
75- case 12:
76- return "DeleteRule";
77-
78- case 13:
79- return "Deferrability";
80- }
81- return "";
82- }
83-
84- @Override
85- public Object getValueAt(int rowIndex, int columnIndex) {
86- ReferenceColumnResult r = exportKey.get(rowIndex);
87-
88- switch (columnIndex) {
89- case 0:
90- return r.getPktableCat();
91- case 1:
92- return r.getPktableSchem();
93- case 2:
94- return r.getPktableName();
95- case 3:
96- return r.getPkName();
97- case 4:
98- return r.getPkcolumnName();
99-
100- case 5:
101- return r.getFktableCat();
102- case 6:
103- return r.getFktableSchem();
104- case 7:
105- return r.getFktableName();
106- case 8:
107- return r.getFkName();
108- case 9:
109- return r.getFkcolumnName();
110-
111- case 10:
112- return r.getKeySeq();
113-
114- case 11:
115- return r.getUpdateRuleName();
116- case 12:
117- return r.getDeleteRuleName();
118-
119- case 13:
120- return r.getDeferrabilityName();
121- }
122- return null;
123- }
124-
125-}
diff -r 43a54fa1463a -r 9784314ce47a src/jdbcacsess2/sqlService/ResultsTableModel.java
--- a/src/jdbcacsess2/sqlService/ResultsTableModel.java Mon Feb 13 22:04:37 2012 +0900
+++ b/src/jdbcacsess2/sqlService/ResultsTableModel.java Tue Feb 14 21:26:34 2012 +0900
@@ -25,7 +25,7 @@
2525 import javax.swing.table.AbstractTableModel;
2626
2727 import jdbcacsess2.main.Jdbcacsess2;
28-import jdbcacsess2.sqlService.SqlExecuteSentencies.SqlExecuteSentence;
28+import jdbcacsess2.sqlService.parse.SqlExecuteSentencies.SqlExecuteSentence;
2929
3030 /**
3131 * @author sima
diff -r 43a54fa1463a -r 9784314ce47a src/jdbcacsess2/sqlService/SqlAsyncExecute.java
--- a/src/jdbcacsess2/sqlService/SqlAsyncExecute.java Mon Feb 13 22:04:37 2012 +0900
+++ b/src/jdbcacsess2/sqlService/SqlAsyncExecute.java Tue Feb 14 21:26:34 2012 +0900
@@ -31,8 +31,9 @@
3131 import jdbcacsess2.main.Jdbcacsess2;
3232 import jdbcacsess2.main.ShowDialog;
3333 import jdbcacsess2.sqlService.SqlExecuteParmeter.Parameter;
34-import jdbcacsess2.sqlService.SqlExecuteSentencies.SqlExecuteSentence;
3534 import jdbcacsess2.sqlService.exception.DbConnectIllgalStateException;
35+import jdbcacsess2.sqlService.parse.SqlExecuteSentencies;
36+import jdbcacsess2.sqlService.parse.SqlExecuteSentencies.SqlExecuteSentence;
3637
3738 /**
3839 * SQL文を実行し、リスナーを通して処理結果を通知します。
diff -r 43a54fa1463a -r 9784314ce47a src/jdbcacsess2/sqlService/SqlExecuteSentencies.java
--- a/src/jdbcacsess2/sqlService/SqlExecuteSentencies.java Mon Feb 13 22:04:37 2012 +0900
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,243 +0,0 @@
1-/*
2- * Copyright 2011 Kazuhiro Shimada
3- *
4- * Licensed under the Apache License, Version 2.0 (the "License");
5- * you may not use this file except in compliance with the License.
6- * You may obtain a copy of the License at
7- *
8- * http://www.apache.org/licenses/LICENSE-2.0
9- *
10- * Unless required by applicable law or agreed to in writing, software
11- * distributed under the License is distributed on an "AS IS" BASIS,
12- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13- * See the License for the specific language governing permissions and
14- * limitations under the License.
15- */
16-package jdbcacsess2.sqlService;
17-
18-import java.util.ArrayList;
19-import java.util.regex.Pattern;
20-
21-import jdbcacsess2.main.Jdbcacsess2;
22-
23-/**
24- * SQL文を解析し、最初の命令句/入力変数/更新可能SELECT文であるか?などを抽出します。
25- *
26- * 画面から入力されたSQLが複数文であった場合、1SQL文毎に分解されます。 SQL文の区切りは{@link SqlSentenceParse}
27- * で行われるので、通知されたSQL文の番号を使用して、それぞれのSQL文を区別します。
28- *
29- * @author sima
30- *
31- */
32-public class SqlExecuteSentencies {
33-
34- /**
35- * コンストラクタ、SQL文のparseを行う。
36- *
37- * @param sqlSentence
38- * 分析したいSQL文
39- * @param sentenceSeparator
40- * 複数SQL文を区切り正規表現文字列
41- */
42- public SqlExecuteSentencies(String sqlSentence, String sentenceSeparator) {
43-
44-
45- final SqlSentenceParse sqlSentenceParse = new SqlSentenceParse();
46-
47- sqlSentenceParse.addSqlSentenceListener(new SqlExecuteSentence());
48-
49- sqlSentenceParse.registSeparatePattern(Pattern.compile(sentenceSeparator));
50- sqlSentenceParse.registSeparateListener(new SqlSentenceSparateListener() {
51- @Override
52- public void rangeSeparate(String matchKeyword,
53- int beginPosition,
54- int endPosition,
55- Pattern pattern) {
56- sqlSentenceParse.removeAllSqlSentenceListener();
57- sqlSentenceParse.addSqlSentenceListener(new SqlExecuteSentence());
58- }
59- });
60-
61- // 解析開始
62- sqlSentenceParse.parse(sqlSentence);
63-
64- Jdbcacsess2.logger.info(sqlExecuteSentenceList.toString());
65- }
66-
67- private int seq = 0;
68- final private ArrayList<SqlExecuteSentence> sqlExecuteSentenceList = new ArrayList<SqlExecuteSentence>();
69-
70- /**
71- * SQL文単位に分解された最終結果
72- *
73- * @return SQL文解析結果のリスト
74- */
75- public ArrayList<SqlExecuteSentence> getSqlExecuteSentenceList() {
76- return sqlExecuteSentenceList;
77- }
78-
79- /**
80- * 分解された1SQL文の解析結果
81- *
82- * @author sima
83- *
84- */
85- public class SqlExecuteSentence implements SqlSentenceListener {
86-
87- private String sqlSentence;
88- private int sentenceCount;
89-
90- /**
91- * SQLの連番
92- *
93- * @return sentenceCount
94- */
95- public int getSentenceCount() {
96- return sentenceCount;
97- }
98-
99- /**
100- * SQL文
101- *
102- * @return sqlSentence
103- */
104- public String getSqlSentence() {
105- return sqlSentence;
106- }
107-
108- private SqlInputParameter sqlInputParameter = new SqlInputParameter();
109-
110- /**
111- * 入力パラメータ
112- *
113- * @return sqlInputParameter
114- */
115- public SqlInputParameter getSqlInputParameter() {
116- return sqlInputParameter;
117- }
118-
119- private String sqlCommand;
120-
121- /**
122- * SQL文の最初の命令句
123- *
124- * @return "SELECT","INSERT"."DELETE","CALL","CREATE","ALTER"等の文字列。
125- * 常に大文字で返却されます 。
126- */
127- public String getSqlCommand() {
128- return sqlCommand;
129- }
130-
131- private boolean editable = false;
132-
133- /**
134- * 更新可能SELECT文であるか
135- *
136- * @return editable
137- */
138- public boolean isEditable() {
139- return editable;
140- }
141-
142- private int phraseCnt = 0;
143- private boolean checkEnd = false;
144- private boolean select = false;
145- private boolean from = false;
146-
147- @Override
148- public void started(String sqlSentence) {
149- // finished で上書きされるの意味はない
150- this.sqlSentence = sqlSentence;
151- }
152-
153- @Override
154- public void rangeInput(String phrase, int begin, int end) {
155- sqlInputParameter.addInputItemName(phrase);
156- }
157-
158- @Override
159- public void rangePhrase(String phrase, int begin, int end) {
160- if (checkEnd) {
161- return;
162- }
163- String upperPhrase = phrase.toUpperCase();
164-
165- phraseCnt++;
166- if (phraseCnt == 1 && upperPhrase.equals("SELECT")) {
167- select = true;
168- return;
169- }
170- if (!select) {
171- checkEnd = true;
172- editable = false;
173- return;
174- }
175- if (upperPhrase.equals("SELECT") || upperPhrase.equals("GROUP")) {
176- checkEnd = true;
177- editable = false;
178- return;
179- }
180-
181- if (upperPhrase.equals("FROM")) {
182- // FROM句を見つけたので、とりあえず更新可能とする
183- editable = true;
184-
185- from = true;
186- return;
187- }
188- if (upperPhrase.equals("WHERE")) {
189- from = false;
190- return;
191- }
192-
193- }
194-
195- @Override
196- public void rangeSymbol(String symbol, int begin, int end) {
197- if (checkEnd) {
198- return;
199- }
200- if (from && symbol.equals(",")) {
201- // FROM句中にカンマを見つけたので、更新不可が確定した
202- checkEnd = true;
203- editable = false;
204- return;
205- }
206- }
207-
208- @Override
209- public void finished(String sentence, String command) {
210- sqlSentence = sentence;
211- sqlCommand = command;
212- if (!sqlCommand.equals("")) {
213- sentenceCount = ++seq;
214- if (sqlCommand.equals("CREATE") || sqlCommand.equals("ALTER")) {
215- sqlInputParameter.clear();
216- }
217- sqlExecuteSentenceList.add(this);
218- }
219- }
220-
221- @Override
222- public void rangeComment(String comment, int begin, int end) {
223- }
224-
225- @Override
226- public void rangeConstant(String constant, int begin, int end) {
227- }
228-
229- @Override
230- public void rangeDelimiter(String delimiter, int begin, int end) {
231- }
232-
233- @Override
234- public String toString() {
235- return "command:" + sqlCommand + " editable:" + editable + " inputItems:"
236- + sqlInputParameter.getInputItemNames() + "["
237- + sqlSentence + "]";
238- }
239-
240- }
241-
242-
243-}
diff -r 43a54fa1463a -r 9784314ce47a src/jdbcacsess2/sqlService/SqlExecutedListener.java
--- a/src/jdbcacsess2/sqlService/SqlExecutedListener.java Mon Feb 13 22:04:37 2012 +0900
+++ b/src/jdbcacsess2/sqlService/SqlExecutedListener.java Tue Feb 14 21:26:34 2012 +0900
@@ -17,7 +17,7 @@
1717
1818 import java.util.List;
1919
20-import jdbcacsess2.sqlService.SqlExecuteSentencies.SqlExecuteSentence;
20+import jdbcacsess2.sqlService.parse.SqlExecuteSentencies.SqlExecuteSentence;
2121
2222 /**
2323 * SQL実行結果の通知するリスナーです。
diff -r 43a54fa1463a -r 9784314ce47a src/jdbcacsess2/sqlService/SqlInputParameter.java
--- a/src/jdbcacsess2/sqlService/SqlInputParameter.java Mon Feb 13 22:04:37 2012 +0900
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
1-/*
2- * Copyright 2011 Kazuhiro Shimada
3- *
4- * Licensed under the Apache License, Version 2.0 (the "License");
5- * you may not use this file except in compliance with the License.
6- * You may obtain a copy of the License at
7- *
8- * http://www.apache.org/licenses/LICENSE-2.0
9- *
10- * Unless required by applicable law or agreed to in writing, software
11- * distributed under the License is distributed on an "AS IS" BASIS,
12- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13- * See the License for the specific language governing permissions and
14- * limitations under the License.
15- */
16-package jdbcacsess2.sqlService;
17-
18-import java.util.ArrayList;
19-import java.util.HashMap;
20-
21-import jdbcacsess2.sqlService.SqlExecuteParmeter.Parameter;
22-
23-/**
24- *
25- * SQL文の入力パラメータに関する情報を、1つの実行SQL文分だけ集めたクラスです。
26- * 1SQL文には複数のパラメータが想定されるので、それぞれの内容はArrayListでリスト化されています。
27- * <ul>
28- * <li>SQL文中に記述された入力パラメータの名称:{@link SqlExecuteSentencies.SqlExecuteSentence}
29- * が解析した結果を格納する事を想定しています。
30- * <li>入力パラメータの値とそのSQLTYPE:3パターンの使い方が出来ます。
31- * <ol>
32- * <li>パラメータが無い
33- * <li>入力パラメータを指定しSQLを1回だけ実行する時
34- * <li>1つのSQLで入力パラメータを切り替えながら順次実行する
35- * </ol>
36- * 3番目の使用方法は、PrepareしたSQL文に対して、入力パラメータの設定とexecuteが、複数回実行されるイメージです。
37- * </ul>
38- *
39- * @author sima
40- *
41- */
42-public class SqlInputParameter {
43-
44- private final Parameter parameter;
45-
46- public SqlInputParameter() {
47- parameter = new SqlExecuteParmeter.Parameter();
48- parameter.values = new ArrayList<Object>();
49- parameter.sqlTypes = new HashMap<Integer, ConstSqlTypes>();
50- }
51-
52- /**
53- * 入力パラメータ名のSQL文字句要素
54- */
55- final private ArrayList<String> inputItemNames = new ArrayList<String>();
56-
57- /**
58- * 入力パラメータ名のSQL文字句要素を返却します。このリストの順番に
59- * {@link SqlInputParameter#addParameter(Object, ConstSqlTypes)}
60- * でパラメータを設定する必要があります。
61- *
62- * @return
63- */
64- public ArrayList<String> getInputItemNames() {
65- return inputItemNames;
66- }
67-
68- /**
69- * 入力パラメータ名のSQL文字句要素を追加します。これは、{@link SqlExecuteSentencies}が結果格納する時に使用されます。
70- *
71- * @param inputItemName
72- */
73- void addInputItemName(String inputItemName) {
74- inputItemNames.add(inputItemName);
75- }
76-
77- /**
78- * パラメータの値とタイプをパラメータリストの最後に追加します。
79- *
80- * @param value
81- * 値
82- * @param constSqlType
83- * 値のSQLTYPE
84- */
85- public void addParameter(Object value, ConstSqlTypes constSqlType) {
86- addParameter(parameter.values.size() - 1, value, constSqlType);
87- }
88-
89- /**
90- * パラメータの値とタイプをパラメータリストの順番を指定して追加します。
91- *
92- * @param index
93- * {@link SqlInputParameter#inputItemNames}のリストに存在するindex
94- * @param value
95- * 値
96- * @param constSqlType
97- * 値のSQLTYPE
98- */
99- public void addParameter(Integer index, Object value, ConstSqlTypes constSqlType) {
100- inputItemNames.get(index); // check
101-
102- parameter.values.add(value);
103- parameter.sqlTypes.put(index, constSqlType);
104- }
105-
106- SqlExecuteParmeter getSqlExecuteParmeter() {
107- return sqlExecuteParmeter;
108- }
109-
110- /**
111- * デフォルトではパラメータ値は通常1SQLで1組となっています。<br>
112- * 同一SQLで複数組を処理したい場合、値とSQLTYPEを順次外部から与える方法を指定出来ます。
113- *
114- * @param sqlExecuteParmeter
115- * {@link SqlExecuteParmeter}を実装した値とSQLTYPEの生成器。
116- */
117- public void setSqlExecuteParmeter(SqlExecuteParmeter sqlExecuteParmeter) {
118- this.sqlExecuteParmeter = sqlExecuteParmeter;
119- }
120-
121- private SqlExecuteParmeter sqlExecuteParmeter = new SqlExecuteParmeter() {
122-
123- boolean flg = true;
124-
125- @Override
126- public boolean hasNext() {
127- // 1回目の呼出はtrue、2回目以降はfalse
128- if (flg) {
129- flg = false;
130- return true;
131- }
132- return false;
133- }
134-
135- @Override
136- public Parameter getParameter() {
137- return parameter;
138- }
139- };
140-
141- /**
142- * 入力パラメータ名とパラメータ値を全て初期化します。
143- */
144- public void clear() {
145- inputItemNames.clear();
146- parameter.values.clear();
147- parameter.sqlTypes.clear();
148- }
149-
150-}
diff -r 43a54fa1463a -r 9784314ce47a src/jdbcacsess2/sqlService/SqlSentenceListener.java
--- a/src/jdbcacsess2/sqlService/SqlSentenceListener.java Mon Feb 13 22:04:37 2012 +0900
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
1-/*
2- * Copyright 2011 Kazuhiro Shimada
3- *
4- * Licensed under the Apache License, Version 2.0 (the "License");
5- * you may not use this file except in compliance with the License.
6- * You may obtain a copy of the License at
7- *
8- * http://www.apache.org/licenses/LICENSE-2.0
9- *
10- * Unless required by applicable law or agreed to in writing, software
11- * distributed under the License is distributed on an "AS IS" BASIS,
12- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13- * See the License for the specific language governing permissions and
14- * limitations under the License.
15- */
16-package jdbcacsess2.sqlService;
17-
18-
19-/**
20- * SQL文を解析した結果の字句要素を通知するリスナーです。
21- *
22- * @author sima
23- *
24- */
25-public interface SqlSentenceListener {
26-
27- /**
28- * 処理開始
29- *
30- * @param sqlSentence
31- * 解析対象のSQL文
32- */
33- public void started(String sqlSentence);
34-
35- /**
36- * コメント
37- *
38- * @param comment
39- * コメント文字列
40- * @param beginPosition
41- * 開始位置
42- * @param endPosition
43- * 終了位置
44- */
45- public void rangeComment(String comment, int beginPosition, int endPosition);
46-
47- /**
48- * SQL句と要素
49- *
50- * @param phrase
51- * SQL句と要素文字列
52- * @param beginPosition
53- * 開始位置
54- * @param endPosition
55- * 終了位置
56- */
57- public void rangePhrase(String phrase, int beginPosition, int endPosition);
58-
59- /**
60- * SQL句と要素
61- *
62- * @param input
63- * SQL句と要素文字列
64- * @param beginPosition
65- * 開始位置
66- * @param endPosition
67- * 終了位置
68- */
69- public void rangeInput(String input, int beginPosition, int endPosition);
70-
71- /**
72- * 定数
73- *
74- * @param constant
75- * 定数
76- * @param beginPosition
77- * 開始位置
78- * @param endPosition
79- * 終了位置
80- */
81- public void rangeConstant(String constant, int beginPosition, int endPosition);
82-
83- /**
84- * デリミタ
85- *
86- * @param delimiter
87- * デリミタ文字列
88- * @param beginPosition
89- * 開始位置
90- * @param endPosition
91- * 終了位置
92- */
93- public void rangeDelimiter(String delimiter, int beginPosition, int endPosition);
94-
95- /**
96- * 記号
97- *
98- * @param symbol
99- * 記号文字
100- * @param beginPosition
101- * 開始位置
102- * @param endPosition
103- * 終了位置
104- */
105- public void rangeSymbol(String symbol, int beginPosition, int endPosition);
106-
107- /**
108- * 終了
109- *
110- * @param separateSentence
111- * 1SQLに分解されたSQL文
112- * @param command
113- * SQL命令種類(SELECT,INSERT,DELETE,UPDATE,CREATE,ALTER,...)
114- */
115- public void finished(String separateSentence, String command);
116-
117-}
diff -r 43a54fa1463a -r 9784314ce47a src/jdbcacsess2/sqlService/SqlSentenceParse.java
--- a/src/jdbcacsess2/sqlService/SqlSentenceParse.java Mon Feb 13 22:04:37 2012 +0900
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,484 +0,0 @@
1-/*
2- * Copyright 2011 Kazuhiro Shimada
3- *
4- * Licensed under the Apache License, Version 2.0 (the "License");
5- * you may not use this file except in compliance with the License.
6- * You may obtain a copy of the License at
7- *
8- * http://www.apache.org/licenses/LICENSE-2.0
9- *
10- * Unless required by applicable law or agreed to in writing, software
11- * distributed under the License is distributed on an "AS IS" BASIS,
12- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13- * See the License for the specific language governing permissions and
14- * limitations under the License.
15- */
16-package jdbcacsess2.sqlService;
17-
18-import java.util.ArrayList;
19-import java.util.List;
20-import java.util.regex.Matcher;
21-import java.util.regex.Pattern;
22-
23-/**
24- * SQL文を字句要素に分解し、リスナーを通して要素種類毎に通知します。 字句要素は、下記6種類。
25- * <ul>
26- * <li>comment ハイフン開始コメント及び スラッシュアスタリスク範囲領域のコメント
27- * <li>constant アスタリスク範囲領域の文字列定数
28- * <li>symbol 記号
29- * <li>delimiter 区切り文字
30- * <li>input 入力パラメータ
31- * <li>phrase その他を全てSQL句と判定
32- * </ul>
33- * 複数のSQL文を単一のSQLに分解するために、文区切りの正規表現にマッチした時に、リスナーを通じて分区切りを通知します。
34- * その時のリスナーへの通知順は下記のようになります。
35- * <ol>
36- * <li>{@link SqlSentenceListener#started(String)}
37- * <li>{@link SqlSentenceListener#finished(String, String)}
38- * <li>
39- * {@link SqlSentenceSparateListener#rangeSeparate(String, int, int, Pattern)}
40- * <li>{@link SqlSentenceListener#started(String)}
41- * <li>{@link SqlSentenceListener#finished(String, String)}
42- * </ol>
43- */
44-public class SqlSentenceParse {
45-
46- private String sqlSentence;
47-
48- private Pattern separatePattern;
49- private SqlSentenceSparateListener sqlSentenceSparateListener;
50- private final List<SqlSentenceListener> listenerList = new ArrayList<SqlSentenceListener>();
51-
52- /**
53- * 複数SQLを単一SQL文に分解するときの正規表現を登録する
54- *
55- * @param pattern
56- */
57- public void registSeparatePattern(Pattern pattern) {
58- if (pattern == null) {
59- throw new NullPointerException();
60- }
61- separatePattern = pattern;
62- }
63-
64- /**
65- * SQL文の区切りを通知するリスナーを登録する
66- *
67- * @param sqlSentenceSparateListener
68- */
69- public void registSeparateListener(SqlSentenceSparateListener sqlSentenceSparateListener) {
70- this.sqlSentenceSparateListener = sqlSentenceSparateListener;
71- }
72- /**
73- * 字句要素解析結果通知リスナーを登録する
74- *
75- * @param listener
76- */
77- public void addSqlSentenceListener(SqlSentenceListener listener) {
78- if (listener == null) {
79- throw new NullPointerException();
80- }
81- listenerList.add(listener);
82- }
83-
84- /**
85- * 字句要素解析結果通知リスナーを削除する
86- */
87- public void removeSqlSentenceListener(SqlSentenceListener listener) {
88- if (listener == null) {
89- throw new NullPointerException();
90- }
91- listenerList.remove(listener);
92- }
93-
94- /**
95- * 字句要素解析結果通知リスナーを全削除する
96- */
97- public void removeAllSqlSentenceListener() {
98- listenerList.clear();
99- }
100-
101- /**
102- * SQL文を解析し、字句要素に応じて、リスナーのメソッドを呼び出す。
103- *
104- * @param sqlSentence
105- */
106- public void parse(String sqlSentence) {
107- this.sqlSentence = sqlSentence;
108-
109- int sentenceStartPosition = 0;
110-
111- State flg = State.PHRASE;
112-
113- // 解析開始の通知
114- for (SqlSentenceListener l : listenerList)
115- l.started(sqlSentence);
116-
117- // 字句要素範囲を一時保管するオブジェクトの初期化
118- RangePhrase rangePhrase = new RangePhrase();
119- RangeComment rangeComment = new RangeComment();
120- RangeConstant rangeConstant = new RangeConstant();
121- RangeDelimiter rangeDelimiter = new RangeDelimiter();
122- RangeSymbol rangeSymbol = new RangeSymbol();
123-
124- // SQL文を1文字ずつ解析する
125- for (int i = 0; i < sqlSentence.length(); i++) {
126-
127- // コメントは、2文字を同時に判断する必要がある
128- char[] dst = new char[2];
129- if (i == sqlSentence.length() - 1) {
130- sqlSentence.getChars(i, i + 1, dst, 0);
131- dst[1] = 0xff;
132- } else {
133- sqlSentence.getChars(i, i + 2, dst, 0);
134- }
135-
136- // 読み込み文字を判断し、現状態からどの状態に遷移すればよいか決定する。
137- flg = flg.next(dst);
138-
139- // デリミタとSQL句は、終了文字が規定できないので、コメントや定数が始まったら終了とする。
140- // コメントや定数は、明確な終了記号が存在すので、開始・途中・終了のそれぞれを状態として管理する。
141-
142- if (flg == State.HIFUNCOMMENT_START || flg == State.SLASHCOMMENT_START) {
143- rangePhrase.end(i - 1);
144- rangeDelimiter.end(i - 1);
145- rangeComment.begin(i);
146-
147- } else if (flg == State.COMMENT_END) {
148- rangeComment.end(i);
149-
150- } else if (flg == State.APOST_START) {
151- rangePhrase.end(i - 1);
152- rangeDelimiter.end(i - 1);
153- rangeConstant.begin(i);
154-
155- } else if (flg == State.APOST_END) {
156- rangeConstant.end(i);
157-
158- } else if (flg == State.DELIMITER) {
159- rangePhrase.end(i - 1);
160- rangeDelimiter.begin(i);
161-
162- } else if (flg == State.PHRASE) {
163- rangeDelimiter.end(i - 1);
164- rangePhrase.begin(i);
165-
166- } else if (flg == State.SYMBOL_CHAR) {
167- rangeDelimiter.end(i - 1);
168- rangePhrase.end(i - 1);
169- rangeSymbol.begin(i);
170- rangeSymbol.end(i);
171-
172- }
173-
174- if (sqlSentenceSparateListener != null) {
175- if (flg == State.PHRASE || flg == State.SYMBOL_CHAR || flg == State.DELIMITER) {
176- int beginIndex = i;
177- int endIndex = i + 10;
178- if (endIndex > sqlSentence.length()) {
179- endIndex = sqlSentence.length();
180- }
181- Matcher m = separatePattern.matcher(sqlSentence.substring(beginIndex, endIndex));
182- if (m.lookingAt()) {
183- // 解析終了通知
184- for (SqlSentenceListener l : listenerList)
185- l.finished(sqlSentence.substring(sentenceStartPosition, i), rangePhrase.getFirstSqlWord());
186-
187- String matchKeyword = m.group();
188- sqlSentenceSparateListener.rangeSeparate(matchKeyword,
189- i + m.start(),
190- i + m.end(),
191- separatePattern);
192-
193- rangePhrase.setFirstSqlWord("");
194- i = i + m.end() - 1;
195- sentenceStartPosition = i;
196- // 解析開始の通知
197- for (SqlSentenceListener l : listenerList)
198- l.started(sqlSentence.substring(i));
199- }
200- }
201- }
202-
203- }
204-
205- // 中途半端な状態であったらその状態で終了させる。
206- // 但し、どれか一つしかその対象にならない。
207- // rangeSymbolは1文字だけであり、必ず閉じているので必要ない
208- rangePhrase.finish();
209- rangeComment.finish();
210- rangeConstant.finish();
211- rangeDelimiter.finish();
212-
213- // 解析終了通知
214- for (SqlSentenceListener l : listenerList)
215- l.finished(sqlSentence.substring(sentenceStartPosition), rangePhrase.getFirstSqlWord());
216- }
217-
218- /**
219- * 記号文字の集合
220- */
221- static final char[] SYMBOLS = { ',', '(', ')', '!', '+', '-', '*', '/', '=', '<', '>', ';' };
222-
223- /**
224- * 現時点状態に対し、読み込み文字が次状態へ遷移すべきかを決定する。
225- * 例えば、SQL句状態で、コメント開始文字(--や/*)を受け取ったら、コメント開始状態へ遷移する。
226- */
227- enum State {
228- PHRASE {
229- @Override
230- public State next(char[] dst) {
231- if (dst[0] == '/' && dst[1] == '*')
232- return SLASHCOMMENT_START;
233- if (dst[0] == '-' && dst[1] == '-')
234- return HIFUNCOMMENT_START;
235- if (dst[0] == '\'')
236- return APOST_START;
237- if (dst[0] == ' ' || dst[0] == '\t' || dst[0] == '\n')
238- return DELIMITER;
239- for (int i = 0; i < SYMBOLS.length; i++) {
240- if (dst[0] == SYMBOLS[i])
241- return SYMBOL_CHAR;
242- }
243- return this;
244- }
245- },
246- SYMBOL_CHAR {
247- @Override
248- public State next(char[] dst) {
249- return PHRASE.next(dst);
250- }
251- },
252-
253- // APOST state
254- APOST_START {
255- @Override
256- public State next(char[] dst) {
257- if ((dst[0] == '\'' || dst[0] == '\\') && dst[1] == '\'')
258- return APOST_ESCAPE;
259- if ((dst[0] == '\'' || dst[0] == '\\') && dst[1] != '\'')
260- return APOST_END;
261- return APOST;
262- }
263- },
264- APOST {
265- @Override
266- public State next(char[] dst) {
267- if ((dst[0] == '\'' || dst[0] == '\\') && dst[1] == '\'')
268- return APOST_ESCAPE;
269- if ((dst[0] == '\'' || dst[0] == '\\') && dst[1] != '\'')
270- return APOST_END;
271- return this;
272- }
273- },
274- APOST_ESCAPE {
275- @Override
276- public State next(char[] dst) {
277- return APOST;
278- }
279- },
280- APOST_END {
281- @Override
282- public State next(char[] dst) {
283- return PHRASE.next(dst);
284- }
285- },
286-
287- // SLASH COMMENT state
288- SLASHCOMMENT_START {
289- @Override
290- public State next(char[] dst) {
291- return SLASHCOMMENT;
292- }
293- },
294- SLASHCOMMENT {
295- @Override
296- public State next(char[] dst) {
297- if (dst[0] == '*' && dst[1] == '/')
298- return SLASHCOMMENT_PREEND;
299- return this;
300- }
301- },
302- SLASHCOMMENT_PREEND {
303- @Override
304- public State next(char[] dst) {
305- return COMMENT_END;
306- }
307- },
308-
309- // HIFUN COMMENT state
310- HIFUNCOMMENT_START {
311- @Override
312- public State next(char[] dst) {
313- return HIFUNCOMMENT;
314- }
315- },
316- HIFUNCOMMENT {
317- @Override
318- public State next(char[] dst) {
319- if (dst[0] == '\n')
320- return COMMENT_END;
321- return this;
322- }
323- },
324-
325- // COMMENT state end (SLASH and HIFUN)
326- COMMENT_END {
327- @Override
328- public State next(char[] dst) {
329- return PHRASE.next(dst);
330- }
331- },
332-
333- // DELIMITER state
334- DELIMITER {
335- @Override
336- public State next(char[] dst) {
337- return PHRASE.next(dst);
338- }
339- },
340-
341- ;
342-
343- public abstract State next(char[] dst);
344- }
345-
346- /**
347- * 各字句要素の開始位置と終了位置を管理する
348- *
349- * @author sima
350- *
351- */
352- abstract class Range {
353- /**
354- * 範囲指定が有効状態であるかを示す
355- */
356- boolean valid = false;
357-
358- int beginPosition = Integer.MIN_VALUE;
359- int endPosition = Integer.MAX_VALUE;
360-
361- private String firstSqlWord = "";
362-
363- /**
364- * 開始位置を設定し有効状態にする。但し、既に有効の場合は、開始位置を設定せずに復帰する。
365- *
366- * @param beginPosition
367- */
368- void begin(int beginPosition) {
369- if (valid) {
370- return;
371- }
372- this.beginPosition = beginPosition;
373- valid = true;
374- }
375-
376- /**
377- * 開始位置が設定されており、終了が未設定の場合、残りの領域を全て強制終了する。
378- *
379- * @param sqlSentence
380- * @param listeners
381- */
382- void finish() {
383- if (!valid) {
384- return;
385- }
386- end(sqlSentence.length() - 1);
387- }
388-
389- /**
390- * 終了位置を設定し無効状態にする。登録されているリスナーを呼び出す為に各実装クラスのメソッドを呼び出す。
391- * 但し、無効状態の場合は、何もせずに復帰する。
392- *
393- * @param sqlSentence
394- * @param listeners
395- * @param endPosition
396- */
397- void end(int endPosition) {
398- if (!valid) {
399- return;
400- }
401-
402- this.endPosition = endPosition;
403- String word = sqlSentence.substring(beginPosition, endPosition + 1);
404-
405- for (SqlSentenceListener l : listenerList) {
406- fire(l, word);
407- }
408- valid = false;
409- if (getFirstSqlWord().equals("")) {
410- setFirstSqlWord(word);
411- }
412- }
413-
414- /**
415- * リスナーを呼びだす。継承先クラスで呼出処理は実装する。
416- *
417- * @param l
418- * リスナー
419- * @param s
420- * 通知文字列
421- */
422- abstract void fire(SqlSentenceListener l, String sqlWord);
423-
424- @Override
425- public String toString() {
426- return beginPosition + ":" + endPosition;
427- }
428-
429- /**
430- * @param firstSqlWord
431- * セットする firstSqlWord
432- */
433- void setFirstSqlWord(String firstSqlWord) {
434- this.firstSqlWord = firstSqlWord;
435- }
436-
437- /**
438- * @return firstSqlWord
439- */
440- String getFirstSqlWord() {
441- return firstSqlWord.toUpperCase();
442- }
443- }
444-
445- class RangeComment extends Range {
446- @Override
447- void fire(SqlSentenceListener l, String sqlWord) {
448- l.rangeComment(sqlWord, beginPosition, endPosition);
449- }
450- }
451-
452- class RangePhrase extends Range {
453- @Override
454- void fire(SqlSentenceListener l, String sqlWord) {
455- if (sqlWord.startsWith(":") || sqlWord.equals("?")) {
456- l.rangeInput(sqlWord, beginPosition, endPosition);
457- } else {
458- l.rangePhrase(sqlWord, beginPosition, endPosition);
459- }
460- }
461- }
462-
463- class RangeConstant extends Range {
464- @Override
465- void fire(SqlSentenceListener l, String sqlWord) {
466- l.rangeConstant(sqlWord, beginPosition, endPosition);
467- }
468- }
469-
470- class RangeDelimiter extends Range {
471- @Override
472- void fire(SqlSentenceListener l, String sqlWord) {
473- l.rangeDelimiter(sqlWord, beginPosition, endPosition);
474- }
475- }
476-
477- class RangeSymbol extends Range {
478- @Override
479- void fire(SqlSentenceListener l, String sqlWord) {
480- l.rangeSymbol(sqlWord, beginPosition, endPosition);
481- }
482- }
483-
484-}
diff -r 43a54fa1463a -r 9784314ce47a src/jdbcacsess2/sqlService/SqlSentenceSparateListener.java
--- a/src/jdbcacsess2/sqlService/SqlSentenceSparateListener.java Mon Feb 13 22:04:37 2012 +0900
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
1-/*
2- * Copyright 2011 Kazuhiro Shimada
3- *
4- * Licensed under the Apache License, Version 2.0 (the "License");
5- * you may not use this file except in compliance with the License.
6- * You may obtain a copy of the License at
7- *
8- * http://www.apache.org/licenses/LICENSE-2.0
9- *
10- * Unless required by applicable law or agreed to in writing, software
11- * distributed under the License is distributed on an "AS IS" BASIS,
12- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13- * See the License for the specific language governing permissions and
14- * limitations under the License.
15- */
16-
17-package jdbcacsess2.sqlService;
18-
19-import java.util.regex.Pattern;
20-
21-/**
22- * @author sima
23- *
24- */
25-public interface SqlSentenceSparateListener {
26- /**
27- * SQL文セパレータ
28- *
29- * @param matchKeyword
30- * マッチ文字
31- * @param beginPosition
32- * 開始位置
33- * @param endPosition
34- * 終了位置
35- * @param pattern
36- * マッチ時の正規表現
37- */
38- public void rangeSeparate(String matchKeyword, int beginPosition, int endPosition, Pattern pattern);
39-
40-}
diff -r 43a54fa1463a -r 9784314ce47a src/jdbcacsess2/sqlService/dbobject/PropertyDBObjectsTableModel.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdbcacsess2/sqlService/dbobject/PropertyDBObjectsTableModel.java Tue Feb 14 21:26:34 2012 +0900
@@ -0,0 +1,66 @@
1+/*
2+ * Copyright 2011 Kazuhiro Shimada
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+
17+package jdbcacsess2.sqlService.dbobject;
18+
19+import java.util.List;
20+
21+import javax.swing.table.AbstractTableModel;
22+
23+import jdbcacsess2.sqlService.dbobject.DBObject.Property;
24+
25+/**
26+ * @author sima
27+ *
28+ */
29+public class PropertyDBObjectsTableModel extends AbstractTableModel {
30+ private static final long serialVersionUID = 3293479625219161204L;
31+
32+ private final List<Property> properties;
33+
34+ public PropertyDBObjectsTableModel(List<Property> properties) {
35+ this.properties = properties;
36+ }
37+
38+ @Override
39+ public int getColumnCount() {
40+ return 2;
41+ }
42+
43+ @Override
44+ public int getRowCount() {
45+ return properties.size();
46+ }
47+
48+ @Override
49+ public String getColumnName(int column) {
50+ if (column == 0) {
51+ return "name";
52+ } else {
53+ return "value";
54+ }
55+ }
56+
57+ @Override
58+ public Object getValueAt(int rowIndex, int columnIndex) {
59+ if (columnIndex == 0) {
60+ return properties.get(rowIndex).getName();
61+ } else {
62+ return properties.get(rowIndex).getValue();
63+ }
64+ }
65+}
66+
diff -r 43a54fa1463a -r 9784314ce47a src/jdbcacsess2/sqlService/dbobject/PropertyExportedKeyTableModel.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdbcacsess2/sqlService/dbobject/PropertyExportedKeyTableModel.java Tue Feb 14 21:26:34 2012 +0900
@@ -0,0 +1,127 @@
1+/*
2+ * Copyright 2011 Kazuhiro Shimada
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+
17+package jdbcacsess2.sqlService.dbobject;
18+
19+import java.util.List;
20+
21+import javax.swing.table.AbstractTableModel;
22+
23+import jdbcacsess2.sqlService.ReferenceColumnResult;
24+
25+/**
26+ * @author sima
27+ *
28+ */
29+public class PropertyExportedKeyTableModel extends AbstractTableModel {
30+ private static final long serialVersionUID = 6816351858372050538L;
31+ private List<ReferenceColumnResult> exportKey;
32+
33+ public PropertyExportedKeyTableModel(List<ReferenceColumnResult> exportKey) {
34+ this.exportKey = exportKey;
35+ }
36+
37+ @Override
38+ public int getColumnCount() {
39+ return 14;
40+ }
41+
42+ @Override
43+ public int getRowCount() {
44+ return exportKey.size();
45+ }
46+
47+ @Override
48+ public String getColumnName(int column) {
49+ switch (column) {
50+ case 0:
51+ return "PKcat";
52+ case 1:
53+ return "PKschem";
54+ case 2:
55+ return "PKtable";
56+ case 3:
57+ return "PKname";
58+ case 4:
59+ return "PKcolumn";
60+
61+ case 5:
62+ return "FKcat";
63+ case 6:
64+ return "FKschem";
65+ case 7:
66+ return "FKtable";
67+ case 8:
68+ return "FKname";
69+ case 9:
70+ return "FKcolumn";
71+
72+ case 10:
73+ return "KeySeq";
74+
75+ case 11:
76+ return "UpdateRule";
77+ case 12:
78+ return "DeleteRule";
79+
80+ case 13:
81+ return "Deferrability";
82+ }
83+ return "";
84+ }
85+
86+ @Override
87+ public Object getValueAt(int rowIndex, int columnIndex) {
88+ ReferenceColumnResult r = exportKey.get(rowIndex);
89+
90+ switch (columnIndex) {
91+ case 0:
92+ return r.getPktableCat();
93+ case 1:
94+ return r.getPktableSchem();
95+ case 2:
96+ return r.getPktableName();
97+ case 3:
98+ return r.getPkName();
99+ case 4:
100+ return r.getPkcolumnName();
101+
102+ case 5:
103+ return r.getFktableCat();
104+ case 6:
105+ return r.getFktableSchem();
106+ case 7:
107+ return r.getFktableName();
108+ case 8:
109+ return r.getFkName();
110+ case 9:
111+ return r.getFkcolumnName();
112+
113+ case 10:
114+ return r.getKeySeq();
115+
116+ case 11:
117+ return r.getUpdateRuleName();
118+ case 12:
119+ return r.getDeleteRuleName();
120+
121+ case 13:
122+ return r.getDeferrabilityName();
123+ }
124+ return null;
125+ }
126+
127+}
diff -r 43a54fa1463a -r 9784314ce47a src/jdbcacsess2/sqlService/history/Record.java
--- a/src/jdbcacsess2/sqlService/history/Record.java Mon Feb 13 22:04:37 2012 +0900
+++ b/src/jdbcacsess2/sqlService/history/Record.java Tue Feb 14 21:26:34 2012 +0900
@@ -25,10 +25,10 @@
2525 import jdbcacsess2.main.Config;
2626 import jdbcacsess2.main.ShowDialog;
2727 import jdbcacsess2.sqlService.ColumnAttributeResult;
28-import jdbcacsess2.sqlService.SqlExecuteSentencies.SqlExecuteSentence;
2928 import jdbcacsess2.sqlService.SqlExecuteTask;
3029 import jdbcacsess2.sqlService.SqlExecutedListener;
3130 import jdbcacsess2.sqlService.history.ExecHistory.ResultStatus;
31+import jdbcacsess2.sqlService.parse.SqlExecuteSentencies.SqlExecuteSentence;
3232 import net.java.ao.DBParam;
3333 import net.java.ao.EntityManager;
3434
diff -r 43a54fa1463a -r 9784314ce47a src/jdbcacsess2/sqlService/parse/SqlExecuteSentencies.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdbcacsess2/sqlService/parse/SqlExecuteSentencies.java Tue Feb 14 21:26:34 2012 +0900
@@ -0,0 +1,243 @@
1+/*
2+ * Copyright 2011 Kazuhiro Shimada
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+package jdbcacsess2.sqlService.parse;
17+
18+import java.util.ArrayList;
19+import java.util.regex.Pattern;
20+
21+import jdbcacsess2.main.Jdbcacsess2;
22+
23+/**
24+ * SQL文を解析し、最初の命令句/入力変数/更新可能SELECT文であるか?などを抽出します。
25+ *
26+ * 画面から入力されたSQLが複数文であった場合、1SQL文毎に分解されます。 SQL文の区切りは{@link SqlSentenceParse}
27+ * で行われるので、通知されたSQL文の番号を使用して、それぞれのSQL文を区別します。
28+ *
29+ * @author sima
30+ *
31+ */
32+public class SqlExecuteSentencies {
33+
34+ /**
35+ * コンストラクタ、SQL文のparseを行う。
36+ *
37+ * @param sqlSentence
38+ * 分析したいSQL文
39+ * @param sentenceSeparator
40+ * 複数SQL文を区切り正規表現文字列
41+ */
42+ public SqlExecuteSentencies(String sqlSentence, String sentenceSeparator) {
43+
44+
45+ final SqlSentenceParse sqlSentenceParse = new SqlSentenceParse();
46+
47+ sqlSentenceParse.addSqlSentenceListener(new SqlExecuteSentence());
48+
49+ sqlSentenceParse.registSeparatePattern(Pattern.compile(sentenceSeparator));
50+ sqlSentenceParse.registSeparateListener(new SqlSentenceSparateListener() {
51+ @Override
52+ public void rangeSeparate(String matchKeyword,
53+ int beginPosition,
54+ int endPosition,
55+ Pattern pattern) {
56+ sqlSentenceParse.removeAllSqlSentenceListener();
57+ sqlSentenceParse.addSqlSentenceListener(new SqlExecuteSentence());
58+ }
59+ });
60+
61+ // 解析開始
62+ sqlSentenceParse.parse(sqlSentence);
63+
64+ Jdbcacsess2.logger.info(sqlExecuteSentenceList.toString());
65+ }
66+
67+ private int seq = 0;
68+ final private ArrayList<SqlExecuteSentence> sqlExecuteSentenceList = new ArrayList<SqlExecuteSentence>();
69+
70+ /**
71+ * SQL文単位に分解された最終結果
72+ *
73+ * @return SQL文解析結果のリスト
74+ */
75+ public ArrayList<SqlExecuteSentence> getSqlExecuteSentenceList() {
76+ return sqlExecuteSentenceList;
77+ }
78+
79+ /**
80+ * 分解された1SQL文の解析結果
81+ *
82+ * @author sima
83+ *
84+ */
85+ public class SqlExecuteSentence implements SqlSentenceListener {
86+
87+ private String sqlSentence;
88+ private int sentenceCount;
89+
90+ /**
91+ * SQLの連番
92+ *
93+ * @return sentenceCount
94+ */
95+ public int getSentenceCount() {
96+ return sentenceCount;
97+ }
98+
99+ /**
100+ * SQL文
101+ *
102+ * @return sqlSentence
103+ */
104+ public String getSqlSentence() {
105+ return sqlSentence;
106+ }
107+
108+ private final SqlInputParameter sqlInputParameter = new SqlInputParameter();
109+
110+ /**
111+ * 入力パラメータ
112+ *
113+ * @return sqlInputParameter
114+ */
115+ public SqlInputParameter getSqlInputParameter() {
116+ return sqlInputParameter;
117+ }
118+
119+ private String sqlCommand;
120+
121+ /**
122+ * SQL文の最初の命令句
123+ *
124+ * @return "SELECT","INSERT"."DELETE","CALL","CREATE","ALTER"等の文字列。
125+ * 常に大文字で返却されます 。
126+ */
127+ public String getSqlCommand() {
128+ return sqlCommand;
129+ }
130+
131+ private boolean editable = false;
132+
133+ /**
134+ * 更新可能SELECT文であるか
135+ *
136+ * @return editable
137+ */
138+ public boolean isEditable() {
139+ return editable;
140+ }
141+
142+ private int phraseCnt = 0;
143+ private boolean checkEnd = false;
144+ private boolean select = false;
145+ private boolean from = false;
146+
147+ @Override
148+ public void started(String sqlSentence) {
149+ // finished で上書きされるの意味はない
150+ this.sqlSentence = sqlSentence;
151+ }
152+
153+ @Override
154+ public void rangeInput(String phrase, int begin, int end) {
155+ sqlInputParameter.addInputItemName(phrase);
156+ }
157+
158+ @Override
159+ public void rangePhrase(String phrase, int begin, int end) {
160+ if (checkEnd) {
161+ return;
162+ }
163+ String upperPhrase = phrase.toUpperCase();
164+
165+ phraseCnt++;
166+ if (phraseCnt == 1 && upperPhrase.equals("SELECT")) {
167+ select = true;
168+ return;
169+ }
170+ if (!select) {
171+ checkEnd = true;
172+ editable = false;
173+ return;
174+ }
175+ if (upperPhrase.equals("SELECT") || upperPhrase.equals("GROUP")) {
176+ checkEnd = true;
177+ editable = false;
178+ return;
179+ }
180+
181+ if (upperPhrase.equals("FROM")) {
182+ // FROM句を見つけたので、とりあえず更新可能とする
183+ editable = true;
184+
185+ from = true;
186+ return;
187+ }
188+ if (upperPhrase.equals("WHERE")) {
189+ from = false;
190+ return;
191+ }
192+
193+ }
194+
195+ @Override
196+ public void rangeSymbol(String symbol, int begin, int end) {
197+ if (checkEnd) {
198+ return;
199+ }
200+ if (from && symbol.equals(",")) {
201+ // FROM句中にカンマを見つけたので、更新不可が確定した
202+ checkEnd = true;
203+ editable = false;
204+ return;
205+ }
206+ }
207+
208+ @Override
209+ public void finished(String sentence, String command) {
210+ sqlSentence = sentence;
211+ sqlCommand = command;
212+ if (!sqlCommand.equals("")) {
213+ sentenceCount = ++seq;
214+ if (sqlCommand.equals("CREATE") || sqlCommand.equals("ALTER")) {
215+ sqlInputParameter.clear();
216+ }
217+ sqlExecuteSentenceList.add(this);
218+ }
219+ }
220+
221+ @Override
222+ public void rangeComment(String comment, int begin, int end) {
223+ }
224+
225+ @Override
226+ public void rangeConstant(String constant, int begin, int end) {
227+ }
228+
229+ @Override
230+ public void rangeDelimiter(String delimiter, int begin, int end) {
231+ }
232+
233+ @Override
234+ public String toString() {
235+ return "command:" + sqlCommand + " editable:" + editable + " inputItems:"
236+ + sqlInputParameter.getInputItemNames() + "["
237+ + sqlSentence + "]";
238+ }
239+
240+ }
241+
242+
243+}
diff -r 43a54fa1463a -r 9784314ce47a src/jdbcacsess2/sqlService/parse/SqlInputParameter.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdbcacsess2/sqlService/parse/SqlInputParameter.java Tue Feb 14 21:26:34 2012 +0900
@@ -0,0 +1,152 @@
1+/*
2+ * Copyright 2011 Kazuhiro Shimada
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+package jdbcacsess2.sqlService.parse;
17+
18+import java.util.ArrayList;
19+import java.util.HashMap;
20+
21+import jdbcacsess2.sqlService.ConstSqlTypes;
22+import jdbcacsess2.sqlService.SqlExecuteParmeter;
23+import jdbcacsess2.sqlService.SqlExecuteParmeter.Parameter;
24+
25+/**
26+ *
27+ * SQL文の入力パラメータに関する情報を、1つの実行SQL文分だけ集めたクラスです。
28+ * 1SQL文には複数のパラメータが想定されるので、それぞれの内容はArrayListでリスト化されています。
29+ * <ul>
30+ * <li>SQL文中に記述された入力パラメータの名称:{@link SqlExecuteSentencies.SqlExecuteSentence}
31+ * が解析した結果を格納する事を想定しています。
32+ * <li>入力パラメータの値とそのSQLTYPE:3パターンの使い方が出来ます。
33+ * <ol>
34+ * <li>パラメータが無い
35+ * <li>入力パラメータを指定しSQLを1回だけ実行する時
36+ * <li>1つのSQLで入力パラメータを切り替えながら順次実行する
37+ * </ol>
38+ * 3番目の使用方法は、PrepareしたSQL文に対して、入力パラメータの設定とexecuteが、複数回実行されるイメージです。
39+ * </ul>
40+ *
41+ * @author sima
42+ *
43+ */
44+public class SqlInputParameter {
45+
46+ private final Parameter parameter;
47+
48+ public SqlInputParameter() {
49+ parameter = new SqlExecuteParmeter.Parameter();
50+ parameter.values = new ArrayList<Object>();
51+ parameter.sqlTypes = new HashMap<Integer, ConstSqlTypes>();
52+ }
53+
54+ /**
55+ * 入力パラメータ名のSQL文字句要素
56+ */
57+ final private ArrayList<String> inputItemNames = new ArrayList<String>();
58+
59+ /**
60+ * 入力パラメータ名のSQL文字句要素を返却します。このリストの順番に
61+ * {@link SqlInputParameter#addParameter(Object, ConstSqlTypes)}
62+ * でパラメータを設定する必要があります。
63+ *
64+ * @return
65+ */
66+ public ArrayList<String> getInputItemNames() {
67+ return inputItemNames;
68+ }
69+
70+ /**
71+ * 入力パラメータ名のSQL文字句要素を追加します。これは、{@link SqlExecuteSentencies}が結果格納する時に使用されます。
72+ *
73+ * @param inputItemName
74+ */
75+ void addInputItemName(String inputItemName) {
76+ inputItemNames.add(inputItemName);
77+ }
78+
79+ /**
80+ * パラメータの値とタイプをパラメータリストの最後に追加します。
81+ *
82+ * @param value
83+ * 値
84+ * @param constSqlType
85+ * 値のSQLTYPE
86+ */
87+ public void addParameter(Object value, ConstSqlTypes constSqlType) {
88+ addParameter(parameter.values.size() - 1, value, constSqlType);
89+ }
90+
91+ /**
92+ * パラメータの値とタイプをパラメータリストの順番を指定して追加します。
93+ *
94+ * @param index
95+ * {@link SqlInputParameter#inputItemNames}のリストに存在するindex
96+ * @param value
97+ * 値
98+ * @param constSqlType
99+ * 値のSQLTYPE
100+ */
101+ public void addParameter(Integer index, Object value, ConstSqlTypes constSqlType) {
102+ inputItemNames.get(index); // check
103+
104+ parameter.values.add(value);
105+ parameter.sqlTypes.put(index, constSqlType);
106+ }
107+
108+ public SqlExecuteParmeter getSqlExecuteParmeter() {
109+ return sqlExecuteParmeter;
110+ }
111+
112+ /**
113+ * デフォルトではパラメータ値は通常1SQLで1組となっています。<br>
114+ * 同一SQLで複数組を処理したい場合、値とSQLTYPEを順次外部から与える方法を指定出来ます。
115+ *
116+ * @param sqlExecuteParmeter
117+ * {@link SqlExecuteParmeter}を実装した値とSQLTYPEの生成器。
118+ */
119+ public void setSqlExecuteParmeter(SqlExecuteParmeter sqlExecuteParmeter) {
120+ this.sqlExecuteParmeter = sqlExecuteParmeter;
121+ }
122+
123+ private SqlExecuteParmeter sqlExecuteParmeter = new SqlExecuteParmeter() {
124+
125+ boolean flg = true;
126+
127+ @Override
128+ public boolean hasNext() {
129+ // 1回目の呼出はtrue、2回目以降はfalse
130+ if (flg) {
131+ flg = false;
132+ return true;
133+ }
134+ return false;
135+ }
136+
137+ @Override
138+ public Parameter getParameter() {
139+ return parameter;
140+ }
141+ };
142+
143+ /**
144+ * 入力パラメータ名とパラメータ値を全て初期化します。
145+ */
146+ public void clear() {
147+ inputItemNames.clear();
148+ parameter.values.clear();
149+ parameter.sqlTypes.clear();
150+ }
151+
152+}
diff -r 43a54fa1463a -r 9784314ce47a src/jdbcacsess2/sqlService/parse/SqlSentenceListener.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdbcacsess2/sqlService/parse/SqlSentenceListener.java Tue Feb 14 21:26:34 2012 +0900
@@ -0,0 +1,117 @@
1+/*
2+ * Copyright 2011 Kazuhiro Shimada
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+package jdbcacsess2.sqlService.parse;
17+
18+
19+/**
20+ * SQL文を解析した結果の字句要素を通知するリスナーです。
21+ *
22+ * @author sima
23+ *
24+ */
25+public interface SqlSentenceListener {
26+
27+ /**
28+ * 処理開始
29+ *
30+ * @param sqlSentence
31+ * 解析対象のSQL文
32+ */
33+ public void started(String sqlSentence);
34+
35+ /**
36+ * コメント
37+ *
38+ * @param comment
39+ * コメント文字列
40+ * @param beginPosition
41+ * 開始位置
42+ * @param endPosition
43+ * 終了位置
44+ */
45+ public void rangeComment(String comment, int beginPosition, int endPosition);
46+
47+ /**
48+ * SQL句と要素
49+ *
50+ * @param phrase
51+ * SQL句と要素文字列
52+ * @param beginPosition
53+ * 開始位置
54+ * @param endPosition
55+ * 終了位置
56+ */
57+ public void rangePhrase(String phrase, int beginPosition, int endPosition);
58+
59+ /**
60+ * SQL句と要素
61+ *
62+ * @param input
63+ * SQL句と要素文字列
64+ * @param beginPosition
65+ * 開始位置
66+ * @param endPosition
67+ * 終了位置
68+ */
69+ public void rangeInput(String input, int beginPosition, int endPosition);
70+
71+ /**
72+ * 定数
73+ *
74+ * @param constant
75+ * 定数
76+ * @param beginPosition
77+ * 開始位置
78+ * @param endPosition
79+ * 終了位置
80+ */
81+ public void rangeConstant(String constant, int beginPosition, int endPosition);
82+
83+ /**
84+ * デリミタ
85+ *
86+ * @param delimiter
87+ * デリミタ文字列
88+ * @param beginPosition
89+ * 開始位置
90+ * @param endPosition
91+ * 終了位置
92+ */
93+ public void rangeDelimiter(String delimiter, int beginPosition, int endPosition);
94+
95+ /**
96+ * 記号
97+ *
98+ * @param symbol
99+ * 記号文字
100+ * @param beginPosition
101+ * 開始位置
102+ * @param endPosition
103+ * 終了位置
104+ */
105+ public void rangeSymbol(String symbol, int beginPosition, int endPosition);
106+
107+ /**
108+ * 終了
109+ *
110+ * @param separateSentence
111+ * 1SQLに分解されたSQL文
112+ * @param command
113+ * SQL命令種類(SELECT,INSERT,DELETE,UPDATE,CREATE,ALTER,...)
114+ */
115+ public void finished(String separateSentence, String command);
116+
117+}
diff -r 43a54fa1463a -r 9784314ce47a src/jdbcacsess2/sqlService/parse/SqlSentenceParse.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdbcacsess2/sqlService/parse/SqlSentenceParse.java Tue Feb 14 21:26:34 2012 +0900
@@ -0,0 +1,484 @@
1+/*
2+ * Copyright 2011 Kazuhiro Shimada
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+package jdbcacsess2.sqlService.parse;
17+
18+import java.util.ArrayList;
19+import java.util.List;
20+import java.util.regex.Matcher;
21+import java.util.regex.Pattern;
22+
23+/**
24+ * SQL文を字句要素に分解し、リスナーを通して要素種類毎に通知します。 字句要素は、下記6種類。
25+ * <ul>
26+ * <li>comment ハイフン開始コメント及び スラッシュアスタリスク範囲領域のコメント
27+ * <li>constant アスタリスク範囲領域の文字列定数
28+ * <li>symbol 記号
29+ * <li>delimiter 区切り文字
30+ * <li>input 入力パラメータ
31+ * <li>phrase その他を全てSQL句と判定
32+ * </ul>
33+ * 複数のSQL文を単一のSQLに分解するために、文区切りの正規表現にマッチした時に、リスナーを通じて分区切りを通知します。
34+ * その時のリスナーへの通知順は下記のようになります。
35+ * <ol>
36+ * <li>{@link SqlSentenceListener#started(String)}
37+ * <li>{@link SqlSentenceListener#finished(String, String)}
38+ * <li>
39+ * {@link SqlSentenceSparateListener#rangeSeparate(String, int, int, Pattern)}
40+ * <li>{@link SqlSentenceListener#started(String)}
41+ * <li>{@link SqlSentenceListener#finished(String, String)}
42+ * </ol>
43+ */
44+public class SqlSentenceParse {
45+
46+ private String sqlSentence;
47+
48+ private Pattern separatePattern;
49+ private SqlSentenceSparateListener sqlSentenceSparateListener;
50+ private final List<SqlSentenceListener> listenerList = new ArrayList<SqlSentenceListener>();
51+
52+ /**
53+ * 複数SQLを単一SQL文に分解するときの正規表現を登録する
54+ *
55+ * @param pattern
56+ */
57+ public void registSeparatePattern(Pattern pattern) {
58+ if (pattern == null) {
59+ throw new NullPointerException();
60+ }
61+ separatePattern = pattern;
62+ }
63+
64+ /**
65+ * SQL文の区切りを通知するリスナーを登録する
66+ *
67+ * @param sqlSentenceSparateListener
68+ */
69+ public void registSeparateListener(SqlSentenceSparateListener sqlSentenceSparateListener) {
70+ this.sqlSentenceSparateListener = sqlSentenceSparateListener;
71+ }
72+ /**
73+ * 字句要素解析結果通知リスナーを登録する
74+ *
75+ * @param listener
76+ */
77+ public void addSqlSentenceListener(SqlSentenceListener listener) {
78+ if (listener == null) {
79+ throw new NullPointerException();
80+ }
81+ listenerList.add(listener);
82+ }
83+
84+ /**
85+ * 字句要素解析結果通知リスナーを削除する
86+ */
87+ public void removeSqlSentenceListener(SqlSentenceListener listener) {
88+ if (listener == null) {
89+ throw new NullPointerException();
90+ }
91+ listenerList.remove(listener);
92+ }
93+
94+ /**
95+ * 字句要素解析結果通知リスナーを全削除する
96+ */
97+ public void removeAllSqlSentenceListener() {
98+ listenerList.clear();
99+ }
100+
101+ /**
102+ * SQL文を解析し、字句要素に応じて、リスナーのメソッドを呼び出す。
103+ *
104+ * @param sqlSentence
105+ */
106+ public void parse(String sqlSentence) {
107+ this.sqlSentence = sqlSentence;
108+
109+ int sentenceStartPosition = 0;
110+
111+ State flg = State.PHRASE;
112+
113+ // 解析開始の通知
114+ for (SqlSentenceListener l : listenerList)
115+ l.started(sqlSentence);
116+
117+ // 字句要素範囲を一時保管するオブジェクトの初期化
118+ RangePhrase rangePhrase = new RangePhrase();
119+ RangeComment rangeComment = new RangeComment();
120+ RangeConstant rangeConstant = new RangeConstant();
121+ RangeDelimiter rangeDelimiter = new RangeDelimiter();
122+ RangeSymbol rangeSymbol = new RangeSymbol();
123+
124+ // SQL文を1文字ずつ解析する
125+ for (int i = 0; i < sqlSentence.length(); i++) {
126+
127+ // コメントは、2文字を同時に判断する必要がある
128+ char[] dst = new char[2];
129+ if (i == sqlSentence.length() - 1) {
130+ sqlSentence.getChars(i, i + 1, dst, 0);
131+ dst[1] = 0xff;
132+ } else {
133+ sqlSentence.getChars(i, i + 2, dst, 0);
134+ }
135+
136+ // 読み込み文字を判断し、現状態からどの状態に遷移すればよいか決定する。
137+ flg = flg.next(dst);
138+
139+ // デリミタとSQL句は、終了文字が規定できないので、コメントや定数が始まったら終了とする。
140+ // コメントや定数は、明確な終了記号が存在すので、開始・途中・終了のそれぞれを状態として管理する。
141+
142+ if (flg == State.HIFUNCOMMENT_START || flg == State.SLASHCOMMENT_START) {
143+ rangePhrase.end(i - 1);
144+ rangeDelimiter.end(i - 1);
145+ rangeComment.begin(i);
146+
147+ } else if (flg == State.COMMENT_END) {
148+ rangeComment.end(i);
149+
150+ } else if (flg == State.APOST_START) {
151+ rangePhrase.end(i - 1);
152+ rangeDelimiter.end(i - 1);
153+ rangeConstant.begin(i);
154+
155+ } else if (flg == State.APOST_END) {
156+ rangeConstant.end(i);
157+
158+ } else if (flg == State.DELIMITER) {
159+ rangePhrase.end(i - 1);
160+ rangeDelimiter.begin(i);
161+
162+ } else if (flg == State.PHRASE) {
163+ rangeDelimiter.end(i - 1);
164+ rangePhrase.begin(i);
165+
166+ } else if (flg == State.SYMBOL_CHAR) {
167+ rangeDelimiter.end(i - 1);
168+ rangePhrase.end(i - 1);
169+ rangeSymbol.begin(i);
170+ rangeSymbol.end(i);
171+
172+ }
173+
174+ if (sqlSentenceSparateListener != null) {
175+ if (flg == State.PHRASE || flg == State.SYMBOL_CHAR || flg == State.DELIMITER) {
176+ int beginIndex = i;
177+ int endIndex = i + 10;
178+ if (endIndex > sqlSentence.length()) {
179+ endIndex = sqlSentence.length();
180+ }
181+ Matcher m = separatePattern.matcher(sqlSentence.substring(beginIndex, endIndex));
182+ if (m.lookingAt()) {
183+ // 解析終了通知
184+ for (SqlSentenceListener l : listenerList)
185+ l.finished(sqlSentence.substring(sentenceStartPosition, i), rangePhrase.getFirstSqlWord());
186+
187+ String matchKeyword = m.group();
188+ sqlSentenceSparateListener.rangeSeparate(matchKeyword,
189+ i + m.start(),
190+ i + m.end(),
191+ separatePattern);
192+
193+ rangePhrase.setFirstSqlWord("");
194+ i = i + m.end() - 1;
195+ sentenceStartPosition = i;
196+ // 解析開始の通知
197+ for (SqlSentenceListener l : listenerList)
198+ l.started(sqlSentence.substring(i));
199+ }
200+ }
201+ }
202+
203+ }
204+
205+ // 中途半端な状態であったらその状態で終了させる。
206+ // 但し、どれか一つしかその対象にならない。
207+ // rangeSymbolは1文字だけであり、必ず閉じているので必要ない
208+ rangePhrase.finish();
209+ rangeComment.finish();
210+ rangeConstant.finish();
211+ rangeDelimiter.finish();
212+
213+ // 解析終了通知
214+ for (SqlSentenceListener l : listenerList)
215+ l.finished(sqlSentence.substring(sentenceStartPosition), rangePhrase.getFirstSqlWord());
216+ }
217+
218+ /**
219+ * 記号文字の集合
220+ */
221+ static final char[] SYMBOLS = { ',', '(', ')', '!', '+', '-', '*', '/', '=', '<', '>', ';' };
222+
223+ /**
224+ * 現時点状態に対し、読み込み文字が次状態へ遷移すべきかを決定する。
225+ * 例えば、SQL句状態で、コメント開始文字(--や/*)を受け取ったら、コメント開始状態へ遷移する。
226+ */
227+ enum State {
228+ PHRASE {
229+ @Override
230+ public State next(char[] dst) {
231+ if (dst[0] == '/' && dst[1] == '*')
232+ return SLASHCOMMENT_START;
233+ if (dst[0] == '-' && dst[1] == '-')
234+ return HIFUNCOMMENT_START;
235+ if (dst[0] == '\'')
236+ return APOST_START;
237+ if (dst[0] == ' ' || dst[0] == '\t' || dst[0] == '\n')
238+ return DELIMITER;
239+ for (int i = 0; i < SYMBOLS.length; i++) {
240+ if (dst[0] == SYMBOLS[i])
241+ return SYMBOL_CHAR;
242+ }
243+ return this;
244+ }
245+ },
246+ SYMBOL_CHAR {
247+ @Override
248+ public State next(char[] dst) {
249+ return PHRASE.next(dst);
250+ }
251+ },
252+
253+ // APOST state
254+ APOST_START {
255+ @Override
256+ public State next(char[] dst) {
257+ if ((dst[0] == '\'' || dst[0] == '\\') && dst[1] == '\'')
258+ return APOST_ESCAPE;
259+ if ((dst[0] == '\'' || dst[0] == '\\') && dst[1] != '\'')
260+ return APOST_END;
261+ return APOST;
262+ }
263+ },
264+ APOST {
265+ @Override
266+ public State next(char[] dst) {
267+ if ((dst[0] == '\'' || dst[0] == '\\') && dst[1] == '\'')
268+ return APOST_ESCAPE;
269+ if ((dst[0] == '\'' || dst[0] == '\\') && dst[1] != '\'')
270+ return APOST_END;
271+ return this;
272+ }
273+ },
274+ APOST_ESCAPE {
275+ @Override
276+ public State next(char[] dst) {
277+ return APOST;
278+ }
279+ },
280+ APOST_END {
281+ @Override
282+ public State next(char[] dst) {
283+ return PHRASE.next(dst);
284+ }
285+ },
286+
287+ // SLASH COMMENT state
288+ SLASHCOMMENT_START {
289+ @Override
290+ public State next(char[] dst) {
291+ return SLASHCOMMENT;
292+ }
293+ },
294+ SLASHCOMMENT {
295+ @Override
296+ public State next(char[] dst) {
297+ if (dst[0] == '*' && dst[1] == '/')
298+ return SLASHCOMMENT_PREEND;
299+ return this;
300+ }
301+ },
302+ SLASHCOMMENT_PREEND {
303+ @Override
304+ public State next(char[] dst) {
305+ return COMMENT_END;
306+ }
307+ },
308+
309+ // HIFUN COMMENT state
310+ HIFUNCOMMENT_START {
311+ @Override
312+ public State next(char[] dst) {
313+ return HIFUNCOMMENT;
314+ }
315+ },
316+ HIFUNCOMMENT {
317+ @Override
318+ public State next(char[] dst) {
319+ if (dst[0] == '\n')
320+ return COMMENT_END;
321+ return this;
322+ }
323+ },
324+
325+ // COMMENT state end (SLASH and HIFUN)
326+ COMMENT_END {
327+ @Override
328+ public State next(char[] dst) {
329+ return PHRASE.next(dst);
330+ }
331+ },
332+
333+ // DELIMITER state
334+ DELIMITER {
335+ @Override
336+ public State next(char[] dst) {
337+ return PHRASE.next(dst);
338+ }
339+ },
340+
341+ ;
342+
343+ public abstract State next(char[] dst);
344+ }
345+
346+ /**
347+ * 各字句要素の開始位置と終了位置を管理する
348+ *
349+ * @author sima
350+ *
351+ */
352+ abstract class Range {
353+ /**
354+ * 範囲指定が有効状態であるかを示す
355+ */
356+ boolean valid = false;
357+
358+ int beginPosition = Integer.MIN_VALUE;
359+ int endPosition = Integer.MAX_VALUE;
360+
361+ private String firstSqlWord = "";
362+
363+ /**
364+ * 開始位置を設定し有効状態にする。但し、既に有効の場合は、開始位置を設定せずに復帰する。
365+ *
366+ * @param beginPosition
367+ */
368+ void begin(int beginPosition) {
369+ if (valid) {
370+ return;
371+ }
372+ this.beginPosition = beginPosition;
373+ valid = true;
374+ }
375+
376+ /**
377+ * 開始位置が設定されており、終了が未設定の場合、残りの領域を全て強制終了する。
378+ *
379+ * @param sqlSentence
380+ * @param listeners
381+ */
382+ void finish() {
383+ if (!valid) {
384+ return;
385+ }
386+ end(sqlSentence.length() - 1);
387+ }
388+
389+ /**
390+ * 終了位置を設定し無効状態にする。登録されているリスナーを呼び出す為に各実装クラスのメソッドを呼び出す。
391+ * 但し、無効状態の場合は、何もせずに復帰する。
392+ *
393+ * @param sqlSentence
394+ * @param listeners
395+ * @param endPosition
396+ */
397+ void end(int endPosition) {
398+ if (!valid) {
399+ return;
400+ }
401+
402+ this.endPosition = endPosition;
403+ String word = sqlSentence.substring(beginPosition, endPosition + 1);
404+
405+ for (SqlSentenceListener l : listenerList) {
406+ fire(l, word);
407+ }
408+ valid = false;
409+ if (getFirstSqlWord().equals("")) {
410+ setFirstSqlWord(word);
411+ }
412+ }
413+
414+ /**
415+ * リスナーを呼びだす。継承先クラスで呼出処理は実装する。
416+ *
417+ * @param l
418+ * リスナー
419+ * @param s
420+ * 通知文字列
421+ */
422+ abstract void fire(SqlSentenceListener l, String sqlWord);
423+
424+ @Override
425+ public String toString() {
426+ return beginPosition + ":" + endPosition;
427+ }
428+
429+ /**
430+ * @param firstSqlWord
431+ * セットする firstSqlWord
432+ */
433+ void setFirstSqlWord(String firstSqlWord) {
434+ this.firstSqlWord = firstSqlWord;
435+ }
436+
437+ /**
438+ * @return firstSqlWord
439+ */
440+ String getFirstSqlWord() {
441+ return firstSqlWord.toUpperCase();
442+ }
443+ }
444+
445+ class RangeComment extends Range {
446+ @Override
447+ void fire(SqlSentenceListener l, String sqlWord) {
448+ l.rangeComment(sqlWord, beginPosition, endPosition);
449+ }
450+ }
451+
452+ class RangePhrase extends Range {
453+ @Override
454+ void fire(SqlSentenceListener l, String sqlWord) {
455+ if (sqlWord.startsWith(":") || sqlWord.equals("?")) {
456+ l.rangeInput(sqlWord, beginPosition, endPosition);
457+ } else {
458+ l.rangePhrase(sqlWord, beginPosition, endPosition);
459+ }
460+ }
461+ }
462+
463+ class RangeConstant extends Range {
464+ @Override
465+ void fire(SqlSentenceListener l, String sqlWord) {
466+ l.rangeConstant(sqlWord, beginPosition, endPosition);
467+ }
468+ }
469+
470+ class RangeDelimiter extends Range {
471+ @Override
472+ void fire(SqlSentenceListener l, String sqlWord) {
473+ l.rangeDelimiter(sqlWord, beginPosition, endPosition);
474+ }
475+ }
476+
477+ class RangeSymbol extends Range {
478+ @Override
479+ void fire(SqlSentenceListener l, String sqlWord) {
480+ l.rangeSymbol(sqlWord, beginPosition, endPosition);
481+ }
482+ }
483+
484+}
diff -r 43a54fa1463a -r 9784314ce47a src/jdbcacsess2/sqlService/parse/SqlSentenceSparateListener.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdbcacsess2/sqlService/parse/SqlSentenceSparateListener.java Tue Feb 14 21:26:34 2012 +0900
@@ -0,0 +1,40 @@
1+/*
2+ * Copyright 2011 Kazuhiro Shimada
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+
17+package jdbcacsess2.sqlService.parse;
18+
19+import java.util.regex.Pattern;
20+
21+/**
22+ * @author sima
23+ *
24+ */
25+public interface SqlSentenceSparateListener {
26+ /**
27+ * SQL文セパレータ
28+ *
29+ * @param matchKeyword
30+ * マッチ文字
31+ * @param beginPosition
32+ * 開始位置
33+ * @param endPosition
34+ * 終了位置
35+ * @param pattern
36+ * マッチ時の正規表現
37+ */
38+ public void rangeSeparate(String matchKeyword, int beginPosition, int endPosition, Pattern pattern);
39+
40+}
Show on old repository browser