返回首页

gbase数据、南大通用产品文档:GBase8c

更新日期:2024年09月11日

使用指导
前提条件

需要保证用户提供训练数据。

如果用户通过提供的工具收集训练数据,则需要启用WDR 功能,涉及到的参数为
track_stmt_stat_level 和log_min_duration_statement,具体情况见下面小结。

为保证预测准确率,用户提供的历史语句日志应尽可能全面并具有代表性。
SQL 流水采集方法
本工具需要用户提前准备数据,训练数据格式如下,每个样本通过换行符分隔:
SQL,EXECUTION_TIME
预测数据格式如下:
SQL

GBase 8c V5 开发者手册
南大通用数据技术股份有限公司
396
其中SQL 表示SQL 语句的文本,EXECUTION_TIME 表示SQL 语句的执行时间,样
例数据见sample_data 中的train.csv 和predict.csv。
用户可以按照要求格式自己收集训练数据,工具也提供了脚本自动采集
(load_sql_from_rd ),该脚本基于WDR 报告获取SQL 信息,涉及到的参数有
log_min_duration_statement 和track_stmt_stat_level:

其中log_min_duration_statement 表示慢SQL 阈值,如果为0 则全量收集,时间单位为
毫秒;

track_stmt_stat_level 表示信息捕获的级别,建议设置为track_stmt_stat_level='L0,L0'
参数开启后,可能占用一定的系统资源,但一般不大。持续的高并发场景可能产生5%
以内的损耗,数据库并发较低的场景,性能损耗可忽略。下述脚本存在于sqldiag 根目录
($GAUSSHOME/bin/components/sqldiag)中。
使用脚本获取训练集方式:
load_sql_from_wdr.py [-h] --port PORT --start_time START_TIME
--finish_time FINISH_TIME [--save_path SAVE_PATH]
例如:
python load_sql_from_wdr.py --start_time "2021-04-25 00:00:00" --finish_time
"2021-04-26 14:00:00" --port 5432
--save_path ./data.csv
操作步骤
(1)
提供历史日志以供模型训练
(2)
进行训练与预测操作。
基于模板法的训练与预测:
gs_dbmind component sqldiag [train, predict] -f FILE --model template --model-path
template_model_path
基于DNN 的训练与预测:
gs_dbmind component sqldiag [train, predict] -f FILE --model dnn --model-path
dnn_model_path
使用方法示例
使用提供的测试数据进行模板化训练:
gs_dbmind component sqldiag train -f ./sample_data/train.csv --model template
--model-path ./template
使用提供的测试数据进行模板化预测:

GBase 8c V5 开发者手册
南大通用数据技术股份有限公司
397
gs_dbmind component sqldiag predict -f ./sample_data/predict.csv --model template
--model-path ./template --predicted-file ./result/t_result
使用提供的测试数据进行模板化模型更新:
gs_dbmind component sqldiag finetune -f ./sample_data/train.csv --model template
--model-path ./template
使用提供的测试数据进行DNN 训练:
gs_dbmind component sqldiag train -f ./sample_data/train.csv --model dnn
--model-path ./dnn_model
使用提供的测试数据进行DNN 预测:
gs_dbmind component sqldiag predict -f ./sample_data/predict.csv --model dnn
--model-path ./dnn_model --predicted-file
使用提供的测试数据进行DNN 模型更新:
gs_dbmind component sqldiag finetune -f ./sample_data/train.csv --model dnn
--model-path ./dnn_model


GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 546 -
dyn_sql.ec 程序是一个使用动态 SQL 的 GBase 8s ESQL/C 演示程序。
该程序提示用
户输入 stores7 演示数据库的 SELECT 语句,
然后,
使用系统描述符区域来动态地执行该
SELECT。

在缺省情况下,该程序打开 stores7 数据库。然而,如果给定了演示数据库的名称而
不是 stores7,则您可在命令行上指定数据库名称。下列命令在 mystores7 数据库上运行
可执行的 dyn_sql:
dyn_sql mystores7
编译该程序
请使用下列命令来编译 dyn_sql 程序:
esql -o dyn_sql dyn_sql.ec

