# SQL-REPL

ここまではJavaアプリケーションからuroboroSQLを利用する場合の説明でした。 uroboroSQLにはもう一つ特徴的な機能として、SQLを対話しながら実行するための REPL(Read-Eval-Print Loop) 機能を提供しています。

今度はこのREPL機能を利用してみましょう。

# REPLの利用

REPLを起動するためにはjp.co.future.uroborosql.client.SqlREPLクラスを実行する必要があります。 サンプルアプリケーションでSqlREPLクラスを実行するためには以下のコマンドを実行します。

mvn -PREPL
1

実行すると以下のようにタイトル表示とコマンド説明、設定値の情報が表示され、そのあとコマンド入力状態になります。

===========================================================
                 _                    ____   ___  _
 _   _ _ __ ___ | |__   ___  _ __ ___/ ___| / _ \| |
| | | | '__/ _ \| '_ \ / _ \| '__/ _ \___ \| | | | |
| |_| | | | (_) | |_) | (_) | | | (_) |__) | |_| | |___
 \__,_|_|  \___/|_.__/ \___/|_|  \___/____/ \__\_\_____|

uroboroSQL SQL REPL ver.0.25.0
===========================================================

Commands :
        query   : execute query from loaded sql file.
                ex1) query [sql file name]<Enter> : Execute SQL without parameter.
                ex2) query [sql file name] param1=val1 param2=val2 ...<Enter> : Execute SQL with the specified parameters.
        update  : execute update from loaded sql file.
                ex1) update [sql file name]<Enter> : Execute SQL without parameter.
                ex2) update [sql file name] param1=val1 param2=val2 ...<Enter> : Execute SQL with the specified parameters.
        view    : view sql file.
                ex) view [sql file name]<Enter> : Show sql file contents.
        list    : list loaded sql files.
                ex1) list<Enter> : Show all loaded sql file(s).
                ex2) list keyword<Enter> : Show loaded sql file(s) filter by keyword.
        history : list command history.
                ex1) history<Enter> : Show all command history.
                ex2) history keyword<Enter> : Show command history filter by keyword.
        driver  : list loaded drivers.
        desc    : describe table.
                ex) desc [table name]<Enter> : Show table description.
        generate: generate sql to access the table.
                ex) generate [select/insert/update/delete] [table name]<Enter> : Show sql to access tables according to keywords.
        parse   : parse sql file.
                ex) parse [sql file name]<Enter> : Parse sql file.
        cls     : clear screen.
        exit    : exit SQL REPL. `CTRL+C` is an alias.
Properties file path:REPL\repl.properties
[Properties]
db.password=
sql.additionalClassPath=src/test/resources;target/test-classes;${user.home}/.m2/repository/com/h2database/h2/1.4.199/h2-1.4.199.jar
sql.encoding=UTF-8
db.user=sa
sql.versionColumnName=lock_no
sql.optimisticLockSupplier=jp.co.future.uroborosql.mapping.FieldIncrementOptimisticLockSupplier
db.url=jdbc:h2:mem:repldb;DB_CLOSE_DELAY=-1;
sqlContextFactory.enumConstantPackageNames=jp.co.future.uroborosql.context.test
sqlContextFactory.constantClassNames=jp.co.future.uroborosql.context.test.TestConsts
initialize.

uroborosql >
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

REPLを立ち上げた状態では接続したDB(H2DB メモリDB)には何もない状態なので、まずはテーブルを作成します。 サンプルアプリケーションで利用できるSQLファイルを確認しましょう。

uroborosql > list[Enter]
1

と入力してください。

uroborosql > list
LIST:
ddl/create_tables
department/insert_department
department/select_department
employee/insert_employee
employee/select_employee
employee/update_employee
relation/insert_dept_emp
relation/select_dept_emp
setup/insert_data
uroborosql >
1
2
3
4
5
6
7
8
9
10
11

ロード済みのSQLファイルのSQL名がわかります。 テーブルを作成するためにddl/create_tablesを実行します。 ddl/create_tablesはDDLなので実行するためにはupdateコマンドを使用します。

uroborosql > u[Tab]
1

と入力してください。

