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