-o dyn_sql 选项导致将可执行程序命名为 dyn_sql。不带有 -o 选项,则可执行程序
的名称缺省为 a.out。
dyn_sql.ec 文件指南
=================================================================
======
1. /*
2. This program prompts the user to enter a SELECT statement
3. for the stores7 database. It processes the statement using
dynamic sql
4. and system descriptor areas and displays the rows returned by the
5. database server.
6. */
7. #include
8. #include
9. #include
10. EXEC SQL include sqltypes;
11. EXEC SQL include locator;
12. EXEC SQL include datetime;
13. EXEC SQL include decimal;
14. #define WARNNOTIFY 1
15. #define NOWARNNOTIFY 0
16. #define LCASE(c) (isupper(c) ? tolower(c) : (c))

GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 547 -
17. #define BUFFSZ 256
18. extern char statement[80];
=================================================================
======

7 - 13 行

这些行指定要包括在该程序中的 C 和 GBase 8s ESQL/C 文件。stdio.h 文件启用
dyn_sql 来使用标准 C I/O 库。stdlib.h 文件包含从字符串至数值的转换函数、内存分配函
数和各种各样的标准库函数。ctypes.h 文件包含检查字符的属性的宏。例如,确定字符为
大写还是小写的宏。

sqltypes.h 头文件包含对应于在 GBase 8s 数据库中找到的数据类型的符号常量。

程序使用这些常量来确定动态 SELECT 语句返回的列的数据类型。

locator.h 文件包含定位器结构(ifx_loc_t)的定义,其为 TEXT 和 BYTE 列所需要
的主变量的类型。datetime.h 文件包含 datetime 和 interval 结构的定义,其为
DATETIME 和 INTERVAL 列的主变量的数据类型。decimal.h 文件包含 dec_t 结构的定
义,其为 DECIMAL 列所需要的主变量的类型。


14 - 17 行

exp_chk() 异常处理函数使用 WARNNOTIFY 和 NOWARNNOTIFY 常量(14 和
15 行)。exp_chk() 的第二个参数告诉该函数显示 SQLSTATE 中的信息,以及
警告的 SQLCODE 变量
(WARNNOTIFY)

或不显示警告的信息
(NOWARNNOTIFY)

exp_chk() 函数在 exp_chk.ec 源文件中。

16 行定义 LCASE,
一个将大写字符转换为小写字符的宏。
17 行将 BUFFSZ 定义为
数值 256。该程序使用 BUFFSZ 来指定存储来自用户的输入的数组的大小。


18 行

18 行声明 statement 作为外部全局变量,来保存该程序请求数据库服务器执行的最

GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 548 -
后 的 SQL 语句的名称。该异常处理函数使用此信息(请参阅 399 - 406 行。)

