暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

DM8达梦数据库DPI 接口

原创 达梦 2021-01-31
4754

DM DPI 驱动程序是 DM 数据库的 C/C++ 类驱动程序,是访问 DM 数据库的最直接的途径。

DM DPI 的实现参考了 Microsoft ODBC 3.0 标准,函数功能以及调用过程与 ODBC 3.0 十分类似,命名统一采用 dpi 开头的小写英文字母方式,各个单词之间以下划线分割(例:ODBC 函数 SQLAllocStmt 对应的 DPI 函数就是 dpi_alloc_stmt),用户可以参考《Microsoft ODBC 3.0 程序员参考手册(第二卷)》之 API 参考部分的函数说明及调用方法。

开发环境搭建

软件 版本
DM 数据库 DM 8.0 及以上版本

安装 DM 数据库

请参考 DM8 数据库快速上手指南

数据库安装过程中,请勾选创建 DMHR 示例库,作为数据库模拟环境,如下图所示:

DMHR 示例库

gcc 环境检查

gcc --version

执行结果如下:

[root@localhost dpitest]# gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

项目目录结构

dpitest
├── dpi_bind.c // 绑定变量示例
├── dpi_conn.c // 数据库连接示例
├── dpi_dml.c // 基本操作示例
├── dpi_lob.c // 大字段操作示例
├── file // 大字段操作示例中导入和导出文件目录
| ├── DM8_SQL.pdf // 大字段操作示例中导入文件
├── makfile // makefile 编译脚本

makefile 脚本如下:

CC=gcc

includepath=$(DM_HOME)/include
libpath=$(DM_HOME)/bin
vpath=./

CFLAGS=-I$(includepath) -DDM64 -Wall
LINKFLAGS=-L$(libpath) -ldmdpi -Wall

%.o:%.c
$(CC) -g -c $(CFLAGS) $< -o $@

object_file1=dpi_conn.o
object_file2=dpi_dml.o
object_file3=dpi_bind.o
object_file4=dpi_lob.o

object_files=dpi_conn.o dpi_dml.o dpi_bind.o dpi_lob.o

final_objects=dpi_conn dpi_dml dpi_bind dpi_lob

all : $(final_objects)

.PHONY : all clean rebuild

dpi_conn : $(object_file1)
$(CC) -o $@ $(object_file1) -g $(LINKFLAGS)
@echo make ok.

dpi_dml : $(object_file2)
$(CC) -o $@ $(object_file2) -g $(LINKFLAGS)
@echo make ok.

dpi_bind : $(object_file3)
$(CC) -o $@ $(object_file3) -g $(LINKFLAGS)
@echo make ok.

dpi_lob : $(object_file4)
$(CC) -o $@ $(object_file4) -g $(LINKFLAGS)
@echo make ok.

clean :
@rm -rf $(object_files)
@rm -rf $(final_objects)

rebuild : clean all

数据库连接

DPI 接口驱动程序为 libdmdpi.so,存放目录位于 $DM_HOME/bin

连接 API 说明如下:

DPIRETURN
dpi_login(
dhcon dpi_hcon,
sdbyte* svr,
sdbyte* user,
sdbyte* pwd,
);
  • dpi_hcon 输入参数,连接句柄。
  • svr 输入参数,数据库服务器所对应的地址。示例为:IP:PORT
  • user 输入参数,登录数据库服务器的登录名。
  • pwd 输入参数,登录数据库服务器的口令。

数据库连接示例

DPI 接口登录、登出示例程序 dpi_conn.c 如下:

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

#include "DPI.h"
#include "DPIext.h"
#include "DPItypes.h"

#define DM_SVR "192.168.117.223:5236"
#define DM_USER "SYSDBA"
#define DM_PWD "SYSDBA"

dhenv henv; /* 环境句柄 */
dhcon hcon; /* 连接句柄 */
dhstmt hstmt; /* 语句句柄 */
dhdesc hdesc; /* 描述符句柄 */
DPIRETURN rt; /* 函数返回值 */

/******************************************************
Notes:
获取错误信息
*******************************************************/
void dpi_err_msg_print(sdint2 hndl_type, dhandle hndl)
{
sdint4 err_code;
sdint2 msg_len;
sdbyte err_msg[SDBYTE_MAX];

/* 获取错误信息集合 */
dpi_get_diag_rec(hndl_type, hndl, 1, &err_code, err_msg, sizeof(err_msg), &msg_len);
printf("err_msg = %s, err_code = %d\n", err_msg, err_code);
}

