001/** 002 * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.mybatisflex.core.query; 017 018import com.mybatisflex.core.FlexConsts; 019import com.mybatisflex.core.dialect.DialectFactory; 020import com.mybatisflex.core.dialect.IDialect; 021import com.mybatisflex.core.util.ArrayUtil; 022import com.mybatisflex.core.util.LambdaGetter; 023import com.mybatisflex.core.util.LambdaUtil; 024import com.mybatisflex.core.util.StringUtil; 025 026import java.util.ArrayList; 027import java.util.List; 028 029public class CaseSearchQueryColumn extends QueryColumn implements HasParamsColumn { 030 031 private QueryColumn queryColumn; 032 private List<When> whens; 033 private Object elseValue; 034 035 @Override 036 String toSelectSql(List<QueryTable> queryTables, IDialect dialect) { 037 StringBuilder sql = new StringBuilder("CASE "); 038 sql.append(queryColumn.toSelectSql(queryTables, dialect)); 039 for (When when : whens) { 040 sql.append(" WHEN ").append(buildValue(when.searchValue)).append(" THEN ").append(buildValue(when.thenValue)); 041 } 042 if (elseValue != null) { 043 sql.append(" ELSE ").append(buildValue(elseValue)); 044 } 045 sql.append(" END"); 046 if (StringUtil.isNotBlank(alias)) { 047 return "(" + sql + ") AS " + dialect.wrap(alias); 048 } 049 return sql.toString(); 050 } 051 052 053 @Override 054 String toConditionSql(List<QueryTable> queryTables, IDialect dialect) { 055 StringBuilder sql = new StringBuilder("CASE "); 056 sql.append(queryColumn.toSelectSql(queryTables, dialect)); 057 for (When when : whens) { 058 sql.append(" WHEN ").append(buildValue(when.searchValue)).append(" THEN ").append(buildValue(when.thenValue)); 059 } 060 if (elseValue != null) { 061 sql.append(" ELSE ").append(buildValue(elseValue)); 062 } 063 sql.append(" END"); 064 return "(" + sql + ")"; 065 } 066 067 068 private String buildValue(Object value) { 069 if (value instanceof Number || value instanceof Boolean) { 070 return String.valueOf(value); 071 } else if (value instanceof RawFragment) { 072 return ((RawFragment) value).getContent(); 073 } else if (value instanceof QueryColumn) { 074 return ((QueryColumn) value).toConditionSql(null, DialectFactory.getDialect()); 075 } else { 076 return "'" + value + "'"; 077 } 078 } 079 080 081 void addWhen(When when) { 082 if (whens == null) { 083 whens = new ArrayList<>(); 084 } 085 whens.add(when); 086 } 087 088 @Override 089 public QueryColumn as(String alias) { 090 this.alias = alias; 091 return this; 092 } 093 094 @Override 095 public <T> QueryColumn as(LambdaGetter<T> fn) { 096 return as(LambdaUtil.getFieldName(fn)); 097 } 098 099 100 @Override 101 public Object[] getParamValues() { 102 Object[] values = FlexConsts.EMPTY_ARRAY; 103 if (elseValue instanceof HasParamsColumn) { 104 values = ArrayUtil.concat(values, ((HasParamsColumn) elseValue).getParamValues()); 105 } 106 return values; 107 } 108 109 110 public static class When { 111 private Builder builder; 112 private Object searchValue; 113 private Object thenValue; 114 115 public When(Builder builder, Object searchValue) { 116 this.builder = builder; 117 this.searchValue = searchValue; 118 } 119 120 public Builder then(Object thenValue) { 121 this.thenValue = thenValue; 122 this.builder.caseQueryColumn.addWhen(this); 123 return builder; 124 } 125 } 126 127 public static class Builder { 128 129 private CaseSearchQueryColumn caseQueryColumn = new CaseSearchQueryColumn(); 130 131 public Builder(QueryColumn queryColumn) { 132 this.caseQueryColumn.queryColumn = queryColumn; 133 } 134 135 public When when(Object searchValue) { 136 return new When(this, searchValue); 137 } 138 139 public Builder else_(Object elseValue) { 140 caseQueryColumn.elseValue = elseValue; 141 return this; 142 } 143 144 public CaseSearchQueryColumn end() { 145 return caseQueryColumn; 146 } 147 } 148}