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 018 019import com.mybatisflex.core.constant.SqlConsts; 020import com.mybatisflex.core.dialect.IDialect; 021import com.mybatisflex.core.exception.FlexExceptions; 022import com.mybatisflex.core.table.TableDef; 023import com.mybatisflex.core.util.*; 024 025import java.util.Collection; 026import java.util.List; 027import java.util.function.Predicate; 028 029/** 030 * 查询列,描述的是一张表的字段 031 */ 032public class QueryColumn implements CloneSupport<QueryColumn> { 033 034 protected QueryTable table; 035 protected String name; 036 protected String alias; 037 038 private boolean returnCopyByAsMethod = false; 039 040 041 public QueryColumn() { 042 } 043 044 public QueryColumn(String name) { 045 SqlUtil.keepColumnSafely(name); 046 this.name = StringUtil.tryTrim(name); 047 } 048 049 public QueryColumn(String tableName, String name) { 050 SqlUtil.keepColumnSafely(name); 051 this.table = new QueryTable(tableName); 052 this.name = StringUtil.tryTrim(name); 053 } 054 055 public QueryColumn(String schema, String tableName, String name) { 056 SqlUtil.keepColumnSafely(name); 057 this.table = new QueryTable(schema, tableName); 058 this.name = StringUtil.tryTrim(name); 059 } 060 061 public QueryColumn(String schema, String tableName, String name, String alias) { 062 SqlUtil.keepColumnSafely(name); 063 this.returnCopyByAsMethod = true; 064 this.table = new QueryTable(schema, tableName); 065 this.name = StringUtil.tryTrim(name); 066 this.alias = StringUtil.tryTrim(alias); 067 } 068 069 public QueryColumn(QueryTable queryTable, String name) { 070 SqlUtil.keepColumnSafely(name); 071 this.table = queryTable; 072 this.name = StringUtil.tryTrim(name); 073 } 074 075 public QueryColumn(TableDef tableDef, String name) { 076 this(tableDef, name, null); 077 } 078 079 public QueryColumn(TableDef tableDef, String name, String alias) { 080 SqlUtil.keepColumnSafely(name); 081 this.returnCopyByAsMethod = true; 082 this.table = new QueryTable(tableDef); 083 this.name = name; 084 this.alias = alias; 085 } 086 087 088 public QueryTable getTable() { 089 return table; 090 } 091 092 public void setTable(QueryTable table) { 093 this.table = table; 094 } 095 096 public String getName() { 097 return name; 098 } 099 100 public void setName(String name) { 101 this.name = name; 102 } 103 104 public String getAlias() { 105 return alias; 106 } 107 108 public void setAlias(String alias) { 109 this.alias = alias; 110 } 111 112 public <T> QueryColumn as(LambdaGetter<T> fn) { 113 return as(fn, false); 114 } 115 116 public <T> QueryColumn as(LambdaGetter<T> fn, boolean withPrefix) { 117 return as(LambdaUtil.getAliasName(fn, withPrefix)); 118 } 119 120 public QueryColumn as(String alias) { 121 SqlUtil.keepColumnSafely(alias); 122 if (returnCopyByAsMethod) { 123 QueryColumn newColumn = new QueryColumn(); 124 newColumn.table = this.table; 125 newColumn.name = this.name; 126 newColumn.alias = alias; 127 return newColumn; 128 } else { 129 this.alias = alias; 130 return this; 131 } 132 } 133 134 135 // query methods /////// 136 137 /** 138 * equals 139 * 140 * @param value 141 */ 142 public QueryCondition eq(Object value) { 143 if (value == null) { 144 return QueryCondition.createEmpty(); 145 } 146 return QueryCondition.create(this, SqlConsts.EQUALS, value); 147 } 148 149 150 public <T> QueryCondition eq(Object value, Predicate<T> fn) { 151 if (value == null) { 152 return QueryCondition.createEmpty(); 153 } 154 return QueryCondition.create(this, SqlConsts.EQUALS, value).when(fn); 155 } 156 157 158 /** 159 * not equals != 160 * 161 * @param value 162 */ 163 public QueryCondition ne(Object value) { 164 if (value == null) { 165 return QueryCondition.createEmpty(); 166 } 167 return QueryCondition.create(this, SqlConsts.NOT_EQUALS, value); 168 } 169 170 public <T> QueryCondition ne(Object value, Predicate<T> fn) { 171 if (value == null) { 172 return QueryCondition.createEmpty(); 173 } 174 return QueryCondition.create(this, SqlConsts.NOT_EQUALS, value).when(fn); 175 } 176 177 178 /** 179 * like %% 180 * 181 * @param value 182 */ 183 public QueryCondition like(Object value) { 184 if (value == null) { 185 return QueryCondition.createEmpty(); 186 } 187 return QueryCondition.create(this, SqlConsts.LIKE, "%" + value + "%"); 188 } 189 190 public <T> QueryCondition like(Object value, Predicate<T> fn) { 191 if (value == null) { 192 return QueryCondition.createEmpty(); 193 } 194 return QueryCondition.create(this, SqlConsts.LIKE, "%" + value + "%").when(fn); 195 } 196 197 198 public QueryCondition likeLeft(Object value) { 199 if (value == null) { 200 return QueryCondition.createEmpty(); 201 } 202 return QueryCondition.create(this, SqlConsts.LIKE, value + "%"); 203 } 204 205 public <T> QueryCondition likeLeft(Object value, Predicate<T> fn) { 206 if (value == null) { 207 return QueryCondition.createEmpty(); 208 } 209 return QueryCondition.create(this, SqlConsts.LIKE, value + "%").when(fn); 210 } 211 212 213 public QueryCondition likeRight(Object value) { 214 if (value == null) { 215 return QueryCondition.createEmpty(); 216 } 217 return QueryCondition.create(this, SqlConsts.LIKE, "%" + value); 218 } 219 220 public <T> QueryCondition likeRight(Object value, Predicate<T> fn) { 221 if (value == null) { 222 return QueryCondition.createEmpty(); 223 } 224 return QueryCondition.create(this, SqlConsts.LIKE, "%" + value).when(fn); 225 } 226 227 public QueryCondition likeRaw(Object value) { 228 if (value == null) { 229 return QueryCondition.createEmpty(); 230 } 231 return QueryCondition.create(this, SqlConsts.LIKE, value); 232 } 233 234 public <T> QueryCondition likeRaw(Object value, Predicate<T> fn) { 235 if (value == null) { 236 return QueryCondition.createEmpty(); 237 } 238 return QueryCondition.create(this, SqlConsts.LIKE, value).when(fn); 239 } 240 241 /** 242 * 大于 greater than 243 * 244 * @param value 245 */ 246 public QueryCondition gt(Object value) { 247 if (value == null) { 248 return QueryCondition.createEmpty(); 249 } 250 return QueryCondition.create(this, SqlConsts.GT, value); 251 } 252 253 public <T> QueryCondition gt(Object value, Predicate<T> fn) { 254 if (value == null) { 255 return QueryCondition.createEmpty(); 256 } 257 return QueryCondition.create(this, SqlConsts.GT, value).when(fn); 258 } 259 260 /** 261 * 大于等于 greater or equal 262 * 263 * @param value 264 */ 265 public QueryCondition ge(Object value) { 266 if (value == null) { 267 return QueryCondition.createEmpty(); 268 } 269 return QueryCondition.create(this, SqlConsts.GE, value); 270 } 271 272 public <T> QueryCondition ge(Object value, Predicate<T> fn) { 273 if (value == null) { 274 return QueryCondition.createEmpty(); 275 } 276 return QueryCondition.create(this, SqlConsts.GE, value).when(fn); 277 } 278 279 /** 280 * 小于 less than 281 * 282 * @param value 283 */ 284 public QueryCondition lt(Object value) { 285 if (value == null) { 286 return QueryCondition.createEmpty(); 287 } 288 return QueryCondition.create(this, SqlConsts.LT, value); 289 } 290 291 public <T> QueryCondition lt(Object value, Predicate<T> fn) { 292 if (value == null) { 293 return QueryCondition.createEmpty(); 294 } 295 return QueryCondition.create(this, SqlConsts.LT, value).when(fn); 296 } 297 298 /** 299 * 小于等于 less or equal 300 * 301 * @param value 302 */ 303 public QueryCondition le(Object value) { 304 if (value == null) { 305 return QueryCondition.createEmpty(); 306 } 307 return QueryCondition.create(this, SqlConsts.LE, value); 308 } 309 310 public <T> QueryCondition le(Object value, Predicate<T> fn) { 311 if (value == null) { 312 return QueryCondition.createEmpty(); 313 } 314 return QueryCondition.create(this, SqlConsts.LE, value).when(fn); 315 } 316 317 318 /** 319 * IS NULL 320 * 321 * @return 322 */ 323 public QueryCondition isNull() { 324 return QueryCondition.create(this, SqlConsts.IS_NULL, null); 325 } 326 327 public <T> QueryCondition isNull(Predicate<T> fn) { 328 return QueryCondition.create(this, SqlConsts.IS_NULL, null).when(fn); 329 } 330 331 332 /** 333 * IS NOT NULL 334 * 335 * @return 336 */ 337 public QueryCondition isNotNull() { 338 return QueryCondition.create(this, SqlConsts.IS_NOT_NULL, null); 339 } 340 341 public <T> QueryCondition isNotNull(Predicate<T> fn) { 342 return QueryCondition.create(this, SqlConsts.IS_NOT_NULL, null).when(fn); 343 } 344 345 346 /** 347 * in arrays 348 * 349 * @param arrays 350 * @return 351 */ 352 public QueryCondition in(Object... arrays) { 353 //忽略 QueryWrapper.in("name", null) 的情况 354 if (arrays == null || arrays.length == 0 || (arrays.length == 1 && arrays[0] == null)) { 355 return QueryCondition.createEmpty(); 356 } 357 return QueryCondition.create(this, SqlConsts.IN, arrays); 358 } 359 360 public <T> QueryCondition in(Object[] arrays, Predicate<T> fn) { 361 //忽略 QueryWrapper.in("name", null) 的情况 362 if (arrays == null || arrays.length == 0 || (arrays.length == 1 && arrays[0] == null)) { 363 return QueryCondition.createEmpty(); 364 } 365 return QueryCondition.create(this, SqlConsts.IN, arrays).when(fn); 366 } 367 368 /** 369 * in child select 370 * 371 * @param queryWrapper 372 * @return 373 */ 374 public QueryCondition in(QueryWrapper queryWrapper) { 375 return QueryCondition.create(this, SqlConsts.IN, queryWrapper); 376 } 377 378 public <T> QueryCondition in(QueryWrapper queryWrapper, Predicate<T> fn) { 379 return QueryCondition.create(this, SqlConsts.IN, queryWrapper).when(fn); 380 } 381 382 383 /** 384 * in Collection 385 * 386 * @param collection 387 * @return 388 */ 389 public QueryCondition in(Collection<?> collection) { 390 if (collection != null && !collection.isEmpty()) { 391 return in(collection.toArray()); 392 } 393 return QueryCondition.createEmpty(); 394 } 395 396 public <T> QueryCondition in(Collection<?> collection, Predicate<T> fn) { 397 if (collection != null && !collection.isEmpty()) { 398 return in(collection.toArray(), fn); 399 } 400 return QueryCondition.createEmpty(); 401 } 402 403 /** 404 * not int arrays 405 * 406 * @param arrays 407 * @return 408 */ 409 public QueryCondition notIn(Object... arrays) { 410 //忽略 QueryWrapper.notIn("name", null) 的情况 411 if (arrays == null || arrays.length == 0 || (arrays.length == 1 && arrays[0] == null)) { 412 return QueryCondition.createEmpty(); 413 } 414 return QueryCondition.create(this, SqlConsts.NOT_IN, arrays); 415 } 416 417 public <T> QueryCondition notIn(Object[] arrays, Predicate<T> fn) { 418 //忽略 QueryWrapper.notIn("name", null) 的情况 419 if (arrays == null || arrays.length == 0 || (arrays.length == 1 && arrays[0] == null)) { 420 return QueryCondition.createEmpty(); 421 } 422 return QueryCondition.create(this, SqlConsts.NOT_IN, arrays).when(fn); 423 } 424 425 426 /** 427 * not in Collection 428 * 429 * @param collection 430 * @return 431 */ 432 public QueryCondition notIn(Collection<?> collection) { 433 if (collection != null && !collection.isEmpty()) { 434 return notIn(collection.toArray()); 435 } 436 return QueryCondition.createEmpty(); 437 } 438 439 public <T> QueryCondition notIn(Collection<?> collection, Predicate<T> fn) { 440 if (collection != null && !collection.isEmpty()) { 441 return notIn(collection.toArray(), fn); 442 } 443 return QueryCondition.createEmpty(); 444 } 445 446 /** 447 * not in child select 448 * 449 * @param queryWrapper 450 */ 451 public QueryCondition notIn(QueryWrapper queryWrapper) { 452 return QueryCondition.create(this, SqlConsts.NOT_IN, queryWrapper); 453 } 454 455 public <T> QueryCondition notIn(QueryWrapper queryWrapper, Predicate<T> fn) { 456 return QueryCondition.create(this, SqlConsts.NOT_IN, queryWrapper).when(fn); 457 } 458 459 460 /** 461 * between 462 * 463 * @param start 464 * @param end 465 */ 466 public QueryCondition between(Object start, Object end) { 467 return QueryCondition.create(this, SqlConsts.BETWEEN, new Object[]{start, end}); 468 } 469 470 public <T> QueryCondition between(Object start, Object end, Predicate<T> fn) { 471 return QueryCondition.create(this, SqlConsts.BETWEEN, new Object[]{start, end}).when(fn); 472 } 473 474 475 /** 476 * not between 477 * 478 * @param start 479 * @param end 480 */ 481 public QueryCondition notBetween(Object start, Object end) { 482 return QueryCondition.create(this, SqlConsts.NOT_BETWEEN, new Object[]{start, end}); 483 } 484 485 public <T> QueryCondition notBetween(Object start, Object end, Predicate<T> fn) { 486 return QueryCondition.create(this, SqlConsts.NOT_BETWEEN, new Object[]{start, end}).when(fn); 487 } 488 489 490 ////order by //// 491 public QueryOrderBy asc() { 492 return new QueryOrderBy(this, SqlConsts.ASC); 493 } 494 495 496 public QueryOrderBy desc() { 497 return new QueryOrderBy(this, SqlConsts.DESC); 498 } 499 500 501 // 运算 加减乘除 + - * / 502 public QueryColumn add(QueryColumn queryColumn) { 503 return new ArithmeticQueryColumn(this).add(queryColumn); 504 } 505 506 public QueryColumn add(Number number) { 507 return new ArithmeticQueryColumn(this).add(number); 508 } 509 510 public QueryColumn subtract(QueryColumn queryColumn) { 511 return new ArithmeticQueryColumn(this).subtract(queryColumn); 512 } 513 514 public QueryColumn subtract(Number number) { 515 return new ArithmeticQueryColumn(this).subtract(number); 516 } 517 518 public QueryColumn multiply(QueryColumn queryColumn) { 519 return new ArithmeticQueryColumn(this).multiply(queryColumn); 520 } 521 522 public QueryColumn multiply(Number number) { 523 return new ArithmeticQueryColumn(this).multiply(number); 524 } 525 526 public QueryColumn divide(QueryColumn queryColumn) { 527 return new ArithmeticQueryColumn(this).divide(queryColumn); 528 } 529 530 public QueryColumn divide(Number number) { 531 return new ArithmeticQueryColumn(this).divide(number); 532 } 533 534 535 String toConditionSql(List<QueryTable> queryTables, IDialect dialect) { 536 QueryTable selectTable = getSelectTable(queryTables, table); 537 if (selectTable == null) { 538 return dialect.wrap(name); 539 } else { 540 if (StringUtil.isNotBlank(selectTable.alias)) { 541 return dialect.wrap(selectTable.alias) + SqlConsts.REFERENCE + dialect.wrap(name); 542 } else if (StringUtil.isNotBlank(selectTable.getSchema()) && StringUtil.isNotBlank(selectTable.getName())) { 543 return dialect.wrap(dialect.getRealSchema(selectTable.schema)) + SqlConsts.REFERENCE + dialect.wrap(dialect.getRealTable(selectTable.getName())) + SqlConsts.REFERENCE + dialect.wrap(name); 544 } else if (StringUtil.isNotBlank(selectTable.getName())) { 545 return dialect.wrap(dialect.getRealTable(selectTable.getName())) + SqlConsts.REFERENCE + dialect.wrap(name); 546 } else { 547 return dialect.wrap(name); 548 } 549 } 550 } 551 552 553 String toSelectSql(List<QueryTable> queryTables, IDialect dialect) { 554 return toConditionSql(queryTables, dialect) + WrapperUtil.buildAlias(alias, dialect); 555 } 556 557 558 QueryTable getSelectTable(List<QueryTable> queryTables, QueryTable selfTable) { 559 //未查询任何表 560 if (queryTables == null || queryTables.isEmpty()) { 561 return null; 562 } 563 564 if (selfTable != null && StringUtil.isNotBlank(selfTable.alias)){ 565 return selfTable; 566 } 567 568 if (queryTables.size() == 1 && queryTables.get(0).isSameTable(selfTable)) { 569 //ignore table 570 return null; 571 } 572 573 if (CollectionUtil.isEmpty(queryTables)) { 574 return selfTable; 575 } 576 577 if (selfTable == null && queryTables.size() == 1) { 578 return queryTables.get(0); 579 } 580 581 for (QueryTable table : queryTables) { 582 if (table.isSameTable(selfTable)) { 583 return table; 584 } 585 } 586 return selfTable; 587 } 588 589 590 @Override 591 public String toString() { 592 return "QueryColumn{" + 593 "table=" + table + 594 ", name='" + name + '\'' + 595 ", alias='" + alias + '\'' + 596 '}'; 597 } 598 599 600 @Override 601 public QueryColumn clone() { 602 try { 603 QueryColumn clone = (QueryColumn) super.clone(); 604 // deep clone ... 605 clone.table = ObjectUtil.clone(this.table); 606 return clone; 607 } catch (CloneNotSupportedException e) { 608 throw FlexExceptions.wrap(e); 609 } 610 } 611 612}