=================================================================
======
19. EXEC SQL BEGIN DECLARE SECTION;
20. ifx_loc_t lcat_descr;
21. ifx_loc_t lcat_picture;
22. EXEC SQL END DECLARE SECTION;
23. mint whenexp_chk();
24. main(argc, argv)
25. mint argc;
26. char *argv[];
27. {
28. int4 ret, getrow();
29. short data_found = 0;
30. EXEC SQL BEGIN DECLARE SECTION;
31. char ans[BUFFSZ], db_name[30];
32. char name[40];
33. mint sel_cnt, i;
34. short type;
35. EXEC SQL END DECLARE SECTION;
36. printf("DYN_SQL Sample ESQL Program running.\n\n");
37. EXEC SQL whenever sqlerror call whenexp_chk;
38. if (argc > 2) /* correct no. of args? */
39. {
40. printf("\nUsage: %s [database]\nIncorrect no. of
argument(s)\n",
41. argv[0]);
42. printf("\nDYN_SQL Sample Program over.\n\n");
43. exit(1);
44. }
45. strcpy(db_name, "stores7");
46. if(argc == 2)

GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 549 -
47. strcpy(db_name, argv[1]);
48. sprintf(statement,"CONNECT TO %s",db_name);
49. EXEC SQL connect to :db_name;
50. printf("Connected to %s\n", db_name);
51. ++argv;
=================================================================
======

19 - 23 行

19 - 23 行定义在 SQL 语句中使用的全局主变量。20 和 21 行定义定位器结构,其
为 catalog 表的 cat_descr 和 cat_picture 列的主变量。23 行声明 whenexp_chk() 函数,
当发生 SQL 语句错误时,该程序调用它。


24 - 27 行

main() 函数是该程序开始执行的始点。argc 函数给定当调用该程序时,来自命令行
的参数的数目。argv 是一个执行命令行参数的指针的数组。此程序仅期望一个参数(要访
问的数据库的名称),且它是可选的。


28 - 51 行

28 行定义 int4 数据类型(ret)来接收来自 getrow() 函数的返回值。
28 行还声明 getrow 函数返回 int4 数据类型。30 - 35 行定义 main() 函数
块的本地主变量。如果在 SQL 语句中发生任何错误,则 37 行执行 WHENEVER
语句来将控制转移至 whenexp_chk()。

38 - 51 行建立到数据库的连接。如果 argc 等于 2,则该程序假设用户在命令行上输
入了数据库名称(按照惯例,第一个参数是该程序的名称),且该程序打开此数据库。如
果用户未在命令行上输入数据库名称,则该程序打开 stores7 数据库(请参阅 45 行),
这是缺省的。在这两种情况下,该程序连接到由 GBASEDBTSERVER 环境变量指定的缺
省数据库服务器,因为未指定数据库服务器。


GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 550 -
=================================================================
======
52. while(1)
53. {
54. /* prompt for SELECT statement */
55. printf("\nEnter a SELECT statement for the %s database",
56. db_name);
57. printf("\n\t(e.g. select * from customer;)\n");
58. printf("\tOR a ';' to terminate program:\n>> ");
59. if(!getans(ans, BUFFSZ))
60. continue;
61. if (*ans == ';')
62. {
63. strcpy(statement, "DISCONNECT");
64. EXEC SQL disconnect current;
65. printf("\nDYN_SQL Sample Program over.\n\n");
66. exit(1);
67. }
68. /* prepare statement id */
69. printf("\nPreparing statement (%s)...\n", ans);
70. strcpy(statement, "PREPARE sel_id");
71. EXEC SQL prepare sel_id from :ans;
72. /* declare cursor */
73. printf("Declaring cursor 'sel_curs' for SELECT...\n");
74. strcpy(statement, "DECLARE sel_curs");
75. EXEC SQL declare sel_curs cursor for sel_id;
76. /* allocate descriptor area */
77. printf("Allocating system-descriptor area...\n");
78. strcpy(statement, "ALLOCATE DESCRIPTOR selcat");
79. EXEC SQL allocate descriptor 'selcat';
80. /* Ask the database server to describe the statement */
81. printf("Describing prepared SELECT...\n");
82. strcpy(statement,

GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 551 -
83. "DESCRIBE sel_id USING SQL DESCRIPTOR selcat");
84. EXEC SQL describe sel_id using sql descriptor 'selcat';
85. if (SQLCODE != 0)
86. {
87. printf("** Statement is not a SELECT.\n");
88. free_stuff();
89. strcpy(statement, "DISCONNECT");
90. EXEC SQL disconnect current;
91. printf("\nDYN_SQL Sample Program over.\n\n");
92. exit(1);
93. }
=================================================================
======

52 - 67 行

52 行上的 while(1) 开始一个持续到 main() 函数的结束的循环。55 - 58 行提示用户
输入 SELECT 语句,或输入分号终止该程序。getans() 函数从用户接收该输入。如果第一
个字符不是分号,则该程序继续处理输入。


68 - 75 行

PREPARE 语句准备来自数组 ans[] 的(用户输入的)SELECT 语句,并为它指定语
句标识符 sel_id。PREPARE 语句使得数据库服务器能够解析、验证并为该语句生成执行
计划。

DECLARE 语句(72 - 75 行)为 SELECT 语句返回的行集创建 sel_curs 游标,如
果它返回多行的话。


76 - 79 行


GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 552 -
ALLOCATE DESCRIPTOR 语句在内存中分配 selcat 系统描述符区域。该语句不包
括 WITH MAX 子句,因此使用缺省的内存分配,其为 100 列分配。


80 - 93 行

DESCRIBE 语句从数据库服务器获得关于 sel_id 语句标识符中的语句的信息。数据
库服务器返回 selcat 系统描述符区域中的信息,前面的 ALLOCATE DESCRIPTOR 语句
创建该信息。DESCRIBE 放入系统描述符区域内的信息,包括选择列表中列的名称、数据
类型和长度。

DESCRIBE 语句还将 SQLCODE 变量设置为指示被描述的语句的类型的数值。要检
查该语句类型是否为 SELECT,
85 行将 SQLCODE 的值与 0 相比较
(对于不带有 INTO
TEMP 子句的 SELECT 语句,
在 sqlstypes.h 文件中定义该值)

如果该语句不是 SELECT,
则 87 行显示相关意思的消息,该程序释放已分配了的游标和资源。然后,它关闭连接并
退出。

=================================================================
======
94. /* Determine the number of columns in the select list */
95. printf("Getting number of described values from ");
96. printf("system-descriptor area...\n");
97. strcpy(statement, "GET DESCRIPTOR selcat: COUNT field");
98. EXEC SQL get descriptor 'selcat' :sel_cnt = COUNT;
99. /* open cursor; process select statement */
100. printf("Opening cursor 'sel_curs'...\n");
101. strcpy(statement, "OPEN sel_curs");
102. EXEC SQL open sel_curs;
103. /*
104. * The following loop checks whether the cat_picture or
105. * cat_descr columns are described in the system-descriptor area.
106. * If so, it initializes a locator structure to read the simple
107. * large-object data into memory and sets the address of the
108. * locator structure in the system-descriptor area.

GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 553 -
109. */
110. for(i = 1; i <= sel_cnt; i++)
111. {
112. strcpy(statement,
113. "GET DESCRIPTOR selcat: TYPE, NAME fields");
114. EXEC SQL get descriptor 'selcat' VALUE :i
115. :type = TYPE,
116. :name = NAME;
117. if (type == SQLTEXT && !strncmp(name, "cat_descr",
118. strlen("cat_descr")))
119. {
120. lcat_descr.loc_loctype = LOCMEMORY;
121. lcat_descr.loc_bufsize = -1;
122. lcat_descr.loc_oflags = 0;
123. strcpy(statement, "SET DESCRIPTOR selcat: DATA field");
124. EXEC SQL set descriptor 'selcat' VALUE :i
125. DATA = :lcat_descr;
126. }
127. if (type == SQLBYTES && !strncmp(name, "cat_picture",
128. strlen("cat_picture")))
129. {
130. lcat_picture.loc_loctype = LOCMEMORY;
131. lcat_picture.loc_bufsize = -1;
132. lcat_picture.loc_oflags = 0;
133. strcpy(statement, "SET DESCRIPTOR selcat: DATA field");
134. EXEC SQL set descriptor 'selcat' VALUE :i
135. DATA = :lcat_picture;
136. }
137. }
=================================================================
======

94 - 98 行

GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 554 -

GET DESCRIPTOR 语句从 selcat 系统描述符区域检索 COUNT 值。该 COUNT 值
指示在该系统描述符区域中描述了多少列。


99 - 102 行

OPEN 语句开始执行动态 SELECT 语句,并为它返回的列集激活 sel_curs 游标。


114 - 137 行

本部分代码使用 GET DESCRIPTOR 语句来确定在选择列表中是否包括来自 catalog
表的简单大对象(cat_descr 和 cat_picture)。如果您动态地选择简单大对象列,则您必
须将定位符结构的地址设置到该项描述符的 DATA 字段内,
以便告诉数据库将定位器结构
返回至哪里。

然而,首先,该程序初始化定位器结构,如下:
在内存缓冲区中返回的数据(loc_loctype = LOCMEMORY)。
数据库服务器分配该内存缓冲区(loc_bufsize = -1)。

然后,该程序使用 SET DESCRIPTOR 语句来将定位器结构的地址加载至描述符区域
的 DATA 字段。

=================================================================
======
138. while(ret = getrow("selcat")) /* fetch a row */
139. {
140. data_found = 1;
141. if (ret < 0)
142. {
143. strcpy(statement, "DISCONNECT");
144. EXEC SQL disconnect current;

GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 555 -
145. printf("\nDYN_SQL Sample Program over.\n\n");
146. exit(1);
147. }
148. disp_data(sel_cnt, "selcat"); /* display the data */
149. }
150. if (!data_found)
151. printf("** No matching rows found.\n");
152. free_stuff();
153. if (!more_to_do()) /* More to do? */
154. break; /* no, terminate loop */
155. }
156. }
157. /* fetch the next row for selected items */
158. int4 getrow(sysdesc)
159. EXEC SQL BEGIN DECLARE SECTION;
160. PARAMETER char *sysdesc;
161. EXEC SQL END DECLARE SECTION;
162. {
163. int4 exp_chk();
164. sprintf(statement, "FETCH %s", sysdesc);
165. EXEC SQL fetch sel_curs using sql descriptor :sysdesc;
166. return((exp_chk(statement)) == 100 ? 0 : 1);
167. }
=================================================================
======

