今天给大家介绍下连接 GBase 8a 服务器用的 GBase 8a C API 接口驱动程序。本部分内容通过示例为大家演示如何使用 GBase 8a C API 函数及使用 GBase C API 进行编程的示例。

1 GBase C API

1.1数据类型

1.1.1GBASE

  • 结构说明

该结构代表与数据库连接的句柄。不建议对GBase结构进行拷贝,不保证这样的拷贝会有用。

1.1.2GBASE_RES

  • 结构说明

该结构用来保存SELECT、SHOW、DESCRIBE、EXPLAIN查询返回的结果集。

1.1.3GBASE_ROW

  • 结构说明

该结构用来保存1行数据。它是按照计数字节字符串的数组实施的。(如果字段值可能包含二进制数据,不能将其当作由NULL终结的字符串对待,这是因为这类值可能会包含NULL字节)。它是通过gbase_fetch_row()获取的。

1.1.4GBASE_FIELD

  • 结构说明

该结构用来保存字段的信息(字段名、类型、大小)。通过重复调用gbase_fetch_field()可以为每个字段获取GBASE_FIELD结构。

  • 结构成员

名  称

类  型

描  述

name

char*

字段名称,由NULL终结的字符串。如果用AS子句为该字段指定了别名,名称的值也是别名。

org_name

char*

字段名称,由NULL终结的字符串。忽略别名。

table

char*

包含该字段的表的名称,如果该字段不是计算出的字段的话。对于计算出的字段,表值为空的字符串。如果用AS子句为该表指定了别名,表的值也是别名。

org_table

char*

表的名称,由NULL终结的字符串。忽略别名。

db

char*

字段源自的数据的名称,由NULL终结的字符串。如果该字段是计算出的字段,db为空的字符串。

catalog

char*

catalog名称。该值总是"def"。

def

char*

该字段的默认值,由NULL终结的字符串。仅当使用GBASE_list_fields()时才设置它。

length

unsigned long

字段的宽度,如表定义中所指定的那样。

max_length

unsigned long

用于结果集的字段的最大宽度(对于实际位于结果集中的行,最长字段值的长度)。如果使用gbase_store_result()或gbase_list_fields(),它将包含字段的最大长度。如果使用gbase_use_result(),该变量的值为0。

name_length

unsigned int

名称的长度。

org_name_length

unsigned int

org_name的长度。

table_length

unsigned int

表的长度。

org_table_length

unsigned int

org_table的长度。

db_length

unsigned int

db的长度。

catalog_length

unsigned int

catalog的长度。

def_length

unsigned int

def的长度。

flags

unsigned int

用于字段的不同“位标志”。

decimals

unsigned int

用于数值字段的十进制数数目。

charsetnr

unsigned int

用于字段的字符集编号。

type

enum_field_types

字段的类型。类型值可以是下标所列的GBASE_TYPE_符号之一

  • flags字段值集合

标志值

标志描述

NOT_NULL_FLAG

字段不能为NULL

PRI_KEY_FLAG

字段是主键的组成部分

UNIQUE_KEY_FLAG

字段是唯一键的组成部分

MULTIPLE_KEY_FLAG

字段是非唯一键的组成部分

UNSIGNED_FLAG

字段具有UNSIGNED属性

ZEROFILL_FLAG

字段具有ZEROFILL属性

BINARY_FLAG

字段具有BINARY属性

AUTO_INCREMENT_FLAG

字段具有AUTO_INCREMENT属性

ENUM_FLAG

字段是ENUM(不再重视)

SET_FLAG

字段是 SET(不再重视)

BLOB_FLAG

字段是BLOB或TEXT(不再重视)

TIMESTAMP_FLAG

字段是TIMESTAMP(不再重视)

标志值的典型用法:

if (field->flags & NOT_NULL_FLAG)
printf("Field can't be null\n");

可以使用下述方面的宏来定义标志值的布尔状态:

