返回首页

gbase数据、南大通用产品文档:GBase8sonstat i 命令: 开始® 交互方式

更新日期:2024年09月11日

可以使用 onstat -i 命令将 onstat 实用程序置于交互方式。
语法:

在交互方式中,可以为每个会话输入多个 onstat 选项,但一次只能输入一个。onstat 提示
显示并允许您输出选项。
重要: 在交互方式中,不要在该选项前加连字符。
其他选项
两个其他选项 onstat r seconds 和 onstat rz seconds 可用于交互方式。onstat r seconds 选项
类似于当前的 onstat -r seconds 选项,
它重复生成显示。
如果管理员在交互方式提示处执行
onstat r seconds ,那么提示更改以反映指定的时间间隔(秒)并重新出现,等待下一命令。
在以下示例中,由下一条命令生成的显示每 3 秒重复一次:
onstat> r 3
onstat[3]>
onstat rz seconds 选项使您可以如指定的那样重复下一条命令并在每个执行之间将所有概
要文件计数器设置为 0 。
终止交互方式或重复顺序
要终止交互方式,请按 CTRL-d。
要终止重复顺序,请按 CTRL-c。

本部分包含要准备系统来使用 JDBC 驱动程序 XML 方法所需要了解的信息。
设置 CLASSPATH
要使用 XML 方法,请将下列文件的路径名称添加至 CLASSPATH 设置:

ifxtools.jar

xerces.jar
所有这些文件都位于安装驱动程序处的 lib 目录中。
已将 Xerces XML 库 xerces.jar 从 GBase 8s JDBC Driver Version 3.00 移除。
XML 方法不是 ifxjdbc.jar 文件的一部分。反而,将它们发布在单独的名
为 ifxtools.jar 的 .jar 文件中。要使用这些方法,必须将此文件与ifxjdbc.jar 一起添加至
CLASSPATH 设置。
此外,构建 ifxtools.jar 需要使用来自支持 SAX、DOM 和 JAXP 方法的 .jar 文件的代码。
要使用 ifxtools.jar,必须将这些 .jar 文件添加至 CLASSPATH 设置。
JDK version 1.4 或更新的版本使用缺省的 XML 解析器,即使 xml4j 解析器在
CLASSPATH 中。要使用 SAX 解析器的 xml4j 实现,请在应用程序代码中设置下列系统
属性,或使用 -D 命令行选项:

必须将属性 javax.xml.parsers.SAXParserFactory 设置
为 org.apache.xerces.jaxp.SAXParserFactoryImpl。

对于“文档对象模型”,必须将属性 javax.xml.parsers.DocumentBuilderFactory 设置
为org.apache.xerces.jaxp.DocumentBuilderFactoryImpl。
要获取关于如何设置这些属性的更多信息,请参阅 指定解析器 factory。
指定解析器 factory

GBase 8s JDBC Driver 程序员指南
南大通用数据技术股份有限公司
- 95 -
在缺省情况下,
xml4j xerces 解析器
(以及作为结果,
ifxtools.jar)
使用未经验证的 XML 解
析器。要使用替代的 SAX 解析器 factory,请从命令行运行应用程序,如下:
% java -Djavax.xml.parsers.SAXParserFactory=new-factory
如果未从命令行运行,则必须将 factory 名称括在双引号中:
% java -Djavax.xml.parsers.SAXParserFactory="new-factory"
还可在代码中设置系统属性:
System.setProperty("javax.xml.parsers.SAXParserFactory",
"new-factory")
在此代码中,
new-factory 是替代的解析器 factory。
例如,
如果您正在使用 xerces 解析器,
则以org.apache.xerces.jaxp.SAXParserFactoryImpl 来替代 new-factory。
还可能为 DOM 方法使用替代的文档 factory for DOM。请从命令行运行应用程序,如下:

% java -Djavax.xml.parsers.DocumentBuilderFactory=new-factory
如果未从命令行运行,则 factory 名称必须括在双引号中:
% java -Djavax.xml.parsers.DocumentBuilderFactory="new-factory"
还可在代码中设置系统属性:
System.setProperty("javax.xml.parsers.DocumentBuilderFactory",
"new-factory")
例如,如果正在使用 xerces 解析器,则
以 jorg.apache.xerces.jaxp.DocumentBuilderFactoryImpl 来替代 new-factory。

