001/**
002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (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 io.jboot.db.dialect;
017
018import com.jfinal.plugin.activerecord.CPI;
019import com.jfinal.plugin.activerecord.Record;
020import com.jfinal.plugin.activerecord.Table;
021import com.jfinal.plugin.activerecord.dialect.OracleDialect;
022import io.jboot.db.model.Column;
023import io.jboot.db.model.Join;
024import io.jboot.db.model.SqlBuilder;
025
026import java.util.List;
027import java.util.Map;
028import java.util.Set;
029
030/**
031 * 达梦数据库的数据方言
032 */
033public class JbootDmDialect extends OracleDialect implements JbootDialect {
034
035    private static final char separator = '"';
036
037    public String wrap(String wrap) {
038        return "\"" + wrap.toUpperCase() + "\"";
039    }
040
041    @Override
042    public String forTableBuilderDoBuild(String tableName) {
043        return toUpperCase("select * from " + wrap(tableName) + " where rownum < 1");
044    }
045
046
047    @Override
048    // insert into table (id,name) values(seq.nextval, ?)
049    public void forModelSave(Table table, Map<String, Object> attrs, StringBuilder sql, List<Object> paras) {
050        sql.append("insert into ").append(wrap(table.getName())).append('(');
051        StringBuilder temp = new StringBuilder(") values(");
052        String[] pKeys = table.getPrimaryKey();
053        int count = 0;
054        for (Map.Entry<String, Object> e : attrs.entrySet()) {
055            String colName = e.getKey();
056            if (table.hasColumnLabel(colName)) {
057                Object value = e.getValue();
058                if (isPrimaryKey(colName, pKeys) && value == null) {
059                    continue;
060                }
061
062                if (count++ > 0) {
063                    sql.append(", ");
064                    temp.append(", ");
065                }
066
067
068                if (isPrimaryKey(colName, pKeys) && value instanceof String && ((String) value).endsWith(".nextval")) {
069                    sql.append(wrap(colName));
070                    temp.append(value);
071                } else {
072                    sql.append(wrap(colName));
073                    temp.append('?');
074                    paras.add(value);
075                }
076            }
077        }
078        sql.append(temp).append(')');
079    }
080
081    @Override
082    public String forModelDeleteById(Table table) {
083        String[] pKeys = table.getPrimaryKey();
084        StringBuilder sql = new StringBuilder(45);
085        sql.append("delete from ");
086        sql.append(wrap(table.getName()));
087        sql.append(" where ");
088        for (int i = 0; i < pKeys.length; i++) {
089            if (i > 0) {
090                sql.append(" and ");
091            }
092            sql.append(wrap(pKeys[i])).append(" = ?");
093        }
094        return sql.toString();
095    }
096
097    @Override
098    public void forModelUpdate(Table table, Map<String, Object> attrs, Set<String> modifyFlag, StringBuilder sql, List<Object> paras) {
099        sql.append("update ").append(wrap(table.getName())).append(" set ");
100        String[] pKeys = table.getPrimaryKey();
101        for (Map.Entry<String, Object> e : attrs.entrySet()) {
102            String colName = e.getKey();
103            if (modifyFlag.contains(colName) && !isPrimaryKey(colName, pKeys) && table.hasColumnLabel(colName)) {
104                if (paras.size() > 0) {
105                    sql.append(", ");
106                }
107                sql.append(wrap(colName)).append(" = ? ");
108                paras.add(e.getValue());
109            }
110        }
111        sql.append(" where ");
112        for (int i = 0; i < pKeys.length; i++) {
113            if (i > 0) {
114                sql.append(" and ");
115            }
116            sql.append(wrap(pKeys[i])).append(" = ?");
117            paras.add(attrs.get(pKeys[i]));
118        }
119    }
120
121
122    @Override
123    public String forModelFindById(Table table, String columns) {
124        StringBuilder sql = new StringBuilder("select ").append(columns).append(" from ");
125        sql.append(wrap(table.getName()));
126        sql.append(" where ");
127        String[] pKeys = table.getPrimaryKey();
128        for (int i = 0; i < pKeys.length; i++) {
129            if (i > 0) {
130                sql.append(" and ");
131            }
132            sql.append(wrap(pKeys[i])).append(" = ?");
133        }
134        return sql.toString();
135    }
136
137
138    @Override
139    public String forDbFindById(String tableName, String[] pKeys) {
140        tableName = tableName.trim();
141        trimPrimaryKeys(pKeys);
142
143        StringBuilder sql = new StringBuilder("select * from ").append(wrap(tableName)).append(" where ");
144        for (int i = 0; i < pKeys.length; i++) {
145            if (i > 0) {
146                sql.append(" and ");
147            }
148            sql.append(wrap(pKeys[i])).append(" = ?");
149        }
150        return sql.toString();
151    }
152
153    @Override
154    public String forDbDeleteById(String tableName, String[] pKeys) {
155        tableName = tableName.trim();
156        trimPrimaryKeys(pKeys);
157
158        StringBuilder sql = new StringBuilder("delete from ").append(wrap(tableName)).append(" where ");
159        for (int i = 0; i < pKeys.length; i++) {
160            if (i > 0) {
161                sql.append(" and ");
162            }
163            sql.append(wrap(pKeys[i])).append(" = ?");
164        }
165        return sql.toString();
166    }
167
168
169    @Override
170    public void forDbSave(String tableName, String[] pKeys, Record record, StringBuilder sql, List<Object> paras) {
171        tableName = tableName.trim();
172        trimPrimaryKeys(pKeys);
173
174        sql.append("insert into ");
175        sql.append(wrap(tableName)).append('(');
176        StringBuilder temp = new StringBuilder();
177        temp.append(") values(");
178
179        int count = 0;
180        for (Map.Entry<String, Object> e : record.getColumns().entrySet()) {
181
182            String colName = e.getKey();
183            Object value = e.getValue();
184
185            if (isPrimaryKey(colName, pKeys) && value == null) {
186                continue;
187            }
188
189            if (count++ > 0) {
190                sql.append(", ");
191                temp.append(", ");
192            }
193            sql.append(wrap(colName));
194
195            if (value instanceof String && isPrimaryKey(colName, pKeys) && ((String) value).endsWith(".nextval")) {
196                temp.append(value);
197            } else {
198                temp.append('?');
199                paras.add(value);
200            }
201        }
202        sql.append(temp).append(')');
203    }
204
205
206    @Override
207    public void forDbUpdate(String tableName, String[] pKeys, Object[] ids, Record record, StringBuilder sql, List<Object> paras) {
208        tableName = tableName.trim();
209        trimPrimaryKeys(pKeys);
210
211        // Record 新增支持 modifyFlag
212        Set<String> modifyFlag = CPI.getModifyFlag(record);
213
214        sql.append("update ").append(wrap(tableName)).append(" set ");
215        for (Map.Entry<String, Object> e : record.getColumns().entrySet()) {
216            String colName = e.getKey();
217            if (modifyFlag.contains(colName) && !isPrimaryKey(colName, pKeys)) {
218                if (paras.size() > 0) {
219                    sql.append(", ");
220                }
221                sql.append(wrap(colName)).append(" = ? ");
222                paras.add(e.getValue());
223            }
224        }
225        sql.append(" where ");
226        for (int i = 0; i < pKeys.length; i++) {
227            if (i > 0) {
228                sql.append(" and ");
229            }
230            sql.append(wrap(pKeys[i])).append(" = ?");
231            paras.add(ids[i]);
232        }
233    }
234
235    @Override
236    public String forPaginate(int pageNumber, int pageSize, StringBuilder findSql) {
237        int start = (pageNumber - 1) * pageSize;
238        int end = pageNumber * pageSize;
239        StringBuilder ret = new StringBuilder();
240        ret.append("select * from ( select row_.*, rownum rownum_ from (  ");
241        ret.append(findSql);
242        ret.append(" ) row_ where rownum <= ").append(end).append(") table_alias");
243        ret.append(" where table_alias.rownum_ > ").append(start);
244        return ret.toString();
245    }
246
247
248    /////////////////jboot////////////
249
250    @Override
251    public String forFindByColumns(String alias, List<Join> joins, String table, String loadColumns, List<Column> columns, String orderBy, Object limit) {
252        StringBuilder sqlBuilder = SqlBuilder.forFindByColumns(alias, joins, table, loadColumns, columns, orderBy, separator);
253
254        if (limit != null) {
255            sqlBuilder.append(" LIMIT " + limit);
256        }
257        return toUpperCase(sqlBuilder.toString());
258    }
259
260    @Override
261    public String forFindCountByColumns(String alias, List<Join> joins, String table, String loadColumns, List<Column> columns) {
262        return toUpperCase(SqlBuilder.forFindCountByColumns(alias, joins, table, loadColumns, columns, separator));
263    }
264
265    @Override
266    public String forDeleteByColumns(String alias, List<Join> joins, String table, List<Column> columns) {
267        return toUpperCase(SqlBuilder.forDeleteByColumns(alias, joins, table, columns, separator));
268    }
269
270    @Override
271    public String forPaginateSelect(String loadColumns) {
272        return toUpperCase("SELECT " + loadColumns);
273    }
274
275
276    @Override
277    public String forPaginateFrom(String alias, List<Join> joins, String table, List<Column> columns, String orderBy) {
278        return toUpperCase(SqlBuilder.forPaginateFrom(alias, joins, table, columns, orderBy, separator));
279    }
280
281    @Override
282    public String forPaginateTotalRow(String select, String sqlExceptSelect, Object ext) {
283        String distinctSql = SqlBuilder.forPaginateDistinctTotalRow(select, sqlExceptSelect, ext);
284        return toUpperCase(distinctSql != null ? distinctSql : super.forPaginateTotalRow(select, sqlExceptSelect, ext));
285    }
286
287    public  String toUpperCase(String sql) {
288        return sql.toUpperCase();
289    }
290}