更新时间:2026-10-21 GMT+08:00
分享

使用库函数

除通过嵌入式EXEC SQL语法操作数据库外,ecpg运行库(libecpg)还提供了一组C语言原生底层API接口。开发者可以通过这些函数实现全局调试诊断、提取原生libpq连接句柄、实时监测事务状态以及清理自动分配的堆内存,从而增强对数据库通信层的精细化控制。

日志调试函数ECPGdebug

在排查SQL语法错误或底层通信故障时,可以使用ECPGdebug开启客户端的调试日志。开启后,ecpg引擎会将所有生成的SQL语句文本以及GaussDB返回的底层响应实时输出至指定的标准流中。

语法声明:

void ECPGdebug(int on, FILE *stream);

参数说明:

  • on:开关标识。非0值表示开启调试日志,0表示关闭日志。
  • stream:指定日志输出的目标流(如stderr或stdout)。

示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sqlca.h"

int main()
{
    /* 开启调试日志并将信息输出至stderr */
    ECPGdebug(1, stderr);

    /* 需提前创建testdb */
    EXEC SQL CONNECT TO testdb;
    EXEC SQL SET AUTOCOMMIT TO ON;
    EXEC SQL CREATE TABLE T1(a int);
    return (0);
}

运行结果如下([23893]为线程ID,随机生成):

[23893]: ECPGdebug: set to 1
[23893]: ECPGconnect: opening database testdb on <DEFAULT> port <DEFAULT>
[23893]: ECPGsetcommit on line 12: action "on"; connection "testdb"
[23893]: ecpg_execute on line 13: query: create table T1 ( a int ); with 0 parameter(s) on connection testdb
[23893]: ecpg_execute on line 13: using PQexec
[23893]: ecpg_execute on line 13: OK: CREATE TABLE

获取原生连接句柄函数ECPGget_PGconn

嵌入式SQL底层依赖libpq库实现网络通信。当高级业务场景需要在C程序中混合调用libpq原生C API时,可以通过ECPGget_PGconn提取已有连接对应的PGconn*底层指针。

语法声明:

PGconn *ECPGget_PGconn(const char *connection_name);

参数说明:

connection_name:建立连接时通过AS指定的连接名称。若传入NULL,则默认返回当前活动连接的句柄。若无匹配连接,则返回NULL。

示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sqlca.h"

int main(void)
{
    ECPGdebug(1, stderr);

    /* 需提前创建testdb数据库 */
    EXEC SQL CONNECT TO testdb as con1;
    EXEC SQL SET AUTOCOMMIT TO ON;
    EXEC SQL DROP TABLE IF EXISTS T1;

    PGconn *conn;
    /* 按连接名获取底层PGconn句柄 */
    conn = ECPGget_PGconn("con1");
    printf("conn = %p\n", conn);

    /* 获取当前默认连接句柄 */
    conn = ECPGget_PGconn(NULL);
    printf("conn = %p\n", conn);

    EXEC SQL CREATE TABLE T1(a int);
    return 0;
}

运行结果如下([29709]为线程ID,随机生成。连接生成地址随机,运行结果不固定。):

[29709]: ECPGdebug: set to 1
[29709]: ECPGconnect: opening database testdb on <DEFAULT> port <DEFAULT>
[29709]: ECPGsetcommit on line 12: action "on"; connection "con1"
[29709]: ecpg_execute on line 13: query: drop table if exists T1; with 0 parameter(s) on connection con1
[29709]: ecpg_execute on line 13: using PQexec
[29709]: ecpg_execute on line 13: OK: DROP TABLE
conn = 0x14daf70
conn = 0x14daf70
[29709]: ecpg_execute on line 19: query: create table T1 ( a int ); with 0 parameter(s) on connection con1
[29709]: ecpg_execute on line 19: using PQexec
[29709]: ecpg_execute on line 19: OK: CREATE TABLE

事务状态查询函数ECPGtransactionStatus

为了在运行期监测指定数据库连接的事务运行状态,以便程序根据当前环境做出回滚或提交等决策,可以使用ECPGtransactionStatus查询事务枚举状态值。

语法声明:

