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.dialect.IDialect;
019import com.mybatisflex.core.util.StringUtil;
020
021import java.util.ArrayList;
022import java.util.List;
023
024public class ArithmeticQueryColumn extends QueryColumn {
025
026    private List<ArithmeticInfo> arithmeticInfos;
027
028    public ArithmeticQueryColumn(Object value) {
029        arithmeticInfos = new ArrayList<>();
030        arithmeticInfos.add(new ArithmeticInfo(value));
031    }
032
033    @Override
034    public QueryColumn add(QueryColumn queryColumn) {
035        arithmeticInfos.add(new ArithmeticInfo(" + ", queryColumn));
036        return this;
037    }
038
039    @Override
040    public QueryColumn add(Number number) {
041        arithmeticInfos.add(new ArithmeticInfo(" + ", number));
042        return this;
043    }
044
045    @Override
046    public QueryColumn subtract(QueryColumn queryColumn) {
047        arithmeticInfos.add(new ArithmeticInfo(" - ", queryColumn));
048        return this;
049    }
050
051    @Override
052    public QueryColumn subtract(Number number) {
053        arithmeticInfos.add(new ArithmeticInfo(" - ", number));
054        return this;
055    }
056
057    @Override
058    public QueryColumn multiply(QueryColumn queryColumn) {
059        arithmeticInfos.add(new ArithmeticInfo(" * ", queryColumn));
060        return this;
061    }
062
063    @Override
064    public QueryColumn multiply(Number number) {
065        arithmeticInfos.add(new ArithmeticInfo(" * ", number));
066        return this;
067    }
068
069    @Override
070    public QueryColumn divide(QueryColumn queryColumn) {
071        arithmeticInfos.add(new ArithmeticInfo(" / ", queryColumn));
072        return this;
073    }
074
075    @Override
076    public QueryColumn divide(Number number) {
077        arithmeticInfos.add(new ArithmeticInfo(" / ", number));
078        return this;
079    }
080
081    @Override
082    public QueryColumn as(String alias) {
083        this.alias = alias;
084        return this;
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 "(" + sql + ") AS " + dialect.wrap(alias);
095        }
096        return sql.toString();
097    }
098
099
100    @Override
101    String toConditionSql(List<QueryTable> queryTables, IDialect dialect) {
102        StringBuilder sql = new StringBuilder();
103        for (int i = 0; i < arithmeticInfos.size(); i++) {
104            sql.append(arithmeticInfos.get(i).toSql(queryTables, dialect, i));
105        }
106        return "(" + sql + ")";
107    }
108
109
110    static class ArithmeticInfo {
111        private String symbol;
112        private Object value;
113
114        public ArithmeticInfo(Object value) {
115            this.value = value;
116        }
117
118        public ArithmeticInfo(String symbol, Object value) {
119            this.symbol = symbol;
120            this.value = value;
121        }
122
123        private String toSql(List<QueryTable> queryTables, IDialect dialect, int index) {
124            String valueSql;
125            if (value instanceof QueryColumn) {
126                valueSql = ((QueryColumn) value).toConditionSql(queryTables, dialect);
127            } else {
128                valueSql = String.valueOf(value);
129            }
130            return index == 0 ? valueSql : symbol  + valueSql;
131        }
132    }
133}