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}