标志状态

描  述

IS_NOT_NULL(flags)

如果该字段定义为NOT NULL,为“真”。

IS_PRI_KEY(flags)

如果该字段是主键,为“真”。

IS_BLOB(flags)

如果该字段是BLOB或TEXT,为“真”(不再重视,用测试field->type取而代之)。

  • type字段值集合

类型值

类型描述

GBASE_TYPE_TINY

TINYINT字段

GBASE_TYPE_SHORT

SMALLINT字段

GBASE_TYPE_LONG

INTEGER字段

GBASE_TYPE_INT24

MEDIUMINT字段

GBASE_TYPE_LONGLONG

BIGINT字段

GBASE_TYPE_DECIMAL

DECIMAL或NUMERIC字段

GBASE_TYPE_NEWDECIMAL

精度数DECIMAL或NUMERIC

GBASE_TYPE_FLOAT

FLOAT字段

GBASE_TYPE_DOUBLE

DOUBLE或REAL字段

GBASE_TYPE_BIT

BIT字段

GBASE_TYPE_TIMESTAMP

TIMESTAMP字段

GBASE_TYPE_DATE

DATE字段

GBASE_TYPE_TIME

TIME字段

GBASE_TYPE_DATETIME

DATETIME字段

GBASE_TYPE_YEAR

YEAR字段

GBASE_TYPE_STRING

CHAR字段

GBASE_TYPE_VAR_STRING

VARCHAR字段

GBASE_TYPE_BLOB

BLOB或TEXT字段(使用max_length来确定最大长度)

GBASE_TYPE_SET

SET字段

GBASE_TYPE_ENUM

ENUM字段

GBASE_TYPE_GEOMETRY

Spatial字段

GBASE_TYPE_NULL

NULL-type字段

GBASE_TYPE_CHAR

不再重视,用GBASE_TYPE_TINY取代

1.1.5 GBASE_FIELD_OFFSET

结构说明

这是GBASE字段列表偏移量的“类型安全”表示(由gbase_field_seek()使用)。偏移量是行内的字段编号,从0开始。

1.1.6 gs_ulonglong

结构说明

用于行数以及gbase_affected_rows()、gbase_num_rows()的类型。该类型提供的范围为0-1.84e19。在某些系统上,不能打印类型gs_ulonglong的值。要想打印这类值,请将其转换为无符号长整数类型并使用%lu打印格式,如:printf ("Number of rows: %lu\n", (unsigned long) gbase_num_rows(result))

2 C API预处理

2.1 数据类型

2.1.1 GBASE_STMT

  • 结构说明

该结构表示预处理语句。通过调用gbase_stmt_init()创建语句,返回语句句柄,即指向GBASE_STMT的指针。该句柄用户所有后续的与语句有关的函数,直至使用gbase_stmt_close()关闭了它为止。
GBASE_STMT结构没有供应用程序使用的参数。此外,不应尝试复制GBASE_STMT结构。不保证这类复制物会有用。多个语句句柄能够与单个连接关联起来。对句柄数目的限制取决于系统资源。

2.1.2GBASE_BIND

  • 结构说明

该结构用于语句输入(发送给服务器的数据值)和输出(从服务器返回的结果值)。对于输入,它与gbase_stmt_bind_param()一起使用,用于将参数数据值绑定到缓冲区上,以供gbase_stmt_execute()使用。对于输出,它与gbase_stmt_bind_result()一起使用,用于绑定结果缓冲区,以便用于用gbase_stmt_fetch()以获取行。
GBASE_BIND结构包含下述供应用程序使用的成员。每个成员用于输入和输出,但在某些时候,也能用于不同的目的,具体情况取决于数据传输的方向。

  • 结构成员

名  称

类  型

描  述

buffer_type

enum_field_types

缓冲的类型。

buffer 

void *

指向缓冲区的指针。

buffer_length

unsigned long