访存数组使得您能够在您的程序中增加单个 FETCH 语句从访存缓冲区返回至 sqlda
结构的行数。当您访存简单大对象(TEXT 或 BYTE)数据时,访存数组特别有用。

对不带有访存数组的简单大对象的访存,需要与数据库服务器进行下列两项交换:
当 GBase 8s ESQL/C 访存 TEXT 或 BYTE 列时,
数据库服务器为该列返回描述符。

然后,GBase 8s ESQL/C 请求数据库服务器获取该列数据。

当您使用访存数组时,GBase 8s ESQL/C 将一些列简单大对象描述符发送至数据库服
务器,且数据库服务器一次返回所有对应的列数据。
使用访存数组
要使用访存数组:

声明 sqlda 结构来保存您想要访存的列。
您不可在 FETCH 语句中使用主变量或系统描述符区域来为列保存访
存数组。您必须使用 sqlda 结构和 FETCH...USING DESCRIPTOR 语
句。

使用 DESCRIBE...INTO 语句来初始化 sqlda 结构,并获得关于准备好的查询的信息。

DESCRIBE...INTO statement 语句为 sqlda 结构和 sqlvar_struct 结构分配内存。

对于 sqldata 字段,为每一列分配大到足以保存访存数组的缓冲区。
要为 sqldata 字段分配内存,您必须为相关的列将 FetArrSize 全
局变量设置为访存设置的大小。

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


发出 FETCH...USING DESCRIPTOR 语句来将该列值检索至访存设置内。
FETCH 语句将检索到的行放置至 sqlda 中的 sqlvar_struct 结构的 sqldata 字段内。
每一 FETCH 语句将由 FetArrSize 指定的值的数目返回至 sqldata 字段内。

从每一 sqlvar_struct 结构的访存数组获得列值。
在您执行下一 FETCH 语句之前,
您必须从访存数组获得这些值。
您可
检查 sqlca.sqlerrd[2] 字段来确定 FETCH 已返回的有效行的数目。
sqlerrd[2] 中的值等于或小于您在 FetArrSize 中设置的值。

重复步骤 4和 5,直到访存所有行为止。
释放 sqlda 结构使用的内存。
正如 sqlda 结构的其他使用一样,GBase 8s ESQL/C 不为此结构释放资源。当您的应
用程序不再需要分配给 sqlda 结构的内存时,它必须释放它。

重要:
当启用“延迟的 PREPARE” 和 OPTOFC 特性时,
FetArrSize 特性不起作用。
当启用这两个特性时,GBase 8s ESQL/C 不知道行的大小,直到 FETCH 语句完成之后为
止。到此时,对于要以 FetArrSize 值来调整访存缓冲区而言,为时已晚。
样例访存数组程序
下列样例程序展示如何执行 使用访存数组中的步骤。它使用分开的函数来
初始化、打印和释放 sqlda 结构。在下面的部分中描述这些函数。

#include
#include
#include

EXEC SQL include sqlda.h;
EXEC SQL include locator.h;
EXEC SQL include sqltypes.h;


#define BLOBSIZE 32275 /* using a predetermined length for blob */

EXEC SQL begin declare section;
long blobsize; /* finding the maximum blob size at runtime */
EXEC SQL end declare section;


