LightDB对ecpg的功能增强

注:本文基于LightDB的13.8-23.3版本

什么是ecpg

通常,c语言程序访问和操作PG系的数据库时,我们会使用PG提供的libpq,这是PG官方提供的一套c语言API,功能比较强大,但是使用比较繁琐且不优雅。而ecpg作为嵌入式的SQL,可以通过某些特殊的标记直接将SQL语句嵌入到c语言源程序中,使得代码更加简洁易读。

嵌入式 SQL 程序(*.pgc)的工作原理是通过嵌入式 SQL 预处理器,将源代码(*.pgc)转换成一个普通 c 程序(*.c),而这个c程序中使用了libpq的库函数,因此经过编译链接后生成的可执行程序可以与PG数据库进行通信。所以可以将ecpg理解为在libpq库之上抽象了一层新的更易用更简洁的接口。

给个最简单的例子来直观感受下ecpg,可以看到只需要在SQL前面标记"EXEC SQL",程序执行过程中就能执行SQL语句了

#include <stdio.h>

EXEC SQL WHENEVER SQLERROR SQLPRINT;

int
main()
{
    EXEC SQL BEGIN DECLARE SECTION;
        char dbname[1024];
        const char *testdb1 = "oracle@127.0.0.1";
        const char *user = "lightdb";
        const char *passwd = "!QAZ2wsx";
    EXEC SQL END DECLARE SECTION;

    EXEC SQL CONNECT TO "oracle@127.0.0.1" as oracle_conn user :user/:passwd;


    /* 这个查询将在最近打开的数据库 "oracle" 中执行 */
    EXEC SQL SELECT current_database() INTO :dbname;
    printf("current=%s (should be oracle)\n", dbname);

    /* 创建表 */
    EXEC SQL CREATE TABLE if not exists foo (a integer, b text);
    EXEC SQL CREATE UNIQUE index if not exists num1 ON foo(a);
	EXEC SQL INSERT INTO foo values(1,'aa');
    EXEC SQL commit;
    printf("table foo created\n", dbname);

    EXEC SQL DISCONNECT ALL;
    printf("all connections released\n", dbname);
    return 0;
}

LightDB增强1-匿名块支持引用外部变量及赋值

简单说就是LightDB支持在嵌入式SQL程序中的匿名块中直接对c语言变量进行读写,而且使用方法及其简单,仅需在c程序变量前添加一个冒号,即可在匿名块中使用该c程序变量,详见代码中的retCode变量

注:LightDB为了更好地兼容Oracle数据库,引入了PL/oraSQL过程语言,这里对PL/oraSQL就不展开了,感兴趣的可以参考官网说明。

#include <stdio.h>

EXEC SQL WHENEVER SQLERROR SQLPRINT;

int
main()
{
    EXEC SQL BEGIN DECLARE SECTION;
        char dbname[1024];
        const char *testdb1 = "oracle@127.0.0.1";
        const char *user = "lightdb";
        const char *passwd = "!QAZ2wsx";
        int retCode = 0;
    EXEC SQL END DECLARE SECTION;

    EXEC SQL CONNECT TO "oracle@127.0.0.1" as oracle_conn user :user/:passwd;


    /* 这个查询将在最近打开的数据库 "oracle" 中执行 */
    EXEC SQL SELECT current_database() INTO :dbname;
    printf("current=%s (should be oracle)\n", dbname);

    /* 创建表 */
    EXEC SQL CREATE TABLE if not exists foo (a integer, b text);
    EXEC SQL CREATE UNIQUE index if not exists num1 ON foo(a);
    EXEC SQL commit;
    printf("table foo created\n", dbname);

    EXEC SQL
    Do $$	 
	BEGIN
		begin
			insert into foo values(1,'aa');
            :retCode := 1;
        exception when others then
            :retCode := -1;
		end;
	END;
    $$ Language plorasql;

    EXEC SQL commit;

    if(1 == retCode){
        printf("anonymous block execution success\n");
    } else {
        printf("anonymous block execution failure\n");
    }

    EXEC SQL DISCONNECT ALL;
    printf("all connections released\n", dbname);
    return 0;
}

LightDB增强2-支持//和--注释

c程序员习惯使用//注释,而存储过程程序员习惯使用--注释,LightDB索性就在ecpg的内嵌存储过程中,将两种注释方式都支持了,当然传统的/**/注释方式也是支持的。

#include <stdio.h>

EXEC SQL WHENEVER SQLERROR SQLPRINT;

int
main()
{
    EXEC SQL BEGIN DECLARE SECTION;
        char dbname[1024];
        const char *testdb1 = "oracle@127.0.0.1";
        const char *user = "lightdb";
        const char *passwd = "!QAZ2wsx";
        int retCode = 0;
    EXEC SQL END DECLARE SECTION;

    EXEC SQL CONNECT TO "oracle@127.0.0.1" as oracle_conn user :user/:passwd;

    /* 这个查询将在最近打开的数据库 "oracle" 中执行 */
    EXEC SQL SELECT current_database() INTO :dbname;
    printf("current=%s (should be oracle)\n", dbname);

    EXEC SQL
    Do $$	 
	BEGIN
		begin
			insert into foo values(2,'aa');
            --insert into foo values(3,'aa');
            //insert into foo values(4,'aa');
            /*insert into foo values(5,'aa');*/
            :retCode := 1;
        exception when others then
            :retCode := -1;
		end;
	END;
    $$ Language plorasql;

    EXEC SQL commit;

    if(1 == retCode){
        printf("anonymous block execution success\n");
    } else {
        printf("anonymous block execution failure\n");
    }

    EXEC SQL DISCONNECT ALL;
    printf("all connections released\n", dbname);
    return 0;
}

LightDB增强3-支持Oracle (+)外连接写法

在Oracle兼容模式下,LightDB内核已经支持Oracle(+)的外连接写法,目前ecpg中也支持此写法。

初始数据如下:

#include <stdio.h>

EXEC SQL WHENEVER SQLERROR SQLPRINT;

int
main()
{
    EXEC SQL BEGIN DECLARE SECTION;
        char dbname[1024];
        const char *testdb1 = "oracle@127.0.0.1";
        const char *user = "lightdb";
        const char *passwd = "!QAZ2wsx";
        int cntOuter = 0;
        int cntInner = 0;
        int retCode = 0;
    EXEC SQL END DECLARE SECTION;

    EXEC SQL CONNECT TO "oracle@127.0.0.1" as oracle_conn user :user/:passwd;

    /* 这个查询将在最近打开的数据库 "oracle" 中执行 */
    EXEC SQL SELECT current_database() INTO :dbname;
    printf("current=%s (should be oracle)\n", dbname);

    EXEC SQL
    Do $$	 
	BEGIN
		begin
			select count(*) into :cntOuter from foo,foo1 where foo.a=foo1.a(+);
            select count(*) into :cntInner from foo,foo1 where foo.a=foo1.a;
            exception when others then
                :retCode := -1;
            end;
	END;
    $$ Language plorasql;

    EXEC SQL commit;

    if(0 != retCode) {
        printf("anonymous block execution failure\n");
    } else {
        printf("cntOuter=%d, cntInner=%d\n",cntOuter,cntInner);
    }

    EXEC SQL DISCONNECT ALL;
    printf("all connections released\n", dbname);
    return 0;
}

执行结果如下:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值