一、测试环境

名称
cpuIntel® Core™ i5-1035G1 CPU @ 1.00GHz
操作系统CentOS Linux release 7.9.2009 (Core)
内存4G
逻辑核数3
Gbase-8a节点-IP192.168.142.10
Gbase-8a数据库版本8.6.2.43-R33.132743
gcc版本4.8.5 20150623

本文只介绍我程序中用到的结构体或函数,其他的大家可以参考CAPI开发手册。

二、CAPI结构体介绍

1、GBASE

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

typedef struct st_gbase
{
  GB_NET		net;			
  unsigned char	*connector_fd;		
  char		*host,*user,*passwd,*unix_socket,*server_version,*host_info;
  char          *info, *db;
  struct charset_info_st *charset;
  GBASE_FIELD	*fields;
  GB_MEM_ROOT	field_alloc;
  gs_ulonglong affected_rows;
  gs_ulonglong insert_id;		
  gs_ulonglong extra_info;		
  unsigned long thread_id;		
  unsigned long packet_length;
  unsigned int	port;
  unsigned long client_flag,server_capabilities;
  unsigned int	protocol_version;
  unsigned int	field_count;
  unsigned int 	server_status;
  unsigned int  server_language;
  unsigned int	warning_count;
  struct st_gbase_options options;
  enum gbase_status status;
  gs_bool	free_me;		
  gs_bool	reconnect;  
  char	        scramble[SCRAMBLE_LENGTH+1];
  gs_bool unused1;
  void *unused2, *unused3, *unused4, *unused5;
  GB_LIST  *stmts;                     
  const struct st_gbase_methods *methods;
  void *thd;  
  gs_bool *unbuffered_fetch_owner;  
  char *info_buffer;
  void *extension;
} GBASE;

2、GBASE_RES

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

例如:A表有十条数据,SELECT * FROM A,我们可以直接用row_count获得表的总条数,而不是在执行一条COUNT语句,去获取总条数。

typedef struct st_gbase_res {
  gs_ulonglong  row_count;
  GBASE_FIELD	*fields;
  GBASE_DATA	*data;
  GBASE_ROWS	*data_cursor;
  unsigned long *lengths;		
  GBASE		*handle;		
  const struct st_gbase_methods *methods;
  GBASE_ROW	row;			
  GBASE_ROW	current_row;		
  GB_MEM_ROOT	field_alloc;
  unsigned int	field_count, current_field;
  gs_bool	eof;  
  gs_bool       unbuffered_fetch_cancelled;  
  void *extension;
} GBASE_RES;

3、GBASE_ROW

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

typedef char **GBASE_ROW;

4、GBASE_FIELD定义

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

typedef struct st_gbase_field {
  char *name;                 
  char *org_name;             
  char *table;                
  char *org_table;            
  char *db;                   
  char *catalog;	      
  char *def;                  
  unsigned long length;       
  unsigned long max_length;   
  unsigned int name_length;
  unsigned int org_name_length;
  unsigned int table_length;
  unsigned int org_table_length;
  unsigned int db_length;
  unsigned int catalog_length;
  unsigned int def_length;
  unsigned int flags;         
  unsigned int decimals;      
  unsigned int charsetnr;     
  enum GB_enum_field_types type; 
  void *extension;
} GBASE_FIELD;
参数名描述
name字段别名。
org_name字段定义名。
table表别名。
org_table表定义名。
db数据库名。
catalog目录名,默认是def,用途不明。
def字段默认值,仅当使用 GBASE_list_fields()时才设置它。
length表中定义的字段长度。
max_length结果中此字段的所占用的实际长度 ,如果使用 gbase_store_result()或 gbase_list_fields(),它将包含字段 的 最 大 长 度 。 如 果 使 用gbase_use_result(),该变量的值为0。
name_length字段别名长度。
org_name_length字段定义名长度。
table_length表别名长度。
org_table_length表定义名长度。
db_length数据库名长度。
catalog_length目录名长度 。
def_length字段默认值长度。
flags用于字段的不同“位标志” ,flag对应的值分别是什么意思,下面的表格会单独说明。
decimals用于数值字段的十进制数数目。
charsetnr用于字段的字符集编号,但每个编号对应的字符集是哪个,我还没有找到。
type字段的类型,下面的表格会单独说明。
extension用途不明。
(1)flags

其中NUM_FLAG和GROUP_FLAG重复了,都是32768。
值0,144对应的宏定义没有找到。

