1.9.3. 统一SQL Java 接口
1.9.3.1. 简介
统一SQL提供了 Java API,可供 JAVA 程序直接调用;用户只需要在Maven项目中引入sql-convert-runtime依赖即可使用 JAVA API,具体可参考 集成统一SQL代理 。
1.9.3.2. SQL转换
1.9.3.2.1. 接口签名
public static String parse(String sql, String sourceDialect, String targetDialect) {}
public static String parse(String sql, String sourceDialect, String targetDialect, long sessionId) {}
该接口方法位于sql-convert-runtime模块中的com.hundsun.lightdb.unisql.golang.Transformer类中。
1.9.3.2.2. 接口请求参数
JAVA 接口的每一项参数说明如下:
参数名 |
类型 |
是否必须 |
说明 |
示例 |
|---|---|---|---|---|
sql |
string |
是 |
源SQL语句 |
"select name, avg(score) from student_score group by name" |
sourceDialect |
string |
是 |
源数据库方言名称,具体可查看 数据库支持范围 中的 |
ORACLE |
targetDialect |
string |
是 |
目标数据库方言名称,具体可查看 数据库支持范围 中的 |
LIGHTDB_ORACLE |
sessionId |
long |
否 |
会话ID |
1.9.3.2.3. 接口返回参数
返回类型是一个 string,表示转换后的sql语句,返回值有2种情况:
返回 null 值:表示转换失败
返回非 null 值:表示转换后的sql语句
1.9.3.2.4. 调用示例
本例子使用标准的 JAVA 测试用例展示该接口的使用方式,示例代码如下:
@Test
public void parseTest() {
String parsedSql = Transformer.parse("SELECT MEDIAN(amount) AS median_amount FROM aggregate_sales " +
"WHERE product_id = 1 ORDER BY median_amount", DbType.ORACLE.name(), DbType.POSTGRESQL.name());
System.out.println("统一SQL转换后sql " + parsedSql);
}
示例执行结果,Oracle的median函数将被转换为PostgreSQL的percentile_cont分析函数。
统一SQL转换后sql SELECT percentile_cont(5e-01) WITHIN GROUP (ORDER BY amount) AS median_amount FROM aggregate_sales WHERE product_id=1 ORDER BY median_amount
1.9.3.3. SQL转换(返回绑定变量顺序)
1.9.3.3.1. 接口签名
public static String parse(String sql, String source, String target, List<Integer> bindVariableOrder) {}
该接口方法位于sql-convert-runtime模块中的com.hundsun.lightdb.unisql.golang.Transformer类中。
与基础parse接口的区别在于:通过出参返回绑定变量顺序信息,用于处理SQL转换过程中绑定参数位置发生变化的情况(如某些函数转换会导致绑定参数重复或顺序调整)。
1.9.3.3.2. 接口请求参数
JAVA 接口的每一项参数说明如下:
参数名 |
类型 |
是否必须 |
说明 |
示例 |
|---|---|---|---|---|
sql |
String |
是 |
源SQL语句 |
"SELECT lpad(?, 10) FROM t WHERE id = ?" |
source |
String |
是 |
源数据库方言名称,具体可查看 数据库支持范围 中的 |
ORACLE |
target |
String |
是 |
目标数据库方言名称,具体可查看 数据库支持范围 中的 |
GOLDENDB_MYSQL |
bindVariableOrder |
List<Integer> |
是 |
出参,用于接收绑定变量顺序列表。列表中的值表示新绑定参数位置对应的旧绑定参数位置(从1开始计数) |
new ArrayList<>() |
1.9.3.3.3. 重要说明
绑定变量顺序映射规则:
bindVariableOrder列表中的第i个元素(从0开始)表示新SQL中第i+1个绑定参数对应原SQL中第几个绑定参数
例如:bindVariableOrder = [1, 1] 表示新SQL的第1个绑定参数对应原SQL第1个,新SQL的第2个绑定参数也对应原SQL第1个(绑定参数重复的情况)
无变化时的处理:
若绑定参数顺序未发生变化,bindVariableOrder列表会被清空(size=0),不会添加任何元素
若绑定参数不存在,bindVariableOrder列表同样会被清空
列表预清理:
传入的bindVariableOrder列表会被先清空再填充,调用前不需要手动清空
1.9.3.3.4. 接口返回参数
返回类型是一个 String,表示转换后的SQL语句:
返回转换后的SQL:表示转换成功
抛出IllegalStateException:表示转换失败,异常信息包含具体错误原因
1.9.3.3.5. 调用示例
示例1:基本使用(绑定参数顺序变化)
@Test
public void testBasicBindVariableOrder() {
// 设置参数,启用lpad函数转换
Transformer.setParamStr("unisql.skip.custom.funclist", "lpad");
String sourceSql = "SELECT lpad(?, 2) FROM test_lpad order by id";
List<Integer> bindVariableOrder = new ArrayList<>();
// 调用转换接口
String targetSql = Transformer.parse(
sourceSql,
DbType.ORACLE.name(),
DbType.GOLDENDB_MYSQL.name(),
bindVariableOrder
);
System.out.println("源SQL: " + sourceSql);
System.out.println("目标SQL: " + targetSql);
System.out.println("绑定参数数量: " + bindVariableOrder.size());
// 打印绑定参数顺序映射
if (!bindVariableOrder.isEmpty()) {
System.out.println("绑定参数顺序映射(新位置 -> 原位置):");
for (int i = 0; i < bindVariableOrder.size(); i++) {
System.out.println(" 新绑定位置 " + (i + 1) + " 对应原绑定位置: " + bindVariableOrder.get(i));
}
}
}
示例执行结果:
源SQL: SELECT lpad(?, 2) FROM test_lpad order by id
目标SQL: SELECT if(length(?)=0 OR length(2)=0 OR 2=0, NULL, lpad(?, 2, ' ')) FROM test_lpad ORDER BY id
绑定参数数量: 2
绑定参数顺序映射(新位置 -> 原位置):
新绑定位置 1 对应原绑定位置: 1
新绑定位置 2 对应原绑定位置: 1
示例2:绑定参数顺序未变化
@Test
public void testBindVariableOrderNoChange() {
String sourceSql = "SELECT * FROM t WHERE id = ?";
List<Integer> bindVariableOrder = new ArrayList<>();
String targetSql = Transformer.parse(
sourceSql,
DbType.ORACLE.name(),
DbType.GOLDENDB_MYSQL.name(),
bindVariableOrder
);
System.out.println("源SQL: " + sourceSql);
System.out.println("目标SQL: " + targetSql);
System.out.println("绑定参数数量: " + bindVariableOrder.size());
// 绑定参数顺序未变化时,列表应该为空
assert bindVariableOrder.isEmpty() : "绑定参数顺序未变化时,bindVariableOrder应该为空";
}
示例执行结果:
源SQL: SELECT * FROM t WHERE id = ?
目标SQL: SELECT * FROM t WHERE id=?
绑定参数数量: 0
示例3:null参数处理
@Test
public void testNullBindVariableOrder() {
String sourceSql = "SELECT * FROM t WHERE id = ?";
// 传递null作为bindVariableOrder,接口仍能正常工作
String targetSql = Transformer.parse(
sourceSql,
DbType.ORACLE.name(),
DbType.MYSQL.name(),
(List<Integer>) null
);
System.out.println("源SQL: " + sourceSql);
System.out.println("目标SQL: " + targetSql);
}
1.9.3.4. 创建会话
1.9.3.4.1. 接口签名
public static Long createSession() {}
public static Long createSession(String targetDbType, int targetDbVersion) {}
1.9.3.4.2. 接口请求参数
createSession()
无参数,并且不支持库级别的参数配置
createSession(String targetDbType, int targetDbVersion)
参数名 |
类型 |
是否必须 |
说明 |
示例 |
|---|---|---|---|---|
targetDbType |
String |
是 |
目标数据库类型,具体可查看 数据库支持范围 中的 |
"GAUSSDB_ORACLE" |
targetDbVersion |
int |
是 |
目标数据库版本号,支持数据库版本号请参考统一SQL参考手册,若gaussdboracle 505.2.0 为 5050200 |
5050200 |
1.9.3.4.3. 接口返回参数
返回类型是一个 Long,会话ID
1.9.3.5. 销毁会话
1.9.3.5.1. 接口签名
public static void freeSession(Long sessionId) {}
1.9.3.5.2. 接口请求参数
JAVA 接口的每一项参数说明如下:
参数名 |
类型 |
是否必须 |
说明 |
示例 |
|---|---|---|---|---|
sessionId |
Long |
是 |
会话ID |
1.9.3.5.3. 接口返回参数
无
1.9.3.6. 参数设置
1.9.3.6.1. 接口签名
public static void setSessionParamStr(String paramName, String paramValue, long sessionId) {}
1.9.3.6.2. 接口请求参数
JAVA 接口的每一项参数说明如下:
参数名 |
类型 |
是否必须 |
说明 |
示例 |
|---|---|---|---|---|
paramName |
String |
是 |
参数名 |
"unisql.skip" |
paramValue |
String |
是 |
参数值 |
"true" |
sessionId |
long |
是 |
会话ID |
1.9.3.6.3. 参数类型说明
根据配置参数的不同级别,setSessionParamStr 的行为有所不同:
1. 会话参数(session scope)
设置只影响当前会话(session)
典型参数:
unisql.skip、unisql.error.skip、unisql.charset等示例:设置当前会话跳过SQL转换
Long sessionId = Transformer.createSession("ORACLE_19C", 1900);
// 设置当前会话跳过SQL转换
Transformer.setSessionParamStr("unisql.skip", "false", sessionId);
2. 全局参数(global scope)
如果配置了库级别参数,则影响当前目标库;如果没有配置库级别参数,则影响所有库
典型参数:
unisql.keyword.doublequotes、unisql.auto.increment.column等
示例1:未对参数进行库级别配置时,设置影响所有库
// 配置文件中没有配置 unisql.keyword.doublequotes.oracle_19c-1900
// 此时设置影响所有目标库
Long sessionId = Transformer.createSession("ORACLE_19C", 1900);
Transformer.setSessionParamStr("unisql.keyword.doublequotes", "TEST1,TEST2", sessionId);
// 对 ORACLE_19C、GAUSSDB_ORACLE 等所有库都生效
示例2:参数配置了库级别时,设置只影响当前库
// 配置文件中配置了库级别参数:
// unisql.keyword.doublequotes.oracle_19c-1900 = ORA_KEY1,ORA_KEY2
// 创建 ORACLE_19C 会话,只影响 ORACLE_19C,不影响 其他库
Long sessionId1 = Transformer.createSession("ORACLE_19C", 1900);
Transformer.setSessionParamStr("unisql.keyword.doublequotes", "NEW_KEY1,NEW_KEY2", sessionId1);
警告
设置参数时不需要带库名称和版本号,因为createSession已经指定过了
3. 系统参数(system scope)
不允许通过此接口修改
系统参数在进程启动时初始化,运行时不支持修改
典型参数:
unisql.lib.dir、unisql.log.path、unisql.log.level等如需修改系统参数,请通过配置文件
注意
部分全局参数不支持库级别配置(如
unisql.cache、unisql.sql.pretty等)设置参数前请确认参数的级别和作用范围,避免产生非预期效果
1.9.3.6.4. 接口返回参数
无
1.9.3.7. 元数据加载
1.9.3.7.1. 接口说明
统一SQL提供元数据加载功能,用户可以通过调用元数据加载接口将目标端数据库的元数据信息加载到统一SQL中,从而提升SQL转换的准确性。具体接口签名及参数说明可参考: 元数据管理 。