From 7c45234c42fc65b0e338231a0a963c35225184d4 Mon Sep 17 00:00:00 2001 From: jflute Date: Sat, 22 Jul 2023 02:53:01 +0900 Subject: [PATCH] DBFlute Runtime: LikeSearchOption dynamic settings #184 --- .../cbean/coption/ConditionOption.java | 23 +- .../cbean/coption/LikeSearchOption.java | 209 ++++++++++++------ .../cbean/coption/SimpleStringOption.java | 35 +-- .../sqlclause/query/QueryClauseArranger.java | 2 +- .../org/dbflute/dbway/WayOfPostgreSQL.java | 2 +- .../dbway/topic/OnQueryStringConnector.java | 4 +- 6 files changed, 181 insertions(+), 94 deletions(-) diff --git a/dbflute-runtime/src/main/java/org/dbflute/cbean/coption/ConditionOption.java b/dbflute-runtime/src/main/java/org/dbflute/cbean/coption/ConditionOption.java index c76e88ead..61df0de5e 100644 --- a/dbflute-runtime/src/main/java/org/dbflute/cbean/coption/ConditionOption.java +++ b/dbflute-runtime/src/main/java/org/dbflute/cbean/coption/ConditionOption.java @@ -30,12 +30,18 @@ */ public interface ConditionOption { + // =================================================================================== + // Rear Option + // =========== /** * Get the string expression of rear option. * @return The string for rear option. (NotNull, EmptyAllowed) */ String getRearOption(); + // =================================================================================== + // Compound Column + // =============== /** * Does the option have compound columns? * @return The determination, true or false. @@ -44,7 +50,7 @@ public interface ConditionOption { /** * Get the list of compound columns. - * @return The list of specified column. (NotNull, EmptyAllowed) + * @return The read-only list of specified column. (NotNull, EmptyAllowed) */ List getCompoundColumnList(); @@ -64,25 +70,28 @@ default boolean isNullCompoundedAsEmpty() { /** * Get the string connector basically for compound columns? - * @return The object of string connector. (NullAllowed) + * @return The interface providing string connector on query. (NullAllowed: if null, no compound anyway) */ OnQueryStringConnector getStringConnector(); + // =================================================================================== + // Clause Adjustment + // ================= /** - * Get the extension operand. - * @return The object of the extension operand. (NullAllowed) + * Get the extension operand. (e.g. use "ilike" instead of "like") + * @return The interface providing operand. (NullAllowed: if null, it means no extension) */ ExtensionOperand getExtensionOperand(); /** - * Get the arranger of query clause. - * @return The object of the arranger. (NullAllowed) + * Get the arranger of query clause. (e.g. use "collate") + * @return The interface providing arranged clause. (NullAllowed: if null, it means no arrangement) */ QueryClauseArranger getWhereClauseArranger(); /** * Get the manager of geared cipher. (basically for compound columns) - * @return The manager of geared cipher. (NullAllowed) + * @return The manager of geared cipher. (NullAllowed: if null, it means no cipher) */ GearedCipherManager getGearedCipherManager(); } diff --git a/dbflute-runtime/src/main/java/org/dbflute/cbean/coption/LikeSearchOption.java b/dbflute-runtime/src/main/java/org/dbflute/cbean/coption/LikeSearchOption.java index 929b1a1f8..c6ea0d236 100644 --- a/dbflute-runtime/src/main/java/org/dbflute/cbean/coption/LikeSearchOption.java +++ b/dbflute-runtime/src/main/java/org/dbflute/cbean/coption/LikeSearchOption.java @@ -17,6 +17,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import org.dbflute.cbean.cipher.GearedCipherManager; @@ -25,10 +26,12 @@ import org.dbflute.dbway.topic.ExtensionOperand; import org.dbflute.dbway.topic.OnQueryStringConnector; import org.dbflute.twowaysql.node.FilteringBindOption; +import org.dbflute.util.DfCollectionUtil; import org.dbflute.util.DfTypeUtil; +// very memorable code for me /** - * The option of like search. + * The condition option of like-search. *
  * e.g.
  *  new LikeSearchOption().likePrefix()  : PrefixSearch
@@ -50,15 +53,28 @@ public class LikeSearchOption extends SimpleStringOption implements FilteringBin
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
-    protected String _like;
-    protected String _escape;
+    // -----------------------------------------------------
+    //                                                 Basic
+    //                                                 -----
+    protected String _like; // null allowed
+    protected String _escape; // null allowed
     protected boolean _asOrSplit;
