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