/*
入口函数
*/
int main(int argc, char *argv[])
{

//连接数据库
/* 申请环境句柄 */
rt = dpi_alloc_env(&henv);

/* 申请连接句柄 */
rt = dpi_alloc_con(henv, &hcon);

/* 连接数据库服务器 */
rt = dpi_login(hcon, (sdbyte *)DM_SVR, (sdbyte *)DM_USER, (sdbyte *)DM_PWD);
if(!DSQL_SUCCEEDED(rt))
{
dpi_err_msg_print(DSQL_HANDLE_DBC, hcon);
return rt;
}
printf("dpi: connect to server success!\n");


//断开数据库连接
/* 断开连接 */
rt = dpi_logout(hcon);
if(!DSQL_SUCCEEDED(rt))
{
dpi_err_msg_print(DSQL_HANDLE_DBC, hcon);
return rt;
}
printf( "dpi: disconnect from server success!\n" );

/* 释放连接句柄和环境句柄 */
rt = dpi_free_con(hcon);
rt = dpi_free_env(henv);

return rt;
}

执行结果如下:

[root@LC105103 dpitest]# ./dpi_conn
dpi: connect to server success!
dpi: disconnect from server success!

开发示例

基本操作示例

DPI 接口增、删、改、查四个基本操作,示例程序 dpi_dml.c 如下:

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

#include "DPI.h"
#include "DPIext.h"
#include "DPItypes.h"

#define DM_SVR "192.168.117.223:5236"
#define DM_USER "SYSDBA"
#define DM_PWD "SYSDBA"

dhenv henv; /* 环境句柄 */
dhcon hcon; /* 连接句柄 */
dhstmt hstmt; /* 语句句柄 */
dhdesc hdesc; /* 描述符句柄 */
DPIRETURN rt; /* 函数返回值 */

/******************************************************
Notes:
获取错误信息
*******************************************************/
void dpi_err_msg_print(sdint2 hndl_type, dhandle hndl)
{
sdint4 err_code;
sdint2 msg_len;
sdbyte err_msg[SDBYTE_MAX];

/* 获取错误信息集合 */
dpi_get_diag_rec(hndl_type, hndl, 1, &err_code, err_msg, sizeof(err_msg), &msg_len);
printf("err_msg = %s, err_code = %d\n", err_msg, err_code);
}

/*
入口函数
*/
int main(int argc, char *argv[])
{
sdint4 out_c1 = 0;
sdbyte out_c2[20]= { 0 };
slength out_c1_ind = 0;
slength out_c2_ind = 0;
ulength row_num;

//连接数据库
rt = dpi_alloc_env(&henv);
rt = dpi_alloc_con(henv, &hcon);
rt = dpi_login(hcon, (sdbyte *)DM_SVR, (sdbyte *)DM_USER, (sdbyte *)DM_PWD);
if(!DSQL_SUCCEEDED(rt))
{
dpi_err_msg_print(DSQL_HANDLE_DBC, hcon);
return rt;
}

rt = dpi_alloc_stmt(hcon, &hstmt);

//清空表,初始化测试环境
rt = dpi_exec_direct(hstmt, (sdbyte*) "delete from PRODUCTION.PRODUCT_CATEGORY");

//插入数据
rt = dpi_exec_direct(hstmt, (sdbyte*) "insert into PRODUCTION.PRODUCT_CATEGORY(NAME) values('语文'), ('数学'), ('英语'), ('体育') ");
if(!DSQL_SUCCEEDED(rt))
{
dpi_err_msg_print(DSQL_HANDLE_STMT, hstmt);
return rt;
}
printf("dpi: insert success\n");

//删除数据
rt = dpi_exec_direct(hstmt, (sdbyte*) "delete from PRODUCTION.PRODUCT_CATEGORY where name='数学' ");
if(!DSQL_SUCCEEDED(rt))
{
dpi_err_msg_print(DSQL_HANDLE_STMT, hstmt);
return rt;
}
printf("dpi: delete success\n");

//更新数据
rt = dpi_exec_direct(hstmt, (sdbyte*) "update PRODUCTION.PRODUCT_CATEGORY set name = '英语-新课标' where name='英语' ");
if(!DSQL_SUCCEEDED(rt))
{
dpi_err_msg_print(DSQL_HANDLE_STMT, hstmt);
return rt;
}
printf("dpi: update success\n");

//查询数据
dpi_exec_direct(hstmt, (sdbyte*) "select * from PRODUCTION.PRODUCT_CATEGORY");
dpi_bind_col(hstmt, 1, DSQL_C_SLONG, &out_c1, sizeof(out_c1), &out_c1_ind);
dpi_bind_col(hstmt, 2, DSQL_C_NCHAR, &out_c2, sizeof(out_c2), &out_c2_ind);

printf("dpi: select from table...\n");
while(dpi_fetch(hstmt, &row_num) != DSQL_NO_DATA)
{
printf("c1 = %d, c2 = %s ,\n", out_c1, out_c2);
}
printf("dpi: select success\n");

//断开数据库连接
rt = dpi_logout(hcon);
if(!DSQL_SUCCEEDED(rt))
{
dpi_err_msg_print(DSQL_HANDLE_DBC, hcon);
return rt;
}

rt = dpi_free_con(hcon);
rt = dpi_free_env(henv);

return rt;
}

