SlideShare a Scribd company logo
1 of 21
目次
● 舟木 初 (ふなき はじめ)
● U-NEXT新卒1年目
● ずっとLastaFluteで開発
● 今回が初めてのオープンソースコミット
DBFluteにコミットをしました。
カラムの連結検索で、
nullが含まれていても大丈夫なようにした
複数カラムに分かれた住所に対する曖昧検索
市町村区 丁目番地 建物部屋番号 検索値
渋谷区 神宮前3-35-2 クローチェ6F ← 渋谷区神宮前
世田谷区 北沢1-2-3 メゾン201 ← 北沢1-2-3メゾン
(DBとしては検索カラムがあったほうがよかったかもしれないが・・・)
LikeSearchOptionで連結検索できるので・・!
cb.query().setAddress1_LikeSearch(body.address, op -> {
UnregisteredUserCB dreamCruiseCB = cb.dreamCruiseCB();
op.addCompoundColumn(dreamCruiseCB.specify().columnAddress2());
op.addCompoundColumn(dreamCruiseCB.specify().columnAddress3());
op.likeContain();
});
連結するとこうなる
さすがDBFlute! 一件落着!
市町村区 丁目番地 建物部屋番号 → 連結した値
渋谷区 神宮前3-35-2 クローチェ6F → 渋谷区神宮前3-35-2クローチェ6F
世田谷区 北沢1-2-3 メゾン201 → 世田谷区北沢1-2-3メゾン201
あれ・・・?
連結したカラムの値にひとつでもNULLがあると・・・?
市町村区 丁目番地 建物部屋番号 → 連結した値
渋谷区 神宮前3-35-2 クローチェ6F → 渋谷区神宮前3-35-2クローチェ6F
世田谷区 北沢1-2-3 NULL → NULL
NULLが空文字になればいいのに。
市町村区 丁目番地 建物部屋番号 → 連結した値
渋谷区 神宮前3-35-2 クローチェ6F → 渋谷区神宮前3-35-2クローチェ6F
世田谷区 北沢1-2-3 NULL → 世田谷区北沢1-2-3””
ふなき「カラムを連結するとき、
NULLを空文字として扱ってくれる機能はありますか?」
くぼさん「ないねえ」
ふなき「了解です。まあ大丈夫です。」
くぼさん「別に、ふなきくん、
プルリクしても
いいんだからね笑」
プルリクしよう
1. dbflute-coreとdbflute-test-active-docksideをフォークして
2. dbflute-coreでcoalesceを使えるように修正して
3. テストコードをdbflute-test-active-dockside書いて
4. プルリクだす!
5. レビューしてもらう!
発行されるSQLを見てみた。
select dfloc.ADDRESS1 as ADDRESS1, dfloc. ADDRESS2 as ADDRESS2
from USER dfloc
where dfloc.ADDRESS1 || dfloc.ADDRESS2 like ‘%渋谷区西参道%' escape '|'
こうなってほしい
select dfloc.ADDRESS1 as ADDRESS1, dfloc. ADDRESS2 as ADDRESS2
from USER dfloc
where dfloc.ADDRESS1 || dfloc.ADDRESS2 like ‘%渋谷区西参道%' escape '|'
coalesce(dfloc. ADDRESS1,'') || coalesce(dfloc. ADDRESS2,'')
DBFluteのなか
このあたりでcoalesceを足せばよさそう。
public abstract class ConditionKey implements Serializable {
・
・
protected ColumnRealName resolveCompoundColumn(ColumnRealName baseRealName, ConditionOption option) {
・
・
final List<SpecifiedColumn> compoundColumnList = option.getCompoundColumnList();
final List<ColumnRealName> realNameList = new ArrayList<ColumnRealName>();
realNameList.add(baseRealName); // already cipher
for (SpecifiedColumn specifiedColumn : compoundColumnList) {
realNameList.add(doResolveCompoundColumn(option, specifiedColumn));
}
final OnQueryStringConnector stringConnector = option.getStringConnector();
final String connected = stringConnector.connect(realNameList.toArray());
return ColumnRealName.create(null, new ColumnSqlName(connected));
}
・
・
}
public abstract class ConditionKey implements Serializable {
・
・
protected ColumnRealName resolveCompoundColumn(ColumnRealName baseRealName, ConditionOption option) {
・
・
final List<SpecifiedColumn> compoundColumnList = option.getCompoundColumnList();
final List<ColumnRealName> realNameList = new ArrayList<ColumnRealName>();
realNameList.add(baseRealName); // already cipher
realNameList.add(doResolveCompoundColumnOption(option, baseRealName)); // already cipher
for (SpecifiedColumn specifiedColumn : compoundColumnList) {
realNameList.add(doResolveCompoundColumn(option, specifiedColumn));
realNameList.add(doResolveCompoundColumnOption(option, doResolveCompoundColumnCipher(option, specifiedColumn)));
}
・
・
}
protected ColumnRealName doResolveCompoundColumnOption(ConditionOption option, ColumnRealName columnRealName) {
if (option.isNullCompoundedAsEmpty()) {
return toColumnRealName("coalesce(" + columnRealName + ",'')");
}
return columnRealName;
}
・
・
}
cb.query().setAddress1_LikeSearch("渋谷区西参道", op -> {
op.likeContain();
op.addCompoundColumn(dreamCruiseCB.specify().columnAddress2());
op.compoundsNullAsEmpty();
});
optionで呼び出す
coalesce(dfloc. ADDRESS1,'') || coalesce(dfloc. ADDRESS2,'')
// ## Assert ##
assertTrue(Srl.containsIgnoreCase(popCB().toDisplaySql(), "coalesce"));
assertHasAnyElement(vendorCheckList);
assertTrue(vendorCheckList.size() >= 3); // inserted 3 entities
for (VendorCheck vendorCheck : vendorCheckList) {
assertContains(vendorCheck.getTypeOfChar() + vendorCheck.getTypeOfVarchar(), "bcd");
}
テストコードも書いた
※VendorCheckというテスト用のテーブルがある
レビュー
● https://github.com/dbflute/dbflute-core/pull/54/files
● https://github.com/dbflute-test/dbflute-test-active-
dockside/pull/11/files
目次

