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.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); 144 StringBuilder sql = new StringBuilder(); 145 sql.append(INSERT_INTO); 146 if (StringUtil.isNotBlank(schema)) { 147 sql.append(wrap(getRealSchema(schema, table))).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); 180 StringBuilder sql = new StringBuilder(); 181 sql.append(INSERT_INTO); 182 if (StringUtil.isNotBlank(schema)) { 183 sql.append(wrap(getRealSchema(schema, table))).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); 197 StringBuilder sql = new StringBuilder(); 198 sql.append(DELETE_FROM); 199 if (StringUtil.isNotBlank(schema)) { 200 sql.append(wrap(getRealSchema(schema, table))).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); 218 StringBuilder sql = new StringBuilder(); 219 sql.append(DELETE_FROM); 220 if (StringUtil.isNotBlank(schema)) { 221 sql.append(wrap(getRealSchema(schema, table))).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); 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))).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)).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); 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); 371 StringBuilder sql = new StringBuilder(SELECT_ALL_FROM); 372 if (StringUtil.isNotBlank(schema)) { 373 sql.append(wrap(getRealSchema(schema, table))).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))); 442 443 buildJoinSql(sqlBuilder, queryWrapper, allTables); 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); 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()); 550 if (StringUtil.isNotBlank(queryTable.getSchema())) { 551 sqlBuilder.append(wrap(getRealSchema(queryTable.getSchema(), table))).append(REFERENCE); 552 } 553 sqlBuilder.append(BLANK).append(wrap(getRealTable(table))); 554 } 555 556 557 sqlBuilder.append(FROM).append(StringUtil.join(DELIMITER, queryTables, queryTable -> queryTable.toSql(this))); 558 559 buildJoinSql(sqlBuilder, queryWrapper, allTables); 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)); 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.get(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 return sql.append(BRACKET_LEFT).append(sqlFields).append(BRACKET_RIGHT) 616 .append(VALUES) 617 .append(BRACKET_LEFT).append(sqlValues).append(BRACKET_RIGHT) 618 .toString(); 619 } 620 621 622 @Override 623 public String forInsertEntityWithPk(TableInfo tableInfo, Object entity, boolean ignoreNulls) { 624 625 StringBuilder sql = new StringBuilder(); 626 sql.append(INSERT_INTO).append(tableInfo.getWrapSchemaAndTableName(this)); 627 628 String[] insertColumns = tableInfo.obtainInsertColumnsWithPk(entity, ignoreNulls); 629 Map<String, String> onInsertColumns = tableInfo.getOnInsertColumns(); 630 631 StringJoiner sqlFields = new StringJoiner(DELIMITER); 632 StringJoiner sqlValues = new StringJoiner(DELIMITER); 633 634 for (String insertColumn : insertColumns) { 635 sqlFields.add(wrap(insertColumn)); 636 if (onInsertColumns != null && onInsertColumns.containsKey(insertColumn)) { 637 sqlValues.add(onInsertColumns.get(insertColumn)); 638 } else { 639 sqlValues.add(PLACEHOLDER); 640 } 641 } 642 643 return sql.append(BRACKET_LEFT).append(sqlFields).append(BRACKET_RIGHT) 644 .append(VALUES) 645 .append(BRACKET_LEFT).append(sqlValues).append(BRACKET_RIGHT) 646 .toString(); 647 } 648 649 650 @Override 651 public String forInsertEntityBatch(TableInfo tableInfo, List<?> entities) { 652 StringBuilder sql = new StringBuilder(); 653 sql.append(INSERT_INTO).append(tableInfo.getWrapSchemaAndTableName(this)); 654 String[] insertColumns = tableInfo.obtainInsertColumns(null, false); 655 String[] warpedInsertColumns = new String[insertColumns.length]; 656 for (int i = 0; i < insertColumns.length; i++) { 657 warpedInsertColumns[i] = wrap(insertColumns[i]); 658 } 659 sql.append(BRACKET_LEFT) 660 .append(StringUtil.join(DELIMITER, warpedInsertColumns)) 661 .append(BRACKET_RIGHT); 662 sql.append(VALUES); 663 664 Map<String, String> onInsertColumns = tableInfo.getOnInsertColumns(); 665 for (int i = 0; i < entities.size(); i++) { 666 StringJoiner stringJoiner = new StringJoiner(DELIMITER, BRACKET_LEFT, BRACKET_RIGHT); 667 for (String insertColumn : insertColumns) { 668 if (onInsertColumns != null && onInsertColumns.containsKey(insertColumn)) { 669 //直接读取 onInsert 配置的值,而不用 "?" 代替 670 stringJoiner.add(onInsertColumns.get(insertColumn)); 671 } else { 672 stringJoiner.add(PLACEHOLDER); 673 } 674 } 675 sql.append(stringJoiner); 676 if (i != entities.size() - 1) { 677 sql.append(DELIMITER); 678 } 679 } 680 681 return sql.toString(); 682 } 683 684 @Override 685 public String forDeleteEntityById(TableInfo tableInfo) { 686 String logicDeleteColumn = tableInfo.getLogicDeleteColumnOrSkip(); 687 Object[] tenantIdArgs = tableInfo.buildTenantIdArgs(); 688 689 //正常删除 690 if (StringUtil.isBlank(logicDeleteColumn)) { 691 String deleteByIdSql = forDeleteById(tableInfo.getSchema(), tableInfo.getTableName(), tableInfo.getPrimaryColumns()); 692 return tableInfo.buildTenantCondition(deleteByIdSql, tenantIdArgs, this); 693 } 694 695 //逻辑删除 696 StringBuilder sql = new StringBuilder(); 697 String[] primaryKeys = tableInfo.getPrimaryColumns(); 698 699 sql.append(UPDATE).append(tableInfo.getWrapSchemaAndTableName(this)); 700 sql.append(SET).append(buildLogicDeletedSet(logicDeleteColumn, tableInfo)); 701 sql.append(WHERE); 702 for (int i = 0; i < primaryKeys.length; i++) { 703 if (i > 0) { 704 sql.append(AND); 705 } 706 sql.append(wrap(primaryKeys[i])).append(EQUALS_PLACEHOLDER); 707 } 708 709 sql.append(AND).append(buildLogicNormalCondition(logicDeleteColumn, tableInfo)); 710 711 //租户ID 712 tableInfo.buildTenantCondition(sql, tenantIdArgs, this); 713 prepareAuth(tableInfo, sql, OperateType.DELETE); 714 return sql.toString(); 715 } 716 717 718 @Override 719 public String forDeleteEntityBatchByIds(TableInfo tableInfo, Object[] primaryValues) { 720 String logicDeleteColumn = tableInfo.getLogicDeleteColumnOrSkip(); 721 Object[] tenantIdArgs = tableInfo.buildTenantIdArgs(); 722 723 //正常删除 724 if (StringUtil.isBlank(logicDeleteColumn)) { 725 String deleteSQL = forDeleteBatchByIds(tableInfo.getSchema(), tableInfo.getTableName(), tableInfo.getPrimaryColumns(), primaryValues); 726 727 //多租户 728 if (ArrayUtil.isNotEmpty(tenantIdArgs)) { 729 deleteSQL = deleteSQL.replace(WHERE, WHERE + BRACKET_LEFT) + BRACKET_RIGHT; 730 deleteSQL = tableInfo.buildTenantCondition(deleteSQL, tenantIdArgs, this); 731 } 732 return deleteSQL; 733 } 734 735 StringBuilder sql = new StringBuilder(); 736 sql.append(UPDATE); 737 sql.append(tableInfo.getWrapSchemaAndTableName(this)); 738 sql.append(SET).append(buildLogicDeletedSet(logicDeleteColumn, tableInfo)); 739 sql.append(WHERE); 740 sql.append(BRACKET_LEFT); 741 742 String[] primaryKeys = tableInfo.getPrimaryColumns(); 743 744 //多主键的场景 745 if (primaryKeys.length > 1) { 746 for (int i = 0; i < primaryValues.length / primaryKeys.length; i++) { 747 if (i > 0) { 748 sql.append(OR); 749 } 750 sql.append(BRACKET_LEFT); 751 for (int j = 0; j < primaryKeys.length; j++) { 752 if (j > 0) { 753 sql.append(AND); 754 } 755 sql.append(wrap(primaryKeys[j])).append(EQUALS_PLACEHOLDER); 756 } 757 sql.append(BRACKET_RIGHT); 758 } 759 } 760 // 单主键 761 else { 762 for (int i = 0; i < primaryValues.length; i++) { 763 if (i > 0) { 764 sql.append(OR); 765 } 766 sql.append(wrap(primaryKeys[0])).append(EQUALS_PLACEHOLDER); 767 } 768 } 769 770 sql.append(BRACKET_RIGHT).append(AND).append(buildLogicNormalCondition(logicDeleteColumn, tableInfo)); 771 772 tableInfo.buildTenantCondition(sql, tenantIdArgs, this); 773 prepareAuth(tableInfo, sql, OperateType.DELETE); 774 return sql.toString(); 775 } 776 777 @Override 778 public String forDeleteEntityBatchByQuery(TableInfo tableInfo, QueryWrapper queryWrapper) { 779 780 String logicDeleteColumn = tableInfo.getLogicDeleteColumnOrSkip(); 781 782 //正常删除 783 if (StringUtil.isBlank(logicDeleteColumn)) { 784 return forDeleteByQuery(queryWrapper); 785 } 786 787 788 prepareAuth(queryWrapper, OperateType.DELETE); 789 //逻辑删除 790 List<QueryTable> queryTables = CPI.getQueryTables(queryWrapper); 791 List<QueryTable> joinTables = CPI.getJoinTables(queryWrapper); 792 List<QueryTable> allTables = CollectionUtil.merge(queryTables, joinTables); 793 794 //ignore selectColumns 795 StringBuilder sqlBuilder = new StringBuilder(UPDATE).append(forHint(CPI.getHint(queryWrapper))); 796 sqlBuilder.append(tableInfo.getWrapSchemaAndTableName(this)); 797 sqlBuilder.append(SET).append(buildLogicDeletedSet(logicDeleteColumn, tableInfo)); 798 799 800 buildJoinSql(sqlBuilder, queryWrapper, allTables); 801 buildWhereSql(sqlBuilder, queryWrapper, allTables, false); 802 buildGroupBySql(sqlBuilder, queryWrapper, allTables); 803 buildHavingSql(sqlBuilder, queryWrapper, allTables); 804 805 //ignore orderBy and limit 806 //buildOrderBySql(sqlBuilder, queryWrapper) 807 //buildLimitSql(sqlBuilder, queryWrapper) 808 809 return sqlBuilder.toString(); 810 } 811 812 813 @Override 814 public String forUpdateEntity(TableInfo tableInfo, Object entity, boolean ignoreNulls) { 815 StringBuilder sql = new StringBuilder(); 816 817 Set<String> updateColumns = tableInfo.obtainUpdateColumns(entity, ignoreNulls, false); 818 Map<String, RawValue> rawValueMap = tableInfo.obtainUpdateRawValueMap(entity); 819 String[] primaryKeys = tableInfo.getPrimaryColumns(); 820 821 sql.append(UPDATE).append(tableInfo.getWrapSchemaAndTableName(this)).append(SET); 822 823 StringJoiner stringJoiner = new StringJoiner(DELIMITER); 824 825 for (String updateColumn : updateColumns) { 826 if (rawValueMap.containsKey(updateColumn)) { 827 stringJoiner.add(wrap(updateColumn) + EQUALS + rawValueMap.get(updateColumn).toSql(this)); 828 } else { 829 stringJoiner.add(wrap(updateColumn) + EQUALS_PLACEHOLDER); 830 } 831 } 832 833 Map<String, String> onUpdateColumns = tableInfo.getOnUpdateColumns(); 834 if (onUpdateColumns != null && !onUpdateColumns.isEmpty()) { 835 onUpdateColumns.forEach((column, value) -> stringJoiner.add(wrap(column) + EQUALS + value)); 836 } 837 838 //乐观锁字段 839 String versionColumn = tableInfo.getVersionColumn(); 840 if (StringUtil.isNotBlank(versionColumn)) { 841 stringJoiner.add(wrap(versionColumn) + EQUALS + wrap(versionColumn) + " + 1 "); 842 } 843 844 sql.append(stringJoiner); 845 846 sql.append(WHERE); 847 for (int i = 0; i < primaryKeys.length; i++) { 848 if (i > 0) { 849 sql.append(AND); 850 } 851 sql.append(wrap(primaryKeys[i])).append(EQUALS_PLACEHOLDER); 852 } 853 854 //逻辑删除条件,已删除的数据不能被修改 855 String logicDeleteColumn = tableInfo.getLogicDeleteColumnOrSkip(); 856 if (StringUtil.isNotBlank(logicDeleteColumn)) { 857 sql.append(AND).append(buildLogicNormalCondition(logicDeleteColumn, tableInfo)); 858 } 859 860 861 //租户ID字段 862 Object[] tenantIdArgs = tableInfo.buildTenantIdArgs(); 863 tableInfo.buildTenantCondition(sql, tenantIdArgs, this); 864 865 //乐观锁条件 866 if (StringUtil.isNotBlank(versionColumn)) { 867 Object versionValue = tableInfo.buildColumnSqlArg(entity, versionColumn); 868 if (versionValue == null) { 869 throw FlexExceptions.wrap(LocalizedFormats.ENTITY_VERSION_NULL, entity); 870 } 871 sql.append(AND).append(wrap(versionColumn)).append(EQUALS).append(versionValue); 872 } 873 874 prepareAuth(tableInfo, sql, OperateType.UPDATE); 875 return sql.toString(); 876 } 877 878 @Override 879 public String forUpdateEntityByQuery(TableInfo tableInfo, Object entity, boolean ignoreNulls, QueryWrapper queryWrapper) { 880 prepareAuth(queryWrapper, OperateType.UPDATE); 881 StringBuilder sqlBuilder = new StringBuilder(); 882 883 Set<String> updateColumns = tableInfo.obtainUpdateColumns(entity, ignoreNulls, true); 884 Map<String, RawValue> rawValueMap = tableInfo.obtainUpdateRawValueMap(entity); 885 886 sqlBuilder.append(UPDATE).append(forHint(CPI.getHint(queryWrapper))); 887 sqlBuilder.append(tableInfo.getWrapSchemaAndTableName(this)); 888 889 List<QueryTable> queryTables = CPI.getQueryTables(queryWrapper); 890 buildJoinSql(sqlBuilder, queryWrapper, queryTables); 891 892 893 sqlBuilder.append(SET); 894 895 StringJoiner stringJoiner = new StringJoiner(DELIMITER); 896 897 for (String modifyAttr : updateColumns) { 898 if (rawValueMap.containsKey(modifyAttr)) { 899 stringJoiner.add(wrap(modifyAttr) + EQUALS + rawValueMap.get(modifyAttr).toSql(this)); 900 } else { 901 stringJoiner.add(wrap(modifyAttr) + EQUALS_PLACEHOLDER); 902 } 903 } 904 905 906 Map<String, String> onUpdateColumns = tableInfo.getOnUpdateColumns(); 907 if (onUpdateColumns != null && !onUpdateColumns.isEmpty()) { 908 onUpdateColumns.forEach((column, value) -> stringJoiner.add(wrap(column) + EQUALS + value)); 909 } 910 911 //乐观锁字段 912 String versionColumn = tableInfo.getVersionColumn(); 913 if (StringUtil.isNotBlank(versionColumn)) { 914 stringJoiner.add(wrap(versionColumn) + EQUALS + wrap(versionColumn) + " + 1 "); 915 } 916 917 sqlBuilder.append(stringJoiner); 918 919 920 buildWhereSql(sqlBuilder, queryWrapper, queryTables, false); 921 buildGroupBySql(sqlBuilder, queryWrapper, queryTables); 922 buildHavingSql(sqlBuilder, queryWrapper, queryTables); 923 924 //ignore orderBy and limit 925 buildOrderBySql(sqlBuilder, queryWrapper, queryTables); 926 927 Long limitRows = CPI.getLimitRows(queryWrapper); 928 Long limitOffset = CPI.getLimitOffset(queryWrapper); 929 if (limitRows != null || limitOffset != null) { 930 sqlBuilder = buildLimitOffsetSql(sqlBuilder, queryWrapper, limitRows, limitOffset); 931 } 932 933 934 List<String> endFragments = CPI.getEndFragments(queryWrapper); 935 if (CollectionUtil.isNotEmpty(endFragments)) { 936 for (String endFragment : endFragments) { 937 sqlBuilder.append(BLANK).append(endFragment); 938 } 939 } 940 941 return sqlBuilder.toString(); 942 } 943 944 945 @Override 946 public String forSelectOneEntityById(TableInfo tableInfo) { 947 StringBuilder sql = new StringBuilder(); 948 buildSelectColumnSql(sql, null, null, null); 949 sql.append(FROM).append(tableInfo.getWrapSchemaAndTableName(this)); 950 sql.append(WHERE); 951 String[] pKeys = tableInfo.getPrimaryColumns(); 952 for (int i = 0; i < pKeys.length; i++) { 953 if (i > 0) { 954 sql.append(AND); 955 } 956 sql.append(wrap(pKeys[i])).append(EQUALS_PLACEHOLDER); 957 } 958 959 //逻辑删除的情况下,需要添加逻辑删除的条件 960 String logicDeleteColumn = tableInfo.getLogicDeleteColumnOrSkip(); 961 if (StringUtil.isNotBlank(logicDeleteColumn)) { 962 sql.append(AND).append(buildLogicNormalCondition(logicDeleteColumn, tableInfo)); 963 } 964 965 //多租户 966 Object[] tenantIdArgs = tableInfo.buildTenantIdArgs(); 967 tableInfo.buildTenantCondition(sql, tenantIdArgs, this); 968 prepareAuth(tableInfo, sql, OperateType.SELECT); 969 return sql.toString(); 970 } 971 972 973 @Override 974 public String forSelectEntityListByIds(TableInfo tableInfo, Object[] primaryValues) { 975 StringBuilder sql = new StringBuilder(); 976 buildSelectColumnSql(sql, null, tableInfo.getDefaultQueryColumn(), null); 977 sql.append(FROM).append(tableInfo.getWrapSchemaAndTableName(this)); 978 sql.append(WHERE); 979 String[] primaryKeys = tableInfo.getPrimaryColumns(); 980 981 String logicDeleteColumn = tableInfo.getLogicDeleteColumnOrSkip(); 982 Object[] tenantIdArgs = tableInfo.buildTenantIdArgs(); 983 if (StringUtil.isNotBlank(logicDeleteColumn) || ArrayUtil.isNotEmpty(tenantIdArgs)) { 984 sql.append(BRACKET_LEFT); 985 } 986 987 //多主键的场景 988 if (primaryKeys.length > 1) { 989 for (int i = 0; i < primaryValues.length / primaryKeys.length; i++) { 990 if (i > 0) { 991 sql.append(OR); 992 } 993 sql.append(BRACKET_LEFT); 994 for (int j = 0; j < primaryKeys.length; j++) { 995 if (j > 0) { 996 sql.append(AND); 997 } 998 sql.append(wrap(primaryKeys[j])).append(EQUALS_PLACEHOLDER); 999 } 1000 sql.append(BRACKET_RIGHT); 1001 } 1002 } 1003 // 单主键 1004 else { 1005 for (int i = 0; i < primaryValues.length; i++) { 1006 if (i > 0) { 1007 sql.append(OR); 1008 } 1009 sql.append(wrap(primaryKeys[0])).append(EQUALS_PLACEHOLDER); 1010 } 1011 } 1012 1013 if (StringUtil.isNotBlank(logicDeleteColumn) || ArrayUtil.isNotEmpty(tenantIdArgs)) { 1014 sql.append(BRACKET_RIGHT); 1015 } 1016 1017 1018 if (StringUtil.isNotBlank(logicDeleteColumn)) { 1019 sql.append(AND).append(buildLogicNormalCondition(logicDeleteColumn, tableInfo)); 1020 } 1021 1022 //多租户 1023 tableInfo.buildTenantCondition(sql, tenantIdArgs, this); 1024 prepareAuth(tableInfo, sql, OperateType.SELECT); 1025 return sql.toString(); 1026 } 1027 1028 1029 protected boolean buildJoinSql(StringBuilder sqlBuilder, QueryWrapper queryWrapper, List<QueryTable> queryTables) { 1030 List<Join> joins = CPI.getJoins(queryWrapper); 1031 boolean joinSuccess = false; 1032 if (joins != null && !joins.isEmpty()) { 1033 for (Join join : joins) { 1034 if (!join.checkEffective()) { 1035 continue; 1036 } 1037 sqlBuilder.append(join.toSql(queryTables, this)); 1038 joinSuccess = true; 1039 } 1040 } 1041 return joinSuccess; 1042 } 1043 1044 1045 protected void buildWhereSql(StringBuilder sqlBuilder, QueryWrapper queryWrapper, List<QueryTable> queryTables, boolean allowNoCondition) { 1046 QueryCondition whereQueryCondition = CPI.getWhereQueryCondition(queryWrapper); 1047 if (whereQueryCondition != null) { 1048 String whereSql = whereQueryCondition.toSql(queryTables, this); 1049 if (StringUtil.isNotBlank(whereSql)) { 1050 sqlBuilder.append(WHERE).append(whereSql); 1051 } else if (!allowNoCondition) { 1052 throw FlexExceptions.wrap(LocalizedFormats.UPDATE_OR_DELETE_NOT_ALLOW); 1053 } 1054 } else { 1055 // whereQueryCondition == null 1056 if (!allowNoCondition) { 1057 throw FlexExceptions.wrap(LocalizedFormats.UPDATE_OR_DELETE_NOT_ALLOW); 1058 } 1059 } 1060 } 1061 1062 1063 protected void buildGroupBySql(StringBuilder sqlBuilder, QueryWrapper queryWrapper, List<QueryTable> queryTables) { 1064 List<QueryColumn> groupByColumns = CPI.getGroupByColumns(queryWrapper); 1065 if (groupByColumns != null && !groupByColumns.isEmpty()) { 1066 sqlBuilder.append(GROUP_BY); 1067 int index = 0; 1068 for (QueryColumn groupByColumn : groupByColumns) { 1069 String groupBy = CPI.toConditionSql(groupByColumn, queryTables, this); 1070 sqlBuilder.append(groupBy); 1071 if (index != groupByColumns.size() - 1) { 1072 sqlBuilder.append(DELIMITER); 1073 } 1074 index++; 1075 } 1076 } 1077 } 1078 1079 1080 protected void buildHavingSql(StringBuilder sqlBuilder, QueryWrapper queryWrapper, List<QueryTable> queryTables) { 1081 QueryCondition havingQueryCondition = CPI.getHavingQueryCondition(queryWrapper); 1082 if (havingQueryCondition != null) { 1083 String havingSql = havingQueryCondition.toSql(queryTables, this); 1084 if (StringUtil.isNotBlank(havingSql)) { 1085 sqlBuilder.append(HAVING).append(havingSql); 1086 } 1087 } 1088 } 1089 1090 1091 protected void buildOrderBySql(StringBuilder sqlBuilder, QueryWrapper queryWrapper, List<QueryTable> queryTables) { 1092 List<QueryOrderBy> orderBys = CPI.getOrderBys(queryWrapper); 1093 if (orderBys != null && !orderBys.isEmpty()) { 1094 sqlBuilder.append(ORDER_BY); 1095 int index = 0; 1096 for (QueryOrderBy orderBy : orderBys) { 1097 sqlBuilder.append(orderBy.toSql(queryTables, this)); 1098 if (index != orderBys.size() - 1) { 1099 sqlBuilder.append(DELIMITER); 1100 } 1101 index++; 1102 } 1103 } 1104 } 1105 1106 1107 /** 1108 * 构建 limit 和 offset 的参数 1109 */ 1110 protected StringBuilder buildLimitOffsetSql(StringBuilder sqlBuilder, QueryWrapper queryWrapper, Long limitRows, Long limitOffset) { 1111 return limitOffsetProcessor.process(this, sqlBuilder, queryWrapper, limitRows, limitOffset); 1112 } 1113 1114 1115 protected String buildLogicNormalCondition(String logicColumn, TableInfo tableInfo) { 1116 return LogicDeleteManager.getProcessor().buildLogicNormalCondition(logicColumn, tableInfo, this); 1117 } 1118 1119 1120 protected String buildLogicDeletedSet(String logicColumn, TableInfo tableInfo) { 1121 return LogicDeleteManager.getProcessor().buildLogicDeletedSet(logicColumn, tableInfo, this); 1122 } 1123 1124 1125}