uroborosql > update
1

という風にuに一致するコマンドがコード補完されます。

TIP

REPLでは[Tab]を押下することでコマンドやSQL名、バインドパラメータなどが必要に応じでコード補完されます。

続いて

uroborosql > update d[Tab]
1

と入力してください。
今度はddlに一致するSQL名の候補が表示されます。

uroborosql > update d
ddl/create_tables   department/insert_department   department/select_department
1
2

この状態で[Tab]を入力することで候補を選択することが出来ます。
ddl/create_tablesを選択して[Enter]を入力すると以下のようになります。

uroborosql > update ddl/create_tables
1

もう一度[Enter]を入力するとSQLが実行されます。

uroborosql > update ddl/create_tables
[DEBUG] Executed SQL[
-- employee
drop table if exists employee cascade;
create table employee (
  emp_no number(6) auto_increment
  , first_name varchar(20) not null
  , last_name varchar(20) not null
  , birth_date date not null
  , gender char(1) not null
  , lock_version number(10) not null default 0
  , constraint employee_PKC primary key (emp_no)
) ;
-- dept_emp
drop table if exists dept_emp cascade;
create table dept_emp (
  emp_no number(6) not null
  , dept_no number(4) not null
  , constraint dept_emp_PKC primary key (emp_no,dept_no)
) ;
-- department
drop table if exists department cascade;
create table department (
  dept_no number(4) auto_increment
  , dept_name varchar(100) not null
  , lock_version number(10) not null default 0
  , constraint department_PKC primary key (dept_no)
) ;
comment on table employee is 'employee';
comment on column employee.emp_no is 'emp_no';
comment on column employee.first_name is 'first_name';
comment on column employee.last_name is 'last_name';
comment on column employee.birth_date is 'birth_date';
comment on column employee.gender is 'gender     ''F''emale/''M''ale/''O''ther';
comment on column employee.lock_version is 'lock_version';
comment on table dept_emp is 'dept_emp';
comment on column dept_emp.emp_no is 'emp_no';
comment on column dept_emp.dept_no is 'dept_no';
comment on table department is 'department';
comment on column department.dept_no is 'dept_no';
comment on column department.dept_name is 'dept_name';
comment on column department.lock_version is 'lock_version'
]
[DEBUG] Execute update SQL.
[DEBUG] SQL execution time [ddl/create_tables] : [00:00:00.030]
update sql[ddl/create_tables] end. row count=0
uroborosql >
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

ddl/create_tablesが実行され、DBにテーブルが作成されました。

では次に作成されたテーブルの定義情報を確認します。
テーブル定義情報の確認にはdescコマンドを使用します。 ここではEMPLOYEEテーブルの定義情報を確認してみましょう。

uroborosql > desc EMPLOYEE[Enter]
1
uroborosql > desc EMPLOYEE
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|TABLE_NAME|COLUMN_NAME |TYPE_NAME|COLUMN_SIZE|DECIMAL_DIGITS|IS_NULLABLE|COLUMN_DEF                                                                      |REMARKS                        |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|EMPLOYEE  |EMP_NO      |DECIMAL  |          6|             0|NO         |(NEXT VALUE FOR "PUBLIC"."SYSTEM_SEQUENCE_D06A5524_EC18_4835_A536_1F5A372BFC73")|emp_no                         |
|EMPLOYEE  |FIRST_NAME  |VARCHAR  |         20|             0|NO         |                                                                                |first_name                     |
|EMPLOYEE  |LAST_NAME   |VARCHAR  |         20|             0|NO         |                                                                                |last_name                      |
|EMPLOYEE  |BIRTH_DATE  |DATE     |         10|             0|NO         |                                                                                |birth_date                     |
|EMPLOYEE  |GENDER      |CHAR     |          1|             0|NO         |                                                                                |gender        'F'emale/'M'ale/'O'ther|
|EMPLOYEE  |LOCK_VERSION|DECIMAL  |         10|             0|NO         |                                                                               0|lock_version                   |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uroborosql >
1
2
3
4
5
6
7
8
9
10
11

EMPLOYEEテーブルの定義情報が表形式で表示されました。