缓冲区的实现大小,单位为字节。

length

unsigned long*

指向unsigned long变量的指针,该变量指明了存储在*buffer中数据的实际字节数。

is_null

gs_bool*

该成员指向gs_bool变量,如果值为NULL,该变量为“真”,如果值为非NULL,该变量为“假”。“is_null”是指向布尔类型的指针,而不是布尔标量,以便能以下述方式使用它:

1. 如果数据值总是NULL,使用GBASE_TYPE_NULL绑定列。

2. 如果数据值总是NOT NULL,设置is_null = (gs_bool*) 0。

3. 在所有其他情况下,应将is_null设置为gs_bool变量的地址,并在各次执行之间恰当地更改变量的值,以指明数据值是NULL或NOT NULL。

is_unsigned

gs_bool

对于无符号类型,应将“is_unsigned”设置为“真”,对于带符号类型,应将其设置为“假”。

error

gs_bool

对于输出,该成员用于通报数据截短错误。必须通过调用带有GBASE_REPORT_DATA_TRUNCATION选项的gbase_options(),启用截短通报功能。允许该功能后,gbase_stmt_fetch()返回GBASE_DATA_TRUNCATED,而且对于出现截短情况的参数,在GBASE_BIND结构中,错误标志为“真”。截短指明丢失了符号或有效位数,或字符串过长以至于无法容纳在1列中。

2.1.3GBASE_TIME

  • 结构说明

该结构用于将DATE、TIME、DATETIME和TIMESTAMP数据直接发送到服务器,或从服务器直接接收这类数据。

  • 结构成员

名  称

类  型

描  述

year

unsigned int

年份

month

unsigned int

月份

day

unsigned int

hour

unsigned int

小时

minute

unsigned int

分钟

second

unsigned int

neg

unsigned int

布尔标志,用于指明时间是否为负数

3GBase C API应用示例

3.1使用GBase C API创建连接

GBASE* gbase=NULL;
/*初始化GBASE结构体*/
if(!(gbase = gbase_init(0)))
{
fprintf(stderr, "不能初始化GBASE结构体!\n");
exit(1);
}
/*数据库连接*/
if(!gbase_real_connect(gbase, host, user, passwd, db, port, NULL, 0))
{
fprintf(stderr, "\n%s\n", gbase_error(gbase));
exit(1);
}
/*释放数据库连接句柄*/
gbase_close(gbase);

3.2使用GBase C API连接集群

GBASE* gbase=NULL;
CHAR* host=”192.168.5.64;192.168.5.67;”; // 集群各节点的IP地址
/*初始化GBASE结构体*/
if(!(gbase = gbase_init(0)))
{
fprintf(stderr, "不能初始化GBASE结构体!\n");
exit(1);
}
/*数据库连接*/
if(!gbase_real_connect(gbase, host, user, passwd, db, port, NULL, 0))
{
fprintf(stderr, "\n%s\n", gbase_error(gbase));
exit(1);
}
/*释放数据库连接句柄*/
gbase_close(gbase);

3.3使用GBase C API执行存储过程

