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.query; 017 018import com.mybatisflex.core.constant.SqlConsts; 019import com.mybatisflex.core.dialect.IDialect; 020import com.mybatisflex.core.dialect.OperateType; 021import com.mybatisflex.core.exception.FlexExceptions; 022import com.mybatisflex.core.util.ObjectUtil; 023 024import java.util.ArrayList; 025import java.util.List; 026import java.util.function.Supplier; 027 028/** 029 * @author michael yang (fuhai999@gmail.com) 030 * @Date: 2020/1/14 031 */ 032public class Join implements CloneSupport<Join> { 033 034 private static final long serialVersionUID = 1L; 035 036 037 protected final String type; 038 protected QueryTable queryTable; 039 protected QueryCondition on; 040 protected boolean effective; 041 042 public Join(String type, QueryTable table, boolean when) { 043 this.type = type; 044 this.queryTable = table; 045 this.effective = when; 046 } 047 048 public Join(String type, QueryWrapper queryWrapper, boolean when) { 049 this.type = type; 050 this.queryTable = new SelectQueryTable(queryWrapper); 051 this.effective = when; 052 } 053 054 055 QueryTable getQueryTable() { 056 return queryTable; 057 } 058 059 060 public void on(QueryCondition condition) { 061 replaceConditionColumn(condition); 062 this.on = condition; 063 } 064 065 private void replaceConditionColumn(QueryCondition condition) { 066 if (condition != null) { 067 if (condition.checkEffective() && condition.column != null) { 068 QueryTable table = condition.column.getTable(); 069 if (queryTable.isSameTable(table)) { 070 QueryColumn newColumn = condition.column.clone(); 071 newColumn.table.alias = queryTable.alias; 072 condition.column = newColumn; 073 } 074 } else if (condition instanceof Brackets) { 075 replaceConditionColumn(((Brackets) condition).getChildCondition()); 076 } else if (condition instanceof OperatorQueryCondition) { 077 replaceConditionColumn(((OperatorQueryCondition) condition).getChildCondition()); 078 } else if (condition instanceof OperatorSelectCondition) { 079 QueryWrapper qw = ((OperatorSelectCondition) condition).getQueryWrapper(); 080 replaceConditionColumn(qw.whereQueryCondition); 081 } 082 replaceConditionColumn(condition.next); 083 } 084 } 085 086 087 QueryCondition getOnCondition() { 088 return on; 089 } 090 091 public boolean checkEffective() { 092 return effective; 093 } 094 095 public void when(boolean when) { 096 this.effective = when; 097 } 098 099 public void when(Supplier<Boolean> fn) { 100 this.effective = fn.get(); 101 } 102 103 public String toSql(List<QueryTable> queryTables, IDialect dialect, OperateType operateType) { 104 //left join, right join, inner join ... 105 StringBuilder sql = new StringBuilder(type); 106 sql.append(queryTable.toSql(dialect,operateType)); 107 108 //left join xxx as xxx2 on xxx2.id = xxx3.other 109 List<QueryTable> newQueryTables = new ArrayList<>(queryTables); 110 newQueryTables.add(queryTable); 111 sql.append(SqlConsts.ON).append(on.toSql(newQueryTables, dialect)); 112 return sql.toString(); 113 } 114 115 @Override 116 public Join clone() { 117 try { 118 Join clone = (Join) super.clone(); 119 // deep clone ... 120 clone.queryTable = ObjectUtil.clone(this.queryTable); 121 clone.on = ObjectUtil.clone(this.on); 122 return clone; 123 } catch (CloneNotSupportedException e) { 124 throw FlexExceptions.wrap(e); 125 } 126 } 127 128}