続いて初期データを投入しましょう。

setup/insert_dataを実行します。

uroborosql > update setup/insert_data[Enter]
1
uroborosql > update setup/insert_data
[DEBUG] Executed SQL[
insert into department (dept_name) values ('sales');
insert into department (dept_name) values ('export');
insert into department (dept_name) values ('accounting');
insert into department (dept_name) values ('personnel');
insert into employee (first_name, last_name, birth_date, gender) values ('Bob', 'Smith', '1970-01-02', 'M');
insert into employee (first_name, last_name, birth_date, gender) values ('Susan', 'Davis', '1969-02-10', 'F');
insert into employee (first_name, last_name, birth_date, gender) values ('John', 'Wilson', '1982-05-08', 'M');
insert into employee (first_name, last_name, birth_date, gender) values ('Sharon', 'Johnson', '1990-01-20', 'F');
insert into employee (first_name, last_name, birth_date, gender) values ('Stephen', 'Taylor', '2003-12-31', 'M');
insert into dept_emp (emp_no, dept_no) values (1, 1);
insert into dept_emp (emp_no, dept_no) values (2, 1);
insert into dept_emp (emp_no, dept_no) values (3, 2);
insert into dept_emp (emp_no, dept_no) values (4, 3);
insert into dept_emp (emp_no, dept_no) values (5, 4)
]
[DEBUG] Execute update SQL.
[DEBUG] SQL execution time [setup/insert_data] : [00:00:00.017]
update sql[setup/insert_data] end. row count=1
uroborosql >
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

これでテーブルに初期データが挿入されました。 では、挿入したデータを検索してみましょう。

検索を行う前に、検索を行うSQLの内容を確認してみましょう。
SQLの内容を確認するにはviewコマンドを使用します。

uroborosql > view department/select_department[Enter]
1
uroborosql > view department/select_department
select /* _SQL_ID_ */
        dept.dept_no            as      dept_no
,       dept.dept_name          as      dept_name
,       dept.lock_version       as      lock_version
from
        department      dept
/*BEGIN*/
where
/*IF SF.isNotEmpty(deptNo)*/
and     dept.dept_no    =       /*deptNo*/1
/*END*/
/*IF SF.isNotEmpty(deptName)*/
and     dept.dept_name  =       /*deptName*/'sample'
/*END*/
/*END*/
uroborosql >
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

検索を行う場合はqueryコマンドを使用します。 queryの後に実行するSQL名を指定します。

uroborosql > query department/select_department[Enter]
1
uroborosql > query department/select_department
[DEBUG] Evaluation Expression:[SF.isNotEmpty(deptNo)], Result:[false], Parameter:[deptNo:[null]]
[DEBUG] Evaluation Expression:[SF.isNotEmpty(deptName)], Result:[false], Parameter:[deptName:[null]]
[DEBUG] Executed SQL[
select /* department/select_department */
        dept.dept_no            as      dept_no
,       dept.dept_name          as      dept_name
,       dept.lock_version       as      lock_version
from
        department      dept

]
[DEBUG] Execute search SQL.
[INFO ]
+-------+----------+------------+
|DEPT_NO|DEPT_NAME |LOCK_VERSION|
+-------+----------+------------+
|      1|sales     |           0|
|      2|export    |           0|
|      3|accounting|           0|
|      4|personnel |           0|
+-------+----------+------------+
[DEBUG] SQL execution time [department/select_department] : [00:00:00.078]
query sql[department/select_department] end.
uroborosql >
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

ここではバインドパラメータを指定しなかったため、絞込み条件のないSQLが実行され検索結果として4件のデータが取得できました。

REPLでは上の結果のように、

  • 実行するSQL
  • バインドパラメータ
  • SQL文の中の評価式とその評価結果
  • 検索結果
  • 実行時間

が表示されるので、SQLがどういう風に実行され、どういう値が取得できるのかが良く分かるようになっています。

次にバインドパラメータを指定して検索してみましょう。

検索するSQLにどのようなバインドパラメータや条件分岐があるかを確認するにはparseコマンドを使用します。

uroborosql > parse department/select_department[Enter]
1
uroborosql > parse department/select_department
PARSE:

