jsqlparser(四):实现MySQL 函数DATE_FORMAT到Phoenix函数TO_CHAR的替换

上一篇博客《jsqlparser:基于语法分析实现SQL中的CAST函数替换》中我用jsqlparser这个神器实现了 TO_DATE(TO_CHAR("local_time"), 'yyyy-MM-dd')替换CAST(local_time AS DATE)
现在又遇到新问题了,
MySQL中日期格式化函数为DATE_FORMAT,对应Phoenix中的函数为TO_CHAR,如果应用层使用DATE_FORMAT函数,也要替换为TO_CHAR才能在HBase数据库中正常执行。有了上次经验,这次就简单多了,
不同的是DATE_FORMAT的日期格式定义与Phoenix不同,所以DATE_FORMATformat参数也需要自动替换,但是只能不完全替换。

以下为实现代码

import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.Function;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.util.TablesNamesFinder;

import java.util.List;
/**
 * 基于SQL语法对象实现对SQL的修改<br>
 * 将MySQL函数DATE_FORMAT替换为Phoenix的函数TO_CHAR
 * @author guyadong
 *
 */
public class PhoenixNormalizer  extends TablesNamesFinder{
    public PhoenixNormalizer() {
	}
	
    /**
     * 将MySQL的 DATE_FORMAT格式转为Java 日期格式<br>     
     * 参见 <a href="https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-format">function_date-format</a>,
     * 因为不能实现完全转换,所以当有不支持的格式时返回原字符串 
     * @param format
     * @see java.text.SimpleDateFormat
     */
    String castFormat(String format){
        if(null != format){
            String fmt=format.replace("%Y", "yyyy").replace("%y", "yy").replace("%m", "MM").replaceAll("%[de]", "dd")
            .replaceAll("%[Hk]", "HH").replace("%i", "mm").replaceAll("%[sS]", "ss")
            .replace("%W", "E")
            .replace("%j", "D")
            .replace("%T", "hh:mm:ss")
            .replace("%r", "hh:mm:ss a")
            .replaceAll("%[Uu]", "w")
            .replace("%%", "%");
            // 当有不支持的格式时返回原字符串 
            if(fmt.indexOf('%') < 0){
                return fmt;
            }
        }
        return format;
    }
    
    @Override
    public void visit(Function function){
        if("DATE_FORMAT".equalsIgnoreCase(function.getName())){
            /** DATE_FORMAT 改为 TO_CHAR */
            List<Expression> expressions = function.getParameters().getExpressions();
            if(null != expressions && 2 == expressions.size() ){
            	/** 修改函数名 */
                function.setName("TO_CHAR");
                Expression formatExp = expressions.get(1);
                if(formatExp instanceof StringValue){
                	/** 修改第二个参数(format) */
                    StringValue stringValue = (StringValue)formatExp;
                    stringValue.setValue(castFormat(stringValue.getValue()));
                }
            }
            
        }
        super.visit(function);
    }
}

完整的代码参见码云仓库:

https://gitee.com/l0km/sql2java/blob/master/sql2java-manager/src/main/java/gu/sql2java/phoenix/PhoenixNormalizer.java

参考资料

《DATE_FORMAT》
《TO_CHAR》

jsqlparser系列文章

《jsqlparser(一):基于抽象语法树(AST)遍历SQL语句的语法元素》
《jsqlparser(二):实现基于SQL语法分析的SQL注入攻击检查》
《jsqlparser(三):基于语法分析实现SQL中的CAST函数替换》
《jsqlparser(四):实现MySQL 函数DATE_FORMAT到Phoenix函数TO_CHAR的替换》
《jsqlparser(五):修改语法定义(JSqlParserCC.jjt)实现UPSERT支持Phoenix语法ON DUPLICATE KEY IGNORE》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

10km

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值