001/*
002 *  Copyright (c) 2022-2024, 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.constant.SqlConsts;
020import com.mybatisflex.core.constant.SqlOperator;
021import com.mybatisflex.core.dialect.IDialect;
022import com.mybatisflex.core.dialect.OperateType;
023import com.mybatisflex.core.exception.FlexExceptions;
024import com.mybatisflex.core.util.LambdaGetter;
025import com.mybatisflex.core.util.LambdaUtil;
026import com.mybatisflex.core.util.ObjectUtil;
027import com.mybatisflex.core.util.SqlUtil;
028import com.mybatisflex.core.util.StringUtil;
029
030import java.util.Collection;
031import java.util.List;
032import java.util.ListIterator;
033import java.util.Objects;
034import java.util.function.BiPredicate;
035import java.util.function.BooleanSupplier;
036import java.util.function.Predicate;
037
038/**
039 * 查询列,描述的是一张表的字段
040 */
041public class QueryColumn implements CloneSupport<QueryColumn>, Conditional<QueryCondition> {
042
043    protected QueryTable table;
044    protected String name;
045    protected String alias;
046
047    private boolean returnCopyByAsMethod = false;
048
049    public QueryColumn() {
050    }
051
052    public QueryColumn(String name) {
053        SqlUtil.keepColumnSafely(name);
054        this.name = StringUtil.tryTrim(name);
055    }
056
057    public QueryColumn(String tableName, String name) {
058        SqlUtil.keepColumnSafely(name);
059        this.table = new QueryTable(tableName);
060        this.name = StringUtil.tryTrim(name);
061    }
062
063    public QueryColumn(String schema, String tableName, String name) {
064        SqlUtil.keepColumnSafely(name);
065        this.table = new QueryTable(schema, tableName);
066        this.name = StringUtil.tryTrim(name);
067    }
068
069    public QueryColumn(String schema, String tableName, String name, String alias) {
070        SqlUtil.keepColumnSafely(name);
071        this.returnCopyByAsMethod = true;
072        this.table = new QueryTable(schema, tableName);
073        this.name = StringUtil.tryTrim(name);
074        this.alias = StringUtil.tryTrim(alias);
075    }
076
077    public QueryColumn(QueryTable queryTable, String name) {
078        SqlUtil.keepColumnSafely(name);
079        this.table = queryTable;
080        this.name = StringUtil.tryTrim(name);
081        this.returnCopyByAsMethod = true;
082    }
083
084    public QueryColumn(QueryTable queryTable, String name, String alias) {
085        SqlUtil.keepColumnSafely(name);
086        this.returnCopyByAsMethod = true;
087        this.table = queryTable;
088        this.name = StringUtil.tryTrim(name);
089        this.alias = StringUtil.tryTrim(alias);
090    }
091
092    public QueryTable getTable() {
093        return table;
094    }
095
096    public void setTable(QueryTable table) {
097        this.table = table;
098    }
099
100    public String getName() {
101        return name;
102    }
103
104    public void setName(String name) {
105        this.name = name;
106    }
107
108    public String getAlias() {
109        return alias;
110    }
111
112    public void setAlias(String alias) {
113        this.alias = alias;
114    }
115
116    public <T> QueryColumn as(LambdaGetter<T> fn) {
117        return as(fn, false);
118    }
119
120    public <T> QueryColumn as(LambdaGetter<T> fn, boolean withPrefix) {
121        return as(LambdaUtil.getAliasName(fn, withPrefix));
122    }
123
124    public QueryColumn as(String alias) {
125        SqlUtil.keepColumnSafely(alias);
126        if (returnCopyByAsMethod) {
127            QueryColumn newColumn = new QueryColumn();
128            newColumn.table = this.table;
129            newColumn.name = this.name;
130            newColumn.alias = alias;
131            return newColumn;
132        } else {
133            this.alias = alias;
134            return this;
135        }
136    }
137
138
139    // query methods ///////
140    QueryCondition eq_(Object value) {
141        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.EQUALS, value));
142    }
143
144    @Override
145    public QueryCondition eq(Object value) {
146        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
147            return QueryCondition.createEmpty();
148        }
149        return eq_(value);
150    }
151
152    @Override
153    public QueryCondition eq(Object value, boolean isEffective) {
154        if (!isEffective) {
155            return QueryCondition.createEmpty();
156        }
157        return eq_(value);
158    }
159
160    @Override
161    public QueryCondition eq(Object value, BooleanSupplier isEffective) {
162        return eq(value, isEffective.getAsBoolean());
163    }
164
165    @Override
166    public <T> QueryCondition eq(T value, Predicate<T> isEffective) {
167        return eq(value, isEffective.test(value));
168    }
169
170
171    QueryCondition ne_(Object value) {
172        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.NOT_EQUALS, value));
173    }
174
175    @Override
176    public QueryCondition ne(Object value) {
177        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
178            return QueryCondition.createEmpty();
179        }
180        return ne_(value);
181    }
182
183    @Override
184    public QueryCondition ne(Object value, boolean isEffective) {
185        if (!isEffective) {
186            return QueryCondition.createEmpty();
187        }
188        return ne_(value);
189    }
190
191    @Override
192    public QueryCondition ne(Object value, BooleanSupplier isEffective) {
193        return ne(value, isEffective.getAsBoolean());
194    }
195
196    @Override
197    public <T> QueryCondition ne(T value, Predicate<T> isEffective) {
198        return ne(value, isEffective.test(value));
199    }
200
201
202    QueryCondition gt_(Object value) {
203        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.GT, value));
204    }
205
206    @Override
207    public QueryCondition gt(Object value) {
208        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
209            return QueryCondition.createEmpty();
210        }
211        return gt_(value);
212    }
213
214    @Override
215    public QueryCondition gt(Object value, boolean isEffective) {
216        if (!isEffective) {
217            return QueryCondition.createEmpty();
218        }
219        return gt_(value);
220    }
221
222    @Override
223    public QueryCondition gt(Object value, BooleanSupplier isEffective) {
224        return gt(value, isEffective.getAsBoolean());
225    }
226
227    @Override
228    public <T> QueryCondition gt(T value, Predicate<T> isEffective) {
229        return gt(value, isEffective.test(value));
230    }
231
232
233    QueryCondition ge_(Object value) {
234        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.GE, value));
235    }
236
237    @Override
238    public QueryCondition ge(Object value) {
239        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
240            return QueryCondition.createEmpty();
241        }
242        return ge_(value);
243    }
244
245    @Override
246    public QueryCondition ge(Object value, boolean isEffective) {
247        if (!isEffective) {
248            return QueryCondition.createEmpty();
249        }
250        return ge_(value);
251    }
252
253    @Override
254    public QueryCondition ge(Object value, BooleanSupplier isEffective) {
255        return ge(value, isEffective.getAsBoolean());
256    }
257
258    @Override
259    public <T> QueryCondition ge(T value, Predicate<T> isEffective) {
260        return ge(value, isEffective.test(value));
261    }
262
263
264    QueryCondition lt_(Object value) {
265        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.LT, value));
266    }
267
268    @Override
269    public QueryCondition lt(Object value) {
270        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
271            return QueryCondition.createEmpty();
272        }
273        return lt_(value);
274    }
275
276    @Override
277    public QueryCondition lt(Object value, boolean isEffective) {
278        if (!isEffective) {
279            return QueryCondition.createEmpty();
280        }
281        return lt_(value);
282    }
283
284    @Override
285    public QueryCondition lt(Object value, BooleanSupplier isEffective) {
286        return lt(value, isEffective.getAsBoolean());
287    }
288
289    @Override
290    public <T> QueryCondition lt(T value, Predicate<T> isEffective) {
291        return lt(value, isEffective.test(value));
292    }
293
294
295    QueryCondition le_(Object value) {
296        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.LE, value));
297    }
298
299    @Override
300    public QueryCondition le(Object value) {
301        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
302            return QueryCondition.createEmpty();
303        }
304        return le_(value);
305    }
306
307    @Override
308    public QueryCondition le(Object value, boolean isEffective) {
309        if (!isEffective) {
310            return QueryCondition.createEmpty();
311        }
312        return le_(value);
313    }
314
315    @Override
316    public QueryCondition le(Object value, BooleanSupplier isEffective) {
317        return le(value, isEffective.getAsBoolean());
318    }
319
320    @Override
321    public <T> QueryCondition le(T value, Predicate<T> isEffective) {
322        return le(value, isEffective.test(value));
323    }
324
325
326    QueryCondition in_(Object... value) {
327        // IN 里面只有一个值的情况
328        if (value.length == 1) {
329            if (QueryColumnBehavior.isSmartConvertInToEquals()) {
330                return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.EQUALS, value[0]));
331            }
332        }
333        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlConsts.IN, value));
334    }
335
336
337    @Override
338    public QueryCondition in(Object... value) {
339        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
340            return QueryCondition.createEmpty();
341        }
342        return in_(value);
343    }
344
345    @Override
346    public QueryCondition in(Object[] value, boolean isEffective) {
347        if (!isEffective) {
348            return QueryCondition.createEmpty();
349        }
350        return in_(value);
351    }
352
353    @Override
354    public QueryCondition in(Object[] value, BooleanSupplier isEffective) {
355        return in(value, isEffective.getAsBoolean());
356    }
357
358    @Override
359    public <T> QueryCondition in(T[] value, Predicate<T[]> isEffective) {
360        return in(value, isEffective.test(value));
361    }
362
363    QueryCondition in_(Collection<?> value) {
364        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlConsts.IN, value));
365    }
366
367    @Override
368    public QueryCondition in(Collection<?> value) {
369        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
370            return QueryCondition.createEmpty();
371        }
372        return in_(value);
373    }
374
375    @Override
376    public QueryCondition in(Collection<?> value, boolean isEffective) {
377        if (!isEffective) {
378            return QueryCondition.createEmpty();
379        }
380        return in_(value);
381    }
382
383    @Override
384    public QueryCondition in(Collection<?> value, BooleanSupplier isEffective) {
385        return in(value, isEffective.getAsBoolean());
386    }
387
388    @Override
389    public <T extends Collection<?>> QueryCondition in(T value, Predicate<T> isEffective) {
390        return in(value, isEffective.test(value));
391    }
392
393    QueryCondition in_(QueryWrapper queryWrapper) {
394        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlConsts.IN, queryWrapper));
395    }
396
397    @Override
398    public QueryCondition in(QueryWrapper queryWrapper) {
399        if (QueryColumnBehavior.shouldIgnoreValue(queryWrapper)) {
400            return QueryCondition.createEmpty();
401        }
402        return in_(queryWrapper);
403    }
404
405    @Override
406    public QueryCondition in(QueryWrapper queryWrapper, boolean isEffective) {
407        if (!isEffective) {
408            return QueryCondition.createEmpty();
409        }
410        return in_(queryWrapper);
411    }
412
413    @Override
414    public QueryCondition in(QueryWrapper queryWrapper, BooleanSupplier isEffective) {
415        return in(queryWrapper, isEffective.getAsBoolean());
416    }
417
418    QueryCondition notIn_(Object... value) {
419        // NOT IN 里面只有一个值的情况
420        if (value.length == 1 && QueryColumnBehavior.isSmartConvertInToEquals()) {
421            return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.NOT_EQUALS, value[0]));
422        }
423        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlConsts.NOT_IN, value));
424    }
425
426    @Override
427    public QueryCondition notIn(Object... value) {
428        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
429            return QueryCondition.createEmpty();
430        }
431        return notIn_(value);
432    }
433
434    @Override
435    public QueryCondition notIn(Object[] value, boolean isEffective) {
436        if (!isEffective) {
437            return QueryCondition.createEmpty();
438        }
439        return notIn_(value);
440    }
441
442    @Override
443    public QueryCondition notIn(Object[] value, BooleanSupplier isEffective) {
444        return notIn(value, isEffective.getAsBoolean());
445    }
446
447    @Override
448    public <T> QueryCondition notIn(T[] value, Predicate<T[]> isEffective) {
449        return notIn(value, isEffective.test(value));
450    }
451
452    QueryCondition notIn_(Collection<?> value) {
453        // NOT IN 里面只有一个值的情况
454        if (value.size() == 1 && QueryColumnBehavior.isSmartConvertInToEquals()) {
455            Object next = value.iterator().next();
456            return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.NOT_EQUALS, next));
457        }
458        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlConsts.NOT_IN, value));
459    }
460
461    @Override
462    public QueryCondition notIn(Collection<?> value) {
463        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
464            return QueryCondition.createEmpty();
465        }
466        return notIn_(value);
467    }
468
469    @Override
470    public QueryCondition notIn(Collection<?> value, boolean isEffective) {
471        if (!isEffective) {
472            return QueryCondition.createEmpty();
473        }
474        return notIn_(value);
475    }
476
477    @Override
478    public QueryCondition notIn(Collection<?> value, BooleanSupplier isEffective) {
479        return notIn(value, isEffective.getAsBoolean());
480    }
481
482    @Override
483    public <T extends Collection<?>> QueryCondition notIn(T value, Predicate<T> isEffective) {
484        return notIn(value, isEffective.test(value));
485    }
486
487    QueryCondition notIn_(QueryWrapper queryWrapper) {
488        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlConsts.NOT_IN, queryWrapper));
489    }
490
491    @Override
492    public QueryCondition notIn(QueryWrapper queryWrapper) {
493        if (QueryColumnBehavior.shouldIgnoreValue(queryWrapper)) {
494            return QueryCondition.createEmpty();
495        }
496        return notIn_(queryWrapper);
497    }
498
499    @Override
500    public QueryCondition notIn(QueryWrapper queryWrapper, boolean isEffective) {
501        if (!isEffective) {
502            return QueryCondition.createEmpty();
503        }
504        return notIn_(queryWrapper);
505    }
506
507    @Override
508    public QueryCondition notIn(QueryWrapper queryWrapper, BooleanSupplier isEffective) {
509        return notIn(queryWrapper, isEffective.getAsBoolean());
510    }
511
512    QueryCondition between_(Object[] values) {
513        if (values == null || values.length != 2) {
514            throw new IllegalArgumentException("values is null or length is not 2");
515        }
516        Object start = values[0], end = values[1];
517        return between_(start, end);
518    }
519
520    QueryCondition between_(Object start, Object end) {
521        if (start == null && end == null) {
522            return QueryCondition.createEmpty();
523        }
524
525        boolean smartConvertBetweenToLeOrGe = QueryColumnBehavior.isSmartConvertBetweenToLeOrGe();
526        if ((start == null || end == null) && !smartConvertBetweenToLeOrGe) {
527            return QueryCondition.createEmpty();
528        }
529
530        /* && end != null */
531        if (start == null) {
532            return le_(end);
533        }
534
535        /* && start != null */
536        if (end == null) {
537            return ge_(start);
538        }
539        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlConsts.BETWEEN, new Object[]{start, end}));
540    }
541
542    @Override
543    public QueryCondition between(Object[] values) {
544//        if (QueryColumnBehavior.shouldIgnoreValue(values)) {
545//            return QueryCondition.createEmpty();
546//        }
547        return between_(values);
548    }
549
550    @Override
551    public QueryCondition between(Object[] values, boolean isEffective) {
552        if (!isEffective) {
553            return QueryCondition.createEmpty();
554        }
555        return between_(values);
556    }
557
558    @Override
559    public QueryCondition between(Object start, Object end) {
560//        if (QueryColumnBehavior.shouldIgnoreValue(start) || QueryColumnBehavior.shouldIgnoreValue(end)) {
561//            return QueryCondition.createEmpty();
562//        }
563        return between_(start, end);
564    }
565
566    @Override
567    public QueryCondition between(Object start, Object end, boolean isEffective) {
568        if (!isEffective) {
569            return QueryCondition.createEmpty();
570        }
571        return between_(start, end);
572    }
573
574    @Override
575    public QueryCondition between(Object start, Object end, BooleanSupplier isEffective) {
576        return between(start, end, isEffective.getAsBoolean());
577    }
578
579    @Override
580    public <S, E> QueryCondition between(S start, E end, BiPredicate<S, E> isEffective) {
581        return between(start, end, isEffective.test(start, end));
582    }
583
584    QueryCondition notBetween_(Object[] values) {
585        if (values == null || values.length != 2) {
586            throw new IllegalArgumentException("values is null or length is not 2");
587        }
588
589        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlConsts.NOT_BETWEEN, values));
590    }
591
592    QueryCondition notBetween_(Object start, Object end) {
593        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlConsts.NOT_BETWEEN, new Object[]{start, end}));
594    }
595
596    @Override
597    public QueryCondition notBetween(Object[] values) {
598//        if (QueryColumnBehavior.shouldIgnoreValue(values)) {
599//            return QueryCondition.createEmpty();
600//        }
601        return notBetween_(values);
602    }
603
604    @Override
605    public QueryCondition notBetween(Object[] values, boolean isEffective) {
606        if (!isEffective) {
607            return QueryCondition.createEmpty();
608        }
609        return notBetween_(values);
610    }
611
612    @Override
613    public QueryCondition notBetween(Object start, Object end) {
614//        if (QueryColumnBehavior.shouldIgnoreValue(start) || QueryColumnBehavior.shouldIgnoreValue(end)) {
615//            return QueryCondition.createEmpty();
616//        }
617        return notBetween_(start, end);
618    }
619
620    @Override
621    public QueryCondition notBetween(Object start, Object end, boolean isEffective) {
622        if (!isEffective) {
623            return QueryCondition.createEmpty();
624        }
625        return notBetween_(start, end);
626    }
627
628    @Override
629    public QueryCondition notBetween(Object start, Object end, BooleanSupplier isEffective) {
630        return notBetween(start, end, isEffective.getAsBoolean());
631    }
632
633    @Override
634    public <S, E> QueryCondition notBetween(S start, E end, BiPredicate<S, E> isEffective) {
635        return notBetween(start, end, isEffective.test(start, end));
636    }
637
638    QueryCondition like_(Object value) {
639        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.LIKE, "%" + value + "%"));
640    }
641
642    @Override
643    public QueryCondition like(Object value) {
644        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
645            return QueryCondition.createEmpty();
646        }
647        return like_(value);
648    }
649
650    @Override
651    public QueryCondition like(Object value, boolean isEffective) {
652        if (!isEffective) {
653            return QueryCondition.createEmpty();
654        }
655        return like_(value);
656    }
657
658    @Override
659    public QueryCondition like(Object value, BooleanSupplier isEffective) {
660        return like(value, isEffective.getAsBoolean());
661    }
662
663    @Override
664    public <T> QueryCondition like(T value, Predicate<T> isEffective) {
665        return like(value, isEffective.test(value));
666    }
667
668    QueryCondition likeLeft_(Object value) {
669        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.LIKE, value + "%"));
670    }
671
672    @Override
673    public QueryCondition likeLeft(Object value) {
674        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
675            return QueryCondition.createEmpty();
676        }
677        return likeLeft_(value);
678    }
679
680    @Override
681    public QueryCondition likeLeft(Object value, boolean isEffective) {
682        if (!isEffective) {
683            return QueryCondition.createEmpty();
684        }
685        return likeLeft_(value);
686    }
687
688    @Override
689    public QueryCondition likeLeft(Object value, BooleanSupplier isEffective) {
690        return likeLeft(value, isEffective.getAsBoolean());
691    }
692
693    @Override
694    public <T> QueryCondition likeLeft(T value, Predicate<T> isEffective) {
695        return likeLeft(value, isEffective.test(value));
696    }
697
698    QueryCondition likeRight_(Object value) {
699        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.LIKE, "%" + value));
700    }
701
702    @Override
703    public QueryCondition likeRight(Object value) {
704        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
705            return QueryCondition.createEmpty();
706        }
707        return likeRight_(value);
708    }
709
710    @Override
711    public QueryCondition likeRight(Object value, boolean isEffective) {
712        if (!isEffective) {
713            return QueryCondition.createEmpty();
714        }
715        return likeRight_(value);
716    }
717
718    @Override
719    public QueryCondition likeRight(Object value, BooleanSupplier isEffective) {
720        return likeRight(value, isEffective.getAsBoolean());
721    }
722
723    @Override
724    public <T> QueryCondition likeRight(T value, Predicate<T> isEffective) {
725        return likeRight(value, isEffective.test(value));
726    }
727
728
729    QueryCondition likeRaw_(Object value) {
730        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.LIKE, value));
731    }
732
733
734    /**
735     * {@code LIKE value}
736     */
737    public QueryCondition likeRaw(Object value) {
738        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
739            return QueryCondition.createEmpty();
740        }
741        return likeRaw_(value);
742    }
743
744    /**
745     * {@code LIKE value}
746     */
747    public QueryCondition likeRaw(Object value, boolean isEffective) {
748        if (!isEffective) {
749            return QueryCondition.createEmpty();
750        }
751        return likeRaw_(value);
752    }
753
754    /**
755     * {@code LIKE value}
756     */
757    public QueryCondition likeRaw(Object value, BooleanSupplier isEffective) {
758        return likeRaw(value, isEffective.getAsBoolean());
759    }
760
761    /**
762     * {@code LIKE value}
763     */
764    public <T> QueryCondition likeRaw(T value, Predicate<T> isEffective) {
765        return likeRaw(value, isEffective.test(value));
766    }
767
768    QueryCondition notLike_(Object value) {
769        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.NOT_LIKE, "%" + value + "%"));
770    }
771
772    @Override
773    public QueryCondition notLike(Object value) {
774        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
775            return QueryCondition.createEmpty();
776        }
777        return notLike_(value);
778    }
779
780    @Override
781    public QueryCondition notLike(Object value, boolean isEffective) {
782        if (!isEffective) {
783            return QueryCondition.createEmpty();
784        }
785        return notLike_(value);
786    }
787
788    @Override
789    public QueryCondition notLike(Object value, BooleanSupplier isEffective) {
790        return notLike(value, isEffective.getAsBoolean());
791    }
792
793    @Override
794    public <T> QueryCondition notLike(T value, Predicate<T> isEffective) {
795        return notLike(value, isEffective.test(value));
796    }
797
798    QueryCondition notLikeLeft_(Object value) {
799        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.NOT_LIKE, value + "%"));
800    }
801
802    @Override
803    public QueryCondition notLikeLeft(Object value) {
804        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
805            return QueryCondition.createEmpty();
806        }
807        return notLikeLeft_(value);
808    }
809
810    @Override
811    public QueryCondition notLikeLeft(Object value, boolean isEffective) {
812        if (!isEffective) {
813            return QueryCondition.createEmpty();
814        }
815        return notLikeLeft_(value);
816    }
817
818    @Override
819    public QueryCondition notLikeLeft(Object value, BooleanSupplier isEffective) {
820        return notLikeLeft(value, isEffective.getAsBoolean());
821    }
822
823    @Override
824    public <T> QueryCondition notLikeLeft(T value, Predicate<T> isEffective) {
825        return notLikeLeft(value, isEffective.test(value));
826    }
827
828    QueryCondition notLikeRight_(Object value) {
829        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.NOT_LIKE, "%" + value));
830    }
831
832    @Override
833    public QueryCondition notLikeRight(Object value) {
834        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
835            return QueryCondition.createEmpty();
836        }
837        return notLikeRight_(value);
838    }
839
840    @Override
841    public QueryCondition notLikeRight(Object value, boolean isEffective) {
842        if (!isEffective) {
843            return QueryCondition.createEmpty();
844        }
845        return notLikeRight_(value);
846    }
847
848    @Override
849    public QueryCondition notLikeRight(Object value, BooleanSupplier isEffective) {
850        return notLikeRight(value, isEffective.getAsBoolean());
851    }
852
853    @Override
854    public <T> QueryCondition notLikeRight(T value, Predicate<T> isEffective) {
855        return notLikeRight(value, isEffective.test(value));
856    }
857
858
859    QueryCondition notLikeRaw_(Object value) {
860        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.NOT_LIKE, value));
861    }
862
863    /**
864     * {@code NOT LIKE value}
865     */
866    public QueryCondition notLikeRaw(Object value) {
867        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
868            return QueryCondition.createEmpty();
869        }
870        return notLikeRaw_(value);
871    }
872
873    /**
874     * {@code NOT LIKE value}
875     */
876    public QueryCondition notLikeRaw(Object value, boolean isEffective) {
877        if (!isEffective) {
878            return QueryCondition.createEmpty();
879        }
880        return notLikeRaw_(value);
881    }
882
883    /**
884     * {@code NOT LIKE value}
885     */
886    public QueryCondition notLikeRaw(Object value, BooleanSupplier isEffective) {
887        return notLikeRaw(value, isEffective.getAsBoolean());
888    }
889
890    /**
891     * {@code NOT LIKE value}
892     */
893    public <T> QueryCondition notLikeRaw(T value, Predicate<T> isEffective) {
894        return notLikeRaw(value, isEffective.test(value));
895    }
896
897    @Override
898    public QueryCondition isNull(boolean isEffective) {
899        if (!isEffective) {
900            return QueryCondition.createEmpty();
901        }
902        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.IS_NULL, null));
903    }
904
905    @Override
906    public QueryCondition isNotNull(boolean isEffective) {
907        if (!isEffective) {
908            return QueryCondition.createEmpty();
909        }
910        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.IS_NOT_NULL, null));
911    }
912
913
914    /// /order by ////
915    public QueryOrderBy asc() {
916        return new QueryOrderBy(this, SqlConsts.ASC);
917    }
918
919
920    public QueryOrderBy desc() {
921        return new QueryOrderBy(this, SqlConsts.DESC);
922    }
923
924
925    // 运算 加减乘除 + - * /
926    public QueryColumn add(QueryColumn queryColumn) {
927        return new ArithmeticQueryColumn(this).add(queryColumn);
928    }
929
930    public QueryColumn add(Number number) {
931        return new ArithmeticQueryColumn(this).add(number);
932    }
933
934    public QueryColumn subtract(QueryColumn queryColumn) {
935        return new ArithmeticQueryColumn(this).subtract(queryColumn);
936    }
937
938    public QueryColumn subtract(Number number) {
939        return new ArithmeticQueryColumn(this).subtract(number);
940    }
941
942    public QueryColumn multiply(QueryColumn queryColumn) {
943        return new ArithmeticQueryColumn(this).multiply(queryColumn);
944    }
945
946    public QueryColumn multiply(Number number) {
947        return new ArithmeticQueryColumn(this).multiply(number);
948    }
949
950    public QueryColumn divide(QueryColumn queryColumn) {
951        return new ArithmeticQueryColumn(this).divide(queryColumn);
952    }
953
954    public QueryColumn divide(Number number) {
955        return new ArithmeticQueryColumn(this).divide(number);
956    }
957
958    /**
959     * 生成列用于构建查询条件的 SQL 语句。
960     *
961     * @param queryTables 查询表
962     * @param dialect     方言
963     * @return SQL 语句
964     */
965    protected String toConditionSql(List<QueryTable> queryTables, IDialect dialect) {
966        QueryTable selectTable = getSelectTable(queryTables, table);
967        if (selectTable == null) {
968            return dialect.wrap(name);
969        } else {
970            if (StringUtil.hasText(selectTable.alias)) {
971                return dialect.wrap(selectTable.alias) + SqlConsts.REFERENCE + dialect.wrap(name);
972            } else if (StringUtil.hasText(selectTable.getSchema()) && StringUtil.hasText(selectTable.getName())) {
973                String realTable = dialect.getRealTable(selectTable.getName(), OperateType.SELECT);
974                return dialect.wrap(dialect.getRealSchema(selectTable.schema, realTable, OperateType.SELECT)) + SqlConsts.REFERENCE + dialect.wrap(realTable)
975                    + SqlConsts.REFERENCE + dialect.wrap(name);
976            } else if (StringUtil.hasText(selectTable.getName())) {
977                return dialect.wrap(dialect.getRealTable(selectTable.getName(), OperateType.SELECT)) + SqlConsts.REFERENCE + dialect.wrap(name);
978            } else {
979                return dialect.wrap(name);
980            }
981        }
982    }
983
984    /**
985     * 生成列用于构建查询列的 SQL 语句。
986     *
987     * @param queryTables 查询表
988     * @param dialect     方言
989     * @return SQL 语句
990     */
991    protected String toSelectSql(List<QueryTable> queryTables, IDialect dialect) {
992        return toConditionSql(queryTables, dialect) + WrapperUtil.buildColumnAlias(alias, dialect);
993    }
994
995    QueryTable getSelectTable(List<QueryTable> queryTables, QueryTable selfTable) {
996        // 未查询任何表,或查询表仅有一个
997        // 可以省略表的引用,直接使用列名
998        // SELECT 1
999        // SELECT id FROM tb_user
1000        if (queryTables == null || queryTables.isEmpty()) {
1001            return null;
1002        }
1003
1004        QueryTable consideredTable = queryTables.get(0);
1005
1006        // 列未指定表名,仅以字符串的形式输入列名
1007        // 以查询表中的第一个表为主
1008        // SELECT tb_user.id FROM tb_user
1009        if (selfTable == null) {
1010            return consideredTable;
1011        }
1012
1013        // 当前表有别名,以别名为主
1014        // SELECT u.id FROM tb_user u
1015        if (StringUtil.hasText(selfTable.alias)) {
1016            return selfTable;
1017        }
1018
1019        // 当前表没有别名,查询表只有一个
1020        // 如果两个表是一样的则可以忽略表的引用
1021        // 兼容子查询时,子查询的查询表和父查询没有合并的问题
1022        if (queryTables.size() == 1 && Objects.equals(selfTable.name, consideredTable.name)) {
1023            return null;
1024        }
1025
1026        consideredTable = selfTable;
1027
1028        // 当前表存在且没有别名
1029        ListIterator<QueryTable> it = queryTables.listIterator(queryTables.size());
1030
1031        while (it.hasPrevious()) {
1032            QueryTable queryTable = it.previous();
1033            if (Objects.equals(queryTable.name, selfTable.name)) {
1034                if (StringUtil.noText(queryTable.alias)) {
1035                    // 因为当前表没有别名,所以表名相同有没有别名,一定是这个表
1036                    return queryTable;
1037                } else {
1038                    // 只是表名相同,但是查询表有别名,当前表没有别名
1039                    // 考虑这个表,但是继续寻找,是否有未设置别名的表
1040                    consideredTable = queryTable;
1041                }
1042            }
1043        }
1044
1045        return consideredTable;
1046    }
1047
1048
1049    @Override
1050    public String toString() {
1051        return "QueryColumn{" +
1052            "table=" + table +
1053            ", name='" + name + '\'' +
1054            ", alias='" + alias + '\'' +
1055            '}';
1056    }
1057
1058
1059    @Override
1060    public QueryColumn clone() {
1061        try {
1062            QueryColumn clone = (QueryColumn) super.clone();
1063            // deep clone ...
1064            clone.table = ObjectUtil.clone(this.table);
1065            return clone;
1066        } catch (CloneNotSupportedException e) {
1067            throw FlexExceptions.wrap(e);
1068        }
1069    }
1070
1071}