SQL :
select /* _SQL_ID_ */
        dept.dept_no            as      dept_no
,       dept.dept_name          as      dept_name
,       dept.lock_version       as      lock_version
from
        department      dept
/*BEGIN*/
where
/*IF SF.isNotEmpty(deptNo)*/
and     dept.dept_no    =       /*deptNo*/1
/*END*/
/*IF SF.isNotEmpty(deptName)*/
and     dept.dept_name  =       /*deptName*/'sample'
/*END*/
/*END*/

BRANCHES :
        BEGIN {
                IF ( SF.isNotEmpty(deptNo) ) {
                }
                IF ( SF.isNotEmpty(deptName) ) {
                }
        }

BIND_PARAMS :
        deptName
        deptNo
uroborosql >
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

parseコマンドの結果は以下のようになります。

  • SQL : 解析対象のSQL
  • BRANCHES : 条件分岐
  • BIND_PARAMS : バインドパラメータ

条件分岐では BEGINのスコープ({}で囲まれた中)に2つのIF分岐が並んでいることがわかります。
また、バインドパラメータでは deptNodeptNameがあることがわかります。

parseコマンドで確認したバインドパラメータを指定して検索を行います。

uroborosql > query department/select_department deptNo=1[Enter]
1
uroborosql > query department/select_department deptNo=1
[DEBUG] Evaluation Expression:[SF.isNotEmpty(deptNo)], Result:[true], Parameter:[deptNo:[1]]
[DEBUG] Evaluation Expression:[SF.isNotEmpty(deptName)], Result:[false], Parameter:[deptName:[null]]
[DEBUG] Executed SQL[
select /* department/select_department */
        dept.dept_no            as      dept_no
,       dept.dept_name          as      dept_name
,       dept.lock_version       as      lock_version
from
        department      dept
where
dept.dept_no    =       ?/*deptNo*/

]
[DEBUG] Set the parameter.[INDEX[1], Parameter name[deptNo], Value[1], Class[Integer]]
[DEBUG] Execute search SQL.
[INFO ]
+-------+---------+------------+
|DEPT_NO|DEPT_NAME|LOCK_VERSION|
+-------+---------+------------+
|      1|sales    |           0|
+-------+---------+------------+
[DEBUG] SQL execution time [department/select_department] : [00:00:00.005]
query sql[department/select_department] end.
uroborosql >
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

deptNo1を指定して検索しています。 この時、SQL文の評価式である/*IF SF.isNotEmpty(deptNo)*/がtrueとなりSQLのwhere句にdept_noの条件が追加されバインドパラメータがバインドされます。
その結果、検索結果は1件になっています。

このようにSQL名の後ろにバインドパラメータ名=という形でバインドパラメータを記述することでバインドパラメータを指定してSQLを実行することができます。

バインドパラメータが複数ある場合はバインドパラメータ名1=値1 バインドパラメータ名2=値2 ... という風に各パラメータの間を空白で区切って指定してください。

  • バインドパラメータを複数指定する例
uroborosql > query department/select_department deptNo=1 deptName=sales[Enter]
1
uroborosql > query department/select_department deptNo=1 deptName=sales
[DEBUG] Evaluation Expression:[SF.isNotEmpty(deptNo)], Result:[true], Parameter:[deptNo:[1]]
[DEBUG] Evaluation Expression:[SF.isNotEmpty(deptName)], Result:[true], Parameter:[deptName:[{115,97,108,101,115},0,0]]
[DEBUG] Executed SQL[
select /* department/select_department */
        dept.dept_no            as      dept_no
,       dept.dept_name          as      dept_name
,       dept.lock_version       as      lock_version
from
        department      dept
where
dept.dept_no    =       ?/*deptNo*/
and     dept.dept_name  =       ?/*deptName*/

]
[DEBUG] Set the parameter.[INDEX[1], Parameter name[deptNo], Value[1], Class[Integer]]
[DEBUG] Set the parameter.[INDEX[2], Parameter name[deptName], Value[sales], Class[String]]
[DEBUG] Execute search SQL.
[INFO ]
+-------+---------+------------+
|DEPT_NO|DEPT_NAME|LOCK_VERSION|
+-------+---------+------------+
|      1|sales    |           0|
+-------+---------+------------+
[DEBUG] SQL execution time [department/select_department] : [00:00:00.006]
query sql[department/select_department] end.
uroborosql >
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

