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