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 CaseQueryColumn extends QueryColumn implements HasParamsColumn { 030 031 private List<When> whens; 032 private Object elseValue; 033 034 void addWhen(When when) { 035 if (whens == null) { 036 whens = new ArrayList<>(); 037 } 038 whens.add(when); 039 } 040 041 042 @Override 043 String toSelectSql(List<QueryTable> queryTables, IDialect dialect) { 044 StringBuilder sql = new StringBuilder("CASE"); 045 for (When when : whens) { 046 sql.append(" WHEN ").append(when.whenCondition.toSql(queryTables, dialect)); 047 sql.append(" THEN ").append(buildValue(when.thenValue)); 048 } 049 if (elseValue != null) { 050 sql.append(" ELSE ").append(buildValue(elseValue)); 051 } 052 sql.append(" END"); 053 if (StringUtil.isNotBlank(alias)) { 054 return "(" + sql + ") AS " + dialect.wrap(alias); 055 } 056 return sql.toString(); 057 } 058 059 060 @Override 061 String toConditionSql(List<QueryTable> queryTables, IDialect dialect) { 062 StringBuilder sql = new StringBuilder("CASE"); 063 for (When when : whens) { 064 sql.append(" WHEN ").append(when.whenCondition.toSql(queryTables, dialect)); 065 sql.append(" THEN ").append(buildValue(when.thenValue)); 066 } 067 if (elseValue != null) { 068 sql.append(" ELSE ").append(buildValue(elseValue)); 069 } 070 sql.append(" END"); 071 return "(" + sql + ")"; 072 } 073 074 @Override 075 public QueryColumn as(String alias) { 076 this.alias = alias; 077 return this; 078 } 079 080 @Override 081 public <T> QueryColumn as(LambdaGetter<T> fn) { 082 return as(LambdaUtil.getFieldName(fn)); 083 } 084 085 private String buildValue(Object value) { 086 if (value instanceof Number || value instanceof Boolean) { 087 return String.valueOf(value); 088 } else if (value instanceof RawFragment) { 089 return ((RawFragment) value).getContent(); 090 } else if (value instanceof QueryColumn) { 091 return ((QueryColumn) value).toConditionSql(null, DialectFactory.getDialect()); 092 } else { 093 return "'" + value + "'"; 094 } 095 } 096 097 @Override 098 public Object[] getParamValues() { 099 Object[] values = FlexConsts.EMPTY_ARRAY; 100 for (When when : whens) { 101 values = ArrayUtil.concat(values, WrapperUtil.getValues(when.whenCondition)); 102 } 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 QueryCondition whenCondition; 113 private Object thenValue; 114 115 public When(Builder builder, QueryCondition whenCondition) { 116 this.builder = builder; 117 this.whenCondition = whenCondition; 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 CaseQueryColumn caseQueryColumn = new CaseQueryColumn(); 130 131 public When when(QueryCondition condition) { 132 return new When(this, condition); 133 } 134 135 public Builder else_(Object elseValue) { 136 caseQueryColumn.elseValue = elseValue; 137 return this; 138 } 139 140 public CaseQueryColumn end() { 141 return caseQueryColumn; 142 } 143 } 144}