/*******************************************************************

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

**
* Function: init_sqlda()
* Purpose: With the sqlda pointer that was returned from the DESCRIBE
* statement, function allocates memory for the fetch arrays
* in the sqldata fields of each column. The function uses
* FetArrSize to determine the size to allocate.
* Returns: < 0 for error
* > 0 error with messagesize
********************************************************************
*/
int init_sqlda(struct sqlda *in_da, int print)
{
int i, j,
row_size=0,
msglen=0,
num_to_alloc;
struct sqlvar_struct *col_ptr;
ifx_loc_t *temp_loc;
char *type;


if (print)
printf("columns: %d. \n", in_da->sqld);

/* Step 1: determine row size */
for
(i
=
0,
col_ptr
=
in_da->sqlvar;
i
<
in_da->sqld;
i++,
col_ptr++)
{
/* The msglen variable holds the sum of the column sizes in the
* database; these are the sizes that DESCRIBE returns. This
* sum is the amount of memory that ESQL/C needs to store
* one row from the database. This value is <= row_size. */
msglen += col_ptr->sqllen; /* get database sizes */


/* calculate size for C data: string columns get extra byte added
* to hold null terminator */
col_ptr->sqllen = rtypmsize(col_ptr->sqltype, col_ptr->sqllen);

/* The row_size variable holds the sum of the column sizes in
* the client application; these are the sizes that rtypmsize()
* returns. This sum is amount of memory that the client
* application needs to store one row. */
row_size += col_ptr->sqllen;
if(print)

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

printf("Column %d size: %d\n", i+1, col_ptr->sqllen);
}

if (print)
{
printf("Total message size = %d\n", msglen);
printf("Total row size = %d\n", row_size);
}

EXEC
SQL
select
max(length(cat_descr))
into
:blobsize
from
catalog;

/* Step 2: set FetArrSize global variable to number of elements
* in fetch array; this function calculates the FetArrSize
* value that can fit into the existing fetch buffer.
* If FetBufSize is not set (equals zero), the code assigns a
* default size of 4096 bytes (4 kilobytes). Alternatively, you
* could set FetArrSize to the number elements you wanted to
* have and let ESQL/C size the fetch buffer. See the text in
* "Allocating Memory for the Fetch Arrays" for more information.*/
if (FetArrSize <= 0) /* if FetArrSize not yet initialized */
{
if (FetBufSize == 0) /* if FetBufSize not set */
FetBufSize = 4096; /* default FetBufSize */
FetArrSize = FetBufSize/msglen;
}
num_to_alloc = (FetArrSize == 0)? 1: FetArrSize;
if (print)
{
printf("Fetch Buffer Size %d\n", FetBufSize);
printf("Fetch Array Size: %d\n", FetArrSize);
}

/* set type in sqlvar_struct structure to corresponding C type */
for (i = 0, col_ptr = in_da->sqlvar; i < in_da->sqld; i++,
col_ptr++)
{
switch(col_ptr->sqltype)
{
case SQLCHAR:
type = "char ";
col_ptr->sqltype = CCHARTYPE;
break;
case SQLINT:
case SQLSERIAL:

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

type = "int ";
col_ptr->sqltype = CINTTYPE;
break;
case SQLBYTES:
case SQLTEXT:
if (col_ptr->sqltype == SQLBYTES)
type = "blob ";
else
type = "text ";
col_ptr->sqltype = CLOCATORTYPE;

/* Step 3 (TEXT & BLOB only): allocate memory for sqldata
* that contains ifx_loc_t structures for TEXT or BYTE column
*/
temp_loc = (ifx_loc_t *)malloc(col_ptr->sqllen *
num_to_alloc);
if (!temp_loc)
{
fprintf(stderr, "blob sqldata malloc failed\n");
return(-1);
}
col_ptr->sqldata = (char *)temp_loc;

/* Step 4 (TEXT & BLOB only): initialize ifx_loc_t structures
to
hold blob values in a user-defined buffer in memory */
byfill( (char *)temp_loc, col_ptr->sqllen*num_to_alloc ,0);
for (j = 0; j< num_to_alloc; j++, temp_loc++)
{
/* blob data to go in memory */
temp_loc->loc_loctype = LOCMEMORY;

/* assume none of the blobs are larger than BLOBSIZE */
temp_loc->loc_bufsize = blobsize;
temp_loc->loc_buffer = (char *)malloc(blobsize+1);
if (!temp_loc->loc_buffer)
{
fprintf(stderr, "loc_buffer malloc failed\n");
return(-1);
}
temp_loc->loc_oflags = 0; /* clear flag */
} /* end for */
break;
default: /* all other data types */

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

fprintf(stderr,
"not
yet
handled(%d)!\n",
col_ptr->sqltype);
return(-1);
} /* switch */

/* Step 5: allocate memory for the indicator variable */
col_ptr->sqlind = (short *)malloc(sizeof(short) * num_to_alloc);
if (!col_ptr->sqlind)
{
printf("indicator malloc failed\n");
return -1;
}

/* Step 6 (other data types): allocate memory for sqldata. This
* function
* casts the pointer to this memory as a (char *). Subsequent
* accesses to the data would need to cast it back to the data
* type that corresponds to the column type. See the print_sqlda()
* function for an example of this casting. */
if (col_ptr->sqltype != CLOCATORTYPE)
{
col_ptr->sqldata = (char *) malloc(col_ptr->sqllen *
num_to_alloc);
if (!col_ptr->sqldata)
{
printf("sqldata malloc failed\n");
return -1;
}
if (print)
printf("column %3d, type = %s(%3d), len=%d\n", i+1, type,
col_ptr->sqltype, col_ptr->sqllen);
}
} /* end for */
return msglen;
}

