jsqlparser:修改语法定义(JSqlParserCC.jjt)实现UPSERT支持Phoenix语法ON DUPLICATE KEY IGNORE

article/2025/10/5 4:39:06

最近在用jsqlparser4.5解析SQL时遇到了一个问题,

如下是apache phoenix的UPSERT语句

UPSERT INTO TEST (ID, COUNTER) VALUES (123, 0) ON DUPLICATE KEY IGNORE

ON DUPLICATE KEY IGNORE即为当主键重复时忽略,这与MySQL的IGNORE语法不同:

INSERT IGNORE INTO TEST (ID, COUNTER) VALUES (123, 0) 

jsqlparser目前的最新版本支持UPSERT语法,也支持ON DUPLICATE KEY UPDATE,但不支持ON DUPLICATE KEY IGNORE

所以jsqlparser解析SQL遇到ON DUPLICATE KEY IGNORE语法时解析器会报错 expect "UPDATE"

JSqlParserCC.jjt

为了解决这个问题我翻了jsqlparser的源码,找到了jsqlparser的语法定义文件(JSqlParserCC.jjt),是基于JavaCC实现的。

JSqlParserCC.jjt文件的位置在:jsqlparser/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt

打开它在1635行就能找到UPSERT语句分析ON DUPLICATE KEY UPDATE语法的位置,
为了看懂语法定义文件(JSqlParserCC.jjt),我又恶补了一下JavaCC的语法,基本上能看懂了。
原来的代码是

    [ <K_ON> <K_DUPLICATE> <K_KEY> <K_UPDATE>{ useDuplicate = true; }tableColumn=Column() "=" exp=SimpleExpression(){duplicateUpdateColumns = new ArrayList<Column>();duplicateUpdateExpressionList = new ArrayList<Expression>();duplicateUpdateColumns.add(tableColumn);duplicateUpdateExpressionList.add(exp);}("," tableColumn=Column() "=" exp=SimpleExpression(){ duplicateUpdateColumns.add(tableColumn);duplicateUpdateExpressionList.add(exp); } )*]

修改为如下:

    [<K_ON> <K_DUPLICATE> <K_KEY> (<K_IGNORE>{ modifierIgnore = true; }|<K_UPDATE>{ useDuplicate = true; }tableColumn=Column() "=" exp=SimpleExpression(){duplicateUpdateColumns = new ArrayList<Column>();duplicateUpdateExpressionList = new ArrayList<Expression>();duplicateUpdateColumns.add(tableColumn);duplicateUpdateExpressionList.add(exp);}("," tableColumn=Column() "=" exp=SimpleExpression(){ duplicateUpdateColumns.add(tableColumn);duplicateUpdateExpressionList.add(exp); } )*)]

即允许 ON DUPLICATE后为IGNOREUPDATE,为IGNORE时将modifierIgnore 设置为true

modifierIgnore为新增加的变量定义,后续会用到。

如下图为主要修改的前后对比
在这里插入图片描述

Upsert.java

不仅要修改语法定义文件,同时还要修改src/main/java/net/sf/jsqlparser/statement/upsert/Upsert.java,相应增加modifierIgnore字段,
完整代码参见我的码云仓库:
https://gitee.com/l0km/JSqlParser.git

【不是master分支,是gyd分支,gyd分支,gyd分支,重要的事情说三遍】

下载代码

git clone -b gyd https://gitee.com/l0km/JSqlParser.git

maven编译

cd JSqlParser
$ mvn clean install -DskipTests=true

单元测试

jsqlparser项目有比较完备的单元测试,上述修改完毕执行UPSERT语句的单元测试UpsertTest.java验证修改是否有效。
先执行原有的ON DUPLICATE KEY UPDATE语法测试,看看是否有影响

$ mvn -Dtest=UpsertTest#testUpsertDuplicate test

我在src/test/java/net/sf/jsqlparser/statement/upsert/UpsertTest.java增加了新的单元测试方法testUpsertIgnore 以验证ON DUPLICATE KEY IGNORE语法有效性。

    @Testpublic void testUpsertIgnore() throws JSQLParserException {String statement = "UPSERT INTO TEST (ID, COUNTER) VALUES (123, 0) ON DUPLICATE KEY IGNORE";Upsert upsert = (Upsert) parserManager.parse(new StringReader(statement));assertEquals("TEST", upsert.getTable().getName());assertEquals(2, upsert.getColumns().size());assertTrue(upsert.isUseValues());assertEquals("ID", upsert.getColumns().get(0).getColumnName());assertEquals("COUNTER", upsert.getColumns().get(1).getColumnName());assertEquals(2, ((ExpressionList) upsert.getItemsList()).getExpressions().size());assertEquals(123, ((LongValue) upsert.getItemsList(ExpressionList.class).getExpressions().get(0)).getValue());assertEquals(0, ((LongValue) upsert.getItemsList(ExpressionList.class).getExpressions().get(1)).getValue());assertTrue(upsert.isModifierIgnore());assertEquals(statement, "" + upsert);}

