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.constant.SqlConsts; 019import com.mybatisflex.core.dialect.IDialect; 020import com.mybatisflex.core.exception.FlexExceptions; 021import com.mybatisflex.core.util.CollectionUtil; 022import com.mybatisflex.core.util.StringUtil; 023 024import java.util.ArrayList; 025import java.util.Arrays; 026import java.util.List; 027 028import static com.mybatisflex.core.constant.SqlConsts.*; 029 030public class ArithmeticQueryColumn extends QueryColumn implements HasParamsColumn { 031 032 private List<ArithmeticInfo> arithmeticInfos; 033 034 public ArithmeticQueryColumn(Object value) { 035 arithmeticInfos = new ArrayList<>(); 036 arithmeticInfos.add(new ArithmeticInfo(value)); 037 } 038 039 @Override 040 public QueryColumn add(QueryColumn queryColumn) { 041 arithmeticInfos.add(new ArithmeticInfo(PLUS_SIGN, queryColumn)); 042 return this; 043 } 044 045 @Override 046 public QueryColumn add(Number number) { 047 arithmeticInfos.add(new ArithmeticInfo(PLUS_SIGN, number)); 048 return this; 049 } 050 051 @Override 052 public QueryColumn subtract(QueryColumn queryColumn) { 053 arithmeticInfos.add(new ArithmeticInfo(MINUS_SIGN, queryColumn)); 054 return this; 055 } 056 057 @Override 058 public QueryColumn subtract(Number number) { 059 arithmeticInfos.add(new ArithmeticInfo(MINUS_SIGN, number)); 060 return this; 061 } 062 063 @Override 064 public QueryColumn multiply(QueryColumn queryColumn) { 065 arithmeticInfos.add(new ArithmeticInfo(MULTIPLICATION_SIGN, queryColumn)); 066 return this; 067 } 068 069 @Override 070 public QueryColumn multiply(Number number) { 071 arithmeticInfos.add(new ArithmeticInfo(MULTIPLICATION_SIGN, number)); 072 return this; 073 } 074 075 @Override 076 public QueryColumn divide(QueryColumn queryColumn) { 077 arithmeticInfos.add(new ArithmeticInfo(DIVISION_SIGN, queryColumn)); 078 return this; 079 } 080 081 @Override 082 public QueryColumn divide(Number number) { 083 arithmeticInfos.add(new ArithmeticInfo(DIVISION_SIGN, number)); 084 return this; 085 } 086 087 088 @Override 089 String toSelectSql(List<QueryTable> queryTables, IDialect dialect) { 090 StringBuilder sql = new StringBuilder(); 091 for (int i = 0; i < arithmeticInfos.size(); i++) { 092 sql.append(arithmeticInfos.get(i).toSql(queryTables, dialect, i)); 093 } 094 if (StringUtil.isNotBlank(alias)) { 095 return WrapperUtil.withAlias(sql.toString(), alias, dialect); 096 } 097 return sql.toString(); 098 } 099 100 @Override 101 public ArithmeticQueryColumn clone() { 102 ArithmeticQueryColumn clone = (ArithmeticQueryColumn) super.clone(); 103 // deep clone ... 104 clone.arithmeticInfos = CollectionUtil.cloneArrayList(this.arithmeticInfos); 105 return clone; 106 } 107 108 109 @Override 110 String toConditionSql(List<QueryTable> queryTables, IDialect dialect) { 111 StringBuilder sql = new StringBuilder(); 112 for (int i = 0; i < arithmeticInfos.size(); i++) { 113 sql.append(arithmeticInfos.get(i).toSql(queryTables, dialect, i)); 114 } 115 return SqlConsts.BRACKET_LEFT + sql + SqlConsts.BRACKET_RIGHT; 116 } 117 118 @Override 119 public Object[] getParamValues() { 120 return arithmeticInfos.stream() 121 .map(arithmeticInfo -> arithmeticInfo.value) 122 .filter(value -> value instanceof HasParamsColumn) 123 .map(value -> ((HasParamsColumn) value).getParamValues()) 124 .flatMap(Arrays::stream) 125 .toArray(); 126 } 127 128 129 static class ArithmeticInfo implements CloneSupport<ArithmeticInfo> { 130 131 private String symbol; 132 private Object value; 133 134 public ArithmeticInfo(Object value) { 135 this(null, value); 136 } 137 138 public ArithmeticInfo(String symbol, Object value) { 139 this.symbol = symbol; 140 this.value = value; 141 } 142 143 private String toSql(List<QueryTable> queryTables, IDialect dialect, int index) { 144 String valueSql; 145 if (value instanceof QueryColumn) { 146 valueSql = ((QueryColumn) value).toConditionSql(queryTables, dialect); 147 } else { 148 valueSql = String.valueOf(value); 149 } 150 return index == 0 ? valueSql : symbol + valueSql; 151 } 152 153 @Override 154 public ArithmeticInfo clone() { 155 try { 156 return (ArithmeticInfo) super.clone(); 157 } catch (CloneNotSupportedException e) { 158 throw FlexExceptions.wrap(e); 159 } 160 } 161 162 } 163 164}