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.exception.FlexExceptions; 019import com.mybatisflex.core.table.TableDef; 020import com.mybatisflex.core.util.ArrayUtil; 021import com.mybatisflex.core.util.CollectionUtil; 022import com.mybatisflex.core.util.StringUtil; 023 024import java.util.*; 025 026public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> { 027 028 029 public static QueryWrapper create() { 030 return new QueryWrapper(); 031 } 032 033 public QueryWrapper select(QueryColumn... queryColumns) { 034 for (QueryColumn column : queryColumns) { 035 if (column != null) { 036 addSelectColumn(column); 037 } 038 } 039 return this; 040 } 041 042 043 public QueryWrapper from(TableDef... tableDefs) { 044 for (TableDef tableDef : tableDefs) { 045 from(new QueryTable(tableDef.getTableName())); 046 } 047 return this; 048 } 049 050 051 public QueryWrapper from(String... tables) { 052 for (String table : tables) { 053 if (StringUtil.isBlank(table)) { 054 throw new IllegalArgumentException("table must not be null or blank."); 055 } 056 from(new QueryTable(table)); 057 } 058 return this; 059 } 060 061 062 public QueryWrapper from(QueryTable... tables) { 063 if (CollectionUtil.isEmpty(queryTables)) { 064 queryTables = new ArrayList<>(); 065 queryTables.addAll(Arrays.asList(tables)); 066 } else { 067 for (QueryTable table : tables) { 068 boolean contains = false; 069 for (QueryTable queryTable : queryTables) { 070 if (queryTable.isSameTable(table)) { 071 contains = true; 072 } 073 } 074 if (!contains) { 075 queryTables.add(table); 076 } 077 } 078 } 079 return this; 080 } 081 082 083 public QueryWrapper from(QueryWrapper queryWrapper) { 084 return from(new SelectQueryTable(queryWrapper)); 085 } 086 087 088 public QueryWrapper as(String alias) { 089 if (CollectionUtil.isEmpty(queryTables)) { 090 throw new IllegalArgumentException("query table must not be empty."); 091 } 092 if (queryTables.size() > 1) { 093 throw FlexExceptions.wrap("QueryWrapper.as(...) only support 1 table"); 094 } 095 queryTables.get(0).alias = alias; 096 return this; 097 } 098 099 100 public QueryWrapper where(QueryCondition queryCondition) { 101 this.setWhereQueryCondition(queryCondition); 102 return this; 103 } 104 105 public QueryWrapper where(String sql) { 106 this.setWhereQueryCondition(new StringQueryCondition(sql)); 107 return this; 108 } 109 110 111 public QueryWrapper where(String sql, Object... params) { 112 this.setWhereQueryCondition(new StringQueryCondition(sql, params)); 113 return this; 114 } 115 116 117 public QueryWrapper where(Map<String, Object> whereConditions) { 118 if (whereConditions != null) { 119 whereConditions.forEach((s, o) -> and(QueryCondition.create(new QueryColumn(s), o))); 120 } 121 return this; 122 } 123 124 public QueryWrapper and(QueryCondition queryCondition) { 125 return addWhereQueryCondition(queryCondition, SqlConnector.AND); 126 } 127 128 public QueryWrapper and(String sql) { 129 this.addWhereQueryCondition(new StringQueryCondition(sql), SqlConnector.AND); 130 return this; 131 } 132 133 public QueryWrapper and(String sql, Object... params) { 134 this.addWhereQueryCondition(new StringQueryCondition(sql, params), SqlConnector.AND); 135 return this; 136 } 137 138 public QueryWrapper or(QueryCondition queryCondition) { 139 return addWhereQueryCondition(queryCondition, SqlConnector.OR); 140 } 141 142 public QueryWrapper or(String sql) { 143 this.addWhereQueryCondition(new StringQueryCondition(sql), SqlConnector.OR); 144 return this; 145 } 146 147 public QueryWrapper or(String sql, Object... params) { 148 this.addWhereQueryCondition(new StringQueryCondition(sql, params), SqlConnector.OR); 149 return this; 150 } 151 152 153 public Joiner<QueryWrapper> leftJoin(String table) { 154 return joining(Join.TYPE_LEFT, table, true); 155 } 156 157 158 public Joiner<QueryWrapper> leftJoinIf(String table, boolean condition) { 159 return joining(Join.TYPE_LEFT, table, condition); 160 } 161 162 public Joiner<QueryWrapper> leftJoin(TableDef table) { 163 return joining(Join.TYPE_LEFT, table.getTableName(), true); 164 } 165 166 167 public Joiner<QueryWrapper> leftJoinIf(TableDef table, boolean condition) { 168 return joining(Join.TYPE_LEFT, table.getTableName(), condition); 169 } 170 171 public Joiner<QueryWrapper> leftJoin(QueryWrapper table) { 172 return joining(Join.TYPE_LEFT, table, true); 173 } 174 175 public Joiner<QueryWrapper> leftJoinIf(QueryWrapper table, boolean condition) { 176 return joining(Join.TYPE_LEFT, table, condition); 177 } 178 179 public Joiner<QueryWrapper> rightJoin(String table) { 180 return joining(Join.TYPE_RIGHT, table, true); 181 } 182 183 public Joiner<QueryWrapper> rightJoinIf(String table, boolean condition) { 184 return joining(Join.TYPE_RIGHT, table, condition); 185 } 186 187 public Joiner<QueryWrapper> rightJoin(QueryWrapper table) { 188 return joining(Join.TYPE_RIGHT, table, true); 189 } 190 191 public Joiner<QueryWrapper> rightJoinIf(QueryWrapper table, boolean condition) { 192 return joining(Join.TYPE_RIGHT, table, condition); 193 } 194 195 public Joiner<QueryWrapper> innerJoin(String table) { 196 return joining(Join.TYPE_INNER, table, true); 197 } 198 199 public Joiner<QueryWrapper> innerJoinIf(String table, boolean condition) { 200 return joining(Join.TYPE_INNER, table, condition); 201 } 202 203 public Joiner<QueryWrapper> innerJoin(TableDef table) { 204 return innerJoinIf(table, true); 205 } 206 207 public Joiner<QueryWrapper> innerJoinIf(TableDef table, boolean condition) { 208 return joining(Join.TYPE_INNER, table.getTableName(), condition); 209 } 210 211 public Joiner<QueryWrapper> innerJoin(QueryWrapper table) { 212 return joining(Join.TYPE_INNER, table, true); 213 } 214 215 public Joiner<QueryWrapper> innerJoinIf(QueryWrapper table, boolean condition) { 216 return joining(Join.TYPE_INNER, table, condition); 217 } 218 219 public Joiner<QueryWrapper> fullJoin(String table) { 220 return joining(Join.TYPE_FULL, table, true); 221 } 222 223 public Joiner<QueryWrapper> fullJoinIf(String table, boolean condition) { 224 return joining(Join.TYPE_FULL, table, condition); 225 } 226 227 public Joiner<QueryWrapper> fullJoin(QueryWrapper table) { 228 return joining(Join.TYPE_FULL, table, true); 229 } 230 231 public Joiner<QueryWrapper> fullJoinIf(QueryWrapper table, boolean condition) { 232 return joining(Join.TYPE_FULL, table, condition); 233 } 234 235 public Joiner<QueryWrapper> crossJoin(String table) { 236 return joining(Join.TYPE_CROSS, table, true); 237 } 238 239 public Joiner<QueryWrapper> crossJoinIf(String table, boolean condition) { 240 return joining(Join.TYPE_CROSS, table, condition); 241 } 242 243 public Joiner<QueryWrapper> crossJoin(QueryWrapper table) { 244 return joining(Join.TYPE_CROSS, table, true); 245 } 246 247 public Joiner<QueryWrapper> crossJoinIf(QueryWrapper table, boolean condition) { 248 return joining(Join.TYPE_CROSS, table, condition); 249 } 250 251 public QueryWrapper union(QueryWrapper unionQuery) { 252 if (unions == null) { 253 unions = new ArrayList<>(); 254 } 255 unions.add(UnionWrapper.union(unionQuery)); 256 return this; 257 } 258 259 public QueryWrapper unionAll(QueryWrapper unionQuery) { 260 if (unions == null) { 261 unions = new ArrayList<>(); 262 } 263 unions.add(UnionWrapper.unionAll(unionQuery)); 264 return this; 265 } 266 267 protected Joiner<QueryWrapper> joining(String type, String table, boolean condition) { 268 Join join = new Join(type, table, condition); 269 addJoinTable(join.getQueryTable()); 270 return new Joiner<>(AddJoin(join), join); 271 } 272 273 protected Joiner<QueryWrapper> joining(String type, QueryWrapper queryWrapper, boolean condition) { 274 Join join = new Join(type, queryWrapper, condition); 275 addJoinTable(join.getQueryTable()); 276 return new Joiner<>(AddJoin(join), join); 277 } 278 279 280 public QueryWrapper groupBy(String name) { 281 addGroupByColumns(new QueryColumn(name)); 282 return this; 283 } 284 285 public QueryWrapper groupBy(String... names) { 286 for (String name : names) { 287 groupBy(name); 288 } 289 return this; 290 } 291 292 public QueryWrapper groupBy(QueryColumn column) { 293 addGroupByColumns(column); 294 return this; 295 } 296 297 public QueryWrapper groupBy(QueryColumn... columns) { 298 for (QueryColumn column : columns) { 299 groupBy(column); 300 } 301 return this; 302 } 303 304 305 public QueryWrapper having(QueryCondition queryCondition) { 306 addHavingQueryCondition(queryCondition, SqlConnector.AND); 307 return this; 308 } 309 310 public QueryWrapper orderBy(QueryOrderBy... orderBys) { 311 for (QueryOrderBy queryOrderBy : orderBys) { 312 addOrderBy(queryOrderBy); 313 } 314 return this; 315 } 316 317 public QueryWrapper orderBy(String... orderBys) { 318 for (String queryOrderBy : orderBys) { 319 addOrderBy(new StringQueryOrderBy(queryOrderBy)); 320 } 321 return this; 322 } 323 324 325 public QueryWrapper limit(Integer rows) { 326 setLimitRows(rows); 327 return this; 328 } 329 330 public QueryWrapper offset(Integer offset) { 331 setLimitOffset(offset); 332 return this; 333 } 334 335 public QueryWrapper limit(Integer offset, Integer rows) { 336 setLimitOffset(offset); 337 setLimitRows(rows); 338 return this; 339 } 340 341 public QueryWrapper datasource(String datasource) { 342 setDatasource(datasource); 343 return this; 344 } 345 346 /** 347 * 获取 queryWrapper 的参数 348 * 在构建 sql 的时候,需要保证 where 在 having 的前面 349 */ 350 Object[] getValueArray() { 351 Object[] whereValues = WrapperUtil.getValues(whereQueryCondition); 352 Object[] havingValues = WrapperUtil.getValues(havingQueryCondition); 353 Object[] values = ArrayUtil.concat(whereValues, havingValues); 354 if (CollectionUtil.isNotEmpty(unions)) { 355 for (UnionWrapper union : unions) { 356 QueryWrapper queryWrapper = union.getQueryWrapper(); 357 values = ArrayUtil.concat(values, queryWrapper.getValueArray()); 358 } 359 } 360 return values; 361 } 362 363 364 List<QueryWrapper> getChildSelect() { 365 366 List<QueryWrapper> whereChildQuery= WrapperUtil.getChildSelect(whereQueryCondition); 367 List<QueryWrapper> havingChildQuery = WrapperUtil.getChildSelect(havingQueryCondition); 368 369 if (whereChildQuery.isEmpty() && havingChildQuery.isEmpty()){ 370 return Collections.emptyList(); 371 } 372 373 List<QueryWrapper> childQueryWrappers = new ArrayList<>(whereChildQuery); 374 childQueryWrappers.addAll(havingChildQuery); 375 376 return childQueryWrappers; 377 } 378 379 380}