执行新增的ON DUPLICATE KEY IGNORE语法测试

$ mvn -Dtest=UpsertTest#testUpsertIgnore test

Pull Request

此问题修复已经向jsqlparser提交了Pull Request
参见 https://github.com/JSQLParser/JSqlParser/pull/1689

如果批准,就可以在下一个官方版本中更新了。

参考资料

《UPSERT》
《JavaCC》


http://chatgpt.dhexx.cn/article/NUoM73EG.shtml

相关文章

jsqlparser mysql_java sql解析器比较druid sql parser vs jsqlparser vs fdb-sql-parser

先上结论。 功能上&#xff1a;druid sql parser(支持分区、WITH、DUAL等。使用mysql语法解析时&#xff0c;已知oracle的一些操作符会被转为mysql&#xff0c;如|| 转为OR。使用oracle解析器时&#xff0c;union all里面的括号会被移到外面&#xff0c;从而导致可能执行出错) …

JSqlParser4.3版本无法解析mysql中JSON_OBJECT函数抛出ParseException异常

2022年3月31日&#xff0c;找了一下午的bug bug 已经提交issues&#xff0c;详情请看GitHub&#xff0c;地址&#xff1a;https://github.com/JSQLParser/JSqlParser/issues/1504 使用JSqlparser4.3版作者提供的补丁版后解决&#xff0c;下载地址&#xff1a;https://download.…

JSqlparser 使用攻略(高效的SQL解析工具)

JSqlparser github地址 目录 Maven 引用远程仓库依赖包 SQL解析获取SQL中的信息创建Select的方式创建Select&#xff08;非SQL String 创建&#xff09; Insert 插入字段和值where条件中字段替换解析SQL例子获取所有tableNames自动生成别名SQL函数单表where条件拼装JOIN 拼装 校…

jsqlparser 简介、中文文档、中英对照文档 下载

jsqlparser 文档 下载链接&#xff08;含jar包、源码、pom&#xff09; 组件名称中文-文档-下载链接中英对照-文档-下载链接jsqlparser-0.9.5.jarjsqlparser-0.9.5-API文档-中文版.zipjsqlparser-0.9.5-API文档-中英对照版.zipjsqlparser-1.0.jarjsqlparser-1.0-API文档-中文版…

java使用jsqlparser实现自定义转换

jsqlparser描述&#xff1a; JSqlParser 解析 SQL 语句并将其转换为 Java 类的层次结构。基本上的sql关键字和函数都可以被jsqlparser解析成对象层层包装。 实现的功能&#xff1a; 基础sql查询&#xff0c;条件查询&#xff0c;字段和表得别名&#xff0c;排序&#xff0c;…

JSQLParser碰到的问题

JSQLParser是github上一个开源的项目&#xff0c;专门解析SQL&#xff0c;可以轻松地得到一条SQL的列、表、条件等对象&#xff0c; P.S. https://github.com/JSQLParser/JSqlParser 最近在做一个功能开发的时候&#xff0c;被他困扰了下&#xff0c;从需求来讲&#xff0c;就是…

JSqlParser-SQL解析处理

一、介绍 JSqlParse是一款很精简的sql解析工具&#xff0c;将sql语句转成Java对象。 官网&#xff1a;JSqlParser - Home 用法&#xff1a;可以用于数据权限处理&#xff0c;拦截sql解析改写sql等等。 二、版本 <dependency><groupId>com.github.jsqlparser&l…

JSQLParser 解析复杂SQL 2.0

前言 这段时间&#xff0c;为了开发数据中台项目&#xff0c;我去研究学习了JSQLParser&#xff08;Java中解析SQL语句的工具&#xff09;&#xff0c;并且结合网上资料&#xff0c;写了一个初步的SQL解析工具类... 正文 时隔三天&#xff0c;我又回来了&#xff0c; 因为之前J…

JSqlParser入门系列(1)-JSqlParser简介及入门案例

简介 JSqlParser是一个SQL语句解析器。它将SQL转换为Java类的可遍历层次结构。 支持Oracle&#xff0c;SqlServer&#xff0c;MySQL&#xff0c;PostgreSQL等常用数据库。但各种数据库系统的SQL语法都在动态变化&#xff0c;可以解析某些&#xff08;不是全部&#xff09;。 …

