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
018
019import com.mybatisflex.core.dialect.IDialect;
020import com.mybatisflex.core.table.TableDef;
021import com.mybatisflex.core.util.*;
022
023import java.io.Serializable;
024import java.util.Collection;
025import java.util.List;
026import java.util.function.Predicate;
027
028/**
029 * 查询列,描述的是一张表的字段
030 */
031public class QueryColumn implements Serializable {
032
033    protected QueryTable table;
034    protected String name;
035    protected String alias;
036
037
038    public QueryColumn() {
039    }
040
041    public QueryColumn(String name) {
042        SqlUtil.keepColumnSafely(name);
043        this.name = name;
044    }
045
046    public QueryColumn(String schema, String tableName, String name) {
047        SqlUtil.keepColumnSafely(name);
048        this.table = new QueryTable(schema, tableName);
049        this.name = name;
050    }
051
052    public QueryColumn(TableDef tableDef, String name) {
053        SqlUtil.keepColumnSafely(name);
054        this.table = new QueryTable(tableDef);
055        this.name = name;
056    }
057
058    public QueryColumn(QueryTable queryTable, String name) {
059        SqlUtil.keepColumnSafely(name);
060        this.table = queryTable;
061        this.name = name;
062    }
063
064
065    public QueryTable getTable() {
066        return table;
067    }
068
069    public void setTable(QueryTable table) {
070        this.table = table;
071    }
072
073    public String getName() {
074        return name;
075    }
076
077    public void setName(String name) {
078        this.name = name;
079    }
080
081    public String getAlias() {
082        return alias;
083    }
084
085    public void setAlias(String alias) {
086        this.alias = alias;
087    }
088
089    public <T> QueryColumn as(LambdaGetter<T> fn) {
090        return as(LambdaUtil.getFieldName(fn));
091    }
092
093    public QueryColumn as(String alias) {
094        SqlUtil.keepColumnSafely(alias);
095        QueryColumn newColumn = new QueryColumn();
096        newColumn.table = this.table;
097        newColumn.name = this.name;
098        newColumn.alias = alias;
099        return newColumn;
100    }
101
102
103    // query methods ///////
104
105    /**
106     * equals
107     *
108     * @param value
109     */
110    public QueryCondition eq(Object value) {
111        if (value == null) {
112            return QueryCondition.createEmpty();
113        }
114        return QueryCondition.create(this, QueryCondition.LOGIC_EQUALS, value);
115    }
116
117
118    public <T> QueryCondition eq(Object value, Predicate<T> fn) {
119        if (value == null) {
120            return QueryCondition.createEmpty();
121        }
122        return QueryCondition.create(this, QueryCondition.LOGIC_EQUALS, value).when(fn);
123    }
124
125
126    /**
127     * not equals !=
128     *
129     * @param value
130     */
131    public QueryCondition ne(Object value) {
132        if (value == null) {
133            return QueryCondition.createEmpty();
134        }
135        return QueryCondition.create(this, QueryCondition.LOGIC_NOT_EQUALS, value);
136    }
137
138    public <T> QueryCondition ne(Object value, Predicate<T> fn) {
139        if (value == null) {
140            return QueryCondition.createEmpty();
141        }
142        return QueryCondition.create(this, QueryCondition.LOGIC_NOT_EQUALS, value).when(fn);
143    }
144
145
146    /**
147     * like %%
148     *
149     * @param value
150     */
151    public QueryCondition like(Object value) {
152        if (value == null) {
153            return QueryCondition.createEmpty();
154        }
155        return QueryCondition.create(this, QueryCondition.LOGIC_LIKE, "%" + value + "%");
156    }
157
158    public <T> QueryCondition like(Object value, Predicate<T> fn) {
159        if (value == null) {
160            return QueryCondition.createEmpty();
161        }
162        return QueryCondition.create(this, QueryCondition.LOGIC_LIKE, "%" + value + "%").when(fn);
163    }
164
165
166    public QueryCondition likeLeft(Object value) {
167        if (value == null) {
168            return QueryCondition.createEmpty();
169        }
170        return QueryCondition.create(this, QueryCondition.LOGIC_LIKE, "%" + value);
171    }
172
173    public <T> QueryCondition likeLeft(Object value, Predicate<T> fn) {
174        if (value == null) {
175            return QueryCondition.createEmpty();
176        }
177        return QueryCondition.create(this, QueryCondition.LOGIC_LIKE, "%" + value).when(fn);
178    }
179
180
181    public QueryCondition likeRight(Object value) {
182        if (value == null) {
183            return QueryCondition.createEmpty();
184        }
185        return QueryCondition.create(this, QueryCondition.LOGIC_LIKE, value + "%");
186    }
187
188    public <T> QueryCondition likeRight(Object value, Predicate<T> fn) {
189        if (value == null) {
190            return QueryCondition.createEmpty();
191        }
192        return QueryCondition.create(this, QueryCondition.LOGIC_LIKE, value + "%").when(fn);
193    }
194
195    /**
196     * 大于 greater than
197     *
198     * @param value
199     */
200    public QueryCondition gt(Object value) {
201        if (value == null) {
202            return QueryCondition.createEmpty();
203        }
204        return QueryCondition.create(this, QueryCondition.LOGIC_GT, value);
205    }
206
207    public <T> QueryCondition gt(Object value, Predicate<T> fn) {
208        if (value == null) {
209            return QueryCondition.createEmpty();
210        }
211        return QueryCondition.create(this, QueryCondition.LOGIC_GT, value).when(fn);
212    }
213
214    /**
215     * 大于等于 greater or equal
216     *
217     * @param value
218     */
219    public QueryCondition ge(Object value) {
220        if (value == null) {
221            return QueryCondition.createEmpty();
222        }
223        return QueryCondition.create(this, QueryCondition.LOGIC_GE, value);
224    }
225
226    public <T> QueryCondition ge(Object value, Predicate<T> fn) {
227        if (value == null) {
228            return QueryCondition.createEmpty();
229        }
230        return QueryCondition.create(this, QueryCondition.LOGIC_GE, value).when(fn);
231    }
232
233    /**
234     * 小于 less than
235     *
236     * @param value
237     */
238    public QueryCondition lt(Object value) {
239        if (value == null) {
240            return QueryCondition.createEmpty();
241        }
242        return QueryCondition.create(this, QueryCondition.LOGIC_LT, value);
243    }
244
245    public <T> QueryCondition lt(Object value, Predicate<T> fn) {
246        if (value == null) {
247            return QueryCondition.createEmpty();
248        }
249        return QueryCondition.create(this, QueryCondition.LOGIC_LT, value).when(fn);
250    }
251
252    /**
253     * 小于等于 less or equal
254     *
255     * @param value
256     */
257    public QueryCondition le(Object value) {
258        if (value == null) {
259            return QueryCondition.createEmpty();
260        }
261        return QueryCondition.create(this, QueryCondition.LOGIC_LE, value);
262    }
263
264    public <T> QueryCondition le(Object value, Predicate<T> fn) {
265        if (value == null) {
266            return QueryCondition.createEmpty();
267        }
268        return QueryCondition.create(this, QueryCondition.LOGIC_LE, value).when(fn);
269    }
270
271
272    /**
273     * IS NULL
274     *
275     * @return
276     */
277    public QueryCondition isNull() {
278        return QueryCondition.create(this, QueryCondition.LOGIC_IS_NULL, null);
279    }
280
281    public <T> QueryCondition isNull(Predicate<T> fn) {
282        return QueryCondition.create(this, QueryCondition.LOGIC_IS_NULL, null).when(fn);
283    }
284
285
286    /**
287     * IS NOT NULL
288     *
289     * @return
290     */
291    public QueryCondition isNotNull() {
292        return QueryCondition.create(this, QueryCondition.LOGIC_IS_NOT_NULL, null);
293    }
294
295    public <T> QueryCondition isNotNull(Predicate<T> fn) {
296        return QueryCondition.create(this, QueryCondition.LOGIC_IS_NOT_NULL, null).when(fn);
297    }
298
299
300    /**
301     * in arrays
302     *
303     * @param arrays
304     * @return
305     */
306    public QueryCondition in(Object... arrays) {
307        //忽略 QueryWrapper.in("name", null) 的情况
308        if (arrays == null || arrays.length == 0 || (arrays.length == 1 && arrays[0] == null)) {
309            return QueryCondition.createEmpty();
310        }
311        return QueryCondition.create(this, QueryCondition.LOGIC_IN, arrays);
312    }
313
314    public <T> QueryCondition in(Object[] arrays, Predicate<T> fn) {
315        //忽略 QueryWrapper.in("name", null) 的情况
316        if (arrays == null || arrays.length == 0 || (arrays.length == 1 && arrays[0] == null)) {
317            return QueryCondition.createEmpty();
318        }
319        return QueryCondition.create(this, QueryCondition.LOGIC_IN, arrays).when(fn);
320    }
321
322    /**
323     * in child select
324     *
325     * @param queryWrapper
326     * @return
327     */
328    public QueryCondition in(QueryWrapper queryWrapper) {
329        return QueryCondition.create(this, QueryCondition.LOGIC_IN, queryWrapper);
330    }
331
332    public <T> QueryCondition in(QueryWrapper queryWrapper, Predicate<T> fn) {
333        return QueryCondition.create(this, QueryCondition.LOGIC_IN, queryWrapper).when(fn);
334    }
335
336
337    /**
338     * in Collection
339     *
340     * @param collection
341     * @return
342     */
343    public QueryCondition in(Collection<?> collection) {
344        if (collection != null && !collection.isEmpty()) {
345            return in(collection.toArray());
346        }
347        return QueryCondition.createEmpty();
348    }
349
350    public <T> QueryCondition in(Collection<?> collection, Predicate<T> fn) {
351        if (collection != null && !collection.isEmpty()) {
352            return in(collection.toArray(), fn);
353        }
354        return QueryCondition.createEmpty();
355    }
356
357    /**
358     * not int arrays
359     *
360     * @param arrays
361     * @return
362     */
363    public QueryCondition notIn(Object... arrays) {
364        //忽略 QueryWrapper.notIn("name", null) 的情况
365        if (arrays == null || arrays.length == 0 || (arrays.length == 1 && arrays[0] == null)) {
366            return QueryCondition.createEmpty();
367        }
368        return QueryCondition.create(this, QueryCondition.LOGIC_NOT_IN, arrays);
369    }
370
371    public <T> QueryCondition notIn(Object[] arrays, Predicate<T> fn) {
372        //忽略 QueryWrapper.notIn("name", null) 的情况
373        if (arrays == null || arrays.length == 0 || (arrays.length == 1 && arrays[0] == null)) {
374            return QueryCondition.createEmpty();
375        }
376        return QueryCondition.create(this, QueryCondition.LOGIC_NOT_IN, arrays).when(fn);
377    }
378
379
380    /**
381     * not in Collection
382     *
383     * @param collection
384     * @return
385     */
386    public QueryCondition notIn(Collection<?> collection) {
387        if (collection != null && !collection.isEmpty()) {
388            return notIn(collection.toArray());
389        }
390        return QueryCondition.createEmpty();
391    }
392
393    public <T> QueryCondition notIn(Collection<?> collection, Predicate<T> fn) {
394        if (collection != null && !collection.isEmpty()) {
395            return notIn(collection.toArray(), fn);
396        }
397        return QueryCondition.createEmpty();
398    }
399
400    /**
401     * not in child select
402     *
403     * @param queryWrapper
404     */
405    public QueryCondition notIn(QueryWrapper queryWrapper) {
406        return QueryCondition.create(this, QueryCondition.LOGIC_NOT_IN, queryWrapper);
407    }
408
409    public <T> QueryCondition notIn(QueryWrapper queryWrapper, Predicate<T> fn) {
410        return QueryCondition.create(this, QueryCondition.LOGIC_NOT_IN, queryWrapper).when(fn);
411    }
412
413
414    /**
415     * between
416     *
417     * @param start
418     * @param end
419     */
420    public QueryCondition between(Object start, Object end) {
421        return QueryCondition.create(this, QueryCondition.LOGIC_BETWEEN, new Object[]{start, end});
422    }
423
424    public <T> QueryCondition between(Object start, Object end, Predicate<T> fn) {
425        return QueryCondition.create(this, QueryCondition.LOGIC_BETWEEN, new Object[]{start, end}).when(fn);
426    }
427
428
429    /**
430     * not between
431     *
432     * @param start
433     * @param end
434     */
435    public QueryCondition notBetween(Object start, Object end) {
436        return QueryCondition.create(this, QueryCondition.LOGIC_NOT_BETWEEN, new Object[]{start, end});
437    }
438
439    public <T> QueryCondition notBetween(Object start, Object end, Predicate<T> fn) {
440        return QueryCondition.create(this, QueryCondition.LOGIC_NOT_BETWEEN, new Object[]{start, end}).when(fn);
441    }
442
443
444    ////order by ////
445    public QueryOrderBy asc() {
446        return new QueryOrderBy(this);
447    }
448
449
450    public QueryOrderBy desc() {
451        return new QueryOrderBy(this, "DESC");
452    }
453
454
455    // 运算 加减乘除 + - * /
456    public QueryColumn add(QueryColumn queryColumn) {
457        return new ArithmeticQueryColumn(this).add(queryColumn);
458    }
459
460    public QueryColumn add(Number number) {
461        return new ArithmeticQueryColumn(this).add(number);
462    }
463
464    public QueryColumn subtract(QueryColumn queryColumn) {
465        return new ArithmeticQueryColumn(this).subtract(queryColumn);
466    }
467
468    public QueryColumn subtract(Number number) {
469        return new ArithmeticQueryColumn(this).subtract(number);
470    }
471
472    public QueryColumn multiply(QueryColumn queryColumn) {
473        return new ArithmeticQueryColumn(this).multiply(queryColumn);
474    }
475
476    public QueryColumn multiply(Number number) {
477        return new ArithmeticQueryColumn(this).multiply(number);
478    }
479
480    public QueryColumn divide(QueryColumn queryColumn) {
481        return new ArithmeticQueryColumn(this).divide(queryColumn);
482    }
483
484    public QueryColumn divide(Number number) {
485        return new ArithmeticQueryColumn(this).divide(number);
486    }
487
488
489    String toConditionSql(List<QueryTable> queryTables, IDialect dialect) {
490        QueryTable selectTable = getSelectTable(queryTables, table);
491        if (selectTable == null) {
492            return dialect.wrap(name);
493        } else {
494            if (StringUtil.isNotBlank(selectTable.alias)) {
495                return dialect.wrap(selectTable.alias) + "." + dialect.wrap(name);
496            } else if (StringUtil.isNotBlank(selectTable.getSchema()) && StringUtil.isNotBlank(selectTable.getName())) {
497                return dialect.wrap(dialect.getRealSchema(selectTable.schema)) + "." + dialect.wrap(dialect.getRealTable(selectTable.getName())) + "." + dialect.wrap(name);
498            } else if (StringUtil.isNotBlank(selectTable.getName())) {
499                return dialect.wrap(dialect.getRealTable(selectTable.getName())) + "." + dialect.wrap(name);
500            } else {
501                return dialect.wrap(name);
502            }
503        }
504    }
505
506
507    String toSelectSql(List<QueryTable> queryTables, IDialect dialect) {
508        return toConditionSql(queryTables, dialect) + WrapperUtil.buildAsAlias(alias, dialect);
509    }
510
511
512    QueryTable getSelectTable(List<QueryTable> queryTables, QueryTable columnTable) {
513        if (queryTables == null || queryTables.isEmpty()) {
514            return null;
515        }
516
517        if (queryTables.size() == 1 && queryTables.get(0).isSameTable(columnTable)) {
518            //ignore table
519            return null;
520        }
521
522        if (CollectionUtil.isEmpty(queryTables)) {
523            return columnTable;
524        }
525
526        if (columnTable == null && queryTables.size() == 1) {
527            return queryTables.get(0);
528        }
529
530        for (QueryTable table : queryTables) {
531            if (table.isSameTable(columnTable)) {
532                return table;
533            }
534        }
535        return columnTable;
536    }
537
538
539    @Override
540    public String toString() {
541        return "QueryColumn{" +
542                "table=" + table +
543                ", name='" + name + '\'' +
544                ", alias='" + alias + '\'' +
545                '}';
546    }
547
548
549}