138 - 149 行

getrow() 函数逐一地检索选择了的行。while 循环的每一迭代检索一行,
然后,该程序以 disp_data() 函数(148 行)处理这行。当检索了所有行时,
getrow() 返回 0(零),该 while 循环结束。

152 行


GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 556 -
free_stuff() 函数释放当处理动态 SELECT 语句时分配了的那些资源。

153 - 156 行

当处理了所有选择的行时,该程序调用 more_to_do() 函数,其询问用户是否要处理
更多的 SELECT 语句。如果回答为否,则 more_to_do() 返回 0,且 break 语句终止始于
52 行的 while 循环。如果回答为是,则程序开始 52 行上的 while 语句的下一迭代,来
接收和处理另一 SELECT 语句。


157 - 167 行

getrow() 函数移动游标,然后访存由动态 SELECT 语句返回的行集中的下一行。它
将该行值访存至系统描述符区域内,在 sysdesc 变量中指定它。如果没有更多的行要访存
(exp_chk() 返回 100)

则 getrow() 返回 0。
如果 FETCH 遇到运行时刻错误,
则 getrow()
返回 1。


=================================================================
======
168. {/*
169. * This function loads a column into a host variable of the correct
170. * type and displays the name of the column and the value, unless
* the
171. * value is NULL.
172. disp_data(col_cnt, sysdesc)
173. */
174. mint col_cnt;
175. EXEC SQL BEGIN DECLARE SECTION;
176. PARAMETER char *sysdesc;
177. EXEC SQL END DECLARE SECTION;
178. EXEC SQL BEGIN DECLARE SECTION;
179. mint int_data, i;
180. char *char_data;

GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 557 -
181. int4 date_data;
182. datetime dt_data;
183. interval intvl_data;
184. decimal dec_data;
185. short short_data;
186. char name[40];
187. short char_len, type, ind;
188. EXEC SQL END DECLARE SECTION;
189. int4 size;
190. unsigned amount;
191. mint x;
192. char shdesc[81], str[40], *p;
193. printf("\n\n");
194. /* For each column described in the system descriptor area,
195. * determine its data type. Then retrieve the column name and its
196. * value, storing the value in a host variable defined for the
197. * particular data type. If the column is not NULL, display the
198. * name and value.
199. */
200. for(i = 1; i <= col_cnt; i++)
201. {
202. strcpy(statement, "GET DESCRIPTOR: TYPE field");
203. EXEC SQL get descriptor :sysdesc VALUE :i
204. :type = TYPE;
205. switch(type)
206. {
207. case SQLSERIAL:
208. case SQLINT:
209. strcpy(statement,
210. "GET DESCRIPTOR: NAME, INDICATOR, DATA fields");
211. EXEC SQL get descriptor :sysdesc VALUE :i
212. :name = NAME,
213. ind = INDICATOR,

GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 558 -
214. :int_data = DATA;
215. if(ind == -1)
216. printf("\n%.20s: NULL", name);
217. else
218. printf("\n%.20s: %d", name, int_data);
219. break;
220. case SQLSMINT:
221. strcpy(statement,
222. "GET DESCRIPTOR: NAME, INDICATOR, DATA fields");
223. EXEC SQL get descriptor :sysdesc VALUE :i
224. :name = NAME,
225. :ind = INDICATOR,
226. :short_data = DATA;
227. if(ind == -1)
228. printf("\n%.20s: NULL", name);
229. else
230. printf("\n%.20s: %d", name, short_data);
231. break;
232. case SQLDECIMAL:
233. case SQLMONEY:
234. strcpy(statement,
235. "GET DESCRIPTOR: NAME, INDICATOR, DATA fields");
236. EXEC SQL get descriptor :sysdesc VALUE :i
237. :name = NAME,
238. :ind = INDICATOR,
239. :dec_data = DATA;
240. if(ind == -1)
241. printf("\n%.20s: NULL", name);
242. else
243. {
244. if(type == SQLDECIMAL)
245. rfmtdec(&dec_data, "###,###,###.##", str);
246. else

GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 559 -
247. rfmtdec(&dec_data, "$$$,$$$,$$$.$$", str);
248. printf("\n%.20s: %s", name, str);
249. }
250. break;
251. case SQLDATE:
252. strcpy(statement,
253. "GET DESCRIPTOR: NAME, INDICATOR, DATA fields");
254. EXEC SQL get descriptor :sysdesc VALUE :i
255. :name = NAME,
256. :ind = INDICATOR,
257. :date_data = DATA;
258. if(ind == -1)
259. printf("\n%.20s: NULL", name);
260. else
261. {
262. if((x = rfmtdate(date_data, "mmm. dd, yyyy",
263. str)) < 0)
264. printf("\ndisp_data() - DATE - fmt error");
265. else
266. printf("\n%.20s: %s", name, str);
267. }
268. break;
269. case SQLDTIME:
270. strcpy(statement,
271. "GET DESCRIPTOR: NAME, INDICATOR, DATA fields");
272. EXEC SQL get descriptor :sysdesc VALUE :i
273. :name = NAME,
274. :ind = INDICATOR,
275. :dt_data = DATA;
276. if(ind == -1)
277. printf("\n%.20s: NULL", name);
278. else
279. {

GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 560 -
280. x = dttofmtasc(&dt_data, str, sizeof(str), 0);
281. printf("\n%.20s: %s", name, str);
282. }
283. break;
284. case SQLINTERVAL:
285. strcpy(statement,
286. "GET DESCRIPTOR: NAME, INDICATOR, DATA fields");
287. EXEC SQL get descriptor :sysdesc VALUE :i
288. :name = NAME,
289. :ind = INDICATOR,
290. :intvl_data = DATA;
291. if(ind == -1)
292. printf("\n%.20s: NULL", name);
293. else
294. {
295. if((x = intofmtasc(&intvl_data, str,
296. sizeof(str),
297. "%3d days, %2H hours, %2M minutes"))
298. < 0)
299. printf("\nINTRVL - fmt error %d", x);
300. else
301. printf("\n%.20s: %s", name, str);
302. }
303. break;
304. case SQLVCHAR:
305. case SQLCHAR:
306. strcpy(statement,
307. "GET DESCRIPTOR: LENGTH, NAME fields");
308. EXEC SQL get descriptor :sysdesc VALUE :i
309. :char_len = LENGTH,
310. :name = NAME;
311. amount = char_len;
312. if(char_data = (char *)(malloc(amount + 1)))

GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 561 -
313. {
314. strcpy(statement,
315. "GET DESCRIPTOR: NAME, INDICATOR, DATA fields");
316. EXEC SQL get descriptor :sysdesc VALUE :i
317. :char_data = DATA,
318. :ind = INDICATOR;
319. if(ind == -1)
320. printf("\n%.20s: NULL", name);
321. else
322. printf("\n%.20s: %s", name, char_data);
323. }
324. else
325. {
326. printf("\n%.20s: ", name);
327. printf("Can't display: out of memory");
328. }
329. break;
330. case SQLTEXT:
331. strcpy (statement,
332. "GET DESCRIPTOR: NAME, INDICATOR, DATA fields");
333. EXEC SQL get descriptor :sysdesc VALUE :i
334. :name = NAME,
335. :ind = INDICATOR,
336. :lcat_descr = DATA;
337. size = lcat_descr.loc_size; /* get size of data */
338. printf("\n%.20s: ", name);
339. if(ind == -1)
340. {
341. printf("NULL");
342. break;
343. }
344. p = lcat_descr.loc_buffer; /* set p to buf addr */
345. /* print buffer 80 characters at a time */

GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 562 -
346. while(size >= 80)
347. {
348. /* mv from buffer to shdesc */
349. ldchar(p, 80, shdesc);
350. printf("\n%80s", shdesc); /* display it */
351. size -= 80; /* decrement length */
352. p += 80; /* bump p by 80 */
353. }
354. strncpy(shdesc, p, size);
355. shdesc[size] = '\0';
356. printf("%-s\n", shdesc); /* dsply last segment */
357. break;
358. case SQLBYTES:
359. strcpy (statement,
360. "GET DESCRIPTOR: NAME, INDICATOR fields");
361. EXEC SQL get descriptor :sysdesc VALUE :i
362. :name = NAME,
363. :ind = INDICATOR;
364. if(ind == -1)
365. printf("%.20s: NULL", name);
366. else
367. {
368. printf("%.20s: ", name);
369. printf("Can't display BYTE type value");
370. }
371. break;
372. default:
373. printf("\nUnexpected data type: %d", type);
374. EXEC SQL disconnect current;
375. printf("\nDYN_SQL Sample Program over.\n\n");
376. exit(1);
377. }
378. }

GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 563 -
379. printf("\n");
380.}
=================================================================
======