参数名
NOT_NULL_FLAG1
PRI_KEY_FLAG2
UNIQUE_KEY_FLAG4
MULTIPLE_KEY_FLAG8
BLOB_FLAG16
UNSIGNED_FLAG32
ZEROFILL_FLAG64
BINARY_FLAG128
ENUM_FLAG256
AUTO_INCREMENT_FLAG512
TIMESTAMP_FLAG1024
SET_FLAG2048
NO_DEFAULT_VALUE_FLAG4096
ON_UPDATE_NOW_FLAG8192
NUM_FLAG32768
PART_KEY_FLAG16384
GROUP_FLAG32768
UNIQUE_FLAG65536
BINCMP_FLAG131072
GET_FIXED_FIELDS_FLAG(1 << 18)
FIELD_IN_PART_FUNC_FLAG(1 << 19)
(2)type

enum GB_enum_field_types定义:

enum GB_enum_field_types { GBASE_TYPE_DECIMAL, GBASE_TYPE_TINY,
                        GBASE_TYPE_SHORT,  GBASE_TYPE_LONG,
                        GBASE_TYPE_FLOAT,  GBASE_TYPE_DOUBLE,
                        GBASE_TYPE_NULL,   GBASE_TYPE_TIMESTAMP,
                        GBASE_TYPE_LONGLONG,GBASE_TYPE_INT24,
                        GBASE_TYPE_DATE,   GBASE_TYPE_TIME,
                        GBASE_TYPE_DATETIME, GBASE_TYPE_YEAR,
                        GBASE_TYPE_NEWDATE, GBASE_TYPE_VARCHAR,
                        GBASE_TYPE_BIT,
                        GBASE_TYPE_NEWDECIMAL=246,
                        GBASE_TYPE_ENUM=247,
                        GBASE_TYPE_SET=248,
                        GBASE_TYPE_TINY_BLOB=249,
                        GBASE_TYPE_MEDIUM_BLOB=250,
                        GBASE_TYPE_LONG_BLOB=251,
                        GBASE_TYPE_BLOB=252,
                        GBASE_TYPE_VAR_STRING=253,
                        GBASE_TYPE_STRING=254,
                        GBASE_TYPE_GEOMETRY=255,
                        GB_MAX_NO_FIELD_TYPES 
};

5、GBASE_STMT

该结构表示预处理语句。通过调用 gbase_stmt_init()创建语句,返回语句句柄,即指向 GBASE_STMT 的指针。该句柄用户所有后续的与语句有关的函数,直至使用 gbase_stmt_close()关闭了它为止。

GBASE_STMT 结构没有供应用程序使用的参数。此外,不应尝试复制GBASE_STMT 结构。不保证这类复制物会有用。

多个语句句柄能够与单个连接关联起来。对句柄数目的限制取决于系统资源。

typedef struct st_gbase_stmt
{
  GB_MEM_ROOT       mem_root;             
  GB_LIST           list;                 
  GBASE          *gbase;               
  GBASE_BIND     *params;              
  GBASE_BIND     *bind;                
  GBASE_FIELD    *fields;              
  GBASE_DATA     result;               
  GBASE_ROWS     *data_cursor;   
  int            (*read_row_func)(struct st_gbase_stmt *stmt, 
                                  unsigned char **row);  
  gs_ulonglong   affected_rows;
  gs_ulonglong   insert_id;            
  unsigned long	 stmt_id;	       
  unsigned long  flags;                
  unsigned long  prefetch_rows;   
  unsigned int   server_status;
  unsigned int	 last_errno;	       
  unsigned int   param_count;          
  unsigned int   field_count;          
  enum enum_gbase_stmt_state state;    
  char		 last_error[GBASE_ERRMSG_SIZE]; 
  char		 sqlstate[SQLSTATE_LENGTH+1];  
  gs_bool        send_types_to_server;
  gs_bool        bind_param_done;      
  unsigned char  bind_result_done;    
  gs_bool       unbuffered_fetch_cancelled;   
  gs_bool       update_max_length;     
  void *extension;
} GBASE_STMT;

6、GBASE_BIND

该结构用于语句输入(发送给服务器的数据值)和输出(从服务器返回的结果值)。对于输入,它与 gbase_stmt_bind_param()一起使用,用于将参数数据值绑定到缓冲区上,以供 gbase_stmt_execute()使用。对于输出,它与gbase_stmt_bind_result()一起使用,用于绑定结果缓冲区,以便用于用gbase_stmt_fetch()以获取行。

