背景介绍
为了方便ORACLE数据库迁移到LightDB数据库,兼容Pro*C的语法规则。从LightDB24.1版本开始ECPG支持EXEC ORACLE OPTION(CHAR_MAP=STRING)。设置该选项后,将保证字符数组已null结尾。
使用约束:
- 仅支持一维字符数组,保证一维字符数组已null结尾。
- 仅支持select into到本地数组,保证本地数组null结尾。
使用示例
- ecpg源文件
#include <stdio.h>
#include <stdlib.h>
EXEC ORACLE OPTION (RELEASE_cursor = No);
EXEC ORACLE OPTION (char_map=String);
exec sql type string is char[5];
typedef char string[5];
EXEC SQL BEGIN DECLARE SECTION;
struct TBempl
{
char a;
char b[5];
};
union StateMachine
{
char c1[5];
int c2;
};
EXEC SQL END DECLARE SECTION;
int main()
{
EXEC SQL BEGIN DECLARE SECTION;
struct TBempl v1;
struct TBempl v2;
int i = 0;
int j = 0;
string s1;
string s2[2];
char arr[2][5];
struct TBempl v3[2];
union StateMachine u1;
EXEC SQL END DECLARE SECTION;
EXEC SQL WHENEVER SQLWARNING SQLPRINT;
EXEC SQL WHENEVER SQLERROR SQLPRINT;
char cc[5];
EXEC SQL CONNECT TO oracle_test AS main;
EXEC SQL SELECT c1,c2 INTO :v1 from test_struct;
EXEC SQL SELECT c2 INTO :v2.b from test_struct;
EXEC SQL SELECT name INTO :s1 from test;
EXEC SQL SELECT name INTO :s2 from test2;
EXEC SQL SELECT name INTO :arr from test2;
EXEC SQL SELECT name INTO :u1.c1 from test;
EXEC SQL SELECT name INTO :cc from test;
EXEC SQL SELECT c1,c2 INTO :v3 from test_struct2;
printf("===============struct v1================\n");
printf("Print ASCII:%x\n",(unsigned char)v1.a);
printf("======================================\n");
for(i=0;i<5;i++) {
printf("Print ASCII:%x\n",(unsigned char)v1.b[i]);
}
printf("===============struct v2================\n");
//printf("Print ASCII:%x\n",(unsigned char)v1.a);
printf("======================================\n");
for(i=0;i<5;i++) {
printf("Print ASCII:%x\n",(unsigned char)v2.b[i]);
}
printf("================string s1===================\n");
for(i=0;i<5;i++) {
printf("Print ASCII:%x\n",(unsigned char)s1[i]);
}
printf("================string s2[2]===================\n");
for(i=0;i<5;i++) {
printf("Print ASCII:%x\n",(unsigned char)s2[0][i]);
}
printf("======================================\n");
for(i=0;i<5;i++) {
printf("Print ASCII:%x\n",(unsigned char)s2[1][i]);
}
printf("================union u1.c1===================\n");
for(i=0;i<5;i++) {
printf("Print ASCII:%x\n",(unsigned char)u1.c1[i]);
}
printf("================arr[2][5]===================\n");
for (i=0;i<5;i++)
{
printf("Print ASCII:%x\n",(unsigned char)arr[0][i]);
}
for (i=0;i<5;i++)
{
printf("Print ASCII:%x\n",(unsigned char)arr[1][i]);
}
printf("================cc[5]===================\n");
for (i=0;i<5;i++)
{
printf("Print ASCII:%x\n",(unsigned char)cc[i]);
}
printf("================v3[2]===================\n");
printf("Print ASCII:%x\n",(unsigned char)v3[0].a);
printf("======================================\n");
for(i=0;i<5;i++) {
printf("Print ASCII:%x\n",(unsigned char)v3[0].b[i]);
}
printf("======================================\n");
printf("Print ASCII:%x\n",(unsigned char)v3[1].a);
printf("======================================\n");
for(i=0;i<5;i++) {
printf("Print ASCII:%x\n",(unsigned char)v3[1].b[i]);
}
EXEC SQL SELECT c1,c2 INTO :v3[1] from test_struct;
printf("================v3[1]===================\n");
printf("Print ASCII:%x\n",(unsigned char)v3[1].a);
printf("======================================\n");
for(i=0;i<5;i++) {
printf("Print ASCII:%x\n",(unsigned char)v3[1].b[i]);
}
EXEC SQL DISCONNECT;
}
- 编译pgc文件生成c文件,ecpg ecpg_struct.pgc -o ecpg_struct.c
/* Processed by ecpg (13.8) */
/* These include files are added by the preprocessor */
#include <ecpglib.h>
#include <ecpgerrno.h>
#include <sqlca.h>
/* End of automatic include section */
#line 1 "ecpg_struct.pgc"
#include <stdio.h>
#include <stdlib.h>
/* exec oracle option (RELEASE_cursor=No) */
/* exec oracle option (char_map=String) */
/* exec sql type string is char [ 5 ] */
#line 7 "ecpg_struct.pgc"
typedef char string [ 5 ];
#line 8 "ecpg_struct.pgc"
#line 8 "ecpg_struct.pgc"
/* exec sql begin declare section */
struct TBempl {
#line 13 "ecpg_struct.pgc"
char a ;
#line 14 "ecpg_struct.pgc"
char b [ 5 ] ;
} ; union StateMachine {
#line 19 "ecpg_struct.pgc"
char c1 [ 5 ] ;
#line 20 "ecpg_struct.pgc"
int c2 ;
} ;/* exec sql end declare section */
#line 22 "ecpg_struct.pgc"
int main ( )
#line 24 "ecpg_struct.pgc"
{
/* exec sql begin declare section */
#line 27 "ecpg_struct.pgc"
struct TBempl v1 ;
#line 28 "ecpg_struct.pgc"
struct TBempl v2 ;
#line 29 "ecpg_struct.pgc"
int i = 0 ;
#line 30 "ecpg_struct.pgc"
int j = 0 ;
#line 31 "ecpg_struct.pgc"
string s1 ;
#line 32 "ecpg_struct.pgc"
string s2 [ 2 ] ;
#line 33 "ecpg_struct.pgc"
char arr [ 2 ] [ 5 ] ;
#line 34 "ecpg_struct.pgc"
struct TBempl v3 [ 2 ] ;
#line 35 "ecpg_struct.pgc"
union StateMachine u1 ;
/* exec sql end declare section */
#line 36 "ecpg_struct.pgc"
/* exec sql whenever sql_warning sqlprint ; */
#line 37 "ecpg_struct.pgc"
/* exec sql whenever sqlerror sqlprint ; */
#line 38 "ecpg_struct.pgc"
#line 40 "ecpg_struct.pgc"
char cc [ 5 ] ;
#line 40 "ecpg_struct.pgc"
{ ECPGconnect(__LINE__, 0, "oracle_test", NULL, NULL, "main", 0);
#line 41 "ecpg_struct.pgc"
if (sqlca.sqlwarn[0] == 'W') sqlprint();
#line 41 "ecpg_struct.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 41 "ecpg_struct.pgc"
{ struct lt_ecpg_config lt_conf;lt_conf.ecpg_version_num=LT_ECPG_CONFIG_VERSION;lt_conf.oracle_char_map=1;ECPGdo(__LINE__, 0, 1, NULL, 0, <_conf, ECPGst_normal, "select c1, c2 from test_struct", ECPGt_EOIT,
ECPGt_char,&(v1.a),(long)1,(long)1,sizeof( struct TBempl ),0L,
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,&(v1.b),(long)5,(long)1,sizeof( struct TBempl ),1L,
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 44 "ecpg_struct.pgc"
if (sqlca.sqlwarn[0] == 'W') sqlprint();
#line 44 "ecpg_struct.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 44 "ecpg_struct.pgc"
{ struct lt_ecpg_config lt_conf;lt_conf.ecpg_version_num=LT_ECPG_CONFIG_VERSION;lt_conf.oracle_char_map=1;ECPGdo(__LINE__, 0, 1, NULL, 0, <_conf, ECPGst_normal, "select c2 from test_struct", ECPGt_EOIT,
ECPGt_char,(v2.b),(long)5,(long)1,(5)*sizeof(char),1L,
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 45 "ecpg_struct.pgc"
if (sqlca.sqlwarn[0] == 'W') sqlprint();
#line 45 "ecpg_struct.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 45 "ecpg_struct.pgc"
{ struct lt_ecpg_config lt_conf;lt_conf.ecpg_version_num=LT_ECPG_CONFIG_VERSION;lt_conf.oracle_char_map=1;ECPGdo(__LINE__, 0, 1, NULL, 0, <_conf, ECPGst_normal, "select name from test", ECPGt_EOIT,
ECPGt_char,(s1),(long)5,(long)1,(5)*sizeof(char),1L,
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 46 "ecpg_struct.pgc"
if (sqlca.sqlwarn[0] == 'W') sqlprint();
#line 46 "ecpg_struct.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 46 "ecpg_struct.pgc"
{ struct lt_ecpg_config lt_conf;lt_conf.ecpg_version_num=LT_ECPG_CONFIG_VERSION;lt_conf.oracle_char_map=1;ECPGdo(__LINE__, 0, 1, NULL, 0, <_conf, ECPGst_normal, "select name from test2", ECPGt_EOIT,
ECPGt_char,(s2),(long)5,(long)2,(5)*sizeof(char),0L,
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 47 "ecpg_struct.pgc"
if (sqlca.sqlwarn[0] == 'W') sqlprint();
#line 47 "ecpg_struct.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 47 "ecpg_struct.pgc"
{ struct lt_ecpg_config lt_conf;lt_conf.ecpg_version_num=LT_ECPG_CONFIG_VERSION;lt_conf.oracle_char_map=1;ECPGdo(__LINE__, 0, 1, NULL, 0, <_conf, ECPGst_normal, "select name from test2", ECPGt_EOIT,
ECPGt_char,(arr),(long)5,(long)2,(5)*sizeof(char),0L,
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 48 "ecpg_struct.pgc"
if (sqlca.sqlwarn[0] == 'W') sqlprint();
#line 48 "ecpg_struct.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 48 "ecpg_struct.pgc"
{ struct lt_ecpg_config lt_conf;lt_conf.ecpg_version_num=LT_ECPG_CONFIG_VERSION;lt_conf.oracle_char_map=1;ECPGdo(__LINE__, 0, 1, NULL, 0, <_conf, ECPGst_normal, "select name from test", ECPGt_EOIT,
ECPGt_char,(u1.c1),(long)5,(long)1,(5)*sizeof(char),1L,
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 49 "ecpg_struct.pgc"
if (sqlca.sqlwarn[0] == 'W') sqlprint();
#line 49 "ecpg_struct.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 49 "ecpg_struct.pgc"
{ struct lt_ecpg_config lt_conf;lt_conf.ecpg_version_num=LT_ECPG_CONFIG_VERSION;lt_conf.oracle_char_map=1;ECPGdo(__LINE__, 0, 1, NULL, 0, <_conf, ECPGst_normal, "select name from test", ECPGt_EOIT,
ECPGt_char,(cc),(long)5,(long)1,(5)*sizeof(char),0L,
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 50 "ecpg_struct.pgc"
if (sqlca.sqlwarn[0] == 'W') sqlprint();
#line 50 "ecpg_struct.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 50 "ecpg_struct.pgc"
{ struct lt_ecpg_config lt_conf;lt_conf.ecpg_version_num=LT_ECPG_CONFIG_VERSION;lt_conf.oracle_char_map=1;ECPGdo(__LINE__, 0, 1, NULL, 0, <_conf, ECPGst_normal, "select c1, c2 from test_struct2", ECPGt_EOIT,
ECPGt_char,&(v3->a),(long)1,(long)2,sizeof( struct TBempl ),0L,
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,&(v3->b),(long)5,(long)2,sizeof( struct TBempl ),0L,
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 51 "ecpg_struct.pgc"
if (sqlca.sqlwarn[0] == 'W') sqlprint();
#line 51 "ecpg_struct.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 51 "ecpg_struct.pgc"
printf("===============struct v1================\n");
printf("Print ASCII:%x\n",( unsigned char)v1.a);
printf("======================================\n");
for(i=0;i<5;i++) {
printf("Print ASCII:%x\n",( unsigned char)v1.b[i]);
}
printf("===============struct v2================\n");
//printf("Print ASCII:%x\n",(unsigned char)v1.a);
printf("======================================\n");
for(i=0;i<5;i++) {
printf("Print ASCII:%x\n",( unsigned char)v2.b[i]);
}
printf("================string s1===================\n");
for(i=0;i<5;i++) {
printf("Print ASCII:%x\n",( unsigned char)s1[i]);
}
printf("================string s2[2]===================\n");
for(i=0;i<5;i++) {
printf("Print ASCII:%x\n",( unsigned char)s2[0][i]);
}
printf("======================================\n");
for(i=0;i<5;i++) {
printf("Print ASCII:%x\n",( unsigned char)s2[1][i]);
}
printf("================union u1.c1===================\n");
for(i=0;i<5;i++) {
printf("Print ASCII:%x\n",( unsigned char)u1.c1[i]);
}
printf("================arr[2][5]===================\n");
for(i=0;i<5;i++)
{
printf("Print ASCII:%x\n",( unsigned char)arr[0][i]);
}
for(i=0;i<5;i++)
{
printf("Print ASCII:%x\n",( unsigned char)arr[1][i]);
}
printf("================cc[5]===================\n");
for(i=0;i<5;i++)
{
printf("Print ASCII:%x\n",( unsigned char)cc[i]);
}
printf("================v3[2]===================\n");
printf("Print ASCII:%x\n",( unsigned char)v3[0].a);
printf("======================================\n");
for(i=0;i<5;i++) {
printf("Print ASCII:%x\n",( unsigned char)v3[0].b[i]);
}
printf("======================================\n");
printf("Print ASCII:%x\n",( unsigned char)v3[1].a);
printf("======================================\n");
for(i=0;i<5;i++) {
printf("Print ASCII:%x\n",( unsigned char)v3[1].b[i]);
}
{ struct lt_ecpg_config lt_conf;lt_conf.ecpg_version_num=LT_ECPG_CONFIG_VERSION;lt_conf.oracle_char_map=1;ECPGdo(__LINE__, 0, 1, NULL, 0, <_conf, ECPGst_normal, "select c1, c2 from test_struct", ECPGt_EOIT,
ECPGt_char,&(v3[1].a),(long)1,(long)1,sizeof( struct TBempl ),0L,
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,&(v3[1].b),(long)5,(long)1,sizeof( struct TBempl ),1L,
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 108 "ecpg_struct.pgc"
if (sqlca.sqlwarn[0] == 'W') sqlprint();
#line 108 "ecpg_struct.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 108 "ecpg_struct.pgc"
printf("================v3[1]===================\n");
printf("Print ASCII:%x\n",( unsigned char)v3[1].a);
printf("======================================\n");
for(i=0;i<5;i++) {
printf("Print ASCII:%x\n",( unsigned char)v3[1].b[i]);
}
{ ECPGdisconnect(__LINE__, "CURRENT");
#line 116 "ecpg_struct.pgc"
if (sqlca.sqlwarn[0] == 'W') sqlprint();
#line 116 "ecpg_struct.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 116 "ecpg_struct.pgc"
}
- 编译c文件生成bin文件,运行得到结果,会发现只有一维数组添加了null结尾
gcc ecpg_struct.c -lecpg -lpgtypes -o ecpg_charmap -I /home/lightdb/stage/lightdb-x/include/ -L/home/lightdb/stage/lightdb-x/lib
[lightdb@192 ~]$ ./ecpg_charmap
===============struct v1================
Print ASCII:48
======================================
Print ASCII:41
Print ASCII:42
Print ASCII:43
Print ASCII:44
Print ASCII:0
===============struct v2================
======================================
Print ASCII:41
Print ASCII:42
Print ASCII:43
Print ASCII:44
Print ASCII:0
================string s1===================
Print ASCII:41
Print ASCII:42
Print ASCII:43
Print ASCII:20
Print ASCII:0
================string s2[2]===================
Print ASCII:41
Print ASCII:42
Print ASCII:43
Print ASCII:20
Print ASCII:20
======================================
Print ASCII:44
Print ASCII:45
Print ASCII:46
Print ASCII:20
Print ASCII:20
================union u1.c1===================
Print ASCII:41
Print ASCII:42
Print ASCII:43
Print ASCII:20
Print ASCII:0
================arr[2][5]===================
Print ASCII:41
Print ASCII:42
Print ASCII:43
Print ASCII:20
Print ASCII:20
Print ASCII:44
Print ASCII:45
Print ASCII:46
Print ASCII:20
Print ASCII:20
================cc[5]===================
Print ASCII:41
Print ASCII:42
Print ASCII:43
Print ASCII:20
Print ASCII:20
================v3[2]===================
Print ASCII:48
======================================
Print ASCII:41
Print ASCII:42
Print ASCII:43
Print ASCII:44
Print ASCII:45
======================================
Print ASCII:49
======================================
Print ASCII:46
Print ASCII:47
Print ASCII:48
Print ASCII:49
Print ASCII:4a
================v3[1]===================
Print ASCII:48
======================================
Print ASCII:41
Print ASCII:42
Print ASCII:43
Print ASCII:44
Print ASCII:0
[lightdb@192 ~]$