168 - 380 行

disp_data() 函数显示该 SELECT 语句返回的每一行中存储的值。该函数必须能够接
收和处理该动态 SELECT 语句的作用域内的任何数据类型
(在此情况下,
为 stores7 数据
库内的任何列)。此函数接收两个参数:col_cnt 包含那些在系统描述符区域中包含的列的
数目,sysdesc 包含包含该列信息的系统描述符区域的名称。必须以 PARAMETER 关键字
来声明这第二个参数,因为在 FETCH 语句中使用该参数。

disp_data() 函数首先为在 stores7 数据库中找到的每一数据类型定义主变量(178 -
188 行),除了已经为 catalog 表的 cat_descr 和 cat_picture 列全局地定义了的定位符
结构之外(19 - 22 行)。

对于系统描述符区域中描述的每一列,
disp_data() 以 GET DESCRIPTOR 语句检索它
的数据类型。接下来,disp_data() 对该数据类型执行 switch,对于每一类型(列),它执
行另一 GET DESCRIPTOR 语句来检索该列的名称、指示符标志和数据。除非该列为空,
否则 disp_data() 将列数据从系统描述符区域的 DATA 字段移至对应的主变量。然后,它
显示列名称和主变量的内容。

disp_data() 使用在 sqltypes.h 中定义的符号常量来比较数据类型。
它还使用 GBase 8s
ESQL/C 库函数 rfmtdec()、rfmtdate()、dttofmtasc() 和 intofmtosc() 来为显示格式化
DECIMAL 和 MONEY、DATE、DATETIME 和 INTERVAL 数据类型。