/*执行存储过程*/
void demo_3(void)
{
GBASE* gbase = NULL;
char* sql_drop = "drop table if exists g_demo3";
char* sql = "create table g_demo3(a varchar(10), b int)";
char* p_drop = "DROP PROCEDURE IF EXISTS demo_p";
char* p = "create procedure demo_p(in a varchar(10), \
                                  in b int) \
                                  begin \
                                    insert into g_demo3(a, b) values (a, b); \
                                  end;";
char* call_p = "CALL demo_p('call_p', 1)";
if(!(gbase = gbase_init(0)))
{
fprintf(stderr, "不能初始化GBASE结构体!\n");
exit(1);
}
if(!gbase_real_connect(gbase, host, user, passwd, db, port, NULL, 0))
{
fprintf(stderr, "\n%s\n", gbase_error(gbase));
exit(1);
}
/*在数据库中创建表*/
if(gbase_query(gbase, sql_drop))
{
fprintf(stderr, "%s", gbase_error(gbase));
exit(1);
}
if(gbase_query(gbase, sql))
{
fprintf(stderr, "\n%s\n", gbase_error(gbase));
exit(1);
}
if(gbase_query(gbase, p_drop))
{
fprintf(stderr, "\n%s\n", gbase_error(gbase));
exit(1);
}
if(gbase_query(gbase, p))
{
fprintf(stderr, "\n%s\n", gbase_error(gbase));
exit(1);
}
if(gbase_query(gbase, call_p))
{
fprintf(stderr, "\n%s\n", gbase_error(gbase));
exit(1);
}
printf("PROCEDURE 执行结果\n");
print_table(gbase, "g_demo3");
gbase_close(gbase);
}

3.5在多线程环境下使用GBase C API

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include "gbase.h"
#include <pthread.h>
static pthread_mutex_t lock_thread_num;
static pthread_cond_t cond_thread_num;
static int thread_num;
void* th_new(void* arg)
{
GBASE* gbase;
GBASE_RES *res;
gbase_thread_init();
gbase = gbase_init(0);
if(!gbase_real_connect(gbase,"192.168.111.96","root","1111","test",5258, NULL, 0))
{
fprintf(stderr, "%s\n", gbase_error(gbase));
goto exit;
}
exit:
gbase_close(gbase);
gbase_thread_end();
pthread_mutex_lock(&lock_thread_num);
thread_num--;
pthread_cond_signal(&cond_thread_num); 
pthread_mutex_unlock(&lock_thread_num);
pthread_exit(0);
return 0;
}
int main()
{
pthread_t t;
unsigned int i=10;
int error;
pthread_attr_t thr_attr;
if(gbase_library_init(0, NULL, NULL))
{
exit(1);
}
thread_num = i;
if ((error=pthread_cond_init(&cond_thread_num,NULL)))
{
exit(1);
}
pthread_mutex_init(&lock_thread_num, NULL);
if ((error=pthread_attr_init(&thr_attr)))
{
exit(1);
}
if ((error=pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED)))
{
exit(1);
}
while(i--)
{
pthread_create(&t, &thr_attr, th_new, NULL);
}
pthread_mutex_lock(&lock_thread_num);
while(thread_num > 0) 
{
if ((error=pthread_cond_wait(&cond_thread_num,&lock_thread_num)))
fprintf(stderr,"\nGot error: %d from pthread_cond_wait\n",error);
}
pthread_mutex_unlock(&lock_thread_num);
pthread_mutex_destroy(&lock_thread_num);    
gbase_library_end();
return 0;
}

3.5使用预处理快速插入数据