GBASE_BIND 结构包含下述供应用程序使用的成员。每个成员用于输入和输出,但在某些时候,也能用于不同的目的,具体情况取决于数据传输的方向。

typedef struct st_gbase_bind
{
  unsigned long	*length;          
  gs_bool       *is_null;	  
  void		*buffer;	  
  
  gs_bool       *error;
  unsigned char *row_ptr;         
  void (*store_param_func)(GB_NET *net, struct st_gbase_bind *param);
  void (*fetch_result)(struct st_gbase_bind *, GBASE_FIELD *,
                       unsigned char **row);
  void (*skip_result)(struct st_gbase_bind *, GBASE_FIELD *,
		      unsigned char **row);
  
  unsigned long buffer_length;
  unsigned long offset;           
  unsigned long	length_value;     
  unsigned int	param_number;	  
  unsigned int  pack_length;	  
  enum GB_enum_field_types buffer_type;	
  gs_bool       error_value;      
  gs_bool       is_unsigned;      
  gs_bool	long_data_used;	  
  gs_bool	is_null_value;    
  void *extension;
} GBASE_BIND;
参数描述
length指向 unsigned long 变量的指针,该变量指明了存储在*buffer 中数据的实际字节数。
is_null该成员指向 gs_bool 变量,如果值为 NULL,该变量为“真”,如果值为非 NULL,该变量为“假”。“is_null”是指向布尔类型的指针,而不是布尔标量,如果数据值总是NOT NULL,设置is_null = (gs_bool*) 0。
buffer指向缓冲区的指针。
buffer_length缓冲区的实现大小,单位为字节。
is_unsigned对于无符号类型,应将“is_unsigned”设置为“真”,对于带符号类型,应将其设置为“假”。
error对于输出,该成员用于通报数据截短错误。必须通过调用带有GBASE_REPORT_DATA_TRUNCATION选项的 gbase_options(),启用截短通报功能。允许该功能后,gbase_stmt_fetch()返回GBASE_DATA_TRUNCATED,而且对于出现截短情况的参数,在GBASE_BIND 结构中,错误标志为“真”。截短指明丢失了符号或有效位数,或字符串过长以至于无法容纳在1列中。

7、GBASE_TIME

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

typedef struct st_gbase_time
{
  unsigned int  year, month, day, hour, minute, second;
  unsigned long second_part;
  gs_bool       neg;
  enum enum_gbase_timestamp_type time_type;
} GBASE_TIME;
(1)enum enum_gbase_timestamp_type定义
enum enum_gbase_timestamp_type
{
  GBASE_TIMESTAMP_NONE= -2, GBASE_TIMESTAMP_ERROR= -1,
  GBASE_TIMESTAMP_DATE= 0, GBASE_TIMESTAMP_DATETIME= 1, GBASE_TIMESTAMP_TIME= 2
};

三、CAPI函数介绍

1、gbase_init

(1)声明
GBASE * gbase_init(GBASE *gbase);
(2)描述

分配或初始化与 gbase_real_connect()相适应的 GBASE 对象。如果 gbase是 NULL 指针,该函数将分配、初始化、并返回新对象。否则,将初始化对象,并返回对象的地址。如果 gbase_init()分配了新的对象,当调用 gbase_close()来关闭连接时。将释放该对象。

2、gbase_real_connect

(1)声明
GBASE * gbase_real_connect(GBASE *gbase, 
 const char *host,
 const char *user,
 const char *passwd,
 const char *db,
 unsigned int port,
 const char *unix_socket,
 unsigned long clientflag);
(2)描述

gbase_real_connect()尝试与运行在主机上的 GBase数据库引擎建立连接。在你能够执行需要有效 GBase 连接句柄结构的任何其他 API 函数之前,gbase_real_connect()必须成功完成。