对于 TEXT 和 BYTE 数据类型,由于数据库服务器返回定位器结构,而不是数据,
因此,您可以下列两个阶段的处理,来检索该列的值:
GET DESCRIPTOR 语句(333 和 361 行)从系统描述符区域检索定位符结构,并将
它移至 ifx_loc_t 主变量。
disp_data() 函数包含来自定位符结构的数据缓冲区的地址,
在 loc_buffer 中,
并从那
里检索该数据。

关于 BYTE 数据类型,为了简短起见,disp_data() 检索定位符结构,但

GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 564 -
不显示该数据。

=================================================================
======
381. free_stuff()
382. {
383. EXEC SQL free sel_id; /* free resources for statement */
384. EXEC SQL free sel_curs; /* free resources for cursor */
385. /* free system descriptor area */
386. EXEC SQL deallocate descriptor 'selcat';
387. }
388. /*
389. * The inpfuncs.c file contains the following functions used in
* this
390. * program:
391. * more_to_do() - asks the user to enter 'y' or 'n' to indicate
392. * whether to run the main program loop again.
393. *
394. * getans(ans, len) - accepts user input, up to 'len' number of
395. * characters and puts it in 'ans'
396. */
397. #include "inpfuncs.c"
398. /*
399 * The exp_chk.ec file contains the exception handling functions to
400. * check the SQLSTATE status variable to see if an error has
* occurred
401. * following an SQL statement. If a warning or an error has
402. * occurred, exp_chk() executes the GET DIAGNOSTICS statement and
403. * displays the detail for each exception that is returned.
404. */
405. EXEC SQL include exp_chk.ec;
=================================================================
======