JSqlParser

JSqlParser 关于SqlParser引言&#xff1a; Java 生态中较为流行的 SQL Parser 有以下几种&#xff1a; fdb-sql-parser 是 FoundationDB 在被 Apple 收购前开源的 SQL Parser&#xff08;不支持很复杂的SQL&#xff09;&#xff0c;目前已无人维护。jsqlparser 是基于 Java…

Sql解析转换之JSqlParse完整介绍

1、 jsqlparse介绍 JSqlParse是一款很精简的sql解析工具&#xff0c;它可以将常用的sql文本解析成具有层级结构的“语法树”&#xff0c;我们可以针对解析后的“树节点&#xff08;也即官网里说的有层次结构的java类&#xff09;”进行处理进而生成符合我们要求的sql形式。 官…

相机内参模型Kannala-Brandt/fisheye/pinhole+equi详解

文章目录 1. 论文总述2. pinholeradtan无法建模鱼眼相机3. 内参模型3.1 Radially Symmetric Model3.2 Full Model3.3 affine transformation3.4 Backward Model 4. 标定4.1 ORIFL190-3 lens 可以被标定 5. 内参结果验证参考文献 本博客主要从fisheye论文角度&#xff0c;详细介…

python-opencv实现pinhole相机图像转fisheye相机图像

根据鱼眼相机公式rff*θ&#xff0c;其中θatan(rc/f)&#xff0c;即可实现从pinhole相机模型到fisheye相机模型的像素映射。可自行设置焦距&#xff0c;我使用如下代码完成了将cityscape数据集转换为鱼眼视角。 import numpy as np import cv2 import osclass ConvertFisheye…

jiraconfluencefisheye用户同步

分别安装好jira和confluence&#xff0c;fisheye之后&#xff0c;先在jira中将confluence和fisheye的应用程序连接配置好。如下 配置好后&#xff0c;在jira中的用户服务器中可以已经允许对应的程序使用jira的用户了。 此时&#xff0c;分别去confluence或者fisheye的user-d…

Atlassian家族 JIRA Confluence Fisheye 在 Linux (CentOS 7.6 )安装部署教程

安装包 atlassian-agent-v1.2.2.tar.gz # 破解工具atlassian-fisheye-4.8.3.zipatlassian-confluence-7.4.1-lts-x64.binatlassian-jira-software-8.5.5-lts-x64.bin 部署环境 Linux版本&#xff1a;CentOS 7.6VMware 16Confluence 6.3.1Jira 8.5.5MySQL 5.6JDK 1.8…

【图像】【OpenCV鱼眼矫正】二、fisheye::initUndistortRectifyMap()源码分析

目录 一、fisheye::initUndistortRectifyMap() 之 功能介绍二、fisheye::initUndistortRectifyMap() 之 源码分析1. 源码分析2. 更进一步3. 如何由 (j, i) 算出 (u, v) &#xff1f; 一、fisheye::initUndistortRectifyMap() 之 功能介绍 在上一篇文章的第 2. 部分中&#xff…

Monocular Fisheye Camera Depth Estimation Using Sparse LiDAR Supervision

Paper name Monocular Fisheye Camera Depth Estimation Using Sparse LiDAR Supervision Paper Reading Note URL: https://arxiv.org/pdf/1803.06192.pdf TL;DR 2018 年 ITSC 文章&#xff0c;出自于德国 Valeo 自动驾驶公司&#xff0c;提出了单目鱼眼深度估计的有监督…

Linux环境fisheye+crucible安装与破解

由于最新的版本中fisheye和crucible已经集成在一起了&#xff0c;故只需要下载一个包就可以了。 需要的软件及版本情况如下&#xff1a; fisheye4.8.7&#xff1b;&#xff08;安装包&#xff09; atlassian-agent-v1.2.3&#xff1b;&#xff08;破解工具&#xff09; mysql-c…

相机模型-鱼眼模型(fisheye camera model)

鱼眼相机模型 &#xff08;fisheye camera model&#xff09; 模型介绍等距投影等立体角投影正交投影体视投影线性投影 Kannala-Brandt 模型去畸变过程投影过程反投影过程 雅可比计算 之前总结了一下针孔相机的模型&#xff0c;然后得到了比较积极的回复&#xff08;其实是我到…

opencv fisheye calibration(鱼眼相机校正)

文章目录 fisheye_calibration小孔成像模型&#xff08;理想相机成像模型&#xff09;fisheye model 相机模型内参校正的原理calibration过程对这个过程简单分析参考文章 fisheye_calibration 小孔成像模型&#xff08;理想相机成像模型&#xff09; 请参考下面的文章 理想相…