REPLを終了する場合はコマンドquit,もしくはexitを入力してください。

uroborosql > quit[Enter]
SQL REPL end.
1
2

終了メッセージが表示されてREPLが終了します。

REPLには他にも以下のコマンドがあります。

コマンド 説明
query 検索SQLを実行します
update 更新SQL(insert/update/delete)やDDLを実行します
view SQL名で指定したSQLの内容を表示します
list 使用可能なSQL名の一覧を表示します
history 実行したコマンドの履歴を表示します
driver 使用可能なJDBCドライバーの一覧を表示します
desc 指定したテーブルの定義情報を表示します
generate 指定したテーブルに対するselect/insert/update/deleteを行うSQLを生成します
parse 指定したSQLで使用されているバインドパラメータやIF分岐条件を抽出して表示します
cls コンソール画面のクリア
exit REPLを終了します
help 利用できるコマンドの説明を表示します

# REPLの設定

さて、ここまでREPLの操作を説明してきましたが、DB接続情報やSQLファイルの場所はどこで指定していたのでしょうか。 実はjp.co.future.uroborosql.client.SqlREPLを実行する際、引数としてプロパティファイルを指定します。このプロパティファイルにDB接続情報やSQLファイルの場所などREPLを実行するのに必要な情報が記載されています。

pom.xmlのREPL実行部分

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>exec-maven-plugin</artifactId>
  <executions>
    <execution>
      <id>repl</id>
      <goals>
        <goal>java</goal>
      </goals>
      <configuration>
        <workingDirectory>${basedir}</workingDirectory>
        <mainClass>jp.co.future.uroborosql.client.SqlREPL</mainClass>
        <arguments>
          <argument>REPL/repl.properties</argument>
        </arguments>
      </configuration>
      <phase>process-test-classes</phase>
    </execution>
  </executions>
</plugin>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

初期設定ではプロパティファイルの場所はREPL/repl.propertiesになっています。

  • REPL/repl.properties
db.url=jdbc:h2:file:./target/db/repldb;
db.user=sa
db.password=

sql.additionalClassPath=${user.home}/.m2/repository/com/h2database/h2/1.4.192/h2-1.4.192.jar
1
2
3
4
5
プロパティ名 説明
db.url DB接続URL
db.schema DB接続スキーマ
db.user DB接続ユーザ
db.password DB接続パスワード
sql.loadPath SQLをロードするパス。初期値はsql
sql.encoding SQLファイルのエンコーディング。初期値はUTF-8
sql.fileExtension ロードするSQLファイルの拡張子。初期値は.sql
sql.detectChanges SQLファイルの変更検知を行うかどうか。初期値はtrue
sql.additionalClassPath REPL起動時に起動時クラスパス以外でクラスパスに追加する場所。;で区切ることで複数指定可。SQLファイルのルート(sqlフォルダの親フォルダ)をクラスパスに追加することで、自動的にSQLファイルがロードされます。合わせて接続するDBのJDBCドライバを含むJarを指定することで動的にJDBCドライバを読み込みます。
sqlContextFactory.constantClassNames SqlContextFactoryに登録する定数クラスを指定。,で区切ることで複数指定可。 ex) jp.co.future.uroborosql.context.test.TestConsts
sqlContextFactory.enumConstantPackageNames SqlContextFactoryに登録するEnum定数パッケージ名を指定。,で区切ることで複数指定可。ex) jp.co.future.uroborosql.context.test

このプロパティファイルを変更することでいろいろなDBに接続することができるようになります。

これまで見てきたようにREPLを利用することで簡単にSQL実行や動作確認ができるので、SQL開発には欠かせないツールになります。 色々なSQLを記述してREPLで試してみてください。

これで Getting Started は終了です。

uroboroSQLで使用するSQLの文法や基本的な操作については基本操作を参照してください。