GBase 8s ESQL/C 编程指南
南大通用数据技术股份有限公司
- 565 -
381 - 387 行

free_stuff() 函数释放为处理该动态语句而分配了的资源。383 行释放由该应用程序在
准备动态 SELECT 语句时分配了的资源。384 行释放由数据库服务器处理 sel_curs 游标
而分配了的资源。DEALLOCATE DESCRIPTOR 语句释放为 selcat 系统描述符区域及其
相关联的数据区域分配了的内存。


388 - 397 行

几个 GBase 8s ESQL/C 演示程序还调用 more_to_do() 和 getans() 函数。

因此,还将这些函数分至单独的 C 源文件内,包含在恰当的演示程序中。 这
些函数都不包含 GBase 8s ESQL/C,因此, 该程序可使用 C #include 预处理
器语句来包括该文件。

398 - 405 行

作为 37 行上 WHENEVER 语句的结果,如果在执行 SQL 语句期间发生错误,则
调用 whenexp_chk() 函数。whenexp_chk() 函数检测 SQLSTATE 状态变量来确
定 SQL 语句的结果。由于几个演示程序都以 WHENEVER 语句使用此函数来处理
异常,因此,已将 whenexp_chk() 函数及其支持函数分至单独的 exp_chk.ec
源文件内。
因为该异常处理函数使用 GBase
8s
ESQL/C 语句,
因此,
dyn_sql 程
序必须以 GBase 8s ESQL/Cinclude 伪指令包括此文件。在 异常处理中描述该
exp_chk.ec 源文件。