clientflag值描述
CLIENT_COMPRESS使用压缩协议。
CLIENT_FOUND_ROWS返回发现的行数(匹配的),而不是受影响的行数。
CLIENT_INTERACTIVE关闭连接之前,允许 interactive_timeout(取代了 wait_timeout)秒的不活动时间。客户端的会话wait_timeout 变量被设为会话interactive_timeout 变量的值。
CLIENT_LOCAL_FILES允许 LOAD DATA LOCAL 处理功能。
CLIENT_MULTI_STATEMENTS通知服务器,客户端可能在单个字符串内发送多条语句(由‘;’隔开)。如果未设置该标志,将禁止多语句执行。
CLIENT_MULTI_RESULTS通知服务器,客户端能够处理来自多语句执行或存储程序的多个结果集。如果设置了CLIENT_MULTI_STATEMENTS,将自动设置它。
CLIENT_NO_SCHEMA禁止 db_name.tbl_name.col_name 语法。它用于ODBC。如果使用了该语法,它会使分析程序生成错误,在捕获某些 ODBC 程序中的缺陷时,它很有用。
CLIENT_ODBC客户端是 ODBC 客户端。它将 gbased 变得更为 ODBC友好。
CLIENT_SSL使用 SSL(加密协议)。该选项不应由应用程序设置,它是在客户端库内部设置的。

3、gbase_close

(1)声明
void gbase_close(GBASE *sock);
(2)描述

关闭前面打开的连接。如果句柄是由 gbase_init()或 gbase_connect()自动分配的,gbase_close()还将解除分配由 gbase 指向的连接句柄。

4、gbase_autocommit

(1)声明
gs_bool gbase_autocommit(GBASE * gbase, gs_bool auto_mode);
(2)描述

如果模式为‚1‛,启用 autocommit 模式;如果模式为‚0‛,禁止 autocommit模式。

5、gbase_real_query

(1)声明
int gbase_real_query(GBASE *gbase, const char *q, unsigned long length);
(2)描述

执行由query指向的 SQL 查询,它应是字符串长度字节long。正常情况下,字符串必须包含 1 条 SQL 语句,而且不应为语句添加终结分号(‘;’)或‚\g‛。如果允许多语句执行,字符串可包含由分号隔开的多条语句。

6、gbase_store_result

(1)声明
GBASE_RES * gbase_store_result(GBASE *gbase);
(2)描述

检索完整的结果集至客户端。如果成功,gbase_store_result()将复位
gbase_error()和 gbase_errno()。

7、gbase_stmt_bind_param

(1)声明
gs_bool gbase_stmt_bind_param(GBASE_STMT * stmt, GBASE_BIND * bnd);
(2)描述

将应用程序数据缓冲与预处理 SQL 语句中的参数标记符关联起来。

8、gbase_stmt_execute

(1)声明
int gbase_stmt_execute(GBASE_STMT *stmt);
(2)描述

执行预处理语句。

9、gbase_commit

(1)声明
gs_bool gbase_commit(GBASE * gbase);
(2)描述

提交当前事务。

10、gbase_free_result

(1)声明
void gbase_free_result(GBASE_RES *result);
(2)描述

释放由 gbase_store_result()、gbase_use_result()、gbase_list_dbs()等为结果集分配的内存。完成对结果集的操作后,必须调用 gbase_free_result()释放结果集使用的内存。释放完成后,不要尝试访问结果集。

11、gbase_stmt_close

(1)声明
gs_bool gbase_stmt_close(GBASE_STMT * stmt);
(2)描述

释放预处理语句使用的内存。

四、测试Demo

现在效率还比较慢,因为没有添加批量插入代码,CAPI我看了看手册或者MySql官网都没有找到类似于Python接口的executemany批量插入方法,是没有吗,还是我没找到,有知道的大佬告知一下。那我先改一版拼接sql,类似于

insert into czg.sun_copy values(?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?);

应该效率会上升一些,测试程序后续改进也会发出来,大家试用一下。

1、Demo运行效果

