虽然在ObConnector的帮助下,Oceanbase已经能够被psql等通用SQL客户端访问,但在一些特定场合(例如调试)可能还是需要对查询有更强的控制,这时候依然需要用户自己编写C/Java客户端,下面以一个例子简要说明C客户端的编写方法。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "oceanbase.h" /结果打印函数开始// const int MAX_DISPLAY_ROW_KEY_LEN = 48; char* get_display_row_key(const char* row_key, int64_t row_key_len) { const int aux_len = 2; const int ending_len = 1; static char dis_row_key[MAX_DISPLAY_ROW_KEY_LEN + aux_len + ending_len]; int64_t dis_row_key_len = row_key_len <= MAX_DISPLAY_ROW_KEY_LEN / 2 ? row_key_len : MAX_DISPLAY_ROW_KEY_LEN / 2; int64_t dis_len = dis_row_key_len * 2; dis_row_key[0] = '0'; dis_row_key[1] = 'x'; int i = 0; for (i = 0; i < dis_row_key_len; i++) { snprintf(dis_row_key + i * 2 + aux_len, 3, "%02x", (unsigned char)row_key[i]); } dis_row_key[dis_len + aux_len] = '\0'; return dis_row_key; } char* rowkey2hex(const char* row_key, int64_t row_key_len) { static char* hex = NULL; static int64_t hex_len = 0; if (NULL == hex || hex_len <= row_key_len) { if (NULL != hex && hex_len <= row_key_len) { free(hex); hex = NULL; } hex = (char*)malloc(row_key_len + 1); if (NULL != hex) { hex_len = row_key_len + 1; } } if (NULL != hex) { snprintf(hex, hex_len, "%.*x", row_key_len, row_key); } return hex; } char* trim_newline(char* s) { int s_len = strlen(s); while (s_len > 0 && s[s_len - 1] == '\n') { s[s_len - 1] = '\0'; s_len--; } return s; } void pcell(OB_CELL* cell) { printf("%ld", cell->table_len); printf("%.*s\t%s(%ld)\t%.*s\t", (int)cell->table_len, cell->table, rowkey2hex(cell->row_key, cell->row_key_len), cell->row_key_len, (int)cell->column_len, cell->column); switch (cell->v.type) { case OB_INT_TYPE: printf("%ld", cell->v.v.v_int); break; case OB_VARCHAR_TYPE: printf("%.*s", cell->v.v.v_varchar.len, cell->v.v.v_varchar.p); break; case OB_DATETIME_TYPE: printf("\t%s(%d.%d)", trim_newline(ctime(&(cell->v.v.v_datetime.tv_sec))), cell->v.v.v_datetime.tv_sec, cell->v.v.v_datetime.tv_usec); break; } if (cell->is_null || cell->is_row_not_exist || cell->is_row_changed) { printf("(%s%s%s)\n", cell->is_null ? "NULL " : "", cell->is_row_not_exist ? "ROW NOT EXIST " : "", cell->is_row_changed ? "NEW ROW" : ""); } else { printf("\n"); } } void pcolumnname(OB_RES* res) { OB_CELL* cell = NULL; cell = ob_fetch_cell(res); if (NULL != cell) { printf("\t\t%.*s", cell->column_len, cell->column); } while ((cell = ob_fetch_cell(res)) != NULL && !cell->is_row_changed) { printf("\t%.*s", cell->column_len, cell->column); } } void pres(OB_RES* res) { pcolumnname(res); printf("\n"); ob_res_seek_to_begin_cell(res); OB_ROW* row = NULL; while ((row = ob_fetch_row(res)) != NULL) { int64_t i = 0; printf("%s", get_display_row_key(row->cell[0].row_key, row->cell[0].row_key_len)); for (; i < row->cell_num; i++) { switch (row->cell[i].v.type) { case OB_INT_TYPE: printf("\t%ld", row->cell[i].v.v.v_int); break; case OB_VARCHAR_TYPE: printf("\t%.*s", row->cell[i].v.v.v_varchar.len, row->cell[i].v.v.v_varchar.p); break; case OB_DATETIME_TYPE: printf("\t%s(%d.%d)", trim_newline(ctime(&(row->cell[i].v.v.v_datetime.tv_sec))), row->cell[i].v.v.v_datetime.tv_sec, row->cell[i].v.v.v_datetime.tv_usec); break; } } printf("\n"); } } /结果打印函数结束// 上面是结果输出部分,主要是处理一些字符串和格式化问题,稍微看看即可。重点请关注下面的核心逻辑 int main(int argc, char **argv) { /// select nick,auc_cnt_max_cnt,prov from test_seller_wm_4 /// where /*+ rowkey, issue_id:6,cat_id:8,selr_user_id:8 */ issue_id = '201145' and cat_id=16 /// and nick='lovinlovin3' and prov='shanghai3' limit 2 offset 0; /* char* table = "collect_item"; char* column1 = "item_collector_count"; char* column2 = "item_collect_count"; char* rowkey1 = "AAAAAAAAA"; char* rowkey2 = "AAAAAAAAF"; */ char* table = "test_seller_wm_4"; char* column1 = "nick"; char* column2 = "prov"; char* column3 = "auc_cnt_max_cnt"; char rowkey1[44]; char rowkey2[44]; OB_ERR_CODE err = OB_ERR_SUCCESS; memset(rowkey1, 0x00, 44); memset(rowkey2, 0x00, 44); memcpy(&rowkey1[0], "201145", 6); rowkey1[8+6-1] = 16; memcpy(&rowkey2[0], "201145", 6); rowkey2[8+6-1] = 16; memset(&rowkey2[14], 0xff, 8); OB* ob = ob_api_init(); if (NULL == ob) { fprintf(stderr, "ob_init error: %s\n", ob_error()); return 1; } ob_api_debug_log(ob, "DEBUG", NULL); if (argc > 2) { fprintf(stderr, "connection param used: %s:%s\n", argv[1], argv[2]); char *rs_ip = argv[1]; int rs_port = atoi(argv[2]); // 连接OceanBase err = ob_connect(ob, rs_ip, rs_port, NULL, NULL); } else { // 连接OceanBase err = ob_connect(ob, "172.24.131.234", 5433, NULL, NULL); } if (OB_ERR_SUCCESS != err) { fprintf(stderr, "ob_connect error: %s\n", ob_error()); } else { // 获得OB_SCAN结构体 OB_SCAN* scan_st = ob_acquire_scan_st(ob); if (NULL == scan_st) { fprintf(stderr, "ob_acquire_scan_st error: %s\n", ob_error()); } else { memset(rowkey1, 0x00, 22); memset(rowkey2, 0xff, 22); ob_scan(scan_st, table, rowkey1, 22, 1, rowkey2, 22, 1); ob_scan_column(scan_st, "nick", 1); ob_scan_column(scan_st, "prov", 1); //ob_scan_complex_column(scan_st, "1=1", "_expr0", 0); //ob_scan_complex_column(scan_st, "2 < 1", "_expr1", 0); ob_scan_complex_column(scan_st, "nick='lovinlovin'", "_expr0", 0); ob_scan_complex_column(scan_st, "`prov`='shanghai'", "_expr1", 0); //ob_scan_complex_column(scan_st, "3+4", "_expr2", 0); //ob_scan_complex_column(scan_st, "nick='songyi0209'", "_expr1", 0); //ob_scan_set_where(scan_st, "nick='lovinlovin' and prov='shanghai'"); //ob_scan_set_where(scan_st, "_expr0 or nick='songyi0209'"); if (argc > 3) { } else { //ob_scan_set_where(scan_st, "`_expr0` = `_expr0` and `prov`='beijing'"); fprintf(stderr, "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"); //ob_scan_set_where(scan_st, "_expr2 < 10 and (_expr1 or _expr0)"); ob_scan_set_where(scan_st, "_expr1 and _expr0"); } //ob_scan_set_where(scan_st, "_expr0 = _expr1"); //ob_scan_set_where(scan_st, "nick='lovinlovin'"); //ob_scan_column(scan_st, column2, 1); //ob_scan_column(scan_st, column3, 1); ob_scan_set_limit(scan_st,0, 20); if (OB_ERR_SUCCESS != ob_errno()) { fprintf(stderr, "ob_scan error: %s\n", ob_error()); } else { OB_RES* res_st = ob_exec_scan(ob, scan_st); if (NULL == res_st) { fprintf(stderr, "ob_exec_scan error(%d): %s\n", ob_errno(), ob_error()); } else { printf("scan succ: row_num=%ld\n", ob_fetch_row_num(res_st)); pres(res_st); #if 0 OB_CELL* cell = NULL; while ((cell = ob_fetch_cell(res_st)) != NULL) { pcell(cell); } #endif } ob_release_res_st(ob, res_st); } ob_release_scan_st(ob, scan_st); } } ob_api_destroy(ob); return 0; } 执行方式:
./scan_client rs_ip rs_port
简要说明:
主要函数包括:
ob_api_init,ob_connect,ob_acquire_scan_st,ob_scan,ob_scan_column,ob_scan_complex_column,ob_scan_set_where,ob_scan_set_limit,ob_exec_scan,ob_fetch_cell,ob_release_scan_st,ob_api_destroy
其中ob_scan,ob_scan_column,ob_scan_complex_column,ob_scan_set_where,ob_scan_set_limit,ob_exec_scan这几个函数是与scan相关的(oceanbase还支持get,支持单个或者多个cell的获取,而不是scan这种按行获取)
Oceanbase C客户端API手册下载:
http://ishare.iask.sina.com.cn/f/22948741.html
作者邮箱:hustos@qq.com