001/* 002 * Copyright (c) 2022-2025, 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.dialect.impl; 017 018import com.mybatisflex.core.dialect.IDialect; 019import com.mybatisflex.core.dialect.KeywordWrap; 020import com.mybatisflex.core.dialect.LimitOffsetProcessor; 021import com.mybatisflex.core.dialect.OperateType; 022import com.mybatisflex.core.exception.FlexExceptions; 023import com.mybatisflex.core.exception.locale.LocalizedFormats; 024import com.mybatisflex.core.logicdelete.LogicDeleteManager; 025import com.mybatisflex.core.query.CPI; 026import com.mybatisflex.core.query.Join; 027import com.mybatisflex.core.query.QueryColumn; 028import com.mybatisflex.core.query.QueryCondition; 029import com.mybatisflex.core.query.QueryOrderBy; 030import com.mybatisflex.core.query.QueryTable; 031import com.mybatisflex.core.query.QueryWrapper; 032import com.mybatisflex.core.query.UnionWrapper; 033import com.mybatisflex.core.query.With; 034import com.mybatisflex.core.row.Row; 035import com.mybatisflex.core.row.RowCPI; 036import com.mybatisflex.core.table.TableInfo; 037import com.mybatisflex.core.update.RawValue; 038import com.mybatisflex.core.util.ArrayUtil; 039import com.mybatisflex.core.util.CollectionUtil; 040import com.mybatisflex.core.util.SqlUtil; 041import com.mybatisflex.core.util.StringUtil; 042 043import java.util.Collection; 044import java.util.Collections; 045import java.util.List; 046import java.util.Map; 047import java.util.Set; 048import java.util.StringJoiner; 049import java.util.function.Function; 050import java.util.stream.Collectors; 051import java.util.stream.IntStream; 052 053import static com.mybatisflex.core.constant.SqlConsts.AND; 054import static com.mybatisflex.core.constant.SqlConsts.ASTERISK; 055import static com.mybatisflex.core.constant.SqlConsts.BLANK; 056import static com.mybatisflex.core.constant.SqlConsts.BRACKET_LEFT; 057import static com.mybatisflex.core.constant.SqlConsts.BRACKET_RIGHT; 058import static com.mybatisflex.core.constant.SqlConsts.DELETE; 059import static com.mybatisflex.core.constant.SqlConsts.DELETE_FROM; 060import static com.mybatisflex.core.constant.SqlConsts.DELIMITER; 061import static com.mybatisflex.core.constant.SqlConsts.EMPTY; 062import static com.mybatisflex.core.constant.SqlConsts.EQUALS; 063import static com.mybatisflex.core.constant.SqlConsts.EQUALS_PLACEHOLDER; 064import static com.mybatisflex.core.constant.SqlConsts.FROM; 065import static com.mybatisflex.core.constant.SqlConsts.GROUP_BY; 066import static com.mybatisflex.core.constant.SqlConsts.HAVING; 067import static com.mybatisflex.core.constant.SqlConsts.HINT_END; 068import static com.mybatisflex.core.constant.SqlConsts.HINT_START; 069import static com.mybatisflex.core.constant.SqlConsts.INSERT_INTO; 070import static com.mybatisflex.core.constant.SqlConsts.OR; 071import static com.mybatisflex.core.constant.SqlConsts.ORDER_BY; 072import static com.mybatisflex.core.constant.SqlConsts.PLACEHOLDER; 073import static com.mybatisflex.core.constant.SqlConsts.REFERENCE; 074import static com.mybatisflex.core.constant.SqlConsts.SELECT; 075import static com.mybatisflex.core.constant.SqlConsts.SELECT_ALL_FROM; 076import static com.mybatisflex.core.constant.SqlConsts.SEMICOLON; 077import static com.mybatisflex.core.constant.SqlConsts.SET; 078import static com.mybatisflex.core.constant.SqlConsts.UPDATE; 079import static com.mybatisflex.core.constant.SqlConsts.VALUES; 080import static com.mybatisflex.core.constant.SqlConsts.WHERE; 081 082/** 083 * 通用的方言设计,其他方言可以继承于当前 CommonsDialectImpl 084 * 创建或获取方言请参考 {@link com.mybatisflex.core.dialect.DialectFactory} 085 */ 086public class CommonsDialectImpl implements IDialect { 087 088 protected KeywordWrap keywordWrap = KeywordWrap.BACK_QUOTE; 089 private LimitOffsetProcessor limitOffsetProcessor = LimitOffsetProcessor.MYSQL; 090 091 public CommonsDialectImpl() { 092 } 093 094 public CommonsDialectImpl(LimitOffsetProcessor limitOffsetProcessor) { 095 this.limitOffsetProcessor = limitOffsetProcessor; 096 } 097 098 public CommonsDialectImpl(KeywordWrap keywordWrap, LimitOffsetProcessor limitOffsetProcessor) { 099 this.keywordWrap = keywordWrap; 100 this.limitOffsetProcessor = limitOffsetProcessor; 101 } 102 103 @Override 104 public String wrap(String keyword) { 105 return ASTERISK.equals(keyword) ? keyword : keywordWrap.wrap(keyword); 106 } 107 108 @Override 109 public String wrapColumnAlias(String keyword) { 110// return ASTERISK.equals(keyword) ? keyword : keywordWrap.getPrefix() + keyword + keywordWrap.getSuffix(); 111 return ASTERISK.equals(keyword) ? keyword : keywordWrap.wrap(keyword); 112 } 113 114 @Override 115 public String forHint(String hintString) { 116 return StringUtil.isNotBlank(hintString) ? HINT_START + hintString + HINT_END : EMPTY; 117 } 118 119 @Override 120 public String forInsertRow(String schema, String tableName, Row row) { 121 StringBuilder fields = new StringBuilder(); 122 StringBuilder paramsOrPlaceholder = new StringBuilder(); 123 124 // 插入数据时,可能包含主键 125 Set<String> modifyAttrs = RowCPI.getInsertAttrs(row); 126 int index = 0; 127 for (String attr : modifyAttrs) { 128 fields.append(wrap(attr)); 129 130 Object value = row.get(attr); 131 if (value instanceof RawValue) { 132 paramsOrPlaceholder.append(((RawValue) value).toSql(this)); 133 } else { 134 paramsOrPlaceholder.append(PLACEHOLDER); 135 } 136 if (index != modifyAttrs.size() - 1) { 137 fields.append(DELIMITER); 138 paramsOrPlaceholder.append(DELIMITER); 139 } 140 index++; 141 } 142 143 String table = getRealTable(tableName, OperateType.INSERT); 144 StringBuilder sql = new StringBuilder(); 145 sql.append(INSERT_INTO); 146 if (StringUtil.isNotBlank(schema)) { 147 sql.append(wrap(getRealSchema(schema, table, OperateType.INSERT))).append(REFERENCE); 148 } 149 sql.append(wrap(table)); 150 sql.append(BRACKET_LEFT).append(fields).append(BRACKET_RIGHT); 151 sql.append(VALUES).append(BRACKET_LEFT).append(paramsOrPlaceholder).append(BRACKET_RIGHT); 152 return sql.toString(); 153 } 154 155 156 @Override 157 public String forInsertBatchWithFirstRowColumns(String schema, String tableName, List<Row> rows) { 158 StringBuilder fields = new StringBuilder(); 159 StringBuilder questions = new StringBuilder(); 160 161 Row firstRow = rows.get(0); 162 Set<String> attrs = RowCPI.getInsertAttrs(firstRow); 163 int index = 0; 164 for (String column : attrs) { 165 fields.append(wrap(column)); 166 if (index != attrs.size() - 1) { 167 fields.append(DELIMITER); 168 } 169 index++; 170 } 171 172 for (int i = 0; i < rows.size(); i++) { 173 questions.append(SqlUtil.buildSqlParamPlaceholder(attrs.size())); 174 if (i != rows.size() - 1) { 175 questions.append(DELIMITER); 176 } 177 } 178 179 String table = getRealTable(tableName, OperateType.INSERT); 180 StringBuilder sql = new StringBuilder(); 181 sql.append(INSERT_INTO); 182 if (StringUtil.isNotBlank(schema)) { 183 sql.append(wrap(getRealSchema(schema, table, OperateType.INSERT))).append(REFERENCE); 184 } 185 sql.append(wrap(table)); 186 sql.append(BLANK).append(BRACKET_LEFT) 187 .append(fields) 188 .append(BRACKET_RIGHT).append(BLANK); 189 sql.append(VALUES).append(questions); 190 return sql.toString(); 191 } 192 193 194 @Override 195 public String forDeleteById(String schema, String tableName, String[] primaryKeys) { 196 String table = getRealTable(tableName, OperateType.DELETE); 197 StringBuilder sql = new StringBuilder(); 198 sql.append(DELETE_FROM); 199 if (StringUtil.isNotBlank(schema)) { 200 sql.append(wrap(getRealSchema(schema, table, OperateType.DELETE))).append(REFERENCE); 201 } 202 sql.append(wrap(table)); 203 sql.append(WHERE); 204 for (int i = 0; i < primaryKeys.length; i++) { 205 if (i > 0) { 206 sql.append(AND); 207 } 208 sql.append(wrap(primaryKeys[i])).append(EQUALS_PLACEHOLDER); 209 } 210 prepareAuth(schema, table, sql, OperateType.DELETE); 211 return sql.toString(); 212 } 213 214 215 @Override 216 public String forDeleteBatchByIds(String schema, String tableName, String[] primaryKeys, Object[] ids) { 217 String table = getRealTable(tableName, OperateType.DELETE); 218 StringBuilder sql = new StringBuilder(); 219 sql.append(DELETE_FROM); 220 if (StringUtil.isNotBlank(schema)) { 221 sql.append(wrap(getRealSchema(schema, table, OperateType.DELETE))).append(REFERENCE); 222 } 223 224 sql.append(wrap(table)); 225 sql.append(WHERE); 226 227 // 多主键的场景 228 if (primaryKeys.length > 1) { 229 for (int i = 0; i < ids.length / primaryKeys.length; i++) { 230 if (i > 0) { 231 sql.append(OR); 232 } 233 sql.append(BRACKET_LEFT); 234 for (int j = 0; j < primaryKeys.length; j++) { 235 if (j > 0) { 236 sql.append(AND); 237 } 238 sql.append(wrap(primaryKeys[j])).append(EQUALS_PLACEHOLDER); 239 } 240 sql.append(BRACKET_RIGHT); 241 } 242 } 243 // 单主键 244 else { 245 for (int i = 0; i < ids.length; i++) { 246 if (i > 0) { 247 sql.append(OR); 248 } 249 sql.append(wrap(primaryKeys[0])).append(EQUALS_PLACEHOLDER); 250 } 251 } 252 prepareAuth(schema, table, sql, OperateType.DELETE); 253 return sql.toString(); 254 } 255 256 @Override 257 public String forDeleteByQuery(QueryWrapper queryWrapper) { 258 prepareAuth(queryWrapper, OperateType.DELETE); 259 return buildDeleteSql(queryWrapper); 260 } 261 262 @Override 263 public String forUpdateById(String schema, String tableName, Row row) { 264 String table = getRealTable(tableName, OperateType.UPDATE); 265 StringBuilder sql = new StringBuilder(); 266 Set<String> modifyAttrs = RowCPI.getModifyAttrs(row); 267 Map<String, RawValue> rawValueMap = RowCPI.getRawValueMap(row); 268 String[] primaryKeys = RowCPI.obtainsPrimaryKeyStrings(row); 269 270 sql.append(UPDATE); 271 if (StringUtil.isNotBlank(schema)) { 272 sql.append(wrap(getRealSchema(schema, table, OperateType.UPDATE))).append(REFERENCE); 273 } 274 275 sql.append(wrap(table)).append(SET); 276 int index = 0; 277 for (Map.Entry<String, Object> e : row.entrySet()) { 278 String colName = e.getKey(); 279 if (modifyAttrs.contains(colName) && !ArrayUtil.contains(primaryKeys, colName)) { 280 if (index > 0) { 281 sql.append(DELIMITER); 282 } 283 sql.append(wrap(colName)); 284 285 if (rawValueMap.containsKey(colName)) { 286 sql.append(EQUALS).append(rawValueMap.get(colName).toSql(this)); 287 } else { 288 sql.append(EQUALS_PLACEHOLDER); 289 } 290 291 index++; 292 } 293 } 294 sql.append(WHERE); 295 for (int i = 0; i < primaryKeys.length; i++) { 296 if (i > 0) { 297 sql.append(AND); 298 } 299 sql.append(wrap(primaryKeys[i])).append(EQUALS_PLACEHOLDER); 300 } 301 prepareAuth(schema, table, sql, OperateType.UPDATE); 302 return sql.toString(); 303 } 304 305 @Override 306 public String forUpdateByQuery(QueryWrapper queryWrapper, Row row) { 307 prepareAuth(queryWrapper, OperateType.UPDATE); 308 StringBuilder sqlBuilder = new StringBuilder(); 309 310 Set<String> modifyAttrs = RowCPI.getModifyAttrs(row); 311 Map<String, RawValue> rawValueMap = RowCPI.getRawValueMap(row); 312 313 List<QueryTable> queryTables = CPI.getQueryTables(queryWrapper); 314 if (queryTables == null || queryTables.size() != 1) { 315 throw FlexExceptions.wrap(LocalizedFormats.UPDATE_ONLY_SUPPORT_1_TABLE); 316 } 317 318 // fix: support schema 319 QueryTable queryTable = queryTables.get(0); 320 sqlBuilder.append(UPDATE).append(queryTable.toSql(this, OperateType.UPDATE)).append(SET); 321 int index = 0; 322 for (String modifyAttr : modifyAttrs) { 323 if (index > 0) { 324 sqlBuilder.append(DELIMITER); 325 } 326 327 sqlBuilder.append(wrap(modifyAttr)); 328 329 if (rawValueMap.containsKey(modifyAttr)) { 330 sqlBuilder.append(EQUALS).append(rawValueMap.get(modifyAttr).toSql(this)); 331 } else { 332 sqlBuilder.append(EQUALS_PLACEHOLDER); 333 } 334 335 index++; 336 } 337 338 buildJoinSql(sqlBuilder, queryWrapper, queryTables, OperateType.UPDATE); 339 buildWhereSql(sqlBuilder, queryWrapper, queryTables, false); 340 buildGroupBySql(sqlBuilder, queryWrapper, queryTables); 341 buildHavingSql(sqlBuilder, queryWrapper, queryTables); 342 343 // ignore orderBy and limit 344 buildOrderBySql(sqlBuilder, queryWrapper, queryTables); 345 346 Long limitRows = CPI.getLimitRows(queryWrapper); 347 Long limitOffset = CPI.getLimitOffset(queryWrapper); 348 if (limitRows != null || limitOffset != null) { 349 sqlBuilder = buildLimitOffsetSql(sqlBuilder, queryWrapper, limitRows, limitOffset); 350 } 351 352 return sqlBuilder.toString(); 353 } 354 355 @Override 356 public String forUpdateBatchById(String schema, String tableName, List<Row> rows) { 357 if (rows.size() == 1) { 358 return forUpdateById(schema, tableName, rows.get(0)); 359 } 360 StringBuilder sql = new StringBuilder(); 361 for (Row row : rows) { 362 sql.append(forUpdateById(schema, tableName, row)).append(SEMICOLON).append(BLANK); 363 } 364 return sql.toString(); 365 } 366 367 368 @Override 369 public String forSelectOneById(String schema, String tableName, String[] primaryKeys, Object[] primaryValues) { 370 String table = getRealTable(tableName, OperateType.SELECT); 371 StringBuilder sql = new StringBuilder(SELECT_ALL_FROM); 372 if (StringUtil.isNotBlank(schema)) { 373 sql.append(wrap(getRealSchema(schema, table, OperateType.SELECT))).append(REFERENCE); 374 } 375 sql.append(wrap(table)).append(WHERE); 376 for (int i = 0; i < primaryKeys.length; i++) { 377 if (i > 0) { 378 sql.append(AND); 379 } 380 sql.append(wrap(primaryKeys[i])).append(EQUALS_PLACEHOLDER); 381 } 382 prepareAuth(schema, table, sql, OperateType.SELECT); 383 return sql.toString(); 384 } 385 386 @Override 387 public String forSelectByQuery(QueryWrapper queryWrapper) { 388 prepareAuth(queryWrapper, OperateType.SELECT); 389 return buildSelectSql(queryWrapper); 390 } 391 392 393 ////////////build query sql/////// 394 @Override 395 public String buildSelectSql(QueryWrapper queryWrapper) { 396 List<QueryTable> queryTables = CPI.getQueryTables(queryWrapper); 397 398 List<QueryTable> joinTables = CPI.getJoinTables(queryWrapper); 399 List<QueryTable> allTables = CollectionUtil.merge(queryTables, joinTables); 400 401 List<QueryColumn> selectColumns = CPI.getSelectColumns(queryWrapper); 402 403 // 多个表,非 SELECT * 时,需要处理重名字段 404 if (allTables.size() > 1 && selectColumns != null && selectColumns.size() > 1) { 405 IntStream.range(0, selectColumns.size()) 406 .boxed() 407 // 生成 索引-字段值 对应关系 408 .collect(Collectors.toMap(Function.identity(), selectColumns::get)) 409 .entrySet() 410 .stream() 411 // 需要处理别名的情况 412 .filter(e -> StringUtil.isNotBlank(e.getValue().getName())) 413 .filter(e -> StringUtil.isBlank(e.getValue().getAlias())) 414 .filter(e -> !"*".equals(e.getValue().getName())) 415 // 将相同字段对象放在一个集合里 416 .collect(Collectors.groupingBy(e -> e.getValue().getName(), 417 Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList))) 418 .values() 419 .stream() 420 // 过滤出来重名的字段 421 .filter(e -> e.size() > 1) 422 // 合并所有需要加别名的字段 423 .flatMap(Collection::stream) 424 // 过滤出来可以添加别名的列 425 .filter(e -> e.getValue().getTable() != null) 426 .filter(e -> StringUtil.isNotBlank(e.getValue().getTable().getName())) 427 // 添加别名并放回原集合索引位置 428 .forEach(e -> selectColumns.set(e.getKey(), 429 e.getValue().as(e.getValue().getTable().getName() + "$" + e.getValue().getName()))); 430 } 431 432 StringBuilder sqlBuilder = new StringBuilder(); 433 With with = CPI.getWith(queryWrapper); 434 if (with != null) { 435 sqlBuilder.append(with.toSql(this)); 436 } 437 438 buildSelectColumnSql(sqlBuilder, allTables, selectColumns, CPI.getHint(queryWrapper)); 439 440 441 sqlBuilder.append(FROM).append(StringUtil.join(DELIMITER, queryTables, queryTable -> queryTable.toSql(this, OperateType.SELECT))); 442 443 buildJoinSql(sqlBuilder, queryWrapper, allTables, OperateType.SELECT); 444 buildWhereSql(sqlBuilder, queryWrapper, allTables, true); 445 buildGroupBySql(sqlBuilder, queryWrapper, allTables); 446 buildHavingSql(sqlBuilder, queryWrapper, allTables); 447 buildOrderBySql(sqlBuilder, queryWrapper, allTables); 448 449 List<UnionWrapper> unions = CPI.getUnions(queryWrapper); 450 if (CollectionUtil.isNotEmpty(unions)) { 451 sqlBuilder.insert(0, BRACKET_LEFT).append(BRACKET_RIGHT); 452 for (UnionWrapper unionWrapper : unions) { 453 unionWrapper.buildSql(sqlBuilder, this); 454 } 455 } 456 457 Long limitRows = CPI.getLimitRows(queryWrapper); 458 Long limitOffset = CPI.getLimitOffset(queryWrapper); 459 if (limitRows != null || limitOffset != null) { 460 sqlBuilder = buildLimitOffsetSql(sqlBuilder, queryWrapper, limitRows, limitOffset); 461 } 462 463 List<String> endFragments = CPI.getEndFragments(queryWrapper); 464 if (CollectionUtil.isNotEmpty(endFragments)) { 465 for (String endFragment : endFragments) { 466 sqlBuilder.append(BLANK).append(endFragment); 467 } 468 } 469 470 return sqlBuilder.toString(); 471 } 472 473 @Override 474 public String buildNoSelectSql(QueryWrapper queryWrapper) { 475 StringBuilder sqlBuilder = new StringBuilder(); 476 477 buildJoinSql(sqlBuilder, queryWrapper, Collections.EMPTY_LIST, OperateType.SELECT); 478 buildWhereSql(sqlBuilder, queryWrapper, Collections.EMPTY_LIST, true); 479 buildGroupBySql(sqlBuilder, queryWrapper, Collections.EMPTY_LIST); 480 buildHavingSql(sqlBuilder, queryWrapper, Collections.EMPTY_LIST); 481 buildOrderBySql(sqlBuilder, queryWrapper, Collections.EMPTY_LIST); 482 483 List<UnionWrapper> unions = CPI.getUnions(queryWrapper); 484 if (CollectionUtil.isNotEmpty(unions)) { 485 if (sqlBuilder.length() > 0) { 486 sqlBuilder.insert(0, BRACKET_LEFT).append(BRACKET_RIGHT); 487 } 488 for (UnionWrapper unionWrapper : unions) { 489 unionWrapper.buildSql(sqlBuilder, this); 490 } 491 } 492 493 Long limitRows = CPI.getLimitRows(queryWrapper); 494 Long limitOffset = CPI.getLimitOffset(queryWrapper); 495 if (limitRows != null || limitOffset != null) { 496 sqlBuilder = buildLimitOffsetSql(sqlBuilder, queryWrapper, limitRows, limitOffset); 497 } 498 499 List<String> endFragments = CPI.getEndFragments(queryWrapper); 500 if (CollectionUtil.isNotEmpty(endFragments)) { 501 for (String endFragment : endFragments) { 502 sqlBuilder.append(BLANK).append(endFragment); 503 } 504 } 505 506 return sqlBuilder.toString(); 507 } 508 509 private void buildSelectColumnSql(StringBuilder sqlBuilder, List<QueryTable> queryTables, List<QueryColumn> selectColumns, String hint) { 510 sqlBuilder.append(SELECT); 511 sqlBuilder.append(forHint(hint)); 512 if (selectColumns == null || selectColumns.isEmpty()) { 513 sqlBuilder.append(ASTERISK); 514 } else { 515 int index = 0; 516 for (QueryColumn selectColumn : selectColumns) { 517 String selectColumnSql = CPI.toSelectSql(selectColumn, queryTables, this); 518 sqlBuilder.append(selectColumnSql); 519 if (index != selectColumns.size() - 1) { 520 sqlBuilder.append(DELIMITER); 521 } 522 index++; 523 } 524 } 525 } 526 527 528 @Override 529 public String buildDeleteSql(QueryWrapper queryWrapper) { 530 List<QueryTable> queryTables = CPI.getQueryTables(queryWrapper); 531 List<QueryTable> joinTables = CPI.getJoinTables(queryWrapper); 532 List<QueryTable> allTables = CollectionUtil.merge(queryTables, joinTables); 533 534 // ignore selectColumns 535 StringBuilder sqlBuilder = new StringBuilder(DELETE); 536 String hint = CPI.getHint(queryWrapper); 537 if (StringUtil.isNotBlank(hint)) { 538 sqlBuilder.append(BLANK).append(hint).deleteCharAt(sqlBuilder.length() - 1); 539 } 540 541 // delete with join 542 if (joinTables != null && !joinTables.isEmpty()) { 543 if (queryTables == null || queryTables.isEmpty()) { 544 throw new IllegalArgumentException("Delete with join sql must designate the from table."); 545 } else if (queryTables.size() != 1) { 546 throw new IllegalArgumentException("Delete with join sql must has 1 table only. but current has " + queryTables.size()); 547 } 548 QueryTable queryTable = queryTables.get(0); 549 String table = getRealTable(queryTable.getName(), OperateType.DELETE); 550 if (StringUtil.isNotBlank(queryTable.getSchema())) { 551 sqlBuilder.append(wrap(getRealSchema(queryTable.getSchema(), table, OperateType.DELETE))).append(REFERENCE); 552 } 553 sqlBuilder.append(BLANK).append(wrap(getRealTable(table, OperateType.DELETE))); 554 } 555 556 557 sqlBuilder.append(FROM).append(StringUtil.join(DELIMITER, queryTables, queryTable -> queryTable.toSql(this, OperateType.DELETE))); 558 559 buildJoinSql(sqlBuilder, queryWrapper, allTables, OperateType.DELETE); 560 buildWhereSql(sqlBuilder, queryWrapper, allTables, false); 561 buildGroupBySql(sqlBuilder, queryWrapper, allTables); 562 buildHavingSql(sqlBuilder, queryWrapper, allTables); 563 564 // ignore orderBy and limit 565 buildOrderBySql(sqlBuilder, queryWrapper, allTables); 566 567 Long limitRows = CPI.getLimitRows(queryWrapper); 568 Long limitOffset = CPI.getLimitOffset(queryWrapper); 569 if (limitRows != null || limitOffset != null) { 570 sqlBuilder = buildLimitOffsetSql(sqlBuilder, queryWrapper, limitRows, limitOffset); 571 } 572 573 List<String> endFragments = CPI.getEndFragments(queryWrapper); 574 if (CollectionUtil.isNotEmpty(endFragments)) { 575 for (String endFragment : endFragments) { 576 sqlBuilder.append(BLANK).append(endFragment); 577 } 578 } 579 580 return sqlBuilder.toString(); 581 } 582 583 584 @Override 585 public String buildWhereConditionSql(QueryWrapper queryWrapper) { 586 QueryCondition whereQueryCondition = CPI.getWhereQueryCondition(queryWrapper); 587 return whereQueryCondition != null ? whereQueryCondition.toSql(CPI.getQueryTables(queryWrapper), this) : EMPTY; 588 } 589 590 591 @Override 592 public String forInsertEntity(TableInfo tableInfo, Object entity, boolean ignoreNulls) { 593 StringBuilder sql = new StringBuilder(); 594 sql.append(INSERT_INTO).append(tableInfo.getWrapSchemaAndTableName(this, OperateType.INSERT)); 595 596 String[] insertColumns = tableInfo.obtainInsertColumns(entity, ignoreNulls); 597 Map<String, String> onInsertColumns = tableInfo.getOnInsertColumns(); 598 599 Map<String, RawValue> rawValueMap = tableInfo.obtainUpdateRawValueMap(entity); 600 601 StringJoiner sqlFields = new StringJoiner(DELIMITER); 602 StringJoiner sqlValues = new StringJoiner(DELIMITER); 603 604 for (String insertColumn : insertColumns) { 605 sqlFields.add(wrap(insertColumn)); 606 if (rawValueMap.containsKey(insertColumn)) { 607 sqlValues.add(rawValueMap.remove(insertColumn).toSql(this)); 608 } else if (onInsertColumns != null && onInsertColumns.containsKey(insertColumn)) { 609 sqlValues.add(onInsertColumns.get(insertColumn)); 610 } else { 611 sqlValues.add(PLACEHOLDER); 612 } 613 } 614 615 rawValueMap.forEach((k, v) -> { 616 sqlFields.add(wrap(k)); 617 sqlValues.add(v.toSql(this)); 618 }); 619 620 return sql.append(BRACKET_LEFT).append(sqlFields).append(BRACKET_RIGHT) 621 .append(VALUES) 622 .append(BRACKET_LEFT).append(sqlValues).append(BRACKET_RIGHT) 623 .toString(); 624 } 625 626 627 @Override 628 public String forInsertEntityWithPk(TableInfo tableInfo, Object entity, boolean ignoreNulls) { 629 630 StringBuilder sql = new StringBuilder(); 631 sql.append(INSERT_INTO).append(tableInfo.getWrapSchemaAndTableName(this, OperateType.INSERT)); 632 633 String[] insertColumns = tableInfo.obtainInsertColumnsWithPk(entity, ignoreNulls); 634 Map<String, String> onInsertColumns = tableInfo.getOnInsertColumns(); 635 636 StringJoiner sqlFields = new StringJoiner(DELIMITER); 637 StringJoiner sqlValues = new StringJoiner(DELIMITER); 638 639 for (String insertColumn : insertColumns) { 640 sqlFields.add(wrap(insertColumn)); 641 if (onInsertColumns != null && onInsertColumns.containsKey(insertColumn)) { 642 sqlValues.add(onInsertColumns.get(insertColumn)); 643 } else { 644 sqlValues.add(PLACEHOLDER); 645 } 646 } 647 648 return sql.append(BRACKET_LEFT).append(sqlFields).append(BRACKET_RIGHT) 649 .append(VALUES) 650 .append(BRACKET_LEFT).append(sqlValues).append(BRACKET_RIGHT) 651 .toString(); 652 } 653 654 655 @Override 656 public String forInsertEntityBatch(TableInfo tableInfo, Collection<?> entities) { 657 StringBuilder sql = new StringBuilder(); 658 sql.append(INSERT_INTO).append(tableInfo.getWrapSchemaAndTableName(this, OperateType.INSERT)); 659 String[] insertColumns = tableInfo.obtainInsertColumns(null, false); 660 String[] warpedInsertColumns = new String[insertColumns.length]; 661 for (int i = 0; i < insertColumns.length; i++) { 662 warpedInsertColumns[i] = wrap(insertColumns[i]); 663 } 664 sql.append(BRACKET_LEFT) 665 .append(StringUtil.join(DELIMITER, warpedInsertColumns)) 666 .append(BRACKET_RIGHT); 667 sql.append(VALUES); 668 669 Map<String, String> onInsertColumns = tableInfo.getOnInsertColumns(); 670 for (int i = 0; i < entities.size(); i++) { 671 StringJoiner stringJoiner = new StringJoiner(DELIMITER, BRACKET_LEFT, BRACKET_RIGHT); 672 for (String insertColumn : insertColumns) { 673 if (onInsertColumns != null && onInsertColumns.containsKey(insertColumn)) { 674 // 直接读取 onInsert 配置的值,而不用 "?" 代替 675 stringJoiner.add(onInsertColumns.get(insertColumn)); 676 } else { 677 stringJoiner.add(PLACEHOLDER); 678 } 679 } 680 sql.append(stringJoiner); 681 if (i != entities.size() - 1) { 682 sql.append(DELIMITER); 683 } 684 } 685 686 return sql.toString(); 687 } 688 689 @Override 690 public String forDeleteEntityById(TableInfo tableInfo) { 691 String logicDeleteColumn = tableInfo.getLogicDeleteColumnOrSkip(); 692 Object[] tenantIdArgs = tableInfo.buildTenantIdArgs(); 693 694 // 正常删除 695 if (StringUtil.isBlank(logicDeleteColumn)) { 696 String deleteByIdSql = forDeleteById(tableInfo.getSchema(), tableInfo.getTableName(), tableInfo.getPrimaryColumns()); 697 return tableInfo.buildTenantCondition(deleteByIdSql, tenantIdArgs, this); 698 } 699 700 // 逻辑删除 701 StringBuilder sql = new StringBuilder(); 702 String[] primaryKeys = tableInfo.getPrimaryColumns(); 703 704 sql.append(UPDATE).append(tableInfo.getWrapSchemaAndTableName(this, OperateType.UPDATE)); 705 sql.append(SET).append(buildLogicDeletedSet(logicDeleteColumn, tableInfo)); 706 sql.append(WHERE); 707 for (int i = 0; i < primaryKeys.length; i++) { 708 if (i > 0) { 709 sql.append(AND); 710 } 711 sql.append(wrap(primaryKeys[i])).append(EQUALS_PLACEHOLDER); 712 } 713 714 sql.append(AND).append(buildLogicNormalCondition(logicDeleteColumn, tableInfo)); 715 716 // 租户ID 717 tableInfo.buildTenantCondition(sql, tenantIdArgs, this); 718 prepareAuth(tableInfo, sql, OperateType.DELETE); 719 return sql.toString(); 720 } 721 722 723 @Override 724 public String forDeleteEntityBatchByIds(TableInfo tableInfo, Object[] primaryValues) { 725 String logicDeleteColumn = tableInfo.getLogicDeleteColumnOrSkip(); 726 Object[] tenantIdArgs = tableInfo.buildTenantIdArgs(); 727 728 // 正常删除 729 if (StringUtil.isBlank(logicDeleteColumn)) { 730 String deleteSQL = forDeleteBatchByIds(tableInfo.getSchema(), tableInfo.getTableName(), tableInfo.getPrimaryColumns(), primaryValues); 731 732 // 多租户 733 if (ArrayUtil.isNotEmpty(tenantIdArgs)) { 734 deleteSQL = deleteSQL.replace(WHERE, WHERE + BRACKET_LEFT) + BRACKET_RIGHT; 735 deleteSQL = tableInfo.buildTenantCondition(deleteSQL, tenantIdArgs, this); 736 } 737 return deleteSQL; 738 } 739 740 StringBuilder sql = new StringBuilder(); 741 sql.append(UPDATE); 742 sql.append(tableInfo.getWrapSchemaAndTableName(this, OperateType.UPDATE)); 743 sql.append(SET).append(buildLogicDeletedSet(logicDeleteColumn, tableInfo)); 744 sql.append(WHERE); 745 sql.append(BRACKET_LEFT); 746 747 String[] primaryKeys = tableInfo.getPrimaryColumns(); 748 749 // 多主键的场景 750 if (primaryKeys.length > 1) { 751 for (int i = 0; i < primaryValues.length / primaryKeys.length; i++) { 752 if (i > 0) { 753 sql.append(OR); 754 } 755 sql.append(BRACKET_LEFT); 756 for (int j = 0; j < primaryKeys.length; j++) { 757 if (j > 0) { 758 sql.append(AND); 759 } 760 sql.append(wrap(primaryKeys[j])).append(EQUALS_PLACEHOLDER); 761 } 762 sql.append(BRACKET_RIGHT); 763 } 764 } 765 // 单主键 766 else { 767 for (int i = 0; i < primaryValues.length; i++) { 768 if (i > 0) { 769 sql.append(OR); 770 } 771 sql.append(wrap(primaryKeys[0])).append(EQUALS_PLACEHOLDER); 772 } 773 } 774 775 sql.append(BRACKET_RIGHT).append(AND).append(buildLogicNormalCondition(logicDeleteColumn, tableInfo)); 776 777 tableInfo.buildTenantCondition(sql, tenantIdArgs, this); 778 prepareAuth(tableInfo, sql, OperateType.DELETE); 779 return sql.toString(); 780 } 781 782 @Override 783 public String forDeleteEntityBatchByQuery(TableInfo tableInfo, QueryWrapper queryWrapper) { 784 785 String logicDeleteColumn = tableInfo.getLogicDeleteColumnOrSkip(); 786 787 // 正常删除 788 if (StringUtil.isBlank(logicDeleteColumn)) { 789 return forDeleteByQuery(queryWrapper); 790 } 791 792 793 prepareAuth(queryWrapper, OperateType.DELETE); 794 // 逻辑删除 795 List<QueryTable> queryTables = CPI.getQueryTables(queryWrapper); 796 List<QueryTable> joinTables = CPI.getJoinTables(queryWrapper); 797 List<QueryTable> allTables = CollectionUtil.merge(queryTables, joinTables); 798 799 // ignore selectColumns 800 StringBuilder sqlBuilder = new StringBuilder(UPDATE).append(forHint(CPI.getHint(queryWrapper))); 801 sqlBuilder.append(tableInfo.getWrapSchemaAndTableName(this, OperateType.DELETE)); 802 sqlBuilder.append(SET).append(buildLogicDeletedSet(logicDeleteColumn, tableInfo)); 803 804 805 buildJoinSql(sqlBuilder, queryWrapper, allTables, OperateType.DELETE); 806 buildWhereSql(sqlBuilder, queryWrapper, allTables, false); 807 buildGroupBySql(sqlBuilder, queryWrapper, allTables); 808 buildHavingSql(sqlBuilder, queryWrapper, allTables); 809 810 // ignore orderBy and limit 811 // buildOrderBySql(sqlBuilder, queryWrapper) 812 // buildLimitSql(sqlBuilder, queryWrapper) 813 814 return sqlBuilder.toString(); 815 } 816 817 818 @Override 819 public String forUpdateEntity(TableInfo tableInfo, Object entity, boolean ignoreNulls) { 820 StringBuilder sql = new StringBuilder(); 821 822 Set<String> updateColumns = tableInfo.obtainUpdateColumns(entity, ignoreNulls, false); 823 Map<String, RawValue> rawValueMap = tableInfo.obtainUpdateRawValueMap(entity); 824 String[] primaryKeys = tableInfo.getPrimaryColumns(); 825 826 sql.append(UPDATE).append(tableInfo.getWrapSchemaAndTableName(this, OperateType.UPDATE)).append(SET); 827 828 StringJoiner stringJoiner = new StringJoiner(DELIMITER); 829 830 for (String updateColumn : updateColumns) { 831 if (rawValueMap.containsKey(updateColumn)) { 832 stringJoiner.add(wrap(updateColumn) + EQUALS + rawValueMap.get(updateColumn).toSql(this)); 833 } else { 834 stringJoiner.add(wrap(updateColumn) + EQUALS_PLACEHOLDER); 835 } 836 } 837 838 Map<String, String> onUpdateColumns = tableInfo.getOnUpdateColumns(); 839 if (onUpdateColumns != null && !onUpdateColumns.isEmpty()) { 840 onUpdateColumns.forEach((column, value) -> stringJoiner.add(wrap(column) + EQUALS + value)); 841 } 842 843 // 乐观锁字段 844 String versionColumn = tableInfo.getVersionColumn(); 845 if (StringUtil.isNotBlank(tableInfo.getOptimisticLockColumnOrSkip())) { 846 stringJoiner.add(wrap(versionColumn) + EQUALS + wrap(versionColumn) + " + 1 "); 847 } 848 849 sql.append(stringJoiner); 850 851 sql.append(WHERE); 852 for (int i = 0; i < primaryKeys.length; i++) { 853 if (i > 0) { 854 sql.append(AND); 855 } 856 sql.append(wrap(primaryKeys[i])).append(EQUALS_PLACEHOLDER); 857 } 858 859 // 逻辑删除条件,已删除的数据不能被修改 860 String logicDeleteColumn = tableInfo.getLogicDeleteColumnOrSkip(); 861 if (StringUtil.isNotBlank(logicDeleteColumn)) { 862 sql.append(AND).append(buildLogicNormalCondition(logicDeleteColumn, tableInfo)); 863 } 864 865 866 // 租户ID字段 867 Object[] tenantIdArgs = tableInfo.buildTenantIdArgs(); 868 tableInfo.buildTenantCondition(sql, tenantIdArgs, this); 869 870 // 乐观锁条件 871 if (StringUtil.isNotBlank(tableInfo.getOptimisticLockColumnOrSkip())) { 872 Object versionValue = tableInfo.buildColumnSqlArg(entity, versionColumn); 873 if (versionValue == null) { 874 throw FlexExceptions.wrap(LocalizedFormats.ENTITY_VERSION_NULL, entity); 875 } 876 sql.append(AND).append(wrap(versionColumn)).append(EQUALS).append(versionValue); 877 } 878 879 prepareAuth(tableInfo, sql, OperateType.UPDATE); 880 return sql.toString(); 881 } 882 883 @Override 884 public String forUpdateEntityByQuery(TableInfo tableInfo, Object entity, boolean ignoreNulls, QueryWrapper queryWrapper) { 885 prepareAuth(queryWrapper, OperateType.UPDATE); 886 StringBuilder sqlBuilder = new StringBuilder(); 887 888 Set<String> updateColumns = tableInfo.obtainUpdateColumns(entity, ignoreNulls, true); 889 Map<String, RawValue> rawValueMap = tableInfo.obtainUpdateRawValueMap(entity); 890 891 sqlBuilder.append(UPDATE).append(forHint(CPI.getHint(queryWrapper))); 892 sqlBuilder.append(tableInfo.getWrapSchemaAndTableName(this, OperateType.UPDATE)); 893 894 List<QueryTable> queryTables = CPI.getQueryTables(queryWrapper); 895 List<QueryTable> joinTables = CPI.getJoinTables(queryWrapper); 896 List<QueryTable> allTables = CollectionUtil.merge(queryTables, joinTables); 897 buildJoinSql(sqlBuilder, queryWrapper, allTables, OperateType.UPDATE); 898 899 900 sqlBuilder.append(SET); 901 902 StringJoiner stringJoiner = new StringJoiner(DELIMITER); 903 904 for (String modifyAttr : updateColumns) { 905 if (rawValueMap.containsKey(modifyAttr)) { 906 stringJoiner.add(wrap(modifyAttr) + EQUALS + rawValueMap.get(modifyAttr).toSql(this)); 907 } else { 908 stringJoiner.add(wrap(modifyAttr) + EQUALS_PLACEHOLDER); 909 } 910 } 911 912 913 Map<String, String> onUpdateColumns = tableInfo.getOnUpdateColumns(); 914 if (onUpdateColumns != null && !onUpdateColumns.isEmpty()) { 915 onUpdateColumns.forEach((column, value) -> stringJoiner.add(wrap(column) + EQUALS + value)); 916 } 917 918 // 乐观锁字段 919 String versionColumn = tableInfo.getVersionColumn(); 920 if (StringUtil.isNotBlank(tableInfo.getOptimisticLockColumnOrSkip())) { 921 stringJoiner.add(wrap(versionColumn) + EQUALS + wrap(versionColumn) + " + 1 "); 922 } 923 924 sqlBuilder.append(stringJoiner); 925 926 927 buildWhereSql(sqlBuilder, queryWrapper, queryTables, false); 928 buildGroupBySql(sqlBuilder, queryWrapper, queryTables); 929 buildHavingSql(sqlBuilder, queryWrapper, queryTables); 930 931 // ignore orderBy and limit 932 buildOrderBySql(sqlBuilder, queryWrapper, queryTables); 933 934 Long limitRows = CPI.getLimitRows(queryWrapper); 935 Long limitOffset = CPI.getLimitOffset(queryWrapper); 936 if (limitRows != null || limitOffset != null) { 937 sqlBuilder = buildLimitOffsetSql(sqlBuilder, queryWrapper, limitRows, limitOffset); 938 } 939 940 941 List<String> endFragments = CPI.getEndFragments(queryWrapper); 942 if (CollectionUtil.isNotEmpty(endFragments)) { 943 for (String endFragment : endFragments) { 944 sqlBuilder.append(BLANK).append(endFragment); 945 } 946 } 947 948 return sqlBuilder.toString(); 949 } 950 951 952 @Override 953 public String forSelectOneEntityById(TableInfo tableInfo) { 954 StringBuilder sql = new StringBuilder(); 955 buildSelectColumnSql(sql, null, null, null); 956 sql.append(FROM).append(tableInfo.getWrapSchemaAndTableName(this, OperateType.SELECT)); 957 sql.append(WHERE); 958 String[] pKeys = tableInfo.getPrimaryColumns(); 959 for (int i = 0; i < pKeys.length; i++) { 960 if (i > 0) { 961 sql.append(AND); 962 } 963 sql.append(wrap(pKeys[i])).append(EQUALS_PLACEHOLDER); 964 } 965 966 // 逻辑删除的情况下,需要添加逻辑删除的条件 967 String logicDeleteColumn = tableInfo.getLogicDeleteColumnOrSkip(); 968 if (StringUtil.isNotBlank(logicDeleteColumn)) { 969 sql.append(AND).append(buildLogicNormalCondition(logicDeleteColumn, tableInfo)); 970 } 971 972 // 多租户 973 Object[] tenantIdArgs = tableInfo.buildTenantIdArgs(); 974 tableInfo.buildTenantCondition(sql, tenantIdArgs, this); 975 prepareAuth(tableInfo, sql, OperateType.SELECT); 976 return sql.toString(); 977 } 978 979 980 @Override 981 public String forSelectEntityListByIds(TableInfo tableInfo, Object[] primaryValues) { 982 StringBuilder sql = new StringBuilder(); 983 buildSelectColumnSql(sql, null, tableInfo.getDefaultQueryColumn(), null); 984 sql.append(FROM).append(tableInfo.getWrapSchemaAndTableName(this, OperateType.SELECT)); 985 sql.append(WHERE); 986 String[] primaryKeys = tableInfo.getPrimaryColumns(); 987 988 String logicDeleteColumn = tableInfo.getLogicDeleteColumnOrSkip(); 989 Object[] tenantIdArgs = tableInfo.buildTenantIdArgs(); 990 if (StringUtil.isNotBlank(logicDeleteColumn) || ArrayUtil.isNotEmpty(tenantIdArgs)) { 991 sql.append(BRACKET_LEFT); 992 } 993 994 // 多主键的场景 995 if (primaryKeys.length > 1) { 996 for (int i = 0; i < primaryValues.length / primaryKeys.length; i++) { 997 if (i > 0) { 998 sql.append(OR); 999 } 1000 sql.append(BRACKET_LEFT); 1001 for (int j = 0; j < primaryKeys.length; j++) { 1002 if (j > 0) { 1003 sql.append(AND); 1004 } 1005 sql.append(wrap(primaryKeys[j])).append(EQUALS_PLACEHOLDER); 1006 } 1007 sql.append(BRACKET_RIGHT); 1008 } 1009 } 1010 // 单主键 1011 else { 1012 for (int i = 0; i < primaryValues.length; i++) { 1013 if (i > 0) { 1014 sql.append(OR); 1015 } 1016 sql.append(wrap(primaryKeys[0])).append(EQUALS_PLACEHOLDER); 1017 } 1018 } 1019 1020 if (StringUtil.isNotBlank(logicDeleteColumn) || ArrayUtil.isNotEmpty(tenantIdArgs)) { 1021 sql.append(BRACKET_RIGHT); 1022 } 1023 1024 1025 if (StringUtil.isNotBlank(logicDeleteColumn)) { 1026 sql.append(AND).append(buildLogicNormalCondition(logicDeleteColumn, tableInfo)); 1027 } 1028 1029 // 多租户 1030 tableInfo.buildTenantCondition(sql, tenantIdArgs, this); 1031 prepareAuth(tableInfo, sql, OperateType.SELECT); 1032 return sql.toString(); 1033 } 1034 1035 1036 protected boolean buildJoinSql(StringBuilder sqlBuilder, QueryWrapper queryWrapper, List<QueryTable> queryTables, OperateType operateType) { 1037 List<Join> joins = CPI.getJoins(queryWrapper); 1038 boolean joinSuccess = false; 1039 if (joins != null && !joins.isEmpty()) { 1040 for (Join join : joins) { 1041 if (!join.checkEffective()) { 1042 continue; 1043 } 1044 sqlBuilder.append(join.toSql(queryTables, this, operateType)); 1045 joinSuccess = true; 1046 } 1047 } 1048 return joinSuccess; 1049 } 1050 1051 1052 protected void buildWhereSql(StringBuilder sqlBuilder, QueryWrapper queryWrapper, List<QueryTable> queryTables, boolean allowNoCondition) { 1053 QueryCondition whereQueryCondition = CPI.getWhereQueryCondition(queryWrapper); 1054 if (whereQueryCondition != null) { 1055 String whereSql = whereQueryCondition.toSql(queryTables, this); 1056 if (StringUtil.isNotBlank(whereSql)) { 1057 sqlBuilder.append(WHERE).append(whereSql); 1058 } else if (!allowNoCondition) { 1059 throw FlexExceptions.wrap(LocalizedFormats.UPDATE_OR_DELETE_NOT_ALLOW); 1060 } 1061 } else { 1062 // whereQueryCondition == null 1063 if (!allowNoCondition) { 1064 throw FlexExceptions.wrap(LocalizedFormats.UPDATE_OR_DELETE_NOT_ALLOW); 1065 } 1066 } 1067 } 1068 1069 1070 protected void buildGroupBySql(StringBuilder sqlBuilder, QueryWrapper queryWrapper, List<QueryTable> queryTables) { 1071 List<QueryColumn> groupByColumns = CPI.getGroupByColumns(queryWrapper); 1072 if (groupByColumns != null && !groupByColumns.isEmpty()) { 1073 sqlBuilder.append(GROUP_BY); 1074 int index = 0; 1075 for (QueryColumn groupByColumn : groupByColumns) { 1076 String groupBy = CPI.toConditionSql(groupByColumn, queryTables, this); 1077 sqlBuilder.append(groupBy); 1078 if (index != groupByColumns.size() - 1) { 1079 sqlBuilder.append(DELIMITER); 1080 } 1081 index++; 1082 } 1083 } 1084 } 1085 1086 1087 protected void buildHavingSql(StringBuilder sqlBuilder, QueryWrapper queryWrapper, List<QueryTable> queryTables) { 1088 QueryCondition havingQueryCondition = CPI.getHavingQueryCondition(queryWrapper); 1089 if (havingQueryCondition != null) { 1090 String havingSql = havingQueryCondition.toSql(queryTables, this); 1091 if (StringUtil.isNotBlank(havingSql)) { 1092 sqlBuilder.append(HAVING).append(havingSql); 1093 } 1094 } 1095 } 1096 1097 1098 protected void buildOrderBySql(StringBuilder sqlBuilder, QueryWrapper queryWrapper, List<QueryTable> queryTables) { 1099 List<QueryOrderBy> orderBys = CPI.getOrderBys(queryWrapper); 1100 if (orderBys != null && !orderBys.isEmpty()) { 1101 sqlBuilder.append(ORDER_BY); 1102 int index = 0; 1103 for (QueryOrderBy orderBy : orderBys) { 1104 sqlBuilder.append(orderBy.toSql(queryTables, this)); 1105 if (index != orderBys.size() - 1) { 1106 sqlBuilder.append(DELIMITER); 1107 } 1108 index++; 1109 } 1110 } 1111 } 1112 1113 1114 /** 1115 * 构建 limit 和 offset 的参数 1116 */ 1117 protected StringBuilder buildLimitOffsetSql(StringBuilder sqlBuilder, QueryWrapper queryWrapper, Long limitRows, Long limitOffset) { 1118 return limitOffsetProcessor.process(this, sqlBuilder, queryWrapper, limitRows, limitOffset); 1119 } 1120 1121 1122 protected String buildLogicNormalCondition(String logicColumn, TableInfo tableInfo) { 1123 return LogicDeleteManager.getProcessor().buildLogicNormalCondition(logicColumn, tableInfo, this); 1124 } 1125 1126 1127 protected String buildLogicDeletedSet(String logicColumn, TableInfo tableInfo) { 1128 return LogicDeleteManager.getProcessor().buildLogicDeletedSet(logicColumn, tableInfo, this); 1129 } 1130 1131 1132}