[root@czg0 src]# time ./Gbase8aCApiDemo 
192.168.142.10 : Connect Db Ok!!!
Source client character set: utf8
192.168.142.11 : Connect Db Ok!!!
Target client character set: utf8
========================================
Select Sql      : select * from czg.sun_copy
++++++++++++++++++++++++++
Insert Sql      : insert into czg.sun_copy values(?,?,?,?,?,?,?,?)
++++++++++++++++++++++++++
alias name         : a
max column len     : 1
charset            : 63
flags              : 32768    , info  :group
type               : 3        , info  :INTEGER
++++++++++++++++++++++++++
alias name         : b
max column len     : 3
charset            : 63
flags              : 32768    , info  :group
type               : 5        , info  :DOUBLE or REAL 
++++++++++++++++++++++++++
alias name         : c
max column len     : 3
charset            : 33
flags              : 0        , info  :unkown flags!!!
type               : 253      , info  :VARCHAR
++++++++++++++++++++++++++
alias name         : d
max column len     : 18
charset            : 33
flags              : 16       , info  :blob or text
type               : 252      , info  :BLOB or TEXT
++++++++++++++++++++++++++
alias name         : e
max column len     : 18
charset            : 63
flags              : 144      , info  :unkown flags!!!
type               : 252      , info  :BLOB or TEXT
++++++++++++++++++++++++++
alias name         : f
max column len     : 24
charset            : 63
flags              : 144      , info  :unkown flags!!!
type               : 252      , info  :BLOB or TEXT
++++++++++++++++++++++++++
alias name         : g
max column len     : 10
charset            : 63
flags              : 128      , info  :binary
type               : 10       , info  :DATE
++++++++++++++++++++++++++
alias name         : h
max column len     : 19
charset            : 63
flags              : 9441     , info  :unkown flags!!!
type               : 7        , info  :TIMESTAMP
++++++++++++++++++++++++++
DataNum : 100000
Elapsed Time : 64 s

2、测试表结构

gbase> desc sun_copy;
+-------+--------------+------+-----+-------------------+-----------------------------+
| Field | Type         | Null | Key | Default           | Extra                       |
+-------+--------------+------+-----+-------------------+-----------------------------+
| a     | int(11)      | YES  |     | NULL              |                             |
| b     | double       | YES  |     | NULL              |                             |
| c     | varchar(100) | YES  |     | NULL              |                             |
| d     | text         | YES  |     | NULL              |                             |
| e     | blob         | YES  |     | NULL              |                             |
| f     | longblob     | YES  |     | NULL              |                             |
| g     | date         | YES  |     | NULL              |                             |
| h     | timestamp    | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+-------+--------------+------+-----+-------------------+-----------------------------+
8 rows in set (Elapsed: 00:00:00.00)

3、迁移数据

gbase> select * from sun_copy limit 10;
+------+------+------+--------------------+--------------------+--------------------------+------------+---------------------+
| a    | b    | c    | d                  | e                  | f                        | g          | h                   |
+------+------+------+--------------------+--------------------+--------------------------+------------+---------------------+
|    2 |  1.1 | zxj  | 快乐的小天使       | qwertasdsdfzxczxxv | gregergjsfishfuieehfuiew | 1995-09-18 | 2022-08-03 09:24:00 |
|    2 |  1.1 | zxj  | 快乐的小天使       | qwertasdsdfzxczxxv | gregergjsfishfuieehfuiew | 1995-09-18 | 2022-08-03 09:24:00 |
|    2 |  1.1 | zxj  | 快乐的小天使       | qwertasdsdfzxczxxv | gregergjsfishfuieehfuiew | 1995-09-18 | 2022-08-03 09:24:00 |
|    2 |  1.1 | zxj  | 快乐的小天使       | qwertasdsdfzxczxxv | gregergjsfishfuieehfuiew | 1995-09-18 | 2022-08-03 09:24:00 |
|    2 |  1.1 | zxj  | 快乐的小天使       | qwertasdsdfzxczxxv | gregergjsfishfuieehfuiew | 1995-09-18 | 2022-08-03 09:24:00 |
|    2 |  1.1 | zxj  | 快乐的小天使       | qwertasdsdfzxczxxv | gregergjsfishfuieehfuiew | 1995-09-18 | 2022-08-03 09:24:00 |
|    2 |  1.1 | zxj  | 快乐的小天使       | qwertasdsdfzxczxxv | gregergjsfishfuieehfuiew | 1995-09-18 | 2022-08-03 09:24:00 |
|    2 |  1.1 | zxj  | 快乐的小天使       | qwertasdsdfzxczxxv | gregergjsfishfuieehfuiew | 1995-09-18 | 2022-08-03 09:24:00 |
|    2 |  1.1 | zxj  | 快乐的小天使       | qwertasdsdfzxczxxv | gregergjsfishfuieehfuiew | 1995-09-18 | 2022-08-03 09:24:00 |
|    2 |  1.1 | zxj  | 快乐的小天使       | qwertasdsdfzxczxxv | gregergjsfishfuieehfuiew | 1995-09-18 | 2022-08-03 09:24:00 |
+------+------+------+--------------------+--------------------+--------------------------+------------+---------------------+
10 rows in set (Elapsed: 00:00:00.01)
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