/*******************************************************************
***
* Function: print_sqlda
* Purpose: Prints contents of fetch arrays for each column that the
* sqlda structure contains. Current version only implements
* data types found in the blobtab table. Other data types
* would need to me implemented to make this function complete.
********************************************************************
**/

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

void print_sqlda(struct sqlda *sqlda, int count)
{
void *data;
int i, j;
ifx_loc_t *temp_loc;
struct sqlvar_struct *col_ptr;
char *type;
char buffer[512];
int ind;
char i1, i2;

/*
print
number
of
columns
(sqld)
and
number
of
fetch-array
elements
*/
printf("\nsqld: %d, fetch-array elements: %d.\n", sqlda->sqld,
count);

/* Outer loop: loop through each element of a fetch array */
for (j = 0; j < count; j ++)
{
if (count > 1)
{
printf("record[%4d]:\n", j);
printf("col | type | id | len | ind | rin | data ");
printf("| value\n");
printf("--------------------------------------------");
printf("------------------\n");
}

/* Inner loop: loop through each of the sqlvar_struct structures */
for (i = 0, col_ptr = sqlda->sqlvar; i < sqlda->sqld; i++, col_ptr++)
{
data = col_ptr->sqldata + (j*col_ptr->sqllen);
switch (col_ptr->sqltype)
{
case CFIXCHARTYPE:
case CCHARTYPE:
type = "char";
if (col_ptr->sqllen > 40)
sprintf(buffer, " %39.39s<..", data);
else
sprintf(buffer, "%*.*s", col_ptr->sqllen,
col_ptr->sqllen, data);
break;
case CINTTYPE:

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

type = "int";
sprintf(buffer, " %d", *(int *) data);
break;
case CLOCATORTYPE:
type = "byte";
temp_loc = (ifx_loc_t *)(col_ptr->sqldata +
(j * sizeof(ifx_loc_t)));
sprintf(buffer, " buf ptr: %p, buf sz: %d, blob sz: %d",
temp_loc->loc_buffer,
temp_loc->loc_bufsize, temp_loc->loc_size);
break;
default:
type = "??????";
sprintf(buffer, " type not implemented: ",
"can't print %d", col_ptr->sqltype);
break;
} /* end switch */

i1 = (col_ptr->sqlind==NULL) ? 'X' :
(((col_ptr->sqlind)[j] != 0) ? 'T' : 'F');
i2 = (risnull(col_ptr->sqltype, data)) ? 'T' : 'F';

printf("%3d | %-6.6s | %3d | %3d | %c | %c | ",
i, type, col_ptr->sqltype, col_ptr->sqllen, i1, i2);
printf("%8p |%s\n", data, buffer);
} /* end for (i=0...) */
} /* end for (j=0...) */
}

/*******************************************************************
***
* Function: free_sqlda
* Purpose: Frees memory used by sqlda. This memory includes:
* o loc_buffer memory (used by TEXT & BYTE)
* o sqldata memory
* o sqlda structure
********************************************************************
**/
void free_sqlda(struct sqlda *sqlda)
{
int i,j, num_to_dealloc;
struct sqlvar_struct *col_ptr;
ifx_loc_t *temp_loc;


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

for (i = 0, col_ptr = sqlda->sqlvar; i < sqlda->sqld; i++,
col_ptr++)
{
if ( col_ptr->sqltype == CLOCATORTYPE )
{
/* Free memory for blob buffer of each element in fetch array */
num_to_dealloc = (FetArrSize == 0)? 1: FetArrSize;
temp_loc = (ifx_loc_t *) col_ptr->sqldata;
for (j = 0; j< num_to_dealloc; j++, temp_loc++)
{
free(temp_loc->loc_buffer);
}
}
/* Free memory for sqldata (contains fetch array) */
free(col_ptr->sqldata);
}

/* Free memory for sqlda structure */
free(sqlda);
}