#include <windows.h>
#include <time.h>
#include <stdio.h>
#include "gbase.h"
#define  NUM_INSERT 1000
void main(void)
{
GBASE* gbase=NULL;
GBASE_STMT* stmt;
GBASE_BIND bind[2];
const char* sql_drop_table        = "drop table if exists g_demo2";
const char* sql_create_table    = "create table g_demo2(id int, name varchar(20))";
const char* insert_mode        = "insert into g_demo2(id, name)values(?, ?)";
int in_id[NUM_INSERT];
char in_name[NUM_INSERT][20];
unsigned int i = 0;
char* host = "192.168.111.96";
char* user = "gbase";
char* passwd = "gbase20110531";
char* db = "test";
int port = 5258;
/*初始化GBASE结构体*/
if(!(gbase = gbase_init(0)))
{
fprintf(stderr, "不能初始化GBASE结构体!\n");
exit(1);
}
/*数据库连接*/
if(!gbase_real_connect(gbase, host, user, passwd, db, port, NULL, 0))
{
fprintf(stderr, "\n%s\n", gbase_error(gbase));
exit(1);
    }
gbase->reconnect = 1;
/*在数据库中创建表*/
if(gbase_query(gbase, sql_drop_table))
{
fprintf(stderr, "%s", gbase_error(gbase));
exit(1);
}
if(gbase_query(gbase, sql_create_table))
{
fprintf(stderr, "\n%s\n", gbase_error(gbase));
exit(1);
    }
gbase_autocommit(gbase, 0);
/*向数据库表中插入数据*/
for(i=0; i<NUM_INSERT; i++)
{
in_id[i] = i;
sprintf(in_name[i], "name_%d", i);
}
if(!(stmt = gbase_stmt_init(gbase)))
{
fprintf(stderr, "\n%s\n", gbase_stmt_error(stmt));
exit(1);
}
if(gbase_stmt_prepare(stmt, insert_mode, strlen(insert_mode)))
{
fprintf(stderr, "\n%s\n", gbase_stmt_error(stmt));
exit(1);
}
memset(bind, 0, sizeof(bind));
bind[0].buffer_type = GBASE_TYPE_LONG;
bind[1].buffer_type = GBASE_TYPE_STRING;
printf("开始插入%d条数据\n", NUM_INSERT);
for(i=0; i<NUM_INSERT; i++)
{
bind[0].buffer = (void*)&in_id[i];
bind[1].buffer = (void*)in_name[i];
bind[1].buffer_length = strlen(in_name[i]);
if(gbase_stmt_bind_param(stmt, bind))
{
fprintf(stderr, "\n%s\n", gbase_stmt_error(stmt));
exit(1);
}
if(gbase_stmt_execute(stmt))
{
fprintf(stderr, "\n%s\n", gbase_stmt_error(stmt));
exit(1);
}
}
gbase_commit(gbase);
/*关闭STMT语句句柄*/
if(gbase_stmt_close(stmt))
{
fprintf(stderr, "%s\n", gbase_stmt_error(stmt));
exit(1);
}
/*释放数据库连接句柄*/
gbase_close(gbase);    
}

3.6使用GBase C API负载均衡

使用GBase CAPI负载均衡创建到8a集群的连接时,客户端最少应该把8a集群gcluster节点ip地址传给GBase CAPI。如host="192.168.1.1;192.168.1.2"。如果只有一个节点,那么客户端应该这样传给GBase CAPI集群的节点:host="192.168.1.1;"。字符串中ip地址后的分号是必须的。
使用GBase CAPI负载均衡创建到8a集群的连接时,如果没有设置"GBASE_OPT_USE_SERVER_BALANCE"选项的值(该值默认为0),那么GBase CAPI将在客户端传入的ip地址间进行负载均衡。如果设置"GBASE_OPT_USE_SERVER_BALANCE"选项的值为1,那么GBase CAPI将在8a集群所有节点之间进行负载均衡。如下是使用GBase CAPI负载均衡的代码样例。

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include "gbase.h"
int test_banalce()
{
GBASE* gbase = NULL;
char* host = "192.168.1.1;";
char* user = "gbase";
char* pwd = "gbase20110531";
char* db = "test";
int  port = 5258;
int rc = 0;
int use_server_balance = 1;
gbase = gbase_init(NULL);
gbase_options(gbase,  GBASE_OPT_USE_SERVER_BALANCE, (void*)&use_server_balance);
if(!gbase_real_connect(gbase, host, user, pwd, db, port, NULL, 0))
{
fprintf(stderr, "%d\n%s\n",gbase_errno(gbase), gbase_error(gbase));
rc = 1;
}
else
{
printf("%s\n", gbase_get_host_info(gbase));
}    
gbase_close(gbase);
return rc;
}
int main()
{
int i = 0;
for(;i < 20; i++)
{
test_banalce();
usleep(2*1000);
}
return 0;
}

以上就是关于C-API的全部内容了,本期内容希望对您有所帮助,谢谢!