int ECPGtransactionStatus(const char *connection_name);
可能的返回值包括:
PQTRANS_IDLE,    /* connection idle,连接空闲 */
PQTRANS_ACTIVE,  /* command in progress,命令正在执行 */
PQTRANS_INTRANS, /* idle, within transaction block,空闲,在事务块里 */
PQTRANS_INERROR, /* idle, within failed transaction,空闲,在失败的事务里 */
PQTRANS_UNKNOWN  /* cannot determine status,未知状态 */
示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sqlca.h"

int main()
{
    ECPGdebug(1, stderr);

    /* 需提前创建testdb数据库 */
    EXEC SQL CONNECT TO testdb as con1;
    EXEC SQL DROP TABLE IF EXISTS T1;

    /* 查询con1连接当前的事务状态 */
    int a = ECPGtransactionStatus("con1");
    printf("%d\n", a);

    EXEC SQL CREATE TABLE T1(a int);
    EXEC SQL COMMIT;
    return (0);
}

运行结果如下([44153]为线程ID,随机生成):

[44153]: ECPGdebug: set to 1
[44153]: ECPGconnect: opening database testdb on <DEFAULT> port <DEFAULT>
[44153]: ecpg_execute on line 12: query: drop table if exists T1; with 0 parameter(s) on connection con1
[44153]: ecpg_execute on line 12: using PQexec
[44153]: ecpg_execute on line 12: OK: DROP TABLE
2
[44153]: ecpg_execute on line 15: query: create table T1 ( a int ); with 0 parameter(s) on connection con1
[44153]: ecpg_execute on line 15: using PQexec
[44153]: ecpg_execute on line 15: OK: CREATE TABLE
[44153]: ECPGtrans on line 16: action "commit"; connection "con1"

动态内存释放函数ECPGfree_auto_mem

在使用SQL描述符(SQL Descriptor)或变长指针类型宿主变量提取数据时,ecpg运行库会自动在堆内存中为输出型宿主变量分配空间。在程序退出或函数返回之前,应当显式调用ECPGfree_auto_mem清理这些由运行库自动管理的内存资源,以防止内存泄漏。

语法声明:

void ECPGfree_auto_mem(void);
示例如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sqlca.h"

int main()
{
   EXEC SQL BEGIN DECLARE SECTION;
   int *ip1=0;
   char **cp2=0;
   int *ipointer1=0;
   int *ipointer2=0;
   int column;
   EXEC SQL END DECLARE SECTION;
   int i;


   EXEC SQL WHENEVER SQLERROR DO sqlprint();
   EXEC SQL CONNECT TO testdb;

   /* 需提前创建testdb数据库 */
   EXEC SQL CREATE TABLE test (a int, b text);
   EXEC SQL INSERT INTO test VALUES (1, 'one');
   EXEC SQL INSERT INTO test VALUES (2, 'two');
   EXEC SQL INSERT INTO test VALUES (NULL, 'three');
   EXEC SQL INSERT INTO test VALUES (NULL, NULL);

   EXEC SQL ALLOCATE DESCRIPTOR mydesc;
   EXEC SQL SELECT * INTO SQL DESCRIPTOR mydesc FROM test;
   EXEC SQL GET DESCRIPTOR mydesc :column=COUNT;
   EXEC SQL GET DESCRIPTOR mydesc VALUE 1 :ip1=DATA, :ipointer1=INDICATOR;
   EXEC SQL GET DESCRIPTOR mydesc VALUE 2 :cp2=DATA, :ipointer2=INDICATOR;

   printf("Result (%d columns):\n", column);
   for (i=0;i < sqlca.sqlerrd[2];++i)
   {
      if (ipointer1[i]) printf("NULL, ");
      else printf("%d, ",ip1[i]);

      if (ipointer2[i]) printf("NULL, ");
      else printf("'%s', ",cp2[i]);
      printf("\n");
   }
   ECPGfree_auto_mem();
   printf("\n");

   EXEC SQL DEALLOCATE DESCRIPTOR mydesc;
   EXEC SQL ROLLBACK;
   EXEC SQL DISCONNECT;
   return 0;
}

运行结果如下:

Result (2 columns):
1, 'one',
2, 'two',
NULL, 'three',
NULL, NULL,

相关文档