JSON操作¶
神通数据库中支持Json数据类型,Oracle在20C版本中也支持了Json类型,对应的ACI中也有了Json操作的一些接口,本章节也是对这些新增的Json接口在神通ACI中进行实现。Json数据类型ACIJson描述符对应,ACIJson需要用 ACIDescriptorAlloc 方法分配内存,分配时的描述符句柄类型为ACI_DTYPE_JSON,用 ACIDescriptorFree 进行释放。对于Json类型的绑定和定义时用SQLT_JSON类型。
由于Json类型的表现形式和字符串差不多,因此可以通过字符串相关方式进行读写,比如SQLT_CHR、SQLT_STR、SQLT_CVS等。
对于ACI,有多种方式对Json数据进行返回,可以按照字节、也可以按照字符方式,目前ACI使用了按照字节的方式对Json操作。
备注:
1) 由于Json的数据会完整的放到ACIJson描述符中,且神通数据库的Json类型最大长度为16M,如果一个Json比较大,ACI中对应ACIJson描述符会占用较大内存,建议使用后立即释放。
2) 写入到数据库中的Json会被格式化(格式化会增减空格以及对键值的顺序进行重新排列),可能会导致数据库中Json与应用插入时的Json字符串长度不一致等情况。
3) 调用ACI接口操作Json类型时,请确保当前数据库是支持Json数据类型的。
Json数据查询¶
通过 ACIDescriptorAlloc 分配ACIJson描述后,用 ACIDefineByPos 进行定义,定义类型为SQLT_JSON, ACIStmtExecute 执行后可对ACIJson描述符进行数据查询操作。查询Json流程如下:
ACI提供了ACIJsonBinaryLengthGet来获得ACIJson描述符中Json数据的长度,通过ACIJsonToBinaryBuffer方法将数据读取到定义的buf变量中,比如:
/*
数据库中的表结构和数据
create table t_json (a json)
insert into t_json values ('{"key1": "value1", "key2": "value2"}')
*/
ACIJson * pJson = NULL;
ACIDefine *def = NULL;
sword r = 0;
char *selectSql = "select * from t_json";
char jsonread[1024] = "";
ub8 byte_amtp = 1024;
....
ACIDescriptorAlloc(env, (void **)&pJson, ACI_DTYPE_JSON, 0, 0);
ACIStmtPrepare(stmt, err, (const OraText *)selectSql,(ub4)strlen(selectSql), ACI_HTYPE_ERROR, ACI_DEFAULT);
ACIDefineByPos(stmt, &def, err, 1, (void *)&pJson,sizeof(pJson), SQLT_JSON, (void *)0, 0,(ub2*)0, ACI_DEFAULT);
ACIStmtExecute(svc, stmt, err, 1, 0, 0, 0, ACI_DEFAULT);
ACIJsonBinaryLengthGet(svc, pJson, &byte_amtp, err, ACI_DEFAULT);
ACIJsonToBinaryBuffer(svc, pJson, (ub1*)jsonread, &byte_amtp, err, ACI_DEFAULT); //执行完成后:jsonread中的数据为:{"key1": "value1", "key2": "value2"}
.....
备注:一定要调用 ACIDescriptorFree 对ACIJson描述符进行释放。
Json数据写入¶
通过 ACIDescriptorAlloc 分配ACIJson描述后,用 ACIBindByPos 进行绑定,绑定类型为SQLT_JSON, ACIStmtExecute 执行后可对ACIJson描述符进行数据查询操作。操作流程如下:
ACI提供了ACIJsonBinaryBufferLoad来将一个char*变量的数据写入到ACIJson描述符中,如下:
/*数据库中的表结构和数据
create table t_json (a json);
insert into t_json values ('{"key1": "value1", "key2": "value2"}');*/
ACIJson* pJson = NULL;
ACIBind* bnd = NULL;
int insertCount = 0;
sword r = 0;
char* insertSql = "insert into t_json values (:1)";
char* jsondata = "{\"key1\":\"value1\",\"key2\":\"value2\"}";
......
r = ACIDescriptorAlloc(env, (void **)&pJson, ACI_DTYPE_JSON, 0, 0);
//往pJson中写入数据
{
ub8 byte_amtp = strlen(jsondata);
r = ACIJsonBinaryBufferLoad(svc, pJson, (ub1*)jsondata, byte_amtp, err, ACI_DEFAULT);
byte_amtp = 0;
r = ACIJsonBinaryLengthGet(svc, pJson, &byte_amtp, err, ACI_DEFAULT);
EXPECT_EQ(byte_amtp, strlen(jsondata));
}
r = ACIStmtPrepare(stmt, err, (const OraText *)insertSql,
(ub4)strlen(insertSql), ACI_HTYPE_ERROR, ACI_DEFAULT);
EXPECT_EQ(ACI_SUCCESS, r);
r = ACIBindByPos(stmt, &bnd, err, 1, (void *)&pJson, sizeof(pJson),
SQLT_JSON, (void *)0, (ub2 *)0, (ub2 *)0, 0, 0,
ACI_DEFAULT);
EXPECT_EQ(ACI_SUCCESS, r);
//插入数据
r = ACIStmtExecute(svc, stmt, err, 1, 0, 0, 0, ACI_COMMIT_ON_SUCCESS);
EXPECT_EQ(ACI_SUCCESS, r);
.....
//ACIStmtExecute执行完成后,数据库中会多一条插入的数据
备注:一定要调用 ACIDescriptorFree 对ACIJson描述符进行释放。
Json数据复制¶
ACI支持将一个ACIJson描述符复制给另外一个ACIJson描述符,复制后两者的中的Json数据完全一样,ACI通过ACIJsonClone接口来实现拷贝,将源端的ACIJson描述符拷贝给目的端,使用方式如下:
ACIJson * sJson = NULL;
ACIJson * dJson = NULL;
char *jsondata = "{\"key1\": \"value1\", \"key2\": \"value2\"}";
char jsonread[1024] = "";
sword r = 0;
ub8 byte_amtp_s = 0;
ub8 byte_amtp_d = 0;
......
//构造一个源的ACIJson描述符,并写入数据
{
r = ACIDescriptorAlloc(env, (void **)&sJson, ACI_DTYPE_FILE, 0, 0);
//往sJson写入数据
byte_amtp_s = strlen(jsondata);
r = ACIJsonBinaryBufferLoad(svc, sJson, (ub1*)jsondata, byte_amtp_s, err, ACI_DEFAULT);
byte_amtp = 0;
r = ACIJsonBinaryLengthGet(svc, sJson, &byte_amtp_s, err, ACI_DEFAULT);
}
//构造一个目的端的ACIJson描述符,并进行克隆
{
r = ACIDescriptorAlloc(env, (void **)&dJson, ACI_DTYPE_JSON, 0, 0);
//克隆
r = ACIJsonClone(svc, sJson, dJson, err, ACI_DEFAULT);
r = ACIJsonBinaryLengthGet(svc, dJson, &byte_amtp_d, err, ACI_DEFAULT);
//byte_amtp_d 和 byte_amtp_s 长度应该完全相同
}
r = ACIDescriptorFree((void *)sJson, ACI_DTYPE_JSON);
r = ACIDescriptorFree((void *)dJson, ACI_DTYPE_JSON);
其他方式Json读写¶
由于Json类型的表现形式和字符串差不多,因此可以通过字符串相关方式进行读写,比如SQLT_CHR、SQLT_STR、SQLT_CVS等。
- SQLT_CHR插入:
/*数据库中的表结构和数据
create table t_json (a json);*/
ACIBind *bnd = NULL;
sword r = 0;
char *insertSql = "insert into t_json values (:1)";
char *jsondata = "{\"key1\":\"value1\",\"key2\":\"value2\"}";
......
r = ACIStmtPrepare(stmt, err, insertSql,
(ub4)strlen(insertSql), ACI_HTYPE_ERROR, ACI_DEFAULT);
r = ACIBindByPos(stmt, &bnd, err, 1, (void *)jsondata, strlen(jsondata),SQLT_CHR, (void *)0, (ub2 *)0, (ub2 *)0, 0, 0,ACI_DEFAULT);
//插入数据
r = ACIStmtExecute(svc, stmt, err, 1, 0, 0, 0, ACI_COMMIT_ON_SUCCESS);
//ACIStmtExecute成功执行后,会将jsondata数据插入到数据库中。
.....
- SQLT_CHR查询:
/*数据库中的表结构和数据
create table t_json (a json);
insert into t_json values ('{"key1": "value1", "key2": "value2"}');*/
ACIDefine *def = NULL;
sword r = 0;
char *selectSql = "select * from t_json";
char jsonread[1024] = "";
r = ACIStmtPrepare(stmt, err, selectSql,
(ub4)strlen(selectSql), ACI_HTYPE_ERROR, ACI_DEFAULT);
r = ACIDefineByPos(stmt, &def, err, 1, (void *)jsonread,
sizeof(jsonread), SQLT_CHR, (void *)0, 0,
(ub2*)0, ACI_DEFAULT);
//插入数据
r = ACIStmtExecute(svc, stmt, err, 1, 0, 0, 0, ACI_DEFAULT);
//ACIStmtExecute成功执行后,预取了一条数据放到jsonread中,可以看到和数据库中的数据一致
.....
- SQLT_STR插入:
/*数据库中的表结构和数据
create table t_json (a json);*/
ACIBind *bnd = NULL;
sword r = 0;
char *insertSql = "insert into t_json values (:1)";
char *jsondata = "{\"key1\":\"value1\",\"key2\":\"value2\"}";
......
r = ACIStmtPrepare(stmt, err, insertSql,
(ub4)strlen(insertSql), ACI_HTYPE_ERROR, ACI_DEFAULT);
r = ACIBindByPos(stmt, &bnd, err, 1, (void *)jsondata, strlen(jsondata)+1,SQLT_STR, (void *)0, (ub2 *)0, (ub2 *)0, 0, 0,ACI_DEFAULT);
//插入数据
r = ACIStmtExecute(svc, stmt, err, 1, 0, 0, 0, ACI_COMMIT_ON_SUCCESS);
//ACIStmtExecute成功执行后,会将jsondata数据插入到数据库中。
.....
- SQLT_STR查询:
/*数据库中的表结构和数据
create table t_json (a json);
insert into t_json values ('{"key1": "value1", "key2": "value2"}');*/
ACIDefine *def = NULL;
sword r = 0;
char *selectSql = "select * from t_json";
char jsonread[1024] = "";
r = ACIStmtPrepare(stmt, err, selectSql,
(ub4)strlen(selectSql), ACI_HTYPE_ERROR, ACI_DEFAULT);
r = ACIDefineByPos(stmt, &def, err, 1, (void *)jsonread,
sizeof(jsonread), SQLT_STR, (void *)0, 0,
(ub2*)0, ACI_DEFAULT);
//插入数据
r = ACIStmtExecute(svc, stmt, err, 1, 0, 0, 0, ACI_DEFAULT);
//ACIStmtExecute成功执行后,预取了一条数据放到jsonread中,可以看到和数据库中的数据一致
.....
- SQLT_VCS插入:
/*数据库中的表结构和数据
create table t_json (a json)*/
ACIBind *bnd = NULL;
sword r = 0;
char *insertSql = "insert into t_json values (:1)";
char *jsondata = "{\"key1\":\"value1\",\"key2\":\"value2\"}";
char * jsondatatmp = (char *)malloc(1024);
memset(jsondatatmp, 0, 1024 );
ub2 len = strlen(jsondata);
memcpy(jsondatatmp, &len, 2);
memcpy(jsondatatmp + 2, jsondata, len);
......
r = ACIStmtPrepare(stmt, err, insertSql,(ub4)strlen(insertSql), ACI_HTYPE_ERROR, ACI_DEFAULT);
r = ACIBindByPos(stmt, &bnd, err, 1, (void *)jsondatatmp, strlen(jsondata) + 2, SQLT_VCS, (void *)0, (ub2 *)0, (ub2 *)0, 0, 0, ACI_DEFAULT);
//插入数据
r = ACIStmtExecute(svc, stmt, err, 1, 0, 0, 0, ACI_COMMIT_ON_SUCCESS);
//ACIStmtExecute成功执行后,会将数据插入到数据库中。
.....
- SQLT_VCS查询:
/*数据库中的表结构和数据
create table t_json (a json);
insert into t_json values ('{"key1": "value1", "key2": "value2"}');*/
ACIDefine *def = NULL;
sword r = 0;
char *selectSql = "select * from t_json";
char jsonread[1024] = "";
r = ACIStmtPrepare(stmt, err, selectSql,
(ub4)strlen(selectSql), ACI_HTYPE_ERROR, ACI_DEFAULT);
r = ACIDefineByPos(stmt, &def, err, 1, (void *)jsonread,
sizeof(jsonread), SQLT_VCS, (void *)0, 0,
(ub2*)0, ACI_DEFAULT);
//插入数据
r = ACIStmtExecute(svc, stmt, err, 1, 0, 0, 0, ACI_DEFAULT);
//ACIStmtExecute成功执行后,预取了一条数据放到jsonread中,且jsonread前两个字节是标识数据长度(*(ub2*)jsonread)与插入数据长度strlen(jsondata)一致。
.....