package com.primeton.dsp.datarelease.api.sql; import com.google.common.collect.Sets; import com.primeton.dsp.datarelease.api.model.JoinPair; import com.primeton.dsp.datarelease.api.model.Table; import com.primeton.dsp.datarelease.api.model.WhereCause; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; /** * * 服务发布多表关联,和单表 服务发布时生成预览SQL。 * *
 *
 * Created by zhaopx.
 * User: zhaopx
 * Date: 2020/3/27
 * Time: 17:15
 *
 * 
* * @author zhaopx */ @Slf4j public abstract class SQLCreatorFactory { /** * 单表生成 SQL * @return */ public abstract String singleTable(Table table, WhereCause[] conds); /** * 多表生成 SQL * * @param tables * @param joins * @param conds * @return */ public abstract String mutilTable(Table[] tables, JoinPair[] joins, WhereCause[] conds); /** * 生成一个实例 * @return */ public static SQLCreatorFactory newInstance() { return new SQLCreatorFactory() { @Override public String singleTable(Table table, WhereCause[] conds) { //单表生成SQL预览 SQLQuery sqlQuery = new SQLQuery.Builder(table) .where(conds) .build(); //生成的SQL要预览,这里美化一下 String showSQL = sqlQuery.show(true); log.info("c sql {}", showSQL); return showSQL; } @Override public String mutilTable(Table[] tables, JoinPair[] joins, WhereCause[] conds) { Map tableMapping = new HashMap<>(); for(Table table : tables) { tableMapping.put(table.getTableName(), new SQLJoin.JoinTable(table)); } // join 条件,如果量表 join 多次也当做 where List joinList = new ArrayList<>(); // where 条件,把多余的 join 条件放到 where 条件中 Set condSet = Sets.newHashSet(conds); // 相同的两个表,join 多次的情况,取第一个作为 join,后面的作为 where 条件 Map joinPairCache = new HashMap<>(); for(JoinPair jp : joins) { //左表加右表 String cacheKey = StringUtils.upperCase(jp.getLeft() + jp.getRight()); if(joinPairCache.get(cacheKey) == null) { joinPairCache.put(cacheKey, jp); joinList.add(jp); } else { // 已经存在关联的 join 转为 where 后的条件 WhereCause cause = new WhereCause(); cause.setTableName(jp.getLeft()); cause.setFieldName(jp.getLeftField()); cause.setToTableName(jp.getRight()); cause.setToFieldName(jp.getRightField()); cause.setOpera("="); condSet.add(cause); } } SQLJoin.Builder builder = null; if(joinList.size() == 1) { // 2 个表的关联 SQLJoin.JoinTable left = tableMapping.get(joinList.get(0).getLeft()); SQLJoin.JoinTable right = tableMapping.get(joinList.get(0).getRight()); builder = new SQLJoin.Builder(left, joinList.get(0).getLeftField(), right, joinList.get(0).getRightField(), SQLJoin.JoinType.joinType(joinList.get(0).getJoinType())); } else { // 3 个或者3 个以上的表关联 SQLJoin.JoinTable left = tableMapping.get(joinList.get(0).getLeft()); SQLJoin.JoinTable right = tableMapping.get(joinList.get(0).getRight()); builder = new SQLJoin.Builder(left, joinList.get(0).getLeftField(), right, joinList.get(0).getRightField(), SQLJoin.JoinType.joinType(joinList.get(0).getJoinType())); for(int i = 1; i < joinList.size(); i++) { JoinPair joinPair = joinList.get(i); SQLJoin.JoinTable leftTable = tableMapping.get(joinPair.getLeft()); SQLJoin.JoinTable rightTable = tableMapping.get(joinPair.getRight()); // 下面使用要重新 new 一个,防止重新设置别名是影响原来的别名 if(builder.isCachedTable(leftTable.getTableName())) { //A JOIN B JOIN C, 正好是符合的 builder.join(leftTable, joinPair.getLeftField(), rightTable, joinPair.getRightField(), SQLJoin.JoinType.joinType(joinPair.getJoinType())); } else { // A JOIN C // B JOIN C 模式,生成 JOIN 应该是 A JOIN C JOIN B 的方式 SQLJoin.JoinType joinType = SQLJoin.JoinType.joinType(joinPair.getJoinType()); SQLJoin.JoinType realJoinType = joinType; switch (joinType) { case LEFT_JOIN: realJoinType = SQLJoin.JoinType.RIGHT_JOIN; break; case RIGHT_JOIN: realJoinType = SQLJoin.JoinType.LEFT_JOIN; break; default: } // 调换一下顺序 builder.join( rightTable, joinPair.getRightField(), leftTable, joinPair.getLeftField(), realJoinType); } } } // 把where 条件加入进来 builder.where(condSet); SQLJoin sql = builder.build(); // 前端不显示 SQL,如果加了回车在执行时会乱码报错。因此这里不能加回车进行格式化 String resultSql = sql.show(true); log.info(resultSql); return resultSql; } }; } }