void main()
{
int i = 0;
int row_count, row_size;


EXEC SQL begin declare section;
char *db = "stores7";
char *uid = "odbc";
char *pwd = "odbc";
EXEC SQL end declare section;


/*******************************************************************
*
* Step 1: declare an sqlda structure to hold the retrieved column
* values

********************************************************************
/
struct sqlda *da_ptr;

EXEC SQL connect to :db user :uid using :pwd;

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

if ( SQLCODE < 0 )
{
printf("CONNECT failed: %d\n", SQLCODE);
exit(0);
}

/* Prepare the SELECT */
EXEC SQL prepare selct_id from 'select catalog_num, cat_descr from
catalog';
if ( SQLCODE < 0 )
{
printf("prepare failed: %d\n", SQLCODE);
exit(0);
}


/*******************************************************************
*
*
Step
2:
describe
the
prepared
SELECT
statement
to
allocate
memory
* for the sqlda structure and the sqlda.sqlvar structures
* (DESCRIBE can allocate sqlda.sqlvar structures because
* prepared statement is a SELECT)

********************************************************************
/
EXEC SQL describe selct_id into da_ptr;
if ( SQLCODE < 0 )
{
printf("describe failed: %d\n", SQLCODE);
exit(0);
}


/*******************************************************************
*
* Step 3: initialize the sqlda structure to hold fetch arrays for
* columns

********************************************************************
/
row_size = init_sqlda(da_ptr, 1);

/* declare and open a cursor for the prepared SELECT */
EXEC SQL declare curs cursor for selct_id;

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

if ( SQLCODE < 0 )
{
printf("declare failed: %d\n", SQLCODE);
exit(0);
}
EXEC SQL open curs;
if ( SQLCODE < 0 )
{
printf("open failed: %d\n", SQLCODE);
exit(0);
}
while (1)
{

/*******************************************************************
*
* Step 4: perform fetch to get "FetArrSize" array of rows from
* the database server into the sqlda structure

********************************************************************
/
EXEC SQL fetch curs using descriptor da_ptr;

/* Reached last set of matching rows? */
if ( SQLCODE == SQLNOTFOUND )
break;


/*******************************************************************
*
* Step 5: obtain the values from the fetch arrays of the sqlda
* structure; use sqlca.sqlerrd[2] to determine number
* of array elements actually retrieved.

********************************************************************
/
printf("\n===============\n");
printf("FETCH %d\n", i++);
printf("===============");
print_sqlda(da_ptr, ((FetArrSize == 0) ? 1 : sqlca.sqlerrd[2]));


/*******************************************************************
*

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

* Step 6: repeat the FETCH until all rows have been fetched (SQLCODE
* is SQLNOTFOUND

********************************************************************
/
}


/*******************************************************************
*
* Step 7: Free resources:
* o statement id, selct_id
* o select cursor, curs
* o sqlda structure (with free_sqlda() function)
* o delete sample table and its rows from database

********************************************************************
/

EXEC SQL free selct_id;
EXEC SQL close curs;
EXEC SQL free curs;
free_sqlda(da_ptr);
}
为访存数组分配内存
DESCRIBE...INTO 语句为 sqlda 结构及其 sqlvar_struct 结构分配内存。
然而,
它不
为 sqlvar_struct 结构的 sqldata 字段分配内存。sqldata 字段为检索了的列保存访存数组。
因此,您必须将足够的内存分配给每一 sqldata 字段来保存该访存数组的元素。

新的全局变量 FetArrSize 指示由 FETCH 语句返回的行数。定义此变量为 C 语言
short integer 数据类型。它的缺省值为零,其禁用访存数组特性。您可将 FetArrSize 设置
为在下列范围内的任何整数值:
0 <= FetArrSize <= MAXSMINT

MAXSMINT 值是 GBase 8s ESQL/C 可检索的数据类型的最大数量。
它的值为 32767
字节(32 KB)。如果该访存数组的大小大于 MAXSMINT,则 GBase 8s ESQL/C 自动地
将它的大小减为 32 KB。

您可使用下列计算来确定该访存数组的适当的大小:
(fetch-array size) = (fetch-buffer size) / (row size)

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


前面的等式使用下列信息:
fetch-array size
访存数组的大小,由 FetArrSize 全局变量来指示
fetch-buffer size
访存缓冲区的大小,
由 FetBufSize 和 BigFetBufSize 全局变量来指
示。
row size
要访存的行的大小。要确定要访存的行的大小,对于该行的每一列,
请调用 rtypmsize() 函数。此函数返回需要存储该数据类型的字节数。

然而,如果您设置 FetArrSize 以便于下列关系为真,
(FetArrSize * row size) > FetBufSize

则 GBase 8s ESQL/C 自动地调整该访存缓冲区的大小(FetBufSize)如下,来保存该
访存数组的大小:
FetBufSize = FetArrSize * row size

如果该值大于 32 KB
(MAXSMINT)

则 GBase 8s ESQL/C 将 FetBufSize 设置为 32
KB 和 FetArrSize 如下:
FetArrSize = MAXSMINT / (row size)

重要: FetArrSize 全局变量可用在线程安全 GBase 8s ESQL/C 应用程序中。
为访存数组分配内存
要为访存数组分配内存:

确定您正从数据库检索的行的大小。
确定该访存数组的大小,并将 FetArrSize 全局变量设置为此值。
对于每一简单大对象列(TEXT 或 BYTE),分配一个 ifx_loc_t 结构的访存数组。
对于每一简单大对象列(TEXT 或 BYTE),初始化 ifx_loc_t 数据结构如下。
将 loc_loctype 字段设置为 LOCMEMORY。
a) 将 loc_buffer 字段设置为您在步骤 3中分配的缓冲区的
地址。
将 loc_bufsize 字段设置为您分配了的缓冲区的大小。

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

或者,您可将 loc_bufsize 设置为 -1,来让 GBase 8s ESQL/C 自动地为简单
大对象列分配内存。

为指示符变量分配内存。
对于所有其他列,分配保存那列的数据类型的访存数组。

对于下列准备好的查询,下列示例代码说明您会如何为访存数组分配内存:
SELECT * from blobtab;

该函数称为 init_sqlda():
/**********************************************************************
* Function: init_sqlda()
* Purpose: With the sqlda pointer that was returned from the DESCRIBE
* statement, function allocates memory for the fetch arrays
* in the sqldata fields of each column. The function uses
* FetArrSize to determine the size to allocate.
* Returns: < 0 for error
* > 0 error with messagesize

**********************************************************************/
int init_sqlda(struct sqlda *in_da, int print)
{
int i, j,
row_size=0,
msglen=0,
num_to_alloc;
struct sqlvar_struct *col_ptr;
ifx_loc_t *temp_loc;
char *type;


if (print)
printf("columns: %d. \n", in_da->sqld);


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

/* Step 1: determine row size */
for (i = 0, col_ptr = in_da->sqlvar; i < in_da->sqld; i++,
col_ptr++)
{
/* The msglen variable holds the sum of the column sizes in the
* database; these are the sizes that DESCRIBE returns. This
* sum is the amount of memory that ESQL/C needs to store
* one row from the database. This value is <= row_size. */
msglen += col_ptr->sqllen; /* get database sizes */


/* calculate size for C data: string columns get extra byte added
* to hold null terminator */
col_ptr->sqllen = rtypmsize(col_ptr->sqltype, col_ptr->sqllen);

/* The row_size variable holds the sum of the column sizes in
* the client application; these are the sizes that rtypmsize()
* returns. This sum is amount of memory that the client
* application needs to store one row. */
row_size += col_ptr->sqllen;
if(print)
printf("Column %d size: %d\n", i+1, col_ptr->sqllen);
}

if (print)
{
printf("Total message size = %d\n", msglen);
printf("Total row size = %d\n", row_size);
}

EXEC SQL select max(length(cat_descr)) into :blobsize from catalog;

/* Step 2: set FetArrSize global variable to number of elements

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

* in fetch array; this function calculates the FetArrSize
* value that can fit into the existing fetch buffer.
* If FetBufSize is not set (equals zero), the code assigns a
* default size of 4096 bytes (4 kilobytes). Alternatively, you
* could set FetArrSize to the number elements you wanted to
* have and let ESQL/C size the fetch buffer. See the text in
* "Allocating Memory for the Fetch Arrays" for more information.*/
if (FetArrSize <= 0) /* if FetArrSize not yet initialized */
{
if (FetBufSize == 0) /* if FetBufSize not set */
FetBufSize = 4096; /* default FetBufSize */
FetArrSize = FetBufSize/msglen;
}
num_to_alloc = (FetArrSize == 0)? 1: FetArrSize;
if (print)
{
printf("Fetch Buffer Size %d\n", FetBufSize);
printf("Fetch Array Size: %d\n", FetArrSize);
}

/* set type in sqlvar_struct structure to corresponding C type */
for (i = 0, col_ptr = in_da->sqlvar; i < in_da->sqld; i++,
col_ptr++)
{
switch(col_ptr->sqltype)
{
case SQLCHAR:
type = "char ";
col_ptr->sqltype = CCHARTYPE;
break;
case SQLINT:
case SQLSERIAL:
type = "int ";

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

col_ptr->sqltype = CINTTYPE;
break;
case SQLBYTES:
case SQLTEXT:
if (col_ptr->sqltype == SQLBYTES)
type = "blob ";
else
type = "text ";
col_ptr->sqltype = CLOCATORTYPE;

/* Step 3 (TEXT & BLOB only): allocate memory for sqldata
* that contains ifx_loc_t structures for TEXT or BYTE column */
temp_loc = (ifx_loc_t *)malloc(col_ptr->sqllen * num_to_alloc);
if (!temp_loc)
{
fprintf(stderr, "blob sqldata malloc failed\n");
return(-1);
}
col_ptr->sqldata = (char *)temp_loc;

/* Step 4 (TEXT & BLOB only): initialize ifx_loc_t structures to
hold blob values in a user-defined buffer in memory */
byfill( (char *)temp_loc, col_ptr->sqllen*num_to_alloc ,0);
for (j = 0; j< num_to_alloc; j++, temp_loc++)
{
/* blob data to go in memory */
temp_loc->loc_loctype = LOCMEMORY;

/* assume none of the blobs are larger than BLOBSIZE */
temp_loc->loc_bufsize = blobsize;
temp_loc->loc_buffer = (char *)malloc(blobsize+1);
if (!temp_loc->loc_buffer)
{

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

fprintf(stderr, "loc_buffer malloc failed\n");
return(-1);
}
temp_loc->loc_oflags = 0; /* clear flag */
} /* end for */
break;
default: /* all other data types */
fprintf(stderr, "not yet handled(%d)!\n", col_ptr->sqltype);
return(-1);
} /* switch */

/* Step 5: allocate memory for the indicator variable */
col_ptr->sqlind = (short *)malloc(sizeof(short) * num_to_alloc);
if (!col_ptr->sqlind)
{
printf("indicator malloc failed\n");
return -1;
}

/* Step 6 (other data types): allocate memory for sqldata. This function
* casts the pointer to this memory as a (char *). Subsequent
* accesses to the data would need to cast it back to the data
* type that corresponds to the column type. See the print_sqlda()
* function for an example of this casting. */
if (col_ptr->sqltype != CLOCATORTYPE)
{
col_ptr->sqldata = (char *) malloc(col_ptr->sqllen *
num_to_alloc);
if (!col_ptr->sqldata)
{
printf("sqldata malloc failed\n");
return -1;
}

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

if (print)
printf("column %3d, type = %s(%3d), len=%d\n", i+1, type,
col_ptr->sqltype, col_ptr->sqllen);
}
} /* end for */
return msglen;
}
从访存数组获得值
每一 FETCH 尝试将值的 FetArrSize 数目返回至 sqlda 结构的 sqlvar_struct 结构
的 sqldata 字段内。
您可检查 sqlca.sqlerrd[2] 值来确定 FETCH 确实返回了的实际行数。


对于该查询的一列,每一访存数组保存该值。要获得值的行,您必须访问每一访存数
组的同一索引处的元素。例如,要获得值的第一行,请访问每一访存数组的第一个元素。

样例程序调用 print_sqlda() 函数来为下列准备好的查询从访存数组获得值:
SELECT * from blobtab


/**********************************************************************
* Function: print_sqlda
* Purpose: Prints contents of fetch arrays for each column that the
* sqlda structure contains. Current version only implements
* data types found in the blobtab table. Other data types
* would need to me implemented to make this function complete.

**********************************************************************/
void print_sqlda(struct sqlda *sqlda, int count)
{
void *data;
int i, j;
ifx_loc_t *temp_loc;
struct sqlvar_struct *col_ptr;
char *type;

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

char buffer[512];
int ind;
char i1, i2;

/* print number of columns (sqld) and number of fetch-array elements
*/
printf("\nsqld: %d, fetch-array elements: %d.\n", sqlda->sqld,
count);

/* Outer loop: loop through each element of a fetch array */
for (j = 0; j < count; j ++)
{
if (count > 1)
{
printf("record[%4d]:\n", j);
printf("col | type | id | len | ind | rin | data ");
printf("| value\n");
printf("--------------------------------------------");
printf("------------------\n");
}

/* Inner loop: loop through each of the sqlvar_struct structures */
for (i = 0, col_ptr = sqlda->sqlvar; i < sqlda->sqld; i++, col_ptr++)
{
data = col_ptr->sqldata + (j*col_ptr->sqllen);
switch (col_ptr->sqltype)
{
case CFIXCHARTYPE:
case CCHARTYPE:
type = "char";
if (col_ptr->sqllen > 40)
sprintf(buffer, " %39.39s<..", data);
else

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

sprintf(buffer, "%*.*s", col_ptr->sqllen,
col_ptr->sqllen, data);
break;
case CINTTYPE:
type = "int";
sprintf(buffer, " %d", *(int *) data);
break;
case CLOCATORTYPE:
type = "byte";
temp_loc = (ifx_loc_t *)(col_ptr->sqldata +
(j * sizeof(ifx_loc_t)));
sprintf(buffer, " buf ptr: %p, buf sz: %d, blob sz: %d",
temp_loc->loc_buffer,
temp_loc->loc_bufsize, temp_loc->loc_size);
break;
default:
type = "??????";
sprintf(buffer, " type not implemented: ",
"can't print %d", col_ptr->sqltype);
break;
} /* end switch */

i1 = (col_ptr->sqlind==NULL) ? 'X' :
(((col_ptr->sqlind)[j] != 0) ? 'T' : 'F');
i2 = (risnull(col_ptr->sqltype, data)) ? 'T' : 'F';

printf("%3d | %-6.6s | %3d | %3d | %c | %c | ",
i, type, col_ptr->sqltype, col_ptr->sqllen, i1, i2);
printf("%8p |%s\n", data, buffer);
} /* end for (i=0...) */
} /* end for (j=0...) */
}
为访存数组释放内存

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

GBase 8s ESQL/C 不为 sqlda 结构释放资源。当您的应用程序不再需要 sqlda 结构
时,它必须释放它使用的所有内存。

该样例程序调用 free_sqlda() 函数来释放 sqlda 结构使用的内存。
/**********************************************************************
* Function: free_sqlda
* Purpose: Frees memory used by sqlda. This memory includes:
* o loc_buffer memory (used by TEXT & BYTE)
* o sqldata memory
* o sqlda structure

**********************************************************************/
void free_sqlda(struct sqlda *sqlda)
{
int i,j, num_to_dealloc;
struct sqlvar_struct *col_ptr;
ifx_loc_t *temp_loc;

for (i = 0, col_ptr = sqlda->sqlvar; i < sqlda->sqld; i++,
col_ptr++)
{
if ( col_ptr->sqltype == CLOCATORTYPE )
{
/* Free memory for blob buffer of each element in fetch array */
num_to_dealloc = (FetArrSize == 0)? 1: FetArrSize;
temp_loc = (ifx_loc_t *) col_ptr->sqldata;
for (j = 0; j< num_to_dealloc; j++, temp_loc++)
{
free(temp_loc->loc_buffer);
}
}
/* Free memory for sqldata (contains fetch array) */
free(col_ptr->sqldata);

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

}

/* Free memory for sqlda structure */
free(sqlda);
}