提示: 在产品环境中,您会将诸如 more_to_do()、getans() 和 whenexp_chk() 这样的
函数放至库中,当您编译 GBase 8s ESQL/C 程序时,在命令行上包括它们。

GBMLLib 是GBase 8a MPP Cluster 的数据挖掘和机器学习扩展库,
以插件的形式添
加到GBase 8a MPP Cluster 中。通过其提供的机器学习算法,GBase 8a MPP Cluster
可以对用户数据进行深层次的分析和挖掘,将用户数据转化为用户价值。
GBMLLib 提供了基于SQL 的机器学习算法,
目前包括的算法有:
回归算法(线性回
归)、分类算法(Logistic 回归、支持向量机)和聚类算法(K-Means)。同时也提供了一
些数组操作和线性代数计算的基本函数。
GBMLLib 具备以下技术特征:

SQL 接口:GBMLLib 提供了SQL 方式的数据挖掘算法,模型的训练、评估和
预测都通过SQL 语句来执行,使得数据分析师非常容易掌握,结合现有技能,
充分发挥其创造力、提高工作效率;

In-database 分析:
不同于其他分析工具需要通过API 或ODBC 把数据从数据库
搬移到分析节点进行处理的方式,GBMLLib 的分析算法以数据库UDF/UDAF
的形式运行在GBase 8a MPP Cluster 的线程内部,通过GBase 8a MPP Cluster
的执行计划进行调度,最大程度的减少数据的搬移、提升运行速度;

方便扩展:
GBMLLib 以插件的形式添加到GBase 8a MPP Cluster 中,
并采用弹
性灵活的软件架构,方便后续添加新的数据挖掘和机器学习算法。

GBase 8a MPP Cluster 产品手册
2 产品概述
文档版本953(2022-04-10)
南大通用数据技术股份有限公司
38