Apache Calcite中之SQL解析并替换占位参数和获取复杂SQL中的别名关系

本文介绍了一个基于Apache Calcite的SQL解析工具类,能够处理多种数据库类型的SQL语法,支持参数替换及表别名提取等功能。

Apache Calcite版本:1.30.0
概述:上篇已经详细介绍Apache Calcite的概念,这块就不在多做介绍了,直接看实现代码

package com.joe.common.util;

import com.google.common.collect.ImmutableList;
import org.apache.calcite.avatica.util.Casing;
import org.apache.calcite.avatica.util.Quoting;
import org.apache.calcite.avatica.util.TimeUnitRange;
import org.apache.calcite.config.Lex;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.sql.*;
import org.apache.calcite.sql.SqlDialect.DatabaseProduct;
import org.apache.calcite.sql.dialect.MysqlSqlDialect;
import org.apache.calcite.sql.dialect.OracleSqlDialect;
import org.apache.calcite.sql.fun.SqlFloorFunction;
import org.apache.calcite.sql.fun.SqlLibraryOperators;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.apache.calcite.sql.parser.SqlParseException;
import org.apache.calcite.sql.parser.SqlParser;
import org.apache.calcite.sql.parser.SqlParserPos;
import org.apache.calcite.sql.validate.SqlConformanceEnum;
import org.apache.commons.lang.StringUtils;
import org.checkerframework.checker.nullness.qual.Nullable;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
* @Description:    sql语法解析工具类
*/
public class CalciteSqlUtils {
   
   

    private static SqlParser.Config mysqlConfig = SqlParser.configBuilder()
            .setLex(Lex.MYSQL)
            .setCaseSensitive(false)//大小写敏感
            .setQuoting(Quoting.BACK_TICK)
            .setQuotedCasing(Casing.TO_LOWER)
            .setUnquotedCasing(Casing.TO_LOWER)
            .setConformance(SqlConformanceEnum.MYSQL_5)
            .build();

    private static SqlParser.Config oralceConfig = SqlParser.configBuilder()
            .setLex(Lex.ORACLE)
            .setCaseSensitive(false)//大小写敏感
            .setQuoting(Quoting.BACK_TICK)
            .setQuotedCasing(Casing.TO_LOWER)
            .setUnquotedCasing(Casing.TO_LOWER)
            .setConformance(SqlConformanceEnum.ORACLE_12)
            .build();

    private static SqlParser.Config sqlserverConfig = SqlParser.configBuilder()
            .setLex(Lex.SQL_SERVER)
            .setCaseSensitive(false)//大小写敏感
            .setQuoting(Quoting.BACK_TICK)
            .setQuotedCasing(Casing.TO_LOWER)
            .setUnquotedCasing(Casing.TO_LOWER)
            .setConformance(SqlConformanceEnum.SQL_SERVER_2008)
            .build();

    public static List<Map<String,String>> mapList = new ArrayList<>();

    public static void main(String[] args) {
   
   

        String sql = "select id,name from t_user where id='${id}' and name='zhangsan'";

        String sql2 = "select\n" +
                "  aa.TOTAL_MONEY,\n" +
                "  aa.DRUG_MONEY,\n" +
                "  aa.BASE_DRUG_MONEY,\n" +
                "  bb.CAL_DATE,\n" +
                "  bb.CAL_MONTH,\n" +
                "  bb.CAL_YEAR,\n" +
                "  cc.OFFICE_NAME,\n" +
                "  cc.CUSTOM_CODE\n" +
                "FROM\n" +
                "  F_DRUG_USE aa,\n" +
                "  T_DATES bb,\n" +
                "  T_OFFICE_PROPERTY cc\n" +
                "where\n" +
                "  aa.date_id = bb.id\n" +
                "  and aa.BILLING_OFFICE_ID = cc.id\n" +
                "  and (select cal_year from bb) in ('${year_cond}')\n" +
                "  and bb.cal_year BETWEEN '${yeardes.get(0)}' and '${yeardes.get(1)}'\n" +
                "  and office_name like '${office_name_cond}'";

        try {
   
   
            List<Map<String, String>> list = handlerSqlTableAlias(DatabaseProduct.ORACLE, sql2);
            //打印
            System.out.println("$$$$$$$$$$$$$打印别名sql$$$$$$$$$$$$$");
            list.forEach(System.out::println);
            //替换sql参数
            String rt = handlerSqlParameterSubstitution(DatabaseProduct.ORACLE,sql2, "year_cond");
            System.out.println("$$$$$$$$$$$$$打印参数sql$$$$$$$$$$$$$");
            System.out.println(rt);
        } catch (Exception e) {
   
   
            throw new RuntimeException("", e);
        }
    }

    /**
     * sql参数替换
     * @param type 数据库类型
     * @param sql sql
     * @param param 替换参数名称
     * @return
     * @throws SqlParseException
     */
    public static String handlerSqlParameterSubstitution(DatabaseProduct type,String sql,String param) throws SqlParseException {
   
   
        //加载配置信息
        SqlParser sqlParser = null;
        switch (type){
   
   
            case ORACLE:
                sqlParser = SqlParser.create(sql, oralceConfig)
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值