More Related Content

What's hot

アルゴリズムとデータ構造14
アルゴリズムとデータ構造14アルゴリズムとデータ構造14
アルゴリズムとデータ構造14Kenta Hattori
 
201812 のの会@関数Talk 8th
201812 のの会@関数Talk 8th201812 のの会@関数Talk 8th
201812 のの会@関数Talk 8thSatoru Abe
 
【文献紹介】Automatic community creation for abstractive spoken conversation summar...
【文献紹介】Automatic community creation for abstractive spoken conversation summar...【文献紹介】Automatic community creation for abstractive spoken conversation summar...
【文献紹介】Automatic community creation for abstractive spoken conversation summar...Takashi YAMAMURA
 
圏論のモナドとHaskellのモナド
圏論のモナドとHaskellのモナド圏論のモナドとHaskellのモナド
圏論のモナドとHaskellのモナドYoshihiro Mizoguchi
 
圏論とHaskellは仲良し
圏論とHaskellは仲良し圏論とHaskellは仲良し
圏論とHaskellは仲良しohmori
 
データとは何か
データとは何かデータとは何か
データとは何かKenta Suzuki
 
区間をキーとして保持する分散KVSの効率的な実現法
区間をキーとして保持する分散KVSの効率的な実現法区間をキーとして保持する分散KVSの効率的な実現法
区間をキーとして保持する分散KVSの効率的な実現法Kota Abe
 

What's hot (9)

Couch DB for 197X
Couch DB for 197XCouch DB for 197X
Couch DB for 197X
 
アルゴリズムとデータ構造14
アルゴリズムとデータ構造14アルゴリズムとデータ構造14
アルゴリズムとデータ構造14
 
201812 のの会@関数Talk 8th
201812 のの会@関数Talk 8th201812 のの会@関数Talk 8th
201812 のの会@関数Talk 8th
 
【文献紹介】Automatic community creation for abstractive spoken conversation summar...
【文献紹介】Automatic community creation for abstractive spoken conversation summar...【文献紹介】Automatic community creation for abstractive spoken conversation summar...
【文献紹介】Automatic community creation for abstractive spoken conversation summar...
 
圏とHaskellの型
圏とHaskellの型圏とHaskellの型
圏とHaskellの型
 
圏論のモナドとHaskellのモナド
圏論のモナドとHaskellのモナド圏論のモナドとHaskellのモナド
圏論のモナドとHaskellのモナド
 
圏論とHaskellは仲良し
圏論とHaskellは仲良し圏論とHaskellは仲良し
圏論とHaskellは仲良し
 
データとは何か
データとは何かデータとは何か
データとは何か
 
区間をキーとして保持する分散KVSの効率的な実現法
区間をキーとして保持する分散KVSの効率的な実現法区間をキーとして保持する分散KVSの効率的な実現法
区間をキーとして保持する分散KVSの効率的な実現法
 

DBFlute Fess 2017