-    protected List _originalWildCardList;
-    protected List _compoundColumnList;
-    protected List _compoundColumnSizeList;
+
+    // -----------------------------------------------------
+    //                                       Compound Column
+    //                                       ---------------
+    protected List _compoundColumnList; // null allowed
+    protected List _compoundColumnSizeList; // null allowed
     protected boolean _nullCompoundedAsEmpty;
-    protected OnQueryStringConnector _stringConnector;
-    protected GearedCipherManager _cipherManager;;
+    protected OnQueryStringConnector _stringConnector; // null allowed
+
+    // -----------------------------------------------------
+    //                                     Clause Adjustment
+    //                                     -----------------
+    protected List _originalWildCardList; // null allowed
+    protected ExtensionOperand _extensionOperand; // null allowed, since 1.2.7
+    protected QueryClauseArranger _whereClauseArranger; // null allowed, since 1.2.7
+    protected GearedCipherManager _cipherManager; // null allowed
 
     // ===================================================================================
     //                                                                         Constructor
@@ -273,9 +289,6 @@ public LikeSearchOption cutSplit(int splitLimitCount) {
     // ===================================================================================
     //                                                                     Compound Column
     //                                                                     ===============
-    // -----------------------------------------------------
-    //                                          Dream Cruise
-    //                                          ------------
     /**
      * Add compound column connected to main column. {Dream Cruise}
      * 
@@ -327,11 +340,16 @@ public boolean hasCompoundColumn() {
 
     @Override
     public List getCompoundColumnList() {
-        return _compoundColumnList;
+        return _compoundColumnList != null ? Collections.unmodifiableList(_compoundColumnList) : DfCollectionUtil.emptyList();
     }
 
-    public void compoundsNullAsEmpty() {
+    /**
+     * Use coalesce() for compound columns to filter null as empty.
+     * @return this. (NotNull)
+     */
+    public LikeSearchOption compoundsNullAsEmpty() {
         _nullCompoundedAsEmpty = true;
+        return this;
     }
 
     @Override
@@ -354,6 +372,16 @@ public void clearCompoundColumn() {
     /**
      * Optimize compound columns by fixed size. 
* The columns specified their sizes should be fixed-size string type 'char'. (but no check so attention) + *
+     * e.g. SEA_FIRST char(9), SEA_SECOND char(20)
+     *  cb.query().setSeaFirst_LikeSearch("StojkovicPix", op -> {
+     *      op.likePrefix();
+     *      op.addCompoundColumn(dreamCruiseCB.specify().columnSeaSecond());
+     *      op.optimizeCompoundColumnByFixedSize(9, 20);
+     *  });
+     * // where dfloc.SEA_FIRST = 'Stojkovic'
+     * //   and dfloc.SEA_SECOND like 'Pix%' escape '|'
+     * 
* @param sizes The array of column size for main column and compound columns. (NotNull) * @return this. (NotNull) */ @@ -380,30 +408,108 @@ public boolean hasCompoundColumnOptimization() { return _compoundColumnSizeList != null && !_compoundColumnSizeList.isEmpty(); } - public List getCompoundColumnSizeList() { - return _compoundColumnSizeList; + public List getCompoundColumnSizeList() { // read-only + return _compoundColumnSizeList != null ? Collections.unmodifiableList(_compoundColumnSizeList) : DfCollectionUtil.emptyList(); } // ----------------------------------------------------- // StringConnector // --------------- - // called after being set to condition-query or parameter-bean + // should be called after being set to condition-query or parameter-bean // for DBMS that has original string connection way // e.g. MySQL, SQLServer - public LikeSearchOption acceptStringConnector(OnQueryStringConnector stringConnector) { _stringConnector = stringConnector; return this; } + @Override public boolean hasStringConnector() { return _stringConnector != null; } + @Override public OnQueryStringConnector getStringConnector() { return _stringConnector; } + // =================================================================================== + // Clause Adjustment + // ================= + // ----------------------------------------------------- + // Orginal WildCard + // ---------------- + // should be called after being set to condition-query or parameter-bean + // for DBMS that does not ignore an unused escape character + // e.g. Oracle, Apache Derby + /** + * Accept the list of your original wild-card for e.g. DBMS customization. + * @param originalWildCardList The list of string wild-card. (NullAllowed) + * @return this. (NotNull) + */ + public LikeSearchOption acceptOriginalWildCardList(List originalWildCardList) { + _originalWildCardList = originalWildCardList; + return this; + } + + public List getOriginalWildCardList() { // read-only + return _originalWildCardList != null ? Collections.unmodifiableList(_originalWildCardList) : DfCollectionUtil.emptyList(); + } + + // ----------------------------------------------------- + // Extension Operand + // ----------------- + /** + * Accept your original operand as application extension instead of "like". + * @param extensionOperand The interface that provides your operand. (NullAllowed) + * @return this. (NotNull) + */ + public LikeSearchOption acceptExtensionOperand(ExtensionOperand extensionOperand) { // since 1.2.7 + _extensionOperand = extensionOperand; + return this; + } + + @Override + public ExtensionOperand getExtensionOperand() { + return _extensionOperand; + } + + // ----------------------------------------------------- + // Where Clause Arranger + // --------------------- + /** + * Accept arranger of query clause (like clause) for e.g. collate. + * @param whereClauseArranger The interface that arranges your clause. (NullAllowed) + * @return this. (NotNull) + */ + public LikeSearchOption acceptWhereClauseArranger(QueryClauseArranger whereClauseArranger) { // since 1.2.7 + _whereClauseArranger = whereClauseArranger; + return this; + } + + @Override + public QueryClauseArranger getWhereClauseArranger() { + return _whereClauseArranger; + } + + // ----------------------------------------------------- + // Geared Cipher + // ------------- + /** + * Accept the manager of geared cipher. (basically for compound columns) + * @param cipherManager The manager of geared cipher. (NullAllowed) + * @return this. (NotNull) + */ + public LikeSearchOption acceptGearedCipherManager(GearedCipherManager cipherManager) { + _cipherManager = cipherManager; + return this; + } + + @Override + public GearedCipherManager getGearedCipherManager() { + return _cipherManager; + } + // =================================================================================== // Real Value // ========== @@ -446,27 +552,19 @@ protected String filterEscape(String target, String wildCard) { return replace(target, wildCard, _escape + wildCard); } - // called after being set to condition-query or parameter-bean - // for DBMS that does not ignore an unused escape character - // e.g. Oracle, Apache Derby - - public LikeSearchOption acceptOriginalWildCardList(List originalWildCardList) { - _originalWildCardList = originalWildCardList; - return this; - } - // =================================================================================== // Deep Copy // ========= @Override public LikeSearchOption createDeepCopy() { final LikeSearchOption copy = (LikeSearchOption) super.createDeepCopy(); + + // basic copy._like = _like; copy._escape = _escape; copy._asOrSplit = _asOrSplit; - if (_originalWildCardList != null) { - copy._originalWildCardList = new ArrayList(_originalWildCardList); - } + + // compound column if (_compoundColumnList != null) { copy._compoundColumnList = new ArrayList(_compoundColumnList); } @@ -474,6 +572,17 @@ public LikeSearchOption createDeepCopy() { copy._compoundColumnSizeList = new ArrayList(_compoundColumnSizeList); } copy._stringConnector = _stringConnector; + + // clause adjustment + if (_originalWildCardList != null) { + copy._originalWildCardList = new ArrayList(_originalWildCardList); + } else { + copy._originalWildCardList = null; + } + copy._extensionOperand = _extensionOperand; + copy._whereClauseArranger = _whereClauseArranger; + copy._cipherManager = _cipherManager; + return copy; } @@ -482,51 +591,11 @@ protected LikeSearchOption newDeepCopyInstance() { return new LikeSearchOption(); } - // =================================================================================== - // Extension Operand - // ================= - /** - * Get the operand for extension. - * @return The operand for extension. (NullAllowed: If the value is null, it means no extension) - */ - @Override - public ExtensionOperand getExtensionOperand() { // for application extension - return null; // as default - } - - // =================================================================================== - // Where Clause Arranger - // ===================== - /** - * Get the arranger of where clause. - * @return The arranger of where clause. (NullAllowed: If the value is null, it means no arrangement) - */ - @Override - public QueryClauseArranger getWhereClauseArranger() { // for application extension - return null; // as default - } - - // =================================================================================== - // Geared Cipher - // ============= - /** - * Accept the manager of geared cipher. (basically for compound columns) - * @param cipherManager The manager of geared cipher. (NullAllowed) - */ - public void acceptGearedCipherManager(GearedCipherManager cipherManager) { - _cipherManager = cipherManager; - } - - @Override - public GearedCipherManager getGearedCipherManager() { - return _cipherManager; - } - // =================================================================================== // Basic Override // ============== @Override - public String toString() { + public String toString() { // main items only final String title = DfTypeUtil.toClassTitle(this); final String split = (isSplit() ? (_asOrSplit ? "true(or)" : "true(and)") : "false"); return title + ":{like=" + _like + ", escape=" + _escape + ", split=" + split + "}"; diff --git a/dbflute-runtime/src/main/java/org/dbflute/cbean/coption/SimpleStringOption.java b/dbflute-runtime/src/main/java/org/dbflute/cbean/coption/SimpleStringOption.java index f8a2015ce..ad99892fd 100644 --- a/dbflute-runtime/src/main/java/org/dbflute/cbean/coption/SimpleStringOption.java +++ b/dbflute-runtime/src/main/java/org/dbflute/cbean/coption/SimpleStringOption.java @@ -35,7 +35,7 @@ public class SimpleStringOption implements ConditionOption { // =================================================================================== // Attribute // ========= - protected SplitOptionParts _splitOptionParts; + protected SplitOptionParts _splitOptionParts; // null allowed // =================================================================================== // Split @@ -94,20 +94,19 @@ protected SimpleStringOption doCutSplit(int splitLimitCount) { return this; } - // =================================================================================== - // Real Value - // ========== - public String generateRealValue(String value) { - return value; - } - // =================================================================================== // Interface Implementation // ======================== + // ----------------------------------------------------- + // Rear Option + // ----------- public String getRearOption() { - return ""; + return ""; // as default (not null) } + // ----------------------------------------------------- + // Compound Column + // --------------- public boolean hasCompoundColumn() { return false; } @@ -124,6 +123,9 @@ public OnQueryStringConnector getStringConnector() { return null; } + // ----------------------------------------------------- + // Clause Adjustment + // ----------------- public ExtensionOperand getExtensionOperand() { return null; } @@ -137,10 +139,10 @@ public GearedCipherManager getGearedCipherManager() { } // =================================================================================== - // General Helper - // ============== - protected String replace(String text, String fromText, String toText) { - return Srl.replace(text, fromText, toText); + // Real Value + // ========== + public String generateRealValue(String value) { + return value; // as default (no filter) } // =================================================================================== @@ -157,4 +159,11 @@ public SimpleStringOption createDeepCopy() { protected SimpleStringOption newDeepCopyInstance() { return new SimpleStringOption(); } + + // =================================================================================== + // General Helper + // ============== + protected String replace(String text, String fromText, String toText) { + return Srl.replace(text, fromText, toText); + } } diff --git a/dbflute-runtime/src/main/java/org/dbflute/cbean/sqlclause/query/QueryClauseArranger.java b/dbflute-runtime/src/main/java/org/dbflute/cbean/sqlclause/query/QueryClauseArranger.java index a9fd2d0e4..37a830ff5 100644 --- a/dbflute-runtime/src/main/java/org/dbflute/cbean/sqlclause/query/QueryClauseArranger.java +++ b/dbflute-runtime/src/main/java/org/dbflute/cbean/sqlclause/query/QueryClauseArranger.java @@ -18,7 +18,7 @@ import org.dbflute.dbmeta.name.ColumnRealName; /** - * The arranger of query clause. + * The arranger of query clause, for e.g. collate option. * @author jflute */ public interface QueryClauseArranger { diff --git a/dbflute-runtime/src/main/java/org/dbflute/dbway/WayOfPostgreSQL.java b/dbflute-runtime/src/main/java/org/dbflute/dbway/WayOfPostgreSQL.java index e681979ac..5fd596a3e 100644 --- a/dbflute-runtime/src/main/java/org/dbflute/dbway/WayOfPostgreSQL.java +++ b/dbflute-runtime/src/main/java/org/dbflute/dbway/WayOfPostgreSQL.java @@ -98,7 +98,7 @@ public enum OperandOfLikeSearch implements ExtensionOperand { /** normal */ BASIC("like") - /** regular expression */ + /** like-search with ignoring case (like is case-sensitive on PostgreSQL) */ , CASE_INSENSITIVE("ilike") /** MeCab+textsearch–ja */ diff --git a/dbflute-runtime/src/main/java/org/dbflute/dbway/topic/OnQueryStringConnector.java b/dbflute-runtime/src/main/java/org/dbflute/dbway/topic/OnQueryStringConnector.java index 6b27b2ab1..1e7596473 100644 --- a/dbflute-runtime/src/main/java/org/dbflute/dbway/topic/OnQueryStringConnector.java +++ b/dbflute-runtime/src/main/java/org/dbflute/dbway/topic/OnQueryStringConnector.java @@ -22,8 +22,8 @@ public interface OnQueryStringConnector { /** - * Connect the elements as string. - * @param elements The array of elements. (NotNull) + * Connect the query elements as string. + * @param elements The array of elements to be connected. (NotNull) * @return The connected string. (NotNull) */ String connect(Object... elements);