可以使用 GBase 8s ESQL/C 主机变量以两种方式访问不透明数据类型的内部或二进 制格式: 使用 fixed binary 数据类型访问固定长度的不透明数据类型,您可以为其具有表示不 透明数据类型的 C 语言数据结构。 固定长度的不透明数据类型对其数据具有预定义的大小。该大小等于不透明数据类型 的内部数据结构的大小。 使用 var binary 数据类型访问不同长度的不透明数据类型或访问不具有 C 语言的数 据类型的固定长度不透明数据类型。 GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 268 - 不同长度数据类型保存的数据的大小可能因行到行或实例而而异。 fixed binary 和 var binary 数据类型都在它们的声明和不透明数据类型的内部结构 之间具有一对一的映射。 当应用程序传输 fixed binary 或 var binary 主机变量中的数据时, 数据库服务器调用以下不透明类型的支持函数: 接收支持函数描述如何将数据从 fixed binary 或 var binary 主机变量传输到不透明类 型列。 数据库服务器对诸如将不透明类型的内部格式发送到服务器的 INSERT 和 UPDATE 语句的操作调用接收函数。 发送支持函数描述如何将不透明类型列的不透明类型数据传输到 fixed binary 或 var binary 主机变量。 数据库服务器对将不透明类型的内部格式发送到客户端应用程序的 SELECT 和 FETCH 语句调用发送支持函数。 访问固定长度不透明类型 fixed binary 数据类型允许您以它的内部格式访问固定长度的不透明数据类型。 请按照以下步骤,在数据库服务器和 GBase 8s ESQL/C 应用程序之间传输固定长度 不透明类型列的内部格式: 声明 fixed binary 主机变量。 在 SQL 语句中使用 fixed binary 主机变量在固定长度的不透明类型列的外部格式 上执行 select 、insert 、update 或 delete 操作。 声明固定二进制主机变量 使用 fixed binary 数据类型声明访问固定长度不透明数据类型的内部格式的主机变量。 要声明 fixed binary 主机变量,使用以下语法: GBase 8s 扩展fixed binary’opaque type’structure name,variable name; 元素 意义 限制 SQL 语法 opaque type 固定长度不透明数据类 型的名称, 其内部格式存储在 必须已经在数据库中定 GBase 8s SQL 指南: 语法中 GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 269 - 元素 意义 限制 SQL 语法 fixed binary 变量中 义。 的标识符段 structur e name 代表不透明数据类型的 内部格式的 C 数据结构的名 称 必须在源文件包含的头 文件(.h)中定义。还必须符 合数据库服务器用于表示不 透明类型的内部格式的数据 结构。 名称必须符 合特定于变量名 的语言规则。 variable name 声明为 fixed binary 变 量 ESQL/C 变量的名称 名称必须符 合特定于变量名 的语言规则。 重要: fixed binary 主机变量仅对固定长度不透明数据类型的列有效。如果不透明数 据类型是可变长度,请使用 var binary 主机变量。如果不知道固定长度不透明数据类型的 内部格式,仍必须使用 var binary 主机变量访问它。 要使用 fixed binary 主机变量,必须引用映射不透明数据类型的内部数据结构的 C 数据结构。指定此 C 数据结构作为 fixed binary 声明中相同的结构名。 建议您为定义固定长度的不透明数据类型的 C 数据结构创建 C 头文件 (.h 文件) 。 然后在每个 GBase 8s ESQL/C 源文件中包含此头文件, 来使用 fixed binary 主机变量访问 不透明数据类型。 例如,以下代码片段声明 circle 不透明数据类型的名为 my_circle 的 fixed binary 主机变量: #include /* contains definition of circle_t */ EXEC SQL BEGIN DECLARE SECTION; fixed binary 'circle' circle_t my_circle; EXEC SQL END DECLARE SECTION; 在此示例中,circle.h 头文件包含 circle_t 结构(参见图 1)的声明, 它是 circle 不透明数据类型的内部数据结构。my_circle 主机变量的声明指 定不透明数据类型 circle 的名称和 circle_t 内部数据结构的名称。 不透明类型 当声明 fixed binary 主机变量时,必须指定不透明类型为引用字符串。 GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 270 - 重要: 单引号(')和双引号(")都是有效的引号字符。但是,起始引号和结束引号 字符必须相匹配。 不透明类型名称是可选的;它的存在对声明具有以下影响: 当在 fixed binary 声明中省略不透明类型时, 数据库服务器尝试标识合适的支持函数, 以在它将主机变量发送到数据库服务器来存储不透明类型列时使用。 可以使用 fixed binary 主机变量保存多个不同的不透明类型的数据 (只要数据库服务 器能够找到合适的支持函数。) 当在 fixed binary 声明中指定不透明类型时,数据库服务器精确知道使用哪种函数读 取和写入不透明类型列。 使用不透明数据类型可以使数据转换更有效。但是,在这个情况中,fixed binary 主 机变量仅保存特定的不透明数据类型的数据。 可以在单个声明中声明多个 fixed binary 变量。但是,所有的变量必须具有相同的不 透明类型,如下所示: #include ; EXEC SQL BEGIN DECLARE SECTION; fixed binary 'shape' shape_t square1, square2; EXEC SQL END DECLARE SECTION; 固定二进制主机变量 GBase 8s ESQL/C 程序必须处理 fixed binary 主机变量的内部数据结构的所有操作, 它必须显式分配内存和指定字段值。 下图显示了如何使用 fixed binary 主机变量在 circle_tab 表(参见图 4)circle_col 的 列中插入和选择数据。 图 7. 使用固定的二进制主机变量访问 circle 不透明数据类型的内部结构 /* Include declaration for circle_t structure */ GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 271 - #include ; EXEC SQL BEGIN DECLARE SECTION; fixed binary 'circle' circle_t fbin_circle; EXEC SQL END DECLARE SECTION; /* Assign data to members of internal data structure */ fbin_circle.center.x = 1.00; fbin_circle.center.y = 17.00; fbin_circle.radius = 15.25; /* Insert a new circle_tab row with a fixed binary host * variable */ EXEC SQL insert into circle_tab values (:fbin_circle); /* Select a circle_tab row from into a fixed binary * host variable */ EXEC SQL select circle_col into :fbin_circle from circle_tab where radius(circle_col) = 15.25; if ((fbin_circle.center.x == 1.00) && (fbin_circle.center.y == 17.00)) printf("coordinates = (%d, %d)\n", fbin_circle.center.x, fbin_circle.center.y); 从固定二进制主机变量插入 要将 fixed binary 主机变量包含的数据插入到不透明类型列,图 1中的 代码片段执行以下步骤: 包含 circle 不透明数据类型的内部结构的定义。 circle_t 内部数据结构的定义(图 1显示)必须可用于您的 GBase 8s ESQL/C 程序。因此,代码段包含 circle.h 头文件,它包含 circle_t 结构的定义。 将 fixed binary 主机变量中的数据存储到内部数据结构 circle_t。 使用 fbin_circle 主机变量将 fixed binary 主变量的声明使用与 circle_t 内部数据 结构相关联。此代码片段将值分配给 circle_t 数据结构的每个成员。 GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 272 - 将 fbin_circle 主机变量包含的数据插入到 circle_col 不透明类型列中。 当数据库服务器执行此 INSERT 语句时,它调用 circle 数据类型(circle_rcv)接收 支持函数,以便在 GBase 8s ESQL/C 客户端应用程序发送的数据的内部格式(circle_t)和 磁盘上的 circle 数据类型的内部格式。 使用 fixed binary 主机变量将空值插入到不透明类型列,将指示变量设置为 -1。以 下代码使用使用 fbin circle 主机变量将空值插入到 circle_col 列: #include ; EXEC SQL BEGIN DECLARE SECTION; fixed binary 'circle' circle_t fbin_circle; int circle_ind; EXEC SQL END DECLARE SECTION; ⋮ circle_ind = -1; EXEC SQL insert into circle_tab values (:fbin_circle:circle_ind); 将数据选择到固定二进制主机变量 要将不透明类型列包含的数据选择到 fixed binary 主机变量,图 1中的 代码采用以下步骤: 将 circle_col 不透明列包含的数据选择到 fbin_circle 主机变量中。 当数据库服务器执行此 SELECT 语句时,它会调用 circle (circle_snd)发送支持函数,以便来在从磁盘检索到的内部格式与 GBase 8s ESQL/C 应用程序使用的内部格式之间进行必要的翻译。此 SELECT 语句还使用名为 radius(参见图 2)的用户定义函数精确知 道不透明类型列的半径值。 从 fixed binary 主机变量访问 circle 数据。 SELECT 语句执行完成后,fbin_circle 主机变量包含 circle 数据类型内部格式的数 据。此代码段包含来自 circle_t 数据结构成员的 (x,y) 坐标值。 当将不透明类型列中的空值选择到 fixed binary 主机变量时, GBase 8s ESQL/C 将任 何附加指示变量设置为 -1。 GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 273 - 访问不固定长度的不透明类型 var binary 数据类型允许您访问以下之一的透明数据类型的内部格式: 固定长度不透明类型列,不需要访问内部格式的 C 结构 不固定长度不透明类型列 请按照以下步骤,在数据库服务和 GBase 8s ESQL/C 应用程序之间传输这些不透明 类型列的内部格式: 声明 var binary 主机变量 在 SQL 语句中使用 var binary 主机变量对不透明类型列的内部格式执行 select 、 insert 、update 或 delete 操作。 声明 var binary 主机变量 要声明 var binary 主机变量,请使用以下语法。 GBase 8s 扩展var binary’opaque type’structure name,variable name; 元素 意义 限制 SQL 语法 opaqu e type 不透明数据类型的名 称,其内部格式存储在 var binary 变量中 必须已经在数据库中 定义 GBase 8s SQL 指南: 语法中的标识符段 variab le name 声明为 var binary 变量的 ESQL/C 变量名 名称必须符合特定于 变量名的语言规则 下图显示了三个 var binary 变量。图 8. var binary 主机变量示例 #include ; #include ; EXEC SQL BEGIN DECLARE SECTION; var binary polygon1; var binary 'shape' polygon2, a_circle; var binary 'image' an_image; EXEC SQL END DECLARE SECTION; 在 var binary 主机变量的声明中,不透明类型的名称必须是一个引用字符串。 GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 274 - 重要: 单引号(')和双引号(")都是有效的引号字符。但是,起始引号和结束引号 字符必须相匹配。 不透明类型名称是可选的;它的存在对声明具有以下影响: 当在 var binary 声明中省略不透明类型时,当应用程序接收来自不透明列的内部数 据结构时,数据库服务器尝试标识合适的支持函数。 省略不透明类型的优势是您可以使用 var binary 主机变量保存从多个不同不透明类 型选择的数据(只要数据库服务器能找到合适的支持函数) 。 省略不透明类型的劣势是此方法声明的主机变量不能作为用户定义的例程(UDR)的 参数使用。 当在 var binary 声明中指定不透明类型时,数据库服务器将内部数据结构发送到数据 库服务器来存储在不透明类型列中时,它会精确显示要使用的支持函数。 不透明类型名称提供的歧义的丧失可以使数据转换更有效率。 但是, 在此情况中, var binary 主机变量可以保存特定不透明类型数据类型的数据。 可以在单个声明行中声明多个 var binary 变量。但是所有的变量必须具有相同的不透 明类型,如 图 1中所示。 var binary 主机变量 在 GBase 8s ESQL/C 程序中, 可变长度 C 结构 ifx_varlena_t 存储 var binary 主机 变量的二进制值。此数据结构允许您在不指定此不透明数据类型的精确结构时传输二进制 数据。它提供一个数据缓冲区保存与 var binary 主机变量相关联的数据。 重要: ifx_varlena_t 结构对 GBase 8s ESQL/C 程序来说是一个不透明结构。即,您 不能直接访问它的内部结构。ifx_varlena_t 的内部结构可能在之后的版本更改。因此,要 创建便捷的代码,总是对此结构使用 GBase 8s ESQL/C 访问程序函数获取并将值存储在 ifx_varlena_t 结构中。 本节使用可变长度的不透明数据类型 image 演示 GBase 8s ESQL/Cvar binary 主机 变量如何访问不透明数据类型。 此图像数据类型封装了 JPEG 、 GIF 或 PPM 文件等图像。 如果图像小于 2 千字节,则此数据类型的数据结构直接存储此图像。但是,如果图像大于 2 千字节,则数据结构存储包含此图像数据的智能大对象的引用(LO 指针结构)、下图 显示了数据库中 image 数据类型的内部数据结构。 GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 275 - 图 9. 图像不透明数据类型的内部数据结构 typedef struct { int img_len; int img_thresh; int img_flags; union { ifx_lop_t img_lobhandle; char img_data[4]; } } image_t; typedef struct { point_t center; double radius; } circle_t; 下图显示了 CREATE TABLE 语句,它创建了具有 image 类型的列和图像标识符的 表 image_tab 。 图 10. 创建一个图像不透明数据类型的列 CREATE TABLE image_tab ( image_id integer not null primary key), image_col image ); GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 276 - 下图显示了如何使用 var binary 主机变量在 image_tab 表(参见图 2)image_col 列 中进行插入和选择。 图 11. 使用 var binary 主机变量访问图像不透明数据类型的内部格式 #include ; EXEC SQL BEGIN DECLARE SECTION; var binary 'image' vbin_image; EXEC SQL END DECLARE SECTION; struct image_t user_image, *image_ptr; int imgsz; /* Load data into members of internal data structure load_image(&user_image); imgsz = getsize(&user_image); /* Allocate memory for var binary data buffer */ ifx_var_flag(&vbin_image, 0); ifx_var_alloc(&vbin_image, imgsz); /* Assign data to data buffer of var binary host * variable */ ifx_var_setdata(&vbin_image, &user_image, imgsz); /* Insert a new image_tab row with a var binary host * variable */ EXEC SQL insert into image_tab values (1, :vbin_image); /* Deallocate image data buffer */ ifx_var_dealloc(&vbin_image); GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 277 - /* Select an image_tab row from into a var binary * host variable */ ifx_var_flag(&vbin_image, 1); EXEC SQL select image_col into :vbin_image from image_tab where image_id = 1; image_ptr = (image_t *)ifx_var_getdata(&vbin_image); unload_image(&user_image); ifx_var_dealloc(&vbin_image); 从 var binary 主机变量插入 将 var binary 主机变量包含的数据插入到不透明类型列,图 3中的代码 采用以下步骤: 将图像数据从外部 JPEG 、GIF 或 PPM 文件加载到 image_t 内部数据结构中。 load_image() C 例程从外部文件加载 user_image 结构。图 1所示的 image_t 内部结构的定义必须可用于 GBase 8s ESQL/C 程序。因此,代码片段包含定义 image_t 结构的 image.h 头文件。 getsize() C 函数作为 GBase 8s ESQL/C 支持 image 不透明数据类型的一部分模块提 供,它返回 image_t 结构的大小。 为 var binary 主机变量 vbin_image 的数据缓冲区分配内存。 标志值为 0 的 ifx_var_flag() 函数通知 GBase 8s ESQL/C 应用程序将为 vbin_image 主机变量分配内存。ifx_var_alloc() 函数然后为数据缓冲区分配图像数据所需 的字节数(imgsz)。 将 image_t 结构存储在 vbin_image 主机变量的数据缓冲区。 ifx_var_setdata() 函数将 user_image 结构包含的数据保存到 vbin_image 数据缓冲 区。此函数还要求数据缓冲区的大小,getsize() 函数返回。 将 vbin_image 数据缓冲区包含的数据插入到 image_col 不透明类型列。 当数据库服务器执行此 INSERT 语句时,它调用 image 数据类型的接收支持函数, 以便在 GBase 8s ESQL/C 客户端应用程序发送的数据的内部格式(image_t)和内部格式 磁盘上的 image 数据类型。 GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 278 - 释放 vbin_image 主机变量的数据缓冲区。 ifx_var_dealloc() 函数释放 vbin_image 数据缓冲区。 要使用 var binary 主机变量将空值插入到不透明类型列中,可以使用以下两种方法: 将与 var binary 主机变量相关联的指示变量设置为 -1。 以下代码使用 image_ind 指示变量和 vbin_image 主机变量将空值插入到 circle_col 列: #include ; EXEC SQL BEGIN DECLARE SECTION; var binary 'image' vbin_image; int image_ind; EXEC SQL END DECLARE SECTION; image_ind = -1; EXEC SQL insert into image_tab values (:vbin_image:image_ind); 使用 ifx_var_setnull() 函数将 var binary 主机变量的数据缓冲区设置为空值。 对于相同的 vbin_image 主机变量,下行使用 ifx_var_setnull() 函数将空值插入到 circle_col 列中: ifx_var_setnull(&vbin_image, 1); EXEC SQL insert into image_tab values (:vbin_image); 选择到 var binary 主机变量 将不透明类型列包含的数据选择到 var binary 主机变量中,图 3中的代 码采取以下步骤: 给 var binary 主机变量 vbin_image 的数据缓冲区分配内存。 具有标志值 1 的 ifx_var_flag() 函数通知 GBase 8s ESQL/C 它给 vbin_image 主机 变量分配新的数据缓冲区。 (此数据缓冲区在 INSERT 语句完成后被释放。)当 GBase 8s ESQL/C 接收到 SELECT 语句的数据时,执行此分配。 GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 279 - 将 image_col 不透明类型列包含的数据选择到 vbin_image 数据缓冲区。 当数据库服务器执行此 SELECT 语句时, 它调用 image 的发送支持函数执行在磁盘 上的 image 数据类型的内部格式和已发送(image_t)的 GBase 8s ESQL/C 客户端应用程 序的内部格式之间的必须翻译。 将 vbin_image 主机变量包含的数据缓冲区中的数据存储到 image_t 结构中。 此 SELECT 语句之后,vbin_image 主机变量的数据缓冲区包含 image 数据类型内 部格式的数据。ifx_var_getdata() 函数将此数据缓冲区的内容返回到 image_t 数据结构中。 因为 ifx_var_getdata() 函数将数据缓冲区作为一个 “void *” 值返回,所以这个对 ifx_var_getdata() 的调用在将它分配给 image_ptr 变量之前,将此返回值作为一个指向 image_t 结构的指针。 将 image_t 内部数据结构的图像数据卸载为一个外部 JPEG 、GIF 或 PPM 文件。 unload_image() 例程将 user_image 结构卸载为一个外部文件。 释放 vbin_image 主机变量的数据缓冲区。 ifx_var_dealloc() 函数释放 vbin_image 数据缓冲区。 必须显式释放此数据缓冲区即使 是 GBase 8s ESQL/C 分配的。 要检查具有 var binary 主机变量的不透明类型列是否包含空值,可以使用以下两种 方法: 检查与 var binary 主机变量的相关联的指示变量的值是否为 -1。 以下代码使用 image_ind 指示变量和 vbin_image 主机变量检查 circle_col 列的空值: #include ; EXEC SQL BEGIN DECLARE SECTION; var binary 'image' vbin_image; int image_ind; EXEC SQL END DECLARE SECTION; EXEC SQL select image_col into :vbin_image:image_ind from image_tab where image_id = 1; GBase 8s ESQL/C 编程指南 南大通用数据技术股份有限公司 - 280 - if (image_ind == -1) ? 使用 ifx_var_isnull() 函数检查 var binary 主机变量的数据缓冲区是否为空值。 对于相同的 vbin_image 主机变量,以下行使用 ifx_var_isnull() 函数检查 image_col 列中的空值: EXEC SQL select image_col into :vbin_image from image_tab where image_id = 1; if (ifx_var_isnull(&vbin_image) == 1) ?