001/*
002 *  Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
003 *  <p>
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *  <p>
008 *  http://www.apache.org/licenses/LICENSE-2.0
009 *  <p>
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package com.mybatisflex.core.query;
017
018import com.mybatisflex.core.FlexConsts;
019import com.mybatisflex.core.constant.SqlConsts;
020import com.mybatisflex.core.dialect.DialectFactory;
021import com.mybatisflex.core.table.TableDef;
022import com.mybatisflex.core.table.TableInfo;
023import com.mybatisflex.core.table.TableInfoFactory;
024import com.mybatisflex.core.util.*;
025
026import java.util.*;
027import java.util.function.Consumer;
028
029public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
030
031    public static QueryWrapper create() {
032        return new QueryWrapper();
033    }
034
035
036    /**
037     * 根据实体类对象,构建查询条件
038     *
039     * @param entity 实体类对象
040     * @return 查询对象
041     */
042    public static QueryWrapper create(Object entity) {
043        TableInfo tableInfo = TableInfoFactory.ofEntityClass(ClassUtil.getUsefulClass(entity.getClass()));
044        return tableInfo.buildQueryWrapper(entity);
045    }
046
047
048    public WithBuilder with(String name) {
049        if (with == null) {
050            with = new With();
051        }
052        return new WithBuilder(this, with, name);
053    }
054
055    public WithBuilder with(String name, String... params) {
056        if (with == null) {
057            with = new With();
058        }
059        return new WithBuilder(this, with, name, Arrays.asList(params));
060    }
061
062    public WithBuilder withRecursive(String name) {
063        if (with == null) {
064            with = new With(true);
065        }
066        return new WithBuilder(this, with, name);
067    }
068
069    public WithBuilder withRecursive(String name, String... params) {
070        if (with == null) {
071            with = new With(true);
072        }
073        return new WithBuilder(this, with, name, Arrays.asList(params));
074    }
075
076    public QueryWrapper select() {
077        return this;
078    }
079
080    public QueryWrapper select(String... columns) {
081        for (String column : columns) {
082            addSelectColumn(new StringQueryColumn(column));
083        }
084        return this;
085    }
086
087    public <T> QueryWrapper select(LambdaGetter<T>... lambdaGetters) {
088        for (LambdaGetter<T> lambdaGetter : lambdaGetters) {
089            QueryColumn queryColumn = LambdaUtil.getQueryColumn(lambdaGetter);
090            addSelectColumn(queryColumn);
091        }
092        return this;
093    }
094
095    public QueryWrapper select(QueryColumn... queryColumns) {
096        for (QueryColumn column : queryColumns) {
097            if (column != null) {
098                addSelectColumn(column);
099            }
100        }
101        return this;
102    }
103
104    public QueryWrapper select(QueryColumn[]... queryColumns) {
105        for (QueryColumn[] columnArray : queryColumns) {
106            if (columnArray != null) {
107                for (QueryColumn column : columnArray) {
108                    if (column != null) {
109                        addSelectColumn(column);
110                    }
111                }
112            }
113        }
114        return this;
115    }
116
117    public QueryWrapper from(TableDef... tableDefs) {
118        for (TableDef tableDef : tableDefs) {
119            from(new QueryTable(tableDef));
120        }
121        return this;
122    }
123
124    public QueryWrapper from(Class<?>... entityClasses) {
125        for (Class<?> entityClass : entityClasses) {
126            TableInfo tableInfo = TableInfoFactory.ofEntityClass(entityClass);
127            from(new QueryTable(tableInfo.getSchema(), tableInfo.getTableName()));
128        }
129        return this;
130    }
131
132    public QueryWrapper from(String... tables) {
133        for (String table : tables) {
134            if (StringUtil.isBlank(table)) {
135                throw new IllegalArgumentException("table must not be null or blank.");
136            }
137            from(new QueryTable(table));
138        }
139        return this;
140    }
141
142    public QueryWrapper from(QueryTable... tables) {
143        if (CollectionUtil.isEmpty(queryTables)) {
144            queryTables = new ArrayList<>();
145            queryTables.addAll(Arrays.asList(tables));
146        } else {
147            for (QueryTable table : tables) {
148                boolean contains = false;
149                for (QueryTable queryTable : queryTables) {
150                    if (queryTable.isSameTable(table)) {
151                        contains = true;
152                    }
153                }
154                if (!contains) {
155                    queryTables.add(table);
156                }
157            }
158        }
159        return this;
160    }
161
162    public QueryWrapper from(QueryWrapper queryWrapper) {
163        return from(new SelectQueryTable(queryWrapper));
164    }
165
166    public QueryWrapper as(String alias) {
167        if (CollectionUtil.isEmpty(queryTables)) {
168            throw new IllegalArgumentException("query table must not be empty.");
169        }
170
171        queryTables.get(queryTables.size() - 1).alias = alias;
172        return this;
173    }
174
175    public QueryWrapper where(QueryCondition queryCondition) {
176        this.setWhereQueryCondition(queryCondition);
177        return this;
178    }
179
180    public QueryWrapper where(String sql) {
181        this.setWhereQueryCondition(new RawFragment(sql));
182        return this;
183    }
184
185    public QueryWrapper where(String sql, Object... params) {
186        this.setWhereQueryCondition(new RawFragment(sql, params));
187        return this;
188    }
189
190    public QueryWrapper where(Map<String, Object> whereConditions) {
191        if (whereConditions != null) {
192            whereConditions.forEach((s, o) -> and(QueryCondition.create(new QueryColumn(s), o)));
193        }
194        return this;
195    }
196
197    public <T> QueryConditionBuilder where(LambdaGetter<T> fn) {
198        return new QueryConditionBuilder(this, LambdaUtil.getQueryColumn(fn), SqlConnector.AND);
199    }
200
201    public QueryWrapper and(QueryCondition queryCondition) {
202        return addWhereQueryCondition(queryCondition, SqlConnector.AND);
203    }
204
205    public QueryWrapper and(String sql) {
206        this.addWhereQueryCondition(new RawFragment(sql), SqlConnector.AND);
207        return this;
208    }
209
210    public QueryWrapper and(String sql, Object... params) {
211        this.addWhereQueryCondition(new RawFragment(sql, params), SqlConnector.AND);
212        return this;
213    }
214
215    public <T> QueryConditionBuilder and(LambdaGetter<T> fn) {
216        return new QueryConditionBuilder(this, LambdaUtil.getQueryColumn(fn), SqlConnector.AND);
217    }
218
219    public QueryWrapper and(Consumer<QueryWrapper> consumer) {
220        QueryWrapper newWrapper = new QueryWrapper();
221        consumer.accept(newWrapper);
222        QueryCondition whereQueryCondition = newWrapper.whereQueryCondition;
223        if (whereQueryCondition != null) {
224            and(new Brackets(whereQueryCondition));
225        }
226        return this;
227    }
228
229    public QueryWrapper or(QueryCondition queryCondition) {
230        return addWhereQueryCondition(queryCondition, SqlConnector.OR);
231    }
232
233    public QueryWrapper or(String sql) {
234        this.addWhereQueryCondition(new RawFragment(sql), SqlConnector.OR);
235        return this;
236    }
237
238    public QueryWrapper or(String sql, Object... params) {
239        this.addWhereQueryCondition(new RawFragment(sql, params), SqlConnector.OR);
240        return this;
241    }
242
243    public <T> QueryConditionBuilder or(LambdaGetter<T> fn) {
244        return new QueryConditionBuilder(this, LambdaUtil.getQueryColumn(fn), SqlConnector.OR);
245    }
246
247    public QueryWrapper or(Consumer<QueryWrapper> consumer) {
248        QueryWrapper newWrapper = new QueryWrapper();
249        consumer.accept(newWrapper);
250        QueryCondition whereQueryCondition = newWrapper.whereQueryCondition;
251        if (whereQueryCondition != null) {
252            or(new Brackets(whereQueryCondition));
253        }
254        return this;
255    }
256
257    public Joiner<QueryWrapper> leftJoin(String table) {
258        return joining(SqlConsts.LEFT_JOIN, new QueryTable(table), true);
259    }
260
261    public Joiner<QueryWrapper> leftJoin(String table, boolean when) {
262        return joining(SqlConsts.LEFT_JOIN, new QueryTable(table), when);
263    }
264
265    public Joiner<QueryWrapper> leftJoin(Class<?> entityClass) {
266        return joining(SqlConsts.LEFT_JOIN, entityClass, true);
267    }
268
269    public Joiner<QueryWrapper> leftJoin(Class<?> entityClass, boolean when) {
270        return joining(SqlConsts.LEFT_JOIN, entityClass, when);
271    }
272
273    public Joiner<QueryWrapper> leftJoin(TableDef table) {
274        return joining(SqlConsts.LEFT_JOIN, new QueryTable(table), true);
275    }
276
277    public Joiner<QueryWrapper> leftJoin(TableDef table, boolean when) {
278        return joining(SqlConsts.LEFT_JOIN, new QueryTable(table), when);
279    }
280
281    public Joiner<QueryWrapper> leftJoin(QueryWrapper table) {
282        return joining(SqlConsts.LEFT_JOIN, table, true);
283    }
284
285    public Joiner<QueryWrapper> leftJoin(QueryWrapper table, boolean when) {
286        return joining(SqlConsts.LEFT_JOIN, table, when);
287    }
288
289    public Joiner<QueryWrapper> rightJoin(String table) {
290        return joining(SqlConsts.RIGHT_JOIN, new QueryTable(table), true);
291    }
292
293    public Joiner<QueryWrapper> rightJoin(String table, boolean when) {
294        return joining(SqlConsts.RIGHT_JOIN, new QueryTable(table), when);
295    }
296
297    public Joiner<QueryWrapper> rightJoin(Class<?> entityClass) {
298        return joining(SqlConsts.RIGHT_JOIN, entityClass, true);
299    }
300
301    public Joiner<QueryWrapper> rightJoin(Class<?> entityClass, boolean when) {
302        return joining(SqlConsts.RIGHT_JOIN, entityClass, when);
303    }
304
305    public Joiner<QueryWrapper> rightJoin(TableDef table) {
306        return joining(SqlConsts.RIGHT_JOIN, new QueryTable(table), true);
307    }
308
309    public Joiner<QueryWrapper> rightJoin(TableDef table, boolean when) {
310        return joining(SqlConsts.RIGHT_JOIN, new QueryTable(table), when);
311    }
312
313    public Joiner<QueryWrapper> rightJoin(QueryWrapper table) {
314        return joining(SqlConsts.RIGHT_JOIN, table, true);
315    }
316
317    public Joiner<QueryWrapper> rightJoin(QueryWrapper table, boolean when) {
318        return joining(SqlConsts.RIGHT_JOIN, table, when);
319    }
320
321    public Joiner<QueryWrapper> innerJoin(String table) {
322        return joining(SqlConsts.INNER_JOIN, new QueryTable(table), true);
323    }
324
325    public Joiner<QueryWrapper> innerJoin(String table, boolean when) {
326        return joining(SqlConsts.INNER_JOIN, new QueryTable(table), when);
327    }
328
329    public Joiner<QueryWrapper> innerJoin(Class<?> entityClass) {
330        return joining(SqlConsts.INNER_JOIN, entityClass, true);
331    }
332
333    public Joiner<QueryWrapper> innerJoin(Class<?> entityClass, boolean when) {
334        return joining(SqlConsts.INNER_JOIN, entityClass, when);
335    }
336
337    public Joiner<QueryWrapper> innerJoin(TableDef table) {
338        return innerJoin(table, true);
339    }
340
341    public Joiner<QueryWrapper> innerJoin(TableDef table, boolean when) {
342        return joining(SqlConsts.INNER_JOIN, new QueryTable(table), when);
343    }
344
345    public Joiner<QueryWrapper> innerJoin(QueryWrapper table) {
346        return joining(SqlConsts.INNER_JOIN, table, true);
347    }
348
349    public Joiner<QueryWrapper> innerJoin(QueryWrapper table, boolean when) {
350        return joining(SqlConsts.INNER_JOIN, table, when);
351    }
352
353    public Joiner<QueryWrapper> fullJoin(String table) {
354        return joining(SqlConsts.FULL_JOIN, new QueryTable(table), true);
355    }
356
357    public Joiner<QueryWrapper> fullJoin(String table, boolean when) {
358        return joining(SqlConsts.FULL_JOIN, new QueryTable(table), when);
359    }
360
361    public Joiner<QueryWrapper> fullJoin(Class<?> entityClass) {
362        return joining(SqlConsts.FULL_JOIN, entityClass, true);
363    }
364
365    public Joiner<QueryWrapper> fullJoin(Class<?> entityClass, boolean when) {
366        return joining(SqlConsts.FULL_JOIN, entityClass, when);
367    }
368
369    public Joiner<QueryWrapper> fullJoin(TableDef table) {
370        return joining(SqlConsts.FULL_JOIN, new QueryTable(table), true);
371    }
372
373    public Joiner<QueryWrapper> fullJoin(TableDef table, boolean when) {
374        return joining(SqlConsts.FULL_JOIN, new QueryTable(table), when);
375    }
376
377    public Joiner<QueryWrapper> fullJoin(QueryWrapper table) {
378        return joining(SqlConsts.FULL_JOIN, table, true);
379    }
380
381    public Joiner<QueryWrapper> fullJoin(QueryWrapper table, boolean when) {
382        return joining(SqlConsts.FULL_JOIN, table, when);
383    }
384
385    public Joiner<QueryWrapper> crossJoin(String table) {
386        return joining(SqlConsts.CROSS_JOIN, new QueryTable(table), true);
387    }
388
389    public Joiner<QueryWrapper> crossJoin(String table, boolean when) {
390        return joining(SqlConsts.CROSS_JOIN, new QueryTable(table), when);
391    }
392
393    public Joiner<QueryWrapper> crossJoin(Class<?> entityClass) {
394        return joining(SqlConsts.CROSS_JOIN, entityClass, true);
395    }
396
397    public Joiner<QueryWrapper> crossJoin(Class<?> entityClass, boolean when) {
398        return joining(SqlConsts.CROSS_JOIN, entityClass, when);
399    }
400
401    public Joiner<QueryWrapper> crossJoin(TableDef table) {
402        return joining(SqlConsts.CROSS_JOIN, new QueryTable(table), true);
403    }
404
405    public Joiner<QueryWrapper> crossJoin(TableDef table, boolean when) {
406        return joining(SqlConsts.CROSS_JOIN, new QueryTable(table), when);
407    }
408
409    public Joiner<QueryWrapper> crossJoin(QueryWrapper table) {
410        return joining(SqlConsts.CROSS_JOIN, table, true);
411    }
412
413    public Joiner<QueryWrapper> crossJoin(QueryWrapper table, boolean when) {
414        return joining(SqlConsts.CROSS_JOIN, table, when);
415    }
416
417    public Joiner<QueryWrapper> join(String table) {
418        return joining(SqlConsts.JOIN, new QueryTable(table), true);
419    }
420
421    public Joiner<QueryWrapper> join(String table, boolean when) {
422        return joining(SqlConsts.JOIN, new QueryTable(table), when);
423    }
424
425    public Joiner<QueryWrapper> join(Class<?> entityClass) {
426        return joining(SqlConsts.JOIN, entityClass, true);
427    }
428
429    public Joiner<QueryWrapper> join(Class<?> entityClass, boolean when) {
430        return joining(SqlConsts.JOIN, entityClass, when);
431    }
432
433    public Joiner<QueryWrapper> join(TableDef table) {
434        return joining(SqlConsts.JOIN, new QueryTable(table), true);
435    }
436
437    public Joiner<QueryWrapper> join(TableDef table, boolean when) {
438        return joining(SqlConsts.JOIN, new QueryTable(table), when);
439    }
440
441    public Joiner<QueryWrapper> join(QueryWrapper table) {
442        return joining(SqlConsts.JOIN, table, true);
443    }
444
445    public Joiner<QueryWrapper> join(QueryWrapper table, boolean when) {
446        return joining(SqlConsts.JOIN, table, when);
447    }
448
449    public QueryWrapper union(QueryWrapper unionQuery) {
450        if (unions == null) {
451            unions = new ArrayList<>();
452        }
453        unions.add(UnionWrapper.union(unionQuery));
454        return this;
455    }
456
457    public QueryWrapper unionAll(QueryWrapper unionQuery) {
458        if (unions == null) {
459            unions = new ArrayList<>();
460        }
461        unions.add(UnionWrapper.unionAll(unionQuery));
462        return this;
463    }
464
465    public QueryWrapper forUpdate() {
466        addEndFragment("FOR UPDATE");
467        return this;
468    }
469
470    public QueryWrapper forUpdateNoWait() {
471        addEndFragment("FOR UPDATE NOWAIT");
472        return this;
473    }
474
475    //    public QueryWrapper end(String sqlPart){
476    //        addEndFragment(sqlPart);
477    //        return this;
478    //    }
479
480    protected Joiner<QueryWrapper> joining(String type, QueryTable table, boolean when) {
481        Join join = new Join(type, table, when);
482        addJoinTable(join.getQueryTable());
483        return new Joiner<>(addJoin(join), join);
484    }
485
486    protected Joiner<QueryWrapper> joining(String type, Class<?> entityClass, boolean when) {
487        TableInfo tableInfo = TableInfoFactory.ofEntityClass(entityClass);
488        QueryTable queryTable = new QueryTable(tableInfo.getSchema(), tableInfo.getTableName());
489        return joining(type, queryTable, when);
490    }
491
492    protected Joiner<QueryWrapper> joining(String type, QueryWrapper queryWrapper, boolean when) {
493        Join join = new Join(type, queryWrapper, when);
494        addJoinTable(join.getQueryTable());
495        return new Joiner<>(addJoin(join), join);
496    }
497
498    public QueryWrapper groupBy(String name) {
499        addGroupByColumns(new QueryColumn(name));
500        return this;
501    }
502
503    public QueryWrapper groupBy(String... names) {
504        for (String name : names) {
505            groupBy(name);
506        }
507        return this;
508    }
509
510    public QueryWrapper groupBy(QueryColumn column) {
511        addGroupByColumns(column);
512        return this;
513    }
514
515    public QueryWrapper groupBy(QueryColumn... columns) {
516        for (QueryColumn column : columns) {
517            groupBy(column);
518        }
519        return this;
520    }
521
522    public QueryWrapper having(QueryCondition queryCondition) {
523        addHavingQueryCondition(queryCondition, SqlConnector.AND);
524        return this;
525    }
526
527    public QueryWrapper orderBy(QueryOrderBy... orderBys) {
528        for (QueryOrderBy queryOrderBy : orderBys) {
529            addOrderBy(queryOrderBy);
530        }
531        return this;
532    }
533
534    public QueryWrapper orderBy(String... orderBys) {
535        if (orderBys == null || orderBys.length == 0) {
536            //ignore
537            return this;
538        }
539        for (String queryOrderBy : orderBys) {
540            if (StringUtil.isNotBlank(queryOrderBy)) {
541                addOrderBy(new StringQueryOrderBy(queryOrderBy));
542            }
543        }
544        return this;
545    }
546
547    public QueryWrapper limit(Integer rows) {
548        setLimitRows(rows);
549        return this;
550    }
551
552    public QueryWrapper offset(Integer offset) {
553        setLimitOffset(offset);
554        return this;
555    }
556
557    public QueryWrapper limit(Integer offset, Integer rows) {
558        setLimitOffset(offset);
559        setLimitRows(rows);
560        return this;
561    }
562
563    public QueryWrapper datasource(String datasource) {
564        setDataSource(datasource);
565        return this;
566    }
567
568    public QueryWrapper hint(String hint) {
569        setHint(hint);
570        return this;
571    }
572
573    /**
574     * 获取 queryWrapper 的参数
575     * 在构建 sql 的时候,需要保证 where 在 having 的前面
576     */
577    Object[] getValueArray() {
578
579        List<Object> withValues = null;
580        if (with != null) {
581            Object[] paramValues = with.getParamValues();
582            if (ArrayUtil.isNotEmpty(paramValues)) {
583                withValues = new ArrayList<>(Arrays.asList(paramValues));
584
585            }
586        }
587
588        List<Object> columnValues = null;
589        List<QueryColumn> selectColumns = getSelectColumns();
590        if (CollectionUtil.isNotEmpty(selectColumns)) {
591            for (QueryColumn selectColumn : selectColumns) {
592                if (selectColumn instanceof HasParamsColumn) {
593                    Object[] paramValues = ((HasParamsColumn) selectColumn).getParamValues();
594                    if (ArrayUtil.isNotEmpty(paramValues)) {
595                        if (columnValues == null) {
596                            columnValues = new ArrayList<>(paramValues.length);
597                        }
598                        columnValues.addAll(Arrays.asList(paramValues));
599                    }
600                }
601            }
602        }
603
604        //select 子查询的参数:select * from (select ....)
605        List<Object> tableValues = null;
606        List<QueryTable> queryTables = getQueryTables();
607        if (CollectionUtil.isNotEmpty(queryTables)) {
608            for (QueryTable queryTable : queryTables) {
609                Object[] tableValueArray = queryTable.getValueArray();
610                if (tableValueArray.length > 0) {
611                    if (tableValues == null) {
612                        tableValues = new ArrayList<>(tableValueArray.length);
613                    }
614                    tableValues.addAll(Arrays.asList(tableValueArray));
615                }
616            }
617        }
618
619        //join 子查询的参数:left join (select ...)
620        List<Object> joinValues = null;
621        List<Join> joins = getJoins();
622        if (CollectionUtil.isNotEmpty(joins)) {
623            for (Join join : joins) {
624                QueryTable joinTable = join.getQueryTable();
625                Object[] valueArray = joinTable.getValueArray();
626                if (valueArray.length > 0) {
627                    if (joinValues == null) {
628                        joinValues = new ArrayList<>(valueArray.length);
629                    }
630                    joinValues.addAll(Arrays.asList(valueArray));
631                }
632                QueryCondition onCondition = join.getOnCondition();
633                Object[] values = WrapperUtil.getValues(onCondition);
634                if (values.length > 0) {
635                    if (joinValues == null) {
636                        joinValues = new ArrayList<>(values.length);
637                    }
638                    joinValues.addAll(Arrays.asList(values));
639                }
640            }
641        }
642
643        //where 参数
644        Object[] whereValues = WrapperUtil.getValues(whereQueryCondition);
645
646        //having 参数
647        Object[] havingValues = WrapperUtil.getValues(havingQueryCondition);
648
649        Object[] paramValues = ArrayUtil.concat(whereValues, havingValues);
650
651        //unions 参数
652        if (CollectionUtil.isNotEmpty(unions)) {
653            for (UnionWrapper union : unions) {
654                QueryWrapper queryWrapper = union.getQueryWrapper();
655                paramValues = ArrayUtil.concat(paramValues, queryWrapper.getValueArray());
656            }
657        }
658
659        Object[] returnValues = withValues == null ? FlexConsts.EMPTY_ARRAY : withValues.toArray();
660        returnValues = columnValues != null ? ArrayUtil.concat(returnValues, columnValues.toArray()) : returnValues;
661        returnValues = tableValues != null ? ArrayUtil.concat(returnValues, tableValues.toArray()) : returnValues;
662        returnValues = joinValues != null ? ArrayUtil.concat(returnValues, joinValues.toArray()) : returnValues;
663        returnValues = ArrayUtil.concat(returnValues, paramValues);
664
665        return returnValues;
666    }
667
668    List<QueryWrapper> getChildSelect() {
669
670        List<QueryWrapper> tableChildQuery = null;
671        List<QueryTable> queryTables = getQueryTables();
672        if (CollectionUtil.isNotEmpty(queryTables)) {
673            for (QueryTable queryTable : queryTables) {
674                if (queryTable instanceof SelectQueryTable) {
675                    if (tableChildQuery == null) {
676                        tableChildQuery = new ArrayList<>();
677                    }
678                    tableChildQuery.add(((SelectQueryTable) queryTable).getQueryWrapper());
679                }
680            }
681        }
682
683        List<QueryWrapper> whereChildQuery = WrapperUtil.getChildQueryWrapper(whereQueryCondition);
684        List<QueryWrapper> havingChildQuery = WrapperUtil.getChildQueryWrapper(havingQueryCondition);
685
686        if (tableChildQuery == null && whereChildQuery.isEmpty() && havingChildQuery.isEmpty()) {
687            return Collections.emptyList();
688        }
689
690        List<QueryWrapper> childQueryWrappers = tableChildQuery == null ? new ArrayList<>()
691            : new ArrayList<>(tableChildQuery);
692        childQueryWrappers.addAll(whereChildQuery);
693        childQueryWrappers.addAll(havingChildQuery);
694
695        return childQueryWrappers;
696    }
697
698    public String toSQL() {
699        String sql = DialectFactory.getDialect().forSelectByQuery(this);
700        return SqlUtil.replaceSqlParams(sql, getValueArray());
701    }
702
703    @Override
704    public QueryWrapper clone() {
705        return super.clone();
706    }
707
708}