执行结果如下:

[root@LC105103 dpitest]# ./dpi_dml
dpi: insert success
dpi: delete success
dpi: update success
dpi: select from table...
c1 = 59, c2 = 语文 ,
c1 = 61, c2 = 英语-新课标 ,
c1 = 62, c2 = 体育 ,
dpi: select success
[root@LC105103 dpitest]#

绑定变量示例

DPI 接口绑定变量示例程序 dpi_bind.c 如下:

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

#include "DPI.h"
#include "DPIext.h"
#include "DPItypes.h"

#define DM_SVR "192.168.117.223:5236"
#define DM_USER "SYSDBA"
#define DM_PWD "SYSDBA"

dhenv henv; /* 环境句柄 */
dhcon hcon; /* 连接句柄 */
dhstmt hstmt; /* 语句句柄 */
dhdesc hdesc; /* 描述符句柄 */
DPIRETURN rt; /* 函数返回值 */

/******************************************************
Notes:
获取错误信息
*******************************************************/
void dpi_err_msg_print(sdint2 hndl_type, dhandle hndl)
{
sdint4 err_code;
sdint2 msg_len;
sdbyte err_msg[SDBYTE_MAX];

/* 获取错误信息集合 */
dpi_get_diag_rec(hndl_type, hndl, 1, &err_code, err_msg, sizeof(err_msg), &msg_len);
printf("err_msg = %s, err_code = %d\n", err_msg, err_code);
}

/*
入口函数
*/
int main(int argc, char *argv[])
{
sdbyte sql[]="insert into PRODUCTION.PRODUCT_CATEGORY(NAME) values(?)";
sdbyte in_c1[20] = { 0 };
slength in_c1_ind_ptr;

memcpy(in_c1, "物理", 8);
in_c1_ind_ptr = 8;

sdint4 out_c1 = 0;
sdbyte out_c2[20]= { 0 };
slength out_c1_ind = 0;
slength out_c2_ind = 0;
ulength row_num;

//连接数据库
rt = dpi_alloc_env(&henv);
rt = dpi_alloc_con(henv, &hcon);
rt = dpi_login(hcon, (sdbyte *)DM_SVR, (sdbyte *)DM_USER, (sdbyte *)DM_PWD);
if(!DSQL_SUCCEEDED(rt))
{
dpi_err_msg_print(DSQL_HANDLE_DBC, hcon);
return rt;
}

rt = dpi_alloc_stmt(hcon, &hstmt);

//清空表,初始化测试环境
dpi_exec_direct(hstmt, (sdbyte*) "delete from PRODUCTION.PRODUCT_CATEGORY");

//绑定参数方式插入数据
printf( "insert with bind..\nsql: %s\npara: %s\n", (char*)sql, (char*)in_c1);
rt = dpi_prepare(hstmt, sql);
rt = dpi_bind_param(hstmt, 1, DSQL_PARAM_INPUT, DSQL_C_NCHAR, DSQL_VARCHAR, sizeof(in_c1), 0, in_c1, sizeof(in_c1), &in_c1_ind_ptr);
rt = dpi_exec(hstmt);
if(!DSQL_SUCCEEDED(rt))
{
dpi_err_msg_print(DSQL_HANDLE_DBC, hcon);
return rt;
}
printf( "dpi: insert into table with bind success!\n" );

//查询数据
dpi_exec_direct(hstmt, (sdbyte*) "select * from PRODUCTION.PRODUCT_CATEGORY");
dpi_bind_col(hstmt, 1, DSQL_C_SLONG, &out_c1, sizeof(out_c1), &out_c1_ind);
dpi_bind_col(hstmt, 2, DSQL_C_NCHAR, &out_c2, sizeof(out_c2), &out_c2_ind);

printf("\ndpi: select from table......\n");
while(dpi_fetch(hstmt, &row_num) != DSQL_NO_DATA)
{
printf("c1 = %d, c2 = %s ,\n", out_c1, out_c2);
}
printf("dpi: select from table success\n\n");

//断开数据库连接
rt = dpi_logout(hcon);
if(!DSQL_SUCCEEDED(rt))
{
dpi_err_msg_print(DSQL_HANDLE_DBC, hcon);
return rt;
}

rt = dpi_free_con(hcon);
rt = dpi_free_env(henv);

return rt;
}

执行结果如下:

[root@LC10510   
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论