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
517        if (values == null || values.length == 0) {
518            return QueryCondition.createEmpty();
519        }
520
521
522        Object start = values[0], end = values.length > 1 ? values[1] : null;
523        return between_(start, end);
524    }
525
526    QueryCondition between_(Object start, Object end) {
527        if (start == null && end == null) {
528            return QueryCondition.createEmpty();
529        }
530
531        boolean smartConvertBetweenToLeOrGe = QueryColumnBehavior.isSmartConvertBetweenToLeOrGe();
532        if ((start == null || end == null) && !smartConvertBetweenToLeOrGe) {
533            return QueryCondition.createEmpty();
534        }
535
536        /* && end != null */
537        if (start == null) {
538            return le_(end);
539        }
540
541        /* && start != null */
542        if (end == null) {
543            return ge_(start);
544        }
545        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlConsts.BETWEEN, new Object[]{start, end}));
546    }
547
548    @Override
549    public QueryCondition between(Object[] values) {
550//        if (QueryColumnBehavior.shouldIgnoreValue(values)) {
551//            return QueryCondition.createEmpty();
552//        }
553        return between_(values);
554    }
555
556    @Override
557    public QueryCondition between(Object[] values, boolean isEffective) {
558        if (!isEffective) {
559            return QueryCondition.createEmpty();
560        }
561        return between_(values);
562    }
563
564    @Override
565    public QueryCondition between(Object start, Object end) {
566//        if (QueryColumnBehavior.shouldIgnoreValue(start) || QueryColumnBehavior.shouldIgnoreValue(end)) {
567//            return QueryCondition.createEmpty();
568//        }
569        return between_(start, end);
570    }
571
572    @Override
573    public QueryCondition between(Object start, Object end, boolean isEffective) {
574        if (!isEffective) {
575            return QueryCondition.createEmpty();
576        }
577        return between_(start, end);
578    }
579
580    @Override
581    public QueryCondition between(Object start, Object end, BooleanSupplier isEffective) {
582        return between(start, end, isEffective.getAsBoolean());
583    }
584
585    @Override
586    public <S, E> QueryCondition between(S start, E end, BiPredicate<S, E> isEffective) {
587        return between(start, end, isEffective.test(start, end));
588    }
589
590    QueryCondition notBetween_(Object[] values) {
591        if (values == null || values.length != 2) {
592            throw new IllegalArgumentException("values is null or length is not 2");
593        }
594
595        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlConsts.NOT_BETWEEN, values));
596    }
597
598    QueryCondition notBetween_(Object start, Object end) {
599        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlConsts.NOT_BETWEEN, new Object[]{start, end}));
600    }
601
602    @Override
603    public QueryCondition notBetween(Object[] values) {
604//        if (QueryColumnBehavior.shouldIgnoreValue(values)) {
605//            return QueryCondition.createEmpty();
606//        }
607        return notBetween_(values);
608    }
609
610    @Override
611    public QueryCondition notBetween(Object[] values, boolean isEffective) {
612        if (!isEffective) {
613            return QueryCondition.createEmpty();
614        }
615        return notBetween_(values);
616    }
617
618    @Override
619    public QueryCondition notBetween(Object start, Object end) {
620//        if (QueryColumnBehavior.shouldIgnoreValue(start) || QueryColumnBehavior.shouldIgnoreValue(end)) {
621//            return QueryCondition.createEmpty();
622//        }
623        return notBetween_(start, end);
624    }
625
626    @Override
627    public QueryCondition notBetween(Object start, Object end, boolean isEffective) {
628        if (!isEffective) {
629            return QueryCondition.createEmpty();
630        }
631        return notBetween_(start, end);
632    }
633
634    @Override
635    public QueryCondition notBetween(Object start, Object end, BooleanSupplier isEffective) {
636        return notBetween(start, end, isEffective.getAsBoolean());
637    }
638
639    @Override
640    public <S, E> QueryCondition notBetween(S start, E end, BiPredicate<S, E> isEffective) {
641        return notBetween(start, end, isEffective.test(start, end));
642    }
643
644    QueryCondition like_(Object value) {
645        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.LIKE, "%" + value + "%"));
646    }
647
648    @Override
649    public QueryCondition like(Object value) {
650        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
651            return QueryCondition.createEmpty();
652        }
653        return like_(value);
654    }
655
656    @Override
657    public QueryCondition like(Object value, boolean isEffective) {
658        if (!isEffective) {
659            return QueryCondition.createEmpty();
660        }
661        return like_(value);
662    }
663
664    @Override
665    public QueryCondition like(Object value, BooleanSupplier isEffective) {
666        return like(value, isEffective.getAsBoolean());
667    }
668
669    @Override
670    public <T> QueryCondition like(T value, Predicate<T> isEffective) {
671        return like(value, isEffective.test(value));
672    }
673
674    QueryCondition likeLeft_(Object value) {
675        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.LIKE, value + "%"));
676    }
677
678    @Override
679    public QueryCondition likeLeft(Object value) {
680        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
681            return QueryCondition.createEmpty();
682        }
683        return likeLeft_(value);
684    }
685
686    @Override
687    public QueryCondition likeLeft(Object value, boolean isEffective) {
688        if (!isEffective) {
689            return QueryCondition.createEmpty();
690        }
691        return likeLeft_(value);
692    }
693
694    @Override
695    public QueryCondition likeLeft(Object value, BooleanSupplier isEffective) {
696        return likeLeft(value, isEffective.getAsBoolean());
697    }
698
699    @Override
700    public <T> QueryCondition likeLeft(T value, Predicate<T> isEffective) {
701        return likeLeft(value, isEffective.test(value));
702    }
703
704    QueryCondition likeRight_(Object value) {
705        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.LIKE, "%" + value));
706    }
707
708    @Override
709    public QueryCondition likeRight(Object value) {
710        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
711            return QueryCondition.createEmpty();
712        }
713        return likeRight_(value);
714    }
715
716    @Override
717    public QueryCondition likeRight(Object value, boolean isEffective) {
718        if (!isEffective) {
719            return QueryCondition.createEmpty();
720        }
721        return likeRight_(value);
722    }
723
724    @Override
725    public QueryCondition likeRight(Object value, BooleanSupplier isEffective) {
726        return likeRight(value, isEffective.getAsBoolean());
727    }
728
729    @Override
730    public <T> QueryCondition likeRight(T value, Predicate<T> isEffective) {
731        return likeRight(value, isEffective.test(value));
732    }
733
734
735    QueryCondition likeRaw_(Object value) {
736        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.LIKE, value));
737    }
738
739
740    /**
741     * {@code LIKE value}
742     */
743    public QueryCondition likeRaw(Object value) {
744        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
745            return QueryCondition.createEmpty();
746        }
747        return likeRaw_(value);
748    }
749
750    /**
751     * {@code LIKE value}
752     */
753    public QueryCondition likeRaw(Object value, boolean isEffective) {
754        if (!isEffective) {
755            return QueryCondition.createEmpty();
756        }
757        return likeRaw_(value);
758    }
759
760    /**
761     * {@code LIKE value}
762     */
763    public QueryCondition likeRaw(Object value, BooleanSupplier isEffective) {
764        return likeRaw(value, isEffective.getAsBoolean());
765    }
766
767    /**
768     * {@code LIKE value}
769     */
770    public <T> QueryCondition likeRaw(T value, Predicate<T> isEffective) {
771        return likeRaw(value, isEffective.test(value));
772    }
773
774    QueryCondition notLike_(Object value) {
775        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.NOT_LIKE, "%" + value + "%"));
776    }
777
778    @Override
779    public QueryCondition notLike(Object value) {
780        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
781            return QueryCondition.createEmpty();
782        }
783        return notLike_(value);
784    }
785
786    @Override
787    public QueryCondition notLike(Object value, boolean isEffective) {
788        if (!isEffective) {
789            return QueryCondition.createEmpty();
790        }
791        return notLike_(value);
792    }
793
794    @Override
795    public QueryCondition notLike(Object value, BooleanSupplier isEffective) {
796        return notLike(value, isEffective.getAsBoolean());
797    }
798
799    @Override
800    public <T> QueryCondition notLike(T value, Predicate<T> isEffective) {
801        return notLike(value, isEffective.test(value));
802    }
803
804    QueryCondition notLikeLeft_(Object value) {
805        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.NOT_LIKE, value + "%"));
806    }
807
808    @Override
809    public QueryCondition notLikeLeft(Object value) {
810        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
811            return QueryCondition.createEmpty();
812        }
813        return notLikeLeft_(value);
814    }
815
816    @Override
817    public QueryCondition notLikeLeft(Object value, boolean isEffective) {
818        if (!isEffective) {
819            return QueryCondition.createEmpty();
820        }
821        return notLikeLeft_(value);
822    }
823
824    @Override
825    public QueryCondition notLikeLeft(Object value, BooleanSupplier isEffective) {
826        return notLikeLeft(value, isEffective.getAsBoolean());
827    }
828
829    @Override
830    public <T> QueryCondition notLikeLeft(T value, Predicate<T> isEffective) {
831        return notLikeLeft(value, isEffective.test(value));
832    }
833
834    QueryCondition notLikeRight_(Object value) {
835        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.NOT_LIKE, "%" + value));
836    }
837
838    @Override
839    public QueryCondition notLikeRight(Object value) {
840        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
841            return QueryCondition.createEmpty();
842        }
843        return notLikeRight_(value);
844    }
845
846    @Override
847    public QueryCondition notLikeRight(Object value, boolean isEffective) {
848        if (!isEffective) {
849            return QueryCondition.createEmpty();
850        }
851        return notLikeRight_(value);
852    }
853
854    @Override
855    public QueryCondition notLikeRight(Object value, BooleanSupplier isEffective) {
856        return notLikeRight(value, isEffective.getAsBoolean());
857    }
858
859    @Override
860    public <T> QueryCondition notLikeRight(T value, Predicate<T> isEffective) {
861        return notLikeRight(value, isEffective.test(value));
862    }
863
864
865    QueryCondition notLikeRaw_(Object value) {
866        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.NOT_LIKE, value));
867    }
868
869    /**
870     * {@code NOT LIKE value}
871     */
872    public QueryCondition notLikeRaw(Object value) {
873        if (QueryColumnBehavior.shouldIgnoreValue(value)) {
874            return QueryCondition.createEmpty();
875        }
876        return notLikeRaw_(value);
877    }
878
879    /**
880     * {@code NOT LIKE value}
881     */
882    public QueryCondition notLikeRaw(Object value, boolean isEffective) {
883        if (!isEffective) {
884            return QueryCondition.createEmpty();
885        }
886        return notLikeRaw_(value);
887    }
888
889    /**
890     * {@code NOT LIKE value}
891     */
892    public QueryCondition notLikeRaw(Object value, BooleanSupplier isEffective) {
893        return notLikeRaw(value, isEffective.getAsBoolean());
894    }
895
896    /**
897     * {@code NOT LIKE value}
898     */
899    public <T> QueryCondition notLikeRaw(T value, Predicate<T> isEffective) {
900        return notLikeRaw(value, isEffective.test(value));
901    }
902
903    @Override
904    public QueryCondition isNull(boolean isEffective) {
905        if (!isEffective) {
906            return QueryCondition.createEmpty();
907        }
908        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.IS_NULL, null));
909    }
910
911    @Override
912    public QueryCondition isNotNull(boolean isEffective) {
913        if (!isEffective) {
914            return QueryCondition.createEmpty();
915        }
916        return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlOperator.IS_NOT_NULL, null));
917    }
918
919
920    /// /order by ////
921    public QueryOrderBy asc() {
922        return new QueryOrderBy(this, SqlConsts.ASC);
923    }
924
925
926    public QueryOrderBy desc() {
927        return new QueryOrderBy(this, SqlConsts.DESC);
928    }
929
930
931    // 运算 加减乘除 + - * /
932    public QueryColumn add(QueryColumn queryColumn) {
933        return new ArithmeticQueryColumn(this).add(queryColumn);
934    }
935
936    public QueryColumn add(Number number) {
937        return new ArithmeticQueryColumn(this).add(number);
938    }
939
940    public QueryColumn subtract(QueryColumn queryColumn) {
941        return new ArithmeticQueryColumn(this).subtract(queryColumn);
942    }
943
944    public QueryColumn subtract(Number number) {
945        return new ArithmeticQueryColumn(this).subtract(number);
946    }
947
948    public QueryColumn multiply(QueryColumn queryColumn) {
949        return new ArithmeticQueryColumn(this).multiply(queryColumn);
950    }
951
952    public QueryColumn multiply(Number number) {
953        return new ArithmeticQueryColumn(this).multiply(number);
954    }
955
956    public QueryColumn divide(QueryColumn queryColumn) {
957        return new ArithmeticQueryColumn(this).divide(queryColumn);
958    }
959
960    public QueryColumn divide(Number number) {
961        return new ArithmeticQueryColumn(this).divide(number);
962    }
963
964    public QueryColumn cast(String dataType) {
965        return new CastQueryColumn(this, dataType);
966    }
967
968    /**
969     * 生成列用于构建查询条件的 SQL 语句。
970     *
971     * @param queryTables 查询表
972     * @param dialect     方言
973     * @return SQL 语句
974     */
975    protected String toConditionSql(List<QueryTable> queryTables, IDialect dialect) {
976        QueryTable selectTable = getSelectTable(queryTables, table);
977        if (selectTable == null) {
978            return dialect.wrap(name);
979        } else {
980            if (StringUtil.hasText(selectTable.alias)) {
981                return dialect.wrap(selectTable.alias) + SqlConsts.REFERENCE + dialect.wrap(name);
982            } else if (StringUtil.hasText(selectTable.getSchema()) && StringUtil.hasText(selectTable.getName())) {
983                String realTable = dialect.getRealTable(selectTable.getName(), OperateType.SELECT);
984                return dialect.wrap(dialect.getRealSchema(selectTable.schema, realTable, OperateType.SELECT)) + SqlConsts.REFERENCE + dialect.wrap(realTable)
985                    + SqlConsts.REFERENCE + dialect.wrap(name);
986            } else if (StringUtil.hasText(selectTable.getName())) {
987                return dialect.wrap(dialect.getRealTable(selectTable.getName(), OperateType.SELECT)) + SqlConsts.REFERENCE + dialect.wrap(name);
988            } else {
989                return dialect.wrap(name);
990            }
991        }
992    }
993
994    /**
995     * 生成列用于构建查询列的 SQL 语句。
996     *
997     * @param queryTables 查询表
998     * @param dialect     方言
999     * @return SQL 语句
1000     */
1001    protected String toSelectSql(List<QueryTable> queryTables, IDialect dialect) {
1002        return toConditionSql(queryTables, dialect) + WrapperUtil.buildColumnAlias(alias, dialect);
1003    }
1004
1005    QueryTable getSelectTable(List<QueryTable> queryTables, QueryTable selfTable) {
1006        // 未查询任何表,或查询表仅有一个
1007        // 可以省略表的引用,直接使用列名
1008        // SELECT 1
1009        // SELECT id FROM tb_user
1010        if (queryTables == null || queryTables.isEmpty()) {
1011            return null;
1012        }
1013
1014        QueryTable consideredTable = queryTables.get(0);
1015
1016        // 列未指定表名,仅以字符串的形式输入列名
1017        // 以查询表中的第一个表为主
1018        // SELECT tb_user.id FROM tb_user
1019        if (selfTable == null) {
1020            return consideredTable;
1021        }
1022
1023        // 当前表有别名,以别名为主
1024        // SELECT u.id FROM tb_user u
1025        if (StringUtil.hasText(selfTable.alias)) {
1026            return selfTable;
1027        }
1028
1029        // 当前表没有别名,查询表只有一个
1030        // 如果两个表是一样的则可以忽略表的引用
1031        // 兼容子查询时,子查询的查询表和父查询没有合并的问题
1032        if (queryTables.size() == 1 && Objects.equals(selfTable.name, consideredTable.name)) {
1033            return null;
1034        }
1035
1036        consideredTable = selfTable;
1037
1038        // 当前表存在且没有别名
1039        ListIterator<QueryTable> it = queryTables.listIterator(queryTables.size());
1040
1041        while (it.hasPrevious()) {
1042            QueryTable queryTable = it.previous();
1043            if (Objects.equals(queryTable.name, selfTable.name)) {
1044                if (StringUtil.noText(queryTable.alias)) {
1045                    // 因为当前表没有别名,所以表名相同有没有别名,一定是这个表
1046                    return queryTable;
1047                } else {
1048                    // 只是表名相同,但是查询表有别名,当前表没有别名
1049                    // 考虑这个表,但是继续寻找,是否有未设置别名的表
1050                    consideredTable = queryTable;
1051                }
1052            }
1053        }
1054
1055        return consideredTable;
1056    }
1057
1058
1059    @Override
1060    public String toString() {
1061        return "QueryColumn{" +
1062            "table=" + table +
1063            ", name='" + name + '\'' +
1064            ", alias='" + alias + '\'' +
1065            '}';
1066    }
1067
1068
1069    @Override
1070    public QueryColumn clone() {
1071        try {
1072            QueryColumn clone = (QueryColumn) super.clone();
1073            // deep clone ...
1074            clone.table = ObjectUtil.clone(this.table);
1075            return clone;
1076        } catch (CloneNotSupportedException e) {
1077            throw FlexExceptions.wrap(e);
1078        }
1079    }
1080
1081}