1.9.2. 统一SQL C 接口
1.9.2.1. 简介
统一SQL提供了 C API ,可供 C/C++ 程序直接调用;用户只需要正确地引用 unisql.h 与链接 libunisql.so 即可使用 C API。
1.9.2.2. TransferSQL接口
1.9.2.2.1. 接口说明
转换SQL语句(带缓存)
接口签名:
extern int TransferSQL(
int sourceDbTypeCode,
int targetDbTypeCode,
const char* sourceSqlStr,
char* targetSqlStr,
int targetSqlMemoryLen,
const char* jsonParameter);
要使用 C 接口,您需要发布包中对应操作系统平台的 so 动态库,以及 unisql.h 头文件。
C 接口同样支持读取统一 SQL 配置文件,具体使用方法可参考 配置文件 。
1.9.2.2.2. 接口请求参数
C 接口的每一项参数说明如下:
参数名 |
类型 |
是否必须 |
说明 |
示例 |
|---|---|---|---|---|
sourceDbTypeCode |
int |
是 |
源数据库方言编码,见发布包中 unisql.h 的 |
UNISQL_DBTYPE_ORACLE |
targetDbTypeCode |
int |
是 |
目标数据库方言编码,见发布包中 unisql.h 的 |
UNISQL_DBTYPE_GAUSSDB_ORACLE |
sourceSqlStr |
const char* |
是 |
源SQL语句 |
"select name, avg(score) from student_score group by name" |
targetSqlStr |
char* |
是 |
转换后的 SQL 内存空间,内存由调用方自行管理,推荐使用源 SQL 长度的 4 倍大小 |
buffer |
targetSqlMemoryLen |
int |
是 |
targetSqlStr 的内存大小,比如传入 101 则可以存储长度为 100 的字符 |
101 |
jsonParameter |
const char* |
否 |
转换配置选项,预留扩展字段,目前传 NULL 即可 |
NULL |
1.9.2.2.3. 接口枚举说明
统一 SQL 的 C API 方言编码枚举如下:
#define UNISQL_DBTYPE_LIGHTDB_MYSQL 1 // LIGHTDB MYSQL模式
#define UNISQL_DBTYPE_LIGHTDB_ORACLE 2 // LIGHTDB ORACLE模式
#define UNISQL_DBTYPE_LIGHTDB_POSTGRESQL 3 // LIGHTDB POSTGRESQL模式
#define UNISQL_DBTYPE_DM 4 // 达梦
#define UNISQL_DBTYPE_MYSQL 5 // MYSQL
#define UNISQL_DBTYPE_TDSQL_MYSQL 6 // TDSQL MYSQL模式
#define UNISQL_DBTYPE_MYSQL_80 7 // MYSQL8
#define UNISQL_DBTYPE_OCEAN_BASE_MYSQL 8 // OceanBase MYSQL模式
#define UNISQL_DBTYPE_OCEAN_BASE_ORACLE 9 // OceanBase ORACLE模式
#define UNISQL_DBTYPE_OPENGAUSS 10 // OPENGAUSS
#define UNISQL_DBTYPE_ORACLE 11 // ORACLE
#define UNISQL_DBTYPE_POSTGRESQL 12 // POSTGRESQL
#define UNISQL_DBTYPE_GOLDENDB_MYSQL 13 // GOLDENDB MYSQL模式
#define UNISQL_DBTYPE_GOLDENDB_ORACLE 14 // GOLDENDB ORACLE模式
#define UNISQL_DBTYPE_GAUSSDB_MYSQL 15 // 高斯 MYSQL模式
#define UNISQL_DBTYPE_GAUSSDB_ORACLE 16 // 高斯 ORACLE模式
#define UNISQL_DBTYPE_SQLSVR 17 // SQLSVR模式
#define UNISQL_DBTYPE_TDSQL_PG_ORACLE 18 // tdsql_pg oracle模式
#define UNISQL_DBTYPE_GAUSSDB500_ORACLE 19 // 高斯 ORACLE模式,(GaussDB Kernel V500R002C10 build f6002322)版本
#define UNISQL_DBTYPE_SQLITE 20 // SQLITE
#define UNISQL_DBTYPE_LTMEMDB 21 // LTMEMDB内存数据库
#define UNISQL_DBTYPE_ORACLE_19C 22 // ORACLE 19C版本
#define UNISQL_DBTYPE_GAUSSDB_MYSQL_B 23 // 高斯 MYSQL B版本
#define UNISQL_DBTYPE_TDSQL_PG 24 // TDSQL PG模式
#define UNISQL_DBTYPE_OPENGAUSS_MYSQL 25 // OPENGAUSS MYSQL模式
#define UNISQL_DBTYPE_GAUSSDB_PG 26 // 高斯 PG模式
#define UNISQL_DBTYPE_KINGBASE_ORACLE 27 // 人大金仓 ORACLE模式
#define UNISQL_DBTYPE_INFLUXDB1 28 // INFLUXDB1时序数据库
#define UNISQL_DBTYPE_INFLUXDB3 29 // INFLUXDB3时序数据库
#define UNISQL_DBTYPE_CLICKHOUSE 30 // CLICKHOUSE分析型数据库
#define UNISQL_DBTYPE_TDENGINE 31 // TDENGINE时序数据库
#define UNISQL_DBTYPE_DOLPHINDB 32 // DOLPHINDB时序数据库
#define UNISQL_DBTYPE_DORIS 33 // DORIS分析型数据库
#define UNISQL_DBTYPE_TSDB 34 // TSDB时序数据库
#define UNISQL_DBTYPE_GAUSSDB503_ORACLE 35 // 高斯 ORACLE模式,GaussDB Kernel 503版本
1.9.2.2.4. 接口返回参数
返回类型是一个 int ,取值有 3 种情况:
返回 0: 代表转换成功
返回 -1: 代表转换异常,需要在统一 SQL 的日志中查看具体失败原因
返回大于 0 的数字:代表传入的 targetSqlMemoryLen 空间不足,返回值表示需要的空间
1.9.2.2.5. 调用示例
本例子假设统一 SQL 的发布包放在 /home/lightdb/LightDB1.0-unisql-V202403-00-000 下,示例步骤为:
设置环境变量,为了运行示例:
export LD_LIBRARY_PATH=/home/lightdb/LightDB1.0-unisql-V202403-00-000/c/x86_64/lib:$LD_LIBRARY_PATH编写示例代码,命名为 test.c
编译示例代码:
gcc test.c -L /home/lightdb/LightDB1.0-unisql-V202403-00-000/c/x86_64/lib -I /home/lightdb/LightDB1.0-unisql-V202403-00-000/c/x86_64/include -lunisql -o test执行示例代码查看效果
示例代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "unisql.h"
#include "unisql_dbtype.h"
int main() {
// 数据库类型见unisql.h
// 原始SQL数据库类型
int sourceDbTypeCode=UNISQL_DBTYPE_ORACLE;
// 目标SQL数据库类型
int targetDbTypeCode=UNISQL_DBTYPE_GAUSSDB_ORACLE;
// 原始SQL
char* sourceSqlStr="SELECT o.order_id, o.order_date, c.customer_name, c.city, o.amount FROM unisql_orders o JOIN unisql_customers c ON o.customer_id = c.customer_id and c.customer_id=? and c.city=?;";
// 目标SQL
char* targetSqlStr=NULL;
// 转换配置选项,预留扩展字段,目前传 NULL 即可
char* jsonParameter = NULL;
// 转换结果 0表示成功,>0表示目标串长度不够,<0表示失败
int transRet=0;
// 预设目标SQL的长度为原始SQL的4倍
int targetSqlStrLen = strlen(sourceSqlStr)*4;
// 分配内存
targetSqlStr=(char*)malloc(targetSqlStrLen);
printf("Before transfer sql is:%s\n",sourceSqlStr);
// 调用TransferSQL转换函数
transRet = TransferSQL(sourceDbTypeCode, targetDbTypeCode, sourceSqlStr, targetSqlStr, targetSqlStrLen, jsonParameter);
if (transRet>0){
// 预设目标SQL的长度不够,重新分配内存
targetSqlStr=(char*) realloc (targetSqlStr, transRet) ;
transRet =TransferSQL (sourceDbTypeCode, targetDbTypeCode, sourceSqlStr, targetSqlStr, transRet, jsonParameter);
}
if(transRet == 0)
{
printf("After transfer sql is:%s\n",targetSqlStr);
}else if(transRet < 0)
{
printf("SQL Convert Failed:%d\n",transRet);
}
// 释放内存
free(targetSqlStr);
return 0;
}
示例执行结果:
Before transfer sql is:SELECT o.order_id, o.order_date, c.customer_name, c.city, o.amount FROM unisql_orders o JOIN unisql_customers c ON o.customer_id = c.customer_id and c.customer_id=? and c.city=?;
After transfer sql is:SELECT o.order_id,o.order_date,c.customer_name,c.city,o.amount FROM unisql_orders AS o JOIN unisql_customers AS c ON o.customer_id=c.customer_id AND c.customer_id=? AND c.city=?
1.9.2.3. UnisqlParseSimpleStatement接口
1.9.2.3.1. 接口说明
接口签名:
extern char* UnisqlParseSimpleStatement(const char* sourceSql);
要使用 C 接口,您需要发布包中对应操作系统平台的 so 动态库,以及 unisql.h 头文件。
1.9.2.3.2. 接口请求参数
UnisqlParseSimpleStatement接口的每一项参数说明如下:
参数名 |
类型 |
是否必须 |
说明 |
示例 |
|---|---|---|---|---|
sourceSql |
const char* |
是 |
用户输入的待解析的SQL语句, 只支持针对单表的简单增删改查语句 |
"select * from t1 where c1 = 2 and c2 = 3" |
1.9.2.3.3. 接口返回参数
UnisqlParseSimpleStatement 接口返回类型是一个char*, 是解析结果的序列化形式, 包含内容: set子句和where子句后面的键值对、表名、语句类型、解析状态、是否存在where子句
ParseStatus: 解析状态,0 成功, -1 失败
SourceType: SQL类型, 1 insert、2 update、3 delete、4 select
TableName: 表名
ExistsWhere: 是否存在where子句,对于insert语句,表示是否指定了列名
SetClause: set子句中的键值对
WhereClause: where子句中的键值对
1.9.2.3.4. 调用示例
本例子假设统一 SQL 的发布包放在 /home/lightdb/LightDB1.0-unisql-V202403-00-000 下,示例步骤为:
设置环境变量,为了运行示例:
export LD_LIBRARY_PATH=/home/lightdb/LightDB1.0-unisql-V202403-00-000/c/x86_64/lib:$LD_LIBRARY_PATH编写示例代码,命名为 test.c
编译示例代码:
gcc test.c -L /home/lightdb/LightDB1.0-unisql-V202403-00-000/c/x86_64/lib -I /home/lightdb/LightDB1.0-unisql-V202403-00-000/c/x86_64/include -lunisql -o test执行示例代码查看效果
示例代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "unisql.h"
#include "unisql_dbtype.h"
int main() {
const char* sql = "select * from t1 where c1 = 1 and c2 = 2";
char* parseResult = NULL;
parseResult = UnisqlParseSimpleStatement(sql);
printf("%s\n", parseResult);
// 释放内存
free(parseResult);
return 0;
}
示例执行结果:
parseStatus: 0, sourceType: 4, tableName: "t1", existsWhere: true, setClause: [], whereClause: [{"c1" "1"} {"c2" "2"}]
1.9.2.4. UnisqlParseSimpleStatementInfo接口
1.9.2.4.1. 接口说明
接口签名:
extern char* UnisqlParseSimpleStatementInfo(const char* sourceSql);
要使用 C 接口,您需要发布包中对应操作系统平台的 so 动态库,以及 unisql.h 头文件。
1.9.2.4.2. 接口请求参数
UnisqlParseSimpleStatementInfo接口的每一项参数说明如下:
参数名 |
类型 |
是否必须 |
说明 |
示例 |
|---|---|---|---|---|
sourceSql |
const char* |
是 |
用户输入的待解析的SQL语句, 只支持针对单表的简单增删改查语句 |
"select * from t1 where c1 = 2 and c2 = 3" |
1.9.2.4.3. 接口返回参数
UnisqlParseSimpleStatementInfo 接口返回类型是一个char*, 是解析结果的序列化形式, 包含内容: where子句的字符串、表名、是否多表、语句类型、解析状态、是否存在where子句、insert语句的键值对、update语句的where子句中第一个绑定变量的下标
ParseStatus: 解析状态,0 成功, -1 失败
MultiTable: 是否操作多表
SourceType: SQL类型, 1 insert、2 update、3 delete、4 select
TableName: 表名
ExistsWhere: 是否存在where子句, 对于insert语句, 表示是否指定了列名
InsertKV: insert语句中的列名和值
WhereCondition: where子句的条件
WhereBindParamPos: update语句的where子句中第一个绑定变量的下标(从1开始), 0表示没有绑定变量
1.9.2.4.4. 调用示例
本例子假设统一 SQL 的发布包放在 /home/lightdb/LightDB1.0-unisql-V202403-00-000 下,示例步骤为:
设置环境变量,为了运行示例:
export LD_LIBRARY_PATH=/home/lightdb/LightDB1.0-unisql-V202403-00-000/c/x86_64/lib:$LD_LIBRARY_PATH编写示例代码,命名为 test.c
编译示例代码:
gcc test.c -L /home/lightdb/LightDB1.0-unisql-V202403-00-000/c/x86_64/lib -I /home/lightdb/LightDB1.0-unisql-V202403-00-000/c/x86_64/include -lunisql -o test执行示例代码查看效果
示例代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "unisql.h"
int main() {
const char* sql = "select * from t1 where c1 = 1 and c2 = 2";
char* parseResult = NULL;
parseResult = UnisqlParseSimpleStatementInfo(sql);
printf("%s\n", parseResult);
// 释放内存
free(parseResult);
return 0;
}
示例执行结果:
parseStatus: 0, multiTable: false, sourceType: 4, tableName: "t1", existsWhere: true, insertKV: [], whereCondition: "c1=1 AND c2=2", whereBindParamPos: 0
1.9.2.5. UnisqlParseSimpleStatementInfoWithBuffer接口
1.9.2.5.1. 接口说明
解析简单SQL语句并返回解析信息(缓冲区模式)。与 UnisqlParseSimpleStatementInfo 功能相同,但采用调用者预分配缓冲区的方式,避免内存分配开销,适合高频调用场景。
接口签名:
extern int UnisqlParseSimpleStatementInfoWithBuffer(
const char* sourceSql,
char* buf,
int bufSize);
要使用 C 接口,您需要发布包中对应操作系统平台的 so 动态库,以及 unisql.h 头文件。
1.9.2.5.2. 接口请求参数
参数名 |
类型 |
是否必须 |
说明 |
示例 |
|---|---|---|---|---|
sourceSql |
const char* |
是 |
用户输入的待解析的SQL语句, 只支持针对单表的简单增删改查语句 |
"select * from t1 where c1 = 2 and c2 = 3" |
buf |
char* |
是 |
解析结果的输出缓冲区,内存由调用方自行管理 |
buffer |
bufSize |
int |
是 |
buf 的内存大小 |
推荐使用原有sql长度的10倍 |
1.9.2.5.3. 接口返回参数
返回类型是一个 int ,取值有以下情况:
返回 0: 代表解析成功,结果写入 buf 中
返回 -1: 代表参数错误(sourceSql为NULL、buf为NULL、bufSize<=0)
返回 -10001: 代表SQL解析失败
返回 -10002: 代表多表操作不支持
返回 -10003: 代表INSERT多行不支持
返回 -10004: 代表UPDATE表别名不支持
返回 -10005: 代表DELETE表别名不支持
返回 -10006: 代表SELECT表别名不支持
返回 -10007: 代表INSERT列名和值数量不匹配
返回大于 0 的数字:代表传入的 bufSize 空间不足,返回值表示需要的空间大小
1.9.2.5.4. 解析结果格式
解析成功时,buf 中存储的内容格式与 UnisqlParseSimpleStatementInfo 相同:
ParseStatus: 解析状态,0 成功, -1 失败
MultiTable: 是否操作多表
SourceType: SQL类型, 1 insert、2 update、3 delete、4 select
TableName: 表名
ExistsWhere: 是否存在where子句, 对于insert语句, 表示是否指定了列名
InsertKV: insert语句中的列名和值
WhereCondition: where子句的条件
WhereBindParamPos: update语句的where子句中第一个绑定变量的下标(从1开始), 0表示没有绑定变量
1.9.2.5.5. 调用示例
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "unisql.h"
int main() {
const char* sql = "select * from t1 where c1 = 1 and c2 = 2";
// 预分配缓冲区
int bufSize = 4096;
char* buf = (char*)malloc(bufSize);
int ret;
// 调用解析函数
ret = UnisqlParseSimpleStatementInfoWithBuffer(sql, buf, bufSize);
if (ret > 0) {
// 缓冲区不足,重新分配
buf = (char*)realloc(buf, ret);
ret = UnisqlParseSimpleStatementInfoWithBuffer(sql, buf, ret);
}
if (ret == 0) {
printf("Parse result: %s\n", buf);
} else {
printf("Parse failed: %d\n", ret);
}
// 释放内存
free(buf);
return 0;
}
示例执行结果:
Parse result: parseStatus: 0, multiTable: false, sourceType: 4, tableName: "t1", existsWhere: true, insertKV: [], whereCondition: "c1=1 AND c2=2", whereBindParamPos: 0
1.9.2.6. TransferSQLWithBindInfo接口
1.9.2.6.1. 接口说明
转换SQL语句并返回绑定参数信息(带缓存)。注意:本接口仅支持Linux平台,Windows版本不支持。
接口签名:
extern int TransferSQLWithBindInfo(
int sourceDbTypeCode,
int targetDbTypeCode,
const char* sourceSqlStr,
char* targetSqlStr,
int targetSqlStrLen,
int** bindVariableOrder,
int* bindVariableOrderSize,
const char* jsonParameter);
1.9.2.6.2. 接口请求参数
参数名 |
类型 |
是否必须 |
说明 |
示例 |
|---|---|---|---|---|
sourceDbTypeCode |
int |
是 |
源数据库方言编码,见 |
UNISQL_DBTYPE_ORACLE |
targetDbTypeCode |
int |
是 |
目标数据库方言编码,见 |
UNISQL_DBTYPE_GOLDENDB_MYSQL |
sourceSqlStr |
const char* |
是 |
源SQL语句 |
"SELECT lpad(?, 10) FROM t" |
targetSqlStr |
char* |
是 |
转换后的SQL内存空间,内存由调用方自行管理 |
buffer |
targetSqlStrLen |
int |
是 |
targetSqlStr 的内存大小 |
1024 |
bindVariableOrder |
int** |
是 |
绑定参数顺序数组指针,输出参数。指向的内存位于targetSqlStr末尾,无需单独释放 |
&bindOrder |
bindVariableOrderSize |
int* |
是 |
绑定参数顺序数组大小,输出参数。为0表示绑定参数不存在或未修改 |
&bindSize |
jsonParameter |
const char* |
否 |
json格式的选项,预留未使用 |
NULL |
1.9.2.6.3. 接口返回参数
返回类型是一个 int ,取值有 3 种情况:
返回 0: 代表转换成功
返回 -1: 代表转换异常失败
返回大于 0 的数字:代表传入的 targetSqlStrLen 空间不足,返回值表示需要的空间(包括目标SQL和绑定参数信息大小)
1.9.2.6.4. 重要说明
内存结构:bindVariableOrder 指向的整型数组内存在 targetSqlStr 末尾。最终 targetSqlStr 内存结构为:targetSql(包括末尾空字符)+ bindVariableOrder + 未使用内存
内存管理:bind数组无需单独释放,会跟随 targetSql 一起释放。在 targetSql 释放后就不能再访问 bind 数组
绑定参数映射:bindVariableOrder 下标 0 表示新绑定参数的第1个位置对应的旧的绑定参数位置。例如:bindVariableOrder[0]=2, bindVariableOrder[1]=1 表示新绑定参数的第1个位置对应旧绑定参数的第2个位置,新绑定参数的第2个位置对应旧绑定参数的第1个位置
无变化情况:若绑定参数不存在,或者参数信息没改变,bindVariableOrderSize 为0,bindVariableOrder 指向的内存为NULL
1.9.2.6.5. 调用示例
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "unisql.h"
#include "unisql_dbtype.h"
int main() {
// 数据库类型
int sourceDbTypeCode = UNISQL_DBTYPE_ORACLE;
int targetDbTypeCode = UNISQL_DBTYPE_GOLDENDB_MYSQL;
// 原始SQL:lpad函数在转换时会导致绑定参数重复
char* sourceSqlStr = "SELECT lpad(?, 10) FROM t WHERE id = ?";
// 分配目标SQL内存(源SQL的4倍长度)
int targetSqlStrLen = strlen(sourceSqlStr) * 4;
char* targetSqlStr = (char*)malloc(targetSqlStrLen);
// 绑定参数顺序输出参数
int* bindVariableOrder = NULL;
int bindVariableOrderSize = 0;
printf("Before transfer sql is: %s\n", sourceSqlStr);
// 调用TransferSQLWithBindInfo转换函数
int transRet = TransferSQLWithBindInfo(
sourceDbTypeCode,
targetDbTypeCode,
sourceSqlStr,
targetSqlStr,
targetSqlStrLen,
&bindVariableOrder,
&bindVariableOrderSize,
NULL
);
if (transRet > 0) {
// 内存不足,重新分配
targetSqlStr = (char*)realloc(targetSqlStr, transRet);
transRet = TransferSQLWithBindInfo(
sourceDbTypeCode,
targetDbTypeCode,
sourceSqlStr,
targetSqlStr,
transRet,
&bindVariableOrder,
&bindVariableOrderSize,
NULL
);
}
if (transRet == 0) {
printf("After transfer sql is: %s\n", targetSqlStr);
printf("Bind variable order size: %d\n", bindVariableOrderSize);
// 打印绑定参数顺序映射
if (bindVariableOrderSize > 0) {
printf("Bind variable order mapping:\n");
for (int i = 0; i < bindVariableOrderSize; i++) {
printf(" New position %d -> Old position %d\n",
i + 1, bindVariableOrder[i]);
}
}
} else {
printf("SQL Convert Failed: %d\n", transRet);
}
// 释放内存
free(targetSqlStr);
return 0;
}
示例执行结果:
Before transfer sql is: SELECT lpad(?, 10) FROM t WHERE id = ?
After transfer sql is: SELECT if(length(?)=0 OR length(10)=0 OR 10=0, NULL, lpad(?, 10, ' ')) FROM t WHERE id=?
Bind variable order size: 2
Bind variable order mapping:
New position 1 -> Old position 1
New position 2 -> Old position 1
1.9.2.7. UnisqlTransformSQLWithBindInfo接口
1.9.2.7.1. 接口说明
转换SQL语句并返回绑定参数信息(无缓存版本)。与 TransferSQLWithBindInfo 功能相同,但不使用缓存。
接口签名:
extern int UnisqlTransformSQLWithBindInfo(
int sourceDbTypeCode,
int targetDbTypeCode,
const char* sourceSqlStr,
char* targetSqlStr,
int targetSqlStrLen,
int** bindVariableOrder,
int* bindVariableOrderSize,
const char* jsonParameter);
1.9.2.7.2. 接口请求参数
参数与 TransferSQLWithBindInfo 完全相同,请参考上文。
1.9.2.7.3. 接口返回参数
返回类型与 TransferSQLWithBindInfo 完全相同,请参考上文。
1.9.2.7.4. 重要说明
与 TransferSQLWithBindInfo 的区别:
无缓存:本接口不使用缓存,每次调用都会进行完整的SQL转换
适用场景:适用于不需要缓存或对缓存敏感的场景
性能:由于不使用缓存,相同SQL的重复转换性能会低于 TransferSQLWithBindInfo
1.9.2.7.5. 调用示例
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "unisql.h"
#include "unisql_dbtype.h"
int main() {
// 数据库类型
int sourceDbTypeCode = UNISQL_DBTYPE_ORACLE;
int targetDbTypeCode = UNISQL_DBTYPE_GOLDENDB_MYSQL;
// 原始SQL:lpad函数在转换时会导致绑定参数重复
char* sourceSqlStr = "SELECT lpad(?, 10) FROM t WHERE id = ?";
// 分配目标SQL内存(源SQL的4倍长度)
int targetSqlStrLen = strlen(sourceSqlStr) * 4;
char* targetSqlStr = (char*)malloc(targetSqlStrLen);
// 绑定参数顺序输出参数
int* bindVariableOrder = NULL;
int bindVariableOrderSize = 0;
printf("Before transfer sql is: %s\n", sourceSqlStr);
// 调用TransferSQLWithBindInfo转换函数
int transRet = UnisqlTransformSQLWithBindInfo(
sourceDbTypeCode,
targetDbTypeCode,
sourceSqlStr,
targetSqlStr,
targetSqlStrLen,
&bindVariableOrder,
&bindVariableOrderSize,
NULL
);
if (transRet > 0) {
// 内存不足,重新分配
targetSqlStr = (char*)realloc(targetSqlStr, transRet);
transRet = UnisqlTransformSQLWithBindInfo(
sourceDbTypeCode,
targetDbTypeCode,
sourceSqlStr,
targetSqlStr,
transRet,
&bindVariableOrder,
&bindVariableOrderSize,
NULL
);
}
if (transRet == 0) {
printf("After transfer sql is: %s\n", targetSqlStr);
printf("Bind variable order size: %d\n", bindVariableOrderSize);
// 打印绑定参数顺序映射
if (bindVariableOrderSize > 0) {
printf("Bind variable order mapping:\n");
for (int i = 0; i < bindVariableOrderSize; i++) {
printf(" New position %d -> Old position %d\n",
i + 1, bindVariableOrder[i]);
}
}
} else {
printf("SQL Convert Failed: %d\n", transRet);
}
// 释放内存
free(targetSqlStr);
return 0;
}
示例执行结果:
Before transfer sql is: SELECT lpad(?, 10) FROM t WHERE id = ?
After transfer sql is: SELECT if(length(?)=0 OR length(10)=0 OR 10=0, NULL, lpad(?, 10, ' ')) FROM t WHERE id=?
Bind variable order size: 2
Bind variable order mapping:
New position 1 -> Old position 1
New position 2 -> Old position 1